@pipelex/sdk 0.34.1 → 0.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -3
- package/dist/cli/help.d.ts +3 -3
- package/dist/cli/help.js +6 -3
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/method.d.ts +9 -3
- package/dist/cli/method.js +30 -7
- package/dist/cli/method.js.map +1 -1
- package/dist/cli/script.d.ts +6 -2
- package/dist/cli/script.js +13 -6
- package/dist/cli/script.js.map +1 -1
- package/dist/client.d.ts +178 -40
- package/dist/client.js +267 -42
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +34 -9
- package/dist/errors.js +16 -9
- package/dist/errors.js.map +1 -1
- package/dist/execute-result.d.ts +6 -0
- package/dist/execute-result.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/method-selector.d.ts +42 -0
- package/dist/method-selector.js +63 -0
- package/dist/method-selector.js.map +1 -0
- package/dist/models.d.ts +22 -9
- package/dist/product-models.d.ts +221 -11
- package/dist/runs.d.ts +13 -0
- package/dist/runs.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/architecture.md +6 -5
- package/docs/cli.md +6 -6
- package/docs/crate-routes.md +4 -2
- package/docs/errors.md +18 -5
- package/docs/input-preparation.md +5 -3
- package/docs/run-results.md +1 -1
- package/package.json +1 -1
package/docs/errors.md
CHANGED
|
@@ -41,7 +41,7 @@ try {
|
|
|
41
41
|
| Class | `errorDomain` | `retryable` | Why |
|
|
42
42
|
|---|---|---|---|
|
|
43
43
|
| `ApiResponseError` | the server's, else the fallback | the server's, else no for a sent `input` or `config` domain, else the fallback | See [below](#a-refused-requests-verdict). |
|
|
44
|
-
| `RequestArgumentError` | `input` | no | The client refused a call's arguments before sending any request: no run source given to `execute` or `start`, run sources or method selectors that exclude each other, a selector rule of `validate`, an empty `validateFiles`, a reserved key in `extra
|
|
44
|
+
| `RequestArgumentError` | `input` | no | The client refused a call's arguments before sending any request: no run source given to `execute` or `start`, run sources or method selectors that exclude each other, a selector rule of `validate`, an empty `validateFiles`, a reserved key in `extra`, a `publishMethod` without its token, a `getMethodVersion` version that is not a positive integer, or a selector `parseMethodSelector` refuses. Its options take an optional `verdict`, and the client declares `config` for a base URL that is not host-only, since it typically comes from `PIPELEX_BASE_URL`. That refusal shows the base URL's scheme and host alone and names the other parts it carried (credentials, a path, a query, a fragment) without their text, since those are where a secret travels in a URL; a value that is not an http or https URL is not shown at all. It is a `PipelineRequestError`, as the bare refusal it replaced was, and a refusal the standard's own run-source check raises keeps that original as `cause`. |
|
|
45
45
|
| `ApiUnreachableError` | `config` | yes | The address or the network must be checked, and a later attempt can get through. With the code `ABORT_TIMEOUT`, the SDK's own request timeout, it is `runtime`: the API took the request and did not answer in time. |
|
|
46
46
|
| `PipelineExecuteTimeoutError` | `input` | no | The blocking `execute` cannot outlast the gateway's limit; start the run and poll instead. |
|
|
47
47
|
| `RunFailedError` | the report's | the report's | See [a failed run](#a-failed-run--runerrorreport). |
|
|
@@ -71,7 +71,7 @@ The fallback reads the HTTP status, the platform's `code`, and whether the body
|
|
|
71
71
|
| `404`, bare | `config` | no | The base URL points at a deployment without the route. |
|
|
72
72
|
| `405` | `config` | no | The deployment does not serve this method on the route. |
|
|
73
73
|
| `408`, `429` | `runtime` | yes | Refused for its timing, not its content. |
|
|
74
|
-
| `409` | `input` | no | The request conflicts with the stored state: a method being deleted, a stale
|
|
74
|
+
| `409` | `input` | no | The request conflicts with the stored state: a method being deleted, a stale draft token, a method never published addressed by its bare id, a taken label. |
|
|
75
75
|
| `409` with code `pipelex_api_key_limit_reached` | `config` | no | The organization holds as many keys as it may; someone removes one. |
|
|
76
76
|
| `501` | `config` | no | The deployment does not implement it, and asking again will not change that. |
|
|
77
77
|
| `500`, `502`, `503`, `504`, and any `5xx` not listed here | `runtime` | yes | A fault in the service, which may pass. |
|
|
@@ -155,7 +155,7 @@ A field a newer runner adds is reachable through the interface's index signature
|
|
|
155
155
|
|
|
156
156
|
Every non-2xx answer from a `/v1` route is a problem document, and the SDK throws an `ApiResponseError` whose fields are its members. Each field is `undefined` when the document did not carry it, and a member of the wrong type (a numeric `type`, a `retryable` of `"no"`, a `user_action` without a `detail`) reads as absent rather than as a wrong value. The nested members are checked one level down, exactly as a [stored report's](#a-failed-run--runerrorreport) are: `providerMetadata` and `migration` keep each named field only when it has its type, `validationErrors` keeps only the items that are objects with a string `category` and `message`, and each item of `errors` keeps its `field`, `code` and `detail` only when they are strings; members the SDK does not name are relayed as sent. The verdict is the exception: `errorDomain` and `retryable` are always decided, the server's value when it sent a valid one and otherwise [as the verdict section says](#a-refused-requests-verdict).
|
|
157
157
|
|
|
158
|
-
**An answer the SDK could not read is an `ApiResponseError` too.** A `2xx` whose body is not JSON, such as a gateway's HTML page or an empty body where the route answers one, is no result the SDK can hand back, so every route throws an `ApiResponseError` for it instead of letting the runtime's `SyntaxError` escape. So is a `2xx` whose body is JSON but not the object the route answers — `null`, a number, a string, an array — on every protocol, extension and run-lifecycle route, on `health()`, and on the product routes whose answer the SDK or its caller reads before anything else (`listMethods`, `getMethod`, `createMethod`, `
|
|
158
|
+
**An answer the SDK could not read is an `ApiResponseError` too.** A `2xx` whose body is not JSON, such as a gateway's HTML page or an empty body where the route answers one, is no result the SDK can hand back, so every route throws an `ApiResponseError` for it instead of letting the runtime's `SyntaxError` escape. So is a `2xx` whose body is JSON but not the object the route answers — `null`, a number, a string, an array — on every protocol, extension and run-lifecycle route, on `health()`, and on the product routes whose answer the SDK or its caller reads before anything else (`listMethods`, `getMethod`, `createMethod`, `writeDraft`, `renameMethod`, `publishMethod`, `listMethodVersions`, `getMethodVersion`, `listRuns`, `getRunDetail`, `upload`, `requestUploadGrant`, `resolveStorageUrls`), instead of the `TypeError` that reading it would raise. So is an object missing the member those reads depend on: a page of `listMethods`, `listMethodVersions` or `listRuns` whose `items` is not an array or whose `next_cursor` is neither a string nor `null`, which `iterateMethods` and `iterateRuns` could not walk or would follow forever; a publish result whose `outcome` is not `published`, `unchanged` or `refused`, or whose `method` is not an object, which a caller branching on `outcome` could not read; an `upload` answer with no non-empty string `uri`, which names no stored file; and a stored method or a published version whose `mthds` field is neither a string nor absent (a `null` one is still no source, which `getMethodClosure` reports as `EmptyMethodSourceError`) or whose `python` field is not the serialized `[{ name, content }]` list, as `getMethod`, `createMethod`, `writeDraft`, `renameMethod`, `publishMethod` and `getMethodVersion` answer it: that is server data no change to the call fixes, not an argument the caller passed. Its `status` is the `2xx`, `responseBody` the raw text, `cause` what made the answer unreadable (the parse failure, or `mthds`'s refusal of the `python` field; nothing for a body that parsed to something the route does not answer), `problemDocument` and the problem members are `undefined`, and its verdict is the fallback's for a status no refusal carries: `runtime`, not retryable. A product route that answers a `2xx` with no body at all, such as `revokePipelexApiKey`, still resolves to `undefined`, and the other product routes hand their decoded body back as it came.
|
|
159
159
|
|
|
160
160
|
| Field | Wire member | Meaning |
|
|
161
161
|
|---|---|---|
|
|
@@ -167,7 +167,7 @@ Every non-2xx answer from a `/v1` route is a problem document, and the SDK throw
|
|
|
167
167
|
| `title` | `title` | The stable human label of the error class. |
|
|
168
168
|
| `serverMessage` | `detail` (or `message`) | The per-occurrence message. |
|
|
169
169
|
| `instance` | `instance` | The occurrence: a request URN (`urn:pipelex:request:<id>`) or a request path. |
|
|
170
|
-
| `code` | `code` | The platform's native code, a closed set (`conflict`, `not_found`, `validation_failed`, `pipelex_api_key_limit_reached`, …), one-to-one with `type
|
|
170
|
+
| `code` | `code` | The platform's native code, a closed set (`conflict`, `not_found`, `validation_failed`, `pipelex_api_key_limit_reached`, …), one-to-one with `type`; `MethodErrorCode` names the method ones (see [The method codes](#the-method-codes)). **A branch field for a client of the platform**, absent on a refusal it relays from the runner. |
|
|
171
171
|
| `errorType` | `error_type` | The runner's native code, its open exception class name. |
|
|
172
172
|
| `errorCategory`, `model`, `provider`, `providerMetadata` | `error_category`, `model`, `provider`, `provider_metadata` | An inference failure's class and origin, as on the run report. |
|
|
173
173
|
| `migration` | `migration` | A pending configuration migration that explains the failure. |
|
|
@@ -176,7 +176,7 @@ Every non-2xx answer from a `/v1` route is a problem document, and the SDK throw
|
|
|
176
176
|
| `problemDocument` | the whole body | The decoded document, every member named or not; `undefined` when the body was not a JSON object. The record of what the server sent, verdict members included. |
|
|
177
177
|
| `status`, `statusText`, `responseBody` | the transport | The HTTP status, its text and the raw body. |
|
|
178
178
|
|
|
179
|
-
**Branch on `errorDomain` and `type`, never on the HTTP status or the message.** That is the rule the hosted-envelope spec sets
|
|
179
|
+
**Branch on `errorDomain` and `type`, never on the HTTP status or the message.** That is the rule the hosted-envelope spec sets across surfaces: `errorDomain` tells the caller's own mistake from a fault it cannot fix, and `type` names the error class with a URI that stays the same on every occurrence, and both mean the same on the runner and the platform. `code` and `errorType` are each surface's finer native code, and a client of one surface may branch on that surface's code too. On the platform `type` is `https://pipelex.com/errors/<code>`, derived from `code` one to one, so branching on either reads the same answer; the platform may add codes, so a code the caller does not know gets its generic handling. A refusal the platform relays from the runner, such as a run route's refusal to run an invalid method, carries the runner's `type` and `errorType` and no `code`, so a caller branching on `code` reads its absence as a refusal the runner authored and branches on `type` or `errorType` there. On the platform today `error_domain` is not emitted yet, so the fallback reads `errorDomain` from the status:
|
|
180
180
|
|
|
181
181
|
```ts
|
|
182
182
|
import { ApiResponseError } from "@pipelex/sdk";
|
|
@@ -197,6 +197,19 @@ try {
|
|
|
197
197
|
|
|
198
198
|
The members `mthds`'s own `ApiResponseError` carries (`type`, `title`, `instance`, `requestId`, `errorDomain`, `retryable`, `userAction`) have the same names here, and the same types except the verdict: the standard's client leaves `errorDomain` an open string and `retryable` optional, where this SDK decides both. A type-level test pins `ProblemDetails`, the members as parsed, to the standard client's declaration, so a consumer reads one vocabulary whichever client raised the error. The rest are the Pipelex members the standard's client leaves to this SDK.
|
|
199
199
|
|
|
200
|
+
### The method codes
|
|
201
|
+
|
|
202
|
+
A refusal about a saved method or one of its versions carries one of the platform codes the exported type `MethodErrorCode` names. `code` itself stays a `string`, since the platform adds codes; every one of these is `input` and not retryable by the fallback, since asking again unchanged meets the same answer.
|
|
203
|
+
|
|
204
|
+
| `code` | Status | When | What the caller does |
|
|
205
|
+
|---|---|---|---|
|
|
206
|
+
| `method_update_conflict` | `409` | The draft moved since the token a `writeDraft` (`expected_updated_at`) or a `publishMethod` (`expected_draft_updated_at`) sent; nothing was written or published. `errors[0].field` names the request field that carried the token. | Read the method again, and either load its draft or overwrite it by writing again with the fresh token. |
|
|
207
|
+
| `method_being_deleted` | `409` | The method's erasure has started, on every route that addresses it; the detail tells an erasure in flight from a failed one. | Stop offering the method; retry the delete when the detail says it failed. |
|
|
208
|
+
| `method_not_published` | `409` | A bare `method_id`, which names the latest published version, on a run or tooling route, for a method never published. The detail names `mt_…@draft` and publishing. | Publish the method, or address its draft as `mt_…@draft`. |
|
|
209
|
+
| `method_version_not_found` | `404` | `mt_…@<n>`, or `getMethodVersion`, names a version the method never published. An unknown method is `not_found` instead, so the two are told apart by the code. | Pick a version `listMethodVersions` lists. |
|
|
210
|
+
|
|
211
|
+
A malformed version suffix (`@0`, `@03`, `@Draft`, two suffixes) is a `422` `validation_failed` whose `errors` name the field `method_id`; `parseMethodSelector` refuses the same selectors locally with a `RequestArgumentError`, before anything is sent. So is any suffix on the run routes' linkage form, a `method_id` beside an inline source, which `execute` and `start` refuse locally the same way.
|
|
212
|
+
|
|
200
213
|
## A validation item — `ValidationErrorItem`
|
|
201
214
|
|
|
202
215
|
A method refused for what it says, rather than for how its run went, comes back as a list of validation items. They ride the `/v1/validate` verdict (its invalid arm's `validation_errors[]`, and the advisory `warnings[]` of its valid arm) and the crate routes' invalid verdict (`CrateInvalidReport.validation_errors[]`), each a `200` because an invalid bundle is a produced verdict; the `422` a run route answers when the runner refuses the method for its validation errors, as `ApiResponseError.validationErrors`; and a failed run's report, as `validation_errors`. Each item has a `category` and a `message`; the other members locate the error and say what to do next, and each is present only when the runner knows it:
|
|
@@ -115,7 +115,7 @@ Exactly one per call. The type pins the other two to `never`, so a second select
|
|
|
115
115
|
| --- | --- | --- |
|
|
116
116
|
| `files` | the inline MTHDS closure (`{content, source?}` entries) | nobody — inline |
|
|
117
117
|
| `method_ref` | a published method's address, `github.com/<owner>/<repo>[/<selector>][@<tag>]` | the runner, server-side (pipelex-api >= 0.21.0 fetches the repository at the tag) |
|
|
118
|
-
| `method_id` | a stored method's catalog id (`mt_
|
|
118
|
+
| `method_id` | a stored method's catalog id (`mt_…`, `mt_…@<n>` or `mt_…@draft`) | the hosted platform, which injects the `.mthds` files of the version it names before the runner sees the request |
|
|
119
119
|
|
|
120
120
|
Nothing is expanded client-side: `method_id` here is a **pass-through**, the same rule every other id-taking operation follows. `getMethodClosure` stays available for callers that want the files in hand, but it is no longer a step on the way to preparing inputs.
|
|
121
121
|
|
|
@@ -149,7 +149,9 @@ There is no single-pipe fallback: a method that declares one pipe and no `main_p
|
|
|
149
149
|
client.getMethodClosure(methodId) → MthdsFileItem[]
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
-
`getMethodClosure` is the public **local expansion utility** — a client-side semantic layer over `getMethod` (the platform has no route that returns a parsed closure). It fetches the method, parses its polymorphic `mthds` source with [`methodSourceToContents`](#methodsourcetocontents--the-canonical-source-parser), and labels each resulting file with the `method_id` as its `source` provenance.
|
|
152
|
+
`getMethodClosure` is the public **local expansion utility** — a client-side semantic layer over `getMethod` (the platform has no route that returns a parsed closure). It fetches the method, parses its **draft's** polymorphic `mthds` source with [`methodSourceToContents`](#methodsourcetocontents--the-canonical-source-parser), and labels each resulting file with the `method_id` as its `source` provenance.
|
|
153
|
+
|
|
154
|
+
**It reads the draft, which is not what a bare id runs.** `GET /v1/methods/{id}` answers the method with its draft, whatever the publish state, while a run or a tooling call by a bare `method_id` resolves to the latest *published* version, which the draft may be ahead of. For the closure of a version, read it with `getMethodVersion(methodId, n)` and parse its `mthds` with `methodSourceToContents`. Like `getMethod`, it takes a bare id: a caller holding `mt_…@3` strips the suffix with `parseMethodSelector` first.
|
|
153
155
|
|
|
154
156
|
Reach for it whenever you want the files **in hand** — to edit, to diff, or to send to a bare runner, which has no catalog to resolve an id against:
|
|
155
157
|
|
|
@@ -157,7 +159,7 @@ Reach for it whenever you want the files **in hand** — to edit, to diff, or to
|
|
|
157
159
|
runner.resolve({ files: await hosted.getMethodClosure("mt_…") })
|
|
158
160
|
```
|
|
159
161
|
|
|
160
|
-
Every method-taking operation — `execute` / `start`, `validate` / `resolve` / `codegen` / `pipeIo`, and `prepareInputs` — takes a `method_id` **natively** on the hosted API, as a server pass-through: the platform resolves it and injects the
|
|
162
|
+
Every method-taking operation — `execute` / `start`, `validate` / `resolve` / `codegen` / `pipeIo`, and `prepareInputs` — takes a `method_id` **natively** on the hosted API, as a server pass-through, its version suffix included (`mt_…`, `mt_…@<n>`, `mt_…@draft`): the platform resolves it and injects the source of the version it names before the runner sees the request (see [architecture.md → hosted run extensions](./architecture.md#hosted-run-extensions-method_id)). That is the uniform rule — *an id option is always a server pass-through, and any client-side expansion is the caller's own explicit call*.
|
|
161
163
|
|
|
162
164
|
- **Requires an API key.** The methods catalog is org-scoped to the key's org, so resolution only works with an authenticated Pipelex-product key.
|
|
163
165
|
- **Unknown or foreign-org id → the `getMethod` `404`** (`ApiResponseError`, `code: "not_found"`), propagated unchanged. An id from another org is indistinguishable from a nonexistent one — both 404.
|
package/docs/run-results.md
CHANGED
|
@@ -70,7 +70,7 @@ const results = await client.startAndWaitForResult(
|
|
|
70
70
|
);
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
It is never called on the blocking path, a bare runner's `POST /v1/execute` or the fallback to it, which has no run id to give before it answers. The acknowledgement is handed over whole, a `method_ref` run's `method_provenance` included. The callback runs synchronously and its return value is ignored; an exception it throws propagates out of `startAndWaitForResult` before anything is polled, and the run it was told about keeps going.
|
|
73
|
+
It is never called on the blocking path, a bare runner's `POST /v1/execute` or the fallback to it, which has no run id to give before it answers. The acknowledgement is handed over whole, a `method_ref` run's `method_provenance` and a `method_id` run's `method_version` (the version the run runs, a number or `"draft"`) included. The callback runs synchronously and its return value is ignored; an exception it throws propagates out of `startAndWaitForResult` before anything is polled, and the run it was told about keeps going.
|
|
74
74
|
|
|
75
75
|
**An abort before the run exists creates none.** The `signal` is read before the run is started as well as during the wait: a caller that aborts while the `GET /v1/version` handshake is in flight gets its abort, and neither `POST /v1/start` nor the blocking `POST /v1/execute` is sent; nor is the execute when the abort lands while a runner that looked hosted refuses the start. Once the start or the execute is sent, the abort stops only the wait, and a started run goes on, by its id.
|
|
76
76
|
|