@aexhq/sdk 0.46.4-canary → 0.50.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 +23 -31
- package/dist/client/aex.d.ts +33 -0
- package/dist/client/aex.js +98 -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 +25 -0
- package/dist/downloads/download.js +53 -0
- package/dist/downloads/download.js.map +1 -0
- package/dist/generated/errors.d.ts +12 -0
- package/dist/generated/errors.js +81 -0
- package/dist/generated/errors.js.map +1 -0
- package/dist/generated/resources.d.ts +730 -0
- package/dist/generated/resources.js +606 -0
- package/dist/generated/resources.js.map +1 -0
- package/dist/generated/routes.d.ts +42 -0
- package/dist/generated/routes.js +2101 -0
- package/dist/generated/routes.js.map +1 -0
- package/dist/index.d.ts +20 -50
- package/dist/index.js +11 -62
- package/dist/index.js.map +1 -1
- 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 +28 -0
- package/dist/transport/transport.js.map +1 -0
- package/package.json +63 -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,276 +0,0 @@
|
|
|
1
|
-
import { ApiErrorEnvelopeSchema } from "../schemas/response-common.js";
|
|
2
|
-
import { observeWireResponses } from "../wire-observer.js";
|
|
3
|
-
/**
|
|
4
|
-
* Match a concrete path against a `{param}` pattern.
|
|
5
|
-
*
|
|
6
|
-
* Segment-wise rather than by regex so a placeholder cannot accidentally span a
|
|
7
|
-
* `/` and make two different routes look like one.
|
|
8
|
-
*/
|
|
9
|
-
export function pathMatches(pattern, actual) {
|
|
10
|
-
const patternSegments = pattern.split("/");
|
|
11
|
-
const actualSegments = actual.split("/");
|
|
12
|
-
if (patternSegments.length !== actualSegments.length) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
return patternSegments.every((segment, index) => (segment.startsWith("{") && segment.endsWith("}")) || segment === actualSegments[index]);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Reduce whatever the caller had to hand — a base URL, a URL with a path, a bare
|
|
19
|
-
* origin — to the origin `WireResponse` reports.
|
|
20
|
-
*
|
|
21
|
-
* Throws rather than falling back to "match everything": an unparseable
|
|
22
|
-
* `AEX_API_URL` that silently disabled the filter would reintroduce exactly the
|
|
23
|
-
* false violations the filter exists to prevent, and would do it quietly.
|
|
24
|
-
*/
|
|
25
|
-
export function wireOrigin(baseUrl) {
|
|
26
|
-
try {
|
|
27
|
-
return new URL(baseUrl).origin;
|
|
28
|
-
}
|
|
29
|
-
catch (cause) {
|
|
30
|
-
throw new Error(`wire conformance: could not read an origin from ${JSON.stringify(baseUrl)} — ` +
|
|
31
|
-
`expected an absolute URL like "https://api.aex.dev"`, { cause });
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function issuesOf(result) {
|
|
35
|
-
return (result.issues ?? []).map((issue) => {
|
|
36
|
-
const path = (issue.path ?? [])
|
|
37
|
-
.map((segment) => (typeof segment === "object" ? String(segment.key) : String(segment)))
|
|
38
|
-
.join(".");
|
|
39
|
-
return path ? `${path}: ${issue.message}` : issue.message;
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Which contract a status is judged against.
|
|
44
|
-
*
|
|
45
|
-
* The generated document is coarser than this — it declares `2XX` and a
|
|
46
|
-
* `default` that catches everything else — but judging a redirect against the
|
|
47
|
-
* error envelope would manufacture a violation out of an empty body, which is
|
|
48
|
-
* noise rather than a finding. A 3xx is recorded, named and not judged.
|
|
49
|
-
*
|
|
50
|
-
* In practice `fetch` follows redirects, so `HttpClient` sees the final
|
|
51
|
-
* response; this exists so that a caller who stops following them gets a
|
|
52
|
-
* comprehensible report rather than a wall of false failures.
|
|
53
|
-
*/
|
|
54
|
-
function contractFor(status) {
|
|
55
|
-
if (status < 300)
|
|
56
|
-
return "response";
|
|
57
|
-
if (status < 400)
|
|
58
|
-
return "redirect";
|
|
59
|
-
return "error-envelope";
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Start validating responses.
|
|
63
|
-
*
|
|
64
|
-
* Returns a handle carrying the report and a `stop()`. Validation is
|
|
65
|
-
* synchronous: a schema whose `~standard.validate` returns a promise is treated
|
|
66
|
-
* as unvalidatable and recorded as such rather than silently skipped, because
|
|
67
|
-
* `HttpClient` cannot await an observer without changing request timing.
|
|
68
|
-
*/
|
|
69
|
-
export function installWireConformance(bindings, options = {}) {
|
|
70
|
-
const originFilter = options.origin === undefined ? undefined : wireOrigin(options.origin);
|
|
71
|
-
const errorEnvelope = options.errorEnvelope === undefined ? ApiErrorEnvelopeSchema : options.errorEnvelope;
|
|
72
|
-
const validated = new Set();
|
|
73
|
-
const unschemad = new Set();
|
|
74
|
-
const errorsValidated = new Set();
|
|
75
|
-
const offPlane = new Set();
|
|
76
|
-
const violations = [];
|
|
77
|
-
let observed = 0;
|
|
78
|
-
/** Validate `body`, recording a violation on failure. Returns false if async. */
|
|
79
|
-
const check = (schema, kind, name, response) => {
|
|
80
|
-
const result = schema["~standard"].validate(response.body);
|
|
81
|
-
if (result instanceof Promise) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
if (result.issues) {
|
|
85
|
-
violations.push({
|
|
86
|
-
kind,
|
|
87
|
-
name,
|
|
88
|
-
method: response.method.toUpperCase(),
|
|
89
|
-
origin: response.origin,
|
|
90
|
-
path: response.path,
|
|
91
|
-
status: response.status,
|
|
92
|
-
issues: issuesOf(result),
|
|
93
|
-
body: response.body
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return true;
|
|
97
|
-
};
|
|
98
|
-
const stop = observeWireResponses((response) => {
|
|
99
|
-
observed += 1;
|
|
100
|
-
const method = response.method.toUpperCase();
|
|
101
|
-
if (originFilter !== undefined && response.origin !== originFilter) {
|
|
102
|
-
offPlane.add(`${response.origin} ${method} ${response.path}`);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
const contract = contractFor(response.status);
|
|
106
|
-
if (contract === "redirect") {
|
|
107
|
-
unschemad.add(`${method} ${response.path} -> ${response.status} (redirect — no declared body)`);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
if (contract === "error-envelope") {
|
|
111
|
-
// An error body is the SAME envelope whatever route produced it, so it is
|
|
112
|
-
// checked without needing a binding — which is the point: the routes with
|
|
113
|
-
// no 2xx schema still have their failures covered.
|
|
114
|
-
if (errorEnvelope === null) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
if (check(errorEnvelope, "error-envelope", `${method} ${response.path}`, response)) {
|
|
118
|
-
errorsValidated.add(`${method} ${response.path} -> ${response.status}`);
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
unschemad.add(`${method} ${response.path} -> ${response.status} (async schema — not validated)`);
|
|
122
|
-
}
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
const binding = bindings.find((candidate) => candidate.method === method && pathMatches(candidate.path, response.path));
|
|
126
|
-
if (!binding) {
|
|
127
|
-
unschemad.add(`${method} ${response.path}`);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (!check(binding.schema, "response", binding.name, response)) {
|
|
131
|
-
unschemad.add(`${binding.name} (async schema — not validated)`);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
validated.add(binding.name);
|
|
135
|
-
});
|
|
136
|
-
return {
|
|
137
|
-
stop,
|
|
138
|
-
report: () => ({
|
|
139
|
-
originFilter,
|
|
140
|
-
validated: [...validated].sort(),
|
|
141
|
-
unexercised: bindings
|
|
142
|
-
.map((binding) => binding.name)
|
|
143
|
-
.filter((name) => !validated.has(name))
|
|
144
|
-
.sort(),
|
|
145
|
-
unschemad: [...unschemad].sort(),
|
|
146
|
-
errorsValidated: [...errorsValidated].sort(),
|
|
147
|
-
offPlane: [...offPlane].sort(),
|
|
148
|
-
violations,
|
|
149
|
-
observed
|
|
150
|
-
})
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Fold reports from several processes into one.
|
|
155
|
-
*
|
|
156
|
-
* The suites that matter drive the SDK out of process — one bun child per
|
|
157
|
-
* scenario, one test process per file — so no single process sees the whole
|
|
158
|
-
* surface, and a per-process report would understate coverage by construction.
|
|
159
|
-
*
|
|
160
|
-
* `unexercised` is INTERSECTED, not concatenated: a name is unexercised overall
|
|
161
|
-
* only when every fragment failed to exercise it. Concatenating would report a
|
|
162
|
-
* route as unexercised because some other process did not happen to call it,
|
|
163
|
-
* which is the mirror image of the false-green this harness exists to prevent.
|
|
164
|
-
* That identity only holds when every fragment was produced from the same
|
|
165
|
-
* binding table; {@link installWireConformance} is the only producer.
|
|
166
|
-
*/
|
|
167
|
-
export function mergeWireConformanceReports(reports) {
|
|
168
|
-
const validated = new Set();
|
|
169
|
-
const unschemad = new Set();
|
|
170
|
-
const errorsValidated = new Set();
|
|
171
|
-
const offPlane = new Set();
|
|
172
|
-
const violations = [];
|
|
173
|
-
const originFilters = new Set();
|
|
174
|
-
let unexercised;
|
|
175
|
-
let observed = 0;
|
|
176
|
-
let anyUnfiltered = false;
|
|
177
|
-
for (const report of reports) {
|
|
178
|
-
observed += report.observed;
|
|
179
|
-
for (const name of report.validated)
|
|
180
|
-
validated.add(name);
|
|
181
|
-
for (const route of report.unschemad)
|
|
182
|
-
unschemad.add(route);
|
|
183
|
-
for (const route of report.errorsValidated)
|
|
184
|
-
errorsValidated.add(route);
|
|
185
|
-
for (const route of report.offPlane)
|
|
186
|
-
offPlane.add(route);
|
|
187
|
-
violations.push(...report.violations);
|
|
188
|
-
if (report.originFilter === undefined)
|
|
189
|
-
anyUnfiltered = true;
|
|
190
|
-
else
|
|
191
|
-
originFilters.add(report.originFilter);
|
|
192
|
-
unexercised =
|
|
193
|
-
unexercised === undefined
|
|
194
|
-
? new Set(report.unexercised)
|
|
195
|
-
: new Set(report.unexercised.filter((name) => unexercised.has(name)));
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
// One filter across every fragment is the only case that can be stated
|
|
199
|
-
// simply. A mixed run is reported as unfiltered so the formatter's warning
|
|
200
|
-
// fires rather than a filter being claimed that not every fragment applied.
|
|
201
|
-
originFilter: !anyUnfiltered && originFilters.size === 1 ? [...originFilters][0] : undefined,
|
|
202
|
-
validated: [...validated].sort(),
|
|
203
|
-
unexercised: [...(unexercised ?? new Set())].filter((name) => !validated.has(name)).sort(),
|
|
204
|
-
unschemad: [...unschemad].sort(),
|
|
205
|
-
errorsValidated: [...errorsValidated].sort(),
|
|
206
|
-
offPlane: [...offPlane].sort(),
|
|
207
|
-
violations,
|
|
208
|
-
observed
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
/** Render a body for a violation without letting one huge response bury the report. */
|
|
212
|
-
function renderBody(body, limit = 2000) {
|
|
213
|
-
let text;
|
|
214
|
-
try {
|
|
215
|
-
text = JSON.stringify(body) ?? String(body);
|
|
216
|
-
}
|
|
217
|
-
catch {
|
|
218
|
-
text = String(body);
|
|
219
|
-
}
|
|
220
|
-
return text.length > limit ? `${text.slice(0, limit)}… (${text.length} bytes total)` : text;
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Render the report for a suite's output.
|
|
224
|
-
*
|
|
225
|
-
* Always prints the unexercised and unschemad lists, including when there are no
|
|
226
|
-
* violations — a run that reports only "0 violations" invites the reader to
|
|
227
|
-
* conclude the surface is verified. A violation always prints the BODY that
|
|
228
|
-
* caused it as well as the schema's complaint, because triage needs both.
|
|
229
|
-
*/
|
|
230
|
-
export function formatWireConformanceReport(report) {
|
|
231
|
-
const lines = [
|
|
232
|
-
`wire conformance: ${report.observed} response(s) observed, ` +
|
|
233
|
-
`${report.validated.length} operation(s) validated, ` +
|
|
234
|
-
`${report.errorsValidated.length} error response(s) checked, ` +
|
|
235
|
-
`${report.violations.length} violation(s)`
|
|
236
|
-
];
|
|
237
|
-
lines.push(report.originFilter === undefined
|
|
238
|
-
? ` ORIGIN FILTER: none — every observed response was matched by PATH alone. ` +
|
|
239
|
-
`Sound only for a process that drives ONE plane; the control plane serves ` +
|
|
240
|
-
`different bodies at GET /api/whoami and DELETE /api/workspaces/{id}.`
|
|
241
|
-
: ` ORIGIN FILTER: ${report.originFilter}`);
|
|
242
|
-
if (report.offPlane.length > 0) {
|
|
243
|
-
lines.push(` OFF-PLANE (other origin, not checked against these bindings):`);
|
|
244
|
-
for (const route of report.offPlane) {
|
|
245
|
-
lines.push(` - ${route}`);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (report.validated.length > 0) {
|
|
249
|
-
lines.push(` VALIDATED (${report.validated.length}): ${report.validated.join(", ")}`);
|
|
250
|
-
}
|
|
251
|
-
if (report.errorsValidated.length > 0) {
|
|
252
|
-
lines.push(` ERROR ENVELOPES CHECKED (${report.errorsValidated.length}):`);
|
|
253
|
-
for (const route of report.errorsValidated) {
|
|
254
|
-
lines.push(` - ${route}`);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
if (report.unexercised.length > 0) {
|
|
258
|
-
lines.push(` NOT EXERCISED (schema exists, no response seen) (${report.unexercised.length}): ` +
|
|
259
|
-
`${report.unexercised.join(", ")}`);
|
|
260
|
-
}
|
|
261
|
-
if (report.unschemad.length > 0) {
|
|
262
|
-
lines.push(` NO SCHEMA (response seen, nothing to check it against):`);
|
|
263
|
-
for (const route of report.unschemad) {
|
|
264
|
-
lines.push(` - ${route}`);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
for (const violation of report.violations) {
|
|
268
|
-
lines.push(` VIOLATION [${violation.kind}] ${violation.name} ` +
|
|
269
|
-
`(${violation.method} ${violation.origin}${violation.path} -> ${violation.status}):`);
|
|
270
|
-
for (const issue of violation.issues) {
|
|
271
|
-
lines.push(` - ${issue}`);
|
|
272
|
-
}
|
|
273
|
-
lines.push(` body: ${renderBody(violation.body)}`);
|
|
274
|
-
}
|
|
275
|
-
return lines.join("\n");
|
|
276
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { UsageSummary } from "./runtime-types.js";
|
|
2
|
-
export interface ToolCallTrace {
|
|
3
|
-
readonly id: string;
|
|
4
|
-
readonly name: string;
|
|
5
|
-
readonly args: Readonly<Record<string, unknown>>;
|
|
6
|
-
readonly messageId?: string;
|
|
7
|
-
readonly startSeq?: number;
|
|
8
|
-
readonly startedAt?: string;
|
|
9
|
-
readonly result?: ToolCallResult;
|
|
10
|
-
readonly durationMs?: number;
|
|
11
|
-
}
|
|
12
|
-
export interface ToolCallResult {
|
|
13
|
-
readonly isError: boolean;
|
|
14
|
-
readonly content: unknown;
|
|
15
|
-
readonly seq?: number;
|
|
16
|
-
readonly recordedAt?: string;
|
|
17
|
-
}
|
|
18
|
-
export interface AssistantTextEntry {
|
|
19
|
-
readonly text: string;
|
|
20
|
-
readonly messageId?: string;
|
|
21
|
-
readonly seq?: number;
|
|
22
|
-
readonly recordedAt?: string;
|
|
23
|
-
}
|
|
24
|
-
export interface TurnTrace {
|
|
25
|
-
readonly toolCalls: readonly ToolCallTrace[];
|
|
26
|
-
readonly usage: UsageSummary;
|
|
27
|
-
readonly text: readonly AssistantTextEntry[];
|
|
28
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structured metadata for a strict-parser unknown-field diagnostic.
|
|
3
|
-
*
|
|
4
|
-
* This class is exported only from the workspace-internal contracts entrypoint.
|
|
5
|
-
* Its inherited `Error` name and formatted message preserve existing callers.
|
|
6
|
-
*/
|
|
7
|
-
export declare class UnknownFieldError extends Error {
|
|
8
|
-
readonly objectPath: string;
|
|
9
|
-
readonly unknownKey: string;
|
|
10
|
-
readonly permittedKeys: readonly string[];
|
|
11
|
-
constructor(objectPath: string, unknownKey: string, permittedKeys: readonly string[]);
|
|
12
|
-
withPermittedKeys(permittedKeys: readonly string[]): UnknownFieldError;
|
|
13
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structured metadata for a strict-parser unknown-field diagnostic.
|
|
3
|
-
*
|
|
4
|
-
* This class is exported only from the workspace-internal contracts entrypoint.
|
|
5
|
-
* Its inherited `Error` name and formatted message preserve existing callers.
|
|
6
|
-
*/
|
|
7
|
-
export class UnknownFieldError extends Error {
|
|
8
|
-
objectPath;
|
|
9
|
-
unknownKey;
|
|
10
|
-
permittedKeys;
|
|
11
|
-
constructor(objectPath, unknownKey, permittedKeys) {
|
|
12
|
-
const copiedPermittedKeys = Object.freeze([...permittedKeys]);
|
|
13
|
-
super(`${objectPath}.${unknownKey} is not an allowed field; permitted: ${copiedPermittedKeys.join(", ")}`);
|
|
14
|
-
this.objectPath = objectPath;
|
|
15
|
-
this.unknownKey = unknownKey;
|
|
16
|
-
this.permittedKeys = copiedPermittedKeys;
|
|
17
|
-
}
|
|
18
|
-
withPermittedKeys(permittedKeys) {
|
|
19
|
-
return new UnknownFieldError(this.objectPath, this.unknownKey, permittedKeys);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/** JSON-compatible scalar values carried by public wire contracts. */
|
|
2
|
-
export type JsonPrimitive = string | number | boolean | null;
|
|
3
|
-
/** Recursively JSON-compatible values; numbers must be finite at runtime. */
|
|
4
|
-
export type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
5
|
-
readonly [key: string]: JsonValue;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Broad object-record guard used at untrusted wire boundaries.
|
|
9
|
-
*
|
|
10
|
-
* Deliberately does not require a plain object or a particular prototype. The
|
|
11
|
-
* package's existing parsers have always accepted every non-null, non-array
|
|
12
|
-
* object at this first shape boundary and apply their domain checks afterwards.
|
|
13
|
-
*/
|
|
14
|
-
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
15
|
-
/** Recursively validate the package's JSON value contract. */
|
|
16
|
-
export declare function isJsonValue(value: unknown): value is JsonValue;
|
|
17
|
-
/** Validate an object record whose enumerable values are recursively JSON-compatible. */
|
|
18
|
-
export declare function isJsonRecord(value: unknown): value is Record<string, JsonValue>;
|
|
19
|
-
/** Narrow an unknown scalar to a member of an ordered readonly string tuple. */
|
|
20
|
-
export declare function isStringLiteral<const TAllowed extends readonly string[]>(value: unknown, allowed: TAllowed): value is TAllowed[number];
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Broad object-record guard used at untrusted wire boundaries.
|
|
3
|
-
*
|
|
4
|
-
* Deliberately does not require a plain object or a particular prototype. The
|
|
5
|
-
* package's existing parsers have always accepted every non-null, non-array
|
|
6
|
-
* object at this first shape boundary and apply their domain checks afterwards.
|
|
7
|
-
*/
|
|
8
|
-
export function isRecord(value) {
|
|
9
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
-
}
|
|
11
|
-
/** Recursively validate the package's JSON value contract. */
|
|
12
|
-
export function isJsonValue(value) {
|
|
13
|
-
if (typeof value === "number") {
|
|
14
|
-
return Number.isFinite(value);
|
|
15
|
-
}
|
|
16
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
if (Array.isArray(value)) {
|
|
20
|
-
return value.every(isJsonValue);
|
|
21
|
-
}
|
|
22
|
-
if (isRecord(value)) {
|
|
23
|
-
return Object.values(value).every(isJsonValue);
|
|
24
|
-
}
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
/** Validate an object record whose enumerable values are recursively JSON-compatible. */
|
|
28
|
-
export function isJsonRecord(value) {
|
|
29
|
-
return isRecord(value) && Object.values(value).every(isJsonValue);
|
|
30
|
-
}
|
|
31
|
-
/** Narrow an unknown scalar to a member of an ordered readonly string tuple. */
|
|
32
|
-
export function isStringLiteral(value, allowed) {
|
|
33
|
-
return typeof value === "string" && allowed.includes(value);
|
|
34
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Customer-side verification for aex start webhooks (Standard Webhooks scheme).
|
|
3
|
-
*
|
|
4
|
-
* aex signs every delivery HMAC-SHA256 over `${webhook-id}.${webhook-timestamp}.${rawBody}`
|
|
5
|
-
* and sends three headers:
|
|
6
|
-
* - `webhook-id` : stable across retries (dedupe key)
|
|
7
|
-
* - `webhook-timestamp` : unix seconds at send time
|
|
8
|
-
* - `webhook-signature` : space-delimited list of `v1,<base64(hmac)>` entries
|
|
9
|
-
* (a list during secret rotation — accept ANY match)
|
|
10
|
-
*
|
|
11
|
-
* The secret is the workspace signing secret surfaced once as `whsec_<base64>`;
|
|
12
|
-
* the HMAC key is the raw bytes after the `whsec_` prefix. Verification accepts
|
|
13
|
-
* the secret with or without the prefix.
|
|
14
|
-
*
|
|
15
|
-
* Pure Web Crypto — identical under Bun and Node; this mirrors the
|
|
16
|
-
* `standardwebhooks` library so a customer can verify with either.
|
|
17
|
-
*/
|
|
18
|
-
export interface VerifyAexWebhookInput {
|
|
19
|
-
/** The exact bytes of the request body, as a string (do NOT re-serialize). */
|
|
20
|
-
readonly rawBody: string;
|
|
21
|
-
/** The inbound request headers (case-insensitive lookup). */
|
|
22
|
-
readonly headers: Headers | Readonly<Record<string, string | string[] | undefined>>;
|
|
23
|
-
/** The workspace signing secret, `whsec_<base64>` (or the bare base64). */
|
|
24
|
-
readonly secret: string;
|
|
25
|
-
/** Max allowed clock skew between `webhook-timestamp` and now. Default 300s. */
|
|
26
|
-
readonly toleranceSeconds?: number;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Verify an aex webhook delivery. Returns `true` only when the timestamp is
|
|
30
|
-
* within tolerance AND one of the `v1,<base64>` entries in `webhook-signature`
|
|
31
|
-
* matches the HMAC over `${id}.${timestamp}.${rawBody}`. Constant-time compare;
|
|
32
|
-
* never throws on a bad signature (only on a malformed secret).
|
|
33
|
-
*/
|
|
34
|
-
export declare function verifyAexWebhook(input: VerifyAexWebhookInput): Promise<boolean>;
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Customer-side verification for aex start webhooks (Standard Webhooks scheme).
|
|
3
|
-
*
|
|
4
|
-
* aex signs every delivery HMAC-SHA256 over `${webhook-id}.${webhook-timestamp}.${rawBody}`
|
|
5
|
-
* and sends three headers:
|
|
6
|
-
* - `webhook-id` : stable across retries (dedupe key)
|
|
7
|
-
* - `webhook-timestamp` : unix seconds at send time
|
|
8
|
-
* - `webhook-signature` : space-delimited list of `v1,<base64(hmac)>` entries
|
|
9
|
-
* (a list during secret rotation — accept ANY match)
|
|
10
|
-
*
|
|
11
|
-
* The secret is the workspace signing secret surfaced once as `whsec_<base64>`;
|
|
12
|
-
* the HMAC key is the raw bytes after the `whsec_` prefix. Verification accepts
|
|
13
|
-
* the secret with or without the prefix.
|
|
14
|
-
*
|
|
15
|
-
* Pure Web Crypto — identical under Bun and Node; this mirrors the
|
|
16
|
-
* `standardwebhooks` library so a customer can verify with either.
|
|
17
|
-
*/
|
|
18
|
-
const encoder = new TextEncoder();
|
|
19
|
-
function headerValue(headers, name) {
|
|
20
|
-
if (headers instanceof Headers) {
|
|
21
|
-
return headers.get(name) ?? undefined;
|
|
22
|
-
}
|
|
23
|
-
const lower = name.toLowerCase();
|
|
24
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
25
|
-
if (key.toLowerCase() === lower) {
|
|
26
|
-
return Array.isArray(value) ? value[0] : value ?? undefined;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return undefined;
|
|
30
|
-
}
|
|
31
|
-
/** Strip the `whsec_` prefix and decode the base64 key material to bytes. */
|
|
32
|
-
function decodeSecret(secret) {
|
|
33
|
-
const material = secret.startsWith("whsec_") ? secret.slice("whsec_".length) : secret;
|
|
34
|
-
const binary = atob(material);
|
|
35
|
-
const bytes = new Uint8Array(binary.length);
|
|
36
|
-
for (let i = 0; i < binary.length; i++)
|
|
37
|
-
bytes[i] = binary.charCodeAt(i);
|
|
38
|
-
return bytes;
|
|
39
|
-
}
|
|
40
|
-
async function hmacBase64(keyBytes, message) {
|
|
41
|
-
const key = await crypto.subtle.importKey("raw", keyBytes, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
42
|
-
const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
|
|
43
|
-
let binary = "";
|
|
44
|
-
const view = new Uint8Array(sig);
|
|
45
|
-
for (let i = 0; i < view.length; i++)
|
|
46
|
-
binary += String.fromCharCode(view[i]);
|
|
47
|
-
return btoa(binary);
|
|
48
|
-
}
|
|
49
|
-
/** Length-then-constant-time comparison of two strings. */
|
|
50
|
-
function timingSafeEqual(a, b) {
|
|
51
|
-
if (a.length !== b.length)
|
|
52
|
-
return false;
|
|
53
|
-
let diff = 0;
|
|
54
|
-
for (let i = 0; i < a.length; i++)
|
|
55
|
-
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
56
|
-
return diff === 0;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Verify an aex webhook delivery. Returns `true` only when the timestamp is
|
|
60
|
-
* within tolerance AND one of the `v1,<base64>` entries in `webhook-signature`
|
|
61
|
-
* matches the HMAC over `${id}.${timestamp}.${rawBody}`. Constant-time compare;
|
|
62
|
-
* never throws on a bad signature (only on a malformed secret).
|
|
63
|
-
*/
|
|
64
|
-
export async function verifyAexWebhook(input) {
|
|
65
|
-
const toleranceSeconds = input.toleranceSeconds ?? 300;
|
|
66
|
-
const id = headerValue(input.headers, "webhook-id");
|
|
67
|
-
const timestamp = headerValue(input.headers, "webhook-timestamp");
|
|
68
|
-
const signatureHeader = headerValue(input.headers, "webhook-signature");
|
|
69
|
-
if (!id || !timestamp || !signatureHeader)
|
|
70
|
-
return false;
|
|
71
|
-
const ts = Number(timestamp);
|
|
72
|
-
if (!Number.isFinite(ts))
|
|
73
|
-
return false;
|
|
74
|
-
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
75
|
-
if (Math.abs(nowSeconds - ts) > toleranceSeconds)
|
|
76
|
-
return false;
|
|
77
|
-
const keyBytes = decodeSecret(input.secret);
|
|
78
|
-
const expected = await hmacBase64(keyBytes, `${id}.${timestamp}.${input.rawBody}`);
|
|
79
|
-
// `webhook-signature` is a space-delimited list of versioned signatures; a
|
|
80
|
-
// single delivery may carry several (current + previous key during rotation).
|
|
81
|
-
for (const entry of signatureHeader.split(" ")) {
|
|
82
|
-
const comma = entry.indexOf(",");
|
|
83
|
-
if (comma === -1)
|
|
84
|
-
continue;
|
|
85
|
-
const version = entry.slice(0, comma);
|
|
86
|
-
const value = entry.slice(comma + 1);
|
|
87
|
-
if (version !== "v1")
|
|
88
|
-
continue;
|
|
89
|
-
if (timingSafeEqual(value, expected))
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The seam the wire-conformance harness (C4) attaches to.
|
|
3
|
-
*
|
|
4
|
-
* `HttpClient` reports every JSON response here — 2xx AND the error envelopes it
|
|
5
|
-
* is about to throw on. Nothing observes it unless a harness installs an
|
|
6
|
-
* observer, so the shipped cost is one null check per request and this file's
|
|
7
|
-
* handful of bytes — deliberately small, because it ships in the published SDK
|
|
8
|
-
* while the harness that uses it does not.
|
|
9
|
-
*
|
|
10
|
-
* It lives here rather than in `schemas/` because `http.ts` must not pull the
|
|
11
|
-
* schema library in on the request path.
|
|
12
|
-
*/
|
|
13
|
-
/** A JSON response as it came off the wire, before any client-side shaping. */
|
|
14
|
-
export interface WireResponse {
|
|
15
|
-
readonly method: string;
|
|
16
|
-
/**
|
|
17
|
-
* Scheme + host + port of the plane that served it — `https://api.aex.dev`.
|
|
18
|
-
*
|
|
19
|
-
* Carried because a PATH does not identify a route: the control plane serves
|
|
20
|
-
* different bodies at two of the data plane's paths (`GET /api/whoami`,
|
|
21
|
-
* `DELETE /api/workspaces/{id}`). Without this, a process driving both planes
|
|
22
|
-
* validates a control-plane body against a data-plane schema and reports a
|
|
23
|
-
* violation that is not one. `URL.origin` is a getter on a URL the client has
|
|
24
|
-
* already constructed, and it is read inside the reporting thunk, so nothing
|
|
25
|
-
* computes it when no harness is observing.
|
|
26
|
-
*/
|
|
27
|
-
readonly origin: string;
|
|
28
|
-
/** Path only — no origin, no query string. `/api/sessions/sess_1/messages`. */
|
|
29
|
-
readonly path: string;
|
|
30
|
-
readonly status: number;
|
|
31
|
-
/**
|
|
32
|
-
* The body EXACTLY as it was decoded, including on a non-2xx.
|
|
33
|
-
*
|
|
34
|
-
* Never the client's enrichment of it: `HttpClient` folds the `x-request-id`
|
|
35
|
-
* header into the error body it throws, and a harness validating that derived
|
|
36
|
-
* object would be checking our own client rather than the server's bytes.
|
|
37
|
-
*/
|
|
38
|
-
readonly body: unknown;
|
|
39
|
-
}
|
|
40
|
-
export type WireResponseObserver = (response: WireResponse) => void;
|
|
41
|
-
/**
|
|
42
|
-
* Install an observer and get a function that removes it.
|
|
43
|
-
*
|
|
44
|
-
* Deliberately single-slot: two harnesses observing at once would double-count
|
|
45
|
-
* coverage, and there is no case for it.
|
|
46
|
-
*/
|
|
47
|
-
export declare function observeWireResponses(next: WireResponseObserver): () => void;
|
|
48
|
-
/** Report a response. A no-op — and nearly free — when nothing is observing. */
|
|
49
|
-
export declare function reportWireResponse(response: () => WireResponse): void;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The seam the wire-conformance harness (C4) attaches to.
|
|
3
|
-
*
|
|
4
|
-
* `HttpClient` reports every JSON response here — 2xx AND the error envelopes it
|
|
5
|
-
* is about to throw on. Nothing observes it unless a harness installs an
|
|
6
|
-
* observer, so the shipped cost is one null check per request and this file's
|
|
7
|
-
* handful of bytes — deliberately small, because it ships in the published SDK
|
|
8
|
-
* while the harness that uses it does not.
|
|
9
|
-
*
|
|
10
|
-
* It lives here rather than in `schemas/` because `http.ts` must not pull the
|
|
11
|
-
* schema library in on the request path.
|
|
12
|
-
*/
|
|
13
|
-
let observer;
|
|
14
|
-
/**
|
|
15
|
-
* Install an observer and get a function that removes it.
|
|
16
|
-
*
|
|
17
|
-
* Deliberately single-slot: two harnesses observing at once would double-count
|
|
18
|
-
* coverage, and there is no case for it.
|
|
19
|
-
*/
|
|
20
|
-
export function observeWireResponses(next) {
|
|
21
|
-
observer = next;
|
|
22
|
-
return () => {
|
|
23
|
-
if (observer === next) {
|
|
24
|
-
observer = undefined;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
/** Report a response. A no-op — and nearly free — when nothing is observing. */
|
|
29
|
-
export function reportWireResponse(response) {
|
|
30
|
-
if (observer === undefined) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
observer(response());
|
|
34
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/** Internal orchestration states. Public session reads use `SessionStatus`. */
|
|
2
|
-
export declare const SESSION_WORKFLOW_STATUSES: readonly ["queued", "claiming", "provisioning", "session_created", "dispatched", "provider_running", "provider_idle", "provider_rescheduled", "idle", "suspending", "suspended", "deleting", "deleted", "expired", "cancelling", "capturing_files", "cleaning_up", "succeeded", "failed", "timed_out", "cancelled", "interrupted", "cleanup_failed"];
|
|
3
|
-
export type SessionWorkflowStatus = (typeof SESSION_WORKFLOW_STATUSES)[number];
|
|
4
|
-
export type SessionWorkflowStatusKind = "active" | "terminal";
|
|
5
|
-
export declare const TERMINAL_SESSION_WORKFLOW_STATUSES: readonly ["succeeded", "failed", "timed_out", "cancelled", "interrupted", "deleted", "expired", "cleanup_failed"];
|
|
6
|
-
export declare function isTerminalSessionWorkflowStatus(status: SessionWorkflowStatus): boolean;
|
|
7
|
-
export declare function getSessionWorkflowStatusKind(status: SessionWorkflowStatus): SessionWorkflowStatusKind;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/** Internal orchestration states. Public session reads use `SessionStatus`. */
|
|
2
|
-
export const SESSION_WORKFLOW_STATUSES = [
|
|
3
|
-
"queued",
|
|
4
|
-
"claiming",
|
|
5
|
-
"provisioning",
|
|
6
|
-
"session_created",
|
|
7
|
-
"dispatched",
|
|
8
|
-
"provider_running",
|
|
9
|
-
"provider_idle",
|
|
10
|
-
"provider_rescheduled",
|
|
11
|
-
"idle",
|
|
12
|
-
"suspending",
|
|
13
|
-
"suspended",
|
|
14
|
-
"deleting",
|
|
15
|
-
"deleted",
|
|
16
|
-
"expired",
|
|
17
|
-
"cancelling",
|
|
18
|
-
"capturing_files",
|
|
19
|
-
"cleaning_up",
|
|
20
|
-
"succeeded",
|
|
21
|
-
"failed",
|
|
22
|
-
"timed_out",
|
|
23
|
-
"cancelled",
|
|
24
|
-
"interrupted",
|
|
25
|
-
"cleanup_failed"
|
|
26
|
-
];
|
|
27
|
-
export const TERMINAL_SESSION_WORKFLOW_STATUSES = [
|
|
28
|
-
"succeeded",
|
|
29
|
-
"failed",
|
|
30
|
-
"timed_out",
|
|
31
|
-
"cancelled",
|
|
32
|
-
"interrupted",
|
|
33
|
-
"deleted",
|
|
34
|
-
"expired",
|
|
35
|
-
"cleanup_failed"
|
|
36
|
-
];
|
|
37
|
-
const terminalSessionWorkflowStatuses = new Set(TERMINAL_SESSION_WORKFLOW_STATUSES);
|
|
38
|
-
export function isTerminalSessionWorkflowStatus(status) {
|
|
39
|
-
return terminalSessionWorkflowStatuses.has(status);
|
|
40
|
-
}
|
|
41
|
-
export function getSessionWorkflowStatusKind(status) {
|
|
42
|
-
return isTerminalSessionWorkflowStatus(status) ? "terminal" : "active";
|
|
43
|
-
}
|