Skip to content

fix: address the review of API targets and the Python client target - #100

Closed
moetemp wants to merge 26 commits into
tconley/api-generation-targetsfrom
moe/fix/api-generation-targets-review
Closed

moetemp wants to merge 26 commits into
tconley/api-generation-targetsfrom
moe/fix/api-generation-targets-review

Conversation

@moetemp

@moetemp moetemp commented Oct 30, 2026

Copy link
Copy Markdown
Owner

What changed?

This PR fixes the issues from our review of temporalio#344, on top of its branch.

  • Unscoped @nexus.source and @nexus.default apply to the Workflow API only, so existing WIT keeps working with --targets client.
  • With no --targets, nexgen generates definitions again for WIT with resources or sources. Resources are data classes with their fields.
  • A returned client handle gets the Nexus client of its own service. Each extension has a factory, like client.stream(...), that rebuilds a handle from stored fields.
  • The client protocol matches temporalio.client.NexusClient. Each client method takes an operation_id, and uses a random one when it's None.
  • In a resource method, an applicable source wins over a resource field of the same name, in every language.
  • Python proto decode accepts an empty sourced string again.
  • examples.toml refuses unknown keys, unknown sections and child names that share a directory. A hidden --native-api says to use --targets workflow, and generate_source keeps the Workflow API.
  • target-sources also runs in TypeScript, Go and .NET, and the stream sample gets the Python client target.

Two fixes go beyond the review. Go definitions-only output compiles again, and Go fills @nexus.source fields for requests that aren't proto-backed.

Still open:

Why?

With temporalio#344 as it was, existing WIT broke with --targets client, definitions-only generation refused resources, and a temporalio.client.Client couldn't serve as the client. The other changes are the smaller review points.

How did you test it?

Link to a test plan if any -

  • Unit Tests
  • Staging
  • End to End Tests

Each fix has a sample test or a rejection fixture. tests/test_sdk_client.py runs a real temporalio.client.Client subclass through the SDK's Nexus path, with an interceptor in place of a server. cargo validate passes.

An unscoped helper such as `workflow_namespace()` needs a Workflow context. A
client that called it failed at run time, and generation gave no error.
`PythonTarget` copied `GenerationTarget`, and two checks ran twice per run. A
private client method named `_create_nexus_client` replaced the extension hook.
One long line has no trailing comma, so `ruff format` joined the requests in the
samples, and unformatted output got lines of about 200 characters.
Python sent the resource field, Go overwrote it with the source, and TypeScript
and .NET used the source. A shared per-target plan gives every language the
TypeScript and .NET behavior.
The client resource method sent `None` for an optional Workflow-only source,
and the caller had no parameter to set it.
Without a source default in the shared model, decode refused an empty sourced
value. A handler then rejected requests that it accepted before.
The root classes had stub methods that always raised, and the client package
kept private copies of them. The client now decodes results into the root
classes.
A handler that implements a service generates definitions only, from the WIT
that its callers share. That WIT can have resources and sources, and the
default build has no `--targets`, so it couldn't generate such WIT at all.
When another interface returned a resource, the handle kept the client of the
returning service, so its methods started operations on the wrong endpoint.
`Client.create_nexus_client` didn't fit the generated hook, so a real client
failed to type-check and to run. Each call now passes an operation ID, which
the caller can set so that a retry doesn't start a second operation.
To rebuild a client handle from stored identity fields, a caller needed the
private `_create_nexus_client` hook and the wire names of the service.
The server refuses a second operation with the same ID. A retry doesn't find
the first one.
A misspelled key was read as a child configuration and the parent then stopped generating. The error now names the key and its section.
A misspelled section name gave definitions-only output with no error, or an error that did not point at examples.toml.
Children whose names map to one directory in any language would merge their files. Names with a leading digit or a Python keyword are not importable packages.
The removed flag now points at --targets workflow. The library function generate_source builds the Workflow API again, as it did before the targets change.
The target-sources sample now builds for the workflow target in all three languages, each with a test that a client-only source is a parameter. Go filled sourced fields only on proto-backed inputs, so operations without a proto input now fill them too.
Go output with no Workflow API kept the imports of that API and did not compile. The renderer pruned only aliased imports, and now prunes plain ones too.
The client constructor line describes a new feature, so it moves to added. The breaking entry lists the flag and library changes, and a new fixed entry covers Go output with no Workflow API.
The flag is gone, so READMEs, specs and comments now name the Workflow API.
A reader could copy the sample, but its fields do not match the meaning of the borrowed messages.
AGENTS.md asks for no tests that search generated text. The compile test in validation-tests covers the same output.
…mment.

The sources line still said that sources apply to every target and that
resources need a target. The `kw_only` flips had no entry yet.
Only Python has the client target, and the stream sample also builds the
Workflow API in TypeScript and .NET.
The stream sample is the one System Nexus service with a client, on the
`__temporal_system` endpoint, and no sample built or type-checked it.
The `orders` interface in `target-sources.wit` broke the .NET build of that
sample, which now runs in every language. Two services there declare two
`Operations` classes in one namespace.
@moetemp

moetemp commented Oct 30, 2026

Copy link
Copy Markdown
Owner Author

Moved to temporalio#346.

@moetemp moetemp closed this Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant