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.
Files changed (77) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +16 -8
  3. package/dist/_shared/blueprint.d.ts +93 -108
  4. package/dist/_shared/blueprint.js +144 -78
  5. package/dist/_shared/cleanup-policy.d.ts +2 -2
  6. package/dist/_shared/cleanup-policy.js +2 -5
  7. package/dist/_shared/http.d.ts +2 -2
  8. package/dist/_shared/index.d.ts +7 -1
  9. package/dist/_shared/index.js +6 -1
  10. package/dist/_shared/mcp-proxy-url.d.ts +55 -0
  11. package/dist/_shared/mcp-proxy-url.js +65 -0
  12. package/dist/_shared/operations.d.ts +55 -8
  13. package/dist/_shared/operations.js +163 -20
  14. package/dist/_shared/provider-proxy-url.d.ts +64 -0
  15. package/dist/_shared/provider-proxy-url.js +73 -0
  16. package/dist/_shared/proxy-validation.d.ts +1 -1
  17. package/dist/_shared/proxy-validation.js +2 -2
  18. package/dist/_shared/run-unit.d.ts +23 -36
  19. package/dist/_shared/run-unit.js +30 -46
  20. package/dist/_shared/runner-event.d.ts +120 -0
  21. package/dist/_shared/runner-event.js +193 -0
  22. package/dist/_shared/runner-job.d.ts +159 -0
  23. package/dist/_shared/runner-job.js +54 -0
  24. package/dist/_shared/runtime-manifest.d.ts +191 -0
  25. package/dist/_shared/runtime-manifest.js +221 -0
  26. package/dist/_shared/runtime-types.d.ts +7 -16
  27. package/dist/_shared/sse.d.ts +74 -0
  28. package/dist/_shared/sse.js +0 -0
  29. package/dist/_shared/stable.d.ts +15 -10
  30. package/dist/_shared/stable.js +15 -10
  31. package/dist/_shared/submission.d.ts +199 -73
  32. package/dist/_shared/submission.js +409 -210
  33. package/dist/_shared/telemetry.d.ts +2 -2
  34. package/dist/_shared/telemetry.js +2 -2
  35. package/dist/_shared/template/index.d.ts +0 -1
  36. package/dist/_shared/template/index.js +0 -1
  37. package/dist/agents-md.d.ts +25 -67
  38. package/dist/agents-md.js +35 -121
  39. package/dist/agents-md.js.map +1 -1
  40. package/dist/asset-upload.d.ts +34 -0
  41. package/dist/asset-upload.js +34 -0
  42. package/dist/asset-upload.js.map +1 -1
  43. package/dist/blueprint.d.ts +3 -3
  44. package/dist/bundle.d.ts +2 -2
  45. package/dist/bundle.js +1 -1
  46. package/dist/cli.mjs +559 -105
  47. package/dist/cli.mjs.sha256 +1 -1
  48. package/dist/client.d.ts +53 -22
  49. package/dist/client.js +196 -130
  50. package/dist/client.js.map +1 -1
  51. package/dist/file.d.ts +28 -94
  52. package/dist/file.js +35 -175
  53. package/dist/file.js.map +1 -1
  54. package/dist/index.d.ts +5 -5
  55. package/dist/index.js +4 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/mcp-server.d.ts +10 -2
  58. package/dist/mcp-server.js +17 -2
  59. package/dist/mcp-server.js.map +1 -1
  60. package/dist/skill.d.ts +44 -214
  61. package/dist/skill.js +50 -284
  62. package/dist/skill.js.map +1 -1
  63. package/dist/version.d.ts +1 -1
  64. package/dist/version.js +1 -1
  65. package/dist/version.js.map +1 -1
  66. package/docs/cleanup.md +1 -1
  67. package/docs/credentials.md +2 -2
  68. package/docs/events.md +8 -8
  69. package/docs/outputs.md +2 -0
  70. package/docs/quickstart.md +18 -2
  71. package/docs/skills.md +1 -3
  72. package/docs/templates.md +6 -5
  73. package/package.json +2 -1
  74. package/dist/_shared/secrets.d.ts +0 -7
  75. package/dist/_shared/secrets.js +0 -20
  76. package/dist/_shared/template/mapper.d.ts +0 -11
  77. 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 TRANSIENT_SLOT_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
80
- var TRANSIENT_CONTENT_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
81
- function parseSkillRef(input, path, options = {}) {
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 === "transient") {
125
- if (options.allowTransient === false) {
126
- throw new Error(`${path} carries a transient SkillRef, which cannot round-trip through JSON \u2014 transient skills must be supplied at submitRun time with their bytes attached`);
127
- }
128
- for (const key of Object.keys(record)) {
129
- if (key !== "kind" && key !== "slot" && key !== "name" && key !== "contentHash") {
130
- throw new Error(`${path} contains unexpected field for transient SkillRef: ${key}`);
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
- throw new Error(`${path}.kind must be 'workspace', 'provider', or 'transient'`);
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
- return { name, url };
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 `parseFlatRunSubmissionRequest`,
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}]`, { allowTransient: false }));
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://www.antpath.ai";
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
- submitRunFlat: () => submitRunFlat,
556
- submitRunFlatMultipart: () => submitRunFlatMultipart,
611
+ submitRunMultipart: () => submitRunMultipart,
557
612
  whoami: () => whoami
558
613
  });
559
- async function submitRun(http, request) {
560
- return http.request("/api/runs", {
561
- method: "POST",
562
- body: JSON.stringify(request)
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 submitRunFlat(http, request) {
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 submitRunFlatMultipart(http, request, bundles, agentsMdParts, fileParts) {
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("submitRunFlatMultipart: bundles, agentsMdParts, or fileParts must be non-empty");
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("submitRunFlatMultipart: each bundle must have a non-empty slot id");
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(`submitRunFlatMultipart: duplicate transient skill slot "${bundle.slot}"`);
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("submitRunFlatMultipart: each agentsMd part must have a non-empty slot id");
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(`submitRunFlatMultipart: duplicate agentsMd slot "${part.slot}"`);
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("submitRunFlatMultipart: each file part must have a non-empty slot id");
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(`submitRunFlatMultipart: duplicate file slot "${part.slot}"`);
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 dashboardUrl = null;
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 === "--dashboard-url") {
1166
+ if (arg === "--antpath-url") {
829
1167
  const v = argv[++i];
830
1168
  if (v === void 0)
831
- return { ok: false, reason: "--dashboard-url requires a value" };
832
- dashboardUrl = v;
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, dashboardUrl: dashboardUrl ?? ANTPATH_DEFAULT_BASE_URL },
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.dashboardUrl,
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 anthropicKey = takeFlagValue(rest, "--anthropic-api-key");
1287
- if (anthropicKey.error) {
1288
- io2.stderr(`${anthropicKey.error}
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 = anthropicKey.remaining;
1293
- if (!anthropicKey.value) {
1294
- io2.stderr("--anthropic-api-key is required (the platform does not store provider keys on your behalf)\n");
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 || skillFlags.values.length || providerSkillFlags.values.length || Object.keys(mcpFlags.entries).length || Object.keys(metadataFlags.entries).length) {
1410
- io2.stderr("--config cannot be combined with --model/--system/--prompt/--skill/--provider-skill/--mcp/--metadata\n");
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
- ...workspaceSkills.length + providerSkills.length > 0 ? { skills: [...workspaceSkills, ...providerSkills] } : {},
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
- anthropic: { apiKey: anthropicKey.value },
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.submitRunFlat(http, request);
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 positional = followResult.remaining.filter((arg) => !arg.startsWith("--"));
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
- let emittedCount = 0;
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 (let i = emittedCount; i < events.length; i++) {
2794
- io2.stdout(JSON.stringify(events[i]) + "\n");
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 ID ...] [--mcp name=url ...] --anthropic-api-key K --api-token T [flags]\n");
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(" --dashboard-url <url> Optional; defaults to https://www.antpath.ai (set for self-hosted)\n\n");
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(" --anthropic-api-key <key> REQUIRED \u2014 provider key (never stored)\n");
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");