antpath 0.2.0 → 0.3.1

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 (105) hide show
  1. package/README.md +55 -40
  2. package/dist/_shared/cleanup-policy.d.ts +8 -0
  3. package/dist/_shared/cleanup-policy.js +24 -0
  4. package/dist/_shared/config.d.ts +47 -0
  5. package/dist/_shared/config.js +150 -0
  6. package/dist/_shared/dev-stack.d.ts +19 -0
  7. package/dist/_shared/dev-stack.js +105 -0
  8. package/dist/_shared/errors.d.ts +8 -0
  9. package/dist/_shared/errors.js +18 -0
  10. package/dist/_shared/http.d.ts +20 -0
  11. package/dist/_shared/http.js +94 -0
  12. package/dist/_shared/index.d.ts +17 -0
  13. package/dist/_shared/index.js +20 -0
  14. package/dist/{providers → _shared}/known-events.d.ts +10 -10
  15. package/dist/{providers → _shared}/known-events.js +9 -9
  16. package/dist/_shared/operations.d.ts +19 -0
  17. package/dist/_shared/operations.js +42 -0
  18. package/dist/_shared/proxy-protocol.d.ts +148 -0
  19. package/dist/_shared/proxy-protocol.js +113 -0
  20. package/dist/_shared/proxy-validation.d.ts +19 -0
  21. package/dist/_shared/proxy-validation.js +51 -0
  22. package/dist/_shared/runtime-types.d.ts +90 -0
  23. package/dist/_shared/runtime-types.js +2 -0
  24. package/dist/{errors.d.ts → _shared/sdk-errors.d.ts} +10 -1
  25. package/dist/{errors.js → _shared/sdk-errors.js} +15 -2
  26. package/dist/{utils/secrets.js → _shared/sdk-secrets.js} +1 -1
  27. package/dist/_shared/secrets.d.ts +7 -0
  28. package/dist/_shared/secrets.js +20 -0
  29. package/dist/_shared/status.d.ts +8 -0
  30. package/dist/_shared/status.js +46 -0
  31. package/dist/_shared/submission.d.ts +142 -0
  32. package/dist/_shared/submission.js +681 -0
  33. package/dist/{template → _shared/template}/compiler.js +3 -3
  34. package/dist/{template/index.d.ts → _shared/template/helpers.d.ts} +0 -2
  35. package/dist/{template/index.js → _shared/template/helpers.js} +1 -2
  36. package/dist/_shared/template/index.d.ts +4 -0
  37. package/dist/_shared/template/index.js +4 -0
  38. package/dist/_shared/template/mapper.d.ts +11 -0
  39. package/dist/_shared/template/mapper.js +70 -0
  40. package/dist/cli.mjs +1537 -0
  41. package/dist/cli.mjs.sha256 +1 -0
  42. package/dist/client.d.ts +93 -8
  43. package/dist/client.js +192 -30
  44. package/dist/client.js.map +1 -1
  45. package/dist/index.d.ts +16 -10
  46. package/dist/index.js +16 -7
  47. package/dist/index.js.map +1 -1
  48. package/docs/cleanup.md +7 -4
  49. package/docs/credentials.md +12 -12
  50. package/docs/events.md +19 -82
  51. package/docs/outputs.md +15 -4
  52. package/docs/quickstart.md +42 -5
  53. package/docs/skills.md +1 -1
  54. package/docs/templates.md +1 -1
  55. package/docs/testing.md +11 -8
  56. package/examples/mcp-static-bearer.ts +14 -9
  57. package/examples/quickstart.ts +8 -6
  58. package/package.json +7 -5
  59. package/references/implementation-plan.md +1 -1
  60. package/dist/credentials.d.ts +0 -3
  61. package/dist/credentials.js +0 -56
  62. package/dist/credentials.js.map +0 -1
  63. package/dist/errors.js.map +0 -1
  64. package/dist/files/downloader.d.ts +0 -3
  65. package/dist/files/downloader.js +0 -43
  66. package/dist/files/downloader.js.map +0 -1
  67. package/dist/platform/client.d.ts +0 -204
  68. package/dist/platform/client.js +0 -203
  69. package/dist/platform/client.js.map +0 -1
  70. package/dist/platform/index.d.ts +0 -1
  71. package/dist/platform/index.js +0 -2
  72. package/dist/platform/index.js.map +0 -1
  73. package/dist/providers/anthropic/provider.d.ts +0 -36
  74. package/dist/providers/anthropic/provider.js +0 -380
  75. package/dist/providers/anthropic/provider.js.map +0 -1
  76. package/dist/providers/known-events.js.map +0 -1
  77. package/dist/providers/types.d.ts +0 -42
  78. package/dist/providers/types.js.map +0 -1
  79. package/dist/run/controller.d.ts +0 -30
  80. package/dist/run/controller.js +0 -314
  81. package/dist/run/controller.js.map +0 -1
  82. package/dist/skills/packager.d.ts +0 -11
  83. package/dist/skills/packager.js +0 -76
  84. package/dist/skills/packager.js.map +0 -1
  85. package/dist/template/compiler.js.map +0 -1
  86. package/dist/template/index.js.map +0 -1
  87. package/dist/template/types.js +0 -2
  88. package/dist/template/types.js.map +0 -1
  89. package/dist/types.d.ts +0 -149
  90. package/dist/types.js +0 -2
  91. package/dist/types.js.map +0 -1
  92. package/dist/utils/events.d.ts +0 -27
  93. package/dist/utils/events.js +0 -120
  94. package/dist/utils/events.js.map +0 -1
  95. package/dist/utils/paths.d.ts +0 -3
  96. package/dist/utils/paths.js +0 -27
  97. package/dist/utils/paths.js.map +0 -1
  98. package/dist/utils/secrets.js.map +0 -1
  99. package/dist/utils/stable.js.map +0 -1
  100. /package/dist/{utils/secrets.d.ts → _shared/sdk-secrets.d.ts} +0 -0
  101. /package/dist/{utils → _shared}/stable.d.ts +0 -0
  102. /package/dist/{utils → _shared}/stable.js +0 -0
  103. /package/dist/{template → _shared/template}/compiler.d.ts +0 -0
  104. /package/dist/{template → _shared/template}/types.d.ts +0 -0
  105. /package/dist/{providers → _shared/template}/types.js +0 -0
package/dist/cli.mjs ADDED
@@ -0,0 +1,1537 @@
1
+ #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+
8
+ // dist/cli.js
9
+ import { readFile, writeFile } from "node:fs/promises";
10
+
11
+ // ../shared/dist/config.js
12
+ var DEFAULT_CAPS = {
13
+ maxRunDurationMs: 5 * 60 * 1e3,
14
+ maxActiveRunsPerWorkspace: 1,
15
+ maxActiveRunsPerUserOrToken: 1,
16
+ pollingBaseIntervalMs: 5e3,
17
+ pollingMaxIntervalMs: 6e4,
18
+ pollingJitterRatio: 0.2,
19
+ providerCreateTokensPerMinute: 20,
20
+ providerDeleteTokensPerMinute: 30,
21
+ providerPollTokensPerMinute: 60,
22
+ providerRetryBackoffMs: 5e3,
23
+ leaseDurationMs: 6e4,
24
+ leaseRenewalThresholdMs: 2e4,
25
+ maxProviderAttempts: 1,
26
+ cleanupRetryCount: 3,
27
+ cleanupRetryBackoffMs: 1e4,
28
+ outputDownloadSafetyCapBytes: 1024 * 1024 * 1024,
29
+ workspaceStorageCapBytes: 5 * 1024 * 1024 * 1024,
30
+ signedUrlTtlSeconds: 300
31
+ };
32
+
33
+ // ../shared/dist/proxy-protocol.js
34
+ var PROXY_PROTOCOL_VERSION = "1";
35
+ var PROXY_PROTOCOL_HEADER = "x-antpath-proxy-protocol";
36
+ var PROXY_METHOD_HEADER = "x-antpath-method";
37
+ var PROXY_PATH_HEADER = "x-antpath-path";
38
+ var PROXY_QUERY_HEADER = "x-antpath-query";
39
+ var PROXY_HEADERS_HEADER = "x-antpath-headers";
40
+ var PROXY_RESPONSE_MODE_HEADER = "x-antpath-response-mode";
41
+ var PROXY_RESPONSE_MODES = ["status_only", "headers_only", "full"];
42
+
43
+ // ../shared/dist/status.js
44
+ var TERMINAL_RUN_STATUSES = [
45
+ "succeeded",
46
+ "failed",
47
+ "timed_out",
48
+ "cancelled",
49
+ "cleanup_failed",
50
+ "pending_delete",
51
+ "deleted"
52
+ ];
53
+ var terminalRunStatuses = new Set(TERMINAL_RUN_STATUSES);
54
+
55
+ // ../shared/dist/submission.js
56
+ var PROXY_ENDPOINT_DEFAULTS = {
57
+ allowHeaders: [],
58
+ responseMode: "headers_only",
59
+ maxRequestBytes: 64 * 1024,
60
+ maxResponseBytes: 1024 * 1024,
61
+ timeoutMs: 1e4,
62
+ perCallBudget: 60,
63
+ responseByteBudget: 1024 * 1024
64
+ };
65
+
66
+ // ../shared/dist/stable.js
67
+ import { createHash } from "node:crypto";
68
+ function stableStringify(value) {
69
+ return JSON.stringify(sortValue(value));
70
+ }
71
+ function sha256(value) {
72
+ return createHash("sha256").update(typeof value === "string" ? value : stableStringify(value)).digest("hex");
73
+ }
74
+ function sortValue(value) {
75
+ if (Array.isArray(value)) {
76
+ return value.map(sortValue);
77
+ }
78
+ if (value && typeof value === "object") {
79
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => [key, sortValue(item)]));
80
+ }
81
+ return value;
82
+ }
83
+
84
+ // ../shared/dist/sdk-secrets.js
85
+ var SECRET_PATTERNS = [
86
+ /sk-ant-[A-Za-z0-9_\-]{16,}/g,
87
+ /sk-[A-Za-z0-9_\-]{20,}/g,
88
+ /xox[pbar]-[A-Za-z0-9\-]{10,}/g,
89
+ /(?:bearer|token|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret)["'\s:=]+[A-Za-z0-9_\-./+=]{12,}/gi
90
+ ];
91
+ var REDACTED = "[REDACTED]";
92
+ function redactSecrets(value) {
93
+ if (typeof value === "string") {
94
+ return redactString(value);
95
+ }
96
+ if (Array.isArray(value)) {
97
+ return value.map((item) => redactSecrets(item));
98
+ }
99
+ if (value && typeof value === "object") {
100
+ const out = {};
101
+ for (const [key, item] of Object.entries(value)) {
102
+ if (isSecretKey(key)) {
103
+ out[key] = REDACTED;
104
+ } else {
105
+ out[key] = redactSecrets(item);
106
+ }
107
+ }
108
+ return out;
109
+ }
110
+ return value;
111
+ }
112
+ function redactString(input) {
113
+ return SECRET_PATTERNS.reduce((current, pattern) => current.replace(pattern, REDACTED), input);
114
+ }
115
+ function containsSecretLikeValue(input) {
116
+ return SECRET_PATTERNS.some((pattern) => {
117
+ pattern.lastIndex = 0;
118
+ return pattern.test(input);
119
+ });
120
+ }
121
+ function isSecretKey(key) {
122
+ return /(?:api[_-]?key|authorization|token|secret|password|credential)/i.test(key);
123
+ }
124
+
125
+ // ../shared/dist/sdk-errors.js
126
+ var AntpathError = class extends Error {
127
+ code;
128
+ details;
129
+ constructor(code, message, details) {
130
+ super(redactSecrets(message));
131
+ this.name = this.constructor.name;
132
+ this.code = code;
133
+ this.details = details === void 0 ? void 0 : redactSecrets(details);
134
+ }
135
+ };
136
+ var TemplateValidationError = class extends AntpathError {
137
+ constructor(message, details) {
138
+ super("TEMPLATE_INVALID", message, details);
139
+ }
140
+ };
141
+ var AntpathApiError = class extends AntpathError {
142
+ status;
143
+ body;
144
+ constructor(status, message, body) {
145
+ super("API_ERROR", message, body);
146
+ this.status = status;
147
+ this.body = redactSecrets(body);
148
+ }
149
+ };
150
+
151
+ // ../shared/dist/template/compiler.js
152
+ var ESCAPED_OPEN = "\0ANTPATH_ESCAPED_OPEN\0";
153
+ var VARIABLE_PATTERN = /{{\s*([A-Za-z_][A-Za-z0-9_]*)\s*}}/g;
154
+ function compileTemplate(template, variables = {}) {
155
+ assertTemplateShape(template);
156
+ const values = resolveVariableValues(template, variables);
157
+ const resolved = {
158
+ name: template.name,
159
+ model: resolveValue(template.model, values, template.variables ?? {}),
160
+ system: template.system === void 0 ? void 0 : resolveValue(template.system, values, template.variables ?? {}),
161
+ messages: template.messages.map((message) => resolveValue(message, values, template.variables ?? {})),
162
+ mcpServers: resolveMcpServers(template.mcpServers ?? {}, values, template.variables ?? {}),
163
+ environment: resolveValue(template.environment ?? {}, values, template.variables ?? {}),
164
+ skills: resolveValue(template.skills ?? [], values, template.variables ?? {}),
165
+ outputs: {
166
+ recommendedPath: "/antpath/outputs",
167
+ ...resolveValue(template.outputs ?? {}, values, template.variables ?? {})
168
+ },
169
+ metadata: resolveValue(template.metadata ?? {}, values, template.variables ?? {}),
170
+ credentialRequirements: {}
171
+ };
172
+ resolved.credentialRequirements = Object.fromEntries(resolved.mcpServers.filter((server) => server.auth).map((server) => [server.key, server.auth]));
173
+ scanForSecrets(resolved);
174
+ return {
175
+ ...resolved,
176
+ hash: sha256(stableStringify(resolved))
177
+ };
178
+ }
179
+ function assertTemplateShape(template) {
180
+ if (!template.name?.trim()) {
181
+ throw new TemplateValidationError("Template name is required");
182
+ }
183
+ if (!template.model) {
184
+ throw new TemplateValidationError("Template model is required");
185
+ }
186
+ if (!Array.isArray(template.messages) || template.messages.length === 0) {
187
+ throw new TemplateValidationError("Template must define at least one user message");
188
+ }
189
+ for (const [key, server] of Object.entries(template.mcpServers ?? {})) {
190
+ if (!/^[A-Za-z0-9_-]+$/.test(key)) {
191
+ throw new TemplateValidationError(`MCP server key '${key}' must use letters, numbers, underscores, or hyphens`);
192
+ }
193
+ if (server.tools?.allow && server.tools.deny) {
194
+ throw new TemplateValidationError(`MCP server '${key}' cannot define both allow and deny tool policies`);
195
+ }
196
+ }
197
+ }
198
+ function resolveVariableValues(template, variables) {
199
+ const definitions = template.variables ?? {};
200
+ const resolved = {};
201
+ for (const [key, definition] of Object.entries(definitions)) {
202
+ const value = variables[key] ?? definition.default;
203
+ if (value === void 0) {
204
+ continue;
205
+ }
206
+ if (typeof value !== "string") {
207
+ throw new TemplateValidationError(`Variable '${key}' must resolve to a string`);
208
+ }
209
+ resolved[key] = value;
210
+ }
211
+ for (const key of Object.keys(variables)) {
212
+ if (!definitions[key]) {
213
+ throw new TemplateValidationError(`Unknown Template variable '${key}'`);
214
+ }
215
+ }
216
+ return resolved;
217
+ }
218
+ function resolveMcpServers(servers, values, definitions) {
219
+ return Object.entries(servers).map(([key, server]) => {
220
+ const resolved = {
221
+ key,
222
+ name: key,
223
+ url: resolveValue(server.url, values, definitions ?? {})
224
+ };
225
+ if (server.auth)
226
+ resolved.auth = server.auth;
227
+ if (server.tools)
228
+ resolved.tools = resolveValue(server.tools, values, definitions ?? {});
229
+ return resolved;
230
+ });
231
+ }
232
+ function resolveValue(value, variables, definitions) {
233
+ if (typeof value === "string") {
234
+ return resolveString(value, variables, definitions);
235
+ }
236
+ if (Array.isArray(value)) {
237
+ return value.map((item) => resolveValue(item, variables, definitions));
238
+ }
239
+ if (value && typeof value === "object") {
240
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, resolveValue(item, variables, definitions)]));
241
+ }
242
+ return value;
243
+ }
244
+ function resolveString(input, variables, definitions) {
245
+ const protectedInput = input.replace(/\\{{/g, ESCAPED_OPEN);
246
+ const resolved = protectedInput.replace(VARIABLE_PATTERN, (_match, name) => {
247
+ if (!definitions[name]) {
248
+ throw new TemplateValidationError(`Unresolved Template variable '${name}'`);
249
+ }
250
+ const value = variables[name];
251
+ if (value === void 0) {
252
+ throw new TemplateValidationError(`Missing value for Template variable '${name}'`);
253
+ }
254
+ return value;
255
+ });
256
+ return resolved.replace(new RegExp(ESCAPED_OPEN, "g"), "{{");
257
+ }
258
+ function scanForSecrets(value) {
259
+ const serialized = stableStringify(value);
260
+ if (containsSecretLikeValue(serialized)) {
261
+ throw new TemplateValidationError("Template contains a secret-like value; pass secrets through typed credentials instead");
262
+ }
263
+ }
264
+
265
+ // ../shared/dist/template/mapper.js
266
+ function toPlatformSubmissionTemplate(resolved) {
267
+ const modelId = typeof resolved.model === "string" ? resolved.model : resolved.model.id;
268
+ const environment = mapEnvironment(resolved.environment);
269
+ const metadata = filterMetadata(resolved.metadata);
270
+ const submission = {
271
+ name: resolved.name,
272
+ model: modelId,
273
+ templateHash: resolved.hash,
274
+ messages: resolved.messages
275
+ };
276
+ return {
277
+ ...submission,
278
+ ...resolved.system ? { system: resolved.system } : {},
279
+ ...metadata ? { metadata } : {},
280
+ ...environment ? { environment } : {}
281
+ };
282
+ }
283
+ function mapEnvironment(env) {
284
+ if (!env)
285
+ return void 0;
286
+ let networking;
287
+ if (env.network) {
288
+ if (env.network === "restricted") {
289
+ networking = { mode: "limited", allowedHosts: [] };
290
+ } else if (env.network === "unrestricted") {
291
+ networking = { mode: "open" };
292
+ } else if (typeof env.network === "object" && env.network.type === "limited") {
293
+ const allowedHosts = env.network.allowedHosts ?? [];
294
+ networking = { mode: "limited", allowedHosts };
295
+ }
296
+ }
297
+ let packages;
298
+ if (env.packages) {
299
+ const collected = [];
300
+ for (const [manager, list] of Object.entries(env.packages)) {
301
+ if (!list)
302
+ continue;
303
+ for (const item of list) {
304
+ collected.push({ name: `${manager}:${item}` });
305
+ }
306
+ }
307
+ if (collected.length > 0)
308
+ packages = collected;
309
+ }
310
+ if (!networking && !packages)
311
+ return void 0;
312
+ return {
313
+ ...networking ? { networking } : {},
314
+ ...packages ? { packages } : {}
315
+ };
316
+ }
317
+ function filterMetadata(metadata) {
318
+ if (!metadata)
319
+ return void 0;
320
+ const entries = Object.entries(metadata);
321
+ if (entries.length === 0)
322
+ return void 0;
323
+ return Object.fromEntries(entries);
324
+ }
325
+
326
+ // ../shared/dist/http.js
327
+ var HttpClient = class {
328
+ #baseUrl;
329
+ #apiToken;
330
+ #fetch;
331
+ constructor(options) {
332
+ if (!options.baseUrl) {
333
+ throw new Error("HttpClient: baseUrl is required");
334
+ }
335
+ if (!options.apiToken) {
336
+ throw new Error("HttpClient: apiToken is required");
337
+ }
338
+ const normalized = options.baseUrl.endsWith("/") ? options.baseUrl : `${options.baseUrl}/`;
339
+ this.#baseUrl = new URL(normalized);
340
+ this.#apiToken = options.apiToken;
341
+ this.#fetch = options.fetch ?? fetch;
342
+ }
343
+ async request(path, init = {}, query = {}) {
344
+ const url = new URL(path.replace(/^\//, ""), this.#baseUrl);
345
+ for (const [key, value] of Object.entries(query)) {
346
+ url.searchParams.set(key, value);
347
+ }
348
+ const headers = {
349
+ accept: "application/json",
350
+ authorization: `Bearer ${this.#apiToken}`,
351
+ ...normalizeHeaders(init.headers)
352
+ };
353
+ if (init.body !== void 0 && init.body !== null && !headers["content-type"]) {
354
+ headers["content-type"] = "application/json";
355
+ }
356
+ const response = await this.#fetch(url, { ...init, headers });
357
+ const body = await readJson(response);
358
+ if (!response.ok) {
359
+ throw new AntpathApiError(response.status, extractErrorMessage(body), body);
360
+ }
361
+ return body;
362
+ }
363
+ async download(path, init = {}, query = {}) {
364
+ const url = new URL(path.replace(/^\//, ""), this.#baseUrl);
365
+ for (const [key, value] of Object.entries(query)) {
366
+ url.searchParams.set(key, value);
367
+ }
368
+ const headers = {
369
+ authorization: `Bearer ${this.#apiToken}`,
370
+ ...normalizeHeaders(init.headers)
371
+ };
372
+ const response = await this.#fetch(url, { ...init, headers });
373
+ if (!response.ok) {
374
+ const body = await readJson(response);
375
+ throw new AntpathApiError(response.status, extractErrorMessage(body), body);
376
+ }
377
+ return { response };
378
+ }
379
+ };
380
+ function normalizeHeaders(headers) {
381
+ if (!headers)
382
+ return {};
383
+ if (headers instanceof Headers)
384
+ return Object.fromEntries(headers.entries());
385
+ if (Array.isArray(headers))
386
+ return Object.fromEntries(headers);
387
+ return headers;
388
+ }
389
+ async function readJson(response) {
390
+ const text = await response.text();
391
+ if (text.length === 0)
392
+ return {};
393
+ try {
394
+ return JSON.parse(text);
395
+ } catch {
396
+ return { raw: text };
397
+ }
398
+ }
399
+ function extractErrorMessage(body) {
400
+ if (body && typeof body === "object" && "error" in body) {
401
+ const error = body.error;
402
+ if (typeof error === "string")
403
+ return error;
404
+ if (error && typeof error === "object" && "message" in error) {
405
+ const message = error.message;
406
+ if (typeof message === "string")
407
+ return message;
408
+ }
409
+ }
410
+ return "antpath API request failed";
411
+ }
412
+
413
+ // ../shared/dist/operations.js
414
+ var operations_exports = {};
415
+ __export(operations_exports, {
416
+ cancelRun: () => cancelRun,
417
+ createOutputLink: () => createOutputLink,
418
+ deleteRun: () => deleteRun,
419
+ getRun: () => getRun,
420
+ listOutputs: () => listOutputs,
421
+ listRunEvents: () => listRunEvents,
422
+ submitRun: () => submitRun,
423
+ whoami: () => whoami
424
+ });
425
+ async function submitRun(http, request) {
426
+ return http.request("/api/runs", {
427
+ method: "POST",
428
+ body: JSON.stringify(request)
429
+ });
430
+ }
431
+ async function getRun(http, workspaceId, runId) {
432
+ const result = await http.request(`/api/runs/${encodeURIComponent(runId)}`, {}, { workspaceId });
433
+ return hasRun(result) ? result.run : result;
434
+ }
435
+ async function listRunEvents(http, workspaceId, runId) {
436
+ const result = await http.request(`/api/runs/${encodeURIComponent(runId)}/events`, {}, { workspaceId });
437
+ return result.events;
438
+ }
439
+ async function listOutputs(http, workspaceId, runId) {
440
+ const result = await http.request(`/api/runs/${encodeURIComponent(runId)}/outputs`, {}, { workspaceId });
441
+ return result.outputs;
442
+ }
443
+ async function createOutputLink(http, workspaceId, runId, outputId) {
444
+ return http.request(`/api/runs/${encodeURIComponent(runId)}/outputs/${encodeURIComponent(outputId)}/link`, { method: "POST" }, { workspaceId });
445
+ }
446
+ async function cancelRun(http, workspaceId, runId) {
447
+ await http.request(`/api/runs/${encodeURIComponent(runId)}/cancel`, { method: "POST" }, { workspaceId });
448
+ }
449
+ async function deleteRun(http, workspaceId, runId) {
450
+ await http.request(`/api/runs/${encodeURIComponent(runId)}`, { method: "DELETE" }, { workspaceId });
451
+ }
452
+ async function whoami(http) {
453
+ return http.request("/api/whoami");
454
+ }
455
+ function hasRun(value) {
456
+ return Boolean(value && typeof value === "object" && "run" in value);
457
+ }
458
+
459
+ // ../shared/dist/proxy-validation.js
460
+ function validateProxyAuth(endpoints, auth) {
461
+ const authList = auth ?? [];
462
+ const endpointNames = new Set(endpoints.map((e) => e.name));
463
+ const authNames = /* @__PURE__ */ new Set();
464
+ for (const entry of authList) {
465
+ if (authNames.has(entry.name)) {
466
+ throw new Error(`secrets.proxyEndpointAuth contains duplicate name '${entry.name}'`);
467
+ }
468
+ authNames.add(entry.name);
469
+ if (!endpointNames.has(entry.name)) {
470
+ throw new Error(`secrets.proxyEndpointAuth[].name='${entry.name}' has no matching proxyEndpoints[].name`);
471
+ }
472
+ }
473
+ for (const endpoint of endpoints) {
474
+ const match = authList.find((a) => a.name === endpoint.name);
475
+ if (!match) {
476
+ throw new Error(`proxyEndpoints[].name='${endpoint.name}' is missing a matching secrets.proxyEndpointAuth entry`);
477
+ }
478
+ if (match.value.type !== endpoint.authShape.type) {
479
+ throw new Error(`secrets.proxyEndpointAuth[name='${endpoint.name}'].value.type='${match.value.type}' does not match proxyEndpoints[name='${endpoint.name}'].authShape.type='${endpoint.authShape.type}'`);
480
+ }
481
+ }
482
+ }
483
+
484
+ // dist/internal.js
485
+ var ANTPATH_INDEX_PATH = "/antpath/index.json";
486
+ var ANTPATH_RUN_TOKEN_PATH = "/antpath/run-token";
487
+
488
+ // dist/host/common.js
489
+ var SUCCESS = { code: 0 };
490
+ var USAGE_ERR = { code: 2 };
491
+ var RUNTIME_ERR = { code: 1 };
492
+ function parseCommonHostFlags(argv, options = {}) {
493
+ const requireWorkspace = options.requireWorkspace ?? true;
494
+ let apiToken = null;
495
+ let workspaceId = null;
496
+ let dashboardUrl = null;
497
+ const rest = [];
498
+ for (let i = 0; i < argv.length; i++) {
499
+ const arg = argv[i];
500
+ if (arg === "--api-token") {
501
+ const v = argv[++i];
502
+ if (v === void 0)
503
+ return { ok: false, reason: "--api-token requires a value" };
504
+ apiToken = v;
505
+ continue;
506
+ }
507
+ if (arg === "--workspace") {
508
+ const v = argv[++i];
509
+ if (v === void 0)
510
+ return { ok: false, reason: "--workspace requires a value" };
511
+ workspaceId = v;
512
+ continue;
513
+ }
514
+ if (arg === "--dashboard-url") {
515
+ const v = argv[++i];
516
+ if (v === void 0)
517
+ return { ok: false, reason: "--dashboard-url requires a value" };
518
+ dashboardUrl = v;
519
+ continue;
520
+ }
521
+ rest.push(arg);
522
+ }
523
+ if (!apiToken)
524
+ return { ok: false, reason: "--api-token is required" };
525
+ if (!dashboardUrl)
526
+ return { ok: false, reason: "--dashboard-url is required" };
527
+ if (requireWorkspace && !workspaceId) {
528
+ return { ok: false, reason: "--workspace is required" };
529
+ }
530
+ return {
531
+ ok: true,
532
+ flags: { apiToken, workspaceId: workspaceId ?? "", dashboardUrl },
533
+ rest
534
+ };
535
+ }
536
+ function makeHttpClient(io2, flags) {
537
+ return new HttpClient({
538
+ baseUrl: flags.dashboardUrl,
539
+ apiToken: flags.apiToken,
540
+ fetch: io2.fetchImpl
541
+ });
542
+ }
543
+ async function refuseInsideManagedRun(io2, verb) {
544
+ try {
545
+ await io2.readFile(ANTPATH_INDEX_PATH);
546
+ io2.stderr(`\`antpath ${verb}\` is a host command and cannot run inside a managed run container.
547
+ Use \`antpath proxy ...\` to call your declared upstream endpoints from inside the run.
548
+ `);
549
+ return true;
550
+ } catch {
551
+ return false;
552
+ }
553
+ }
554
+ function emitJsonError(io2, code, message, extra = {}) {
555
+ io2.stderr(JSON.stringify({ error: code, message, ...extra }) + "\n");
556
+ return RUNTIME_ERR;
557
+ }
558
+ function collectRepeatedKv(rest, flag) {
559
+ const entries = {};
560
+ const remaining = [];
561
+ for (let i = 0; i < rest.length; i++) {
562
+ const arg = rest[i];
563
+ if (arg === flag) {
564
+ const kv = rest[++i];
565
+ if (kv === void 0) {
566
+ return { entries, remaining, error: `${flag} requires a KEY=VALUE argument` };
567
+ }
568
+ const eq = kv.indexOf("=");
569
+ if (eq <= 0) {
570
+ return { entries, remaining, error: `${flag} must be in the form KEY=VALUE (got: ${kv})` };
571
+ }
572
+ entries[kv.slice(0, eq)] = kv.slice(eq + 1);
573
+ continue;
574
+ }
575
+ remaining.push(arg);
576
+ }
577
+ return { entries, remaining, error: null };
578
+ }
579
+ function collectRepeated(rest, flag) {
580
+ const values = [];
581
+ const remaining = [];
582
+ for (let i = 0; i < rest.length; i++) {
583
+ const arg = rest[i];
584
+ if (arg === flag) {
585
+ const v = rest[++i];
586
+ if (v === void 0) {
587
+ return { values, remaining, error: `${flag} requires a value` };
588
+ }
589
+ values.push(v);
590
+ continue;
591
+ }
592
+ remaining.push(arg);
593
+ }
594
+ return { values, remaining, error: null };
595
+ }
596
+ function takeFlagValue(rest, flag) {
597
+ let value = null;
598
+ const remaining = [];
599
+ for (let i = 0; i < rest.length; i++) {
600
+ const arg = rest[i];
601
+ if (arg === flag) {
602
+ const v = rest[++i];
603
+ if (v === void 0) {
604
+ return { value, remaining, error: `${flag} requires a value` };
605
+ }
606
+ value = v;
607
+ continue;
608
+ }
609
+ remaining.push(arg);
610
+ }
611
+ return { value, remaining, error: null };
612
+ }
613
+ function takeBooleanFlag(rest, flag) {
614
+ const remaining = [];
615
+ let present = false;
616
+ for (const arg of rest) {
617
+ if (arg === flag) {
618
+ present = true;
619
+ continue;
620
+ }
621
+ remaining.push(arg);
622
+ }
623
+ return { present, remaining };
624
+ }
625
+
626
+ // dist/proxy.js
627
+ function parseProxyFlags(rest) {
628
+ let endpointName = null;
629
+ let method = "GET";
630
+ let path = "/";
631
+ let query = null;
632
+ const headers = /* @__PURE__ */ new Map();
633
+ let dataSpec = null;
634
+ let responseMode = null;
635
+ let showHelp = false;
636
+ for (let i = 0; i < rest.length; i++) {
637
+ const arg = rest[i];
638
+ if (arg === "--help" || arg === "-h") {
639
+ showHelp = true;
640
+ continue;
641
+ }
642
+ if (arg === "--method") {
643
+ method = expect(rest, ++i, "--method");
644
+ continue;
645
+ }
646
+ if (arg === "--path") {
647
+ path = expect(rest, ++i, "--path");
648
+ continue;
649
+ }
650
+ if (arg === "--query") {
651
+ query = expect(rest, ++i, "--query");
652
+ continue;
653
+ }
654
+ if (arg === "--header") {
655
+ const kv = expect(rest, ++i, "--header");
656
+ const eq = kv.indexOf("=");
657
+ if (eq <= 0)
658
+ return { ok: false, reason: "--header must be in the form KEY=VALUE" };
659
+ headers.set(kv.slice(0, eq).toLowerCase(), kv.slice(eq + 1));
660
+ continue;
661
+ }
662
+ if (arg === "--data") {
663
+ dataSpec = expect(rest, ++i, "--data");
664
+ continue;
665
+ }
666
+ if (arg === "--response-mode") {
667
+ responseMode = expect(rest, ++i, "--response-mode");
668
+ continue;
669
+ }
670
+ if (arg.startsWith("--")) {
671
+ return { ok: false, reason: `unknown flag: ${arg}` };
672
+ }
673
+ if (endpointName === null) {
674
+ endpointName = arg;
675
+ continue;
676
+ }
677
+ return { ok: false, reason: `unexpected positional argument: ${arg}` };
678
+ }
679
+ return { ok: true, flags: { endpointName, method, path, query, headers, dataSpec, responseMode, showHelp } };
680
+ }
681
+ function expect(arr, idx, flag) {
682
+ const v = arr[idx];
683
+ if (v === void 0) {
684
+ throw new CliUsageError(`${flag} requires a value`);
685
+ }
686
+ return v;
687
+ }
688
+ var CliUsageError = class extends Error {
689
+ };
690
+ async function printProxyHelp(io2) {
691
+ io2.stdout("antpath proxy \u2014 call an upstream HTTP endpoint via the managed proxy.\n\n");
692
+ io2.stdout("Usage:\n");
693
+ io2.stdout(" antpath proxy <endpoint-name> [flags]\n\n");
694
+ io2.stdout("Flags:\n");
695
+ io2.stdout(" --method <verb> HTTP method (default: GET)\n");
696
+ io2.stdout(" --path <path> Caller-supplied path; must match policy prefixes\n");
697
+ io2.stdout(` --query <json> JSON object of query parameters (e.g. '{"q":"x"}')
698
+ `);
699
+ io2.stdout(" --header K=V Add a caller header (repeatable)\n");
700
+ io2.stdout(" --data <value> Request body. Use '-' for stdin, '@<file>' for file content\n");
701
+ io2.stdout(" --response-mode <mode> status_only | headers_only | full (may only narrow policy)\n");
702
+ io2.stdout(" --help Show this message\n\n");
703
+ const manifest = await tryReadManifest(io2);
704
+ if (manifest && manifest.endpoints.length > 0) {
705
+ io2.stdout("Declared endpoints:\n");
706
+ for (const ep of manifest.endpoints) {
707
+ io2.stdout(` \u2022 ${ep.name}: ${ep.allowMethods.join(",")} ${ep.allowPathPrefixes.join(",")} (mode=${ep.responseMode}, budget=${ep.perCallBudget}/run)
708
+ `);
709
+ }
710
+ }
711
+ return SUCCESS;
712
+ }
713
+ async function runProxy(io2, rest) {
714
+ let parsed;
715
+ try {
716
+ parsed = parseProxyFlags(rest);
717
+ } catch (err) {
718
+ if (err instanceof CliUsageError) {
719
+ io2.stderr(`${err.message}
720
+ `);
721
+ return USAGE_ERR;
722
+ }
723
+ throw err;
724
+ }
725
+ if (!parsed.ok) {
726
+ io2.stderr(`${parsed.reason}
727
+ `);
728
+ return USAGE_ERR;
729
+ }
730
+ const f = parsed.flags;
731
+ if (f.showHelp) {
732
+ return await printProxyHelp(io2);
733
+ }
734
+ if (!f.endpointName) {
735
+ io2.stderr("missing endpoint-name\n");
736
+ io2.stderr("usage: antpath proxy <endpoint-name> [flags]\n");
737
+ return USAGE_ERR;
738
+ }
739
+ if (f.responseMode && !PROXY_RESPONSE_MODES.includes(f.responseMode)) {
740
+ io2.stderr(`--response-mode must be one of: ${PROXY_RESPONSE_MODES.join(", ")}
741
+ `);
742
+ return USAGE_ERR;
743
+ }
744
+ const manifest = await tryReadManifest(io2);
745
+ if (!manifest) {
746
+ emitError(io2, {
747
+ error: "internal_error",
748
+ message: "manifest not mounted; this CLI must run inside an antpath-managed run"
749
+ });
750
+ return RUNTIME_ERR;
751
+ }
752
+ if (!manifest.proxyBaseUrl) {
753
+ emitError(io2, {
754
+ error: "endpoint_not_found",
755
+ message: "this run has no proxy endpoints declared",
756
+ endpointName: f.endpointName
757
+ });
758
+ return RUNTIME_ERR;
759
+ }
760
+ let token;
761
+ try {
762
+ token = (await io2.readFile(ANTPATH_RUN_TOKEN_PATH)).trim();
763
+ } catch {
764
+ emitError(io2, {
765
+ error: "unauthorized",
766
+ message: "run token file missing; this run has no proxy bearer"
767
+ });
768
+ return RUNTIME_ERR;
769
+ }
770
+ if (!token) {
771
+ emitError(io2, { error: "unauthorized", message: "run token is empty" });
772
+ return RUNTIME_ERR;
773
+ }
774
+ let body;
775
+ if (f.dataSpec !== null) {
776
+ try {
777
+ body = await resolveBody(io2, f.dataSpec);
778
+ } catch (err) {
779
+ io2.stderr(`failed to read request body: ${err.message}
780
+ `);
781
+ return RUNTIME_ERR;
782
+ }
783
+ }
784
+ const url = `${manifest.proxyBaseUrl.replace(/\/+$/, "")}/${encodeURIComponent(f.endpointName)}`;
785
+ const requestHeaders = new Headers();
786
+ requestHeaders.set("authorization", `Bearer ${token}`);
787
+ requestHeaders.set(PROXY_PROTOCOL_HEADER, PROXY_PROTOCOL_VERSION);
788
+ requestHeaders.set(PROXY_METHOD_HEADER, f.method.toUpperCase());
789
+ requestHeaders.set(PROXY_PATH_HEADER, f.path);
790
+ if (f.query) {
791
+ requestHeaders.set(PROXY_QUERY_HEADER, f.query);
792
+ }
793
+ if (f.headers.size > 0) {
794
+ requestHeaders.set(PROXY_HEADERS_HEADER, JSON.stringify(Object.fromEntries(f.headers)));
795
+ }
796
+ if (f.responseMode) {
797
+ requestHeaders.set(PROXY_RESPONSE_MODE_HEADER, f.responseMode);
798
+ }
799
+ if (body !== void 0) {
800
+ requestHeaders.set("content-length", String(body.byteLength));
801
+ }
802
+ const init = {
803
+ method: "POST",
804
+ headers: requestHeaders,
805
+ redirect: "manual"
806
+ };
807
+ if (body !== void 0) {
808
+ init.body = body;
809
+ }
810
+ let response;
811
+ try {
812
+ response = await io2.fetchImpl(url, init);
813
+ } catch (err) {
814
+ emitError(io2, {
815
+ error: "upstream_error",
816
+ message: `proxy request failed: ${err.message}`,
817
+ endpointName: f.endpointName
818
+ });
819
+ return RUNTIME_ERR;
820
+ }
821
+ const text = await response.text();
822
+ let parsedBody;
823
+ try {
824
+ parsedBody = text ? JSON.parse(text) : {};
825
+ } catch {
826
+ emitError(io2, {
827
+ error: "internal_error",
828
+ message: "proxy returned non-JSON response",
829
+ endpointName: f.endpointName
830
+ });
831
+ return RUNTIME_ERR;
832
+ }
833
+ if (!response.ok) {
834
+ io2.stderr(JSON.stringify(parsedBody) + "\n");
835
+ return RUNTIME_ERR;
836
+ }
837
+ io2.stdout(JSON.stringify(parsedBody) + "\n");
838
+ return SUCCESS;
839
+ }
840
+ async function resolveBody(io2, spec) {
841
+ if (spec === "-") {
842
+ const data = await io2.readFile("/dev/stdin");
843
+ return new Uint8Array(Buffer.from(data, "utf8"));
844
+ }
845
+ if (spec.startsWith("@")) {
846
+ const path = spec.slice(1);
847
+ if (!path)
848
+ throw new Error("--data @<file> requires a path");
849
+ const data = await io2.readFile(path);
850
+ return new Uint8Array(Buffer.from(data, "utf8"));
851
+ }
852
+ return new Uint8Array(Buffer.from(spec, "utf8"));
853
+ }
854
+ function emitError(io2, body) {
855
+ io2.stderr(JSON.stringify(body) + "\n");
856
+ }
857
+ async function tryReadManifest(io2) {
858
+ try {
859
+ const raw = await io2.readFile(ANTPATH_INDEX_PATH);
860
+ return JSON.parse(raw);
861
+ } catch {
862
+ return null;
863
+ }
864
+ }
865
+
866
+ // dist/host/template.js
867
+ import { resolve as resolvePath } from "node:path";
868
+ import { pathToFileURL } from "node:url";
869
+ async function loadTemplate(io2, filePath, variables) {
870
+ const absPath = resolvePath(io2.cwd(), filePath);
871
+ const lower = absPath.toLowerCase();
872
+ if (lower.endsWith(".json")) {
873
+ const text = await io2.readFile(absPath);
874
+ const parsed = JSON.parse(text);
875
+ return { resolved: ensureResolved(parsed, variables) };
876
+ }
877
+ if (lower.endsWith(".js") || lower.endsWith(".mjs") || lower.endsWith(".ts")) {
878
+ const mod = await import(pathToFileURL(absPath).href);
879
+ if (!mod.default) {
880
+ throw new Error(`template module ${filePath} must export a default TemplateDefinition`);
881
+ }
882
+ return { resolved: ensureResolved(mod.default, variables) };
883
+ }
884
+ throw new Error(`unsupported template extension: ${filePath}. Use .json, .js, .mjs, or .ts.`);
885
+ }
886
+ function ensureResolved(value, variables) {
887
+ if (!value || typeof value !== "object") {
888
+ throw new Error("template must be an object");
889
+ }
890
+ const obj = value;
891
+ if (typeof obj.hash === "string" && obj.hash.length > 0) {
892
+ return value;
893
+ }
894
+ return compileTemplate(value, variables);
895
+ }
896
+
897
+ // dist/host/run-cmd.js
898
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
899
+ "succeeded",
900
+ "failed",
901
+ "terminated",
902
+ "cancelled",
903
+ "canceled",
904
+ "cleaned_up"
905
+ ]);
906
+ async function runRunCmd(io2, argv) {
907
+ if (await refuseInsideManagedRun(io2, "run"))
908
+ return USAGE_ERR;
909
+ const common = parseCommonHostFlags(argv);
910
+ if (!common.ok) {
911
+ io2.stderr(`${common.reason}
912
+ `);
913
+ return USAGE_ERR;
914
+ }
915
+ let rest = common.rest;
916
+ const anthropicKey = takeFlagValue(rest, "--anthropic-api-key");
917
+ if (anthropicKey.error) {
918
+ io2.stderr(`${anthropicKey.error}
919
+ `);
920
+ return USAGE_ERR;
921
+ }
922
+ rest = anthropicKey.remaining;
923
+ if (!anthropicKey.value) {
924
+ io2.stderr("--anthropic-api-key is required (the platform does not store provider keys on your behalf)\n");
925
+ return USAGE_ERR;
926
+ }
927
+ const idempotency = takeFlagValue(rest, "--idempotency-key");
928
+ if (idempotency.error) {
929
+ io2.stderr(`${idempotency.error}
930
+ `);
931
+ return USAGE_ERR;
932
+ }
933
+ rest = idempotency.remaining;
934
+ const cleanup = takeFlagValue(rest, "--cleanup");
935
+ if (cleanup.error) {
936
+ io2.stderr(`${cleanup.error}
937
+ `);
938
+ return USAGE_ERR;
939
+ }
940
+ rest = cleanup.remaining;
941
+ if (cleanup.value && cleanup.value !== "retain" && cleanup.value !== "delete") {
942
+ io2.stderr("--cleanup must be one of: retain, delete\n");
943
+ return USAGE_ERR;
944
+ }
945
+ const follow = takeBooleanFlag(rest, "--follow");
946
+ rest = follow.remaining;
947
+ const variables = collectRepeatedKv(rest, "--var");
948
+ if (variables.error) {
949
+ io2.stderr(`${variables.error}
950
+ `);
951
+ return USAGE_ERR;
952
+ }
953
+ rest = variables.remaining;
954
+ const mcpServerEntries = collectRepeated(rest, "--mcp-server");
955
+ if (mcpServerEntries.error) {
956
+ io2.stderr(`${mcpServerEntries.error}
957
+ `);
958
+ return USAGE_ERR;
959
+ }
960
+ rest = mcpServerEntries.remaining;
961
+ const skillEntries = collectRepeated(rest, "--skill");
962
+ if (skillEntries.error) {
963
+ io2.stderr(`${skillEntries.error}
964
+ `);
965
+ return USAGE_ERR;
966
+ }
967
+ rest = skillEntries.remaining;
968
+ const proxyEndpointEntries = collectRepeated(rest, "--proxy-endpoint");
969
+ if (proxyEndpointEntries.error) {
970
+ io2.stderr(`${proxyEndpointEntries.error}
971
+ `);
972
+ return USAGE_ERR;
973
+ }
974
+ rest = proxyEndpointEntries.remaining;
975
+ const proxyAuthEntries = collectRepeatedKv(rest, "--proxy-auth");
976
+ if (proxyAuthEntries.error) {
977
+ io2.stderr(`${proxyAuthEntries.error}
978
+ `);
979
+ return USAGE_ERR;
980
+ }
981
+ rest = proxyAuthEntries.remaining;
982
+ const positional = rest.filter((a) => !a.startsWith("--"));
983
+ const unknownFlags = rest.filter((a) => a.startsWith("--"));
984
+ if (unknownFlags.length > 0) {
985
+ io2.stderr(`unknown flag: ${unknownFlags[0]}
986
+ `);
987
+ return USAGE_ERR;
988
+ }
989
+ if (positional.length !== 1) {
990
+ io2.stderr("usage: antpath run <template-path> [flags]\n");
991
+ return USAGE_ERR;
992
+ }
993
+ const templatePath = positional[0];
994
+ let resolved;
995
+ try {
996
+ const load = await loadTemplate(io2, templatePath, variables.entries);
997
+ resolved = load.resolved;
998
+ } catch (err) {
999
+ io2.stderr(`failed to load template: ${err.message}
1000
+ `);
1001
+ return USAGE_ERR;
1002
+ }
1003
+ let mcpServers;
1004
+ try {
1005
+ mcpServers = mcpServerEntries.values.map((raw, i) => parseJsonOrThrow(raw, `--mcp-server[${i}]`));
1006
+ } catch (err) {
1007
+ io2.stderr(`${err.message}
1008
+ `);
1009
+ return USAGE_ERR;
1010
+ }
1011
+ let skills;
1012
+ try {
1013
+ skills = skillEntries.values.map((raw, i) => parseSkillFlag(raw, i));
1014
+ } catch (err) {
1015
+ io2.stderr(`${err.message}
1016
+ `);
1017
+ return USAGE_ERR;
1018
+ }
1019
+ let proxyEndpoints;
1020
+ try {
1021
+ proxyEndpoints = proxyEndpointEntries.values.map((raw, i) => parseJsonOrThrow(raw, `--proxy-endpoint[${i}]`));
1022
+ } catch (err) {
1023
+ io2.stderr(`${err.message}
1024
+ `);
1025
+ return USAGE_ERR;
1026
+ }
1027
+ const proxyAuth = [];
1028
+ for (const [name, spec] of Object.entries(proxyAuthEntries.entries)) {
1029
+ const parsed = parseProxyAuth(spec);
1030
+ if (!parsed.ok) {
1031
+ io2.stderr(`--proxy-auth ${name}: ${parsed.reason}
1032
+ `);
1033
+ return USAGE_ERR;
1034
+ }
1035
+ proxyAuth.push({ name, value: parsed.value });
1036
+ }
1037
+ if (proxyEndpoints.length > 0) {
1038
+ try {
1039
+ validateProxyAuth(proxyEndpoints, proxyAuth);
1040
+ } catch (err) {
1041
+ io2.stderr(`proxy auth validation failed: ${err.message}
1042
+ `);
1043
+ return USAGE_ERR;
1044
+ }
1045
+ }
1046
+ const secrets = {
1047
+ anthropic: { apiKey: anthropicKey.value },
1048
+ ...mcpServers.length ? { mcpServers } : {},
1049
+ ...skills.length ? { skills } : {},
1050
+ ...proxyAuth.length ? { proxyEndpointAuth: proxyAuth } : {}
1051
+ };
1052
+ const submission = {
1053
+ workspaceId: common.flags.workspaceId,
1054
+ idempotencyKey: idempotency.value ?? generateIdempotencyKey(),
1055
+ template: toPlatformSubmissionTemplate(resolved),
1056
+ secrets,
1057
+ ...cleanup.value ? { cleanup: { session: cleanup.value } } : {},
1058
+ ...proxyEndpoints.length ? { proxyEndpoints } : {}
1059
+ };
1060
+ const http = makeHttpClient(io2, common.flags);
1061
+ let run;
1062
+ try {
1063
+ run = await operations_exports.submitRun(http, submission);
1064
+ } catch (err) {
1065
+ return emitJsonError(io2, "submit_failed", err.message ?? "submission failed");
1066
+ }
1067
+ io2.stdout(JSON.stringify(run) + "\n");
1068
+ if (!follow.present)
1069
+ return SUCCESS;
1070
+ let emittedEventCount = 0;
1071
+ let currentStatus = run.status;
1072
+ while (!TERMINAL_STATUSES.has(currentStatus)) {
1073
+ await sleep(2e3);
1074
+ try {
1075
+ const events = await operations_exports.listRunEvents(http, common.flags.workspaceId, run.id);
1076
+ for (let i = emittedEventCount; i < events.length; i++) {
1077
+ io2.stdout(JSON.stringify(events[i]) + "\n");
1078
+ }
1079
+ emittedEventCount = events.length;
1080
+ } catch (err) {
1081
+ io2.stderr(`(transient) event poll failed: ${err.message}
1082
+ `);
1083
+ }
1084
+ try {
1085
+ const updated = await operations_exports.getRun(http, common.flags.workspaceId, run.id);
1086
+ currentStatus = updated.status;
1087
+ } catch (err) {
1088
+ io2.stderr(`(transient) status poll failed: ${err.message}
1089
+ `);
1090
+ }
1091
+ }
1092
+ try {
1093
+ const final = await operations_exports.getRun(http, common.flags.workspaceId, run.id);
1094
+ io2.stdout(JSON.stringify(final) + "\n");
1095
+ return final.status === "succeeded" ? SUCCESS : RUNTIME_ERR;
1096
+ } catch (err) {
1097
+ io2.stderr(`final status fetch failed: ${err.message}
1098
+ `);
1099
+ return RUNTIME_ERR;
1100
+ }
1101
+ }
1102
+ function parseProxyAuth(spec) {
1103
+ const idx = spec.indexOf(":");
1104
+ if (idx <= 0) {
1105
+ return { ok: false, reason: `expected '<type>:<value>' (got: ${spec})` };
1106
+ }
1107
+ const type = spec.slice(0, idx);
1108
+ const rest = spec.slice(idx + 1);
1109
+ switch (type) {
1110
+ case "bearer":
1111
+ if (!rest)
1112
+ return { ok: false, reason: "bearer requires a token value" };
1113
+ return { ok: true, value: { type: "bearer", token: rest } };
1114
+ case "header":
1115
+ if (!rest)
1116
+ return { ok: false, reason: "header requires a value" };
1117
+ return { ok: true, value: { type: "header", value: rest } };
1118
+ case "query":
1119
+ if (!rest)
1120
+ return { ok: false, reason: "query requires a value" };
1121
+ return { ok: true, value: { type: "query", value: rest } };
1122
+ case "basic": {
1123
+ const sep = rest.indexOf(":");
1124
+ if (sep <= 0 || sep >= rest.length - 1) {
1125
+ return { ok: false, reason: "basic requires <username>:<password>" };
1126
+ }
1127
+ return {
1128
+ ok: true,
1129
+ value: { type: "basic", username: rest.slice(0, sep), password: rest.slice(sep + 1) }
1130
+ };
1131
+ }
1132
+ default:
1133
+ return { ok: false, reason: `unknown auth type '${type}' (expected bearer|basic|header|query)` };
1134
+ }
1135
+ }
1136
+ function parseSkillFlag(raw, idx) {
1137
+ if (raw.trim().startsWith("{")) {
1138
+ return parseJsonOrThrow(raw, `--skill[${idx}]`);
1139
+ }
1140
+ const sep = raw.indexOf(":");
1141
+ if (sep === -1) {
1142
+ return { skillId: raw };
1143
+ }
1144
+ const skillId = raw.slice(0, sep);
1145
+ const version = raw.slice(sep + 1);
1146
+ if (!skillId || !version) {
1147
+ throw new Error(`--skill[${idx}] must be 'skillId' or 'skillId:version' (got: ${raw})`);
1148
+ }
1149
+ return { skillId, version };
1150
+ }
1151
+ function parseJsonOrThrow(raw, label) {
1152
+ try {
1153
+ return JSON.parse(raw);
1154
+ } catch (err) {
1155
+ throw new Error(`${label} is not valid JSON: ${err.message}`);
1156
+ }
1157
+ }
1158
+ function generateIdempotencyKey() {
1159
+ const c = globalThis.crypto;
1160
+ if (c?.randomUUID)
1161
+ return c.randomUUID();
1162
+ return `idem-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
1163
+ }
1164
+ function sleep(ms) {
1165
+ return new Promise((resolve) => setTimeout(resolve, ms));
1166
+ }
1167
+
1168
+ // dist/host/status.js
1169
+ async function runStatusCmd(io2, argv) {
1170
+ if (await refuseInsideManagedRun(io2, "status"))
1171
+ return USAGE_ERR;
1172
+ const common = parseCommonHostFlags(argv);
1173
+ if (!common.ok) {
1174
+ io2.stderr(`${common.reason}
1175
+ `);
1176
+ return USAGE_ERR;
1177
+ }
1178
+ const positional = common.rest.filter((arg) => !arg.startsWith("--"));
1179
+ if (positional.length !== 1) {
1180
+ io2.stderr("usage: antpath status <run-id> [common flags]\n");
1181
+ return USAGE_ERR;
1182
+ }
1183
+ const runId = positional[0];
1184
+ const http = makeHttpClient(io2, common.flags);
1185
+ try {
1186
+ const run = await operations_exports.getRun(http, common.flags.workspaceId, runId);
1187
+ io2.stdout(JSON.stringify(run) + "\n");
1188
+ return SUCCESS;
1189
+ } catch (err) {
1190
+ return emitJsonError(io2, "status_failed", err.message ?? "status fetch failed", { runId });
1191
+ }
1192
+ }
1193
+
1194
+ // dist/host/events.js
1195
+ var TERMINAL_STATUSES2 = /* @__PURE__ */ new Set([
1196
+ "succeeded",
1197
+ "failed",
1198
+ "terminated",
1199
+ "cancelled",
1200
+ "canceled",
1201
+ "cleaned_up"
1202
+ ]);
1203
+ async function runEventsCmd(io2, argv) {
1204
+ if (await refuseInsideManagedRun(io2, "events"))
1205
+ return USAGE_ERR;
1206
+ const common = parseCommonHostFlags(argv);
1207
+ if (!common.ok) {
1208
+ io2.stderr(`${common.reason}
1209
+ `);
1210
+ return USAGE_ERR;
1211
+ }
1212
+ const followResult = takeBooleanFlag(common.rest, "--follow");
1213
+ const positional = followResult.remaining.filter((arg) => !arg.startsWith("--"));
1214
+ if (positional.length !== 1) {
1215
+ io2.stderr("usage: antpath events <run-id> [--follow] [common flags]\n");
1216
+ return USAGE_ERR;
1217
+ }
1218
+ const runId = positional[0];
1219
+ const http = makeHttpClient(io2, common.flags);
1220
+ if (!followResult.present) {
1221
+ try {
1222
+ const events = await operations_exports.listRunEvents(http, common.flags.workspaceId, runId);
1223
+ for (const event of events) {
1224
+ io2.stdout(JSON.stringify(event) + "\n");
1225
+ }
1226
+ return SUCCESS;
1227
+ } catch (err) {
1228
+ return emitJsonError(io2, "events_failed", err.message ?? "event fetch failed", { runId });
1229
+ }
1230
+ }
1231
+ let emittedCount = 0;
1232
+ while (true) {
1233
+ let events;
1234
+ try {
1235
+ events = await operations_exports.listRunEvents(http, common.flags.workspaceId, runId);
1236
+ } catch (err) {
1237
+ io2.stderr(`(transient) event poll failed: ${err.message}
1238
+ `);
1239
+ await sleep2(2e3);
1240
+ continue;
1241
+ }
1242
+ for (let i = emittedCount; i < events.length; i++) {
1243
+ io2.stdout(JSON.stringify(events[i]) + "\n");
1244
+ }
1245
+ emittedCount = events.length;
1246
+ try {
1247
+ const run = await operations_exports.getRun(http, common.flags.workspaceId, runId);
1248
+ if (TERMINAL_STATUSES2.has(run.status)) {
1249
+ return SUCCESS;
1250
+ }
1251
+ } catch (err) {
1252
+ io2.stderr(`(transient) status poll failed: ${err.message}
1253
+ `);
1254
+ }
1255
+ await sleep2(2e3);
1256
+ }
1257
+ }
1258
+ function sleep2(ms) {
1259
+ return new Promise((resolve) => setTimeout(resolve, ms));
1260
+ }
1261
+
1262
+ // dist/host/outputs.js
1263
+ async function runOutputsCmd(io2, argv) {
1264
+ if (await refuseInsideManagedRun(io2, "outputs"))
1265
+ return USAGE_ERR;
1266
+ const common = parseCommonHostFlags(argv);
1267
+ if (!common.ok) {
1268
+ io2.stderr(`${common.reason}
1269
+ `);
1270
+ return USAGE_ERR;
1271
+ }
1272
+ const positional = common.rest.filter((arg) => !arg.startsWith("--"));
1273
+ if (positional.length !== 1) {
1274
+ io2.stderr("usage: antpath outputs <run-id> [common flags]\n");
1275
+ return USAGE_ERR;
1276
+ }
1277
+ const runId = positional[0];
1278
+ const http = makeHttpClient(io2, common.flags);
1279
+ try {
1280
+ const outputs = await operations_exports.listOutputs(http, common.flags.workspaceId, runId);
1281
+ for (const out of outputs) {
1282
+ io2.stdout(JSON.stringify(out) + "\n");
1283
+ }
1284
+ return SUCCESS;
1285
+ } catch (err) {
1286
+ return emitJsonError(io2, "outputs_failed", err.message ?? "outputs fetch failed", { runId });
1287
+ }
1288
+ }
1289
+
1290
+ // dist/host/download.js
1291
+ import { resolve as resolvePath2, basename } from "node:path";
1292
+ async function runDownloadCmd(io2, argv) {
1293
+ if (await refuseInsideManagedRun(io2, "download"))
1294
+ return USAGE_ERR;
1295
+ const common = parseCommonHostFlags(argv);
1296
+ if (!common.ok) {
1297
+ io2.stderr(`${common.reason}
1298
+ `);
1299
+ return USAGE_ERR;
1300
+ }
1301
+ const outFlag = takeFlagValue(common.rest, "--out");
1302
+ if (outFlag.error) {
1303
+ io2.stderr(`${outFlag.error}
1304
+ `);
1305
+ return USAGE_ERR;
1306
+ }
1307
+ const positional = outFlag.remaining.filter((arg) => !arg.startsWith("--"));
1308
+ if (positional.length !== 2) {
1309
+ io2.stderr("usage: antpath download <run-id> <output-id> [--out path] [common flags]\n");
1310
+ return USAGE_ERR;
1311
+ }
1312
+ const runId = positional[0];
1313
+ const outputId = positional[1];
1314
+ const http = makeHttpClient(io2, common.flags);
1315
+ let link;
1316
+ try {
1317
+ link = await operations_exports.createOutputLink(http, common.flags.workspaceId, runId, outputId);
1318
+ } catch (err) {
1319
+ return emitJsonError(io2, "link_failed", err.message ?? "create link failed", { runId, outputId });
1320
+ }
1321
+ let response;
1322
+ try {
1323
+ response = await io2.fetchImpl(link.url, { method: "GET", redirect: "follow" });
1324
+ } catch (err) {
1325
+ return emitJsonError(io2, "download_failed", `download fetch failed: ${err.message}`, { runId, outputId });
1326
+ }
1327
+ if (!response.ok) {
1328
+ return emitJsonError(io2, "download_failed", `download HTTP ${response.status}`, { runId, outputId });
1329
+ }
1330
+ const buffer = new Uint8Array(await response.arrayBuffer());
1331
+ const destination = resolveDestination(io2, outFlag.value, outputId, link.url);
1332
+ try {
1333
+ await io2.writeFile(destination, buffer);
1334
+ } catch (err) {
1335
+ return emitJsonError(io2, "write_failed", `failed to write output: ${err.message}`, { destination });
1336
+ }
1337
+ io2.stdout(JSON.stringify({ runId, outputId, path: destination, bytes: buffer.byteLength }) + "\n");
1338
+ return SUCCESS;
1339
+ }
1340
+ function resolveDestination(io2, out, outputId, signedUrl) {
1341
+ if (out) {
1342
+ return resolvePath2(io2.cwd(), out);
1343
+ }
1344
+ let fileName = `${outputId}`;
1345
+ try {
1346
+ const url = new URL(signedUrl);
1347
+ const tail = basename(url.pathname);
1348
+ if (tail)
1349
+ fileName = tail;
1350
+ } catch {
1351
+ }
1352
+ return resolvePath2(io2.cwd(), fileName);
1353
+ }
1354
+
1355
+ // dist/host/cancel.js
1356
+ async function runCancelCmd(io2, argv) {
1357
+ if (await refuseInsideManagedRun(io2, "cancel"))
1358
+ return USAGE_ERR;
1359
+ const common = parseCommonHostFlags(argv);
1360
+ if (!common.ok) {
1361
+ io2.stderr(`${common.reason}
1362
+ `);
1363
+ return USAGE_ERR;
1364
+ }
1365
+ const positional = common.rest.filter((arg) => !arg.startsWith("--"));
1366
+ if (positional.length !== 1) {
1367
+ io2.stderr("usage: antpath cancel <run-id> [common flags]\n");
1368
+ return USAGE_ERR;
1369
+ }
1370
+ const runId = positional[0];
1371
+ const http = makeHttpClient(io2, common.flags);
1372
+ try {
1373
+ await operations_exports.cancelRun(http, common.flags.workspaceId, runId);
1374
+ io2.stdout(JSON.stringify({ runId, status: "cancel_requested" }) + "\n");
1375
+ return SUCCESS;
1376
+ } catch (err) {
1377
+ return emitJsonError(io2, "cancel_failed", err.message ?? "cancel failed", { runId });
1378
+ }
1379
+ }
1380
+
1381
+ // dist/host/delete.js
1382
+ async function runDeleteCmd(io2, argv) {
1383
+ if (await refuseInsideManagedRun(io2, "delete"))
1384
+ return USAGE_ERR;
1385
+ const common = parseCommonHostFlags(argv);
1386
+ if (!common.ok) {
1387
+ io2.stderr(`${common.reason}
1388
+ `);
1389
+ return USAGE_ERR;
1390
+ }
1391
+ const positional = common.rest.filter((arg) => !arg.startsWith("--"));
1392
+ if (positional.length !== 1) {
1393
+ io2.stderr("usage: antpath delete <run-id> [common flags]\n");
1394
+ return USAGE_ERR;
1395
+ }
1396
+ const runId = positional[0];
1397
+ const http = makeHttpClient(io2, common.flags);
1398
+ try {
1399
+ await operations_exports.deleteRun(http, common.flags.workspaceId, runId);
1400
+ io2.stdout(JSON.stringify({ runId, deleted: true }) + "\n");
1401
+ return SUCCESS;
1402
+ } catch (err) {
1403
+ return emitJsonError(io2, "delete_failed", err.message ?? "delete failed", { runId });
1404
+ }
1405
+ }
1406
+
1407
+ // dist/host/whoami.js
1408
+ async function runWhoamiCmd(io2, argv) {
1409
+ if (await refuseInsideManagedRun(io2, "whoami"))
1410
+ return USAGE_ERR;
1411
+ const common = parseCommonHostFlags(argv, { requireWorkspace: false });
1412
+ if (!common.ok) {
1413
+ io2.stderr(`${common.reason}
1414
+ `);
1415
+ return USAGE_ERR;
1416
+ }
1417
+ if (common.rest.length > 0) {
1418
+ io2.stderr(`unexpected arguments: ${common.rest.join(" ")}
1419
+ `);
1420
+ return USAGE_ERR;
1421
+ }
1422
+ const http = makeHttpClient(io2, common.flags);
1423
+ try {
1424
+ const me = await operations_exports.whoami(http);
1425
+ io2.stdout(JSON.stringify(me) + "\n");
1426
+ return SUCCESS;
1427
+ } catch (err) {
1428
+ return emitJsonError(io2, "whoami_failed", err.message ?? "whoami failed");
1429
+ }
1430
+ }
1431
+
1432
+ // dist/run.js
1433
+ async function runCli(io2) {
1434
+ const args = io2.argv.slice(2);
1435
+ try {
1436
+ const exit = await dispatch(io2, args);
1437
+ io2.exit(exit.code);
1438
+ } catch (err) {
1439
+ const body = { error: "internal_error", message: err.message ?? "unknown error" };
1440
+ io2.stderr(JSON.stringify(body) + "\n");
1441
+ io2.exit(RUNTIME_ERR.code);
1442
+ }
1443
+ }
1444
+ async function dispatch(io2, args) {
1445
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
1446
+ return printGlobalHelp(io2);
1447
+ }
1448
+ const sub = args[0];
1449
+ const rest = args.slice(1);
1450
+ switch (sub) {
1451
+ case "proxy":
1452
+ return runProxy(io2, rest);
1453
+ case "run":
1454
+ return runRunCmd(io2, rest);
1455
+ case "status":
1456
+ return runStatusCmd(io2, rest);
1457
+ case "events":
1458
+ return runEventsCmd(io2, rest);
1459
+ case "outputs":
1460
+ return runOutputsCmd(io2, rest);
1461
+ case "download":
1462
+ return runDownloadCmd(io2, rest);
1463
+ case "cancel":
1464
+ return runCancelCmd(io2, rest);
1465
+ case "delete":
1466
+ return runDeleteCmd(io2, rest);
1467
+ case "whoami":
1468
+ return runWhoamiCmd(io2, rest);
1469
+ default:
1470
+ io2.stderr(`unknown subcommand: ${sub}
1471
+ `);
1472
+ io2.stderr("run `antpath --help` for usage\n");
1473
+ return USAGE_ERR;
1474
+ }
1475
+ }
1476
+ async function printGlobalHelp(io2) {
1477
+ const manifest = await tryReadManifest(io2);
1478
+ if (manifest) {
1479
+ io2.stdout("antpath \u2014 in-container CLI for managed run sessions\n\n");
1480
+ io2.stdout("Usage:\n");
1481
+ io2.stdout(" antpath proxy <endpoint-name> [flags]\n");
1482
+ io2.stdout(" antpath proxy --help\n\n");
1483
+ if (manifest.endpoints.length === 0) {
1484
+ io2.stdout("This run declared no proxy endpoints.\n");
1485
+ } else {
1486
+ io2.stdout("Declared proxy endpoints for this run:\n");
1487
+ for (const ep of manifest.endpoints) {
1488
+ io2.stdout(` \u2022 ${ep.name} (${ep.allowMethods.join("/")} ${ep.allowPathPrefixes.join(",")}, mode=${ep.responseMode})
1489
+ `);
1490
+ }
1491
+ }
1492
+ io2.stdout(`
1493
+ Protocol version: ${manifest.protocolVersion}
1494
+ `);
1495
+ return SUCCESS;
1496
+ }
1497
+ io2.stdout("antpath \u2014 unified CLI for the antpath platform (mirrors the SDK 1:1)\n\n");
1498
+ io2.stdout("Usage:\n");
1499
+ io2.stdout(" antpath run <template-path> --api-token T --workspace W --dashboard-url U [flags]\n");
1500
+ io2.stdout(" antpath status <run-id> --api-token T --workspace W --dashboard-url U\n");
1501
+ io2.stdout(" antpath events <run-id> [--follow] --api-token T --workspace W --dashboard-url U\n");
1502
+ io2.stdout(" antpath outputs <run-id> --api-token T --workspace W --dashboard-url U\n");
1503
+ io2.stdout(" antpath download <run-id> <output-id> [--out path] --api-token T --workspace W --dashboard-url U\n");
1504
+ io2.stdout(" antpath cancel <run-id> --api-token T --workspace W --dashboard-url U\n");
1505
+ io2.stdout(" antpath delete <run-id> --api-token T --workspace W --dashboard-url U\n");
1506
+ io2.stdout(" antpath whoami --api-token T --dashboard-url U\n");
1507
+ io2.stdout(" antpath --help\n\n");
1508
+ io2.stdout("Required flags on every host subcommand:\n");
1509
+ io2.stdout(" --api-token <token> Workspace-scoped antpath SDK API token\n");
1510
+ io2.stdout(" --workspace <id-or-slug> Workspace this call targets (omit for whoami)\n");
1511
+ io2.stdout(" --dashboard-url <url> Dashboard BFF root, e.g. https://antpath.example.com\n\n");
1512
+ io2.stdout("Submit flags (antpath run):\n");
1513
+ io2.stdout(" --anthropic-api-key <key> REQUIRED \u2014 provider key (never stored)\n");
1514
+ io2.stdout(" --var name=value Template variable (repeatable)\n");
1515
+ io2.stdout(" --mcp-server '<json>' PlatformMcpServerSecret JSON (repeatable)\n");
1516
+ io2.stdout(" --skill <skillId>[:<ver>] Skill reference (repeatable)\n");
1517
+ io2.stdout(" --proxy-endpoint '<json>' PlatformProxyEndpoint JSON (repeatable)\n");
1518
+ io2.stdout(" --proxy-auth name=<spec> bearer:tok | basic:u:p | header:v | query:v (repeatable)\n");
1519
+ io2.stdout(" --cleanup retain|delete Session cleanup policy\n");
1520
+ io2.stdout(" --idempotency-key <key> Optional; defaults to a fresh UUID\n");
1521
+ io2.stdout(" --follow Poll events to stdout until the run terminates\n\n");
1522
+ io2.stdout("Template formats: .json, .js, .mjs, .ts (default export must be a TemplateDefinition).\n");
1523
+ return SUCCESS;
1524
+ }
1525
+
1526
+ // dist/cli.js
1527
+ var io = {
1528
+ readFile: (path) => readFile(path, "utf8"),
1529
+ writeFile: (path, data) => writeFile(path, data),
1530
+ fetchImpl: fetch,
1531
+ stdout: (chunk) => process.stdout.write(chunk),
1532
+ stderr: (chunk) => process.stderr.write(chunk),
1533
+ exit: (code) => process.exit(code),
1534
+ argv: process.argv,
1535
+ cwd: () => process.cwd()
1536
+ };
1537
+ await runCli(io);