@aexhq/sdk 0.40.16 → 0.41.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/README.md +25 -25
- package/dist/_contracts/api-key.d.ts +6 -4
- package/dist/_contracts/api-key.js +20 -7
- package/dist/_contracts/connection-ticket.d.ts +5 -5
- package/dist/_contracts/connection-ticket.js +7 -7
- package/dist/_contracts/error-codes.d.ts +1 -1
- package/dist/_contracts/error-codes.js +4 -4
- package/dist/_contracts/error-factory.js +1 -1
- package/dist/_contracts/event-envelope.d.ts +41 -41
- package/dist/_contracts/event-envelope.js +49 -49
- package/dist/_contracts/event-stream-client.d.ts +9 -9
- package/dist/_contracts/event-stream-client.js +5 -5
- package/dist/_contracts/event-view.d.ts +6 -6
- package/dist/_contracts/event-view.js +12 -12
- package/dist/_contracts/http.js +1 -1
- package/dist/_contracts/index.d.ts +10 -10
- package/dist/_contracts/index.js +9 -9
- package/dist/_contracts/models.d.ts +17 -17
- package/dist/_contracts/models.js +14 -14
- package/dist/_contracts/operations.d.ts +79 -82
- package/dist/_contracts/operations.js +233 -243
- package/dist/_contracts/provider-support.d.ts +2 -2
- package/dist/_contracts/runner-event.d.ts +8 -8
- package/dist/_contracts/runner-event.js +9 -9
- package/dist/_contracts/runtime-manifest.d.ts +12 -12
- package/dist/_contracts/runtime-manifest.js +1 -1
- package/dist/_contracts/runtime-sizes.d.ts +12 -12
- package/dist/_contracts/runtime-sizes.js +18 -18
- package/dist/_contracts/runtime-types.d.ts +117 -117
- package/dist/_contracts/runtime-types.js +2 -2
- package/dist/_contracts/sdk-errors.d.ts +3 -3
- package/dist/_contracts/sdk-errors.js +4 -4
- package/dist/_contracts/sdk-secrets.js +10 -10
- package/dist/_contracts/session-artifacts.d.ts +151 -0
- package/dist/_contracts/session-artifacts.js +234 -0
- package/dist/_contracts/{run-config.d.ts → session-config.d.ts} +29 -29
- package/dist/_contracts/{run-config.js → session-config.js} +37 -37
- package/dist/_contracts/session-cost.d.ts +140 -0
- package/dist/_contracts/{run-cost.js → session-cost.js} +94 -94
- package/dist/_contracts/{run-custody.d.ts → session-custody.d.ts} +16 -16
- package/dist/_contracts/{run-custody.js → session-custody.js} +42 -42
- package/dist/_contracts/session-record.d.ts +112 -0
- package/dist/_contracts/{run-record.js → session-record.js} +23 -23
- package/dist/_contracts/session-retention.d.ts +209 -0
- package/dist/_contracts/{run-retention.js → session-retention.js} +116 -116
- package/dist/_contracts/{run-unit.d.ts → session-unit.d.ts} +38 -38
- package/dist/_contracts/{run-unit.js → session-unit.js} +33 -33
- package/dist/_contracts/side-effect-audit.d.ts +14 -14
- package/dist/_contracts/side-effect-audit.js +38 -38
- package/dist/_contracts/sse.d.ts +1 -1
- package/dist/_contracts/sse.js +0 -0
- package/dist/_contracts/stable.d.ts +1 -1
- package/dist/_contracts/stable.js +1 -1
- package/dist/_contracts/status.d.ts +18 -18
- package/dist/_contracts/status.js +19 -19
- package/dist/_contracts/submission.d.ts +101 -99
- package/dist/_contracts/submission.js +96 -96
- package/dist/_contracts/{run-trace.d.ts → turn-trace.d.ts} +1 -1
- package/dist/_contracts/webhook-verify.d.ts +1 -1
- package/dist/_contracts/webhook-verify.js +1 -1
- package/dist/agents-md.d.ts +4 -4
- package/dist/agents-md.js +5 -5
- package/dist/agents-md.js.map +1 -1
- package/dist/bundle.d.ts +1 -1
- package/dist/bundle.js +1 -1
- package/dist/bundle.js.map +1 -1
- package/dist/cli.mjs +578 -621
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +141 -155
- package/dist/client.js +236 -245
- package/dist/client.js.map +1 -1
- package/dist/fetch-archive.js +3 -3
- package/dist/file.d.ts +7 -7
- package/dist/file.js +8 -8
- package/dist/file.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +1 -1
- package/dist/retry.d.ts +1 -1
- package/dist/secret.d.ts +6 -6
- package/dist/secret.js +6 -6
- package/dist/secret.js.map +1 -1
- package/dist/skill.d.ts +2 -2
- package/dist/skill.js +3 -3
- package/dist/skill.js.map +1 -1
- package/dist/tool.js +2 -2
- package/dist/tool.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/authentication.md +11 -11
- package/docs/billing.md +3 -3
- package/docs/cleanup.md +5 -5
- package/docs/concepts/agent-tools.md +5 -5
- package/docs/concepts/composition.md +3 -3
- package/docs/concepts/providers-and-runtimes.md +3 -3
- package/docs/concepts/{runs.md → sessions.md} +8 -8
- package/docs/concepts/subagents.md +16 -16
- package/docs/credentials.md +7 -7
- package/docs/defaults.md +14 -14
- package/docs/errors.md +10 -10
- package/docs/events.md +26 -26
- package/docs/files.md +267 -0
- package/docs/limits-and-quotas.md +35 -35
- package/docs/limits.md +6 -6
- package/docs/mcp.md +3 -3
- package/docs/networking.md +24 -24
- package/docs/provider-runtime-capabilities.md +1 -1
- package/docs/public-surface.json +6 -6
- package/docs/quickstart.md +13 -13
- package/docs/release.md +5 -5
- package/docs/retries.md +3 -3
- package/docs/secrets.md +16 -16
- package/docs/session-config.md +58 -0
- package/docs/{run-record.md → session-record.md} +16 -16
- package/docs/skills.md +9 -9
- package/docs/vision-skills.md +7 -7
- package/docs/webhooks.md +11 -11
- package/examples/feature-tour.ts +17 -17
- package/examples/spike-settle-latency.ts +11 -11
- package/package.json +1 -1
- package/dist/_contracts/run-artifacts.d.ts +0 -49
- package/dist/_contracts/run-artifacts.js +0 -102
- package/dist/_contracts/run-cost.d.ts +0 -140
- package/dist/_contracts/run-record.d.ts +0 -116
- package/dist/_contracts/run-retention.d.ts +0 -209
- package/docs/outputs.md +0 -267
- package/docs/run-config.md +0 -58
- /package/dist/_contracts/{run-trace.js → turn-trace.js} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Subagents
|
|
3
|
-
description: Delegate bounded sub-tasks to child agent
|
|
3
|
+
description: Delegate bounded sub-tasks to child agent sessions with the subagent tool.
|
|
4
4
|
icon: GitFork
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
A
|
|
7
|
+
A session can delegate bounded sub-tasks to **child agent sessions** with the built-in
|
|
8
8
|
`subagent` tool. Delegation is agent-driven: the model decides to fan work out,
|
|
9
|
-
each child is a real
|
|
9
|
+
each child is a real session with its own record, and the parent collects results
|
|
10
10
|
as the children finish. There is no client-side parent/child API — lineage is
|
|
11
11
|
session-internal.
|
|
12
12
|
|
|
@@ -16,9 +16,9 @@ The agent calls `subagent` with a `prompt` and a `model` (both required), plus
|
|
|
16
16
|
optional `system`, `provider`, `runtimeSize`, `timeout`,
|
|
17
17
|
`includeBuiltinTools`, `tools` (builtin-tool names for the child), `skills`,
|
|
18
18
|
and `files`. The call is **always async**: on a successful spawn it returns
|
|
19
|
-
immediately with the child
|
|
20
|
-
|
|
21
|
-
the child's status and captured
|
|
19
|
+
immediately with the child session id, and the parent keeps working while the child
|
|
20
|
+
sessions. When a child settles, the parent is notified in its loop, and it reads
|
|
21
|
+
the child's status and captured files on demand with the companion
|
|
22
22
|
`subagent_result` tool.
|
|
23
23
|
|
|
24
24
|
Children inherit the parent's vaulted BYOK provider keys server-side — the
|
|
@@ -46,7 +46,7 @@ dials today.
|
|
|
46
46
|
|
|
47
47
|
## Where children run: `in-process` vs `container`
|
|
48
48
|
|
|
49
|
-
By default a child
|
|
49
|
+
By default a child sessions **in-process**: it executes as a sibling agent process
|
|
50
50
|
inside the parent's own machine, sharing the parent's CPU, memory, and
|
|
51
51
|
lifetime. This is the platform default shipped today.
|
|
52
52
|
|
|
@@ -60,7 +60,7 @@ lifetime. This is the platform default shipped today.
|
|
|
60
60
|
- **Joined lifecycle.** The parent's terminal waits for its in-process children,
|
|
61
61
|
and their results are folded into the parent's per-child accounting. Platform
|
|
62
62
|
recovery re-spawns in-process children exactly once if the parent's machine
|
|
63
|
-
is replaced mid-
|
|
63
|
+
is replaced mid-session — settled children are never retry.
|
|
64
64
|
|
|
65
65
|
The escape valve is `host: "container"`: the child is dispatched to its **own
|
|
66
66
|
isolated machine** with its own runtime size and its own runtime billing, and
|
|
@@ -70,21 +70,21 @@ the parent can share.
|
|
|
70
70
|
|
|
71
71
|
## Lineage and observability
|
|
72
72
|
|
|
73
|
-
Every child — in-process or container — is a first-class
|
|
73
|
+
Every child — in-process or container — is a first-class session record:
|
|
74
74
|
|
|
75
|
-
- The parent's transcript logs each spawn with the child's
|
|
76
|
-
- Each child has its own status, typed event timeline, and captured
|
|
77
|
-
The child's events and
|
|
78
|
-
(`aex.sessions.
|
|
79
|
-
`aex
|
|
75
|
+
- The parent's transcript logs each spawn with the child's session id.
|
|
76
|
+
- Each child has its own status, typed event timeline, and captured files.
|
|
77
|
+
The child's events and files are readable by id
|
|
78
|
+
(`aex.sessions.files(id)` in the SDK, or the CLI's `aex events` /
|
|
79
|
+
`aex files`). Child sessions are not served by the session read surface
|
|
80
80
|
today — `aex.sessions.get(id)` / `aex sessions` / the CLI's `aex status`
|
|
81
81
|
answer `not_found` for a child id.
|
|
82
|
-
- The child's
|
|
82
|
+
- The child's files are handed back to the parent via `subagent_result`, and
|
|
83
83
|
they remain independently downloadable after the lineage finishes.
|
|
84
84
|
|
|
85
85
|
## Bounding delegation
|
|
86
86
|
|
|
87
|
-
- Turn delegation off for a
|
|
87
|
+
- Turn delegation off for a session by cherry-picking builtins without `subagent`
|
|
88
88
|
(see [Agent tools](agent-tools.md)) or setting `includeBuiltinTools: false`.
|
|
89
89
|
- A per-session spend cap (`overrides.maxSpendUsd`) bounds the parent's spend.
|
|
90
90
|
- The depth/breadth budgets above are platform-managed and are not settable
|
package/docs/credentials.md
CHANGED
|
@@ -11,7 +11,7 @@ aex uses explicit, per-session credentials:
|
|
|
11
11
|
- `McpServer.remote(..., { headers })` carries MCP auth when a remote MCP server needs it.
|
|
12
12
|
- `environment.secrets` carries runtime secrets for your own code.
|
|
13
13
|
|
|
14
|
-
Secrets never belong in reusable
|
|
14
|
+
Secrets never belong in reusable session config, files, prompts, or examples.
|
|
15
15
|
|
|
16
16
|
## The client credential
|
|
17
17
|
|
|
@@ -35,7 +35,7 @@ A session selects one upstream provider and must carry a BYOK key for it. Includ
|
|
|
35
35
|
additional provider keys only when subagents may use those providers.
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
|
-
const result = await aex.
|
|
38
|
+
const result = await aex.start({
|
|
39
39
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
40
40
|
message: "Write a short report and save it as a file.",
|
|
41
41
|
apiKeys: {
|
|
@@ -58,7 +58,7 @@ import { Aex, Models, Secret } from "@aexhq/sdk";
|
|
|
58
58
|
|
|
59
59
|
const aex = new Aex({ apiKey: process.env.AEX_API_KEY! });
|
|
60
60
|
|
|
61
|
-
await aex.
|
|
61
|
+
await aex.start({
|
|
62
62
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
63
63
|
message: "Call https://api.example.com/v1/status with INTERNAL_API_TOKEN and summarize it.",
|
|
64
64
|
environment: {
|
|
@@ -74,7 +74,7 @@ await aex.run({
|
|
|
74
74
|
});
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
Inside the
|
|
77
|
+
Inside the session, use normal HTTP code for the service:
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
80
|
curl -sS \
|
|
@@ -86,7 +86,7 @@ curl -sS \
|
|
|
86
86
|
|
|
87
87
|
> **Availability note:** workspace-secret `Secret.ref(...)` injection requires
|
|
88
88
|
> the next platform deploy — on the current hosted plane the referenced
|
|
89
|
-
> variable can resolve empty inside the
|
|
89
|
+
> variable can resolve empty inside the session. Per-session `Secret.value(...)`
|
|
90
90
|
> secrets are unaffected.
|
|
91
91
|
|
|
92
92
|
Store reusable values once, then reference them by name:
|
|
@@ -97,7 +97,7 @@ await aex.secrets.set({
|
|
|
97
97
|
value: process.env.INTERNAL_API_TOKEN!
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
await aex.
|
|
100
|
+
await aex.start({
|
|
101
101
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
102
102
|
message: "Use INTERNAL_API_TOKEN for the status request.",
|
|
103
103
|
environment: {
|
|
@@ -115,7 +115,7 @@ Secret reads return metadata only; they never return the stored value.
|
|
|
115
115
|
|
|
116
116
|
Networking is open by default within the platform's managed egress ceiling. Use
|
|
117
117
|
`environment.networking.mode: "limited"` with `allowedHosts` when you want a
|
|
118
|
-
|
|
118
|
+
session's own code to reach only named hosts. See [Networking](networking.md) for
|
|
119
119
|
the two-layer enforcement model.
|
|
120
120
|
|
|
121
121
|
## Explicit call-site rule
|
package/docs/defaults.md
CHANGED
|
@@ -5,7 +5,7 @@ title: Defaults
|
|
|
5
5
|
# Defaults
|
|
6
6
|
|
|
7
7
|
These are the values aex applies when you **omit** the corresponding option on a
|
|
8
|
-
|
|
8
|
+
session. Every value is mirrored from a single source-of-truth constant in the
|
|
9
9
|
platform's limits module; this page is hand-maintained against those constants.
|
|
10
10
|
If a value here ever disagrees with the constant, the constant wins.
|
|
11
11
|
|
|
@@ -16,34 +16,34 @@ For the hard ceilings and who can raise them, see
|
|
|
16
16
|
[Limits & quotas](limits-and-quotas.md). For policy boundaries, see
|
|
17
17
|
[Limits](limits.md).
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## SessionRecord
|
|
20
20
|
|
|
21
21
|
| Option | Default | How to override | Source |
|
|
22
22
|
| --- | --- | --- | --- |
|
|
23
|
-
| `timeout` (
|
|
24
|
-
| `runtime` (machine size) | `shared-0.25x-1gb` — 0.25 vCPU, 1 GB | Per-session via `runtime` (use `Sizes.*` in TypeScript). | `
|
|
23
|
+
| `timeout` (session deadline) | 8 hours (also the ceiling) | Per-session via `overrides.timeout` (e.g. `"30m"`, `"2h"`). Values outside the session-timeout floor (1 minute) / ceiling (8 hours) are rejected with `SessionConfigValidationError` before submission. | `SESSION_DEFAULT_TIMEOUT_MS` |
|
|
24
|
+
| `runtime` (machine size) | `shared-0.25x-1gb` — 0.25 vCPU, 1 GB | Per-session via `runtime` (use `Sizes.*` in TypeScript). | `SESSION_DEFAULT_RUNTIME_SIZE` |
|
|
25
25
|
| `overrides.maxSpendUsd` (per-session spend cap) | None — no spend cap (the session is still bounded by its `timeout` and any workspace-level cap) | Per-session via `overrides.maxSpendUsd` (a positive USD amount); the session is stopped once its spend would exceed the cap. | — |
|
|
26
|
-
| `overrides.maxTurns` (agent iterations per
|
|
26
|
+
| `overrides.maxTurns` (agent iterations per session) | 20 (ceiling 200) | Per-session via `overrides.maxTurns` (a positive integer, clamped to the ceiling). | `SESSION_DEFAULT_MAX_TURNS` |
|
|
27
27
|
|
|
28
28
|
## Tools
|
|
29
29
|
|
|
30
30
|
| Option | Default | How to override | Source |
|
|
31
31
|
| --- | --- | --- | --- |
|
|
32
|
-
| Per-call exec timeout | 30 minutes | Per-call via the tool call's `timeoutMs`. | `
|
|
32
|
+
| Per-call exec timeout | 30 minutes | Per-call via the tool call's `timeoutMs`. | `SESSION_DEFAULT_EXEC_TIMEOUT_MS` |
|
|
33
33
|
| `web_fetch` returned body | 500 KB (UTF-8) | Per-call via the tool's `max_bytes` argument. | `REQUEST_WEB_FETCH_DEFAULT_MAX_BYTES` |
|
|
34
34
|
|
|
35
35
|
## MCP
|
|
36
36
|
|
|
37
37
|
| Option | Default | How to override | Source |
|
|
38
38
|
| --- | --- | --- | --- |
|
|
39
|
-
| MCP connect timeout (register + initialize + discover) | 30 seconds | Per-port via `connectTimeoutMs`. | `
|
|
40
|
-
| MCP `tools/call` timeout | 30 minutes | Per-port via `callTimeoutMs`. | `
|
|
39
|
+
| MCP connect timeout (register + initialize + discover) | 30 seconds | Per-port via `connectTimeoutMs`. | `SESSION_DEFAULT_MCP_CONNECT_TIMEOUT_MS` |
|
|
40
|
+
| MCP `tools/call` timeout | 30 minutes | Per-port via `callTimeoutMs`. | `SESSION_DEFAULT_MCP_CALL_TIMEOUT_MS` |
|
|
41
41
|
|
|
42
42
|
## Links (signed URLs and tickets)
|
|
43
43
|
|
|
44
44
|
| Option | Default | How to override | Source |
|
|
45
45
|
| --- | --- | --- | --- |
|
|
46
|
-
|
|
|
46
|
+
| SessionFile link / signed-URL TTL | 300 seconds (5 minutes) at the storage layer; `session.files().link(...)` defaults to `"1h"` | Per-call via `expiresSeconds` (storage) or `expiresIn` on `session.files().link` / `session.files().fetch`. | `REQUEST_PRESIGN_URL_DEFAULT_TTL_SECONDS` |
|
|
47
47
|
| Event-stream connection ticket TTL | 60 seconds | Per-mint via the `ttlMs` argument. | `REQUEST_TICKET_DEFAULT_TTL_MS` |
|
|
48
48
|
|
|
49
49
|
## Subagents
|
|
@@ -53,15 +53,15 @@ numeric entitlements; exact operational values may change as capacity evolves.
|
|
|
53
53
|
|
|
54
54
|
| Option | Default | How to override | Source |
|
|
55
55
|
| --- | --- | --- | --- |
|
|
56
|
-
| Concurrent child
|
|
57
|
-
| Max subagent depth | Platform-managed; supports high recursive subagent depth. | No public per-
|
|
56
|
+
| Concurrent child sessions per lineage root | Platform-managed; designed to scale across hundreds, even thousands, of live child agents. | No public per-session override; contact support for unusually large workloads. | `SESSION_DEFAULT_MAX_CONCURRENT_CHILD_SESSIONS` |
|
|
57
|
+
| Max subagent depth | Platform-managed; supports high recursive subagent depth. | No public per-session override. | `SESSION_MAX_PUBLIC_SUBAGENT_DEPTH` |
|
|
58
58
|
|
|
59
59
|
## Workspace
|
|
60
60
|
|
|
61
61
|
| Option | Default | How to override | Source |
|
|
62
62
|
| --- | --- | --- | --- |
|
|
63
|
-
|
|
|
64
|
-
| Max concurrent
|
|
63
|
+
| SessionRecord submit rate (per minute) | 120 (`0` = disabled); past it `POST /sessions` fails with `429 workspace_submit_rate_exceeded` | Per-plane via env `AEX_WORKSPACE_SUBMIT_RATE_PER_MIN`; per-workspace via support. | — |
|
|
64
|
+
| Max concurrent sessions | Plan-based: 5 live root sessions (free), 50 (Pro), 200 (Team); hard ceiling 200 | Per-plan (upgrade) or per-workspace override via support, clamped to the ceiling. | `PLANS[planKey].maxConcurrentSessions` |
|
|
65
65
|
| Monthly spend cap | $250 per UTC calendar month (`0` = unlimited) | Per-workspace override via support. | `WORKSPACE_DEFAULT_SPEND_CAP_USD` |
|
|
66
|
-
| Per-workspace mutation rate limits (per minute) |
|
|
66
|
+
| Per-workspace mutation rate limits (per minute) | session cancel 30, session delete 30, signed link 120, API key create 10, API key delete 30 | Per-plane via the matching `AEX_RATE_LIMIT_<ACTION>_PER_MINUTE` env var. | `WORKSPACE_RATE_LIMIT_DEFAULTS` |
|
|
67
67
|
| Workspace storage cap | 500 GB (decimal) | Per-plane via env `AEX_WORKSPACE_STORAGE_CAP_BYTES`; admin workspaces are uncapped (not a customer entitlement). | `WORKSPACE_DEFAULT_STORAGE_CAP_BYTES` |
|
package/docs/errors.md
CHANGED
|
@@ -21,7 +21,7 @@ factory dispatches to a subclass by code/status:
|
|
|
21
21
|
| `AexIdempotencyConflictError` | `409` `idempotency_conflict` | — |
|
|
22
22
|
| `AexNotFoundError` | `404` `not_found` | — |
|
|
23
23
|
| `AexRateLimitError` | `429` (rate_limited, workspace_concurrency_exceeded, workspace_submit_rate_exceeded) | `retryAfterMs` (when advertised) |
|
|
24
|
-
| `AexApiError` (base) | every other stable code (session_busy,
|
|
24
|
+
| `AexApiError` (base) | every other stable code (session_busy, session_not_terminal, insufficient_balance, workspace_spend_cap_exceeded, upstream_error, internal_error, …) | — |
|
|
25
25
|
|
|
26
26
|
Branch with the exported guards instead of parsing bodies or matching status
|
|
27
27
|
codes: `isAuthError`, `isInsufficientScope`, `isIdempotencyConflict`,
|
|
@@ -31,7 +31,7 @@ codes: `isAuthError`, `isInsufficientScope`, `isIdempotencyConflict`,
|
|
|
31
31
|
import { isInsufficientScope, isIdempotencyConflict } from "@aexhq/sdk";
|
|
32
32
|
|
|
33
33
|
try {
|
|
34
|
-
await aex.
|
|
34
|
+
await aex.start(config);
|
|
35
35
|
} catch (err) {
|
|
36
36
|
if (isInsufficientScope(err)) {
|
|
37
37
|
// err.requiredScope names the missing scope; mint a key that includes it.
|
|
@@ -44,7 +44,7 @@ try {
|
|
|
44
44
|
The **stable** `apiCode` set the SDK types and dispatches on is: `unauthorized`,
|
|
45
45
|
`forbidden`, `insufficient_scope`, `token_invalid`, `token_revoked`,
|
|
46
46
|
`token_expired`, `malformed_token`, `not_found`, `idempotency_conflict`,
|
|
47
|
-
`session_busy`, `
|
|
47
|
+
`session_busy`, `session_not_terminal`, `unknown_workspace`,
|
|
48
48
|
`workspace_concurrency_exceeded`, `workspace_submit_rate_exceeded`,
|
|
49
49
|
`workspace_spend_cap_exceeded`, `insufficient_balance`, `rate_limited`,
|
|
50
50
|
`upstream_error`, `internal_error`. A code outside this set (e.g. a validation
|
|
@@ -53,7 +53,7 @@ The **stable** `apiCode` set the SDK types and dispatches on is: `unauthorized`,
|
|
|
53
53
|
|
|
54
54
|
Transport failures with no HTTP response (DNS, connection refused, TLS reset)
|
|
55
55
|
surface as `AexNetworkError`; client-side config validation surfaces as
|
|
56
|
-
`
|
|
56
|
+
`SessionConfigValidationError` (`err.code === "SESSION_CONFIG_INVALID"`) before any
|
|
57
57
|
request is sent.
|
|
58
58
|
|
|
59
59
|
## 401 — authentication
|
|
@@ -78,7 +78,7 @@ is the cheapest way to validate a credential. See
|
|
|
78
78
|
| `forbidden` | The authenticated workspace does not own the addressed resource. |
|
|
79
79
|
|
|
80
80
|
```json
|
|
81
|
-
{ "error": "insufficient_scope", "requiredScope": "
|
|
81
|
+
{ "error": "insufficient_scope", "requiredScope": "sessions:write" }
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
## 400 — validation
|
|
@@ -91,7 +91,7 @@ is the cheapest way to validate a credential. See
|
|
|
91
91
|
| `malformed_token` | The bearer value is not a structurally valid aex token. |
|
|
92
92
|
|
|
93
93
|
400s are permanent for that request — fix the input rather than retrying.
|
|
94
|
-
The SDK's client-side validation (`
|
|
94
|
+
The SDK's client-side validation (`SessionConfigValidationError`) catches most of
|
|
95
95
|
these before the request is sent.
|
|
96
96
|
|
|
97
97
|
## 402 — payment required
|
|
@@ -104,7 +104,7 @@ effective submit floor. Top up the balance or bind a payment method.
|
|
|
104
104
|
```json
|
|
105
105
|
{
|
|
106
106
|
"error": "insufficient_balance",
|
|
107
|
-
"message": "Workspace balance is depleted; top up your prepaid balance or bind a payment method to submit
|
|
107
|
+
"message": "Workspace balance is depleted; top up your prepaid balance or bind a payment method to submit sessions.",
|
|
108
108
|
"balanceUsd": 0,
|
|
109
109
|
"balanceGraceFloorUsd": 0,
|
|
110
110
|
"paymentMethodStatus": "none",
|
|
@@ -132,13 +132,13 @@ raise it.
|
|
|
132
132
|
## 429 — rate limits
|
|
133
133
|
|
|
134
134
|
**`workspace_concurrency_exceeded`** — admitting one more live run would exceed
|
|
135
|
-
the workspace's concurrent-run cap. Wait for a
|
|
135
|
+
the workspace's concurrent-run cap. Wait for a session to finish, or contact
|
|
136
136
|
support to raise the cap.
|
|
137
137
|
|
|
138
138
|
```json
|
|
139
139
|
{
|
|
140
140
|
"error": "workspace_concurrency_exceeded",
|
|
141
|
-
"message": "Workspace concurrency limit reached: 50 live
|
|
141
|
+
"message": "Workspace concurrency limit reached: 50 live sessions at the cap of 50. Wait for a session to finish, or contact support to raise your workspace limit.",
|
|
142
142
|
"cap": 50,
|
|
143
143
|
"observed": 50
|
|
144
144
|
}
|
|
@@ -178,7 +178,7 @@ request body. The SDK raises `AexIdempotencyConflictError` (guard:
|
|
|
178
178
|
the byte-identical body to replay the original result (a matching retry returns
|
|
179
179
|
the existing session rather than conflicting). Note that the SDK validates the
|
|
180
180
|
key client-side first: an empty or whitespace-only `idempotencyKey` throws
|
|
181
|
-
`
|
|
181
|
+
`SessionConfigValidationError` before the request is sent — never pass `""`.
|
|
182
182
|
|
|
183
183
|
## 5xx — server errors
|
|
184
184
|
|
package/docs/events.md
CHANGED
|
@@ -4,7 +4,7 @@ title: Events
|
|
|
4
4
|
|
|
5
5
|
# Events
|
|
6
6
|
|
|
7
|
-
aex
|
|
7
|
+
aex sessions agent sessions on the managed runtime. Sessions are **non-blocking**:
|
|
8
8
|
the managed runtime advances the agent while aex observes lifecycle state, maps
|
|
9
9
|
runtime output into one event shape, and persists every captured event. The SDK
|
|
10
10
|
and CLI observe the durable event timeline from aex — there is no in-process
|
|
@@ -14,7 +14,7 @@ tool-approval hook.
|
|
|
14
14
|
|
|
15
15
|
A session's reads and streams are grouped under accessor sub-resources:
|
|
16
16
|
`session.events()` owns the event timeline, `session.messages()` owns the decoded
|
|
17
|
-
assistant text, and `session.
|
|
17
|
+
assistant text, and `session.files()` owns the captured files. Reach a verb by
|
|
18
18
|
chaining it off the accessor.
|
|
19
19
|
|
|
20
20
|
```ts
|
|
@@ -74,7 +74,7 @@ stream as `session.events().streamEnvelopes()` (replay-from-cursor + tail +
|
|
|
74
74
|
exactly-once resume), so they are the low-latency equivalents of
|
|
75
75
|
`events --follow`'s polling. `--json` is the raw-NDJSON escape hatch; `--filter`
|
|
76
76
|
keeps only the named AG-UI types (`TEXT_MESSAGE_CONTENT`, `TOOL_CALL_START`, …)
|
|
77
|
-
or sources (`agent`/`runtime`/…); a `
|
|
77
|
+
or sources (`agent`/`runtime`/…); a `TURN_ERROR` is surfaced as a jump-to-failure
|
|
78
78
|
line. `aex inspect` adds a header, a settle-consistent full timeline, and a
|
|
79
79
|
cost/usage footer. Both exit `0` parked cleanly / `1` error park / `3` timeout.
|
|
80
80
|
They need a global `WebSocket` (Bun or Node ≥ 22).
|
|
@@ -93,7 +93,7 @@ message is accepted replays the events it missed, then continues live.
|
|
|
93
93
|
## Session turn events
|
|
94
94
|
|
|
95
95
|
The canonical SDK session surface stops a turn on session lifecycle events, not
|
|
96
|
-
terminal
|
|
96
|
+
terminal session events:
|
|
97
97
|
|
|
98
98
|
```ts
|
|
99
99
|
const session = await aex.openSession(config);
|
|
@@ -111,9 +111,9 @@ The turn stream ends on the turn's park terminal: a resumable
|
|
|
111
111
|
`aex.session.succeeded` / `.failed` / `.timed_out` / `.cancelled`, or the held
|
|
112
112
|
`aex.session.awaiting_approval`. (The bare `aex.session.error` park is retired —
|
|
113
113
|
a failed turn is `failed`, a wall-clock kill `timed_out`, a cancel `cancelled`.)
|
|
114
|
-
`aex.
|
|
114
|
+
`aex.start(config)` is a convenience wrapper over the same flow: it opens a
|
|
115
115
|
session, sends `message` once, and returns the collected session turn. The
|
|
116
|
-
returned `
|
|
116
|
+
returned `sessionId` is the session id.
|
|
117
117
|
|
|
118
118
|
## Per-token streaming (`outputMode: 'stream'`)
|
|
119
119
|
|
|
@@ -132,16 +132,16 @@ on a provider that has no streaming producer (currently `gemini`) is a typed
|
|
|
132
132
|
rejection at submission parse — **not** a silent downgrade to buffered. Choose a
|
|
133
133
|
streamable provider or drop back to `buffered` explicitly.
|
|
134
134
|
|
|
135
|
-
## Terminal events vs. the
|
|
135
|
+
## Terminal events vs. the session record
|
|
136
136
|
|
|
137
137
|
Two families of events can end a turn's stream, and which one you see depends
|
|
138
138
|
on how the turn ends:
|
|
139
139
|
|
|
140
|
-
- **AG-UI terminals** — `
|
|
140
|
+
- **AG-UI terminals** — `TURN_FINISHED` / `TURN_ERROR`. These are *render-complete*
|
|
141
141
|
signals emitted by the agent stream itself. On the managed plane a normal
|
|
142
|
-
session turn usually does **not** emit `
|
|
143
|
-
instead (see below). Expect `
|
|
144
|
-
`
|
|
142
|
+
session turn usually does **not** emit `TURN_FINISHED`: the session *parks*
|
|
143
|
+
instead (see below). Expect `TURN_ERROR` on stream-level failures, and treat
|
|
144
|
+
`TURN_FINISHED` — when it does appear — as a low-latency "stop the spinner"
|
|
145
145
|
hint, not a read-consistency barrier.
|
|
146
146
|
- **`aex.session.*` park terminals** — `CUSTOM` events carrying the turn's
|
|
147
147
|
OUTCOME: `aex.session.succeeded` / `aex.session.failed` / `aex.session.timed_out`
|
|
@@ -149,11 +149,11 @@ on how the turn ends:
|
|
|
149
149
|
`aex.session.suspended` / `aex.session.awaiting_approval`. On the managed plane
|
|
150
150
|
these are what actually end a turn. The park event ends the RENDER; the settle
|
|
151
151
|
commit (cost + usage + the authoritative outcome) lands shortly after — which
|
|
152
|
-
is why `
|
|
152
|
+
is why `start()`/`done()` await settle by DEFAULT and return the outcome as
|
|
153
153
|
`result.status` with `result.costUsd`/`result.usage` always populated (never a
|
|
154
154
|
bare `idle`). Pass `await: 'park'` (on `run(...)` or `session.send(msg, {...})`)
|
|
155
155
|
to return early at the park event when you don't need cost/usage. `result.costUsd`
|
|
156
|
-
is aex
|
|
156
|
+
is aex starttime/storage spend and **excludes** your BYOK provider charges — price
|
|
157
157
|
those from `result.usage` token counts. Ending a raw stream on the park event is
|
|
158
158
|
fine for live UI; read the settled record (or the default await-settle result)
|
|
159
159
|
when you need cost/usage/outcome.
|
|
@@ -161,11 +161,11 @@ on how the turn ends:
|
|
|
161
161
|
Each event the stream yields carries method guards that cover both families so
|
|
162
162
|
you never have to switch on the plane:
|
|
163
163
|
|
|
164
|
-
- `event.
|
|
165
|
-
- `event.
|
|
164
|
+
- `event.isTurnTerminal()` — true for the AG-UI `TURN_FINISHED` / `TURN_ERROR` pair.
|
|
165
|
+
- `event.isSessionSettled()` — true for the `aex.session.settled` settle barrier **and**
|
|
166
166
|
for any `aex.session.*` park terminal. The managed plane emits the barrier after
|
|
167
167
|
settle when it is delivered to the stream; the park event remains a terminal
|
|
168
|
-
fallback for streams that do not receive a later barrier. `event.
|
|
168
|
+
fallback for streams that do not receive a later barrier. `event.isSessionSettled()`
|
|
169
169
|
is the one check that reliably means "this stream is done and the record is
|
|
170
170
|
authoritative".
|
|
171
171
|
|
|
@@ -188,16 +188,16 @@ for await (const event of session.events().streamEnvelopes({ settleConsistent: t
|
|
|
188
188
|
const settled = await aex.sessions.get(session.id); // parked/terminal here
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
-
`settleConsistent: true` makes the iterator end exactly when `event.
|
|
192
|
-
first fires; on a raw stream, call `event.
|
|
191
|
+
`settleConsistent: true` makes the iterator end exactly when `event.isSessionSettled()`
|
|
192
|
+
first fires; on a raw stream, call `event.isSessionSettled()` yourself. What it
|
|
193
193
|
guarantees: when the stream ends, a subsequent `aex.sessions.get(id)` reads a
|
|
194
|
-
parked/terminal status and `session.
|
|
194
|
+
parked/terminal status and `session.files().list()` is complete. Files are
|
|
195
195
|
uploaded before the terminal is broadcast, so they are readable the moment the
|
|
196
196
|
stream ends.
|
|
197
197
|
|
|
198
198
|
## Temporary event archive links
|
|
199
199
|
|
|
200
|
-
For terminal
|
|
200
|
+
For terminal sessions, `session.events().archiveLink(options?)` returns a temporary direct URL to `events.jsonl`, the same redacted customer-visible event export used by `session.events().download()`.
|
|
201
201
|
|
|
202
202
|
```ts
|
|
203
203
|
const link = await session.events().archiveLink({ expiresIn: "1h" });
|
|
@@ -215,7 +215,7 @@ Every read and stream surface yields one canonical shape — the versioned coord
|
|
|
215
215
|
|
|
216
216
|
Every event the SDK yields — the turn stream (`session.send()`),
|
|
217
217
|
`session.events().list()`, `session.events().streamEnvelopes()`, and
|
|
218
|
-
`
|
|
218
|
+
`SessionResult.events` — carries a type-guard **method** for each standardized event
|
|
219
219
|
type, so you branch on the event without importing a free function or writing a
|
|
220
220
|
raw `event.type === "…"` compare:
|
|
221
221
|
|
|
@@ -225,15 +225,15 @@ for await (const event of session.send("Continue the task.")) {
|
|
|
225
225
|
process.stdout.write(event.data.text); // `data.text` is typed `string` here
|
|
226
226
|
} else if (event.isToolCallStart()) {
|
|
227
227
|
console.log("tool:", event.data.name); // `data.name` is typed `string` here
|
|
228
|
-
} else if (event.
|
|
229
|
-
console.error("
|
|
228
|
+
} else if (event.isTurnError()) {
|
|
229
|
+
console.error("turn error");
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
The full method set: `
|
|
235
|
-
`
|
|
236
|
-
`isCustom()`, `isLog()`, `isEventChannel()`, `
|
|
234
|
+
The full method set: `isTurnStarted()`, `isTurnFinished()`, `isTurnError()`,
|
|
235
|
+
`isTurnTerminal()`, `isTextMessage()`, `isToolCallStart()`, `isToolCallResult()`,
|
|
236
|
+
`isCustom()`, `isLog()`, `isEventChannel()`, `isSessionSettled()`, and
|
|
237
237
|
`isFromSource(source)`. All test the `type` (or `channel`/`source`) discriminant
|
|
238
238
|
at runtime. `isTextMessage()`, `isToolCallStart()`, and `isToolCallResult()` are
|
|
239
239
|
TS type predicates: inside the guarded branch `event.data` NARROWS to that event
|