@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,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The authenticated data-plane HTTP route table.
|
|
3
|
-
*
|
|
4
|
-
* This is the single machine-readable description of the data-plane surface:
|
|
5
|
-
* the platform api lambda dispatches and scope-gates from it, and the OpenAPI
|
|
6
|
-
* generator in this repo reads the same table. It is declared here exactly
|
|
7
|
-
* once so the two can never drift.
|
|
8
|
-
*
|
|
9
|
-
* Declaration-only and dependency-free: matching, scope lookup and route
|
|
10
|
-
* classification stay with the server that dispatches them.
|
|
11
|
-
*/
|
|
12
|
-
const route = (name, method, pattern, samplePath, requiredScope) => ({
|
|
13
|
-
name,
|
|
14
|
-
method,
|
|
15
|
-
pattern,
|
|
16
|
-
samplePath,
|
|
17
|
-
requiredScope,
|
|
18
|
-
});
|
|
19
|
-
export const AUTHENTICATED_API_ROUTE_DESCRIPTORS = [
|
|
20
|
-
// Valid-token canary.
|
|
21
|
-
route("whoami", "GET", /^\/whoami$/, "/whoami", null),
|
|
22
|
-
// Private runtime liveness of the exact writer baton. This is writer-token
|
|
23
|
-
// only at dispatch; it is not a bearer/public SDK surface.
|
|
24
|
-
route("runtime.writerAuthority", "GET", /^\/runtime\/writer-authority$/, "/runtime/writer-authority", null),
|
|
25
|
-
// (storage-model WS2) The credential-less container's DDB-decided journal commit channel: the api
|
|
26
|
-
// runs the fenced control-item write on its behalf. Writer-token only (same channel as
|
|
27
|
-
// writer-authority); the WS1 writerEpoch fence is applied at dispatch before this route runs.
|
|
28
|
-
route("runtime.journalCommit", "POST", /^\/runtime\/journal\/commit$/, "/runtime/journal/commit", null),
|
|
29
|
-
// Sessions.
|
|
30
|
-
route("sessions.create", "POST", /^\/sessions$/, "/sessions", "sessions:write"),
|
|
31
|
-
route("sessions.list", "GET", /^\/sessions$/, "/sessions", "sessions:read"),
|
|
32
|
-
route("sessions.listMessages", "GET", /^\/sessions\/[^/]+\/messages$/, "/sessions/sess_1/messages", "sessions:read"),
|
|
33
|
-
route("sessions.sendMessage", "POST", /^\/sessions\/[^/]+\/messages$/, "/sessions/sess_1/messages", "sessions:write"),
|
|
34
|
-
route("sessions.suspend", "POST", /^\/sessions\/[^/]+\/suspend$/, "/sessions/sess_1/suspend", "sessions:write"),
|
|
35
|
-
route("sessions.cancel", "POST", /^\/sessions\/[^/]+\/cancel$/, "/sessions/sess_1/cancel", "sessions:cancel"),
|
|
36
|
-
route("sessions.resume", "POST", /^\/sessions\/[^/]+\/resume$/, "/sessions/sess_1/resume", "sessions:write"),
|
|
37
|
-
route("sessions.requestApproval", "POST", /^\/sessions\/[^/]+\/request-approval$/, "/sessions/sess_1/request-approval", "sessions:write"),
|
|
38
|
-
route("sessions.approve", "POST", /^\/sessions\/[^/]+\/approve$/, "/sessions/sess_1/approve", "sessions:write"),
|
|
39
|
-
route("sessions.deny", "POST", /^\/sessions\/[^/]+\/deny$/, "/sessions/sess_1/deny", "sessions:write"),
|
|
40
|
-
route("sessions.delete", "DELETE", /^\/sessions\/[^/]+$/, "/sessions/sess_1", "sessions:delete"),
|
|
41
|
-
route("sessions.eventsTicket", "POST", /^\/sessions\/[^/]+\/events\/ticket$/, "/sessions/sess_1/events/ticket", "sessions:read"),
|
|
42
|
-
route("sessions.listEvents", "GET", /^\/sessions\/[^/]+\/events$/, "/sessions/sess_1/events", "sessions:read"),
|
|
43
|
-
route("sessions.otel", "GET", /^\/sessions\/[^/]+\/otel$/, "/sessions/sess_1/otel", "sessions:read"),
|
|
44
|
-
route("sessions.listChildren", "GET", /^\/sessions\/[^/]+\/children$/, "/sessions/sess_1/children", null),
|
|
45
|
-
route("sessions.childResult", "GET", /^\/sessions\/[^/]+\/result$/, "/sessions/sess_1/result", null),
|
|
46
|
-
route("sessions.eventArchiveLink", "POST", /^\/sessions\/[^/]+\/events\/link$/, "/sessions/sess_1/events/link", "sessions:read"),
|
|
47
|
-
route("sessions.downloadFile", "GET", /^\/sessions\/[^/]+\/files\/[^/]+\/download$/, "/sessions/sess_1/files/file_1/download", "files:read"),
|
|
48
|
-
route("sessions.fileLink", "POST", /^\/sessions\/[^/]+\/files\/[^/]+\/link$/, "/sessions/sess_1/files/file_1/link", "files:read"),
|
|
49
|
-
route("sessions.listFiles", "GET", /^\/sessions\/[^/]+\/files$/, "/sessions/sess_1/files", "files:read"),
|
|
50
|
-
route("sessions.listWebhookDeliveries", "GET", /^\/sessions\/[^/]+\/webhook-deliveries$/, "/sessions/sess_1/webhook-deliveries", "sessions:read"),
|
|
51
|
-
route("sessions.redeliverWebhook", "POST", /^\/sessions\/[^/]+\/webhook-deliveries\/[^/]+\/redeliver$/, "/sessions/sess_1/webhook-deliveries/del_1/redeliver", "sessions:write"),
|
|
52
|
-
route("sessions.archiveInternal", "GET", /^\/internal\/sessions\/[^/]+\/archive$/, "/internal/sessions/sess_1/archive", "files:read"),
|
|
53
|
-
route("sessions.get", "GET", /^\/sessions\/[^/]+$/, "/sessions/sess_1", "sessions:read"),
|
|
54
|
-
route("sessions.finalize", "POST", /^\/sessions\/[^/]+\/finalize$/, "/sessions/ses_1/finalize", "sessions:write"),
|
|
55
|
-
// Immutable content-addressed bytes backing every workspace resource family.
|
|
56
|
-
route("assets.presign", "POST", /^\/assets\/presign$/, "/assets/presign", "assets:write"),
|
|
57
|
-
route("assets.finalize", "POST", /^\/assets\/finalize$/, "/assets/finalize", "assets:write"),
|
|
58
|
-
route("assets.mpuPresignParts", "POST", /^\/assets\/mpu\/presign-parts$/, "/assets/mpu/presign-parts", "assets:write"),
|
|
59
|
-
route("assets.mpuAbort", "POST", /^\/assets\/mpu\/abort$/, "/assets/mpu/abort", "assets:write"),
|
|
60
|
-
route("assets.delete", "DELETE", /^\/assets\/[^/]+$/, "/assets/asset_1", "assets:delete"),
|
|
61
|
-
// Versioned workspace resources. The raw bytes stay in /assets; these routes
|
|
62
|
-
// publish and address immutable typed versions backed by those bytes.
|
|
63
|
-
route("workspace.files.publish", "POST", /^\/workspace\/files$/, "/workspace/files", "files:write"),
|
|
64
|
-
route("workspace.files.list", "GET", /^\/workspace\/files$/, "/workspace/files", "files:read"),
|
|
65
|
-
route("workspace.files.get", "GET", /^\/workspace\/files\/[^/]+$/, "/workspace/files/wres_1", "files:read"),
|
|
66
|
-
route("workspace.files.delete", "DELETE", /^\/workspace\/files\/[^/]+$/, "/workspace/files/wres_1", "files:delete"),
|
|
67
|
-
route("workspace.skills.publish", "POST", /^\/workspace\/skills$/, "/workspace/skills", "skills:write"),
|
|
68
|
-
route("workspace.skills.list", "GET", /^\/workspace\/skills$/, "/workspace/skills", "skills:read"),
|
|
69
|
-
route("workspace.skills.get", "GET", /^\/workspace\/skills\/[^/]+$/, "/workspace/skills/wres_1", "skills:read"),
|
|
70
|
-
route("workspace.skills.delete", "DELETE", /^\/workspace\/skills\/[^/]+$/, "/workspace/skills/wres_1", "skills:delete"),
|
|
71
|
-
route("workspace.tools.publish", "POST", /^\/workspace\/tools$/, "/workspace/tools", "tools:write"),
|
|
72
|
-
route("workspace.tools.list", "GET", /^\/workspace\/tools$/, "/workspace/tools", "tools:read"),
|
|
73
|
-
route("workspace.tools.get", "GET", /^\/workspace\/tools\/[^/]+$/, "/workspace/tools/wres_1", "tools:read"),
|
|
74
|
-
route("workspace.tools.delete", "DELETE", /^\/workspace\/tools\/[^/]+$/, "/workspace/tools/wres_1", "tools:delete"),
|
|
75
|
-
route("workspace.instructions.publish", "POST", /^\/workspace\/instructions$/, "/workspace/instructions", "instructions:write"),
|
|
76
|
-
route("workspace.instructions.list", "GET", /^\/workspace\/instructions$/, "/workspace/instructions", "instructions:read"),
|
|
77
|
-
route("workspace.instructions.get", "GET", /^\/workspace\/instructions\/[^/]+$/, "/workspace/instructions/wres_1", "instructions:read"),
|
|
78
|
-
route("workspace.instructions.delete", "DELETE", /^\/workspace\/instructions\/[^/]+$/, "/workspace/instructions/wres_1", "instructions:delete"),
|
|
79
|
-
// Workspace secret store.
|
|
80
|
-
route("secrets.create", "POST", /^\/secrets$/, "/secrets", "secrets:write"),
|
|
81
|
-
route("secrets.list", "GET", /^\/secrets$/, "/secrets", "secrets:read"),
|
|
82
|
-
route("secrets.rotate", "POST", /^\/secrets\/[^/]+\/rotate$/, "/secrets/NAME/rotate", "secrets:write"),
|
|
83
|
-
route("secrets.delete", "DELETE", /^\/secrets\/[^/]+$/, "/secrets/NAME", "secrets:write"),
|
|
84
|
-
route("secrets.get", "GET", /^\/secrets\/[^/]+$/, "/secrets/NAME", "secrets:read"),
|
|
85
|
-
// Workspace MCP server config.
|
|
86
|
-
route("mcpServers.create", "POST", /^\/mcp-servers$/, "/mcp-servers", "mcp:write"),
|
|
87
|
-
route("mcpServers.list", "GET", /^\/mcp-servers$/, "/mcp-servers", "mcp:read"),
|
|
88
|
-
route("mcpServers.delete", "DELETE", /^\/mcp-servers\/[^/]+$/, "/mcp-servers/mcp_abcdefghi", "mcp:delete"),
|
|
89
|
-
route("mcpServers.get", "GET", /^\/mcp-servers\/[^/]+$/, "/mcp-servers/mcp_abcdefghi", "mcp:read"),
|
|
90
|
-
// Billing (customer read + operator manage).
|
|
91
|
-
route("billing.get", "GET", /^\/billing$/, "/billing", "billing:read"),
|
|
92
|
-
route("billing.ledger", "GET", /^\/billing\/ledger$/, "/billing/ledger", "billing:read"),
|
|
93
|
-
route("billing.topupCheckout", "POST", /^\/billing\/topup\/checkout$/, "/billing/topup/checkout", "billing:read"),
|
|
94
|
-
route("billing.autoTopup", "PATCH", /^\/billing\/autotopup$/, "/billing/autotopup", "billing:read"),
|
|
95
|
-
// Monthly statements. The period segment is pinned to a UTC month rather than
|
|
96
|
-
// the usual `[^/]+`: a looser pattern would route `/billing/statements/../x`
|
|
97
|
-
// into the handler for it to reject, instead of refusing it at the door.
|
|
98
|
-
route("billing.statements", "GET", /^\/billing\/statements$/, "/billing/statements", "billing:read"),
|
|
99
|
-
route("billing.statement", "GET", /^\/billing\/statements\/[0-9]{4}-(0[1-9]|1[0-2])$/, "/billing/statements/2026-07", "billing:read"),
|
|
100
|
-
route("billing.portal", "POST", /^\/billing\/portal$/, "/billing/portal", "billing:read"),
|
|
101
|
-
route("adminBilling.topup", "POST", /^\/admin\/billing\/topup$/, "/admin/billing/topup", "billing:manage"),
|
|
102
|
-
route("adminBilling.paymentMethod", "POST", /^\/admin\/billing\/payment-method$/, "/admin/billing/payment-method", "billing:manage"),
|
|
103
|
-
route("adminBilling.accountType", "POST", /^\/admin\/billing\/account-type$/, "/admin/billing/account-type", "billing:manage"),
|
|
104
|
-
// Session webhooks (reveal/rotate signing secret + delivery ledger).
|
|
105
|
-
route("webhook.signingSecret", "POST", /^\/webhook\/signing-secret$/, "/webhook/signing-secret", "sessions:write"),
|
|
106
|
-
route("webhook.listDeliveries", "GET", /^\/webhook\/deliveries$/, "/webhook/deliveries", "sessions:read"),
|
|
107
|
-
// GDPR workspace hard-erase (owner self-service).
|
|
108
|
-
route("workspaces.erase", "DELETE", /^\/workspaces\/[^/]+$/, "/workspaces/ws_1", "workspaces:delete"),
|
|
109
|
-
];
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ASSET_ARCHIVE_LIMITS } from "./session-config.js";
|
|
2
|
-
/** Render a byte ceiling the way the message quotes it, so the two cannot drift. */
|
|
3
|
-
function mib(bytes) {
|
|
4
|
-
return `${bytes / (1024 * 1024)} MiB`;
|
|
5
|
-
}
|
|
6
|
-
export function assertArchiveCompressedSize(size, source) {
|
|
7
|
-
if (!Number.isSafeInteger(size) || size < 0 || size > ASSET_ARCHIVE_LIMITS.maxCompressedBytes) {
|
|
8
|
-
throw new Error(`${source} exceeds the ${mib(ASSET_ARCHIVE_LIMITS.maxCompressedBytes)} compressed limit ` +
|
|
9
|
-
`(got ${Number.isFinite(size) ? size : "an invalid byte count"})`);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
export function assertArchiveExpandedSize(size, source) {
|
|
13
|
-
if (!Number.isSafeInteger(size) || size < 0 || size > ASSET_ARCHIVE_LIMITS.maxDecompressedBytes) {
|
|
14
|
-
throw new Error(`${source} exceeds the ${mib(ASSET_ARCHIVE_LIMITS.maxDecompressedBytes)} expanded limit ` +
|
|
15
|
-
`(got ${Number.isFinite(size) ? size : "an invalid byte count"})`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
export function assertArchiveEntryCount(count, source) {
|
|
19
|
-
if (!Number.isSafeInteger(count) || count < 0 || count > ASSET_ARCHIVE_LIMITS.maxEntries) {
|
|
20
|
-
throw new Error(`${source} exceeds the ${ASSET_ARCHIVE_LIMITS.maxEntries}-entry limit ` +
|
|
21
|
-
`(got ${Number.isFinite(count) ? count : "an invalid entry count"})`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { type ToolInputSchema } from "./session-config.js";
|
|
2
|
-
import type { SkillFiles, ToolBundleManifest } from "./asset-bundle.js";
|
|
3
|
-
export interface AssetToolManifestInput {
|
|
4
|
-
readonly name: string;
|
|
5
|
-
readonly description: string;
|
|
6
|
-
readonly inputSchema?: ToolInputSchema;
|
|
7
|
-
readonly input_schema?: ToolInputSchema;
|
|
8
|
-
readonly entry: string;
|
|
9
|
-
}
|
|
10
|
-
export interface SkillFrontmatter {
|
|
11
|
-
readonly name?: string;
|
|
12
|
-
readonly description?: string;
|
|
13
|
-
}
|
|
14
|
-
/** Internal authoring helper shared by the SDK and the bundled CLI. */
|
|
15
|
-
export declare function extractSkillFrontmatter(source: string, files: SkillFiles): SkillFrontmatter;
|
|
16
|
-
/** Minimal scalar-only YAML frontmatter reader used by public skill factories. */
|
|
17
|
-
export declare function parseSkillFrontmatter(text: string): SkillFrontmatter;
|
|
18
|
-
/** Resolve and validate the canonical skill name shared by SDK and CLI drafts. */
|
|
19
|
-
export declare function deriveSkillName(source: string, frontmatterName: string | undefined, explicitName: string | undefined, dirBasename: string | undefined, diagnostics?: "sdk" | "cli"): string;
|
|
20
|
-
/** Validate and canonicalize a tool manifest before it is archived. */
|
|
21
|
-
export declare function normalizeToolManifest(source: string, input: AssetToolManifestInput, files?: SkillFiles, diagnostics?: "sdk" | "cli"): ToolBundleManifest;
|
|
22
|
-
export declare function slugifyAssetName(input: string): string;
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { SKILL_NAME_PATTERN, SKILL_RESERVED_NAMES, TOOL_NAME_PATTERN, normaliseSkillBundlePath } from "./session-config.js";
|
|
2
|
-
/** Internal authoring helper shared by the SDK and the bundled CLI. */
|
|
3
|
-
export function extractSkillFrontmatter(source, files) {
|
|
4
|
-
const raw = files["SKILL.md"];
|
|
5
|
-
if (raw === undefined) {
|
|
6
|
-
throw new Error(`${source}: the skill bundle must contain a SKILL.md at its root`);
|
|
7
|
-
}
|
|
8
|
-
const text = typeof raw === "string" ? raw : new TextDecoder().decode(raw);
|
|
9
|
-
return parseSkillFrontmatter(text);
|
|
10
|
-
}
|
|
11
|
-
/** Minimal scalar-only YAML frontmatter reader used by public skill factories. */
|
|
12
|
-
export function parseSkillFrontmatter(text) {
|
|
13
|
-
const src = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
|
|
14
|
-
const match = /^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/.exec(src);
|
|
15
|
-
if (!match)
|
|
16
|
-
return {};
|
|
17
|
-
const out = {};
|
|
18
|
-
for (const line of match[1].split(/\r?\n/)) {
|
|
19
|
-
const kv = /^([A-Za-z0-9_-]+)[ \t]*:[ \t]*(.*)$/.exec(line);
|
|
20
|
-
if (!kv)
|
|
21
|
-
continue;
|
|
22
|
-
const key = kv[1].toLowerCase();
|
|
23
|
-
if (key !== "name" && key !== "description")
|
|
24
|
-
continue;
|
|
25
|
-
let value = kv[2].trim();
|
|
26
|
-
if (value.length >= 2 &&
|
|
27
|
-
((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")))) {
|
|
28
|
-
value = value.slice(1, -1);
|
|
29
|
-
}
|
|
30
|
-
if (value.length > 0)
|
|
31
|
-
out[key] = value;
|
|
32
|
-
}
|
|
33
|
-
return out;
|
|
34
|
-
}
|
|
35
|
-
/** Resolve and validate the canonical skill name shared by SDK and CLI drafts. */
|
|
36
|
-
export function deriveSkillName(source, frontmatterName, explicitName, dirBasename, diagnostics = "sdk") {
|
|
37
|
-
let name = explicitName ?? frontmatterName;
|
|
38
|
-
if (name === undefined && dirBasename !== undefined) {
|
|
39
|
-
const slug = slugifyAssetName(dirBasename);
|
|
40
|
-
if (slug.length > 0)
|
|
41
|
-
name = slug;
|
|
42
|
-
}
|
|
43
|
-
if (typeof name !== "string" || name.length === 0) {
|
|
44
|
-
if (diagnostics === "cli") {
|
|
45
|
-
throw new Error(`${source}: a skill name is required`);
|
|
46
|
-
}
|
|
47
|
-
throw new Error(`${source}: a skill name is required — pass { name }, add a \`name:\` field to the SKILL.md ` +
|
|
48
|
-
`YAML frontmatter, or (for fromDir) use a directory whose basename slugifies to a valid name`);
|
|
49
|
-
}
|
|
50
|
-
if (!SKILL_NAME_PATTERN.test(name)) {
|
|
51
|
-
throw new Error(`${source}: name ${JSON.stringify(name)} must match ${SKILL_NAME_PATTERN.source}`);
|
|
52
|
-
}
|
|
53
|
-
if (name.includes("__")) {
|
|
54
|
-
throw new Error(`${source}: name must not contain "__"; that separator is reserved for MCP tools`);
|
|
55
|
-
}
|
|
56
|
-
if (SKILL_RESERVED_NAMES.has(name)) {
|
|
57
|
-
if (diagnostics === "cli") {
|
|
58
|
-
throw new Error(`${source}: name ${JSON.stringify(name)} is reserved (${[...SKILL_RESERVED_NAMES].join(", ")})`);
|
|
59
|
-
}
|
|
60
|
-
throw new Error(`${source}: name ${JSON.stringify(name)} is reserved (${[...SKILL_RESERVED_NAMES].join(", ")}); pick another`);
|
|
61
|
-
}
|
|
62
|
-
return name;
|
|
63
|
-
}
|
|
64
|
-
/** Validate and canonicalize a tool manifest before it is archived. */
|
|
65
|
-
export function normalizeToolManifest(source, input, files, diagnostics = "sdk") {
|
|
66
|
-
const name = input.name;
|
|
67
|
-
if (typeof name !== "string" || !TOOL_NAME_PATTERN.test(name)) {
|
|
68
|
-
throw new Error(`${source}: name must match ${TOOL_NAME_PATTERN.source}`);
|
|
69
|
-
}
|
|
70
|
-
if (name.includes("__")) {
|
|
71
|
-
throw new Error(`${source}: name must not contain "__"; that separator is reserved for MCP tools`);
|
|
72
|
-
}
|
|
73
|
-
const description = input.description;
|
|
74
|
-
if (typeof description !== "string" || description.trim().length === 0 || description.length > 2048) {
|
|
75
|
-
throw new Error(`${source}: description must be non-empty and <= 2048 chars`);
|
|
76
|
-
}
|
|
77
|
-
const inputSchema = input.inputSchema ?? input.input_schema;
|
|
78
|
-
if (!inputSchema || typeof inputSchema !== "object" || Array.isArray(inputSchema)) {
|
|
79
|
-
throw new Error(`${source}: inputSchema must be a JSON Schema object`);
|
|
80
|
-
}
|
|
81
|
-
if (inputSchema.type !== "object") {
|
|
82
|
-
throw new Error(`${source}: inputSchema.type must be "object"`);
|
|
83
|
-
}
|
|
84
|
-
const entry = normaliseSkillBundlePath(input.entry);
|
|
85
|
-
assertJsModuleEntry(source, entry, input.entry, files, diagnostics);
|
|
86
|
-
return { name, description, input_schema: inputSchema, entry };
|
|
87
|
-
}
|
|
88
|
-
export function slugifyAssetName(input) {
|
|
89
|
-
return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
90
|
-
}
|
|
91
|
-
const JS_MODULE_ENTRY = /\.(?:js|mjs|cjs)$/i;
|
|
92
|
-
function assertJsModuleEntry(source, entry, rawEntry, files, diagnostics) {
|
|
93
|
-
const basename = entry.split("/").pop() ?? entry;
|
|
94
|
-
if (!JS_MODULE_ENTRY.test(basename)) {
|
|
95
|
-
if (diagnostics === "cli") {
|
|
96
|
-
throw new Error(`${source}: entry must be a JS module (.js/.mjs/.cjs)`);
|
|
97
|
-
}
|
|
98
|
-
throw new Error(`${source}: entry must be a JS module (.js/.mjs/.cjs) that default-exports a function or { execute }; got ${JSON.stringify(rawEntry)}`);
|
|
99
|
-
}
|
|
100
|
-
if (files !== undefined && !(entry in files) && !(rawEntry in files)) {
|
|
101
|
-
if (diagnostics === "cli") {
|
|
102
|
-
throw new Error(`${source}: entry ${JSON.stringify(rawEntry)} is not present in files`);
|
|
103
|
-
}
|
|
104
|
-
throw new Error(`${source}: entry ${JSON.stringify(rawEntry)} is not present in files (keys: ${Object.keys(files).join(", ") || "(none)"})`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { type BundleSymlink } from "./bundle-manifest.js";
|
|
2
|
-
import { type ToolInputSchema } from "./session-config.js";
|
|
3
|
-
/**
|
|
4
|
-
* In-memory skill bundle: a flat path -> bytes map and the
|
|
5
|
-
* deterministically-zipped representation.
|
|
6
|
-
*
|
|
7
|
-
* Public authoring consumers run the cheap, safety-critical checks here
|
|
8
|
-
* (`parseSkillBundleEntry`: no `..`, no absolute paths, no Windows
|
|
9
|
-
* backslashes, depth/length limits). The BFF re-canonicalises and
|
|
10
|
-
* recomputes the canonical hash on receipt. Client-side hashing is advisory
|
|
11
|
-
* and exists to make uploads retry-safe and content-addressable.
|
|
12
|
-
*
|
|
13
|
-
* For workspace skills the SDK and CLI compute an advisory `sha256` of the
|
|
14
|
-
* canonicalised zip via `hashSkillBundle()` before upserting the skill by name.
|
|
15
|
-
* The platform verifies the hash against the uploaded bytes and uses it for
|
|
16
|
-
* deduplication.
|
|
17
|
-
*/
|
|
18
|
-
export interface BundledSkill {
|
|
19
|
-
readonly zip: Uint8Array;
|
|
20
|
-
readonly fileCount: number;
|
|
21
|
-
readonly compressedSize: number;
|
|
22
|
-
}
|
|
23
|
-
/** Inline files map: path -> contents (UTF-8 string or raw bytes). */
|
|
24
|
-
export type SkillFiles = Readonly<Record<string, string | Uint8Array>>;
|
|
25
|
-
/**
|
|
26
|
-
* Fidelity metadata captured from a local directory walk: `exec` are the
|
|
27
|
-
* bundle-relative paths that restore executable (0o755); `symlinks` are captured
|
|
28
|
-
* links. When non-empty it is serialized into the {@link RESERVED_META_ENTRY}
|
|
29
|
-
* sidecar, appended LAST so a pure-content bundle stays byte-identical to the
|
|
30
|
-
* pre-fidelity output (dedup continuity).
|
|
31
|
-
*/
|
|
32
|
-
export interface BundleMeta {
|
|
33
|
-
readonly exec?: readonly string[];
|
|
34
|
-
readonly symlinks?: readonly BundleSymlink[];
|
|
35
|
-
}
|
|
36
|
-
export interface ParsedSkillBundle {
|
|
37
|
-
readonly files: SkillFiles;
|
|
38
|
-
readonly meta?: BundleMeta;
|
|
39
|
-
}
|
|
40
|
-
/** Build the canonical single-entry archive used by File/Instructions drafts. */
|
|
41
|
-
export declare function bundleSingleFile(path: string, bytes: Uint8Array, source: string, enforceCompressedLimit?: boolean): Uint8Array;
|
|
42
|
-
/** Remove and parse the reserved fidelity sidecar before canonical rebundling. */
|
|
43
|
-
export declare function splitSkillBundleMetadata(entries: Readonly<Record<string, Uint8Array>>, source: string): ParsedSkillBundle;
|
|
44
|
-
export declare function bundleSkillFiles(files: SkillFiles, meta?: BundleMeta, diagnostics?: "sdk" | "cli"): BundledSkill;
|
|
45
|
-
export interface BundledTool {
|
|
46
|
-
readonly zip: Uint8Array;
|
|
47
|
-
readonly fileCount: number;
|
|
48
|
-
readonly compressedSize: number;
|
|
49
|
-
}
|
|
50
|
-
export interface ToolBundleManifest {
|
|
51
|
-
readonly name: string;
|
|
52
|
-
readonly description: string;
|
|
53
|
-
readonly input_schema: ToolInputSchema;
|
|
54
|
-
readonly entry: string;
|
|
55
|
-
}
|
|
56
|
-
export declare function bundleToolFiles(files: SkillFiles, manifest: ToolBundleManifest, meta?: BundleMeta, diagnostics?: "sdk" | "cli"): BundledTool;
|
|
57
|
-
/**
|
|
58
|
-
* Compute `sha256:<hex>` of the given canonicalised zip bytes. Used by the
|
|
59
|
-
* `Skill.from*` / `File` / `Instructions` factories to populate the draft's
|
|
60
|
-
* `contentHash` field. The hash is advisory — the BFF verifies
|
|
61
|
-
* it against the uploaded zip; a mismatch is rejected. Web-Crypto-only so the
|
|
62
|
-
* SDK works in Bun, Node, edge runtimes, and browsers without polyfills.
|
|
63
|
-
*/
|
|
64
|
-
export declare function hashSkillBundle(zipBytes: Uint8Array, diagnostics?: "sdk" | "cli"): Promise<string>;
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { zipSync } from "fflate";
|
|
2
|
-
import { MAX_SYMLINK_TARGET_LENGTH, RESERVED_META_ENTRY, bundleManifestIsEmpty, tryParseBundleManifest, serializeBundleManifest } from "./bundle-manifest.js";
|
|
3
|
-
import { SKILL_BUNDLE_LIMITS, parseSkillBundleEntry } from "./session-config.js";
|
|
4
|
-
import { assertArchiveCompressedSize, assertArchiveEntryCount, assertArchiveExpandedSize } from "./archive-limits.js";
|
|
5
|
-
import { archiveFileBytesSchema, bundleFidelityMetaSchema, bundleFileContentsSchema, bundleFilesMapSchema, bundleMetadataPathSchema, bundleSymlinkRecordSchema, bundleSymlinkTargetSchema } from "./schemas/asset-bundle.js";
|
|
6
|
-
import { parseWire } from "./schemas/wire.js";
|
|
7
|
-
const TEXT = new TextEncoder();
|
|
8
|
-
/** Build the canonical single-entry archive used by File/Instructions drafts. */
|
|
9
|
-
export function bundleSingleFile(path, bytes, source, enforceCompressedLimit = true) {
|
|
10
|
-
assertArchiveEntryCount(1, source);
|
|
11
|
-
assertArchiveExpandedSize(bytes.byteLength, source);
|
|
12
|
-
const zip = zipSync({ [path]: [bytes, { mtime: ZIP_EPOCH }] }, { level: 6 });
|
|
13
|
-
if (enforceCompressedLimit)
|
|
14
|
-
assertArchiveCompressedSize(zip.byteLength, source);
|
|
15
|
-
return zip;
|
|
16
|
-
}
|
|
17
|
-
/** Remove and parse the reserved fidelity sidecar before canonical rebundling. */
|
|
18
|
-
export function splitSkillBundleMetadata(entries, source) {
|
|
19
|
-
const files = { ...entries };
|
|
20
|
-
const sidecar = files[RESERVED_META_ENTRY];
|
|
21
|
-
delete files[RESERVED_META_ENTRY];
|
|
22
|
-
const collected = collectCanonicalArchiveFiles(files, source);
|
|
23
|
-
if (sidecar === undefined) {
|
|
24
|
-
validateBundleGraph(collected, undefined, source);
|
|
25
|
-
return { files: Object.fromEntries(collected) };
|
|
26
|
-
}
|
|
27
|
-
const manifest = tryParseBundleManifest(sidecar);
|
|
28
|
-
if (manifest === null)
|
|
29
|
-
throw new Error(`${source}: invalid ${RESERVED_META_ENTRY} fidelity metadata`);
|
|
30
|
-
const meta = validateBundleGraph(collected, { exec: manifest.exec, symlinks: manifest.symlinks }, source);
|
|
31
|
-
return { files: Object.fromEntries(collected), ...(meta !== undefined ? { meta } : {}) };
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Build the ordered {@link Zippable} for a collected content map: content entries
|
|
35
|
-
* sorted lexicographically, then (when `meta` carries any exec/symlink) the
|
|
36
|
-
* canonical `.aexmeta.json` sidecar appended LAST. Insertion order is the zip
|
|
37
|
-
* order (fflate iterates keys in insertion order), so the sidecar is always the
|
|
38
|
-
* final entry and a metadata-free bundle is byte-identical to today's output.
|
|
39
|
-
*/
|
|
40
|
-
function buildCanonicalZippable(collected, meta) {
|
|
41
|
-
const sorted = [...collected.entries()].sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
|
|
42
|
-
const zippable = {};
|
|
43
|
-
for (const [path, bytes] of sorted) {
|
|
44
|
-
zippable[path] = [bytes, { mtime: ZIP_EPOCH }];
|
|
45
|
-
}
|
|
46
|
-
let sidecarBytes = 0;
|
|
47
|
-
if (meta && !bundleManifestIsEmpty(meta)) {
|
|
48
|
-
const sidecar = serializeBundleManifest({ v: 1, exec: meta.exec ?? [], symlinks: meta.symlinks ?? [] });
|
|
49
|
-
sidecarBytes = sidecar.byteLength;
|
|
50
|
-
zippable[RESERVED_META_ENTRY] = [sidecar, { mtime: ZIP_EPOCH }];
|
|
51
|
-
}
|
|
52
|
-
return { zippable, sidecarBytes };
|
|
53
|
-
}
|
|
54
|
-
/** Reject a user file colliding with the reserved sidecar name (matches the `tool.json` precedent). */
|
|
55
|
-
function assertNotReservedMetaPath(path, kind) {
|
|
56
|
-
if (path === RESERVED_META_ENTRY) {
|
|
57
|
-
throw new Error(`${kind} files must not include reserved "${RESERVED_META_ENTRY}"; fidelity metadata is emitted by the SDK`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function collectCanonicalArchiveFiles(files, source) {
|
|
61
|
-
const entries = Object.entries(files);
|
|
62
|
-
assertArchiveEntryCount(entries.length, source);
|
|
63
|
-
const collected = new Map();
|
|
64
|
-
for (const [rawPath, bytes] of entries) {
|
|
65
|
-
parseWire(archiveFileBytesSchema(source, rawPath), bytes);
|
|
66
|
-
const path = parseSkillBundleEntry({ path: rawPath, size: bytes.byteLength }).path;
|
|
67
|
-
assertNotReservedMetaPath(path, source);
|
|
68
|
-
if (collected.has(path))
|
|
69
|
-
throw new Error(`${source} contains duplicate path: ${path}`);
|
|
70
|
-
collected.set(path, bytes);
|
|
71
|
-
}
|
|
72
|
-
return collected;
|
|
73
|
-
}
|
|
74
|
-
/** Validate the complete regular-file + fidelity-leaf graph before zipping. */
|
|
75
|
-
function validateBundleGraph(collected, meta, source) {
|
|
76
|
-
assertArchiveEntryCount(collected.size, source);
|
|
77
|
-
const leaves = new Map();
|
|
78
|
-
for (const path of collected.keys())
|
|
79
|
-
leaves.set(path, "regular file");
|
|
80
|
-
if (meta === undefined) {
|
|
81
|
-
assertNoLeafPrefixConflicts(leaves, source);
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
const raw = parseWire(bundleFidelityMetaSchema(source), meta);
|
|
85
|
-
const rawExec = raw.exec ?? [];
|
|
86
|
-
const rawSymlinks = raw.symlinks ?? [];
|
|
87
|
-
assertArchiveEntryCount(rawExec.length, `${source} executable metadata`);
|
|
88
|
-
assertArchiveEntryCount(collected.size + rawSymlinks.length, source);
|
|
89
|
-
const exec = [];
|
|
90
|
-
const execSet = new Set();
|
|
91
|
-
for (const value of rawExec) {
|
|
92
|
-
const path = canonicalMetadataPath(value, source, "executable");
|
|
93
|
-
if (execSet.has(path))
|
|
94
|
-
throw new Error(`${source} contains duplicate executable path: ${path}`);
|
|
95
|
-
if (!collected.has(path)) {
|
|
96
|
-
throw new Error(`${source} executable path ${JSON.stringify(path)} must reference a regular file`);
|
|
97
|
-
}
|
|
98
|
-
execSet.add(path);
|
|
99
|
-
exec.push(path);
|
|
100
|
-
}
|
|
101
|
-
const symlinks = [];
|
|
102
|
-
for (const value of rawSymlinks) {
|
|
103
|
-
parseWire(bundleSymlinkRecordSchema(source), value);
|
|
104
|
-
const record = value;
|
|
105
|
-
const path = canonicalMetadataPath(record.path, source, "symlink");
|
|
106
|
-
const target = parseWire(bundleSymlinkTargetSchema(source, path, MAX_SYMLINK_TARGET_LENGTH), record.target);
|
|
107
|
-
const conflict = leaves.get(path);
|
|
108
|
-
if (conflict !== undefined) {
|
|
109
|
-
throw new Error(`${source} symlink path ${JSON.stringify(path)} conflicts with a ${conflict}`);
|
|
110
|
-
}
|
|
111
|
-
leaves.set(path, "symlink");
|
|
112
|
-
symlinks.push({ path, target });
|
|
113
|
-
}
|
|
114
|
-
assertNoLeafPrefixConflicts(leaves, source);
|
|
115
|
-
return { exec, symlinks };
|
|
116
|
-
}
|
|
117
|
-
function canonicalMetadataPath(value, source, kind) {
|
|
118
|
-
const supplied = parseWire(bundleMetadataPathSchema(source, kind), value);
|
|
119
|
-
let path;
|
|
120
|
-
try {
|
|
121
|
-
path = parseSkillBundleEntry({ path: supplied, size: 0 }).path;
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
throw new Error(`${source} ${kind} path ${JSON.stringify(supplied)} is invalid: ` +
|
|
125
|
-
`${error instanceof Error ? error.message : String(error)}`);
|
|
126
|
-
}
|
|
127
|
-
if (path === RESERVED_META_ENTRY) {
|
|
128
|
-
throw new Error(`${source} ${kind} path must not use reserved ${JSON.stringify(RESERVED_META_ENTRY)}`);
|
|
129
|
-
}
|
|
130
|
-
return path;
|
|
131
|
-
}
|
|
132
|
-
function assertNoLeafPrefixConflicts(leaves, source) {
|
|
133
|
-
for (const path of leaves.keys()) {
|
|
134
|
-
let separator = path.lastIndexOf("/");
|
|
135
|
-
while (separator > 0) {
|
|
136
|
-
const ancestor = path.slice(0, separator);
|
|
137
|
-
if (leaves.has(ancestor)) {
|
|
138
|
-
throw new Error(`${source} leaf prefix conflict: ${JSON.stringify(ancestor)} conflicts with ${JSON.stringify(path)}`);
|
|
139
|
-
}
|
|
140
|
-
separator = ancestor.lastIndexOf("/");
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Canonical pipeline shared by skill and tool authoring. Kind policies own only
|
|
146
|
-
* their required-root checks and any generated regular file; entry coercion,
|
|
147
|
-
* validation, accounting, collection, archive finalization, and counting stay
|
|
148
|
-
* byte-for-byte coupled here.
|
|
149
|
-
*/
|
|
150
|
-
function bundleCanonicalFiles(files, meta, diagnostics, policy) {
|
|
151
|
-
const { kind } = policy;
|
|
152
|
-
const source = `${kind} bundle`;
|
|
153
|
-
parseWire(bundleFilesMapSchema(kind, source, SKILL_BUNDLE_LIMITS.maxFiles), files);
|
|
154
|
-
const entries = Object.entries(files);
|
|
155
|
-
const state = policy.prepare();
|
|
156
|
-
const collected = new Map();
|
|
157
|
-
let totalDecompressed = 0;
|
|
158
|
-
for (const [rawPath, contents] of entries) {
|
|
159
|
-
parseWire(bundleFileContentsSchema(kind, rawPath), contents);
|
|
160
|
-
const bytes = typeof contents === "string" ? TEXT.encode(contents) : contents;
|
|
161
|
-
const entry = parseSkillBundleEntry({ path: rawPath, size: bytes.byteLength });
|
|
162
|
-
assertNotReservedMetaPath(entry.path, source);
|
|
163
|
-
totalDecompressed += bytes.byteLength;
|
|
164
|
-
if (totalDecompressed > SKILL_BUNDLE_LIMITS.maxDecompressedBytes) {
|
|
165
|
-
throw new Error(`${source} exceeds decompressed cap of ${SKILL_BUNDLE_LIMITS.maxDecompressedBytes} bytes`);
|
|
166
|
-
}
|
|
167
|
-
if (collected.has(entry.path)) {
|
|
168
|
-
throw new Error(`${source} contains duplicate path: ${entry.path}`);
|
|
169
|
-
}
|
|
170
|
-
policy.visitEntry(state, entry.path);
|
|
171
|
-
collected.set(entry.path, bytes);
|
|
172
|
-
}
|
|
173
|
-
totalDecompressed += policy.complete(state, collected);
|
|
174
|
-
const validatedMeta = validateBundleGraph(collected, meta, source);
|
|
175
|
-
const { zippable, sidecarBytes } = buildCanonicalZippable(collected, validatedMeta);
|
|
176
|
-
assertArchiveExpandedSize(totalDecompressed + sidecarBytes, source);
|
|
177
|
-
const zip = zipSync(zippable, { level: 6 });
|
|
178
|
-
assertBundleCompressedSize(zip.byteLength, source, diagnostics);
|
|
179
|
-
return { zip, fileCount: collected.size, compressedSize: zip.byteLength };
|
|
180
|
-
}
|
|
181
|
-
export function bundleSkillFiles(files, meta, diagnostics = "sdk") {
|
|
182
|
-
return bundleCanonicalFiles(files, meta, diagnostics, {
|
|
183
|
-
kind: "Skill",
|
|
184
|
-
prepare: () => ({ hasSkillMd: false }),
|
|
185
|
-
visitEntry: (state, path) => {
|
|
186
|
-
if (path === "SKILL.md")
|
|
187
|
-
state.hasSkillMd = true;
|
|
188
|
-
},
|
|
189
|
-
complete: (state) => {
|
|
190
|
-
if (!state.hasSkillMd) {
|
|
191
|
-
throw new Error('Skill bundle must contain a "SKILL.md" file at the root. ' +
|
|
192
|
-
"If you want to upload an instructions file or generic agent context, " +
|
|
193
|
-
"use Instructions.fromPath / File.fromPath instead.");
|
|
194
|
-
}
|
|
195
|
-
return 0;
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
export function bundleToolFiles(files, manifest, meta, diagnostics = "sdk") {
|
|
200
|
-
return bundleCanonicalFiles(files, meta, diagnostics, {
|
|
201
|
-
kind: "Tool",
|
|
202
|
-
prepare: () => ({
|
|
203
|
-
entryPath: parseSkillBundleEntry({ path: manifest.entry, size: 0 }).path,
|
|
204
|
-
hasEntry: false
|
|
205
|
-
}),
|
|
206
|
-
visitEntry: (state, path) => {
|
|
207
|
-
if (path === state.entryPath)
|
|
208
|
-
state.hasEntry = true;
|
|
209
|
-
},
|
|
210
|
-
complete: (state, collected) => {
|
|
211
|
-
if (!state.hasEntry) {
|
|
212
|
-
throw new Error(`Tool bundle entry "${state.entryPath}" must exist in files`);
|
|
213
|
-
}
|
|
214
|
-
const manifestBytes = TEXT.encode(`${JSON.stringify(manifest, null, 2)}\n`);
|
|
215
|
-
if (collected.has("tool.json")) {
|
|
216
|
-
throw new Error('Tool bundle files must not include reserved "tool.json"; pass manifest fields to Tool.fromFiles instead');
|
|
217
|
-
}
|
|
218
|
-
collected.set("tool.json", manifestBytes);
|
|
219
|
-
return manifestBytes.byteLength;
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
const ZIP_EPOCH = new Date(Date.UTC(1980, 0, 1));
|
|
224
|
-
/**
|
|
225
|
-
* Compute `sha256:<hex>` of the given canonicalised zip bytes. Used by the
|
|
226
|
-
* `Skill.from*` / `File` / `Instructions` factories to populate the draft's
|
|
227
|
-
* `contentHash` field. The hash is advisory — the BFF verifies
|
|
228
|
-
* it against the uploaded zip; a mismatch is rejected. Web-Crypto-only so the
|
|
229
|
-
* SDK works in Bun, Node, edge runtimes, and browsers without polyfills.
|
|
230
|
-
*/
|
|
231
|
-
export async function hashSkillBundle(zipBytes, diagnostics = "sdk") {
|
|
232
|
-
const subtle = globalThis.crypto?.subtle;
|
|
233
|
-
if (!subtle) {
|
|
234
|
-
if (diagnostics === "cli") {
|
|
235
|
-
throw new Error("sha256: globalThis.crypto.subtle is not available");
|
|
236
|
-
}
|
|
237
|
-
throw new Error("hashSkillBundle: globalThis.crypto.subtle is not available; Bun, Node 18+, or a Web-Crypto-capable runtime is required");
|
|
238
|
-
}
|
|
239
|
-
// crypto.subtle.digest expects a BufferSource. Pass a freshly-sliced
|
|
240
|
-
// copy to detach from any external Uint8Array view (Web Crypto rejects
|
|
241
|
-
// non-zero byteOffset SharedArrayBuffer views, and view detach also
|
|
242
|
-
// protects against the caller mutating the input after the digest is
|
|
243
|
-
// computed).
|
|
244
|
-
const view = new Uint8Array(zipBytes.byteLength);
|
|
245
|
-
view.set(zipBytes);
|
|
246
|
-
const digest = await subtle.digest("SHA-256", view.buffer);
|
|
247
|
-
return "sha256:" + bufferToHex(digest);
|
|
248
|
-
}
|
|
249
|
-
function assertBundleCompressedSize(size, source, diagnostics) {
|
|
250
|
-
if (diagnostics === "cli" && size > SKILL_BUNDLE_LIMITS.maxCompressedBytes) {
|
|
251
|
-
throw new Error(`bundle exceeds compressed cap of ${SKILL_BUNDLE_LIMITS.maxCompressedBytes} bytes (got ${size})`);
|
|
252
|
-
}
|
|
253
|
-
assertArchiveCompressedSize(size, source);
|
|
254
|
-
}
|
|
255
|
-
function bufferToHex(buffer) {
|
|
256
|
-
const view = new Uint8Array(buffer);
|
|
257
|
-
let out = "";
|
|
258
|
-
for (let i = 0; i < view.length; i++) {
|
|
259
|
-
const byte = view[i];
|
|
260
|
-
out += byte.toString(16).padStart(2, "0");
|
|
261
|
-
}
|
|
262
|
-
return out;
|
|
263
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { type HttpRetryDeps, type HttpRetryOptions } from "./http.js";
|
|
2
|
-
export interface AssetUploadResponse {
|
|
3
|
-
readonly ok: boolean;
|
|
4
|
-
readonly status: number;
|
|
5
|
-
text(): Promise<string>;
|
|
6
|
-
readonly headers?: {
|
|
7
|
-
get(name: string): string | null;
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
/** Minimal fetch shape for direct-to-storage PUT requests. */
|
|
11
|
-
export type AssetFetch = (input: string, init?: RequestInit) => Promise<AssetUploadResponse>;
|
|
12
|
-
export type AssetUploadSleep = NonNullable<HttpRetryDeps["sleep"]>;
|
|
13
|
-
/**
|
|
14
|
-
* The shared {@link HttpRetryOptions} plus the injectable clock/RNG/sleep the
|
|
15
|
-
* upload loops need. Direct-to-storage PUTs use the SAME policy numbers as the
|
|
16
|
-
* API transport — there is no third set of defaults.
|
|
17
|
-
*/
|
|
18
|
-
export interface AssetUploadRetryOptions extends HttpRetryOptions, HttpRetryDeps {
|
|
19
|
-
}
|
|
20
|
-
export declare function putDirectUploadWithRetry(fetchImpl: AssetFetch, uploadUrl: string, init: RequestInit, options?: AssetUploadRetryOptions): Promise<void>;
|
|
21
|
-
/**
|
|
22
|
-
* Object-store PUT retry set: the shared HTTP set from `retry-core.ts`, widened
|
|
23
|
-
* by the two statuses only a storage endpoint emits (408 Request Timeout, 425
|
|
24
|
-
* Too Early) plus the remaining 5xx an S3-compatible endpoint can return.
|
|
25
|
-
*/
|
|
26
|
-
export declare function isRetryableUploadStatus(status: number): boolean;
|
|
27
|
-
/** Every transport rejection except a caller-initiated abort is transient for a PUT. */
|
|
28
|
-
export declare function isRetryableUploadError(err: unknown): boolean;
|
|
29
|
-
export declare function directUploadNetworkError(uploadUrl: string, err: unknown, attempts: number): Error;
|
|
30
|
-
export declare function directUploadResponseError(uploadUrl: string, status: number, detail: string, attempts: number): Error;
|
|
31
|
-
export declare function sanitizeUploadText(text: string): string;
|