@aexhq/sdk 0.35.0 → 0.37.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 (72) hide show
  1. package/README.md +17 -16
  2. package/dist/_contracts/event-envelope.d.ts +22 -1
  3. package/dist/_contracts/event-envelope.js +26 -2
  4. package/dist/_contracts/event-stream-client.js +7 -1
  5. package/dist/_contracts/index.d.ts +3 -4
  6. package/dist/_contracts/index.js +1 -4
  7. package/dist/_contracts/operations.d.ts +31 -1
  8. package/dist/_contracts/operations.js +64 -1
  9. package/dist/_contracts/run-config.d.ts +2 -4
  10. package/dist/_contracts/run-config.js +2 -7
  11. package/dist/_contracts/run-trace.d.ts +0 -86
  12. package/dist/_contracts/run-trace.js +1 -184
  13. package/dist/_contracts/run-unit.d.ts +14 -25
  14. package/dist/_contracts/run-unit.js +56 -2
  15. package/dist/_contracts/runtime-manifest.d.ts +1 -1
  16. package/dist/_contracts/runtime-security-profile.d.ts +0 -2
  17. package/dist/_contracts/runtime-security-profile.js +0 -9
  18. package/dist/_contracts/runtime-sizes.d.ts +2 -2
  19. package/dist/_contracts/runtime-sizes.js +5 -5
  20. package/dist/_contracts/runtime-types.d.ts +123 -4
  21. package/dist/_contracts/stable.d.ts +1 -1
  22. package/dist/_contracts/stable.js +1 -1
  23. package/dist/_contracts/submission.d.ts +8 -76
  24. package/dist/_contracts/submission.js +5 -472
  25. package/dist/cli.mjs +574 -511
  26. package/dist/cli.mjs.sha256 +1 -1
  27. package/dist/client.d.ts +69 -25
  28. package/dist/client.js +338 -68
  29. package/dist/client.js.map +1 -1
  30. package/dist/index.d.ts +8 -16
  31. package/dist/index.js +5 -17
  32. package/dist/index.js.map +1 -1
  33. package/dist/secret.d.ts +2 -2
  34. package/dist/secret.js +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/dist/version.js +1 -1
  37. package/docs/authentication.md +92 -0
  38. package/docs/billing.md +112 -0
  39. package/docs/concepts/agent-tools.md +4 -4
  40. package/docs/concepts/composition.md +8 -14
  41. package/docs/concepts/providers-and-runtimes.md +4 -1
  42. package/docs/concepts/runs.md +2 -1
  43. package/docs/concepts/subagents.md +85 -0
  44. package/docs/credentials.md +78 -96
  45. package/docs/defaults.md +9 -15
  46. package/docs/errors.md +132 -0
  47. package/docs/events.md +44 -32
  48. package/docs/limits-and-quotas.md +30 -17
  49. package/docs/limits.md +4 -8
  50. package/docs/mcp.md +5 -6
  51. package/docs/networking.md +75 -59
  52. package/docs/outputs.md +4 -7
  53. package/docs/public-surface.json +4 -4
  54. package/docs/quickstart.md +12 -13
  55. package/docs/run-config.md +7 -4
  56. package/docs/secrets.md +6 -1
  57. package/docs/skills.md +3 -3
  58. package/docs/vision-skills.md +52 -101
  59. package/docs/webhooks.md +132 -0
  60. package/examples/feature-tour.ts +4 -21
  61. package/package.json +1 -1
  62. package/dist/_contracts/proxy-protocol.d.ts +0 -305
  63. package/dist/_contracts/proxy-protocol.js +0 -297
  64. package/dist/_contracts/proxy-validation.d.ts +0 -19
  65. package/dist/_contracts/proxy-validation.js +0 -51
  66. package/dist/data-tools.d.ts +0 -82
  67. package/dist/data-tools.js +0 -251
  68. package/dist/data-tools.js.map +0 -1
  69. package/dist/proxy-endpoint.d.ts +0 -131
  70. package/dist/proxy-endpoint.js +0 -144
  71. package/dist/proxy-endpoint.js.map +0 -1
  72. package/examples/chat-corpus.ts +0 -84
@@ -1,185 +1,2 @@
1
- /**
2
- * Typed decoders for a `listEvents(runId)` stream.
3
- *
4
- * `listEvents` returns the loose {@link RunEvent} wire shape: `type` at the top
5
- * level, but the tool name at `data.name`, the call args at `data.arguments`,
6
- * assistant text at `data.text`, and — the awkward part — a `TOOL_CALL_RESULT`
7
- * carries no name, so a consumer must correlate each result back to its
8
- * `TOOL_CALL_START` by `data.id` (the tool-call id). Every consumer ended up
9
- * re-implementing that correlation; these helpers do it once, typed and pure.
10
- *
11
- * They are total and side-effect-free: pass the array `listEvents` returns and
12
- * get back structured traces. Unknown event types are ignored (forward-compat),
13
- * a result with no matching start surfaces as an orphan (never dropped silently),
14
- * and timing falls back gracefully when a `recordedAt` is absent.
15
- *
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`.
20
- */
21
- const CUSTOM_USAGE_NAME = "aex.usage";
22
- /** snake_case `aex.usage` field → the camelCase {@link UsageSummary} field. */
23
- const USAGE_FIELD_MAP = {
24
- input_tokens: "inputTokens",
25
- output_tokens: "outputTokens",
26
- cache_read_input_tokens: "cacheReadInputTokens",
27
- cache_creation_input_tokens: "cacheCreationInputTokens"
28
- };
29
- /**
30
- * Decode a `listEvents` stream into correlated tool-call traces, in start order.
31
- *
32
- * Each `TOOL_CALL_START` opens a trace keyed by `data.id`; the matching
33
- * `TOOL_CALL_RESULT` (same `data.id`) fills in `result` + `durationMs`. A result
34
- * whose id never had a start is surfaced as an orphan trace (empty `name`, no
35
- * `args`) rather than dropped, so a partial/mis-ordered stream never hides a
36
- * result. Pure — no I/O, input is not mutated.
37
- */
38
- export function decodeToolCalls(events) {
39
- const order = [];
40
- const byId = new Map();
41
- for (const event of events) {
42
- const data = asRecord(event.data);
43
- if (event.type === "TOOL_CALL_START") {
44
- const id = asString(data.id);
45
- if (id === undefined)
46
- continue;
47
- const trace = {
48
- id,
49
- name: asString(data.name) ?? "",
50
- args: asRecord(data.arguments)
51
- };
52
- const messageId = asString(data.messageId);
53
- if (messageId !== undefined)
54
- trace.messageId = messageId;
55
- if (typeof event.seq === "number")
56
- trace.startSeq = event.seq;
57
- if (typeof event.recordedAt === "string")
58
- trace.startedAt = event.recordedAt;
59
- if (!byId.has(id))
60
- order.push(id);
61
- byId.set(id, trace);
62
- continue;
63
- }
64
- if (event.type === "TOOL_CALL_RESULT") {
65
- const id = asString(data.id);
66
- if (id === undefined)
67
- continue;
68
- const result = {
69
- isError: data.isError === true,
70
- content: data.content ?? null
71
- };
72
- if (typeof event.seq === "number")
73
- result.seq = event.seq;
74
- if (typeof event.recordedAt === "string")
75
- result.recordedAt = event.recordedAt;
76
- let trace = byId.get(id);
77
- if (trace === undefined) {
78
- // Orphan result (no matching start) — surface it, never drop it.
79
- trace = { id, name: "", args: {} };
80
- order.push(id);
81
- byId.set(id, trace);
82
- }
83
- trace.result = result;
84
- const duration = durationMs(trace.startedAt, result.recordedAt);
85
- if (duration !== undefined)
86
- trace.durationMs = duration;
87
- continue;
88
- }
89
- }
90
- return order.map((id) => byId.get(id));
91
- }
92
- /**
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.
96
- * `totalTokens` is the sum of input + output tokens. Pure.
97
- */
98
- export function summarizeRunUsage(events) {
99
- const totals = { inputTokens: 0, outputTokens: 0, cacheReadInputTokens: 0, cacheCreationInputTokens: 0 };
100
- let seen = false;
101
- for (const event of events) {
102
- if (event.type !== "CUSTOM")
103
- continue;
104
- const data = asRecord(event.data);
105
- if (asString(data.name) !== CUSTOM_USAGE_NAME)
106
- continue;
107
- const value = asRecord(data.value);
108
- for (const [snake, camel] of Object.entries(USAGE_FIELD_MAP)) {
109
- const n = value[snake];
110
- if (typeof n === "number" && Number.isFinite(n)) {
111
- totals[camel] += n;
112
- seen = true;
113
- }
114
- }
115
- }
116
- if (!seen)
117
- return {};
118
- return {
119
- inputTokens: totals.inputTokens,
120
- outputTokens: totals.outputTokens,
121
- cacheReadInputTokens: totals.cacheReadInputTokens,
122
- cacheCreationInputTokens: totals.cacheCreationInputTokens,
123
- totalTokens: totals.inputTokens + totals.outputTokens
124
- };
125
- }
126
- /**
127
- * The run's final assistant text: every `TEXT_MESSAGE_CONTENT` block in stream
128
- * order, concatenated. The one-line "what did the agent say" accessor over
129
- * {@link decodeAssistantText} (buffered mode yields whole messages, stream mode
130
- * yields token deltas — both concatenate correctly). Pure.
131
- */
132
- export function textOf(events) {
133
- return decodeAssistantText(events).map((entry) => entry.text).join("");
134
- }
135
- /** Decode the assistant text blocks (`TEXT_MESSAGE_CONTENT`) in stream order. Pure. */
136
- export function decodeAssistantText(events) {
137
- const out = [];
138
- for (const event of events) {
139
- if (event.type !== "TEXT_MESSAGE_CONTENT")
140
- continue;
141
- const data = asRecord(event.data);
142
- const text = asString(data.text);
143
- if (text === undefined)
144
- continue;
145
- const entry = { text };
146
- const messageId = asString(data.messageId);
147
- if (messageId !== undefined)
148
- entry.messageId = messageId;
149
- if (typeof event.seq === "number")
150
- entry.seq = event.seq;
151
- if (typeof event.recordedAt === "string")
152
- entry.recordedAt = event.recordedAt;
153
- out.push(entry);
154
- }
155
- return out;
156
- }
157
- /**
158
- * Decode a whole `listEvents` stream in one pass: correlated tool calls,
159
- * aggregate {@link UsageSummary}, and assistant text. Convenience over the three
160
- * focused decoders; pure.
161
- */
162
- export function summarizeRunTrace(events) {
163
- return {
164
- toolCalls: decodeToolCalls(events),
165
- usage: summarizeRunUsage(events),
166
- text: decodeAssistantText(events)
167
- };
168
- }
169
- function asRecord(value) {
170
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
171
- }
172
- function asString(value) {
173
- return typeof value === "string" ? value : undefined;
174
- }
175
- function durationMs(start, end) {
176
- if (start === undefined || end === undefined)
177
- return undefined;
178
- const a = Date.parse(start);
179
- const b = Date.parse(end);
180
- if (!Number.isFinite(a) || !Number.isFinite(b))
181
- return undefined;
182
- const delta = b - a;
183
- return delta >= 0 ? delta : undefined;
184
- }
1
+ export {};
185
2
  //# sourceMappingURL=run-trace.js.map
@@ -3,8 +3,7 @@
3
3
  *
4
4
  * One canonical struct that captures every non-secret artifact persisted
5
5
  * for a single run: parsed submission inputs, status/lifecycle, attempts,
6
- * indexed events, raw-event Storage manifest, outputs (+ capture
7
- * failures), and the proxy-call audit log.
6
+ * indexed events, raw-event Storage manifest, outputs, and capture failures.
8
7
  *
9
8
  * Wire contract for `GET /api/runs/:runId`, the per-run archive's
10
9
  * `run.json`/`submission.json`/`caps.json`, and the SDK/CLI
@@ -19,7 +18,7 @@
19
18
  * detail response stays bounded). The archive zip carries the bytes.
20
19
  */
21
20
  import type { CleanupStatus } from "./status.js";
22
- import type { JsonValue, PlatformSubmission, PlatformProxyEndpoint } from "./submission.js";
21
+ import type { JsonValue, PlatformSubmission } from "./submission.js";
23
22
  /**
24
23
  * Parsed view of the legacy run snapshot jsonb. Stored shape is
25
24
  * `{kind:"submission", submission}` written by the hosted API's
@@ -97,26 +96,6 @@ export interface RunUnitOutputCaptureFailure {
97
96
  readonly errorMessage?: string;
98
97
  readonly createdAt: string;
99
98
  }
100
- export interface RunUnitProxyCall {
101
- readonly id: string;
102
- readonly endpointName: string;
103
- readonly method: string;
104
- readonly requestPathRedacted: string | null;
105
- readonly requestByteSize: number;
106
- readonly responseStatus: number | null;
107
- readonly responseByteSize: number;
108
- readonly outcome: string;
109
- readonly errorClass: string | null;
110
- readonly startedAt: string;
111
- readonly finishedAt: string | null;
112
- readonly durationMs: number | null;
113
- }
114
- export interface RunUnitProxyCallPage {
115
- readonly entries: readonly RunUnitProxyCall[];
116
- readonly totalCount: number;
117
- readonly truncated: boolean;
118
- readonly nextCursor?: string;
119
- }
120
99
  export interface RunUnit {
121
100
  readonly id: string;
122
101
  readonly workspaceId: string;
@@ -131,14 +110,12 @@ export interface RunUnit {
131
110
  readonly attemptCount: number;
132
111
  readonly submission: RunUnitSubmission;
133
112
  readonly capsSnapshot?: Record<string, JsonValue>;
134
- readonly proxyEndpointsSnapshot?: readonly PlatformProxyEndpoint[];
135
113
  readonly attempts: readonly RunUnitAttempt[];
136
114
  readonly events: RunUnitEventPage;
137
115
  readonly rawEventPages: readonly RunUnitRawEventPage[];
138
116
  readonly outputs: readonly RunUnitOutput[];
139
117
  readonly outputCaptureFailures: readonly RunUnitOutputCaptureFailure[];
140
118
  readonly costTelemetry?: import("./run-cost.js").RunCostTelemetry;
141
- readonly proxyCalls: RunUnitProxyCallPage;
142
119
  /**
143
120
  * Per-run, per-provider runtime manifest — derived from the validated
144
121
  * submission + the chosen provider (`buildRuntimeManifest`). Tells
@@ -159,3 +136,15 @@ export interface RunUnit {
159
136
  * the whole detail page.
160
137
  */
161
138
  export declare function parseRunUnitSubmission(input: unknown): RunUnitSubmission;
139
+ /**
140
+ * Normalize a `GET /api/runs/:runId` payload into a RunUnit whose type contract
141
+ * holds AT RUNTIME. The managed (AWS) plane returns a LEAN record (scalars +
142
+ * costTelemetry only) and omits the aggregate collections; the RunUnit type
143
+ * declares those non-optional, so a naive cast leaves `unit.outputs` /
144
+ * `unit.events.totalCount` `undefined` and a typed consumer crashes on
145
+ * `.map()` / `.totalCount` (pre-launch edge-sweep F25). We fill the aggregates
146
+ * with their empty defaults so array/page access is always safe. NOTE: on the
147
+ * managed plane these summaries are best-effort — read `outputs()` / `events()`
148
+ * / `messages()` for the authoritative per-run data.
149
+ */
150
+ export declare function normalizeRunUnit(raw: unknown): RunUnit;
@@ -3,8 +3,7 @@
3
3
  *
4
4
  * One canonical struct that captures every non-secret artifact persisted
5
5
  * for a single run: parsed submission inputs, status/lifecycle, attempts,
6
- * indexed events, raw-event Storage manifest, outputs (+ capture
7
- * failures), and the proxy-call audit log.
6
+ * indexed events, raw-event Storage manifest, outputs, and capture failures.
8
7
  *
9
8
  * Wire contract for `GET /api/runs/:runId`, the per-run archive's
10
9
  * `run.json`/`submission.json`/`caps.json`, and the SDK/CLI
@@ -19,6 +18,7 @@
19
18
  * detail response stays bounded). The archive zip carries the bytes.
20
19
  */
21
20
  import { parseMcpServerRef } from "./run-config.js";
21
+ import { CLEANUP_STATUSES } from "./status.js";
22
22
  import { Models, parseRunModel } from "./models.js";
23
23
  import { PLATFORM_PACKAGE_ECOSYSTEMS } from "./submission.js";
24
24
  // ---------------------------------------------------------------------------
@@ -120,6 +120,60 @@ function fallbackFlat() {
120
120
  function isRecord(value) {
121
121
  return typeof value === "object" && value !== null && !Array.isArray(value);
122
122
  }
123
+ /**
124
+ * Normalize a `GET /api/runs/:runId` payload into a RunUnit whose type contract
125
+ * holds AT RUNTIME. The managed (AWS) plane returns a LEAN record (scalars +
126
+ * costTelemetry only) and omits the aggregate collections; the RunUnit type
127
+ * declares those non-optional, so a naive cast leaves `unit.outputs` /
128
+ * `unit.events.totalCount` `undefined` and a typed consumer crashes on
129
+ * `.map()` / `.totalCount` (pre-launch edge-sweep F25). We fill the aggregates
130
+ * with their empty defaults so array/page access is always safe. NOTE: on the
131
+ * managed plane these summaries are best-effort — read `outputs()` / `events()`
132
+ * / `messages()` for the authoritative per-run data.
133
+ */
134
+ export function normalizeRunUnit(raw) {
135
+ const r = isRecord(raw) ? raw : {};
136
+ const eventsRaw = isRecord(r.events) ? r.events : {};
137
+ const str = (v) => (typeof v === "string" ? v : undefined);
138
+ const arr = (v) => (Array.isArray(v) ? v : []);
139
+ return {
140
+ id: str(r.id) ?? "",
141
+ workspaceId: str(r.workspaceId) ?? "",
142
+ status: str(r.status) ?? "unknown",
143
+ ...(str(r.lifecyclePhase) ? { lifecyclePhase: r.lifecyclePhase } : {}),
144
+ cleanupStatus: CLEANUP_STATUSES.includes(r.cleanupStatus)
145
+ ? r.cleanupStatus
146
+ : "not_started",
147
+ createdAt: str(r.createdAt) ?? "",
148
+ updatedAt: str(r.updatedAt) ?? "",
149
+ ...(str(r.startedAt) ? { startedAt: r.startedAt } : {}),
150
+ ...(str(r.terminalAt) ? { terminalAt: r.terminalAt } : {}),
151
+ ...(str(r.deletedAt) ? { deletedAt: r.deletedAt } : {}),
152
+ attemptCount: typeof r.attemptCount === "number"
153
+ ? r.attemptCount
154
+ : Array.isArray(r.attempts)
155
+ ? r.attempts.length
156
+ : 0,
157
+ submission: parseRunUnitSubmission(r.submission),
158
+ ...(isRecord(r.capsSnapshot) ? { capsSnapshot: r.capsSnapshot } : {}),
159
+ attempts: arr(r.attempts),
160
+ events: {
161
+ entries: arr(eventsRaw.entries),
162
+ totalCount: typeof eventsRaw.totalCount === "number" ? eventsRaw.totalCount : 0,
163
+ truncated: eventsRaw.truncated === true,
164
+ ...(str(eventsRaw.nextCursor) ? { nextCursor: eventsRaw.nextCursor } : {})
165
+ },
166
+ rawEventPages: arr(r.rawEventPages),
167
+ outputs: arr(r.outputs),
168
+ outputCaptureFailures: arr(r.outputCaptureFailures),
169
+ ...(isRecord(r.costTelemetry)
170
+ ? { costTelemetry: r.costTelemetry }
171
+ : {}),
172
+ ...(isRecord(r.runtimeManifest)
173
+ ? { runtimeManifest: r.runtimeManifest }
174
+ : {})
175
+ };
176
+ }
123
177
  function coerceRunUnitModel(value) {
124
178
  if (typeof value !== "string")
125
179
  return Models.CLAUDE_HAIKU_4_5;
@@ -39,7 +39,7 @@ export interface RuntimeManifest {
39
39
  readonly assetsRoot: string;
40
40
  /** Absolute path of the in-container aex runtime bridge (invoke via `bun`). */
41
41
  readonly aexCli: string;
42
- /** Absolute path of the per-run proxy-endpoints manifest. */
42
+ /** Absolute path of the in-container aex runtime index. */
43
43
  readonly indexJson: string;
44
44
  /** Absolute path of the always-mounted aex runtime contract README. */
45
45
  readonly readme: string;
@@ -6,14 +6,12 @@ export interface RuntimeSecurityProfile {
6
6
  readonly allowOpenNetworking: boolean;
7
7
  readonly allowRuntimePackages: boolean;
8
8
  readonly allowCustomerEnvVars: boolean;
9
- readonly allowProxyEndpoints: boolean;
10
9
  readonly allowMcpServers: boolean;
11
10
  }
12
11
  export interface RuntimeSecurityProfileEvaluationInput {
13
12
  readonly networkingMode?: "limited" | "open";
14
13
  readonly packageCount?: number;
15
14
  readonly customerEnvVarCount?: number;
16
- readonly proxyEndpointCount?: number;
17
15
  readonly mcpServerCount?: number;
18
16
  }
19
17
  export interface RuntimeSecurityProfileViolation {
@@ -6,7 +6,6 @@ export const RUNTIME_SECURITY_PROFILE_CONFIG = Object.freeze({
6
6
  allowOpenNetworking: false,
7
7
  allowRuntimePackages: false,
8
8
  allowCustomerEnvVars: true,
9
- allowProxyEndpoints: true,
10
9
  allowMcpServers: true
11
10
  }),
12
11
  standard: Object.freeze({
@@ -15,7 +14,6 @@ export const RUNTIME_SECURITY_PROFILE_CONFIG = Object.freeze({
15
14
  allowOpenNetworking: true,
16
15
  allowRuntimePackages: true,
17
16
  allowCustomerEnvVars: true,
18
- allowProxyEndpoints: true,
19
17
  allowMcpServers: true
20
18
  }),
21
19
  developer: Object.freeze({
@@ -24,7 +22,6 @@ export const RUNTIME_SECURITY_PROFILE_CONFIG = Object.freeze({
24
22
  allowOpenNetworking: true,
25
23
  allowRuntimePackages: true,
26
24
  allowCustomerEnvVars: true,
27
- allowProxyEndpoints: true,
28
25
  allowMcpServers: true
29
26
  })
30
27
  });
@@ -65,12 +62,6 @@ export function evaluateRuntimeSecurityProfile(profileName, input) {
65
62
  reason: `${profile.name} does not allow customer runtime env vars`
66
63
  });
67
64
  }
68
- if ((input.proxyEndpointCount ?? 0) > 0 && !profile.allowProxyEndpoints) {
69
- violations.push({
70
- field: "proxyEndpoints",
71
- reason: `${profile.name} does not allow HTTP proxy endpoints`
72
- });
73
- }
74
65
  if ((input.mcpServerCount ?? 0) > 0 && !profile.allowMcpServers) {
75
66
  violations.push({
76
67
  field: "submission.mcpServers",
@@ -65,9 +65,9 @@ export declare function runtimeResources(size: RuntimeSize): RuntimeResources;
65
65
  * consumers apply {@link DEFAULT_RUNTIME_SIZE}.
66
66
  */
67
67
  export declare function parseRuntimeSize(input: unknown): RuntimeSize | undefined;
68
- /** Default run deadline when `timeout` is omitted (1 hour). */
68
+ /** Default run deadline when `timeout` is omitted (8 hours). */
69
69
  export declare const DEFAULT_RUN_TIMEOUT_MS: number;
70
- /** Hard ceiling on a run deadline (6 hours). */
70
+ /** Hard ceiling on a run deadline (8 hours). */
71
71
  export declare const MAX_RUN_TIMEOUT_MS: number;
72
72
  /** Floor on a run deadline (1 minute). */
73
73
  export declare const MIN_RUN_TIMEOUT_MS: number;
@@ -54,10 +54,10 @@ export function parseRuntimeSize(input) {
54
54
  // ===========================================================================
55
55
  // Run timeout
56
56
  // ===========================================================================
57
- /** Default run deadline when `timeout` is omitted (1 hour). */
58
- export const DEFAULT_RUN_TIMEOUT_MS = 60 * 60 * 1000;
59
- /** Hard ceiling on a run deadline (6 hours). */
60
- export const MAX_RUN_TIMEOUT_MS = 6 * 60 * 60 * 1000;
57
+ /** Default run deadline when `timeout` is omitted (8 hours). */
58
+ export const DEFAULT_RUN_TIMEOUT_MS = 8 * 60 * 60 * 1000;
59
+ /** Hard ceiling on a run deadline (8 hours). */
60
+ export const MAX_RUN_TIMEOUT_MS = 8 * 60 * 60 * 1000;
61
61
  /** Floor on a run deadline (1 minute). */
62
62
  export const MIN_RUN_TIMEOUT_MS = 60 * 1000;
63
63
  const DURATION_PATTERN = /^(\d+(?:\.\d+)?)(ms|s|m|h)?$/;
@@ -95,7 +95,7 @@ export function parseRunTimeout(input) {
95
95
  throw new Error(`timeout must be at least ${MIN_RUN_TIMEOUT_MS}ms (1m); got ${ms}ms`);
96
96
  }
97
97
  if (ms > MAX_RUN_TIMEOUT_MS) {
98
- throw new Error(`timeout must be at most ${MAX_RUN_TIMEOUT_MS}ms (6h); got ${ms}ms`);
98
+ throw new Error(`timeout must be at most ${MAX_RUN_TIMEOUT_MS}ms (8h); got ${ms}ms`);
99
99
  }
100
100
  return ms;
101
101
  }
@@ -118,6 +118,27 @@ export interface SessionMessageAccepted {
118
118
  readonly turn: SessionTurn;
119
119
  readonly eventCursor?: number;
120
120
  }
121
+ export type SessionMessageSender = "user" | "assistant" | "system" | "tool";
122
+ export interface SessionMessage {
123
+ readonly id: string;
124
+ readonly sender: SessionMessageSender;
125
+ readonly text: string;
126
+ readonly timestamp?: string;
127
+ readonly turnSeq?: number;
128
+ readonly sequence?: number;
129
+ readonly messageId?: string;
130
+ readonly content?: unknown;
131
+ readonly [key: string]: unknown;
132
+ }
133
+ export interface SessionMessagesQuery {
134
+ readonly limit?: number;
135
+ readonly cursor?: string;
136
+ readonly since?: string;
137
+ }
138
+ export interface SessionMessagesPage {
139
+ readonly messages: readonly SessionMessage[];
140
+ readonly nextCursor?: string;
141
+ }
121
142
  export interface SessionStateChangeAccepted {
122
143
  readonly session: Session;
123
144
  readonly turn?: SessionTurn;
@@ -132,7 +153,7 @@ export interface UsageSummary {
132
153
  readonly totalTokens?: number;
133
154
  }
134
155
  /**
135
- * Filters for {@link import("./operations.js").listRuns} / `AgentExecutor.listRuns`.
156
+ * Filters for {@link import("./operations.js").listRuns} / `Aex.runs.list`.
136
157
  * Every field is optional; omitting all of them lists the most recent runs in the
137
158
  * token's workspace. Workspace identity is derived server-side from the API token,
138
159
  * so there is no `workspaceId` here — a token can only ever enumerate its own runs.
@@ -166,7 +187,7 @@ export interface RunListPage {
166
187
  readonly nextCursor?: string;
167
188
  }
168
189
  /**
169
- * Cross-run output search query (`AgentExecutor.searchOutputs`). Restrict to a
190
+ * Cross-run output search query (`Aex.outputs.search`). Restrict to a
170
191
  * corpus with `runIds`; filter by filename substring / extension / content type.
171
192
  * The MVP composes this client-side (per-run `listOutputs` + filter) — a future
172
193
  * server-side `GET /api/outputs/search` can back the same contract with a real
@@ -301,7 +322,7 @@ export interface OutputFileDownload {
301
322
  readonly output: Output;
302
323
  readonly bytes: Uint8Array;
303
324
  }
304
- /** Options for `AgentExecutor.readOutputText` / {@link import("./operations.js").readOutputText}. */
325
+ /** Options for `Aex.outputs.read` / {@link import("./operations.js").readOutputText}. */
305
326
  export interface ReadOutputTextOptions {
306
327
  /**
307
328
  * Stop reading after this many bytes. Defaults to 50_000; clamped server-side
@@ -317,7 +338,7 @@ export interface ReadOutputTextOptions {
317
338
  }
318
339
  /**
319
340
  * A byte-capped, decoded text read of one output file, as returned by
320
- * `AgentExecutor.readOutputText`. Built for feeding run deliverables to an LLM
341
+ * `Aex.outputs.read`. Built for feeding run deliverables to an LLM
321
342
  * without loading the whole (possibly very large) file into memory or context:
322
343
  * the read streams and stops at `maxBytes`, so `text` is at most that many bytes
323
344
  * decoded as UTF-8. Check {@link truncated} before treating `text` as complete.
@@ -377,6 +398,29 @@ export interface WhoAmI {
377
398
  */
378
399
  readonly maxRunDurationMs?: number | null;
379
400
  };
401
+ /**
402
+ * ADDITIVE effective per-workspace limits returned by `GET /whoami` on
403
+ * current platform deployments — everything a caller needs to anticipate a
404
+ * `429` / `402` submit rejection before hitting it. Every value is the same
405
+ * one the platform's admission gates enforce. Optional: older deployments
406
+ * omit the field entirely.
407
+ */
408
+ readonly limits?: {
409
+ /** Effective live-run concurrency cap. One more live run past it fails with `429 workspace_concurrency_exceeded`. */
410
+ readonly maxConcurrentRuns: number;
411
+ /** Effective submit-velocity cap per minute; `0` = unlimited (disabled). Past it: `429 workspace_submit_rate_exceeded`. */
412
+ readonly submitRatePerMinute: number;
413
+ /** Effective monthly spend cap in USD; `0` = unlimited. Once `monthSpendUsd` reaches it: `402 workspace_spend_cap_exceeded`. */
414
+ readonly spendCapUsd: number;
415
+ /** Accrued spend in the current UTC calendar month — the value the spend gate compares. */
416
+ readonly monthSpendUsd: number;
417
+ /** Prepaid balance read-model — the value the balance gate compares. */
418
+ readonly balanceUsd: number;
419
+ /** Effective (payment-method-aware) submit floor: submits fail with `402 insufficient_balance` once `balanceUsd` is at or below it. */
420
+ readonly balanceGraceFloorUsd: number;
421
+ /** `"active"` means a bounded card overdraft is already folded into `balanceGraceFloorUsd`. */
422
+ readonly paymentMethodStatus: "none" | "active";
423
+ };
380
424
  readonly [key: string]: unknown;
381
425
  }
382
426
  /**
@@ -484,3 +528,78 @@ export interface SecretReveal {
484
528
  readonly name: string;
485
529
  readonly value: string;
486
530
  }
531
+ /**
532
+ * Customer-facing billing summary — `GET /api/billing` (scope `billing:read`).
533
+ * All money fields are USD numbers. The index signature keeps the shape tolerant
534
+ * of ADDITIVE server fields (e.g. a deployment newer than this SDK reporting
535
+ * extra plan attributes) — unknown keys are preserved, never rejected.
536
+ */
537
+ export interface BillingSummary {
538
+ /** Prepaid balance (authoritative ledger sum). */
539
+ readonly balanceUsd: number;
540
+ /** Accrued spend for the current calendar month. */
541
+ readonly monthSpendUsd: number;
542
+ /** Monthly spend cap enforced on new runs. */
543
+ readonly spendCapUsd: number;
544
+ readonly planKey: string;
545
+ readonly subscriptionStatus: string;
546
+ /** `"active"` once a payment method is bound; older deployments omit it. */
547
+ readonly paymentMethodStatus?: string;
548
+ readonly [key: string]: unknown;
549
+ }
550
+ /** Self-serve paid plans exposed through hosted checkout. */
551
+ export type BillingCheckoutPlanKey = "pro" | "team";
552
+ export interface BillingCheckoutRequest {
553
+ readonly planKey: BillingCheckoutPlanKey;
554
+ /** Optional return URL after successful hosted checkout. */
555
+ readonly successUrl?: string;
556
+ /** Optional return URL after checkout cancellation. */
557
+ readonly cancelUrl?: string;
558
+ /** Optional caller-stable key so a retry does not create a second hosted session. */
559
+ readonly idempotencyKey?: string;
560
+ }
561
+ export interface BillingPortalRequest {
562
+ /** Optional return URL after leaving the hosted billing portal. */
563
+ readonly returnUrl?: string;
564
+ }
565
+ /** Hosted checkout/portal session. The client should open `url`. */
566
+ export interface BillingHostedSession {
567
+ readonly url: string;
568
+ readonly [key: string]: unknown;
569
+ }
570
+ /**
571
+ * One row of the workspace credit ledger as returned by
572
+ * `GET /api/billing/ledger` (newest first). `amountUsd` is signed: top-ups are
573
+ * positive, run charges negative. Tolerant of additive server fields.
574
+ */
575
+ export interface BillingLedgerEntry {
576
+ readonly id: string;
577
+ /** e.g. `top_up`, `run_charge`. Open server vocabulary. */
578
+ readonly entryType: string;
579
+ readonly amountUsd: number;
580
+ readonly currency: string;
581
+ /** The run this entry charges, `null` for non-run entries. */
582
+ readonly runId?: string | null;
583
+ readonly description?: string | null;
584
+ readonly createdBy?: string;
585
+ readonly createdAt: string;
586
+ readonly [key: string]: unknown;
587
+ }
588
+ /** Query for the billing ledger read. `limit` is clamped server-side to [1, 100] (default 25). */
589
+ export interface BillingLedgerQuery {
590
+ readonly limit?: number;
591
+ }
592
+ /** One page of recent ledger rows (newest first). Not cursor-paged — `limit` bounds the read. */
593
+ export interface BillingLedgerPage {
594
+ readonly entries: readonly BillingLedgerEntry[];
595
+ }
596
+ /**
597
+ * The workspace webhook signing secret reveal — `POST /api/webhook/signing-secret`.
598
+ * `whsec` is the Standard-Webhooks style `whsec_<base64>` string that
599
+ * `verifyAexWebhook` accepts as `secret`. The endpoint reveals the current
600
+ * secret, CREATING one on first use; it does not rotate (a repeat call returns
601
+ * the same value). POST (not GET) so every reveal is a logged action.
602
+ */
603
+ export interface WebhookSigningSecret {
604
+ readonly whsec: string;
605
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Canonical hosted aex API plane URL. Used as the default `baseUrl`
3
- * for the SDK `AgentExecutor` and the host-side CLI `--aex-url`
3
+ * for the SDK `Aex` client and the host-side CLI `--aex-url`
4
4
  * flag.
5
5
  *
6
6
  * Pinned to `api.aex.dev` on purpose: the dashboard at
@@ -1,7 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  /**
3
3
  * Canonical hosted aex API plane URL. Used as the default `baseUrl`
4
- * for the SDK `AgentExecutor` and the host-side CLI `--aex-url`
4
+ * for the SDK `Aex` client and the host-side CLI `--aex-url`
5
5
  * flag.
6
6
  *
7
7
  * Pinned to `api.aex.dev` on purpose: the dashboard at