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