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
CHANGED
|
@@ -58,8 +58,6 @@ var TERMINAL_RUN_STATUSES = [
|
|
|
58
58
|
var terminalRunStatuses = new Set(TERMINAL_RUN_STATUSES);
|
|
59
59
|
|
|
60
60
|
// ../shared/dist/blueprint.js
|
|
61
|
-
var SKILL_ID_PATTERN = /^skl_[A-Za-z0-9_-]{8,128}$/;
|
|
62
|
-
var SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]{0,127}$/;
|
|
63
61
|
var SKILL_BUNDLE_LIMITS = {
|
|
64
62
|
/** Compressed (.zip) ceiling. */
|
|
65
63
|
maxCompressedBytes: 10 * 1024 * 1024,
|
|
@@ -76,26 +74,14 @@ var SKILL_BUNDLE_LIMITS = {
|
|
|
76
74
|
/** Stored directory mode. */
|
|
77
75
|
defaultDirMode: 493
|
|
78
76
|
};
|
|
79
|
-
var
|
|
80
|
-
var
|
|
81
|
-
function parseSkillRef(input, path
|
|
77
|
+
var INLINE_CONTENT_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
78
|
+
var R2_ASSET_PATH_PATTERN = /^assets\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/[0-9a-f]{64}$/;
|
|
79
|
+
function parseSkillRef(input, path) {
|
|
82
80
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
83
81
|
throw new Error(`${path} must be a SkillRef object`);
|
|
84
82
|
}
|
|
85
83
|
const record = input;
|
|
86
84
|
const kind = record.kind;
|
|
87
|
-
if (kind === "workspace") {
|
|
88
|
-
for (const key of Object.keys(record)) {
|
|
89
|
-
if (key !== "kind" && key !== "id") {
|
|
90
|
-
throw new Error(`${path} contains unexpected field for workspace SkillRef: ${key}`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const id = record.id;
|
|
94
|
-
if (typeof id !== "string" || !SKILL_ID_PATTERN.test(id)) {
|
|
95
|
-
throw new Error(`${path}.id must match ${SKILL_ID_PATTERN.source}`);
|
|
96
|
-
}
|
|
97
|
-
return { kind: "workspace", id };
|
|
98
|
-
}
|
|
99
85
|
if (kind === "provider") {
|
|
100
86
|
for (const key of Object.keys(record)) {
|
|
101
87
|
if (key !== "kind" && key !== "vendor" && key !== "skillId" && key !== "version") {
|
|
@@ -121,30 +107,50 @@ function parseSkillRef(input, path, options = {}) {
|
|
|
121
107
|
...version !== void 0 ? { version } : {}
|
|
122
108
|
};
|
|
123
109
|
}
|
|
124
|
-
if (kind === "
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const slot = record.slot;
|
|
134
|
-
if (typeof slot !== "string" || !TRANSIENT_SLOT_PATTERN.test(slot)) {
|
|
135
|
-
throw new Error(`${path}.slot must match ${TRANSIENT_SLOT_PATTERN.source}`);
|
|
136
|
-
}
|
|
137
|
-
const name = record.name;
|
|
138
|
-
if (typeof name !== "string" || !SKILL_NAME_PATTERN.test(name)) {
|
|
139
|
-
throw new Error(`${path}.name must match ${SKILL_NAME_PATTERN.source}`);
|
|
140
|
-
}
|
|
141
|
-
const contentHash = record.contentHash;
|
|
142
|
-
if (typeof contentHash !== "string" || !TRANSIENT_CONTENT_HASH_PATTERN.test(contentHash)) {
|
|
143
|
-
throw new Error(`${path}.contentHash must match ${TRANSIENT_CONTENT_HASH_PATTERN.source}`);
|
|
110
|
+
if (kind === "r2") {
|
|
111
|
+
return parseR2RefFields(record, path);
|
|
112
|
+
}
|
|
113
|
+
throw new Error(`${path}.kind must be 'provider' or 'r2'`);
|
|
114
|
+
}
|
|
115
|
+
function parseR2RefFields(record, path) {
|
|
116
|
+
for (const key of Object.keys(record)) {
|
|
117
|
+
if (key !== "kind" && key !== "path" && key !== "hash" && key !== "sizeBytes" && key !== "name" && key !== "mountPath") {
|
|
118
|
+
throw new Error(`${path} contains unexpected field for r2 ref: ${key}`);
|
|
144
119
|
}
|
|
145
|
-
return { kind: "transient", slot, name, contentHash };
|
|
146
120
|
}
|
|
147
|
-
|
|
121
|
+
const r2Path = record.path;
|
|
122
|
+
if (typeof r2Path !== "string" || !R2_ASSET_PATH_PATTERN.test(r2Path)) {
|
|
123
|
+
throw new Error(`${path}.path must match ${R2_ASSET_PATH_PATTERN.source}`);
|
|
124
|
+
}
|
|
125
|
+
const hash = record.hash;
|
|
126
|
+
if (typeof hash !== "string" || !INLINE_CONTENT_HASH_PATTERN.test(hash)) {
|
|
127
|
+
throw new Error(`${path}.hash must match ${INLINE_CONTENT_HASH_PATTERN.source}`);
|
|
128
|
+
}
|
|
129
|
+
const pathHash = r2Path.slice(r2Path.length - 64);
|
|
130
|
+
const hashHex = hash.slice("sha256:".length);
|
|
131
|
+
if (pathHash !== hashHex) {
|
|
132
|
+
throw new Error(`${path}.path hash segment does not match ${path}.hash`);
|
|
133
|
+
}
|
|
134
|
+
const sizeBytes = record.sizeBytes;
|
|
135
|
+
if (typeof sizeBytes !== "number" || !Number.isInteger(sizeBytes) || sizeBytes <= 0) {
|
|
136
|
+
throw new Error(`${path}.sizeBytes must be a positive integer`);
|
|
137
|
+
}
|
|
138
|
+
const name = record.name;
|
|
139
|
+
if (typeof name !== "string" || name.length === 0 || name.length > 128) {
|
|
140
|
+
throw new Error(`${path}.name must be a non-empty string (<= 128 chars)`);
|
|
141
|
+
}
|
|
142
|
+
const mountPath = record.mountPath;
|
|
143
|
+
if (mountPath !== void 0 && (typeof mountPath !== "string" || mountPath.length === 0)) {
|
|
144
|
+
throw new Error(`${path}.mountPath, when provided, must be a non-empty string`);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
kind: "r2",
|
|
148
|
+
path: r2Path,
|
|
149
|
+
hash,
|
|
150
|
+
sizeBytes,
|
|
151
|
+
name,
|
|
152
|
+
...mountPath !== void 0 ? { mountPath } : {}
|
|
153
|
+
};
|
|
148
154
|
}
|
|
149
155
|
var SkillBundleValidationError = class extends Error {
|
|
150
156
|
constructor(message) {
|
|
@@ -205,15 +211,19 @@ function validateSkillBundleEntry(input) {
|
|
|
205
211
|
}
|
|
206
212
|
return { path, size: input.size, mode };
|
|
207
213
|
}
|
|
214
|
+
var REMOTE_MCP_TRANSPORTS = ["http", "sse"];
|
|
215
|
+
var REMOTE_MCP_STDIO_REJECTED_MESSAGE = "stdio MCP servers are not supported by Antpath. Antpath supports remote MCP servers over HTTP/SSE only.";
|
|
216
|
+
var STDIO_ONLY_FIELDS = ["command", "args", "env"];
|
|
208
217
|
var MCP_SERVER_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
209
218
|
function parseMcpServerRef(input, path) {
|
|
210
219
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
211
220
|
throw new Error(`${path} must be an object`);
|
|
212
221
|
}
|
|
213
222
|
const record = input;
|
|
223
|
+
rejectStdioMcpShape(record);
|
|
214
224
|
for (const key of Object.keys(record)) {
|
|
215
|
-
if (key !== "name" && key !== "url") {
|
|
216
|
-
throw new Error(`${path}.${key} is not an allowed field for McpServerRef; permitted: name, url`);
|
|
225
|
+
if (key !== "name" && key !== "url" && key !== "transport") {
|
|
226
|
+
throw new Error(`${path}.${key} is not an allowed field for McpServerRef; permitted: name, url, transport`);
|
|
217
227
|
}
|
|
218
228
|
}
|
|
219
229
|
const name = record.name;
|
|
@@ -238,19 +248,42 @@ function parseMcpServerRef(input, path) {
|
|
|
238
248
|
}
|
|
239
249
|
throw new Error(`${path}.url is not a valid URL: ${url}`);
|
|
240
250
|
}
|
|
241
|
-
|
|
251
|
+
const transport = parseRemoteMcpTransport(record.transport, `${path}.transport`);
|
|
252
|
+
return transport ? { name, url, transport } : { name, url };
|
|
253
|
+
}
|
|
254
|
+
function rejectStdioMcpShape(record) {
|
|
255
|
+
if (record.transport === "stdio") {
|
|
256
|
+
throw new Error(REMOTE_MCP_STDIO_REJECTED_MESSAGE);
|
|
257
|
+
}
|
|
258
|
+
for (const field of STDIO_ONLY_FIELDS) {
|
|
259
|
+
if (record[field] !== void 0) {
|
|
260
|
+
throw new Error(REMOTE_MCP_STDIO_REJECTED_MESSAGE);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function parseRemoteMcpTransport(input, field) {
|
|
265
|
+
if (input === void 0) {
|
|
266
|
+
return void 0;
|
|
267
|
+
}
|
|
268
|
+
if (typeof input !== "string" || !REMOTE_MCP_TRANSPORTS.includes(input)) {
|
|
269
|
+
throw new Error(`${field} must be one of: ${REMOTE_MCP_TRANSPORTS.join(", ")} (got ${JSON.stringify(input)})`);
|
|
270
|
+
}
|
|
271
|
+
return input;
|
|
242
272
|
}
|
|
243
273
|
function parseBlueprintMcpServerRef(input, path) {
|
|
244
274
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
245
275
|
throw new Error(`${path} must be an object`);
|
|
246
276
|
}
|
|
247
277
|
const record = input;
|
|
278
|
+
rejectStdioMcpShape(record);
|
|
248
279
|
for (const key of Object.keys(record)) {
|
|
249
|
-
if (key !== "name" && key !== "url" && key !== "headers") {
|
|
250
|
-
throw new Error(`${path}.${key} is not an allowed field for BlueprintMcpServer; permitted: name, url, headers`);
|
|
280
|
+
if (key !== "name" && key !== "url" && key !== "headers" && key !== "transport") {
|
|
281
|
+
throw new Error(`${path}.${key} is not an allowed field for BlueprintMcpServer; permitted: name, url, transport, headers`);
|
|
251
282
|
}
|
|
252
283
|
}
|
|
253
284
|
const stripped = { name: record.name, url: record.url };
|
|
285
|
+
if (record.transport !== void 0)
|
|
286
|
+
stripped.transport = record.transport;
|
|
254
287
|
const ref = parseMcpServerRef(stripped, path);
|
|
255
288
|
const rawHeaders = record.headers;
|
|
256
289
|
if (rawHeaders === void 0) {
|
|
@@ -307,7 +340,7 @@ function parseBlueprint(input) {
|
|
|
307
340
|
...skills !== void 0 ? { skills } : {},
|
|
308
341
|
...mcpServers !== void 0 ? { mcpServers } : {},
|
|
309
342
|
// environment / cleanup / proxyEndpoints / metadata: passed through
|
|
310
|
-
// as-is — the BFF revalidates them via `
|
|
343
|
+
// as-is — the BFF revalidates them via `parseRunSubmissionRequest`,
|
|
311
344
|
// so duplicating the heavyweight parsers here would mean two sources
|
|
312
345
|
// of truth. The CLI surfaces structural errors at submission time.
|
|
313
346
|
...record.environment !== void 0 ? { environment: record.environment } : {},
|
|
@@ -346,7 +379,7 @@ function parseBlueprintSkills(value) {
|
|
|
346
379
|
if (!Array.isArray(value)) {
|
|
347
380
|
throw new Error("Blueprint.skills must be an array");
|
|
348
381
|
}
|
|
349
|
-
return value.map((item, index) => parseSkillRef(item, `Blueprint.skills[${index}]
|
|
382
|
+
return value.map((item, index) => parseSkillRef(item, `Blueprint.skills[${index}]`));
|
|
350
383
|
}
|
|
351
384
|
function parseBlueprintMcpServers(value) {
|
|
352
385
|
if (value === void 0) {
|
|
@@ -367,6 +400,15 @@ function parseBlueprintMcpServers(value) {
|
|
|
367
400
|
}
|
|
368
401
|
|
|
369
402
|
// ../shared/dist/submission.js
|
|
403
|
+
var RUN_PROVIDERS = [
|
|
404
|
+
"anthropic",
|
|
405
|
+
"deepseek",
|
|
406
|
+
"openai",
|
|
407
|
+
"gemini",
|
|
408
|
+
"mistral"
|
|
409
|
+
];
|
|
410
|
+
var DEFAULT_RUN_PROVIDER = "anthropic";
|
|
411
|
+
var RUNTIME_KINDS = ["native", "managed"];
|
|
370
412
|
var PROXY_ENDPOINT_DEFAULTS = {
|
|
371
413
|
allowHeaders: [],
|
|
372
414
|
responseMode: "headers_only",
|
|
@@ -377,9 +419,22 @@ var PROXY_ENDPOINT_DEFAULTS = {
|
|
|
377
419
|
responseByteBudget: 1024 * 1024
|
|
378
420
|
};
|
|
379
421
|
|
|
422
|
+
// ../shared/dist/runtime-manifest.js
|
|
423
|
+
var ANTHROPIC_PATHS = Object.freeze({
|
|
424
|
+
skillsRoot: "/workspace/skills",
|
|
425
|
+
filesRoot: "/mnt/session/uploads/antpath/files",
|
|
426
|
+
assetsRoot: "/mnt/session/uploads/antpath/assets",
|
|
427
|
+
outputsRoot: "/mnt/session/outputs",
|
|
428
|
+
antpathCli: "/mnt/session/uploads/antpath/antpath",
|
|
429
|
+
indexJson: "/mnt/session/uploads/antpath/index.json",
|
|
430
|
+
readme: "/mnt/session/uploads/antpath/SKILLS.md",
|
|
431
|
+
runtimeJson: "/mnt/session/uploads/antpath/RUNTIME.json",
|
|
432
|
+
runtimeEnv: "/mnt/session/uploads/antpath/RUNTIME.env"
|
|
433
|
+
});
|
|
434
|
+
|
|
380
435
|
// ../shared/dist/stable.js
|
|
381
436
|
import { createHash } from "node:crypto";
|
|
382
|
-
var ANTPATH_DEFAULT_BASE_URL = "https://
|
|
437
|
+
var ANTPATH_DEFAULT_BASE_URL = "https://api.antpath.ai";
|
|
383
438
|
|
|
384
439
|
// ../shared/dist/sdk-secrets.js
|
|
385
440
|
var SECRET_PATTERNS = [
|
|
@@ -551,17 +606,181 @@ __export(operations_exports, {
|
|
|
551
606
|
listOutputs: () => listOutputs,
|
|
552
607
|
listRunEvents: () => listRunEvents,
|
|
553
608
|
listSkills: () => listSkills,
|
|
609
|
+
streamRunEventsSse: () => streamRunEventsSse,
|
|
554
610
|
submitRun: () => submitRun,
|
|
555
|
-
|
|
556
|
-
submitRunFlatMultipart: () => submitRunFlatMultipart,
|
|
611
|
+
submitRunMultipart: () => submitRunMultipart,
|
|
557
612
|
whoami: () => whoami
|
|
558
613
|
});
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
614
|
+
|
|
615
|
+
// ../shared/dist/sse.js
|
|
616
|
+
var SseParser = class {
|
|
617
|
+
#buffer = "";
|
|
618
|
+
#decoder = new TextDecoder("utf-8");
|
|
619
|
+
#eventType = "";
|
|
620
|
+
#dataLines = [];
|
|
621
|
+
#lastEventId;
|
|
622
|
+
#retry;
|
|
623
|
+
/**
|
|
624
|
+
* Push a chunk of raw bytes through the parser. Returns any frames
|
|
625
|
+
* that completed during this chunk. Chunks may contain zero, one,
|
|
626
|
+
* or many frame boundaries — the parser handles partial trailing
|
|
627
|
+
* data internally.
|
|
628
|
+
*/
|
|
629
|
+
pushBytes(chunk) {
|
|
630
|
+
return this.pushText(this.#decoder.decode(chunk, { stream: true }));
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Push a text chunk directly. Used by the parser tests so they can
|
|
634
|
+
* exercise byte-boundary edge cases without manufacturing a
|
|
635
|
+
* `TextDecoder` round-trip.
|
|
636
|
+
*/
|
|
637
|
+
pushText(text) {
|
|
638
|
+
this.#buffer += text;
|
|
639
|
+
const frames = [];
|
|
640
|
+
let idx;
|
|
641
|
+
while ((idx = findLineBreak(this.#buffer)) !== -1) {
|
|
642
|
+
const line = this.#buffer.slice(0, idx);
|
|
643
|
+
const skip = this.#buffer[idx] === "\r" && this.#buffer[idx + 1] === "\n" ? 2 : 1;
|
|
644
|
+
this.#buffer = this.#buffer.slice(idx + skip);
|
|
645
|
+
const frame = this.#consumeLine(line);
|
|
646
|
+
if (frame)
|
|
647
|
+
frames.push(frame);
|
|
648
|
+
}
|
|
649
|
+
return frames;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Indicate end-of-stream. Returns any final frame that the dispatcher
|
|
653
|
+
* was holding when the stream closed mid-frame (no trailing blank
|
|
654
|
+
* line). The dispatcher pattern is: blank line dispatches; if the
|
|
655
|
+
* remote closes after a partial frame, that frame is dropped per the
|
|
656
|
+
* spec.
|
|
657
|
+
*/
|
|
658
|
+
flush() {
|
|
659
|
+
}
|
|
660
|
+
#consumeLine(line) {
|
|
661
|
+
if (line.length === 0) {
|
|
662
|
+
return this.#dispatch();
|
|
663
|
+
}
|
|
664
|
+
if (line.startsWith(":")) {
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
const colonIdx = line.indexOf(":");
|
|
668
|
+
let field;
|
|
669
|
+
let value;
|
|
670
|
+
if (colonIdx === -1) {
|
|
671
|
+
field = line;
|
|
672
|
+
value = "";
|
|
673
|
+
} else {
|
|
674
|
+
field = line.slice(0, colonIdx);
|
|
675
|
+
value = line.slice(colonIdx + 1);
|
|
676
|
+
if (value.startsWith(" "))
|
|
677
|
+
value = value.slice(1);
|
|
678
|
+
}
|
|
679
|
+
switch (field) {
|
|
680
|
+
case "event":
|
|
681
|
+
this.#eventType = value;
|
|
682
|
+
break;
|
|
683
|
+
case "data":
|
|
684
|
+
this.#dataLines.push(value);
|
|
685
|
+
break;
|
|
686
|
+
case "id":
|
|
687
|
+
if (!value.includes("\0")) {
|
|
688
|
+
this.#lastEventId = value;
|
|
689
|
+
}
|
|
690
|
+
break;
|
|
691
|
+
case "retry": {
|
|
692
|
+
const parsed = Number.parseInt(value, 10);
|
|
693
|
+
if (Number.isFinite(parsed) && parsed >= 0)
|
|
694
|
+
this.#retry = parsed;
|
|
695
|
+
break;
|
|
696
|
+
}
|
|
697
|
+
default:
|
|
698
|
+
break;
|
|
699
|
+
}
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
#dispatch() {
|
|
703
|
+
if (this.#dataLines.length === 0 && this.#eventType === "") {
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
const data = this.#dataLines.join("\n");
|
|
707
|
+
const event = this.#eventType === "" ? "message" : this.#eventType;
|
|
708
|
+
const frame = {
|
|
709
|
+
event,
|
|
710
|
+
data,
|
|
711
|
+
...this.#lastEventId !== void 0 ? { id: this.#lastEventId } : {},
|
|
712
|
+
...this.#retry !== void 0 ? { retry: this.#retry } : {}
|
|
713
|
+
};
|
|
714
|
+
this.#eventType = "";
|
|
715
|
+
this.#dataLines = [];
|
|
716
|
+
this.#retry = void 0;
|
|
717
|
+
return frame;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Current "last event id" — the cursor the SSE spec instructs the
|
|
721
|
+
* client to replay on automatic reconnection. Callers use this to
|
|
722
|
+
* resume after a disconnect.
|
|
723
|
+
*/
|
|
724
|
+
get lastEventId() {
|
|
725
|
+
return this.#lastEventId;
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
async function* iterateSse(body, signal) {
|
|
729
|
+
const reader = body.getReader();
|
|
730
|
+
const parser = new SseParser();
|
|
731
|
+
const ABORT_SENTINEL = /* @__PURE__ */ Symbol("aborted");
|
|
732
|
+
try {
|
|
733
|
+
while (true) {
|
|
734
|
+
if (signal?.aborted)
|
|
735
|
+
return;
|
|
736
|
+
const readPromise = reader.read();
|
|
737
|
+
let result;
|
|
738
|
+
if (signal) {
|
|
739
|
+
result = await Promise.race([
|
|
740
|
+
readPromise,
|
|
741
|
+
new Promise((resolve) => {
|
|
742
|
+
const onAbort = () => resolve(ABORT_SENTINEL);
|
|
743
|
+
if (signal.aborted) {
|
|
744
|
+
resolve(ABORT_SENTINEL);
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
748
|
+
})
|
|
749
|
+
]);
|
|
750
|
+
} else {
|
|
751
|
+
result = await readPromise;
|
|
752
|
+
}
|
|
753
|
+
if (result === ABORT_SENTINEL)
|
|
754
|
+
return;
|
|
755
|
+
if (result.done) {
|
|
756
|
+
parser.flush();
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
const value = result.value;
|
|
760
|
+
if (!value)
|
|
761
|
+
continue;
|
|
762
|
+
const frames = parser.pushBytes(value);
|
|
763
|
+
for (const frame of frames) {
|
|
764
|
+
yield frame;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
} finally {
|
|
768
|
+
try {
|
|
769
|
+
await reader.cancel();
|
|
770
|
+
} catch {
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
function findLineBreak(buffer) {
|
|
775
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
776
|
+
const code = buffer.charCodeAt(i);
|
|
777
|
+
if (code === 10 || code === 13)
|
|
778
|
+
return i;
|
|
779
|
+
}
|
|
780
|
+
return -1;
|
|
564
781
|
}
|
|
782
|
+
|
|
783
|
+
// ../shared/dist/operations.js
|
|
565
784
|
async function getRun(http, runId) {
|
|
566
785
|
const result = await http.request(`/api/runs/${encodeURIComponent(runId)}`);
|
|
567
786
|
return hasRun(result) ? result.run : result;
|
|
@@ -573,6 +792,125 @@ async function listRunEvents(http, runId) {
|
|
|
573
792
|
const result = await http.request(`/api/runs/${encodeURIComponent(runId)}/events`);
|
|
574
793
|
return result.events;
|
|
575
794
|
}
|
|
795
|
+
async function* streamRunEventsSse(http, runId, options = {}) {
|
|
796
|
+
const headers = {
|
|
797
|
+
accept: "text/event-stream"
|
|
798
|
+
};
|
|
799
|
+
if (options.cursor) {
|
|
800
|
+
headers["last-event-id"] = options.cursor;
|
|
801
|
+
}
|
|
802
|
+
const query = {};
|
|
803
|
+
if (options.cursor)
|
|
804
|
+
query.cursor = options.cursor;
|
|
805
|
+
let outcome = {
|
|
806
|
+
kind: "disconnected",
|
|
807
|
+
nextCursor: options.cursor
|
|
808
|
+
};
|
|
809
|
+
let download;
|
|
810
|
+
try {
|
|
811
|
+
const init = { method: "GET", headers };
|
|
812
|
+
if (options.signal)
|
|
813
|
+
init.signal = options.signal;
|
|
814
|
+
download = await http.download(`/api/runs/${encodeURIComponent(runId)}/events/stream`, init, query);
|
|
815
|
+
} catch (err2) {
|
|
816
|
+
return {
|
|
817
|
+
kind: options.signal?.aborted ? "aborted" : "disconnected",
|
|
818
|
+
nextCursor: options.cursor,
|
|
819
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
const body = download.response.body;
|
|
823
|
+
if (!body) {
|
|
824
|
+
return {
|
|
825
|
+
kind: "disconnected",
|
|
826
|
+
nextCursor: options.cursor,
|
|
827
|
+
error: "SSE response body was empty"
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
let cursor = options.cursor;
|
|
831
|
+
try {
|
|
832
|
+
for await (const frame of iterateSse(body, options.signal)) {
|
|
833
|
+
options.onFrame?.(frame);
|
|
834
|
+
if (frame.id)
|
|
835
|
+
cursor = frame.id;
|
|
836
|
+
switch (frame.event) {
|
|
837
|
+
case "run_event": {
|
|
838
|
+
const event = parseRunEventFrame(frame.data);
|
|
839
|
+
if (event) {
|
|
840
|
+
const payloadCursor = readStringField(event, "cursor");
|
|
841
|
+
if (payloadCursor)
|
|
842
|
+
cursor = payloadCursor;
|
|
843
|
+
yield event;
|
|
844
|
+
}
|
|
845
|
+
break;
|
|
846
|
+
}
|
|
847
|
+
case "terminal": {
|
|
848
|
+
const status = readStringField(parseJsonObject(frame.data) ?? {}, "status");
|
|
849
|
+
outcome = {
|
|
850
|
+
kind: "terminal",
|
|
851
|
+
nextCursor: cursor,
|
|
852
|
+
...status ? { terminalStatus: status } : {}
|
|
853
|
+
};
|
|
854
|
+
return outcome;
|
|
855
|
+
}
|
|
856
|
+
case "gone": {
|
|
857
|
+
outcome = {
|
|
858
|
+
kind: "disconnected",
|
|
859
|
+
nextCursor: cursor,
|
|
860
|
+
error: "run no longer exists"
|
|
861
|
+
};
|
|
862
|
+
return outcome;
|
|
863
|
+
}
|
|
864
|
+
case "error": {
|
|
865
|
+
const message = readStringField(parseJsonObject(frame.data) ?? {}, "message") ?? "SSE stream reported an error";
|
|
866
|
+
outcome = {
|
|
867
|
+
kind: "disconnected",
|
|
868
|
+
nextCursor: cursor,
|
|
869
|
+
error: message
|
|
870
|
+
};
|
|
871
|
+
return outcome;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
} catch (err2) {
|
|
876
|
+
return {
|
|
877
|
+
kind: options.signal?.aborted ? "aborted" : "disconnected",
|
|
878
|
+
nextCursor: cursor,
|
|
879
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
return {
|
|
883
|
+
kind: options.signal?.aborted ? "aborted" : "disconnected",
|
|
884
|
+
nextCursor: cursor
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
function parseRunEventFrame(data) {
|
|
888
|
+
const parsed = parseJsonObject(data);
|
|
889
|
+
if (!parsed)
|
|
890
|
+
return null;
|
|
891
|
+
const id = readStringField(parsed, "id");
|
|
892
|
+
const type = readStringField(parsed, "type");
|
|
893
|
+
if (!id || !type)
|
|
894
|
+
return null;
|
|
895
|
+
return parsed;
|
|
896
|
+
}
|
|
897
|
+
function parseJsonObject(data) {
|
|
898
|
+
if (data.length === 0)
|
|
899
|
+
return null;
|
|
900
|
+
try {
|
|
901
|
+
const value = JSON.parse(data);
|
|
902
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
903
|
+
return value;
|
|
904
|
+
}
|
|
905
|
+
return null;
|
|
906
|
+
} catch {
|
|
907
|
+
return null;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function readStringField(obj, field) {
|
|
911
|
+
const value = obj[field];
|
|
912
|
+
return typeof value === "string" ? value : void 0;
|
|
913
|
+
}
|
|
576
914
|
async function listOutputs(http, runId) {
|
|
577
915
|
const result = await http.request(`/api/runs/${encodeURIComponent(runId)}/outputs`);
|
|
578
916
|
return result.outputs;
|
|
@@ -593,28 +931,28 @@ async function downloadRunArchive(http, runId) {
|
|
|
593
931
|
const { response } = await http.download(`/api/runs/${encodeURIComponent(runId)}/download`);
|
|
594
932
|
return response;
|
|
595
933
|
}
|
|
596
|
-
async function
|
|
934
|
+
async function submitRun(http, request) {
|
|
597
935
|
return http.request("/api/runs", {
|
|
598
936
|
method: "POST",
|
|
599
937
|
body: JSON.stringify(request)
|
|
600
938
|
});
|
|
601
939
|
}
|
|
602
|
-
async function
|
|
940
|
+
async function submitRunMultipart(http, request, bundles, agentsMdParts, fileParts) {
|
|
603
941
|
const hasBundles = Array.isArray(bundles) && bundles.length > 0;
|
|
604
942
|
const hasAgentsMd = Array.isArray(agentsMdParts) && agentsMdParts.length > 0;
|
|
605
943
|
const hasFiles = Array.isArray(fileParts) && fileParts.length > 0;
|
|
606
944
|
if (!hasBundles && !hasAgentsMd && !hasFiles) {
|
|
607
|
-
throw new Error("
|
|
945
|
+
throw new Error("submitRunMultipart: bundles, agentsMdParts, or fileParts must be non-empty");
|
|
608
946
|
}
|
|
609
947
|
const form = new FormData();
|
|
610
948
|
form.append("submission", new Blob([JSON.stringify(request)], { type: "application/json" }), "submission.json");
|
|
611
949
|
const seen = /* @__PURE__ */ new Set();
|
|
612
950
|
for (const bundle of bundles) {
|
|
613
951
|
if (typeof bundle.slot !== "string" || !bundle.slot) {
|
|
614
|
-
throw new Error("
|
|
952
|
+
throw new Error("submitRunMultipart: each bundle must have a non-empty slot id");
|
|
615
953
|
}
|
|
616
954
|
if (seen.has(bundle.slot)) {
|
|
617
|
-
throw new Error(`
|
|
955
|
+
throw new Error(`submitRunMultipart: duplicate inline skill slot "${bundle.slot}"`);
|
|
618
956
|
}
|
|
619
957
|
seen.add(bundle.slot);
|
|
620
958
|
const blob = toBlob(bundle.bytes, "application/zip");
|
|
@@ -622,11 +960,11 @@ async function submitRunFlatMultipart(http, request, bundles, agentsMdParts, fil
|
|
|
622
960
|
}
|
|
623
961
|
for (const part of agentsMdParts ?? []) {
|
|
624
962
|
if (typeof part.slot !== "string" || !part.slot) {
|
|
625
|
-
throw new Error("
|
|
963
|
+
throw new Error("submitRunMultipart: each agentsMd part must have a non-empty slot id");
|
|
626
964
|
}
|
|
627
965
|
const partKey = `agentsmd:${part.slot}`;
|
|
628
966
|
if (seen.has(partKey)) {
|
|
629
|
-
throw new Error(`
|
|
967
|
+
throw new Error(`submitRunMultipart: duplicate agentsMd slot "${part.slot}"`);
|
|
630
968
|
}
|
|
631
969
|
seen.add(partKey);
|
|
632
970
|
const blob = new Blob([part.content], { type: "text/plain" });
|
|
@@ -634,11 +972,11 @@ async function submitRunFlatMultipart(http, request, bundles, agentsMdParts, fil
|
|
|
634
972
|
}
|
|
635
973
|
for (const part of fileParts ?? []) {
|
|
636
974
|
if (typeof part.slot !== "string" || !part.slot) {
|
|
637
|
-
throw new Error("
|
|
975
|
+
throw new Error("submitRunMultipart: each file part must have a non-empty slot id");
|
|
638
976
|
}
|
|
639
977
|
const partKey = `file:${part.slot}`;
|
|
640
978
|
if (seen.has(partKey)) {
|
|
641
|
-
throw new Error(`
|
|
979
|
+
throw new Error(`submitRunMultipart: duplicate file slot "${part.slot}"`);
|
|
642
980
|
}
|
|
643
981
|
seen.add(partKey);
|
|
644
982
|
const blob = toBlob(part.bytes, "application/zip");
|
|
@@ -814,7 +1152,7 @@ var USAGE_ERR = { code: 2 };
|
|
|
814
1152
|
var RUNTIME_ERR = { code: 1 };
|
|
815
1153
|
function parseCommonHostFlags(argv) {
|
|
816
1154
|
let apiToken = null;
|
|
817
|
-
let
|
|
1155
|
+
let antpathUrl = null;
|
|
818
1156
|
const rest = [];
|
|
819
1157
|
for (let i = 0; i < argv.length; i++) {
|
|
820
1158
|
const arg = argv[i];
|
|
@@ -825,11 +1163,11 @@ function parseCommonHostFlags(argv) {
|
|
|
825
1163
|
apiToken = v;
|
|
826
1164
|
continue;
|
|
827
1165
|
}
|
|
828
|
-
if (arg === "--
|
|
1166
|
+
if (arg === "--antpath-url") {
|
|
829
1167
|
const v = argv[++i];
|
|
830
1168
|
if (v === void 0)
|
|
831
|
-
return { ok: false, reason: "--
|
|
832
|
-
|
|
1169
|
+
return { ok: false, reason: "--antpath-url requires a value" };
|
|
1170
|
+
antpathUrl = v;
|
|
833
1171
|
continue;
|
|
834
1172
|
}
|
|
835
1173
|
if (arg === "--workspace" || arg === "--workspace-id") {
|
|
@@ -844,13 +1182,13 @@ function parseCommonHostFlags(argv) {
|
|
|
844
1182
|
return { ok: false, reason: "--api-token is required" };
|
|
845
1183
|
return {
|
|
846
1184
|
ok: true,
|
|
847
|
-
flags: { apiToken,
|
|
1185
|
+
flags: { apiToken, antpathUrl: antpathUrl ?? ANTPATH_DEFAULT_BASE_URL },
|
|
848
1186
|
rest
|
|
849
1187
|
};
|
|
850
1188
|
}
|
|
851
1189
|
function makeHttpClient(io2, flags) {
|
|
852
1190
|
return new HttpClient({
|
|
853
|
-
baseUrl: flags.
|
|
1191
|
+
baseUrl: flags.antpathUrl,
|
|
854
1192
|
apiToken: flags.apiToken,
|
|
855
1193
|
fetch: io2.fetchImpl
|
|
856
1194
|
});
|
|
@@ -964,6 +1302,26 @@ function takeBooleanFlag(rest, flag) {
|
|
|
964
1302
|
}
|
|
965
1303
|
return { present, remaining };
|
|
966
1304
|
}
|
|
1305
|
+
function takeOptionFlag(rest, flag) {
|
|
1306
|
+
const remaining = [];
|
|
1307
|
+
let value;
|
|
1308
|
+
const prefix = `${flag}=`;
|
|
1309
|
+
for (let i = 0; i < rest.length; i++) {
|
|
1310
|
+
const arg = rest[i];
|
|
1311
|
+
if (arg === flag) {
|
|
1312
|
+
const next = rest[++i];
|
|
1313
|
+
if (next !== void 0)
|
|
1314
|
+
value = next;
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
if (arg.startsWith(prefix)) {
|
|
1318
|
+
value = arg.slice(prefix.length);
|
|
1319
|
+
continue;
|
|
1320
|
+
}
|
|
1321
|
+
remaining.push(arg);
|
|
1322
|
+
}
|
|
1323
|
+
return { value, remaining };
|
|
1324
|
+
}
|
|
967
1325
|
|
|
968
1326
|
// dist/outputs-sync.js
|
|
969
1327
|
async function runOutputsSyncCmd(io2, dirs) {
|
|
@@ -1283,17 +1641,69 @@ async function runRunCmd(io2, argv) {
|
|
|
1283
1641
|
return USAGE_ERR;
|
|
1284
1642
|
}
|
|
1285
1643
|
let rest = common.rest;
|
|
1286
|
-
const
|
|
1287
|
-
if (
|
|
1288
|
-
io2.stderr(`${
|
|
1644
|
+
const providerFlag = takeFlagValue(rest, "--provider");
|
|
1645
|
+
if (providerFlag.error) {
|
|
1646
|
+
io2.stderr(`${providerFlag.error}
|
|
1289
1647
|
`);
|
|
1290
1648
|
return USAGE_ERR;
|
|
1291
1649
|
}
|
|
1292
|
-
rest =
|
|
1293
|
-
|
|
1294
|
-
|
|
1650
|
+
rest = providerFlag.remaining;
|
|
1651
|
+
let provider = DEFAULT_RUN_PROVIDER;
|
|
1652
|
+
if (providerFlag.value !== null) {
|
|
1653
|
+
if (!RUN_PROVIDERS.includes(providerFlag.value)) {
|
|
1654
|
+
io2.stderr(`--provider must be one of: ${RUN_PROVIDERS.join(", ")} (got: ${providerFlag.value})
|
|
1655
|
+
`);
|
|
1656
|
+
return USAGE_ERR;
|
|
1657
|
+
}
|
|
1658
|
+
provider = providerFlag.value;
|
|
1659
|
+
}
|
|
1660
|
+
const providerKeyValues = {};
|
|
1661
|
+
for (const p of RUN_PROVIDERS) {
|
|
1662
|
+
const flag = takeFlagValue(rest, `--${p}-api-key`);
|
|
1663
|
+
if (flag.error) {
|
|
1664
|
+
io2.stderr(`${flag.error}
|
|
1665
|
+
`);
|
|
1666
|
+
return USAGE_ERR;
|
|
1667
|
+
}
|
|
1668
|
+
rest = flag.remaining;
|
|
1669
|
+
if (flag.value !== null)
|
|
1670
|
+
providerKeyValues[p] = flag.value;
|
|
1671
|
+
}
|
|
1672
|
+
if (!providerKeyValues[provider]) {
|
|
1673
|
+
io2.stderr(`--${provider}-api-key is required when --provider is ${provider} (the platform does not store provider keys on your behalf)
|
|
1674
|
+
`);
|
|
1295
1675
|
return USAGE_ERR;
|
|
1296
1676
|
}
|
|
1677
|
+
for (const p of RUN_PROVIDERS) {
|
|
1678
|
+
if (p === provider)
|
|
1679
|
+
continue;
|
|
1680
|
+
if (providerKeyValues[p] !== void 0) {
|
|
1681
|
+
io2.stderr(`--${p}-api-key is not allowed when --provider is ${provider}
|
|
1682
|
+
`);
|
|
1683
|
+
return USAGE_ERR;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
const runtimeFlag = takeFlagValue(rest, "--runtime");
|
|
1687
|
+
if (runtimeFlag.error) {
|
|
1688
|
+
io2.stderr(`${runtimeFlag.error}
|
|
1689
|
+
`);
|
|
1690
|
+
return USAGE_ERR;
|
|
1691
|
+
}
|
|
1692
|
+
rest = runtimeFlag.remaining;
|
|
1693
|
+
let runtime;
|
|
1694
|
+
if (runtimeFlag.value !== null) {
|
|
1695
|
+
if (!RUNTIME_KINDS.includes(runtimeFlag.value)) {
|
|
1696
|
+
io2.stderr(`--runtime must be one of: ${RUNTIME_KINDS.join(", ")} (got: ${runtimeFlag.value})
|
|
1697
|
+
`);
|
|
1698
|
+
return USAGE_ERR;
|
|
1699
|
+
}
|
|
1700
|
+
runtime = runtimeFlag.value;
|
|
1701
|
+
if (runtime === "native" && provider !== "anthropic") {
|
|
1702
|
+
io2.stderr(`--runtime native is only supported for --provider anthropic (got: ${provider})
|
|
1703
|
+
`);
|
|
1704
|
+
return USAGE_ERR;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1297
1707
|
const idempotency = takeFlagValue(rest, "--idempotency-key");
|
|
1298
1708
|
if (idempotency.error) {
|
|
1299
1709
|
io2.stderr(`${idempotency.error}
|
|
@@ -1342,13 +1752,6 @@ async function runRunCmd(io2, argv) {
|
|
|
1342
1752
|
return USAGE_ERR;
|
|
1343
1753
|
}
|
|
1344
1754
|
rest = promptFlags.remaining;
|
|
1345
|
-
const skillFlags = collectRepeated(rest, "--skill");
|
|
1346
|
-
if (skillFlags.error) {
|
|
1347
|
-
io2.stderr(`${skillFlags.error}
|
|
1348
|
-
`);
|
|
1349
|
-
return USAGE_ERR;
|
|
1350
|
-
}
|
|
1351
|
-
rest = skillFlags.remaining;
|
|
1352
1755
|
const providerSkillFlags = collectRepeated(rest, "--provider-skill");
|
|
1353
1756
|
if (providerSkillFlags.error) {
|
|
1354
1757
|
io2.stderr(`${providerSkillFlags.error}
|
|
@@ -1406,8 +1809,8 @@ async function runRunCmd(io2, argv) {
|
|
|
1406
1809
|
let blueprint;
|
|
1407
1810
|
let mcpHeadersFromConfig = /* @__PURE__ */ new Map();
|
|
1408
1811
|
if (config.value) {
|
|
1409
|
-
if (modelFlag.value || systemFlag.value || promptFlags.values.length ||
|
|
1410
|
-
io2.stderr("--config cannot be combined with --model/--system/--prompt/--
|
|
1812
|
+
if (modelFlag.value || systemFlag.value || promptFlags.values.length || providerSkillFlags.values.length || Object.keys(mcpFlags.entries).length || Object.keys(metadataFlags.entries).length) {
|
|
1813
|
+
io2.stderr("--config cannot be combined with --model/--system/--prompt/--provider-skill/--mcp/--metadata\n");
|
|
1411
1814
|
return USAGE_ERR;
|
|
1412
1815
|
}
|
|
1413
1816
|
try {
|
|
@@ -1449,10 +1852,8 @@ async function runRunCmd(io2, argv) {
|
|
|
1449
1852
|
return USAGE_ERR;
|
|
1450
1853
|
}
|
|
1451
1854
|
}
|
|
1452
|
-
let workspaceSkills;
|
|
1453
1855
|
let providerSkills;
|
|
1454
1856
|
try {
|
|
1455
|
-
workspaceSkills = skillFlags.values.map((v, i) => parseWorkspaceSkillFlag(v, i));
|
|
1456
1857
|
providerSkills = providerSkillFlags.values.map((v, i) => parseProviderSkillFlag(v, i));
|
|
1457
1858
|
} catch (err2) {
|
|
1458
1859
|
io2.stderr(`${err2.message}
|
|
@@ -1467,7 +1868,7 @@ async function runRunCmd(io2, argv) {
|
|
|
1467
1868
|
model: modelFlag.value,
|
|
1468
1869
|
...resolvedSystem ? { system: resolvedSystem } : {},
|
|
1469
1870
|
prompt: resolvedPrompt,
|
|
1470
|
-
...
|
|
1871
|
+
...providerSkills.length > 0 ? { skills: providerSkills } : {},
|
|
1471
1872
|
...mcpRefs.length > 0 ? { mcpServers: mcpRefs } : {},
|
|
1472
1873
|
...Object.keys(metadataFlags.entries).length > 0 ? { metadata: { ...metadataFlags.entries } } : {}
|
|
1473
1874
|
};
|
|
@@ -1553,13 +1954,18 @@ async function runRunCmd(io2, argv) {
|
|
|
1553
1954
|
...blueprint.environment ? { environment: blueprint.environment } : {},
|
|
1554
1955
|
...blueprint.metadata ? { metadata: blueprint.metadata } : {}
|
|
1555
1956
|
};
|
|
1957
|
+
const providerSecrets = {
|
|
1958
|
+
[provider]: { apiKey: providerKeyValues[provider] }
|
|
1959
|
+
};
|
|
1556
1960
|
const secrets = {
|
|
1557
|
-
|
|
1961
|
+
...providerSecrets,
|
|
1558
1962
|
...mcpServerSecrets.length > 0 ? { mcpServers: mcpServerSecrets } : {},
|
|
1559
1963
|
...proxyAuth.length > 0 ? { proxyEndpointAuth: proxyAuth } : {}
|
|
1560
1964
|
};
|
|
1561
1965
|
const request = {
|
|
1562
1966
|
idempotencyKey: idempotency.value ?? generateIdempotencyKey(),
|
|
1967
|
+
provider,
|
|
1968
|
+
...runtime ? { runtime } : {},
|
|
1563
1969
|
submission,
|
|
1564
1970
|
secrets,
|
|
1565
1971
|
...cleanup.value ? { cleanup: { session: cleanup.value } } : {},
|
|
@@ -1569,7 +1975,7 @@ async function runRunCmd(io2, argv) {
|
|
|
1569
1975
|
const http = makeHttpClient(io2, common.flags);
|
|
1570
1976
|
let run;
|
|
1571
1977
|
try {
|
|
1572
|
-
run = await operations_exports.
|
|
1978
|
+
run = await operations_exports.submitRun(http, request);
|
|
1573
1979
|
} catch (err2) {
|
|
1574
1980
|
return emitJsonError(io2, "submit_failed", err2.message ?? "submission failed");
|
|
1575
1981
|
}
|
|
@@ -1649,12 +2055,6 @@ function parseJsonOrThrow(raw, label) {
|
|
|
1649
2055
|
throw new Error(`${label} is not valid JSON: ${err2.message}`);
|
|
1650
2056
|
}
|
|
1651
2057
|
}
|
|
1652
|
-
function parseWorkspaceSkillFlag(raw, idx) {
|
|
1653
|
-
if (!raw) {
|
|
1654
|
-
throw new Error(`--skill[${idx}] must be a non-empty skill id`);
|
|
1655
|
-
}
|
|
1656
|
-
return { kind: "workspace", id: raw };
|
|
1657
|
-
}
|
|
1658
2058
|
function parseProviderSkillFlag(raw, idx) {
|
|
1659
2059
|
const parts = raw.split(":");
|
|
1660
2060
|
if (parts.length < 2 || parts.length > 3) {
|
|
@@ -2751,6 +3151,13 @@ var TERMINAL_STATUSES2 = /* @__PURE__ */ new Set([
|
|
|
2751
3151
|
"canceled",
|
|
2752
3152
|
"cleaned_up"
|
|
2753
3153
|
]);
|
|
3154
|
+
function parseTransport(raw) {
|
|
3155
|
+
if (raw === void 0 || raw === "")
|
|
3156
|
+
return "auto";
|
|
3157
|
+
if (raw === "auto" || raw === "sse" || raw === "polling")
|
|
3158
|
+
return raw;
|
|
3159
|
+
return null;
|
|
3160
|
+
}
|
|
2754
3161
|
async function runEventsCmd(io2, argv) {
|
|
2755
3162
|
if (await refuseInsideManagedRun(io2, "events"))
|
|
2756
3163
|
return USAGE_ERR;
|
|
@@ -2761,9 +3168,16 @@ async function runEventsCmd(io2, argv) {
|
|
|
2761
3168
|
return USAGE_ERR;
|
|
2762
3169
|
}
|
|
2763
3170
|
const followResult = takeBooleanFlag(common.rest, "--follow");
|
|
2764
|
-
const
|
|
3171
|
+
const transportResult = takeOptionFlag(followResult.remaining, "--transport");
|
|
3172
|
+
const transport = parseTransport(transportResult.value);
|
|
3173
|
+
if (transport === null) {
|
|
3174
|
+
io2.stderr(`invalid --transport value '${transportResult.value}'; expected auto|sse|polling
|
|
3175
|
+
`);
|
|
3176
|
+
return USAGE_ERR;
|
|
3177
|
+
}
|
|
3178
|
+
const positional = transportResult.remaining.filter((arg) => !arg.startsWith("--"));
|
|
2765
3179
|
if (positional.length !== 1) {
|
|
2766
|
-
io2.stderr("usage: antpath events <run-id> [--follow] [common flags]\n");
|
|
3180
|
+
io2.stderr("usage: antpath events <run-id> [--follow] [--transport=auto|sse|polling] [common flags]\n");
|
|
2767
3181
|
return USAGE_ERR;
|
|
2768
3182
|
}
|
|
2769
3183
|
const runId = positional[0];
|
|
@@ -2779,7 +3193,44 @@ async function runEventsCmd(io2, argv) {
|
|
|
2779
3193
|
return emitJsonError(io2, "events_failed", err2.message ?? "event fetch failed", { runId });
|
|
2780
3194
|
}
|
|
2781
3195
|
}
|
|
2782
|
-
|
|
3196
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3197
|
+
if (transport !== "polling") {
|
|
3198
|
+
let cursor;
|
|
3199
|
+
while (true) {
|
|
3200
|
+
const sseOpts = {};
|
|
3201
|
+
if (cursor !== void 0)
|
|
3202
|
+
sseOpts.cursor = cursor;
|
|
3203
|
+
const iter = operations_exports.streamRunEventsSse(http, runId, sseOpts);
|
|
3204
|
+
let outcome;
|
|
3205
|
+
try {
|
|
3206
|
+
while (true) {
|
|
3207
|
+
outcome = await iter.next();
|
|
3208
|
+
if (outcome.done)
|
|
3209
|
+
break;
|
|
3210
|
+
const event = outcome.value;
|
|
3211
|
+
if (!seen.has(event.id)) {
|
|
3212
|
+
seen.add(event.id);
|
|
3213
|
+
io2.stdout(JSON.stringify(event) + "\n");
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
} catch (err2) {
|
|
3217
|
+
io2.stderr(`(transient) SSE stream errored: ${err2.message}
|
|
3218
|
+
`);
|
|
3219
|
+
if (transport === "sse")
|
|
3220
|
+
return SUCCESS;
|
|
3221
|
+
break;
|
|
3222
|
+
}
|
|
3223
|
+
const finalOutcome = outcome.value;
|
|
3224
|
+
cursor = finalOutcome.nextCursor;
|
|
3225
|
+
if (finalOutcome.kind === "terminal" || finalOutcome.kind === "aborted")
|
|
3226
|
+
return SUCCESS;
|
|
3227
|
+
if (transport === "sse")
|
|
3228
|
+
return SUCCESS;
|
|
3229
|
+
io2.stderr(`(transient) SSE disconnect (${finalOutcome.error ?? "stream closed"}) \u2014 falling back to polling
|
|
3230
|
+
`);
|
|
3231
|
+
break;
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
2783
3234
|
while (true) {
|
|
2784
3235
|
let events;
|
|
2785
3236
|
try {
|
|
@@ -2790,10 +3241,12 @@ async function runEventsCmd(io2, argv) {
|
|
|
2790
3241
|
await sleep2(2e3);
|
|
2791
3242
|
continue;
|
|
2792
3243
|
}
|
|
2793
|
-
for (
|
|
2794
|
-
|
|
3244
|
+
for (const event of events) {
|
|
3245
|
+
if (!seen.has(event.id)) {
|
|
3246
|
+
seen.add(event.id);
|
|
3247
|
+
io2.stdout(JSON.stringify(event) + "\n");
|
|
3248
|
+
}
|
|
2795
3249
|
}
|
|
2796
|
-
emittedCount = events.length;
|
|
2797
3250
|
try {
|
|
2798
3251
|
const run = await operations_exports.getRun(http, runId);
|
|
2799
3252
|
if (TERMINAL_STATUSES2.has(run.status)) {
|
|
@@ -3040,7 +3493,7 @@ Protocol version: ${manifest.protocolVersion}
|
|
|
3040
3493
|
io2.stdout("antpath \u2014 unified CLI for the antpath platform (mirrors the SDK 1:1)\n\n");
|
|
3041
3494
|
io2.stdout("Usage:\n");
|
|
3042
3495
|
io2.stdout(" antpath run --config <run.json> --anthropic-api-key K --api-token T [flags]\n");
|
|
3043
|
-
io2.stdout(" antpath run --model M --prompt P [--system S] [--skill
|
|
3496
|
+
io2.stdout(" antpath run --model M --prompt P [--system S] [--provider-skill v:s ...] [--mcp name=url ...] --anthropic-api-key K --api-token T [flags]\n");
|
|
3044
3497
|
io2.stdout(" antpath skills upload --name N --from-path <dir> --api-token T\n");
|
|
3045
3498
|
io2.stdout(" antpath skills upload --name N --file <path> [--file <path> ...] --api-token T\n");
|
|
3046
3499
|
io2.stdout(" antpath skills list --api-token T\n");
|
|
@@ -3056,14 +3509,15 @@ Protocol version: ${manifest.protocolVersion}
|
|
|
3056
3509
|
io2.stdout(" antpath --help\n\n");
|
|
3057
3510
|
io2.stdout("Common flags on every host subcommand:\n");
|
|
3058
3511
|
io2.stdout(" --api-token <token> REQUIRED \u2014 antpath SDK API token (workspace is derived from it)\n");
|
|
3059
|
-
io2.stdout(" --
|
|
3512
|
+
io2.stdout(" --antpath-url <url> Optional; defaults to https://api.antpath.ai (set for self-hosted)\n\n");
|
|
3060
3513
|
io2.stdout("antpath run flags:\n");
|
|
3061
|
-
io2.stdout(" --
|
|
3514
|
+
io2.stdout(" --provider <name> Optional; one of: anthropic (default), deepseek\n");
|
|
3515
|
+
io2.stdout(" --anthropic-api-key <key> REQUIRED when --provider anthropic (default); never stored\n");
|
|
3516
|
+
io2.stdout(" --deepseek-api-key <key> REQUIRED when --provider deepseek; never stored\n");
|
|
3062
3517
|
io2.stdout(" --config <path> JSON Blueprint (mutually exclusive with the flat --model/--prompt flags)\n");
|
|
3063
3518
|
io2.stdout(" --model <model-id> Anthropic model id (required in flat mode)\n");
|
|
3064
3519
|
io2.stdout(" --system @file | <text> System message; @-prefix reads from file\n");
|
|
3065
3520
|
io2.stdout(" --prompt @file | <text> User message; @-prefix reads from file (repeatable)\n");
|
|
3066
|
-
io2.stdout(" --skill <skl_id> Workspace skill (repeatable)\n");
|
|
3067
3521
|
io2.stdout(" --provider-skill v:s[:ver] Provider built-in skill (vendor:skillId[:version], repeatable)\n");
|
|
3068
3522
|
io2.stdout(" --mcp name=url MCP server entry (repeatable)\n");
|
|
3069
3523
|
io2.stdout(" --mcp-auth name=Hdr:Val Auth header on the matching --mcp; routed into vaulted secrets (repeatable)\n");
|