Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## [v0.8.0] - 2026-08-29

### Added

- **`method_ref` is a typed run source.** `execute`, `start`, and `start_and_wait` take a published method's address — `github.com/<owner>/<repo>[/<selector>][@<tag>]` — as a keyword parameter beside the protocol's inline source, mirroring `@pipelex/sdk` v0.16.0. It is a layer-2 Pipelex-API argument the RUNNER resolves (git fetch at the tag, package located by manifest identity), deliberately separate from the hosted-only `method_id`: an address is meaningful against a bare runner, a catalog id is not. Served by pipelex-api >= 0.21.0; on `api.pipelex.com` availability follows the platform deploy that forwards it. An empty string is treated as absent, a non-string raises at the boundary, `extra={"method_ref": …}` is rejected (the key joins the reserved set), and the selector survives `start_and_wait`'s blocking-execute fallback.
- **Provenance comes back typed.** A `method_ref` run's start ack is the new `PipelexRunResultStart` (`pipelex_sdk.runs`), carrying `method_provenance` — the new `MethodProvenance` shape `{address, tag, commit_sha}`, the SHA being what keeps the run explainable when a tag moves — and `PipelexExecuteResult` declares the same field on the blocking path. Both are `None` for inline-source and `method_id` runs.
- **Client-side exclusivity guards mirroring the server's 422s.** A `method_ref` is a complete run source, so it pairs with nothing: combining it with inline `mthds_contents` or with `method_id` raises `PipelineRequestError` whose wording mirrors the server's validator — before anything hits the wire. The documented run-route exception is untouched: inline source + `method_id` stays legal (the inline source runs; the id demotes to run-history linkage), and `pipe_code` beside a `method_ref` stays legal (it overrides the manifest's `main_pipe`).
- **`validate` takes method selectors.** `mthds_contents` is now optional, and the new keyword parameters `method_ref=` (runner-resolved by address, the package's real file names feeding the diagnostics' source labels) and `method_id=` (hosted-only, platform-resolved) select what is validated — under the tooling routes' strict three-way XOR: exactly one selector, no linkage exception, `mthds_sources` legal only beside inline contents. A selector validation sends no `mthds_contents` key at all. A selector-resolution failure (fetch failure, no package at the address, an unknown id) is a non-2xx, never an `is_valid: false` verdict.
- **The crate routes, with the typed `method_id` pass-through.** New `resolve()` and `codegen()` client methods for `POST /v1/resolve` (the normalized library crate) and `POST /v1/codegen` (stamped typed artifacts plus their `codegen.lock`), with the new `pipelex_sdk.crate_models` wire models (`ResolveRequest` / `ResolveResponse`, `CodegenRequest` / `CodegenResponse`, `GeneratedArtifact`, `CodegenKind` / `CodegenTarget`). Their closure is exactly one of inline `files` / an address-form `method_ref` / the hosted `method_id`, enforced at request construction as well as by the server — with an empty selector (`files=[]`, a blank or whitespace-only string) normalized to absent before the XOR counts, the same empty-as-absent rule as the run routes, so an unusable value never passes as the sole selector; `method_id` is a pure server pass-through the platform resolves (an unknown or foreign-org id is a `404`, a stored method with no MTHDS source a `422`). This closes the JS-parity gap the architecture doc carried for the two routes.
- **`build_inputs` takes a `method_ref` closure.** `BuildInputsRequest` now extends the shared `CrateRequestBase` envelope (`files` XOR `method_ref`); the address form is server-resolved, the registry form keeps its `501`.
- **A `method_ref` request gets a fetch-sized budget.** Resolving an address can make the server clone a repository before it answers, and the server-side clone timeout runs well past the client's 30s management budget on a cold cache — an abort there would report a healthy, still-cloning server as unreachable. A `method_ref`-carrying `build_inputs`, `resolve`, or `codegen` uses an internal 3-minute budget; it is internal (no new caller-facing parameter) and inert behind the hosted gateway's own cap. The run routes and `validate` need no such override — they already ride the 20-min blocking ceiling, unlike the JS SDK's short start budget.

### Changed

- **Breaking: `start` returns `PipelexRunResultStart`.** A widening of the previous `RunResultStart` return type (one typed optional field over the extension-open base) — no caller change needed unless a caller depended on the exact class.
- **Breaking: `BuildInputsRequest.files` is optional** (the closure is `files` XOR `method_ref`, checked at construction), and handing the model a `method_id` raises a teaching error naming the migration — the `/v1/build/*` projections are deliberately excluded from the hosted tooling selector, so a stored method is expanded by the caller (fetch it with `get_method` and pass its source as `files`). This SDK never had client-side by-id expansion legs to delete, so the JS release's deletions have no Python counterpart.
- **`extra` now also rejects `method_ref`**, for the same reason it rejects every named request option: `extra` merges last into the body, so a smuggled copy would overwrite the validated named option and bypass the selector-exclusivity checks. The guard's wording changed from "hosted args" to "reserved request args" now that it spans two layers.

## [v0.7.0] - 2026-08-28

### Added
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ async def main() -> None:
print(result.main_stuff)
```

### Run a published method by address

A method reaches every method-taking call in exactly one of three forms: inline source, a `method_ref` address (`github.com/<owner>/<repo>[/<selector>][@<tag>]`, resolved by the server — pipelex-api >= 0.21.0; on `api.pipelex.com` availability follows the platform deploy that forwards it), or a hosted `method_id` (`mt_…`, resolved by the platform). A `method_ref` pairs with nothing — it is a complete run source — and its runs carry typed provenance:

```python
ack = await client.start(method_ref="github.com/Pipelex/methods/documents@v0.1.0", inputs={...})
print(ack.method_provenance.commit_sha) # the SHA actually fetched — stable even if the tag moves
result = await client.wait_for_result(ack.pipeline_run_id)

# The tooling routes take the same selectors under a strict XOR (exactly one, no pairing):
report = await client.validate(method_ref="github.com/Pipelex/methods/documents@v0.1.0")
report = await client.validate(method_id="mt_123")
```

### Long runs: start + poll explicitly

Behind the hosted gateway, a synchronous `execute()` is cut off at ~30s and surfaces a `PipelineExecuteTimeoutError` pointing here. For long methods, drive the durable lifecycle yourself — the run survives client disconnects and is resumable by `pipeline_run_id`:
Expand Down
Loading
Loading