@aexhq/sdk 0.23.0 → 0.25.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.
Files changed (44) hide show
  1. package/README.md +36 -125
  2. package/dist/_contracts/models.js +1 -2
  3. package/dist/_contracts/operations.d.ts +2 -2
  4. package/dist/_contracts/operations.js +4 -4
  5. package/dist/_contracts/provider-support.d.ts +23 -23
  6. package/dist/_contracts/provider-support.js +7 -14
  7. package/dist/_contracts/run-config.d.ts +24 -0
  8. package/dist/_contracts/run-config.js +6 -0
  9. package/dist/_contracts/run-trace.d.ts +7 -5
  10. package/dist/_contracts/run-trace.js +7 -5
  11. package/dist/_contracts/run-unit.js +21 -3
  12. package/dist/_contracts/runtime-types.d.ts +7 -8
  13. package/dist/_contracts/submission.d.ts +13 -1
  14. package/dist/_contracts/submission.js +93 -4
  15. package/dist/bundle.d.ts +13 -0
  16. package/dist/bundle.js +51 -0
  17. package/dist/bundle.js.map +1 -1
  18. package/dist/cli.mjs +13 -18
  19. package/dist/cli.mjs.sha256 +1 -1
  20. package/dist/client.d.ts +10 -4
  21. package/dist/client.js +61 -10
  22. package/dist/client.js.map +1 -1
  23. package/dist/index.d.ts +3 -2
  24. package/dist/index.js +3 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/tool.d.ts +41 -0
  27. package/dist/tool.js +138 -0
  28. package/dist/tool.js.map +1 -0
  29. package/dist/version.d.ts +1 -1
  30. package/dist/version.js +1 -1
  31. package/docs/concepts/agent-tools.md +48 -0
  32. package/docs/concepts/composition.md +43 -0
  33. package/docs/concepts/providers-and-runtimes.md +53 -0
  34. package/docs/concepts/runs.md +40 -0
  35. package/docs/credentials.md +3 -1
  36. package/docs/limits.md +44 -0
  37. package/docs/provider-runtime-capabilities.md +52 -54
  38. package/docs/public-surface.json +81 -0
  39. package/docs/quickstart.md +28 -105
  40. package/docs/run-config.md +1 -1
  41. package/docs/secrets.md +123 -0
  42. package/docs/vision-skills.md +3 -6
  43. package/package.json +2 -2
  44. package/docs/product-boundaries.md +0 -57
package/README.md CHANGED
@@ -2,163 +2,74 @@
2
2
  title: aex
3
3
  ---
4
4
 
5
- # aex
5
+ # @aexhq/sdk
6
6
 
7
- aex is a TypeScript-first SDK + CLI for running autonomous agent sessions across providers through the managed aex service. Everything an agent or human needs is reachable through **one** import and **one** binary.
7
+ aex is an agent execution platform for launching autonomous agents from a simple TypeScript SDK and CLI.
8
8
 
9
- ```ts
10
- import {
11
- AgentExecutor, // the only client class — submits durable runs to aex
12
- RunModels, // closed public model id constants
13
- Skill, // local, URL, and catalog skill bundles normalized to assets
14
- McpServer, // MCP server declarations (headers split into secrets server-side)
15
- ProxyEndpoint, // per-run managed HTTP proxy endpoint
16
- AgentsMd, // AGENTS.md / CLAUDE.md uploads
17
- File, // arbitrary workspace files mounted into the session
18
- validateProxyAuth // helper that fails fast on policy/auth mismatch
19
- } from "@aexhq/sdk";
20
- ```
21
-
22
- ```bash
23
- aex run --config ./run.json --api-token ant_… \
24
- --anthropic-api-key sk-ant-… --follow
25
- aex status <run-id> --api-token …
26
- aex wait <run-id> [--timeout 8m] [--interval 2s] --api-token …
27
- aex events <run-id> [--follow] [--timeout 8m] --api-token …
28
- aex outputs <run-id> --api-token …
29
- aex download <run-id> [--only outputs|events|metadata] [--out path] --api-token …
30
- aex cancel <run-id> --api-token …
31
- aex delete <run-id> --api-token …
32
- aex whoami --api-token …
33
- aex skills <upload|list|get|delete> [flags] --api-token …
34
- aex delete-asset <assetId|hash> --api-token …
35
- ```
9
+ The package ships:
36
10
 
37
- The SDK class and the CLI are backed by the same public `@aexhq/contracts` operations module any read or write you can do through one, you can do through the other, against the same durable run records. The same npm package also ships the in-container `aex` CLI as its `bin` entry; managed runs mount that CLI inside the runner so skills can call `aex proxy …` against the per-run manifest. See [product capabilities and boundaries](docs/product-boundaries.md).
11
+ - `AgentExecutor` for submit, run, wait, stream, inspect, download, cancel, and delete.
12
+ - Typed run primitives: `Models`, `Providers`, `RuntimeSizes`, `Skill`, `AgentsMd`, `File`, `McpServer`, `ProxyEndpoint`, and `Secret`.
13
+ - A bundled `aex` CLI with the same run, status, events, outputs, download, cancel, delete, whoami, and skills operations.
38
14
 
39
- The aex URL defaults to `https://api.aex.dev`. Set `--aex-url` on the CLI or `baseUrl` on `AgentExecutor` for local, staging, or hosted aex API planes. This is not a supported self-host deployment claim. The workspace is derived server-side from your API token (1:1 binding), so there is no `--workspace` flag and no `workspaceId` option.
15
+ ## Install
40
16
 
41
- ## Product boundaries
42
-
43
- - Multi-provider via the managed runtime. The published surface is the same
44
- regardless of provider:
45
- - omit `runtime` or pass `runtime: "managed"`; every provider uses the
46
- managed runtime and BYOK provider-proxy.
47
- - `provider: "anthropic" | "deepseek" | "openai" | "gemini" | "mistral"`.
48
- - See [provider/runtime capabilities](docs/provider-runtime-capabilities.md)
49
- for the generated matrix.
50
- - BYO provider key + MCP credentials + skill references — passed inline on every submission and held in run-scoped custody, with cleanup/revocation attempted at terminal. Cross-provider keys are rejected loudly at submission time.
51
- - Workspace is the tenant boundary. Workspace identity is derived server-side from the API token (1:1 binding); the SDK / CLI never name it.
52
- - No SDK-side storage of provider keys, MCP credentials, or output file contents.
53
- - Cleanup runs by default for tracked runtime resources.
54
- - Product boundaries are explicit: see [product capabilities and boundaries](docs/product-boundaries.md) for what aex owns, inherits, and does not support.
17
+ ```bash
18
+ npm install @aexhq/sdk
19
+ ```
55
20
 
56
- ## Quickstart (SDK)
21
+ ## First Run
57
22
 
58
23
  ```ts
59
- import { AgentExecutor, RunModels } from "@aexhq/sdk";
24
+ import { AgentExecutor, Models, Providers } from "@aexhq/sdk";
60
25
 
61
26
  const aex = new AgentExecutor({
62
- apiToken: process.env.AEX_API_TOKEN!,
63
- // baseUrl defaults to https://api.aex.dev - set it for local or staging planes.
27
+ apiToken: process.env.AEX_API_TOKEN!
64
28
  });
65
29
 
66
30
  const runId = await aex.submit({
67
- model: RunModels.CLAUDE_HAIKU_4_5,
68
- system: "You are a concise automation agent.",
69
- prompt: "Write a short answer about agent-first SDK design.",
31
+ provider: Providers.ANTHROPIC,
32
+ model: Models.CLAUDE_HAIKU_4_5,
33
+ prompt: "Write the report and save outputs.",
70
34
  secrets: { apiKey: process.env.ANTHROPIC_API_KEY! }
71
35
  });
72
36
 
73
- const run = await aex.wait(runId);
74
- console.log(run.status);
75
-
76
- for (const output of await aex.outputs(runId)) {
77
- console.log(output.id, output.filename);
78
- }
79
-
80
- const report = await aex.downloadOutput(runId, { path: "report.txt", match: "suffix" });
81
- console.log(new TextDecoder().decode(report));
82
-
83
- await aex.downloadOutputs(runId, { to: "./outputs.zip" });
84
- ```
85
-
86
- Reusable, credential-free configs can be ordinary functions:
87
-
88
- ```ts
89
- function summarise(topic: string) {
90
- return {
91
- model: RunModels.CLAUDE_HAIKU_4_5,
92
- system: "You are a concise automation agent.",
93
- prompt: `Write a short answer about ${topic}.`
94
- };
37
+ for await (const event of aex.stream(runId)) {
38
+ console.log(event.type);
95
39
  }
96
40
 
97
- const runId = await aex.submit({
98
- ...summarise("agent-first SDK design"),
99
- secrets: { apiKey: process.env.ANTHROPIC_API_KEY! }
100
- });
101
- ```
102
-
103
- Stream events live with `aex.stream(runId)`:
41
+ const run = await aex.wait(runId);
42
+ console.log(run.status);
104
43
 
105
- ```ts
106
- for await (const event of aex.stream(runId)) {
107
- if (event.type === "TEXT_MESSAGE_CONTENT") {
108
- // typed event helpers live under `aex`'s event guard exports.
109
- }
110
- }
44
+ await aex.download(runId, { to: "./run.zip" });
111
45
  ```
112
46
 
113
- The same flow from the CLI (two equivalent forms):
47
+ The same request can run from the CLI:
114
48
 
115
49
  ```bash
116
50
  aex run \
117
51
  --api-token "$AEX_API_TOKEN" \
118
52
  --anthropic-api-key "$ANTHROPIC_API_KEY" \
119
53
  --model claude-haiku-4-5 \
120
- --system "You are a concise automation agent." \
121
- --prompt "Write a short answer about agent-first SDK design." \
122
- --follow
123
-
124
- aex run \
125
- --api-token "$AEX_API_TOKEN" \
126
- --anthropic-api-key "$ANTHROPIC_API_KEY" \
127
- --config ./run.json \
54
+ --prompt "Write the report and save outputs." \
128
55
  --follow
129
56
  ```
130
57
 
131
- `--config` accepts a plain run-config JSON file for a single run request: `{ model, system?, prompt, skills?, mcpServers?, environment?, runtimeSize?, timeout?, postHook?, proxyEndpoints?, metadata? }`. There is no saved-definition product or interpolation DSL — build the JSON at the call site. SDK code should use `RunModels`; config JSON is validated against the same `RUN_MODELS` allowlist.
58
+ ## Feature Areas
132
59
 
133
- Runtime controls: omit `builtins` to use the default `["developer"]` toolkit, pass `builtins: []` to disable builtins for a pure-MCP run, use `outputMode: "stream"` for per-token assistant text, prefer `RuntimeSizes` for `runtimeSize`, and use `postHook` to run a verifier command after the agent exits successfully.
60
+ - **Agent runtime:** managed autonomous runs with shell, filesystem, editing, notebook, web fetch/search, background command, and post-hook repair tools.
61
+ - **Durable infrastructure:** run records, status, wait/cancel/delete, idempotency, typed events, output capture, downloads, timeouts, and runtime sizes.
62
+ - **Agent composition:** skills, files, AGENTS.md, remote MCP servers, proxy endpoints, environment variables, packages, and networking controls.
63
+ - **Subagents:** typed parent/child lineage for async child runs, output handoff, and bounded agent delegation.
64
+ - **Models and providers:** Anthropic, DeepSeek, OpenAI, Gemini, Mistral, OpenRouter, Doubao, and Doubao China behind one submission shape.
65
+ - **Typed control surface:** strongly typed SDK inputs, CLI parity, BYOK secrets, scoped proxy auth, redaction, and output modes.
134
66
 
135
- ## Test commands
136
-
137
- ```text
138
- pnpm test # unit (deterministic; uses fakes/snapshots)
139
- pnpm test:user:offline # clean install of packed/published SDK, no live API
140
- pnpm test:user # live hosted API user tests
141
- pnpm test:user:heavy # explicit heavy live canary
142
- ```
143
-
144
- User tests auto-pack the current SDK when no artifact env is set. CI can pin a
145
- specific artifact with exactly one of `AEX_USER_TEST_TARBALL` or
146
- `AEX_USER_TEST_VERSION`; live runs also need `AEX_API_URL`,
147
- `AEX_API_TOKEN`, and `DEEPSEEK_API_KEY`.
148
-
149
- ## Guides
67
+ ## Docs
150
68
 
151
69
  - [Quickstart](docs/quickstart.md)
152
- - [Run config](docs/run-config.md)
153
- - [Run record](docs/run-record.md)
154
- - [Product capabilities and boundaries](docs/product-boundaries.md)
70
+ - [Run configuration](docs/run-config.md)
71
+ - [Agent tools](docs/concepts/agent-tools.md)
72
+ - [Composition](docs/concepts/composition.md)
73
+ - [Secrets](docs/secrets.md)
74
+ - [Limits](docs/limits.md)
155
75
  - [Provider/runtime capabilities](docs/provider-runtime-capabilities.md)
156
- - [Credentials](docs/credentials.md)
157
- - [MCP](docs/mcp.md)
158
- - [Skills](docs/skills.md)
159
- - [Outputs](docs/outputs.md)
160
- - [Events](docs/events.md)
161
- - [Cleanup](docs/cleanup.md)
162
- - [Testing](docs/testing.md)
163
- - [Release](docs/release.md)
164
-
@@ -37,8 +37,7 @@ export const MODEL_PROVIDER_IDS = {
37
37
  // China Volcengine Ark gateway (`doubao-cn`). Ark accepts the API-format
38
38
  // model NAME directly in the chat-completions `model` field (no `ep-…`
39
39
  // inference-endpoint id). The native strings are the same Ark catalog ids on
40
- // both gateways; BytePlus per-account availability is confirmed at live-verify
41
- // (both providers ship `live-unverified` until then — provider-support.ts).
40
+ // both gateways.
42
41
  // pro — Doubao Seed 1.8 (flagship, 256K context).
43
42
  // flash — Doubao Seed 1.6 Flash (fast/cheap, 256K context).
44
43
  "doubao-seed-pro": { doubao: "doubao-seed-1-8-251228", "doubao-cn": "doubao-seed-1-8-251228" },
@@ -215,8 +215,8 @@ export declare function createSecret(http: HttpClient, args: {
215
215
  export declare function listSecrets(http: HttpClient): Promise<readonly SecretRecord[]>;
216
216
  /** Metadata for one workspace secret by name. Never returns the value. */
217
217
  export declare function getSecret(http: HttpClient, name: string): Promise<SecretRecord>;
218
- /** Audited value read — the only path that returns a workspace secret value. */
219
- export declare function revealSecret(http: HttpClient, name: string): Promise<SecretReveal>;
218
+ /** Audited value read — the preferred path that returns a workspace secret value. */
219
+ export declare function getSecretValue(http: HttpClient, name: string): Promise<SecretReveal>;
220
220
  /** Replace the value of an existing workspace secret; bumps its version. */
221
221
  export declare function rotateSecret(http: HttpClient, args: {
222
222
  readonly name: string;
@@ -547,7 +547,7 @@ function unwrapFile(result) {
547
547
  // Value-bearing requests (create/rotate) carry the value in the JSON BODY,
548
548
  // never the URL/query, so it never lands in logs or the request line. Reads
549
549
  // split by sensitivity: `getSecret`/`listSecrets` return METADATA only;
550
- // `revealSecret` is the audited value read (POST so it's a logged action).
550
+ // `getSecretValue` is the audited value read (POST so it's a logged action).
551
551
  // ===========================================================================
552
552
  /** Create a named workspace secret. The value travels in the body. */
553
553
  export async function createSecret(http, args) {
@@ -569,9 +569,9 @@ export async function getSecret(http, name) {
569
569
  const result = await http.request(`/api/secrets/${encodeURIComponent(name)}`);
570
570
  return unwrapSecret(result);
571
571
  }
572
- /** Audited value read — the only path that returns a workspace secret value. */
573
- export async function revealSecret(http, name) {
574
- return http.request(`/api/secrets/${encodeURIComponent(name)}/reveal`, {
572
+ /** Audited value read — the preferred path that returns a workspace secret value. */
573
+ export async function getSecretValue(http, name) {
574
+ return http.request(`/api/secrets/${encodeURIComponent(name)}/get_value`, {
575
575
  method: "POST"
576
576
  });
577
577
  }
@@ -1,5 +1,5 @@
1
1
  import type { RunProvider, RuntimeKind } from "./submission.js";
2
- export declare const PROVIDER_SUPPORT_STATUSES: readonly ["supported", "live-unverified", "rejected"];
2
+ export declare const PROVIDER_SUPPORT_STATUSES: readonly ["supported", "rejected"];
3
3
  export type ProviderSupportStatus = (typeof PROVIDER_SUPPORT_STATUSES)[number];
4
4
  export interface SupportPointer {
5
5
  readonly label: string;
@@ -45,8 +45,8 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
45
45
  readonly status: "supported";
46
46
  readonly docsAnchor: "anthropic";
47
47
  readonly docs: readonly [{
48
- readonly label: "Credentials";
49
- readonly href: "credentials.md";
48
+ readonly label: "Secrets";
49
+ readonly href: "secrets.md";
50
50
  }, {
51
51
  readonly label: "Events";
52
52
  readonly href: "events.md";
@@ -82,8 +82,8 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
82
82
  readonly status: "supported";
83
83
  readonly docsAnchor: "deepseek";
84
84
  readonly docs: readonly [{
85
- readonly label: "Credentials";
86
- readonly href: "credentials.md";
85
+ readonly label: "Secrets";
86
+ readonly href: "secrets.md";
87
87
  }, {
88
88
  readonly label: "Events";
89
89
  readonly href: "events.md";
@@ -122,11 +122,11 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
122
122
  };
123
123
  readonly openai: {
124
124
  readonly displayName: "OpenAI";
125
- readonly status: "live-unverified";
125
+ readonly status: "supported";
126
126
  readonly docsAnchor: "openai";
127
127
  readonly docs: readonly [{
128
- readonly label: "Credentials";
129
- readonly href: "credentials.md";
128
+ readonly label: "Secrets";
129
+ readonly href: "secrets.md";
130
130
  }, {
131
131
  readonly label: "Events";
132
132
  readonly href: "events.md";
@@ -156,11 +156,11 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
156
156
  };
157
157
  readonly gemini: {
158
158
  readonly displayName: "Gemini";
159
- readonly status: "live-unverified";
159
+ readonly status: "supported";
160
160
  readonly docsAnchor: "gemini";
161
161
  readonly docs: readonly [{
162
- readonly label: "Credentials";
163
- readonly href: "credentials.md";
162
+ readonly label: "Secrets";
163
+ readonly href: "secrets.md";
164
164
  }, {
165
165
  readonly label: "Events";
166
166
  readonly href: "events.md";
@@ -190,11 +190,11 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
190
190
  };
191
191
  readonly mistral: {
192
192
  readonly displayName: "Mistral";
193
- readonly status: "live-unverified";
193
+ readonly status: "supported";
194
194
  readonly docsAnchor: "mistral";
195
195
  readonly docs: readonly [{
196
- readonly label: "Credentials";
197
- readonly href: "credentials.md";
196
+ readonly label: "Secrets";
197
+ readonly href: "secrets.md";
198
198
  }, {
199
199
  readonly label: "Events";
200
200
  readonly href: "events.md";
@@ -224,11 +224,11 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
224
224
  };
225
225
  readonly openrouter: {
226
226
  readonly displayName: "OpenRouter";
227
- readonly status: "live-unverified";
227
+ readonly status: "supported";
228
228
  readonly docsAnchor: "openrouter";
229
229
  readonly docs: readonly [{
230
- readonly label: "Credentials";
231
- readonly href: "credentials.md";
230
+ readonly label: "Secrets";
231
+ readonly href: "secrets.md";
232
232
  }, {
233
233
  readonly label: "Events";
234
234
  readonly href: "events.md";
@@ -258,11 +258,11 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
258
258
  };
259
259
  readonly doubao: {
260
260
  readonly displayName: "Doubao";
261
- readonly status: "live-unverified";
261
+ readonly status: "supported";
262
262
  readonly docsAnchor: "doubao";
263
263
  readonly docs: readonly [{
264
- readonly label: "Credentials";
265
- readonly href: "credentials.md";
264
+ readonly label: "Secrets";
265
+ readonly href: "secrets.md";
266
266
  }, {
267
267
  readonly label: "Events";
268
268
  readonly href: "events.md";
@@ -292,11 +292,11 @@ export declare const PROVIDER_PUBLIC_SUPPORT: {
292
292
  };
293
293
  readonly "doubao-cn": {
294
294
  readonly displayName: "Doubao (China)";
295
- readonly status: "live-unverified";
295
+ readonly status: "supported";
296
296
  readonly docsAnchor: "doubao-cn";
297
297
  readonly docs: readonly [{
298
- readonly label: "Credentials";
299
- readonly href: "credentials.md";
298
+ readonly label: "Secrets";
299
+ readonly href: "secrets.md";
300
300
  }, {
301
301
  readonly label: "Events";
302
302
  readonly href: "events.md";
@@ -1,10 +1,9 @@
1
1
  export const PROVIDER_SUPPORT_STATUSES = [
2
2
  "supported",
3
- "live-unverified",
4
3
  "rejected"
5
4
  ];
6
5
  const COMMON_DOCS = [
7
- { label: "Credentials", href: "credentials.md" },
6
+ { label: "Secrets", href: "secrets.md" },
8
7
  { label: "Events", href: "events.md" }
9
8
  ];
10
9
  const COMMON_EVIDENCE = [
@@ -72,7 +71,7 @@ export const PROVIDER_PUBLIC_SUPPORT = {
72
71
  },
73
72
  openai: {
74
73
  displayName: "OpenAI",
75
- status: "live-unverified",
74
+ status: "supported",
76
75
  docsAnchor: "openai",
77
76
  docs: COMMON_DOCS,
78
77
  evidence: COMMON_EVIDENCE,
@@ -82,7 +81,7 @@ export const PROVIDER_PUBLIC_SUPPORT = {
82
81
  },
83
82
  gemini: {
84
83
  displayName: "Gemini",
85
- status: "live-unverified",
84
+ status: "supported",
86
85
  docsAnchor: "gemini",
87
86
  docs: COMMON_DOCS,
88
87
  evidence: COMMON_EVIDENCE,
@@ -92,7 +91,7 @@ export const PROVIDER_PUBLIC_SUPPORT = {
92
91
  },
93
92
  mistral: {
94
93
  displayName: "Mistral",
95
- status: "live-unverified",
94
+ status: "supported",
96
95
  docsAnchor: "mistral",
97
96
  docs: COMMON_DOCS,
98
97
  evidence: COMMON_EVIDENCE,
@@ -102,7 +101,7 @@ export const PROVIDER_PUBLIC_SUPPORT = {
102
101
  },
103
102
  openrouter: {
104
103
  displayName: "OpenRouter",
105
- status: "live-unverified",
104
+ status: "supported",
106
105
  docsAnchor: "openrouter",
107
106
  docs: COMMON_DOCS,
108
107
  evidence: COMMON_EVIDENCE,
@@ -111,13 +110,9 @@ export const PROVIDER_PUBLIC_SUPPORT = {
111
110
  }
112
111
  },
113
112
  // Doubao (ByteDance) via the official Ark API — international BytePlus gateway.
114
- // Wired + parser/routing-verified but not yet proven against a live BytePlus
115
- // account, so `live-unverified`. Promote to `supported` (and swap COMMON_EVIDENCE
116
- // for a DOUBAO_MANAGED_EVIDENCE pointer to live-sdk-doubao.test.ts) once the
117
- // live run passes.
118
113
  doubao: {
119
114
  displayName: "Doubao",
120
- status: "live-unverified",
115
+ status: "supported",
121
116
  docsAnchor: "doubao",
122
117
  docs: COMMON_DOCS,
123
118
  evidence: COMMON_EVIDENCE,
@@ -126,11 +121,9 @@ export const PROVIDER_PUBLIC_SUPPORT = {
126
121
  }
127
122
  },
128
123
  // Doubao (ByteDance) via the official Ark API — China Volcengine gateway.
129
- // Same wiring as `doubao`; additionally gated on CF Worker egress reaching the
130
- // Beijing host (see apps/egress-probe). `live-unverified` until proven live.
131
124
  "doubao-cn": {
132
125
  displayName: "Doubao (China)",
133
- status: "live-unverified",
126
+ status: "supported",
134
127
  docsAnchor: "doubao-cn",
135
128
  docs: COMMON_DOCS,
136
129
  evidence: COMMON_EVIDENCE,
@@ -47,6 +47,12 @@ export declare const SKILL_ID_PATTERN: RegExp;
47
47
  * surface so callers fail at the boundary rather than in the BFF.
48
48
  */
49
49
  export declare const SKILL_NAME_PATTERN: RegExp;
50
+ /**
51
+ * Provider-safe submitted tool name. Tool names share the same lowercase
52
+ * kebab/underscore envelope as skills. Submission parsing rejects `__`
53
+ * because SessionDO reserves that separator for MCP namespace routing.
54
+ */
55
+ export declare const TOOL_NAME_PATTERN: RegExp;
50
56
  /**
51
57
  * Hard caps applied at upload time. The SDK enforces these before
52
58
  * computing the zip hash so a clearly-too-big bundle never wastes
@@ -87,6 +93,23 @@ export interface AssetRef {
87
93
  readonly name: string;
88
94
  readonly mountPath?: string;
89
95
  }
96
+ type ToolJsonPrimitive = string | number | boolean | null;
97
+ type ToolJsonValue = ToolJsonPrimitive | ToolJsonValue[] | {
98
+ readonly [key: string]: ToolJsonValue;
99
+ };
100
+ export type ToolInputSchema = {
101
+ readonly [key: string]: ToolJsonValue;
102
+ };
103
+ /**
104
+ * User-supplied executable tool bundle. The bytes are addressed by the same
105
+ * content-addressed asset ref used by Skills/Files, while the provider-visible
106
+ * manifest rides as value-free metadata on the submission.
107
+ */
108
+ export interface ToolRef extends AssetRef {
109
+ readonly description: string;
110
+ readonly input_schema: ToolInputSchema;
111
+ readonly entry: string;
112
+ }
90
113
  export interface ProviderSkillRef {
91
114
  readonly kind: "provider";
92
115
  readonly vendor: "anthropic" | "custom";
@@ -330,3 +353,4 @@ export interface NormalisedRunRequestConfig {
330
353
  }>;
331
354
  }
332
355
  export declare function normaliseRunRequestConfig(config: RunRequestConfig): NormalisedRunRequestConfig;
356
+ export {};
@@ -48,6 +48,12 @@ export const SKILL_ID_PATTERN = /^skl_[A-Za-z0-9_-]{8,128}$/;
48
48
  * surface so callers fail at the boundary rather than in the BFF.
49
49
  */
50
50
  export const SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]{0,127}$/;
51
+ /**
52
+ * Provider-safe submitted tool name. Tool names share the same lowercase
53
+ * kebab/underscore envelope as skills. Submission parsing rejects `__`
54
+ * because SessionDO reserves that separator for MCP namespace routing.
55
+ */
56
+ export const TOOL_NAME_PATTERN = SKILL_NAME_PATTERN;
51
57
  // ---------------------------------------------------------------------------
52
58
  // Skill bundle limits (uploaded bundles)
53
59
  // ---------------------------------------------------------------------------
@@ -13,9 +13,10 @@
13
13
  * a result with no matching start surfaces as an orphan (never dropped silently),
14
14
  * and timing falls back gracefully when a `recordedAt` is absent.
15
15
  *
16
- * Pairs with {@link Run.usage}: while a run executes `Run.usage` is empty — the
17
- * per-turn token counts live ONLY in the `aex.usage` CUSTOM events so
18
- * {@link summarizeRunUsage} reconstructs the running total from the same stream.
16
+ * `summarizeRunUsage` remains tolerant of historical/internal `aex.usage`
17
+ * CUSTOM records when a caller has them, but the normal public `listEvents`
18
+ * stream is not the live usage-reporting surface. Settled provider/runtime
19
+ * usage is exposed through the run's `costTelemetry`.
19
20
  */
20
21
  import type { UsageSummary } from "./runtime-types.js";
21
22
  /**
@@ -89,8 +90,9 @@ interface TraceEvent {
89
90
  */
90
91
  export declare function decodeToolCalls(events: readonly TraceEvent[]): readonly ToolCallTrace[];
91
92
  /**
92
- * Sum the per-turn `aex.usage` CUSTOM events into one {@link UsageSummary}
93
- * the running token total a customer otherwise hand-sums while watching a run.
93
+ * Sum any `aex.usage` CUSTOM events present in the supplied stream into one
94
+ * {@link UsageSummary}. This is mainly for historical/internal event arrays;
95
+ * current public reads expose settled provider usage through cost telemetry.
94
96
  * `totalTokens` is the sum of input + output tokens. Pure.
95
97
  */
96
98
  export declare function summarizeRunUsage(events: readonly TraceEvent[]): UsageSummary;
@@ -13,9 +13,10 @@
13
13
  * a result with no matching start surfaces as an orphan (never dropped silently),
14
14
  * and timing falls back gracefully when a `recordedAt` is absent.
15
15
  *
16
- * Pairs with {@link Run.usage}: while a run executes `Run.usage` is empty — the
17
- * per-turn token counts live ONLY in the `aex.usage` CUSTOM events so
18
- * {@link summarizeRunUsage} reconstructs the running total from the same stream.
16
+ * `summarizeRunUsage` remains tolerant of historical/internal `aex.usage`
17
+ * CUSTOM records when a caller has them, but the normal public `listEvents`
18
+ * stream is not the live usage-reporting surface. Settled provider/runtime
19
+ * usage is exposed through the run's `costTelemetry`.
19
20
  */
20
21
  const CUSTOM_USAGE_NAME = "aex.usage";
21
22
  /** snake_case `aex.usage` field → the camelCase {@link UsageSummary} field. */
@@ -89,8 +90,9 @@ export function decodeToolCalls(events) {
89
90
  return order.map((id) => byId.get(id));
90
91
  }
91
92
  /**
92
- * Sum the per-turn `aex.usage` CUSTOM events into one {@link UsageSummary}
93
- * the running token total a customer otherwise hand-sums while watching a run.
93
+ * Sum any `aex.usage` CUSTOM events present in the supplied stream into one
94
+ * {@link UsageSummary}. This is mainly for historical/internal event arrays;
95
+ * current public reads expose settled provider usage through cost telemetry.
94
96
  * `totalTokens` is the sum of input + output tokens. Pure.
95
97
  */
96
98
  export function summarizeRunUsage(events) {
@@ -52,6 +52,10 @@ function parseFlatProjection(value) {
52
52
  const outputsRaw = isRecord(submissionRaw.outputs) ? submissionRaw.outputs : {};
53
53
  const allowedDirs = toOptionalStringArray(outputsRaw.allowedDirs);
54
54
  const deniedDirs = toOptionalStringArray(outputsRaw.deniedDirs);
55
+ const captureTimeoutMs = toOptionalPositiveInteger(outputsRaw.captureTimeoutMs);
56
+ const maxFileBytes = toOptionalPositiveInteger(outputsRaw.maxFileBytes);
57
+ const maxTotalBytes = toOptionalPositiveInteger(outputsRaw.maxTotalBytes);
58
+ const maxFiles = toOptionalPositiveInteger(outputsRaw.maxFiles);
55
59
  const submission = {
56
60
  model: coerceRunUnitModel(submissionRaw.model),
57
61
  ...(typeof submissionRaw.system === "string" ? { system: submissionRaw.system } : {}),
@@ -60,6 +64,7 @@ function parseFlatProjection(value) {
60
64
  agentsMd: [],
61
65
  files: [],
62
66
  mcpServers: toMcpServerRefArray(submissionRaw.mcpServers),
67
+ tools: [],
63
68
  ...(parseEnvironment(submissionRaw.environment)
64
69
  ? { environment: parseEnvironment(submissionRaw.environment) }
65
70
  : {}),
@@ -67,11 +72,20 @@ function parseFlatProjection(value) {
67
72
  ? { securityProfile: parseSecurityProfile(submissionRaw.securityProfile) }
68
73
  : {}),
69
74
  ...(isJsonRecord(submissionRaw.metadata) ? { metadata: submissionRaw.metadata } : {}),
70
- ...(allowedDirs || deniedDirs
75
+ ...(allowedDirs ||
76
+ deniedDirs ||
77
+ captureTimeoutMs !== undefined ||
78
+ maxFileBytes !== undefined ||
79
+ maxTotalBytes !== undefined ||
80
+ maxFiles !== undefined
71
81
  ? {
72
82
  outputs: {
73
83
  ...(allowedDirs ? { allowedDirs } : {}),
74
- ...(deniedDirs ? { deniedDirs } : {})
84
+ ...(deniedDirs ? { deniedDirs } : {}),
85
+ ...(captureTimeoutMs !== undefined ? { captureTimeoutMs } : {}),
86
+ ...(maxFileBytes !== undefined ? { maxFileBytes } : {}),
87
+ ...(maxTotalBytes !== undefined ? { maxTotalBytes } : {}),
88
+ ...(maxFiles !== undefined ? { maxFiles } : {})
75
89
  }
76
90
  }
77
91
  : {})
@@ -84,6 +98,9 @@ function parseFlatProjection(value) {
84
98
  function parseSecurityProfile(value) {
85
99
  return value === "strict" || value === "standard" || value === "developer" ? value : undefined;
86
100
  }
101
+ function toOptionalPositiveInteger(value) {
102
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
103
+ }
87
104
  function fallbackFlat() {
88
105
  return {
89
106
  kind: "submission",
@@ -93,7 +110,8 @@ function fallbackFlat() {
93
110
  skills: [],
94
111
  agentsMd: [],
95
112
  files: [],
96
- mcpServers: []
113
+ mcpServers: [],
114
+ tools: []
97
115
  }
98
116
  };
99
117
  }
@@ -27,12 +27,11 @@ export interface Run {
27
27
  readonly startedAt?: string;
28
28
  readonly errorMessage?: string | null;
29
29
  /**
30
- * Aggregate token usage. NOTE: mid-run this is NOT populated detailed
31
- * token counts live ONLY in the per-turn `aex.usage` CUSTOM events on the
32
- * event stream until the run settles. To follow token/cost progress while a
33
- * run executes, decode the event stream with `summarizeRunTrace(events)`
34
- * (its `usage` totals the `aex.usage` events). Settled cost/usage rides
35
- * {@link costTelemetry}.
30
+ * Aggregate token usage when a deployment chooses to expose it on the run
31
+ * record. Mid-run this is not populated. Settled provider/runtime usage is
32
+ * exposed through {@link costTelemetry}; per-turn usage breadcrumbs, when a
33
+ * deployment records them internally, are not part of the normal public event
34
+ * stream.
36
35
  */
37
36
  readonly usage?: UsageSummary;
38
37
  readonly costTelemetry?: import("./run-cost.js").RunCostTelemetry;
@@ -251,8 +250,8 @@ export interface SecretRecord {
251
250
  readonly [key: string]: unknown;
252
251
  }
253
252
  /**
254
- * Value-bearing result of an audited `aex.secrets.reveal`. The ONLY wire shape
255
- * that carries a workspace secret value back to the caller. Reveal is a logged
253
+ * Value-bearing result of an audited `aex.secrets.get_value`. The ONLY wire shape
254
+ * that carries a workspace secret value back to the caller. Value read is a logged
256
255
  * action (POST, not GET) so a value read is always attributable.
257
256
  */
258
257
  export interface SecretReveal {