@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.
- package/README.md +17 -16
- package/dist/_contracts/event-envelope.d.ts +22 -1
- package/dist/_contracts/event-envelope.js +26 -2
- package/dist/_contracts/event-stream-client.js +7 -1
- package/dist/_contracts/index.d.ts +3 -4
- package/dist/_contracts/index.js +1 -4
- package/dist/_contracts/operations.d.ts +31 -1
- package/dist/_contracts/operations.js +64 -1
- package/dist/_contracts/run-config.d.ts +2 -4
- package/dist/_contracts/run-config.js +2 -7
- package/dist/_contracts/run-trace.d.ts +0 -86
- package/dist/_contracts/run-trace.js +1 -184
- package/dist/_contracts/run-unit.d.ts +14 -25
- package/dist/_contracts/run-unit.js +56 -2
- package/dist/_contracts/runtime-manifest.d.ts +1 -1
- package/dist/_contracts/runtime-security-profile.d.ts +0 -2
- package/dist/_contracts/runtime-security-profile.js +0 -9
- package/dist/_contracts/runtime-sizes.d.ts +2 -2
- package/dist/_contracts/runtime-sizes.js +5 -5
- package/dist/_contracts/runtime-types.d.ts +123 -4
- package/dist/_contracts/stable.d.ts +1 -1
- package/dist/_contracts/stable.js +1 -1
- package/dist/_contracts/submission.d.ts +8 -76
- package/dist/_contracts/submission.js +5 -472
- package/dist/cli.mjs +574 -511
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +69 -25
- package/dist/client.js +338 -68
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +8 -16
- package/dist/index.js +5 -17
- package/dist/index.js.map +1 -1
- package/dist/secret.d.ts +2 -2
- package/dist/secret.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/authentication.md +92 -0
- package/docs/billing.md +112 -0
- package/docs/concepts/agent-tools.md +4 -4
- package/docs/concepts/composition.md +8 -14
- package/docs/concepts/providers-and-runtimes.md +4 -1
- package/docs/concepts/runs.md +2 -1
- package/docs/concepts/subagents.md +85 -0
- package/docs/credentials.md +78 -96
- package/docs/defaults.md +9 -15
- package/docs/errors.md +132 -0
- package/docs/events.md +44 -32
- package/docs/limits-and-quotas.md +30 -17
- package/docs/limits.md +4 -8
- package/docs/mcp.md +5 -6
- package/docs/networking.md +75 -59
- package/docs/outputs.md +4 -7
- package/docs/public-surface.json +4 -4
- package/docs/quickstart.md +12 -13
- package/docs/run-config.md +7 -4
- package/docs/secrets.md +6 -1
- package/docs/skills.md +3 -3
- package/docs/vision-skills.md +52 -101
- package/docs/webhooks.md +132 -0
- package/examples/feature-tour.ts +4 -21
- package/package.json +1 -1
- package/dist/_contracts/proxy-protocol.d.ts +0 -305
- package/dist/_contracts/proxy-protocol.js +0 -297
- package/dist/_contracts/proxy-validation.d.ts +0 -19
- package/dist/_contracts/proxy-validation.js +0 -51
- package/dist/data-tools.d.ts +0 -82
- package/dist/data-tools.js +0 -251
- package/dist/data-tools.js.map +0 -1
- package/dist/proxy-endpoint.d.ts +0 -131
- package/dist/proxy-endpoint.js +0 -144
- package/dist/proxy-endpoint.js.map +0 -1
- 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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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 (
|
|
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 (
|
|
58
|
-
export const DEFAULT_RUN_TIMEOUT_MS = 60 * 60 * 1000;
|
|
59
|
-
/** Hard ceiling on a run deadline (
|
|
60
|
-
export const MAX_RUN_TIMEOUT_MS =
|
|
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 (
|
|
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} / `
|
|
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 (`
|
|
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 `
|
|
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
|
-
* `
|
|
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 `
|
|
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 `
|
|
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
|