antpath 0.10.14 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +16 -8
- package/dist/_shared/blueprint.d.ts +93 -108
- package/dist/_shared/blueprint.js +144 -78
- package/dist/_shared/cleanup-policy.d.ts +2 -2
- package/dist/_shared/cleanup-policy.js +2 -5
- package/dist/_shared/http.d.ts +2 -2
- package/dist/_shared/index.d.ts +7 -1
- package/dist/_shared/index.js +6 -1
- package/dist/_shared/mcp-proxy-url.d.ts +55 -0
- package/dist/_shared/mcp-proxy-url.js +65 -0
- package/dist/_shared/operations.d.ts +55 -8
- package/dist/_shared/operations.js +163 -20
- package/dist/_shared/provider-proxy-url.d.ts +64 -0
- package/dist/_shared/provider-proxy-url.js +73 -0
- package/dist/_shared/proxy-validation.d.ts +1 -1
- package/dist/_shared/proxy-validation.js +2 -2
- package/dist/_shared/run-unit.d.ts +23 -36
- package/dist/_shared/run-unit.js +30 -46
- package/dist/_shared/runner-event.d.ts +120 -0
- package/dist/_shared/runner-event.js +193 -0
- package/dist/_shared/runner-job.d.ts +159 -0
- package/dist/_shared/runner-job.js +54 -0
- package/dist/_shared/runtime-manifest.d.ts +191 -0
- package/dist/_shared/runtime-manifest.js +221 -0
- package/dist/_shared/runtime-types.d.ts +7 -16
- package/dist/_shared/sse.d.ts +74 -0
- package/dist/_shared/sse.js +0 -0
- package/dist/_shared/stable.d.ts +15 -10
- package/dist/_shared/stable.js +15 -10
- package/dist/_shared/submission.d.ts +199 -73
- package/dist/_shared/submission.js +409 -210
- package/dist/_shared/telemetry.d.ts +2 -2
- package/dist/_shared/telemetry.js +2 -2
- package/dist/_shared/template/index.d.ts +0 -1
- package/dist/_shared/template/index.js +0 -1
- package/dist/agents-md.d.ts +25 -67
- package/dist/agents-md.js +35 -121
- package/dist/agents-md.js.map +1 -1
- package/dist/asset-upload.d.ts +34 -0
- package/dist/asset-upload.js +34 -0
- package/dist/asset-upload.js.map +1 -1
- package/dist/blueprint.d.ts +3 -3
- package/dist/bundle.d.ts +2 -2
- package/dist/bundle.js +1 -1
- package/dist/cli.mjs +559 -105
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +53 -22
- package/dist/client.js +196 -130
- package/dist/client.js.map +1 -1
- package/dist/file.d.ts +28 -94
- package/dist/file.js +35 -175
- package/dist/file.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +10 -2
- package/dist/mcp-server.js +17 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/skill.d.ts +44 -214
- package/dist/skill.js +50 -284
- package/dist/skill.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/cleanup.md +1 -1
- package/docs/credentials.md +2 -2
- package/docs/events.md +8 -8
- package/docs/outputs.md +2 -0
- package/docs/quickstart.md +18 -2
- package/docs/skills.md +1 -3
- package/docs/templates.md +6 -5
- package/package.json +2 -1
- package/dist/_shared/secrets.d.ts +0 -7
- package/dist/_shared/secrets.js +0 -20
- package/dist/_shared/template/mapper.d.ts +0 -11
- package/dist/_shared/template/mapper.js +0 -70
package/dist/cli.mjs.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ba35805b91e9b19eeeead9f80278140797287bc4d14e6618b842354cb2cb3208 cli.mjs
|
package/dist/client.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { HttpClient, type AgentsMdRecord, type FetchLike, type FileRecord, type Output, type
|
|
1
|
+
import { HttpClient, type AgentsMdRecord, type FetchLike, type FileRecord, type Output, type PlatformRunSubmissionInput, type PlatformSubmission, type PlatformInlineSecrets, type PlatformProxyEndpoint, type PlatformProxyEndpointAuth, type Run, type RunEvent, type RunProvider, type RunUnit, type RuntimeKind, type RuntimeManifest, type SignedOutputLink, type Skill as SkillRecord, type WhoAmI } from "./_shared/index.js";
|
|
2
2
|
import type { Blueprint } from "./blueprint.js";
|
|
3
3
|
import { AgentsMd } from "./agents-md.js";
|
|
4
4
|
import { File } from "./file.js";
|
|
5
5
|
import { McpServer } from "./mcp-server.js";
|
|
6
6
|
import { ProxyEndpoint } from "./proxy-endpoint.js";
|
|
7
7
|
import { Skill } from "./skill.js";
|
|
8
|
-
import type { ChunkedUploadClient } from "./skill.js";
|
|
9
8
|
export interface AntpathClientOptions {
|
|
10
9
|
/** Workspace-scoped SDK API token. */
|
|
11
10
|
readonly apiToken: string;
|
|
12
11
|
/**
|
|
13
|
-
*
|
|
14
|
-
* defaults to the canonical hosted URL (`https://
|
|
12
|
+
* API plane root, e.g. `https://antpath.example.com`. Optional —
|
|
13
|
+
* defaults to the canonical hosted URL (`https://api.antpath.ai`).
|
|
15
14
|
* Self-hosted deployments override; the default lives in source so
|
|
16
15
|
* the agent reading the SDK call site can see exactly where the call
|
|
17
16
|
* goes.
|
|
@@ -27,7 +26,7 @@ export interface AntpathClientOptions {
|
|
|
27
26
|
* - `model` / `system` / `prompt` — the agent's brief.
|
|
28
27
|
* - `skills` — array of `Skill` instances. Each instance is one of:
|
|
29
28
|
* workspace ref (`Skill.fromId` or the result of `.upload(client)`),
|
|
30
|
-
* provider ref (`Skill.provider`), or unstaged
|
|
29
|
+
* provider ref (`Skill.provider`), or unstaged inline
|
|
31
30
|
* (`Skill.fromFiles` / `Skill.fromPath`). Unstaged transient
|
|
32
31
|
* skills cause `submitRun` to switch to multipart and upload the
|
|
33
32
|
* bytes for this one run only.
|
|
@@ -45,6 +44,23 @@ export interface AntpathClientOptions {
|
|
|
45
44
|
* if you want client-driven retry safety across process restarts.
|
|
46
45
|
*/
|
|
47
46
|
export interface SubmitRunOptions {
|
|
47
|
+
/**
|
|
48
|
+
* Provider selector. Optional — defaults to
|
|
49
|
+
* {@link DEFAULT_RUN_PROVIDER} (`"anthropic"`). The call site must
|
|
50
|
+
* supply the matching `secrets.<provider>.apiKey` and MUST NOT
|
|
51
|
+
* supply any other provider's secret block. See
|
|
52
|
+
* `references/platform-rebuild-2026.md` (Customer interface).
|
|
53
|
+
*/
|
|
54
|
+
readonly provider?: RunProvider;
|
|
55
|
+
/**
|
|
56
|
+
* Optional runtime opt-out. `"managed"` forces the Goose Managed
|
|
57
|
+
* runtime (Fly Machine + LiteLLM); `"native"` is only valid when
|
|
58
|
+
* `provider === "anthropic"` and routes through Anthropic's Managed
|
|
59
|
+
* Agents API. Omit to let the platform auto-route based on provider.
|
|
60
|
+
* The platform rejects features the chosen runtime cannot serve —
|
|
61
|
+
* see {@link selectRuntime}.
|
|
62
|
+
*/
|
|
63
|
+
readonly runtime?: RuntimeKind;
|
|
48
64
|
readonly model: string;
|
|
49
65
|
readonly system?: string;
|
|
50
66
|
readonly prompt: string | readonly string[];
|
|
@@ -52,9 +68,9 @@ export interface SubmitRunOptions {
|
|
|
52
68
|
readonly agentsMd?: readonly AgentsMd[];
|
|
53
69
|
readonly files?: readonly File[];
|
|
54
70
|
readonly mcpServers?: readonly McpServer[];
|
|
55
|
-
readonly environment?:
|
|
56
|
-
readonly metadata?:
|
|
57
|
-
readonly cleanup?:
|
|
71
|
+
readonly environment?: PlatformSubmission["environment"];
|
|
72
|
+
readonly metadata?: PlatformSubmission["metadata"];
|
|
73
|
+
readonly cleanup?: PlatformRunSubmissionInput["cleanup"];
|
|
58
74
|
readonly proxyEndpoints?: readonly ProxyEndpoint[];
|
|
59
75
|
/**
|
|
60
76
|
* Container paths to capture as `output_objects` at session terminal.
|
|
@@ -76,8 +92,19 @@ export interface SubmitRunOptions {
|
|
|
76
92
|
readonly signal?: AbortSignal;
|
|
77
93
|
}
|
|
78
94
|
export interface StreamEventsOptions {
|
|
95
|
+
/** Polling interval in ms — used by the `polling` transport and as
|
|
96
|
+
* the fallback when SSE disconnects. Default 1000. */
|
|
79
97
|
readonly intervalMs?: number;
|
|
80
98
|
readonly signal?: AbortSignal;
|
|
99
|
+
/**
|
|
100
|
+
* Transport selector. `"auto"` (default) opens an SSE connection;
|
|
101
|
+
* on disconnect (server-side error, network blip, missing endpoint
|
|
102
|
+
* on older deployments) it falls back to polling for the remaining
|
|
103
|
+
* lifetime of the run. `"sse"` forces SSE and surfaces disconnects
|
|
104
|
+
* as iterator completion. `"polling"` keeps the historical poll
|
|
105
|
+
* loop — useful for environments without streaming support.
|
|
106
|
+
*/
|
|
107
|
+
readonly transport?: "auto" | "sse" | "polling";
|
|
81
108
|
}
|
|
82
109
|
export interface WaitForRunOptions {
|
|
83
110
|
readonly intervalMs?: number;
|
|
@@ -88,11 +115,18 @@ export interface WaitForRunOptions {
|
|
|
88
115
|
* Lightweight reference to a submitted run. All read-back operations
|
|
89
116
|
* delegate to the same `AntpathClient` and the same operations module
|
|
90
117
|
* the CLI uses, so SDK and CLI never drift.
|
|
118
|
+
*
|
|
119
|
+
* `runtimeManifest` is the per-run, per-provider description of where
|
|
120
|
+
* antpath placed things inside the agent container, plus the merged
|
|
121
|
+
* env-var bag delivered via `RUNTIME.env` / `RUNTIME.json`. Populated
|
|
122
|
+
* on instances returned by `submitRun`; instances constructed by `id`
|
|
123
|
+
* elsewhere call `.get()` to populate the field via the GET response.
|
|
91
124
|
*/
|
|
92
125
|
export declare class RunRef {
|
|
93
126
|
#private;
|
|
94
127
|
readonly runId: string;
|
|
95
|
-
|
|
128
|
+
readonly runtimeManifest?: RuntimeManifest;
|
|
129
|
+
constructor(client: AntpathClient, runId: string, runtimeManifest?: RuntimeManifest);
|
|
96
130
|
get(): Promise<Run>;
|
|
97
131
|
/** Convenience wrapper for `AntpathClient.getRunUnit`. */
|
|
98
132
|
getUnit(): Promise<RunUnit>;
|
|
@@ -277,14 +311,6 @@ export declare class AntpathClient {
|
|
|
277
311
|
readonly name: string;
|
|
278
312
|
readonly bytes: Uint8Array;
|
|
279
313
|
}): Promise<FileRecord>;
|
|
280
|
-
/**
|
|
281
|
-
* Internal: chunked-upload entry point for `Skill.upload` and
|
|
282
|
-
* `File.upload` when the bundle exceeds the 6 MiB threshold.
|
|
283
|
-
* Drives the three-step TUS flow: init → uploadChunked → finalize.
|
|
284
|
-
* NOT part of the public API — the underscore is a "do not call
|
|
285
|
-
* from user code" marker.
|
|
286
|
-
*/
|
|
287
|
-
readonly _chunkedUpload: ChunkedUploadClient;
|
|
288
314
|
/**
|
|
289
315
|
* Submit a run and wait for it to reach a terminal state. Returns the
|
|
290
316
|
* final `Run` record. For long-running flows, prefer `submitRun` +
|
|
@@ -300,7 +326,7 @@ export declare class AntpathClient {
|
|
|
300
326
|
* before sending so credentials never enter the hashed submission or
|
|
301
327
|
* the run snapshot.
|
|
302
328
|
*
|
|
303
|
-
* Unstaged
|
|
329
|
+
* Unstaged inline skills (`Skill.fromFiles` / `Skill.fromPath`
|
|
304
330
|
* without a prior `.upload`) are accepted: the SDK switches to a
|
|
305
331
|
* multipart body that carries the canonical zip bytes alongside the
|
|
306
332
|
* JSON submission. The dashboard BFF ingests each one through the
|
|
@@ -317,16 +343,21 @@ export declare class AntpathClient {
|
|
|
317
343
|
* attempts, indexed events (inline + cursor for the tail), raw
|
|
318
344
|
* provider-event Storage manifest, outputs, capture failures,
|
|
319
345
|
* proxy-call audit, pinned workspace skills, provider skills,
|
|
320
|
-
*
|
|
346
|
+
* inline skills. Backed by the same endpoint as `getRun` but
|
|
321
347
|
* typed against the full wire shape — use this when you need
|
|
322
348
|
* fields beyond `{id, status, timestamps, usage}`.
|
|
323
349
|
*/
|
|
324
350
|
getRunUnit(runId: string): Promise<RunUnit>;
|
|
325
351
|
listEvents(runId: string): Promise<readonly RunEvent[]>;
|
|
326
352
|
/**
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
353
|
+
* Yield run events as they arrive. The default transport is SSE
|
|
354
|
+
* (`/api/runs/:id/events/stream`); on disconnect it falls back to
|
|
355
|
+
* polling for the remaining lifetime of the run, so older
|
|
356
|
+
* deployments without the SSE endpoint and transient network blips
|
|
357
|
+
* both keep working.
|
|
358
|
+
*
|
|
359
|
+
* Stops when the run reaches a terminal state, when the signal is
|
|
360
|
+
* aborted, or when the caller breaks out of the iterator.
|
|
330
361
|
*/
|
|
331
362
|
streamEvents(runId: string, options?: StreamEventsOptions): AsyncIterable<RunEvent>;
|
|
332
363
|
/**
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { HttpClient, operations, reportTelemetryError } from "./_shared/index.js";
|
|
1
|
+
import { DEFAULT_RUN_PROVIDER, HttpClient, operations, reportTelemetryError } from "./_shared/index.js";
|
|
2
|
+
import { uploadAssetToR2 } from "./asset-upload.js";
|
|
2
3
|
import { SDK_VERSION } from "./version.js";
|
|
3
4
|
import { AgentsMd } from "./agents-md.js";
|
|
4
5
|
import { File } from "./file.js";
|
|
@@ -9,13 +10,23 @@ import { Skill } from "./skill.js";
|
|
|
9
10
|
* Lightweight reference to a submitted run. All read-back operations
|
|
10
11
|
* delegate to the same `AntpathClient` and the same operations module
|
|
11
12
|
* the CLI uses, so SDK and CLI never drift.
|
|
13
|
+
*
|
|
14
|
+
* `runtimeManifest` is the per-run, per-provider description of where
|
|
15
|
+
* antpath placed things inside the agent container, plus the merged
|
|
16
|
+
* env-var bag delivered via `RUNTIME.env` / `RUNTIME.json`. Populated
|
|
17
|
+
* on instances returned by `submitRun`; instances constructed by `id`
|
|
18
|
+
* elsewhere call `.get()` to populate the field via the GET response.
|
|
12
19
|
*/
|
|
13
20
|
export class RunRef {
|
|
14
21
|
runId;
|
|
22
|
+
runtimeManifest;
|
|
15
23
|
#client;
|
|
16
|
-
constructor(client, runId) {
|
|
24
|
+
constructor(client, runId, runtimeManifest) {
|
|
17
25
|
this.#client = client;
|
|
18
26
|
this.runId = runId;
|
|
27
|
+
if (runtimeManifest) {
|
|
28
|
+
this.runtimeManifest = runtimeManifest;
|
|
29
|
+
}
|
|
19
30
|
}
|
|
20
31
|
get() {
|
|
21
32
|
return this.#client.getRun(this.runId);
|
|
@@ -259,17 +270,6 @@ export class AntpathClient {
|
|
|
259
270
|
async _uploadFile(args) {
|
|
260
271
|
return this.files._uploadFile(args);
|
|
261
272
|
}
|
|
262
|
-
/**
|
|
263
|
-
* Internal: chunked-upload entry point for `Skill.upload` and
|
|
264
|
-
* `File.upload` when the bundle exceeds the 6 MiB threshold.
|
|
265
|
-
* Drives the three-step TUS flow: init → uploadChunked → finalize.
|
|
266
|
-
* NOT part of the public API — the underscore is a "do not call
|
|
267
|
-
* from user code" marker.
|
|
268
|
-
*/
|
|
269
|
-
_chunkedUpload = {
|
|
270
|
-
init: (args) => operations.initAssetUpload(this.#http, args),
|
|
271
|
-
finalize: (args) => operations.finalizeAssetUpload(this.#http, args)
|
|
272
|
-
};
|
|
273
273
|
/**
|
|
274
274
|
* Submit a run and wait for it to reach a terminal state. Returns the
|
|
275
275
|
* final `Run` record. For long-running flows, prefer `submitRun` +
|
|
@@ -288,7 +288,7 @@ export class AntpathClient {
|
|
|
288
288
|
* before sending so credentials never enter the hashed submission or
|
|
289
289
|
* the run snapshot.
|
|
290
290
|
*
|
|
291
|
-
* Unstaged
|
|
291
|
+
* Unstaged inline skills (`Skill.fromFiles` / `Skill.fromPath`
|
|
292
292
|
* without a prior `.upload`) are accepted: the SDK switches to a
|
|
293
293
|
* multipart body that carries the canonical zip bytes alongside the
|
|
294
294
|
* JSON submission. The dashboard BFF ingests each one through the
|
|
@@ -302,8 +302,24 @@ export class AntpathClient {
|
|
|
302
302
|
if (!options || typeof options !== "object") {
|
|
303
303
|
throw new Error("AntpathClient.submitRun: options is required");
|
|
304
304
|
}
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
const provider = options.provider ?? DEFAULT_RUN_PROVIDER;
|
|
306
|
+
if (!options.secrets) {
|
|
307
|
+
throw new Error("AntpathClient.submitRun: secrets is required");
|
|
308
|
+
}
|
|
309
|
+
// The matching provider's apiKey is required; every OTHER provider's
|
|
310
|
+
// secret block must be absent. The shared parser re-runs this check
|
|
311
|
+
// on the server; failing early here gives the caller a synchronous
|
|
312
|
+
// error before any network call.
|
|
313
|
+
const providerSecret = options.secrets[provider];
|
|
314
|
+
if (!providerSecret?.apiKey) {
|
|
315
|
+
throw new Error(`AntpathClient.submitRun: secrets.${provider}.apiKey is required`);
|
|
316
|
+
}
|
|
317
|
+
for (const other of ["anthropic", "deepseek", "openai", "gemini", "mistral"]) {
|
|
318
|
+
if (other === provider)
|
|
319
|
+
continue;
|
|
320
|
+
if (options.secrets[other] !== undefined) {
|
|
321
|
+
throw new Error(`AntpathClient.submitRun: secrets.${other} is not allowed when provider is ${provider}`);
|
|
322
|
+
}
|
|
307
323
|
}
|
|
308
324
|
if (typeof options.model !== "string" || !options.model) {
|
|
309
325
|
throw new Error("AntpathClient.submitRun: model is required");
|
|
@@ -311,22 +327,25 @@ export class AntpathClient {
|
|
|
311
327
|
const prompt = normalisePrompt(options.prompt);
|
|
312
328
|
const { endpoints: proxyEndpointDeclarations, auth: proxyEndpointAuthFromInstances } = splitProxyEndpoints(options.proxyEndpoints ?? []);
|
|
313
329
|
const mergedProxyAuth = mergeProxyEndpointAuth(proxyEndpointAuthFromInstances, options.secrets.proxyEndpointAuth ?? []);
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
330
|
+
// Phase B + D: walk Skill / AgentsMd / File instances, materialize
|
|
331
|
+
// every draft (local bytes) to R2 BEFORE the submit round-trip.
|
|
332
|
+
// The wire shape carries only kind:"r2" / kind:"provider" refs.
|
|
333
|
+
const r2Skills = await materializeSkills(this.#http, options.skills ?? []);
|
|
334
|
+
const r2AgentsMd = await materializeAgentsMd(this.#http, options.agentsMd ?? []);
|
|
335
|
+
const r2Files = await materializeFiles(this.#http, options.files ?? []);
|
|
317
336
|
const { submissionMcpServers, mergedMcpSecrets } = mergeMcpServers(options.mcpServers ?? [], options.secrets.mcpServers ?? []);
|
|
318
337
|
const submission = {
|
|
319
338
|
model: options.model,
|
|
320
339
|
...(options.system ? { system: options.system } : {}),
|
|
321
340
|
prompt,
|
|
322
|
-
skills:
|
|
323
|
-
agentsMd:
|
|
324
|
-
files:
|
|
341
|
+
skills: r2Skills,
|
|
342
|
+
agentsMd: r2AgentsMd,
|
|
343
|
+
files: r2Files,
|
|
325
344
|
// submissionMcpServers may contain workspace refs of the shape
|
|
326
345
|
// {kind:"workspace", id:"mcp_..."}. The BFF runs
|
|
327
346
|
// `resolveWorkspaceMcpRefsInSubmission` BEFORE the shared parser
|
|
328
347
|
// and replaces them with the resolved {name, url}, so by the
|
|
329
|
-
// time anything reads
|
|
348
|
+
// time anything reads PlatformSubmission post-parse the
|
|
330
349
|
// shape matches McpServerRef. The cast acknowledges that the
|
|
331
350
|
// SDK is producing pre-resolution wire input here.
|
|
332
351
|
mcpServers: submissionMcpServers,
|
|
@@ -343,6 +362,15 @@ export class AntpathClient {
|
|
|
343
362
|
};
|
|
344
363
|
const request = {
|
|
345
364
|
idempotencyKey: options.idempotencyKey ?? generateIdempotencyKey(),
|
|
365
|
+
// Always include `provider` on the wire so dashboard / proxy
|
|
366
|
+
// tooling never has to second-guess what the runtime saw. The
|
|
367
|
+
// shared parser still defaults to `anthropic` when callers omit
|
|
368
|
+
// the field entirely, but the SDK has resolved it by here.
|
|
369
|
+
provider,
|
|
370
|
+
// `runtime` is optional on the wire — absent means let the
|
|
371
|
+
// dispatcher auto-route. Only emit it when the caller asked for
|
|
372
|
+
// a specific runtime so the wire shape stays minimal.
|
|
373
|
+
...(options.runtime ? { runtime: options.runtime } : {}),
|
|
346
374
|
submission,
|
|
347
375
|
...(options.cleanup ? { cleanup: options.cleanup } : {}),
|
|
348
376
|
secrets,
|
|
@@ -350,12 +378,11 @@ export class AntpathClient {
|
|
|
350
378
|
? { proxyEndpoints: proxyEndpointDeclarations }
|
|
351
379
|
: {})
|
|
352
380
|
};
|
|
353
|
-
|
|
381
|
+
// All inline refs were materialized to R2 above, so submitRun is
|
|
382
|
+
// always a plain JSON post. The multipart code path is gone.
|
|
354
383
|
let run;
|
|
355
384
|
try {
|
|
356
|
-
run =
|
|
357
|
-
? await operations.submitRunFlatMultipart(this.#http, request, transientBundles, transientAgentsMdParts, transientFileParts)
|
|
358
|
-
: await operations.submitRunFlat(this.#http, request);
|
|
385
|
+
run = await operations.submitRun(this.#http, request);
|
|
359
386
|
}
|
|
360
387
|
catch (err) {
|
|
361
388
|
// Fire-and-forget telemetry for unexpected submit failures so we
|
|
@@ -375,13 +402,12 @@ export class AntpathClient {
|
|
|
375
402
|
status: typeof err.status === "number"
|
|
376
403
|
? err.status
|
|
377
404
|
: undefined,
|
|
378
|
-
message: err?.message?.slice(0, 200) ?? null
|
|
379
|
-
multipart: isMultipart
|
|
405
|
+
message: err?.message?.slice(0, 200) ?? null
|
|
380
406
|
}
|
|
381
407
|
});
|
|
382
408
|
throw err;
|
|
383
409
|
}
|
|
384
|
-
return new RunRef(this, run.id);
|
|
410
|
+
return new RunRef(this, run.id, extractRuntimeManifest(run));
|
|
385
411
|
}
|
|
386
412
|
getRun(runId) {
|
|
387
413
|
return operations.getRun(this.#http, runId);
|
|
@@ -391,7 +417,7 @@ export class AntpathClient {
|
|
|
391
417
|
* attempts, indexed events (inline + cursor for the tail), raw
|
|
392
418
|
* provider-event Storage manifest, outputs, capture failures,
|
|
393
419
|
* proxy-call audit, pinned workspace skills, provider skills,
|
|
394
|
-
*
|
|
420
|
+
* inline skills. Backed by the same endpoint as `getRun` but
|
|
395
421
|
* typed against the full wire shape — use this when you need
|
|
396
422
|
* fields beyond `{id, status, timestamps, usage}`.
|
|
397
423
|
*/
|
|
@@ -402,19 +428,67 @@ export class AntpathClient {
|
|
|
402
428
|
return operations.listRunEvents(this.#http, runId);
|
|
403
429
|
}
|
|
404
430
|
/**
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
*
|
|
431
|
+
* Yield run events as they arrive. The default transport is SSE
|
|
432
|
+
* (`/api/runs/:id/events/stream`); on disconnect it falls back to
|
|
433
|
+
* polling for the remaining lifetime of the run, so older
|
|
434
|
+
* deployments without the SSE endpoint and transient network blips
|
|
435
|
+
* both keep working.
|
|
436
|
+
*
|
|
437
|
+
* Stops when the run reaches a terminal state, when the signal is
|
|
438
|
+
* aborted, or when the caller breaks out of the iterator.
|
|
408
439
|
*/
|
|
409
440
|
async *streamEvents(runId, options = {}) {
|
|
410
|
-
const
|
|
441
|
+
const transport = options.transport ?? "auto";
|
|
411
442
|
const signal = options.signal;
|
|
412
443
|
const seenIds = new Set();
|
|
444
|
+
let cursor;
|
|
445
|
+
if (transport !== "polling") {
|
|
446
|
+
while (!signal?.aborted) {
|
|
447
|
+
const outcome = yield* this.#streamEventsSseRound(runId, {
|
|
448
|
+
cursor: cursor,
|
|
449
|
+
signal: signal,
|
|
450
|
+
seenIds
|
|
451
|
+
});
|
|
452
|
+
cursor = outcome.nextCursor;
|
|
453
|
+
if (outcome.kind === "terminal" || outcome.kind === "aborted")
|
|
454
|
+
return;
|
|
455
|
+
if (transport === "sse")
|
|
456
|
+
return; // disconnects surface as completion
|
|
457
|
+
// "auto" — fall through to polling for the rest of the run.
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (signal?.aborted)
|
|
462
|
+
return;
|
|
463
|
+
yield* this.#streamEventsPolling(runId, { ...options, seenIds });
|
|
464
|
+
}
|
|
465
|
+
async *#streamEventsSseRound(runId, opts) {
|
|
466
|
+
const streamOpts = {};
|
|
467
|
+
if (opts.cursor !== undefined)
|
|
468
|
+
streamOpts.cursor = opts.cursor;
|
|
469
|
+
if (opts.signal !== undefined)
|
|
470
|
+
streamOpts.signal = opts.signal;
|
|
471
|
+
const iter = operations.streamRunEventsSse(this.#http, runId, streamOpts);
|
|
472
|
+
while (true) {
|
|
473
|
+
const next = await iter.next();
|
|
474
|
+
if (next.done) {
|
|
475
|
+
return next.value;
|
|
476
|
+
}
|
|
477
|
+
const event = next.value;
|
|
478
|
+
if (!opts.seenIds.has(event.id)) {
|
|
479
|
+
opts.seenIds.add(event.id);
|
|
480
|
+
yield event;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
async *#streamEventsPolling(runId, options) {
|
|
485
|
+
const intervalMs = options.intervalMs ?? 1_000;
|
|
486
|
+
const signal = options.signal;
|
|
413
487
|
while (!signal?.aborted) {
|
|
414
488
|
const events = await this.listEvents(runId);
|
|
415
489
|
for (const event of events) {
|
|
416
|
-
if (!seenIds.has(event.id)) {
|
|
417
|
-
seenIds.add(event.id);
|
|
490
|
+
if (!options.seenIds.has(event.id)) {
|
|
491
|
+
options.seenIds.add(event.id);
|
|
418
492
|
yield event;
|
|
419
493
|
}
|
|
420
494
|
}
|
|
@@ -477,6 +551,20 @@ const TERMINAL_STATUSES = new Set([
|
|
|
477
551
|
"canceled",
|
|
478
552
|
"cleaned_up"
|
|
479
553
|
]);
|
|
554
|
+
/**
|
|
555
|
+
* Pull the runtime manifest off a submitRun / getRun response. The
|
|
556
|
+
* field is optional on the wire shape (older BFFs predate it); we
|
|
557
|
+
* return `undefined` when absent rather than fabricating a default,
|
|
558
|
+
* so callers can detect deployment skew explicitly.
|
|
559
|
+
*/
|
|
560
|
+
function extractRuntimeManifest(run) {
|
|
561
|
+
if (!run || typeof run !== "object")
|
|
562
|
+
return undefined;
|
|
563
|
+
const value = run.runtimeManifest;
|
|
564
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
565
|
+
return undefined;
|
|
566
|
+
return value;
|
|
567
|
+
}
|
|
480
568
|
function isTerminal(status) {
|
|
481
569
|
return typeof status === "string" && TERMINAL_STATUSES.has(status);
|
|
482
570
|
}
|
|
@@ -524,145 +612,123 @@ function normalisePrompt(input) {
|
|
|
524
612
|
* Walk the user-provided `Skill[]`, validating each instance and
|
|
525
613
|
* producing:
|
|
526
614
|
* - `skillRefs[]` — the wire entries for `submission.skills[]`, with
|
|
527
|
-
*
|
|
528
|
-
* - `
|
|
615
|
+
* inline refs assigned positional slot ids (`transient-0`, …).
|
|
616
|
+
* - `inlineBundles[]` — the bytes for each inline skill,
|
|
529
617
|
* parallel-indexed by slot.
|
|
530
618
|
*
|
|
531
619
|
* Throws on consumed Skills (the user kept a stale reference past an
|
|
532
620
|
* `.upload(client)` call) with the same error message documented in
|
|
533
621
|
* `Skill.upload` — that mistake is loud, not silent.
|
|
534
622
|
*/
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
623
|
+
/**
|
|
624
|
+
* Walk the user-provided Skill[], materialize every draft to R2,
|
|
625
|
+
* return the wire-shape refs. Provider skills pass through.
|
|
626
|
+
*/
|
|
627
|
+
async function materializeSkills(http, skills) {
|
|
628
|
+
const out = [];
|
|
539
629
|
for (let i = 0; i < skills.length; i++) {
|
|
540
630
|
const entry = skills[i];
|
|
541
631
|
if (!(entry instanceof Skill)) {
|
|
542
632
|
throw new Error(`AntpathClient.submitRun: skills[${i}] must be a Skill instance`);
|
|
543
633
|
}
|
|
544
634
|
if (entry.isConsumed) {
|
|
545
|
-
throw new Error(`AntpathClient.submitRun: skills[${i}] was already
|
|
546
|
-
`use the returned Skill or Skill.fromId(record.id) for subsequent runs`);
|
|
635
|
+
throw new Error(`AntpathClient.submitRun: skills[${i}] was already consumed by a prior submitRun`);
|
|
547
636
|
}
|
|
548
|
-
|
|
549
|
-
|
|
637
|
+
const ref = entry.ref;
|
|
638
|
+
if (ref.kind === "draft") {
|
|
639
|
+
const bundle = entry._takeDraftBundle();
|
|
550
640
|
if (!bundle) {
|
|
551
|
-
|
|
552
|
-
throw new Error(`AntpathClient.submitRun: skills[${i}] is unstaged but has no bytes (internal invariant violated)`);
|
|
641
|
+
throw new Error(`AntpathClient.submitRun: skills[${i}] is draft but has no bytes`);
|
|
553
642
|
}
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
kind: "transient",
|
|
557
|
-
slot,
|
|
558
|
-
name: bundle.name,
|
|
559
|
-
contentHash: bundle.contentHash
|
|
560
|
-
});
|
|
561
|
-
// Anthropic filenames forbid `<>:"|?*\/` and control chars 0-31,
|
|
562
|
-
// so the multipart filename uses hyphen separators. The 12-char
|
|
563
|
-
// hash prefix is enough for janitor / orphan reconciliation;
|
|
564
|
-
// the BFF stamps the full run-scoped filename once it knows the
|
|
565
|
-
// run id.
|
|
566
|
-
const shortHash = bundle.contentHash.replace(/^sha256:/, "").slice(0, 12);
|
|
567
|
-
transientBundles.push({
|
|
568
|
-
slot,
|
|
643
|
+
const uploaded = await uploadAssetToR2({
|
|
644
|
+
http,
|
|
569
645
|
bytes: bundle.bytes,
|
|
570
|
-
|
|
646
|
+
hash: bundle.contentHash
|
|
647
|
+
});
|
|
648
|
+
out.push({
|
|
649
|
+
kind: "r2",
|
|
650
|
+
path: uploaded.path,
|
|
651
|
+
hash: uploaded.hash,
|
|
652
|
+
sizeBytes: uploaded.sizeBytes,
|
|
653
|
+
name: bundle.name
|
|
571
654
|
});
|
|
572
655
|
continue;
|
|
573
656
|
}
|
|
574
|
-
|
|
657
|
+
// Provider or r2 (re-used from a previous materialization).
|
|
658
|
+
out.push(ref);
|
|
575
659
|
}
|
|
576
|
-
return
|
|
660
|
+
return out;
|
|
577
661
|
}
|
|
578
|
-
/**
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
* - `agentsMdRefs[]` — the wire entries for `submission.agentsMd[]`,
|
|
582
|
-
* with transient refs assigned positional slot ids
|
|
583
|
-
* (`agentsmd-0`, `agentsmd-1`, …).
|
|
584
|
-
* - `transientAgentsMdParts[]` — the content for each transient
|
|
585
|
-
* AgentsMd, parallel-indexed by slot.
|
|
586
|
-
*/
|
|
587
|
-
function prepareAgentsMd(agentsMds) {
|
|
588
|
-
const agentsMdRefs = [];
|
|
589
|
-
const transientAgentsMdParts = [];
|
|
590
|
-
let transientIndex = 0;
|
|
662
|
+
/** Materialize draft AgentsMd[] to R2; pass-through any already-r2. */
|
|
663
|
+
async function materializeAgentsMd(http, agentsMds) {
|
|
664
|
+
const out = [];
|
|
591
665
|
for (let i = 0; i < agentsMds.length; i++) {
|
|
592
666
|
const entry = agentsMds[i];
|
|
593
667
|
if (!(entry instanceof AgentsMd)) {
|
|
594
668
|
throw new Error(`AntpathClient.submitRun: agentsMd[${i}] must be an AgentsMd instance`);
|
|
595
669
|
}
|
|
596
670
|
if (entry.isConsumed) {
|
|
597
|
-
throw new Error(`AntpathClient.submitRun: agentsMd[${i}] was already
|
|
598
|
-
`use the returned AgentsMd or AgentsMd.fromId(record.id) for subsequent runs`);
|
|
671
|
+
throw new Error(`AntpathClient.submitRun: agentsMd[${i}] was already consumed by a prior submitRun`);
|
|
599
672
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
673
|
+
const ref = entry.ref;
|
|
674
|
+
if (ref.kind === "draft") {
|
|
675
|
+
const bundle = entry._takeDraftBundle();
|
|
676
|
+
if (!bundle) {
|
|
677
|
+
throw new Error(`AntpathClient.submitRun: agentsMd[${i}] is draft but has no bytes`);
|
|
604
678
|
}
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
kind: "
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
transientAgentsMdParts.push({
|
|
613
|
-
slot,
|
|
614
|
-
content: unstaged.content,
|
|
615
|
-
filename: `${unstaged.name}.md`
|
|
679
|
+
const uploaded = await uploadAssetToR2({ http, bytes: bundle.bytes, hash: bundle.contentHash });
|
|
680
|
+
out.push({
|
|
681
|
+
kind: "r2",
|
|
682
|
+
path: uploaded.path,
|
|
683
|
+
hash: uploaded.hash,
|
|
684
|
+
sizeBytes: uploaded.sizeBytes,
|
|
685
|
+
name: bundle.name
|
|
616
686
|
});
|
|
617
687
|
continue;
|
|
618
688
|
}
|
|
619
|
-
|
|
689
|
+
out.push(ref);
|
|
620
690
|
}
|
|
621
|
-
return
|
|
691
|
+
return out;
|
|
622
692
|
}
|
|
623
|
-
/**
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
* transient refs assigned positional slot ids (`file-0`, `file-1`, …).
|
|
627
|
-
* - `transientFileParts[]` — the bytes for each transient file, parallel-indexed.
|
|
628
|
-
*/
|
|
629
|
-
function prepareFiles(files) {
|
|
630
|
-
const fileRefs = [];
|
|
631
|
-
const transientFileParts = [];
|
|
632
|
-
let transientIndex = 0;
|
|
693
|
+
/** Materialize draft File[] to R2; pass-through any already-r2. */
|
|
694
|
+
async function materializeFiles(http, files) {
|
|
695
|
+
const out = [];
|
|
633
696
|
for (let i = 0; i < files.length; i++) {
|
|
634
697
|
const entry = files[i];
|
|
635
698
|
if (!(entry instanceof File)) {
|
|
636
699
|
throw new Error(`AntpathClient.submitRun: files[${i}] must be a File instance`);
|
|
637
700
|
}
|
|
638
701
|
if (entry.isConsumed) {
|
|
639
|
-
throw new Error(`AntpathClient.submitRun: files[${i}] was already
|
|
640
|
-
`use the returned File or File.fromId(record.id) for subsequent runs`);
|
|
702
|
+
throw new Error(`AntpathClient.submitRun: files[${i}] was already consumed by a prior submitRun`);
|
|
641
703
|
}
|
|
642
|
-
|
|
643
|
-
|
|
704
|
+
const ref = entry.ref;
|
|
705
|
+
if (ref.kind === "draft") {
|
|
706
|
+
const bundle = entry._takeDraftBundle();
|
|
644
707
|
if (!bundle) {
|
|
645
|
-
throw new Error(`AntpathClient.submitRun: files[${i}] is
|
|
708
|
+
throw new Error(`AntpathClient.submitRun: files[${i}] is draft but has no bytes`);
|
|
646
709
|
}
|
|
647
|
-
const
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
710
|
+
const uploaded = await uploadAssetToR2({ http, bytes: bundle.bytes, hash: bundle.contentHash });
|
|
711
|
+
out.push(bundle.mountPath !== undefined
|
|
712
|
+
? {
|
|
713
|
+
kind: "r2",
|
|
714
|
+
path: uploaded.path,
|
|
715
|
+
hash: uploaded.hash,
|
|
716
|
+
sizeBytes: uploaded.sizeBytes,
|
|
717
|
+
name: bundle.name,
|
|
718
|
+
mountPath: bundle.mountPath
|
|
719
|
+
}
|
|
720
|
+
: {
|
|
721
|
+
kind: "r2",
|
|
722
|
+
path: uploaded.path,
|
|
723
|
+
hash: uploaded.hash,
|
|
724
|
+
sizeBytes: uploaded.sizeBytes,
|
|
725
|
+
name: bundle.name
|
|
726
|
+
});
|
|
661
727
|
continue;
|
|
662
728
|
}
|
|
663
|
-
|
|
729
|
+
out.push(ref);
|
|
664
730
|
}
|
|
665
|
-
return
|
|
731
|
+
return out;
|
|
666
732
|
}
|
|
667
733
|
function mergeMcpServers(inputs, explicitSecrets) {
|
|
668
734
|
const submissionMcpServers = [];
|