@aexhq/sdk 0.46.5-canary → 0.51.0
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/LICENSE +201 -0
- package/NOTICE +38 -0
- package/README.md +54 -29
- package/dist/client/aex.d.ts +33 -0
- package/dist/client/aex.js +108 -0
- package/dist/client/aex.js.map +1 -0
- package/dist/client/credentials.d.ts +25 -0
- package/dist/client/credentials.js +97 -0
- package/dist/client/credentials.js.map +1 -0
- package/dist/client/routing.d.ts +7 -0
- package/dist/client/routing.js +29 -0
- package/dist/client/routing.js.map +1 -0
- package/dist/downloads/download.d.ts +18 -0
- package/dist/downloads/download.js +67 -0
- package/dist/downloads/download.js.map +1 -0
- package/dist/generated/errors.d.ts +12 -0
- package/dist/generated/errors.js +82 -0
- package/dist/generated/errors.js.map +1 -0
- package/dist/generated/models.d.ts +1392 -0
- package/dist/generated/models.js +62 -0
- package/dist/generated/models.js.map +1 -0
- package/dist/generated/resources.d.ts +710 -0
- package/dist/generated/resources.js +582 -0
- package/dist/generated/resources.js.map +1 -0
- package/dist/generated/routes.d.ts +44 -0
- package/dist/generated/routes.js +1905 -0
- package/dist/generated/routes.js.map +1 -0
- package/dist/index.d.ts +21 -50
- package/dist/index.js +14 -62
- package/dist/index.js.map +1 -1
- package/dist/node/session-file-limits.d.ts +4 -0
- package/dist/node/session-file-limits.js +7 -0
- package/dist/node/session-file-limits.js.map +1 -0
- package/dist/node/session-files.d.ts +80 -0
- package/dist/node/session-files.js +254 -0
- package/dist/node/session-files.js.map +1 -0
- package/dist/observations/stream.d.ts +1 -0
- package/dist/observations/stream.js +18 -0
- package/dist/observations/stream.js.map +1 -0
- package/dist/transport/errors.d.ts +60 -0
- package/dist/transport/errors.js +107 -0
- package/dist/transport/errors.js.map +1 -0
- package/dist/transport/pagination.d.ts +8 -0
- package/dist/transport/pagination.js +34 -0
- package/dist/transport/pagination.js.map +1 -0
- package/dist/transport/retry.d.ts +21 -0
- package/dist/transport/retry.js +37 -0
- package/dist/transport/retry.js.map +1 -0
- package/dist/transport/transport.d.ts +25 -0
- package/dist/transport/transport.js +33 -0
- package/dist/transport/transport.js.map +1 -0
- package/package.json +67 -30
- package/dist/_contracts/account-operations.d.ts +0 -101
- package/dist/_contracts/account-operations.js +0 -242
- package/dist/_contracts/account-types.d.ts +0 -461
- package/dist/_contracts/account-types.js +0 -1
- package/dist/_contracts/api-key.d.ts +0 -61
- package/dist/_contracts/api-key.js +0 -101
- package/dist/_contracts/api-routes.d.ts +0 -20
- package/dist/_contracts/api-routes.js +0 -109
- package/dist/_contracts/archive-limits.d.ts +0 -3
- package/dist/_contracts/archive-limits.js +0 -23
- package/dist/_contracts/asset-authoring.d.ts +0 -22
- package/dist/_contracts/asset-authoring.js +0 -106
- package/dist/_contracts/asset-bundle.d.ts +0 -64
- package/dist/_contracts/asset-bundle.js +0 -263
- package/dist/_contracts/asset-upload-helper.d.ts +0 -31
- package/dist/_contracts/asset-upload-helper.js +0 -84
- package/dist/_contracts/billing-admission.d.ts +0 -29
- package/dist/_contracts/billing-admission.js +0 -28
- package/dist/_contracts/bundle-manifest.d.ts +0 -89
- package/dist/_contracts/bundle-manifest.js +0 -158
- package/dist/_contracts/canonical-sha256.d.ts +0 -8
- package/dist/_contracts/canonical-sha256.js +0 -8
- package/dist/_contracts/connection-ticket.d.ts +0 -22
- package/dist/_contracts/connection-ticket.js +0 -54
- package/dist/_contracts/continuation-event.d.ts +0 -31
- package/dist/_contracts/continuation-event.js +0 -6
- package/dist/_contracts/contract-parse-error.d.ts +0 -12
- package/dist/_contracts/contract-parse-error.js +0 -51
- package/dist/_contracts/error-codes.d.ts +0 -26
- package/dist/_contracts/error-codes.js +0 -116
- package/dist/_contracts/error-factory.d.ts +0 -32
- package/dist/_contracts/error-factory.js +0 -174
- package/dist/_contracts/event-envelope.d.ts +0 -471
- package/dist/_contracts/event-envelope.js +0 -501
- package/dist/_contracts/event-stream-client.d.ts +0 -122
- package/dist/_contracts/event-stream-client.js +0 -445
- package/dist/_contracts/event-view.d.ts +0 -44
- package/dist/_contracts/event-view.js +0 -69
- package/dist/_contracts/failure-class.d.ts +0 -29
- package/dist/_contracts/failure-class.js +0 -73
- package/dist/_contracts/http.d.ts +0 -135
- package/dist/_contracts/http.js +0 -434
- package/dist/_contracts/ids.d.ts +0 -66
- package/dist/_contracts/ids.js +0 -119
- package/dist/_contracts/index.d.ts +0 -42
- package/dist/_contracts/index.js +0 -52
- package/dist/_contracts/internal.d.ts +0 -55
- package/dist/_contracts/internal.js +0 -113
- package/dist/_contracts/models.d.ts +0 -30
- package/dist/_contracts/models.js +0 -28
- package/dist/_contracts/operation-core.d.ts +0 -36
- package/dist/_contracts/operation-core.js +0 -70
- package/dist/_contracts/operations.d.ts +0 -218
- package/dist/_contracts/operations.js +0 -1496
- package/dist/_contracts/otlp-projection.d.ts +0 -78
- package/dist/_contracts/otlp-projection.js +0 -171
- package/dist/_contracts/post-hook.d.ts +0 -31
- package/dist/_contracts/post-hook.js +0 -61
- package/dist/_contracts/provider-fault.d.ts +0 -34
- package/dist/_contracts/provider-fault.js +0 -68
- package/dist/_contracts/retry-core.d.ts +0 -29
- package/dist/_contracts/retry-core.js +0 -79
- package/dist/_contracts/runner-event.d.ts +0 -117
- package/dist/_contracts/runner-event.js +0 -172
- package/dist/_contracts/runtime-kind.d.ts +0 -60
- package/dist/_contracts/runtime-kind.js +0 -70
- package/dist/_contracts/runtime-manifest.d.ts +0 -121
- package/dist/_contracts/runtime-manifest.js +0 -83
- package/dist/_contracts/runtime-security-profile.d.ts +0 -26
- package/dist/_contracts/runtime-security-profile.js +0 -73
- package/dist/_contracts/runtime-sizes.d.ts +0 -104
- package/dist/_contracts/runtime-sizes.js +0 -111
- package/dist/_contracts/runtime-types.d.ts +0 -618
- package/dist/_contracts/runtime-types.js +0 -58
- package/dist/_contracts/schemas/asset-bundle.d.ts +0 -70
- package/dist/_contracts/schemas/asset-bundle.js +0 -107
- package/dist/_contracts/schemas/asset-ref.d.ts +0 -61
- package/dist/_contracts/schemas/asset-ref.js +0 -118
- package/dist/_contracts/schemas/bundle-manifest.d.ts +0 -66
- package/dist/_contracts/schemas/bundle-manifest.js +0 -77
- package/dist/_contracts/schemas/index.d.ts +0 -32
- package/dist/_contracts/schemas/index.js +0 -30
- package/dist/_contracts/schemas/mcp-server.d.ts +0 -99
- package/dist/_contracts/schemas/mcp-server.js +0 -209
- package/dist/_contracts/schemas/models.d.ts +0 -29
- package/dist/_contracts/schemas/models.js +0 -51
- package/dist/_contracts/schemas/numeric.d.ts +0 -18
- package/dist/_contracts/schemas/numeric.js +0 -28
- package/dist/_contracts/schemas/post-hook.d.ts +0 -45
- package/dist/_contracts/schemas/post-hook.js +0 -68
- package/dist/_contracts/schemas/response-assets.d.ts +0 -75
- package/dist/_contracts/schemas/response-assets.js +0 -81
- package/dist/_contracts/schemas/response-billing.d.ts +0 -208
- package/dist/_contracts/schemas/response-billing.js +0 -139
- package/dist/_contracts/schemas/response-common.d.ts +0 -132
- package/dist/_contracts/schemas/response-common.js +0 -162
- package/dist/_contracts/schemas/response-identity.d.ts +0 -648
- package/dist/_contracts/schemas/response-identity.js +0 -131
- package/dist/_contracts/schemas/response-mcp-servers.d.ts +0 -51
- package/dist/_contracts/schemas/response-mcp-servers.js +0 -32
- package/dist/_contracts/schemas/response-secrets.d.ts +0 -50
- package/dist/_contracts/schemas/response-secrets.js +0 -32
- package/dist/_contracts/schemas/response-sessions-internal.d.ts +0 -200
- package/dist/_contracts/schemas/response-sessions-internal.js +0 -142
- package/dist/_contracts/schemas/response-sessions.d.ts +0 -1598
- package/dist/_contracts/schemas/response-sessions.js +0 -377
- package/dist/_contracts/schemas/response-webhooks.d.ts +0 -76
- package/dist/_contracts/schemas/response-webhooks.js +0 -42
- package/dist/_contracts/schemas/response-workspace.d.ts +0 -225
- package/dist/_contracts/schemas/response-workspace.js +0 -99
- package/dist/_contracts/schemas/runtime-kind.d.ts +0 -31
- package/dist/_contracts/schemas/runtime-kind.js +0 -29
- package/dist/_contracts/schemas/runtime-security-profile.d.ts +0 -28
- package/dist/_contracts/schemas/runtime-security-profile.js +0 -26
- package/dist/_contracts/schemas/runtime-sizes.d.ts +0 -70
- package/dist/_contracts/schemas/runtime-sizes.js +0 -127
- package/dist/_contracts/schemas/session-limits.d.ts +0 -34
- package/dist/_contracts/schemas/session-limits.js +0 -39
- package/dist/_contracts/schemas/session-machine.d.ts +0 -23
- package/dist/_contracts/schemas/session-machine.js +0 -24
- package/dist/_contracts/schemas/session-request-config.d.ts +0 -58
- package/dist/_contracts/schemas/session-request-config.js +0 -134
- package/dist/_contracts/schemas/session-webhook.d.ts +0 -11
- package/dist/_contracts/schemas/session-webhook.js +0 -38
- package/dist/_contracts/schemas/side-effect-audit.d.ts +0 -98
- package/dist/_contracts/schemas/side-effect-audit.js +0 -102
- package/dist/_contracts/schemas/submission-assets.d.ts +0 -117
- package/dist/_contracts/schemas/submission-assets.js +0 -147
- package/dist/_contracts/schemas/submission-body.d.ts +0 -251
- package/dist/_contracts/schemas/submission-body.js +0 -378
- package/dist/_contracts/schemas/submission-environment.d.ts +0 -79
- package/dist/_contracts/schemas/submission-environment.js +0 -179
- package/dist/_contracts/schemas/submission-request.d.ts +0 -158
- package/dist/_contracts/schemas/submission-request.js +0 -49
- package/dist/_contracts/schemas/submission-secrets.d.ts +0 -47
- package/dist/_contracts/schemas/submission-secrets.js +0 -108
- package/dist/_contracts/schemas/wire.d.ts +0 -118
- package/dist/_contracts/schemas/wire.js +0 -171
- package/dist/_contracts/schemas/workspace-resources.d.ts +0 -50
- package/dist/_contracts/schemas/workspace-resources.js +0 -87
- package/dist/_contracts/sdk-errors.d.ts +0 -212
- package/dist/_contracts/sdk-errors.js +0 -313
- package/dist/_contracts/sdk-secrets.d.ts +0 -67
- package/dist/_contracts/sdk-secrets.js +0 -427
- package/dist/_contracts/session-archive.d.ts +0 -16
- package/dist/_contracts/session-archive.js +0 -92
- package/dist/_contracts/session-artifacts.d.ts +0 -189
- package/dist/_contracts/session-artifacts.js +0 -264
- package/dist/_contracts/session-config.d.ts +0 -373
- package/dist/_contracts/session-config.js +0 -562
- package/dist/_contracts/session-cost-types.d.ts +0 -211
- package/dist/_contracts/session-cost-types.js +0 -69
- package/dist/_contracts/session-cost.d.ts +0 -8
- package/dist/_contracts/session-cost.js +0 -582
- package/dist/_contracts/session-custody.d.ts +0 -165
- package/dist/_contracts/session-custody.js +0 -345
- package/dist/_contracts/session-file-query.d.ts +0 -14
- package/dist/_contracts/session-file-query.js +0 -178
- package/dist/_contracts/session-record.d.ts +0 -112
- package/dist/_contracts/session-record.js +0 -165
- package/dist/_contracts/session-retention.d.ts +0 -201
- package/dist/_contracts/session-retention.js +0 -450
- package/dist/_contracts/side-effect-audit.d.ts +0 -126
- package/dist/_contracts/side-effect-audit.js +0 -520
- package/dist/_contracts/sse.d.ts +0 -74
- package/dist/_contracts/sse.js +0 -227
- package/dist/_contracts/stable.d.ts +0 -45
- package/dist/_contracts/stable.js +0 -62
- package/dist/_contracts/status.d.ts +0 -25
- package/dist/_contracts/status.js +0 -57
- package/dist/_contracts/submission-limits.d.ts +0 -61
- package/dist/_contracts/submission-limits.js +0 -60
- package/dist/_contracts/submission.d.ts +0 -547
- package/dist/_contracts/submission.js +0 -812
- package/dist/_contracts/suggest.d.ts +0 -15
- package/dist/_contracts/suggest.js +0 -53
- package/dist/_contracts/testing/response-bindings.d.ts +0 -45
- package/dist/_contracts/testing/response-bindings.js +0 -256
- package/dist/_contracts/testing/wire-conformance-entry.d.ts +0 -10
- package/dist/_contracts/testing/wire-conformance-entry.js +0 -8
- package/dist/_contracts/testing/wire-conformance.d.ts +0 -169
- package/dist/_contracts/testing/wire-conformance.js +0 -276
- package/dist/_contracts/turn-trace.d.ts +0 -28
- package/dist/_contracts/turn-trace.js +0 -1
- package/dist/_contracts/unknown-field-error.d.ts +0 -13
- package/dist/_contracts/unknown-field-error.js +0 -21
- package/dist/_contracts/value-guards.d.ts +0 -20
- package/dist/_contracts/value-guards.js +0 -34
- package/dist/_contracts/webhook-verify.d.ts +0 -34
- package/dist/_contracts/webhook-verify.js +0 -93
- package/dist/_contracts/wire-observer.d.ts +0 -49
- package/dist/_contracts/wire-observer.js +0 -34
- package/dist/_contracts/workflow-status.d.ts +0 -7
- package/dist/_contracts/workflow-status.js +0 -43
- package/dist/_contracts/workspace-resources.d.ts +0 -98
- package/dist/_contracts/workspace-resources.js +0 -39
- package/dist/archive-limits.d.ts +0 -1
- package/dist/archive-limits.js +0 -2
- package/dist/archive-limits.js.map +0 -1
- package/dist/asset-upload.d.ts +0 -47
- package/dist/asset-upload.js +0 -269
- package/dist/asset-upload.js.map +0 -1
- package/dist/bundle.d.ts +0 -9
- package/dist/bundle.js +0 -20
- package/dist/bundle.js.map +0 -1
- package/dist/canonical-zip.d.ts +0 -68
- package/dist/canonical-zip.js +0 -355
- package/dist/canonical-zip.js.map +0 -1
- package/dist/cli.mjs +0 -12048
- package/dist/cli.mjs.sha256 +0 -1
- package/dist/client-types.d.ts +0 -192
- package/dist/client-types.js +0 -2
- package/dist/client-types.js.map +0 -1
- package/dist/client.d.ts +0 -464
- package/dist/client.js +0 -1207
- package/dist/client.js.map +0 -1
- package/dist/event-projection.d.ts +0 -22
- package/dist/event-projection.js +0 -380
- package/dist/event-projection.js.map +0 -1
- package/dist/fetch-archive.d.ts +0 -16
- package/dist/fetch-archive.js +0 -252
- package/dist/fetch-archive.js.map +0 -1
- package/dist/file.d.ts +0 -96
- package/dist/file.js +0 -272
- package/dist/file.js.map +0 -1
- package/dist/instructions.d.ts +0 -20
- package/dist/instructions.js +0 -40
- package/dist/instructions.js.map +0 -1
- package/dist/legacy-session-provider-fault.d.ts +0 -7
- package/dist/legacy-session-provider-fault.js +0 -38
- package/dist/legacy-session-provider-fault.js.map +0 -1
- package/dist/mcp-server.d.ts +0 -84
- package/dist/mcp-server.js +0 -117
- package/dist/mcp-server.js.map +0 -1
- package/dist/node-fs.d.ts +0 -29
- package/dist/node-fs.js +0 -19
- package/dist/node-fs.js.map +0 -1
- package/dist/node-walk.d.ts +0 -69
- package/dist/node-walk.js +0 -151
- package/dist/node-walk.js.map +0 -1
- package/dist/path-basename.d.ts +0 -5
- package/dist/path-basename.js +0 -9
- package/dist/path-basename.js.map +0 -1
- package/dist/retry.d.ts +0 -70
- package/dist/retry.js +0 -155
- package/dist/retry.js.map +0 -1
- package/dist/secret.d.ts +0 -65
- package/dist/secret.js +0 -110
- package/dist/secret.js.map +0 -1
- package/dist/session-validate.d.ts +0 -100
- package/dist/session-validate.js +0 -303
- package/dist/session-validate.js.map +0 -1
- package/dist/skill.d.ts +0 -99
- package/dist/skill.js +0 -169
- package/dist/skill.js.map +0 -1
- package/dist/submission-wire.d.ts +0 -13
- package/dist/submission-wire.js +0 -69
- package/dist/submission-wire.js.map +0 -1
- package/dist/tool.d.ts +0 -41
- package/dist/tool.js +0 -76
- package/dist/tool.js.map +0 -1
- package/dist/version.d.ts +0 -9
- package/dist/version.js +0 -10
- package/dist/version.js.map +0 -1
- package/docs/authentication.md +0 -125
- package/docs/billing.md +0 -164
- package/docs/cleanup.md +0 -27
- package/docs/concepts/agent-tools.md +0 -47
- package/docs/concepts/composition.md +0 -60
- package/docs/concepts/providers-and-runtimes.md +0 -121
- package/docs/concepts/sessions.md +0 -51
- package/docs/concepts/subagents.md +0 -35
- package/docs/credentials.md +0 -116
- package/docs/defaults.md +0 -51
- package/docs/errors.md +0 -258
- package/docs/events.md +0 -143
- package/docs/files.md +0 -130
- package/docs/limits-and-quotas.md +0 -114
- package/docs/limits.md +0 -51
- package/docs/mcp.md +0 -47
- package/docs/networking.md +0 -114
- package/docs/provider-runtime-capabilities.md +0 -32
- package/docs/public-surface.json +0 -73
- package/docs/quickstart.md +0 -135
- package/docs/release.md +0 -44
- package/docs/retries.md +0 -108
- package/docs/secrets.md +0 -141
- package/docs/session-config.md +0 -51
- package/docs/session-record.md +0 -58
- package/docs/skills.md +0 -65
- package/docs/telemetry.md +0 -66
- package/docs/testing.md +0 -35
- package/docs/vision-skills.md +0 -94
- package/docs/webhooks.md +0 -143
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schemas for persisted workspace resource references.
|
|
3
|
-
*
|
|
4
|
-
* Two independent gates live here:
|
|
5
|
-
*
|
|
6
|
-
* - {@link workspaceResourceNameSchema} — the directly-supplied resource *name*
|
|
7
|
-
* grammar. Validation only: an accepted name is stored verbatim, so there is
|
|
8
|
-
* deliberately no normaliser to pair with it (no trim, no case folding).
|
|
9
|
-
* - {@link pinnedWorkspaceResourceSchema} — the immutable identity quartet every
|
|
10
|
-
* submitted resource carries, plus the `assetId`/`contentHash` agreement.
|
|
11
|
-
*
|
|
12
|
-
* **Both are factories over the wire grammars rather than owners of them.** The
|
|
13
|
-
* name patterns are supplied because there are two of them with deliberately
|
|
14
|
-
* separate identities (`workspace-resources.ts`), and the digest pattern is
|
|
15
|
-
* supplied because `canonical-sha256.ts` is the single declaring site for that
|
|
16
|
-
* grammar and `workspace-resources.ts` is its declared consumer — an invariant
|
|
17
|
-
* `canonical-sha256-ownership.test.ts` enforces. Threading them in keeps this
|
|
18
|
-
* module about *shape* and leaves grammar ownership where it already is.
|
|
19
|
-
*
|
|
20
|
-
* Neither schema is strict. `assertPinnedWorkspaceResource` is handed a fully
|
|
21
|
-
* projected `WorkspaceResourceRef` — `kind`, `name`, `mountPath`, and friends
|
|
22
|
-
* ride along — and rejecting those would break every caller. Unknown-key
|
|
23
|
-
* rejection for the resource objects themselves is the submission parser's job,
|
|
24
|
-
* one level up, where the per-kind key list actually exists.
|
|
25
|
-
*/
|
|
26
|
-
import * as z from "zod/mini";
|
|
27
|
-
/**
|
|
28
|
-
* A directly supplied resource name: matches `pattern`, and never contains the
|
|
29
|
-
* reserved `__` separator.
|
|
30
|
-
*
|
|
31
|
-
* The envelope failure and the type failure share one message because the
|
|
32
|
-
* ladder this replaces collapsed them (`typeof value !== "string" || !pattern.test(value)`),
|
|
33
|
-
* and `abort` keeps the separator complaint from firing on a name that never
|
|
34
|
-
* cleared the envelope.
|
|
35
|
-
*/
|
|
36
|
-
export declare function workspaceResourceNameSchema(path: string, pattern: RegExp): z.ZodMiniString<string>;
|
|
37
|
-
/**
|
|
38
|
-
* The immutable identity fields common to every submitted workspace resource.
|
|
39
|
-
*
|
|
40
|
-
* Field order is the order the sequential assertions this replaces ran in, and
|
|
41
|
-
* `errorFromZod` reports the shallowest issue, so a field complaint still wins
|
|
42
|
-
* over the `assetId`/`contentHash` agreement — which Zod only evaluates once
|
|
43
|
-
* every field has parsed (measured), exactly as the original ladder did.
|
|
44
|
-
*/
|
|
45
|
-
export declare function pinnedWorkspaceResourceSchema(path: string, digestPattern: RegExp): z.ZodMiniObject<{
|
|
46
|
-
resourceId: z.ZodMiniString<string>;
|
|
47
|
-
version: z.ZodMiniNumber<number>;
|
|
48
|
-
assetId: z.ZodMiniString<string>;
|
|
49
|
-
contentHash: z.ZodMiniString<string>;
|
|
50
|
-
}, z.core.$strip>;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schemas for persisted workspace resource references.
|
|
3
|
-
*
|
|
4
|
-
* Two independent gates live here:
|
|
5
|
-
*
|
|
6
|
-
* - {@link workspaceResourceNameSchema} — the directly-supplied resource *name*
|
|
7
|
-
* grammar. Validation only: an accepted name is stored verbatim, so there is
|
|
8
|
-
* deliberately no normaliser to pair with it (no trim, no case folding).
|
|
9
|
-
* - {@link pinnedWorkspaceResourceSchema} — the immutable identity quartet every
|
|
10
|
-
* submitted resource carries, plus the `assetId`/`contentHash` agreement.
|
|
11
|
-
*
|
|
12
|
-
* **Both are factories over the wire grammars rather than owners of them.** The
|
|
13
|
-
* name patterns are supplied because there are two of them with deliberately
|
|
14
|
-
* separate identities (`workspace-resources.ts`), and the digest pattern is
|
|
15
|
-
* supplied because `canonical-sha256.ts` is the single declaring site for that
|
|
16
|
-
* grammar and `workspace-resources.ts` is its declared consumer — an invariant
|
|
17
|
-
* `canonical-sha256-ownership.test.ts` enforces. Threading them in keeps this
|
|
18
|
-
* module about *shape* and leaves grammar ownership where it already is.
|
|
19
|
-
*
|
|
20
|
-
* Neither schema is strict. `assertPinnedWorkspaceResource` is handed a fully
|
|
21
|
-
* projected `WorkspaceResourceRef` — `kind`, `name`, `mountPath`, and friends
|
|
22
|
-
* ride along — and rejecting those would break every caller. Unknown-key
|
|
23
|
-
* rejection for the resource objects themselves is the submission parser's job,
|
|
24
|
-
* one level up, where the per-kind key list actually exists.
|
|
25
|
-
*/
|
|
26
|
-
import * as z from "zod/mini";
|
|
27
|
-
import { idPattern } from "../ids.js";
|
|
28
|
-
/**
|
|
29
|
-
* Opaque logical resource id minted by the platform.
|
|
30
|
-
*
|
|
31
|
-
* Sourced from the id owner rather than re-declared: `scripts/validate/id-format-parity.test.ts`
|
|
32
|
-
* fails on any `^<prefix>_` literal outside `ids.ts`, because eight hand-copies of the
|
|
33
|
-
* workspace-id pattern had already drifted (one lacked the `/i` flag the others carried,
|
|
34
|
-
* so the same id passed everywhere and threw at the telemetry boundary).
|
|
35
|
-
*/
|
|
36
|
-
const WORKSPACE_RESOURCE_ID_PATTERN = idPattern("resource");
|
|
37
|
-
/** Bytes prefix stripped from a canonical digest to derive the asset id. */
|
|
38
|
-
const DIGEST_PREFIX = "sha256:";
|
|
39
|
-
/**
|
|
40
|
-
* A directly supplied resource name: matches `pattern`, and never contains the
|
|
41
|
-
* reserved `__` separator.
|
|
42
|
-
*
|
|
43
|
-
* The envelope failure and the type failure share one message because the
|
|
44
|
-
* ladder this replaces collapsed them (`typeof value !== "string" || !pattern.test(value)`),
|
|
45
|
-
* and `abort` keeps the separator complaint from firing on a name that never
|
|
46
|
-
* cleared the envelope.
|
|
47
|
-
*/
|
|
48
|
-
export function workspaceResourceNameSchema(path, pattern) {
|
|
49
|
-
const envelope = `${path} must match ${pattern.source}`;
|
|
50
|
-
return z.string({ error: envelope }).check(z.refine((value) => pattern.test(value), { error: envelope, abort: true }), z.refine((value) => !value.includes("__"), {
|
|
51
|
-
error: `${path} must not contain "__"`,
|
|
52
|
-
abort: true
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* The immutable identity fields common to every submitted workspace resource.
|
|
57
|
-
*
|
|
58
|
-
* Field order is the order the sequential assertions this replaces ran in, and
|
|
59
|
-
* `errorFromZod` reports the shallowest issue, so a field complaint still wins
|
|
60
|
-
* over the `assetId`/`contentHash` agreement — which Zod only evaluates once
|
|
61
|
-
* every field has parsed (measured), exactly as the original ladder did.
|
|
62
|
-
*/
|
|
63
|
-
export function pinnedWorkspaceResourceSchema(path, digestPattern) {
|
|
64
|
-
const resourceId = `${path}.resourceId must match wres_<32 lowercase hex>`;
|
|
65
|
-
const version = `${path}.version must be a positive integer`;
|
|
66
|
-
const assetId = `${path}.assetId must be a non-empty string`;
|
|
67
|
-
const contentHash = `${path}.contentHash must be a sha256 digest`;
|
|
68
|
-
return z
|
|
69
|
-
.object({
|
|
70
|
-
resourceId: z.string({ error: resourceId }).check(z.refine((value) => WORKSPACE_RESOURCE_ID_PATTERN.test(value), {
|
|
71
|
-
error: resourceId,
|
|
72
|
-
abort: true
|
|
73
|
-
})),
|
|
74
|
-
version: z.number({ error: version }).check(z.refine((value) => Number.isSafeInteger(value) && value >= 1, {
|
|
75
|
-
error: version,
|
|
76
|
-
abort: true
|
|
77
|
-
})),
|
|
78
|
-
assetId: z
|
|
79
|
-
.string({ error: assetId })
|
|
80
|
-
.check(z.minLength(1, { error: assetId, abort: true })),
|
|
81
|
-
contentHash: z.string({ error: contentHash }).check(z.refine((value) => digestPattern.test(value), {
|
|
82
|
-
error: contentHash,
|
|
83
|
-
abort: true
|
|
84
|
-
}))
|
|
85
|
-
})
|
|
86
|
-
.check(z.refine((value) => value.assetId === `asset_${value.contentHash.slice(DIGEST_PREFIX.length)}`, { error: `${path}.assetId must identify the same bytes as contentHash` }));
|
|
87
|
-
}
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { type AexApiErrorCode } from "./error-codes.js";
|
|
2
|
-
import type { ProviderFault } from "./provider-fault.js";
|
|
3
|
-
export type AexErrorCode = "SESSION_CONFIG_INVALID" | "CREDENTIAL_INVALID" | "PROVIDER_ERROR" | "SESSION_STATE_ERROR" | "CLEANUP_ERROR" | "RUNTIME_UNSUPPORTED" | "API_ERROR" | "NETWORK_ERROR";
|
|
4
|
-
export declare class AexError extends Error {
|
|
5
|
-
readonly code: AexErrorCode;
|
|
6
|
-
readonly details?: unknown;
|
|
7
|
-
constructor(code: AexErrorCode, message: string, details?: unknown, options?: {
|
|
8
|
-
readonly cause?: unknown;
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
export interface SessionConfigValidationDetails {
|
|
12
|
-
/** Stable public field path; human error prose is not a branching contract. */
|
|
13
|
-
readonly field: string;
|
|
14
|
-
}
|
|
15
|
-
export declare class SessionConfigValidationError extends AexError {
|
|
16
|
-
readonly details: SessionConfigValidationDetails;
|
|
17
|
-
/**
|
|
18
|
-
* `code` and `details.field` are the stable machine contract. An optional
|
|
19
|
-
* cause is best-effort diagnostic context and must not be used for branching.
|
|
20
|
-
*/
|
|
21
|
-
constructor(message: string, details: SessionConfigValidationDetails, options?: {
|
|
22
|
-
readonly cause?: unknown;
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
export declare class CredentialValidationError extends AexError {
|
|
26
|
-
constructor(message: string, details?: unknown);
|
|
27
|
-
}
|
|
28
|
-
export declare class ProviderError extends AexError {
|
|
29
|
-
readonly status: number | undefined;
|
|
30
|
-
constructor(message: string, options?: {
|
|
31
|
-
status?: number;
|
|
32
|
-
details?: unknown;
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
export declare class SessionStateError extends AexError {
|
|
36
|
-
/**
|
|
37
|
-
* HTTP status from a wrapped API rejection, when this state error is a
|
|
38
|
-
* bounded client-side interpretation of that rejection.
|
|
39
|
-
*/
|
|
40
|
-
readonly status: number | undefined;
|
|
41
|
-
/** Stable API code from a wrapped API rejection, when available. */
|
|
42
|
-
readonly apiCode: AexApiErrorCode | undefined;
|
|
43
|
-
/** Request id from a wrapped API rejection, when available. */
|
|
44
|
-
readonly requestId: string | undefined;
|
|
45
|
-
constructor(message: string, details?: unknown, options?: {
|
|
46
|
-
readonly cause?: unknown;
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
export declare class CleanupError extends AexError {
|
|
50
|
-
constructor(message: string, details?: unknown);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Thrown by SDK and CLI operations when the hosted aex API returns a non-2xx
|
|
54
|
-
* response. Carries the HTTP status, the redacted parsed body, the server's
|
|
55
|
-
* STABLE {@link AexApiErrorCode} (when present), and a `requestId` for support.
|
|
56
|
-
* Construct via {@link import("./error-factory.js").apiErrorFromResponse} — the
|
|
57
|
-
* single wire→exception mapping — which dispatches to a typed subclass
|
|
58
|
-
* ({@link AexAuthError} / {@link AexIdempotencyConflictError} /
|
|
59
|
-
* {@link AexNotFoundError} / {@link AexRateLimitError}).
|
|
60
|
-
*/
|
|
61
|
-
export declare class AexApiError extends AexError {
|
|
62
|
-
readonly status: number;
|
|
63
|
-
readonly body: unknown;
|
|
64
|
-
/** The server's stable error code, when the body carried a known one. */
|
|
65
|
-
readonly apiCode: AexApiErrorCode | undefined;
|
|
66
|
-
/** Request id (body `requestId` or a response header) for support correlation. */
|
|
67
|
-
readonly requestId: string | undefined;
|
|
68
|
-
constructor(status: number, message: string, body: unknown, options?: {
|
|
69
|
-
readonly apiCode?: AexApiErrorCode | undefined;
|
|
70
|
-
readonly requestId?: string | undefined;
|
|
71
|
-
readonly cause?: unknown;
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
/** Shared construction shape for the typed {@link AexApiError} subclasses. */
|
|
75
|
-
export interface AexApiErrorInit {
|
|
76
|
-
readonly status: number;
|
|
77
|
-
readonly message: string;
|
|
78
|
-
readonly body: unknown;
|
|
79
|
-
readonly apiCode?: AexApiErrorCode | undefined;
|
|
80
|
-
readonly requestId?: string | undefined;
|
|
81
|
-
readonly cause?: unknown;
|
|
82
|
-
}
|
|
83
|
-
/** 401/403 auth failure (token invalid/revoked/expired, forbidden, insufficient scope). */
|
|
84
|
-
export declare class AexAuthError extends AexApiError {
|
|
85
|
-
/** The scope the endpoint required, when the server named it (insufficient_scope). */
|
|
86
|
-
readonly requiredScope: string | undefined;
|
|
87
|
-
constructor(init: AexApiErrorInit & {
|
|
88
|
-
readonly requiredScope?: string | undefined;
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
/** 409 — the idempotency key was reused with a different request body. */
|
|
92
|
-
export declare class AexIdempotencyConflictError extends AexApiError {
|
|
93
|
-
constructor(init: AexApiErrorInit);
|
|
94
|
-
}
|
|
95
|
-
/** 404 — the requested resource was not found. */
|
|
96
|
-
export declare class AexNotFoundError extends AexApiError {
|
|
97
|
-
constructor(init: AexApiErrorInit);
|
|
98
|
-
}
|
|
99
|
-
/** Construction shape for {@link AexRateLimitError}. */
|
|
100
|
-
export type AexRateLimitErrorInit = Omit<AexApiErrorInit, "message" | "body"> & {
|
|
101
|
-
/** Omitted when the retry policy builds the error: a fixed, non-leaky summary is generated. */
|
|
102
|
-
readonly message?: string;
|
|
103
|
-
readonly body?: unknown;
|
|
104
|
-
/** Suggested backoff (ms), when the server advertised one (Retry-After). */
|
|
105
|
-
readonly retryAfterMs?: number | undefined;
|
|
106
|
-
/** How many transport attempts were made before giving up. Defaults to `1`. */
|
|
107
|
-
readonly attempts?: number;
|
|
108
|
-
/** Whether the throttle came from the aex API plane or the upstream provider. */
|
|
109
|
-
readonly source?: "api" | "provider";
|
|
110
|
-
/** The upstream provider fault, when the throttle originated there. */
|
|
111
|
-
readonly providerFault?: ProviderFault;
|
|
112
|
-
};
|
|
113
|
-
/**
|
|
114
|
-
* 429 / 503 / 529 — the workspace hit a rate/concurrency limit, or an upstream
|
|
115
|
-
* provider said "slow down"; retry after a backoff.
|
|
116
|
-
*
|
|
117
|
-
* ONE class for both producers: the wire→exception factory
|
|
118
|
-
* (`apiErrorFromResponse`) and the shared HTTP retry policy, so `isRateLimited`
|
|
119
|
-
* recognises both with no split-brain. When the retry policy raises it, `message`
|
|
120
|
-
* is a fixed non-leaky summary (never an echo of the raw body, which is still
|
|
121
|
-
* available redacted on `.body`) and `attempts` / `source` / `providerFault`
|
|
122
|
-
* carry the retry-layer detail.
|
|
123
|
-
*/
|
|
124
|
-
export declare class AexRateLimitError extends AexApiError {
|
|
125
|
-
/** Suggested backoff (ms), when the server advertised one (Retry-After). */
|
|
126
|
-
readonly retryAfterMs: number | undefined;
|
|
127
|
-
/** How many attempts were made before giving up; `1` for a single-shot rejection. */
|
|
128
|
-
readonly attempts: number;
|
|
129
|
-
/** Whether the throttle came from the aex API plane or the upstream provider. */
|
|
130
|
-
readonly source: "api" | "provider";
|
|
131
|
-
/** The upstream provider fault, when the throttle originated there. */
|
|
132
|
-
readonly providerFault?: ProviderFault;
|
|
133
|
-
constructor(init: AexRateLimitErrorInit);
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* 410 (WS4) — the session's CONTENT (events, messages, files, manifest,
|
|
137
|
-
* archive, event stream) was deleted after its retention window; only the
|
|
138
|
-
* session RECORD (metadata) remains. Carries the `sessionId`, when the content
|
|
139
|
-
* was `purgedAt`, and what triggered it (`deletedBy`). Every content read AND
|
|
140
|
-
* `session…stream()` surface it via the one wire→exception factory. Narrow with
|
|
141
|
-
* {@link isContentDeleted}; check `session.dataState === "metadata_only"` first
|
|
142
|
-
* to avoid the round-trip.
|
|
143
|
-
*/
|
|
144
|
-
export declare class ContentDeletedError extends AexApiError {
|
|
145
|
-
/** The session whose content was deleted. */
|
|
146
|
-
readonly sessionId: string | undefined;
|
|
147
|
-
/** When the content was purged (ISO 8601), when the server reported it. */
|
|
148
|
-
readonly purgedAt: string | undefined;
|
|
149
|
-
/** What triggered the purge: retention-window elapse or an explicit user delete. */
|
|
150
|
-
readonly deletedBy: "retention" | "user" | undefined;
|
|
151
|
-
constructor(init: AexApiErrorInit & {
|
|
152
|
-
readonly sessionId?: string | undefined;
|
|
153
|
-
readonly purgedAt?: string | undefined;
|
|
154
|
-
readonly deletedBy?: "retention" | "user" | undefined;
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
/** True for a 401/403 authentication/authorization failure. */
|
|
158
|
-
export declare function isAuthError(err: unknown): err is AexAuthError;
|
|
159
|
-
/** True for a 403 whose cause is a missing scope (`insufficient_scope`). */
|
|
160
|
-
export declare function isInsufficientScope(err: unknown): boolean;
|
|
161
|
-
/** True for a 409 idempotency-key reuse conflict. */
|
|
162
|
-
export declare function isIdempotencyConflict(err: unknown): err is AexIdempotencyConflictError;
|
|
163
|
-
/** True for a 404 not-found error. */
|
|
164
|
-
export declare function isNotFound(err: unknown): err is AexNotFoundError;
|
|
165
|
-
/** True for a 429 rate/concurrency-limit error. */
|
|
166
|
-
export declare function isRateLimited(err: unknown): err is AexRateLimitError;
|
|
167
|
-
/** True for a 410 whose session content was deleted after its retention window. */
|
|
168
|
-
export declare function isContentDeleted(err: unknown): err is ContentDeletedError;
|
|
169
|
-
/**
|
|
170
|
-
* Thrown when a BFF-bound request fails BEFORE any HTTP response exists — DNS
|
|
171
|
-
* failure, connection refused, TLS error, socket reset. Wraps the raw fetch
|
|
172
|
-
* rejection (whose undici form is a bare `TypeError: fetch failed` with the
|
|
173
|
-
* useful code hidden on `cause.code`) into a message that names the request
|
|
174
|
-
* and the transport failure, e.g.
|
|
175
|
-
* `POST api.aex.dev/api/assets/presign failed: ECONNREFUSED (connect ECONNREFUSED 127.0.0.1:443)`.
|
|
176
|
-
* The original rejection is preserved on `cause`.
|
|
177
|
-
*/
|
|
178
|
-
export declare class AexNetworkError extends AexError {
|
|
179
|
-
readonly method: string;
|
|
180
|
-
/** Request host — never carries credentials or the query string. */
|
|
181
|
-
readonly host: string;
|
|
182
|
-
readonly path: string;
|
|
183
|
-
/** Transport failure code (e.g. `ECONNREFUSED`), when detectable. */
|
|
184
|
-
readonly causeCode: string | undefined;
|
|
185
|
-
/** Attempts made when a retry layer exhausted its budget; `1` otherwise. */
|
|
186
|
-
readonly attempts: number;
|
|
187
|
-
/** Total elapsed time (ms) across all attempts, when the retry layer set it. */
|
|
188
|
-
readonly elapsedMs: number | undefined;
|
|
189
|
-
constructor(args: {
|
|
190
|
-
readonly method: string;
|
|
191
|
-
readonly host: string;
|
|
192
|
-
readonly path: string;
|
|
193
|
-
readonly cause: unknown;
|
|
194
|
-
/** Set by the retry layer when it gave up: appended to the message. */
|
|
195
|
-
readonly attempts?: number;
|
|
196
|
-
readonly elapsedMs?: number;
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Best-effort transport error code (`ECONNREFUSED`, `ENOTFOUND`, …): checks
|
|
201
|
-
* `err.code`, then a bounded native `cause` chain (where undici and database
|
|
202
|
-
* drivers hide it), then falls back to an `E…`-shaped token in the outer
|
|
203
|
-
* message. Five inspected values matches the platform diagnostic boundary and
|
|
204
|
-
* prevents malformed/cyclic cause graphs from becoming unbounded work.
|
|
205
|
-
*/
|
|
206
|
-
export declare function extractErrorCode(err: unknown): string | undefined;
|
|
207
|
-
/**
|
|
208
|
-
* Redact a URL down to protocol + host + path: credentials become
|
|
209
|
-
* `[redacted]@` and any query string becomes `?[redacted]` (presigned URLs
|
|
210
|
-
* carry signatures there). Tolerates unparseable input.
|
|
211
|
-
*/
|
|
212
|
-
export declare function redactUrl(url: string): string;
|
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
import { redactSecrets } from "./sdk-secrets.js";
|
|
2
|
-
import { isAexApiErrorCode } from "./error-codes.js";
|
|
3
|
-
export class AexError extends Error {
|
|
4
|
-
code;
|
|
5
|
-
details;
|
|
6
|
-
constructor(code, message, details, options) {
|
|
7
|
-
super(redactSecrets(message), options?.cause === undefined ? undefined : { cause: options.cause });
|
|
8
|
-
this.name = this.constructor.name;
|
|
9
|
-
this.code = code;
|
|
10
|
-
this.details = details === undefined ? undefined : redactSecrets(details);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export class SessionConfigValidationError extends AexError {
|
|
14
|
-
/**
|
|
15
|
-
* `code` and `details.field` are the stable machine contract. An optional
|
|
16
|
-
* cause is best-effort diagnostic context and must not be used for branching.
|
|
17
|
-
*/
|
|
18
|
-
constructor(message, details, options) {
|
|
19
|
-
super("SESSION_CONFIG_INVALID", message, Object.freeze({ field: details.field }), options?.cause === undefined ? undefined : { cause: options.cause });
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export class CredentialValidationError extends AexError {
|
|
23
|
-
constructor(message, details) {
|
|
24
|
-
super("CREDENTIAL_INVALID", message, details);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export class ProviderError extends AexError {
|
|
28
|
-
status;
|
|
29
|
-
constructor(message, options = {}) {
|
|
30
|
-
super("PROVIDER_ERROR", message, options.details);
|
|
31
|
-
this.status = options.status;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
export class SessionStateError extends AexError {
|
|
35
|
-
/**
|
|
36
|
-
* HTTP status from a wrapped API rejection, when this state error is a
|
|
37
|
-
* bounded client-side interpretation of that rejection.
|
|
38
|
-
*/
|
|
39
|
-
status;
|
|
40
|
-
/** Stable API code from a wrapped API rejection, when available. */
|
|
41
|
-
apiCode;
|
|
42
|
-
/** Request id from a wrapped API rejection, when available. */
|
|
43
|
-
requestId;
|
|
44
|
-
constructor(message, details, options) {
|
|
45
|
-
const detailRecord = details && typeof details === "object" && !Array.isArray(details)
|
|
46
|
-
? details
|
|
47
|
-
: undefined;
|
|
48
|
-
const cause = options?.cause ?? detailRecord?.cause;
|
|
49
|
-
super("SESSION_STATE_ERROR", message, details, cause === undefined ? undefined : { cause });
|
|
50
|
-
const status = detailRecord?.httpStatus ?? detailRecord?.status;
|
|
51
|
-
const apiCode = detailRecord?.apiCode;
|
|
52
|
-
this.status = typeof status === "number" ? status : undefined;
|
|
53
|
-
this.apiCode = isAexApiErrorCode(apiCode) ? apiCode : undefined;
|
|
54
|
-
this.requestId = typeof detailRecord?.requestId === "string" ? detailRecord.requestId : undefined;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export class CleanupError extends AexError {
|
|
58
|
-
constructor(message, details) {
|
|
59
|
-
super("CLEANUP_ERROR", message, details);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Thrown by SDK and CLI operations when the hosted aex API returns a non-2xx
|
|
64
|
-
* response. Carries the HTTP status, the redacted parsed body, the server's
|
|
65
|
-
* STABLE {@link AexApiErrorCode} (when present), and a `requestId` for support.
|
|
66
|
-
* Construct via {@link import("./error-factory.js").apiErrorFromResponse} — the
|
|
67
|
-
* single wire→exception mapping — which dispatches to a typed subclass
|
|
68
|
-
* ({@link AexAuthError} / {@link AexIdempotencyConflictError} /
|
|
69
|
-
* {@link AexNotFoundError} / {@link AexRateLimitError}).
|
|
70
|
-
*/
|
|
71
|
-
export class AexApiError extends AexError {
|
|
72
|
-
status;
|
|
73
|
-
body;
|
|
74
|
-
/** The server's stable error code, when the body carried a known one. */
|
|
75
|
-
apiCode;
|
|
76
|
-
/** Request id (body `requestId` or a response header) for support correlation. */
|
|
77
|
-
requestId;
|
|
78
|
-
constructor(status, message, body, options) {
|
|
79
|
-
super("API_ERROR", message, body, options?.cause === undefined ? undefined : { cause: options.cause });
|
|
80
|
-
this.status = status;
|
|
81
|
-
this.body = redactSecrets(body);
|
|
82
|
-
this.apiCode = options?.apiCode;
|
|
83
|
-
this.requestId = options?.requestId;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/** 401/403 auth failure (token invalid/revoked/expired, forbidden, insufficient scope). */
|
|
87
|
-
export class AexAuthError extends AexApiError {
|
|
88
|
-
/** The scope the endpoint required, when the server named it (insufficient_scope). */
|
|
89
|
-
requiredScope;
|
|
90
|
-
constructor(init) {
|
|
91
|
-
super(init.status, init.message, init.body, {
|
|
92
|
-
apiCode: init.apiCode,
|
|
93
|
-
requestId: init.requestId,
|
|
94
|
-
cause: init.cause
|
|
95
|
-
});
|
|
96
|
-
this.requiredScope = init.requiredScope;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/** 409 — the idempotency key was reused with a different request body. */
|
|
100
|
-
export class AexIdempotencyConflictError extends AexApiError {
|
|
101
|
-
constructor(init) {
|
|
102
|
-
super(init.status, init.message, init.body, {
|
|
103
|
-
apiCode: init.apiCode,
|
|
104
|
-
requestId: init.requestId,
|
|
105
|
-
cause: init.cause
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/** 404 — the requested resource was not found. */
|
|
110
|
-
export class AexNotFoundError extends AexApiError {
|
|
111
|
-
constructor(init) {
|
|
112
|
-
super(init.status, init.message, init.body, {
|
|
113
|
-
apiCode: init.apiCode,
|
|
114
|
-
requestId: init.requestId,
|
|
115
|
-
cause: init.cause
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* 429 / 503 / 529 — the workspace hit a rate/concurrency limit, or an upstream
|
|
121
|
-
* provider said "slow down"; retry after a backoff.
|
|
122
|
-
*
|
|
123
|
-
* ONE class for both producers: the wire→exception factory
|
|
124
|
-
* (`apiErrorFromResponse`) and the shared HTTP retry policy, so `isRateLimited`
|
|
125
|
-
* recognises both with no split-brain. When the retry policy raises it, `message`
|
|
126
|
-
* is a fixed non-leaky summary (never an echo of the raw body, which is still
|
|
127
|
-
* available redacted on `.body`) and `attempts` / `source` / `providerFault`
|
|
128
|
-
* carry the retry-layer detail.
|
|
129
|
-
*/
|
|
130
|
-
export class AexRateLimitError extends AexApiError {
|
|
131
|
-
/** Suggested backoff (ms), when the server advertised one (Retry-After). */
|
|
132
|
-
retryAfterMs;
|
|
133
|
-
/** How many attempts were made before giving up; `1` for a single-shot rejection. */
|
|
134
|
-
attempts;
|
|
135
|
-
/** Whether the throttle came from the aex API plane or the upstream provider. */
|
|
136
|
-
source;
|
|
137
|
-
/** The upstream provider fault, when the throttle originated there. */
|
|
138
|
-
providerFault;
|
|
139
|
-
constructor(init) {
|
|
140
|
-
const attempts = init.attempts ?? 1;
|
|
141
|
-
const source = init.source ?? "api";
|
|
142
|
-
super(init.status, init.message ?? throttleSummary(init.status, attempts, source, init.retryAfterMs), init.body, {
|
|
143
|
-
apiCode: init.apiCode,
|
|
144
|
-
requestId: init.requestId,
|
|
145
|
-
cause: init.cause
|
|
146
|
-
});
|
|
147
|
-
this.retryAfterMs = init.retryAfterMs;
|
|
148
|
-
this.attempts = attempts;
|
|
149
|
-
this.source = source;
|
|
150
|
-
if (init.providerFault !== undefined)
|
|
151
|
-
this.providerFault = init.providerFault;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/** Fixed, non-leaky throttle summary — never echoes the server's error body. */
|
|
155
|
-
function throttleSummary(status, attempts, source, retryAfterMs) {
|
|
156
|
-
const who = source === "provider" ? "upstream provider" : "aex API";
|
|
157
|
-
const label = status === 529 ? "overloaded" : "rate limit reached";
|
|
158
|
-
const attemptsLabel = `${attempts} attempt${attempts === 1 ? "" : "s"}`;
|
|
159
|
-
const wait = retryAfterMs !== undefined ? `; retry after ~${Math.ceil(retryAfterMs / 1000)}s` : "";
|
|
160
|
-
return `${who} ${label} (HTTP ${status}) after ${attemptsLabel}${wait}`;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* 410 (WS4) — the session's CONTENT (events, messages, files, manifest,
|
|
164
|
-
* archive, event stream) was deleted after its retention window; only the
|
|
165
|
-
* session RECORD (metadata) remains. Carries the `sessionId`, when the content
|
|
166
|
-
* was `purgedAt`, and what triggered it (`deletedBy`). Every content read AND
|
|
167
|
-
* `session…stream()` surface it via the one wire→exception factory. Narrow with
|
|
168
|
-
* {@link isContentDeleted}; check `session.dataState === "metadata_only"` first
|
|
169
|
-
* to avoid the round-trip.
|
|
170
|
-
*/
|
|
171
|
-
export class ContentDeletedError extends AexApiError {
|
|
172
|
-
/** The session whose content was deleted. */
|
|
173
|
-
sessionId;
|
|
174
|
-
/** When the content was purged (ISO 8601), when the server reported it. */
|
|
175
|
-
purgedAt;
|
|
176
|
-
/** What triggered the purge: retention-window elapse or an explicit user delete. */
|
|
177
|
-
deletedBy;
|
|
178
|
-
constructor(init) {
|
|
179
|
-
super(init.status, init.message, init.body, {
|
|
180
|
-
apiCode: init.apiCode,
|
|
181
|
-
requestId: init.requestId,
|
|
182
|
-
cause: init.cause
|
|
183
|
-
});
|
|
184
|
-
this.sessionId = init.sessionId;
|
|
185
|
-
this.purgedAt = init.purgedAt;
|
|
186
|
-
this.deletedBy = init.deletedBy;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
/** True for a 401/403 authentication/authorization failure. */
|
|
190
|
-
export function isAuthError(err) {
|
|
191
|
-
return err instanceof AexAuthError;
|
|
192
|
-
}
|
|
193
|
-
/** True for a 403 whose cause is a missing scope (`insufficient_scope`). */
|
|
194
|
-
export function isInsufficientScope(err) {
|
|
195
|
-
return err instanceof AexAuthError && err.apiCode === "insufficient_scope";
|
|
196
|
-
}
|
|
197
|
-
/** True for a 409 idempotency-key reuse conflict. */
|
|
198
|
-
export function isIdempotencyConflict(err) {
|
|
199
|
-
return err instanceof AexIdempotencyConflictError;
|
|
200
|
-
}
|
|
201
|
-
/** True for a 404 not-found error. */
|
|
202
|
-
export function isNotFound(err) {
|
|
203
|
-
return err instanceof AexNotFoundError;
|
|
204
|
-
}
|
|
205
|
-
/** True for a 429 rate/concurrency-limit error. */
|
|
206
|
-
export function isRateLimited(err) {
|
|
207
|
-
return err instanceof AexRateLimitError;
|
|
208
|
-
}
|
|
209
|
-
/** True for a 410 whose session content was deleted after its retention window. */
|
|
210
|
-
export function isContentDeleted(err) {
|
|
211
|
-
return err instanceof ContentDeletedError;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Thrown when a BFF-bound request fails BEFORE any HTTP response exists — DNS
|
|
215
|
-
* failure, connection refused, TLS error, socket reset. Wraps the raw fetch
|
|
216
|
-
* rejection (whose undici form is a bare `TypeError: fetch failed` with the
|
|
217
|
-
* useful code hidden on `cause.code`) into a message that names the request
|
|
218
|
-
* and the transport failure, e.g.
|
|
219
|
-
* `POST api.aex.dev/api/assets/presign failed: ECONNREFUSED (connect ECONNREFUSED 127.0.0.1:443)`.
|
|
220
|
-
* The original rejection is preserved on `cause`.
|
|
221
|
-
*/
|
|
222
|
-
export class AexNetworkError extends AexError {
|
|
223
|
-
method;
|
|
224
|
-
/** Request host — never carries credentials or the query string. */
|
|
225
|
-
host;
|
|
226
|
-
path;
|
|
227
|
-
/** Transport failure code (e.g. `ECONNREFUSED`), when detectable. */
|
|
228
|
-
causeCode;
|
|
229
|
-
/** Attempts made when a retry layer exhausted its budget; `1` otherwise. */
|
|
230
|
-
attempts;
|
|
231
|
-
/** Total elapsed time (ms) across all attempts, when the retry layer set it. */
|
|
232
|
-
elapsedMs;
|
|
233
|
-
constructor(args) {
|
|
234
|
-
const causeCode = extractErrorCode(args.cause);
|
|
235
|
-
super("NETWORK_ERROR", networkErrorMessage(args, causeCode), { method: args.method, host: args.host, path: args.path, ...(causeCode ? { code: causeCode } : {}) }, { cause: args.cause });
|
|
236
|
-
this.method = args.method;
|
|
237
|
-
this.host = args.host;
|
|
238
|
-
this.path = args.path;
|
|
239
|
-
this.causeCode = causeCode;
|
|
240
|
-
this.attempts = args.attempts ?? 1;
|
|
241
|
-
this.elapsedMs = args.elapsedMs;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
function networkErrorMessage(args, causeCode) {
|
|
245
|
-
const target = args.host ? `${args.host}${args.path}` : "request";
|
|
246
|
-
const detail = shortCauseMessage(args.cause, causeCode);
|
|
247
|
-
const suffix = args.attempts === undefined
|
|
248
|
-
? ""
|
|
249
|
-
: ` after ${args.attempts} attempt${args.attempts === 1 ? "" : "s"} over ${args.elapsedMs ?? 0}ms`;
|
|
250
|
-
let message = `${args.method} ${target} failed`;
|
|
251
|
-
if (causeCode)
|
|
252
|
-
message += `: ${causeCode}`;
|
|
253
|
-
if (detail)
|
|
254
|
-
message += causeCode ? ` (${detail})` : `: ${detail}`;
|
|
255
|
-
return message + suffix;
|
|
256
|
-
}
|
|
257
|
-
/** The innermost useful message off the rejection, URL-redacted and bounded. */
|
|
258
|
-
function shortCauseMessage(cause, causeCode) {
|
|
259
|
-
const nested = cause instanceof Error && cause.cause instanceof Error ? cause.cause : cause;
|
|
260
|
-
const message = nested instanceof Error ? nested.message || nested.name : typeof nested === "string" ? nested : undefined;
|
|
261
|
-
if (!message || message === causeCode)
|
|
262
|
-
return undefined;
|
|
263
|
-
return message.replace(/https?:\/\/[^\s<>"'`]+/g, (raw) => redactUrl(raw)).slice(0, 200);
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Best-effort transport error code (`ECONNREFUSED`, `ENOTFOUND`, …): checks
|
|
267
|
-
* `err.code`, then a bounded native `cause` chain (where undici and database
|
|
268
|
-
* drivers hide it), then falls back to an `E…`-shaped token in the outer
|
|
269
|
-
* message. Five inspected values matches the platform diagnostic boundary and
|
|
270
|
-
* prevents malformed/cyclic cause graphs from becoming unbounded work.
|
|
271
|
-
*/
|
|
272
|
-
export function extractErrorCode(err) {
|
|
273
|
-
let current = err;
|
|
274
|
-
for (let depth = 0; depth < 5 && current && typeof current === "object"; depth += 1) {
|
|
275
|
-
const code = stringProperty(current, "code");
|
|
276
|
-
if (code)
|
|
277
|
-
return code;
|
|
278
|
-
current = current.cause;
|
|
279
|
-
}
|
|
280
|
-
const match = /\bE[A-Z0-9_]+\b/.exec(errorMessageOf(err));
|
|
281
|
-
return match?.[0];
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Redact a URL down to protocol + host + path: credentials become
|
|
285
|
-
* `[redacted]@` and any query string becomes `?[redacted]` (presigned URLs
|
|
286
|
-
* carry signatures there). Tolerates unparseable input.
|
|
287
|
-
*/
|
|
288
|
-
export function redactUrl(url) {
|
|
289
|
-
try {
|
|
290
|
-
const parsed = new URL(url);
|
|
291
|
-
const auth = parsed.username || parsed.password ? "[redacted]@" : "";
|
|
292
|
-
const query = parsed.search ? "?[redacted]" : "";
|
|
293
|
-
return `${parsed.protocol}//${auth}${parsed.host}${parsed.pathname}${query}`;
|
|
294
|
-
}
|
|
295
|
-
catch {
|
|
296
|
-
const withoutAuth = url.replace(/\/\/[^/?#\s]+@/, "//[redacted]@");
|
|
297
|
-
const queryStart = withoutAuth.indexOf("?");
|
|
298
|
-
return queryStart === -1 ? withoutAuth : `${withoutAuth.slice(0, queryStart)}?[redacted]`;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
function errorMessageOf(err) {
|
|
302
|
-
if (err instanceof Error)
|
|
303
|
-
return err.message || err.name;
|
|
304
|
-
if (typeof err === "string")
|
|
305
|
-
return err;
|
|
306
|
-
return String(err);
|
|
307
|
-
}
|
|
308
|
-
function stringProperty(value, key) {
|
|
309
|
-
if (!value || typeof value !== "object")
|
|
310
|
-
return undefined;
|
|
311
|
-
const prop = value[key];
|
|
312
|
-
return typeof prop === "string" && prop.length > 0 ? prop : undefined;
|
|
313
|
-
}
|