antpath 0.10.15 → 0.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +16 -8
- package/dist/_shared/blueprint.d.ts +93 -108
- package/dist/_shared/blueprint.js +144 -78
- package/dist/_shared/cleanup-policy.d.ts +2 -2
- package/dist/_shared/cleanup-policy.js +2 -5
- package/dist/_shared/http.d.ts +2 -2
- package/dist/_shared/index.d.ts +5 -1
- package/dist/_shared/index.js +5 -1
- package/dist/_shared/mcp-proxy-url.d.ts +55 -0
- package/dist/_shared/mcp-proxy-url.js +65 -0
- package/dist/_shared/operations.d.ts +7 -8
- package/dist/_shared/operations.js +14 -20
- package/dist/_shared/provider-proxy-url.d.ts +64 -0
- package/dist/_shared/provider-proxy-url.js +73 -0
- package/dist/_shared/proxy-validation.d.ts +1 -1
- package/dist/_shared/proxy-validation.js +2 -2
- package/dist/_shared/run-unit.d.ts +23 -36
- package/dist/_shared/run-unit.js +30 -46
- package/dist/_shared/runner-event.d.ts +120 -0
- package/dist/_shared/runner-event.js +193 -0
- package/dist/_shared/runner-job.d.ts +159 -0
- package/dist/_shared/runner-job.js +54 -0
- package/dist/_shared/runtime-manifest.d.ts +191 -0
- package/dist/_shared/runtime-manifest.js +221 -0
- package/dist/_shared/runtime-types.d.ts +7 -16
- package/dist/_shared/stable.d.ts +15 -10
- package/dist/_shared/stable.js +15 -10
- package/dist/_shared/submission.d.ts +221 -73
- package/dist/_shared/submission.js +442 -212
- package/dist/_shared/telemetry.d.ts +2 -2
- package/dist/_shared/telemetry.js +2 -2
- package/dist/_shared/template/index.d.ts +0 -1
- package/dist/_shared/template/index.js +0 -1
- package/dist/agents-md.d.ts +25 -67
- package/dist/agents-md.js +35 -121
- package/dist/agents-md.js.map +1 -1
- package/dist/asset-upload.d.ts +34 -0
- package/dist/asset-upload.js +34 -0
- package/dist/asset-upload.js.map +1 -1
- package/dist/blueprint.d.ts +3 -3
- package/dist/bundle.d.ts +2 -2
- package/dist/bundle.js +1 -1
- package/dist/cli.mjs +191 -100
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +56 -19
- package/dist/client.js +147 -125
- package/dist/client.js.map +1 -1
- package/dist/file.d.ts +28 -94
- package/dist/file.js +35 -175
- package/dist/file.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +10 -2
- package/dist/mcp-server.js +17 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/skill.d.ts +44 -214
- package/dist/skill.js +50 -284
- package/dist/skill.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/cleanup.md +1 -1
- package/docs/credentials.md +2 -2
- package/docs/events.md +8 -8
- package/docs/outputs.md +2 -0
- package/docs/quickstart.md +18 -2
- package/docs/skills.md +1 -3
- package/docs/templates.md +6 -5
- package/package.json +3 -2
- package/dist/_shared/secrets.d.ts +0 -7
- package/dist/_shared/secrets.js +0 -20
- package/dist/_shared/template/mapper.d.ts +0 -11
- package/dist/_shared/template/mapper.js +0 -70
|
@@ -83,63 +83,41 @@ export const SKILL_BUNDLE_LIMITS = {
|
|
|
83
83
|
/** Stored directory mode. */
|
|
84
84
|
defaultDirMode: 0o755
|
|
85
85
|
};
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
* positionally as `transient-0`, `transient-1`, … but any client may
|
|
89
|
-
* supply an explicit slot as long as it matches the pattern and is
|
|
90
|
-
* unique within the submission.
|
|
91
|
-
*/
|
|
92
|
-
export const TRANSIENT_SLOT_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
93
|
-
/**
|
|
94
|
-
* Content-hash format: `^sha256:[0-9a-f]{64}$` (lowercase hex). The
|
|
95
|
-
* BFF accepts only this exact prefix; uppercase, base64, or any other
|
|
96
|
-
* digest is rejected so the wire form has one stable representation.
|
|
97
|
-
*/
|
|
98
|
-
export const TRANSIENT_CONTENT_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
99
|
-
export function isWorkspaceSkillRef(ref) {
|
|
100
|
-
return ref.kind === "workspace";
|
|
101
|
-
}
|
|
86
|
+
/** Content-hash format: `sha256:<64 lowercase hex>`. */
|
|
87
|
+
export const INLINE_CONTENT_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
102
88
|
export function isProviderSkillRef(ref) {
|
|
103
89
|
return ref.kind === "provider";
|
|
104
90
|
}
|
|
105
|
-
export function
|
|
106
|
-
return ref.kind === "
|
|
107
|
-
}
|
|
108
|
-
export function isWorkspaceAgentsMdRef(ref) {
|
|
109
|
-
return ref.kind === "workspace_agentsmd";
|
|
110
|
-
}
|
|
111
|
-
export function isTransientAgentsMdRef(ref) {
|
|
112
|
-
return ref.kind === "transient_agentsmd";
|
|
91
|
+
export function isR2SkillRef(ref) {
|
|
92
|
+
return ref.kind === "r2";
|
|
113
93
|
}
|
|
114
|
-
|
|
115
|
-
|
|
94
|
+
/**
|
|
95
|
+
* R2 asset path pattern. The Worker validates inbound paths against
|
|
96
|
+
* this so a hostile body can't reach into a foreign workspace or
|
|
97
|
+
* outside the `assets/` prefix.
|
|
98
|
+
* workspaceId is a UUID v4
|
|
99
|
+
* hash is 64 lowercase hex chars (the sha256 digest)
|
|
100
|
+
*/
|
|
101
|
+
export const R2_ASSET_PATH_PATTERN = /^assets\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/[0-9a-f]{64}$/;
|
|
102
|
+
export function isR2AgentsMdRef(ref) {
|
|
103
|
+
return ref.kind === "r2";
|
|
116
104
|
}
|
|
117
|
-
export function
|
|
118
|
-
return ref.kind === "
|
|
105
|
+
export function isR2FileRef(ref) {
|
|
106
|
+
return ref.kind === "r2";
|
|
119
107
|
}
|
|
120
108
|
/**
|
|
121
109
|
* Parse a `SkillRef` from untrusted input. Used by the BFF run parser
|
|
122
|
-
* and by the operations module when deserialising API responses.
|
|
123
|
-
*
|
|
110
|
+
* and by the operations module when deserialising API responses. Only
|
|
111
|
+
* `kind: "r2"` and `kind: "provider"` are valid; all other historical
|
|
112
|
+
* wire shapes (workspace, inline, transient) were retired when R2
|
|
113
|
+
* became the canonical asset store (Phase D, references/platform-rebuild-2026.md).
|
|
124
114
|
*/
|
|
125
|
-
export function parseSkillRef(input, path
|
|
115
|
+
export function parseSkillRef(input, path) {
|
|
126
116
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
127
117
|
throw new Error(`${path} must be a SkillRef object`);
|
|
128
118
|
}
|
|
129
119
|
const record = input;
|
|
130
120
|
const kind = record.kind;
|
|
131
|
-
if (kind === "workspace") {
|
|
132
|
-
for (const key of Object.keys(record)) {
|
|
133
|
-
if (key !== "kind" && key !== "id") {
|
|
134
|
-
throw new Error(`${path} contains unexpected field for workspace SkillRef: ${key}`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const id = record.id;
|
|
138
|
-
if (typeof id !== "string" || !SKILL_ID_PATTERN.test(id)) {
|
|
139
|
-
throw new Error(`${path}.id must match ${SKILL_ID_PATTERN.source}`);
|
|
140
|
-
}
|
|
141
|
-
return { kind: "workspace", id };
|
|
142
|
-
}
|
|
143
121
|
if (kind === "provider") {
|
|
144
122
|
for (const key of Object.keys(record)) {
|
|
145
123
|
if (key !== "kind" && key !== "vendor" && key !== "skillId" && key !== "version") {
|
|
@@ -165,31 +143,63 @@ export function parseSkillRef(input, path, options = {}) {
|
|
|
165
143
|
...(version !== undefined ? { version } : {})
|
|
166
144
|
};
|
|
167
145
|
}
|
|
168
|
-
if (kind === "
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (typeof contentHash !== "string" || !TRANSIENT_CONTENT_HASH_PATTERN.test(contentHash)) {
|
|
188
|
-
throw new Error(`${path}.contentHash must match ${TRANSIENT_CONTENT_HASH_PATTERN.source}`);
|
|
146
|
+
if (kind === "r2") {
|
|
147
|
+
return parseR2RefFields(record, path);
|
|
148
|
+
}
|
|
149
|
+
throw new Error(`${path}.kind must be 'provider' or 'r2'`);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Common parser for any `kind: "r2"` ref (skill / agentsMd / file).
|
|
153
|
+
* Skills and agentsMd ignore the optional `mountPath` field; file refs
|
|
154
|
+
* use it for the Anthropic Files mount remap.
|
|
155
|
+
*/
|
|
156
|
+
export function parseR2RefFields(record, path) {
|
|
157
|
+
for (const key of Object.keys(record)) {
|
|
158
|
+
if (key !== "kind" &&
|
|
159
|
+
key !== "path" &&
|
|
160
|
+
key !== "hash" &&
|
|
161
|
+
key !== "sizeBytes" &&
|
|
162
|
+
key !== "name" &&
|
|
163
|
+
key !== "mountPath") {
|
|
164
|
+
throw new Error(`${path} contains unexpected field for r2 ref: ${key}`);
|
|
189
165
|
}
|
|
190
|
-
return { kind: "transient", slot, name, contentHash };
|
|
191
166
|
}
|
|
192
|
-
|
|
167
|
+
const r2Path = record.path;
|
|
168
|
+
if (typeof r2Path !== "string" || !R2_ASSET_PATH_PATTERN.test(r2Path)) {
|
|
169
|
+
throw new Error(`${path}.path must match ${R2_ASSET_PATH_PATTERN.source}`);
|
|
170
|
+
}
|
|
171
|
+
const hash = record.hash;
|
|
172
|
+
if (typeof hash !== "string" || !INLINE_CONTENT_HASH_PATTERN.test(hash)) {
|
|
173
|
+
throw new Error(`${path}.hash must match ${INLINE_CONTENT_HASH_PATTERN.source}`);
|
|
174
|
+
}
|
|
175
|
+
// Cross-field check: the trailing 64-hex segment of `path` MUST be
|
|
176
|
+
// the lowercase digest from `hash` so a hostile body cannot point
|
|
177
|
+
// `path` at another tenant's blob and claim a different hash.
|
|
178
|
+
const pathHash = r2Path.slice(r2Path.length - 64);
|
|
179
|
+
const hashHex = hash.slice("sha256:".length);
|
|
180
|
+
if (pathHash !== hashHex) {
|
|
181
|
+
throw new Error(`${path}.path hash segment does not match ${path}.hash`);
|
|
182
|
+
}
|
|
183
|
+
const sizeBytes = record.sizeBytes;
|
|
184
|
+
if (typeof sizeBytes !== "number" || !Number.isInteger(sizeBytes) || sizeBytes <= 0) {
|
|
185
|
+
throw new Error(`${path}.sizeBytes must be a positive integer`);
|
|
186
|
+
}
|
|
187
|
+
const name = record.name;
|
|
188
|
+
if (typeof name !== "string" || name.length === 0 || name.length > 128) {
|
|
189
|
+
throw new Error(`${path}.name must be a non-empty string (<= 128 chars)`);
|
|
190
|
+
}
|
|
191
|
+
const mountPath = record.mountPath;
|
|
192
|
+
if (mountPath !== undefined && (typeof mountPath !== "string" || mountPath.length === 0)) {
|
|
193
|
+
throw new Error(`${path}.mountPath, when provided, must be a non-empty string`);
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
kind: "r2",
|
|
197
|
+
path: r2Path,
|
|
198
|
+
hash,
|
|
199
|
+
sizeBytes,
|
|
200
|
+
name,
|
|
201
|
+
...(mountPath !== undefined ? { mountPath } : {})
|
|
202
|
+
};
|
|
193
203
|
}
|
|
194
204
|
export class SkillBundleValidationError extends Error {
|
|
195
205
|
constructor(message) {
|
|
@@ -341,21 +351,48 @@ export function validateSkillBundleManifest(input) {
|
|
|
341
351
|
export function hasSkillMdAtRoot(manifest) {
|
|
342
352
|
return manifest.entries.some((entry) => entry.path === "SKILL.md");
|
|
343
353
|
}
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// McpServerRef (non-secret) + BlueprintMcpServer (with optional headers)
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
/**
|
|
358
|
+
* Remote MCP transports Antpath accepts. Both are over HTTP — `http`
|
|
359
|
+
* is the streamable-HTTP transport, `sse` is the event-stream
|
|
360
|
+
* transport. `stdio` is explicitly NOT a value here: local-process
|
|
361
|
+
* MCP is not implemented (see `references/deepseek-runtime-mcp-plan.md`).
|
|
362
|
+
*/
|
|
363
|
+
export const REMOTE_MCP_TRANSPORTS = ["http", "sse"];
|
|
364
|
+
/**
|
|
365
|
+
* Canonical error string for any attempt to declare a stdio-shaped MCP
|
|
366
|
+
* server (`transport: "stdio"`, or a stdio-only field like `command` /
|
|
367
|
+
* `args` / `env`). Pinned in source so every surface — shared parser,
|
|
368
|
+
* SDK builder, CLI flag parser, dashboard form — surfaces the same
|
|
369
|
+
* message and a user can find it via grep.
|
|
370
|
+
*/
|
|
371
|
+
export const REMOTE_MCP_STDIO_REJECTED_MESSAGE = "stdio MCP servers are not supported by Antpath. Antpath supports remote MCP servers over HTTP/SSE only.";
|
|
372
|
+
/**
|
|
373
|
+
* Stdio-only fields. Used by the parser to detect a stdio shape even
|
|
374
|
+
* when the caller omits `transport: "stdio"` (e.g. `{ url, command }`
|
|
375
|
+
* — the presence of `command` alone is enough to identify a stdio
|
|
376
|
+
* declaration and reject it).
|
|
377
|
+
*/
|
|
378
|
+
const STDIO_ONLY_FIELDS = ["command", "args", "env"];
|
|
344
379
|
export const MCP_SERVER_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
345
380
|
export function parseMcpServerRef(input, path) {
|
|
346
381
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
347
382
|
throw new Error(`${path} must be an object`);
|
|
348
383
|
}
|
|
349
384
|
const record = input;
|
|
385
|
+
rejectStdioMcpShape(record);
|
|
350
386
|
// Headers belong on `BlueprintMcpServer`, not the non-secret wire ref;
|
|
351
387
|
// and the wire `submission.mcpServers` must NEVER contain headers. So
|
|
352
|
-
// reject any field other than {name,url} explicitly to make a
|
|
353
|
-
// accidentally inlining `headers` into the non-secret half fail
|
|
354
|
-
// instead of silently dropping the field.
|
|
355
|
-
// handles the headers case separately for
|
|
388
|
+
// reject any field other than {name,url,transport} explicitly to make a
|
|
389
|
+
// caller accidentally inlining `headers` into the non-secret half fail
|
|
390
|
+
// loudly instead of silently dropping the field.
|
|
391
|
+
// `parseBlueprintMcpServer` handles the headers case separately for
|
|
392
|
+
// Blueprint-level entries.
|
|
356
393
|
for (const key of Object.keys(record)) {
|
|
357
|
-
if (key !== "name" && key !== "url") {
|
|
358
|
-
throw new Error(`${path}.${key} is not an allowed field for McpServerRef; permitted: name, url`);
|
|
394
|
+
if (key !== "name" && key !== "url" && key !== "transport") {
|
|
395
|
+
throw new Error(`${path}.${key} is not an allowed field for McpServerRef; permitted: name, url, transport`);
|
|
359
396
|
}
|
|
360
397
|
}
|
|
361
398
|
const name = record.name;
|
|
@@ -385,7 +422,33 @@ export function parseMcpServerRef(input, path) {
|
|
|
385
422
|
}
|
|
386
423
|
throw new Error(`${path}.url is not a valid URL: ${url}`);
|
|
387
424
|
}
|
|
388
|
-
|
|
425
|
+
const transport = parseRemoteMcpTransport(record.transport, `${path}.transport`);
|
|
426
|
+
return transport ? { name, url, transport } : { name, url };
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Throw the canonical stdio-rejected error if the record carries any
|
|
430
|
+
* stdio-only marker (`transport: "stdio"`, `command`, `args`, `env`).
|
|
431
|
+
* Used by both the shared parser and the SDK `McpServer.remote`
|
|
432
|
+
* builder so every entry point surfaces the same message.
|
|
433
|
+
*/
|
|
434
|
+
export function rejectStdioMcpShape(record) {
|
|
435
|
+
if (record.transport === "stdio") {
|
|
436
|
+
throw new Error(REMOTE_MCP_STDIO_REJECTED_MESSAGE);
|
|
437
|
+
}
|
|
438
|
+
for (const field of STDIO_ONLY_FIELDS) {
|
|
439
|
+
if (record[field] !== undefined) {
|
|
440
|
+
throw new Error(REMOTE_MCP_STDIO_REJECTED_MESSAGE);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
function parseRemoteMcpTransport(input, field) {
|
|
445
|
+
if (input === undefined) {
|
|
446
|
+
return undefined;
|
|
447
|
+
}
|
|
448
|
+
if (typeof input !== "string" || !REMOTE_MCP_TRANSPORTS.includes(input)) {
|
|
449
|
+
throw new Error(`${field} must be one of: ${REMOTE_MCP_TRANSPORTS.join(", ")} (got ${JSON.stringify(input)})`);
|
|
450
|
+
}
|
|
451
|
+
return input;
|
|
389
452
|
}
|
|
390
453
|
/**
|
|
391
454
|
* Strict parser for Blueprint-level MCP server entries. Allows only the
|
|
@@ -398,13 +461,16 @@ function parseBlueprintMcpServerRef(input, path) {
|
|
|
398
461
|
throw new Error(`${path} must be an object`);
|
|
399
462
|
}
|
|
400
463
|
const record = input;
|
|
464
|
+
rejectStdioMcpShape(record);
|
|
401
465
|
for (const key of Object.keys(record)) {
|
|
402
|
-
if (key !== "name" && key !== "url" && key !== "headers") {
|
|
403
|
-
throw new Error(`${path}.${key} is not an allowed field for BlueprintMcpServer; permitted: name, url, headers`);
|
|
466
|
+
if (key !== "name" && key !== "url" && key !== "headers" && key !== "transport") {
|
|
467
|
+
throw new Error(`${path}.${key} is not an allowed field for BlueprintMcpServer; permitted: name, url, transport, headers`);
|
|
404
468
|
}
|
|
405
469
|
}
|
|
406
|
-
// Reuse the {name,url} validator by passing the stripped object.
|
|
470
|
+
// Reuse the {name,url,transport} validator by passing the stripped object.
|
|
407
471
|
const stripped = { name: record.name, url: record.url };
|
|
472
|
+
if (record.transport !== undefined)
|
|
473
|
+
stripped.transport = record.transport;
|
|
408
474
|
const ref = parseMcpServerRef(stripped, path);
|
|
409
475
|
const rawHeaders = record.headers;
|
|
410
476
|
if (rawHeaders === undefined) {
|
|
@@ -499,7 +565,7 @@ export function parseBlueprint(input) {
|
|
|
499
565
|
...(skills !== undefined ? { skills } : {}),
|
|
500
566
|
...(mcpServers !== undefined ? { mcpServers } : {}),
|
|
501
567
|
// environment / cleanup / proxyEndpoints / metadata: passed through
|
|
502
|
-
// as-is — the BFF revalidates them via `
|
|
568
|
+
// as-is — the BFF revalidates them via `parseRunSubmissionRequest`,
|
|
503
569
|
// so duplicating the heavyweight parsers here would mean two sources
|
|
504
570
|
// of truth. The CLI surfaces structural errors at submission time.
|
|
505
571
|
...(record.environment !== undefined
|
|
@@ -546,7 +612,7 @@ function parseBlueprintSkills(value) {
|
|
|
546
612
|
if (!Array.isArray(value)) {
|
|
547
613
|
throw new Error("Blueprint.skills must be an array");
|
|
548
614
|
}
|
|
549
|
-
return value.map((item, index) => parseSkillRef(item, `Blueprint.skills[${index}]
|
|
615
|
+
return value.map((item, index) => parseSkillRef(item, `Blueprint.skills[${index}]`));
|
|
550
616
|
}
|
|
551
617
|
function parseBlueprintMcpServers(value) {
|
|
552
618
|
if (value === undefined) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Provider-neutral cleanup-policy resolution.
|
|
3
3
|
*
|
|
4
|
-
* Reads `cleanup.session
|
|
5
|
-
*
|
|
4
|
+
* Reads `cleanup.session`. Returns the worker default for any malformed
|
|
5
|
+
* shape — never throws.
|
|
6
6
|
*/
|
|
7
7
|
export type SessionCleanupPolicy = "retain" | "delete";
|
|
8
8
|
export declare function resolveCleanupPolicyFromSnapshot(snapshot: unknown, fallback: SessionCleanupPolicy): SessionCleanupPolicy;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Provider-neutral cleanup-policy resolution.
|
|
3
3
|
*
|
|
4
|
-
* Reads `cleanup.session
|
|
5
|
-
*
|
|
4
|
+
* Reads `cleanup.session`. Returns the worker default for any malformed
|
|
5
|
+
* shape — never throws.
|
|
6
6
|
*/
|
|
7
7
|
export function resolveCleanupPolicyFromSnapshot(snapshot, fallback) {
|
|
8
8
|
if (snapshot === null || snapshot === undefined || typeof snapshot !== "object" || Array.isArray(snapshot)) {
|
|
@@ -16,9 +16,6 @@ export function resolveCleanupPolicyFromSnapshot(snapshot, fallback) {
|
|
|
16
16
|
if (policy.session === "retain" || policy.session === "delete") {
|
|
17
17
|
return policy.session;
|
|
18
18
|
}
|
|
19
|
-
if (policy.claudeSession === "retain" || policy.claudeSession === "delete") {
|
|
20
|
-
return policy.claudeSession;
|
|
21
|
-
}
|
|
22
19
|
return fallback;
|
|
23
20
|
}
|
|
24
21
|
//# sourceMappingURL=cleanup-policy.js.map
|
package/dist/_shared/http.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
2
2
|
export interface HttpClientOptions {
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* (`https://
|
|
4
|
+
* API plane root. Optional — defaults to `ANTPATH_DEFAULT_BASE_URL`
|
|
5
|
+
* (`https://api.antpath.ai`). Self-hosted deployments override with their
|
|
6
6
|
* own URL; no env var consults this value.
|
|
7
7
|
*/
|
|
8
8
|
readonly baseUrl?: string;
|
package/dist/_shared/index.d.ts
CHANGED
|
@@ -3,10 +3,14 @@ export * from "./config.js";
|
|
|
3
3
|
export * from "./dev-stack.js";
|
|
4
4
|
export * from "./errors.js";
|
|
5
5
|
export * from "./proxy-protocol.js";
|
|
6
|
-
export * from "./secrets.js";
|
|
7
6
|
export * from "./status.js";
|
|
8
7
|
export * from "./submission.js";
|
|
8
|
+
export * from "./mcp-proxy-url.js";
|
|
9
|
+
export * from "./provider-proxy-url.js";
|
|
10
|
+
export * from "./runner-job.js";
|
|
11
|
+
export * from "./runner-event.js";
|
|
9
12
|
export * from "./run-unit.js";
|
|
13
|
+
export * from "./runtime-manifest.js";
|
|
10
14
|
export * from "./stable.js";
|
|
11
15
|
export * from "./sdk-secrets.js";
|
|
12
16
|
export * from "./sdk-errors.js";
|
package/dist/_shared/index.js
CHANGED
|
@@ -3,10 +3,14 @@ export * from "./config.js";
|
|
|
3
3
|
export * from "./dev-stack.js";
|
|
4
4
|
export * from "./errors.js";
|
|
5
5
|
export * from "./proxy-protocol.js";
|
|
6
|
-
export * from "./secrets.js";
|
|
7
6
|
export * from "./status.js";
|
|
8
7
|
export * from "./submission.js";
|
|
8
|
+
export * from "./mcp-proxy-url.js";
|
|
9
|
+
export * from "./provider-proxy-url.js";
|
|
10
|
+
export * from "./runner-job.js";
|
|
11
|
+
export * from "./runner-event.js";
|
|
9
12
|
export * from "./run-unit.js";
|
|
13
|
+
export * from "./runtime-manifest.js";
|
|
10
14
|
// SDK + CLI shared surface — moved here so the published `antpath` SDK
|
|
11
15
|
// and the in-container `antpath` CLI consume the SAME implementation.
|
|
12
16
|
export * from "./stable.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run Antpath MCP proxy URL + bearer minting types.
|
|
3
|
+
*
|
|
4
|
+
* The Antpath MCP proxy is the provider-independent abstraction that
|
|
5
|
+
* sits between the runtime (Anthropic Managed Agents OR the self-hosted
|
|
6
|
+
* Claude Code runner) and the customer-supplied MCP server. The
|
|
7
|
+
* runtime only sees Antpath-issued URLs and a scoped bearer; the
|
|
8
|
+
* customer's real MCP URL + auth headers stay in the run Vault
|
|
9
|
+
* bundle and never enter the runtime container.
|
|
10
|
+
*
|
|
11
|
+
* See `references/deepseek-runtime-mcp-plan.md` (Remote MCP proxy).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Platform-reserved key under which the per-run **MCP** proxy bearer is
|
|
15
|
+
* folded into the Vault bundle. Distinct from
|
|
16
|
+
* `__antpath_proxy_token` (which authorises the customer-declared
|
|
17
|
+
* `proxyEndpoints` route) so the two capabilities can be revoked
|
|
18
|
+
* independently — `references/deepseek-runtime-mcp-plan.md` (Security
|
|
19
|
+
* requirements: provider proxy and MCP proxy tokens are separate
|
|
20
|
+
* capabilities).
|
|
21
|
+
*
|
|
22
|
+
* The shared `parseInlineSecrets` rejects any inbound submission whose
|
|
23
|
+
* `secrets` carries a key with the `__antpath_` prefix, so this key
|
|
24
|
+
* can only be set by the BFF after the parser runs.
|
|
25
|
+
*/
|
|
26
|
+
export declare const MCP_PROXY_BEARER_BUNDLE_KEY = "__antpath_mcp_proxy_token";
|
|
27
|
+
/**
|
|
28
|
+
* Output of the per-run MCP proxy bearer mint. Same shape as the
|
|
29
|
+
* customer-proxy mint — the value is folded into the Vault bundle
|
|
30
|
+
* under {@link MCP_PROXY_BEARER_BUNDLE_KEY}; the hash + expiry are
|
|
31
|
+
* persisted on the runs row in dedicated columns so the two
|
|
32
|
+
* capabilities have independent lifetimes.
|
|
33
|
+
*/
|
|
34
|
+
export interface MintedMcpProxyBearer {
|
|
35
|
+
readonly plaintext: string;
|
|
36
|
+
readonly hash: string;
|
|
37
|
+
readonly expiresAt: Date;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Canonical URL path of the per-run MCP proxy endpoint. The BFF route
|
|
41
|
+
* lives at `/api/runs/[runId]/mcp/[mcpName]`; runtimes / providers
|
|
42
|
+
* receive the absolute URL from {@link buildMcpProxyUrl}.
|
|
43
|
+
*/
|
|
44
|
+
export declare function mcpProxyPath(runId: string, mcpName: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Build the absolute per-run, per-MCP proxy URL. `baseUrl` is the
|
|
47
|
+
* configured Antpath API plane root (e.g. `https://api.antpath.ai`);
|
|
48
|
+
* the function strips any trailing slash and appends
|
|
49
|
+
* `/api/runs/<runId>/mcp/<mcpName>`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildMcpProxyUrl(args: {
|
|
52
|
+
readonly baseUrl: string;
|
|
53
|
+
readonly runId: string;
|
|
54
|
+
readonly mcpName: string;
|
|
55
|
+
}): string;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run Antpath MCP proxy URL + bearer minting types.
|
|
3
|
+
*
|
|
4
|
+
* The Antpath MCP proxy is the provider-independent abstraction that
|
|
5
|
+
* sits between the runtime (Anthropic Managed Agents OR the self-hosted
|
|
6
|
+
* Claude Code runner) and the customer-supplied MCP server. The
|
|
7
|
+
* runtime only sees Antpath-issued URLs and a scoped bearer; the
|
|
8
|
+
* customer's real MCP URL + auth headers stay in the run Vault
|
|
9
|
+
* bundle and never enter the runtime container.
|
|
10
|
+
*
|
|
11
|
+
* See `references/deepseek-runtime-mcp-plan.md` (Remote MCP proxy).
|
|
12
|
+
*/
|
|
13
|
+
import { MCP_SERVER_NAME_PATTERN } from "./blueprint.js";
|
|
14
|
+
/**
|
|
15
|
+
* Platform-reserved key under which the per-run **MCP** proxy bearer is
|
|
16
|
+
* folded into the Vault bundle. Distinct from
|
|
17
|
+
* `__antpath_proxy_token` (which authorises the customer-declared
|
|
18
|
+
* `proxyEndpoints` route) so the two capabilities can be revoked
|
|
19
|
+
* independently — `references/deepseek-runtime-mcp-plan.md` (Security
|
|
20
|
+
* requirements: provider proxy and MCP proxy tokens are separate
|
|
21
|
+
* capabilities).
|
|
22
|
+
*
|
|
23
|
+
* The shared `parseInlineSecrets` rejects any inbound submission whose
|
|
24
|
+
* `secrets` carries a key with the `__antpath_` prefix, so this key
|
|
25
|
+
* can only be set by the BFF after the parser runs.
|
|
26
|
+
*/
|
|
27
|
+
export const MCP_PROXY_BEARER_BUNDLE_KEY = "__antpath_mcp_proxy_token";
|
|
28
|
+
/**
|
|
29
|
+
* Canonical URL path of the per-run MCP proxy endpoint. The BFF route
|
|
30
|
+
* lives at `/api/runs/[runId]/mcp/[mcpName]`; runtimes / providers
|
|
31
|
+
* receive the absolute URL from {@link buildMcpProxyUrl}.
|
|
32
|
+
*/
|
|
33
|
+
export function mcpProxyPath(runId, mcpName) {
|
|
34
|
+
if (!runId || typeof runId !== "string") {
|
|
35
|
+
throw new Error("mcpProxyPath: runId must be a non-empty string");
|
|
36
|
+
}
|
|
37
|
+
if (!mcpName || typeof mcpName !== "string" || !MCP_SERVER_NAME_PATTERN.test(mcpName)) {
|
|
38
|
+
throw new Error(`mcpProxyPath: mcpName must match ${MCP_SERVER_NAME_PATTERN.source}`);
|
|
39
|
+
}
|
|
40
|
+
return `/api/runs/${encodeURIComponent(runId)}/mcp/${encodeURIComponent(mcpName)}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build the absolute per-run, per-MCP proxy URL. `baseUrl` is the
|
|
44
|
+
* configured Antpath API plane root (e.g. `https://api.antpath.ai`);
|
|
45
|
+
* the function strips any trailing slash and appends
|
|
46
|
+
* `/api/runs/<runId>/mcp/<mcpName>`.
|
|
47
|
+
*/
|
|
48
|
+
export function buildMcpProxyUrl(args) {
|
|
49
|
+
if (!args.baseUrl || typeof args.baseUrl !== "string") {
|
|
50
|
+
throw new Error("buildMcpProxyUrl: baseUrl must be a non-empty string");
|
|
51
|
+
}
|
|
52
|
+
let parsedBase;
|
|
53
|
+
try {
|
|
54
|
+
parsedBase = new URL(args.baseUrl);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new Error(`buildMcpProxyUrl: baseUrl is not a valid URL: ${args.baseUrl}`);
|
|
58
|
+
}
|
|
59
|
+
if (parsedBase.protocol !== "https:" && parsedBase.protocol !== "http:") {
|
|
60
|
+
throw new Error(`buildMcpProxyUrl: baseUrl protocol must be http or https (got ${parsedBase.protocol})`);
|
|
61
|
+
}
|
|
62
|
+
const trimmedBase = `${parsedBase.origin}${parsedBase.pathname.replace(/\/+$/, "")}`;
|
|
63
|
+
return `${trimmedBase}${mcpProxyPath(args.runId, args.mcpName)}`;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=mcp-proxy-url.js.map
|
|
@@ -2,7 +2,7 @@ import type { HttpClient } from "./http.js";
|
|
|
2
2
|
import type { RunUnit } from "./run-unit.js";
|
|
3
3
|
import type { AgentsMdRecord, FileRecord, Output, Run, RunEvent, SignedOutputLink, Skill, WhoAmI } from "./runtime-types.js";
|
|
4
4
|
import { type SseFrame } from "./sse.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { PlatformRunSubmissionInput } from "./submission.js";
|
|
6
6
|
/**
|
|
7
7
|
* The single source of truth for SDK<->BFF transport. The SDK class
|
|
8
8
|
* AND the CLI subcommands both call these functions; neither
|
|
@@ -16,14 +16,13 @@ import type { PlatformFlatRunSubmissionInput, PlatformRunSubmissionInput } from
|
|
|
16
16
|
* `references/development-principles.md` (Agent-first surface design,
|
|
17
17
|
* Concrete rule 3).
|
|
18
18
|
*/
|
|
19
|
-
export declare function submitRun(http: HttpClient, request: PlatformRunSubmissionInput): Promise<Run>;
|
|
20
19
|
export declare function getRun(http: HttpClient, runId: string): Promise<Run>;
|
|
21
20
|
/**
|
|
22
21
|
* Strongly-typed accessor for the full self-contained run unit:
|
|
23
22
|
* parsed submission inputs, attempts, indexed events (with
|
|
24
23
|
* pagination cursor for large runs), raw-event Storage manifest,
|
|
25
24
|
* outputs, capture failures, proxy-call audit, pinned skills,
|
|
26
|
-
* provider skills,
|
|
25
|
+
* provider skills, inline skills.
|
|
27
26
|
*
|
|
28
27
|
* Backed by the same `GET /api/runs/:runId` endpoint that
|
|
29
28
|
* `getRun` calls; this variant just narrows the return type to
|
|
@@ -97,15 +96,15 @@ export declare function whoami(http: HttpClient): Promise<WhoAmI>;
|
|
|
97
96
|
* + `partial` fields.
|
|
98
97
|
*/
|
|
99
98
|
export declare function downloadRunArchive(http: HttpClient, runId: string): Promise<Response>;
|
|
100
|
-
export declare function
|
|
99
|
+
export declare function submitRun(http: HttpClient, request: PlatformRunSubmissionInput): Promise<Run>;
|
|
101
100
|
/**
|
|
102
|
-
* Multipart variant of `
|
|
101
|
+
* Multipart variant of `submitRun` for runs that carry transient
|
|
103
102
|
* (per-run) skill bundles and/or transient AgentsMd content.
|
|
104
103
|
*
|
|
105
104
|
* The JSON submission travels as the `submission` part; each
|
|
106
|
-
* `
|
|
105
|
+
* `InlineSkillRef.slot` in `request.submission.skills` MUST be
|
|
107
106
|
* mirrored by exactly one `skill:<slot>` part with the bundle bytes.
|
|
108
|
-
* Each `
|
|
107
|
+
* Each `InlineAgentsMdRef.slot` in `request.submission.agentsMd`
|
|
109
108
|
* MUST be mirrored by exactly one `agentsmd:<slot>` part with the
|
|
110
109
|
* markdown text.
|
|
111
110
|
*
|
|
@@ -114,7 +113,7 @@ export declare function submitRunFlat(http: HttpClient, request: PlatformFlatRun
|
|
|
114
113
|
*
|
|
115
114
|
* At least one of `bundles` or `agentsMdParts` must be non-empty.
|
|
116
115
|
*/
|
|
117
|
-
export declare function
|
|
116
|
+
export declare function submitRunMultipart(http: HttpClient, request: PlatformRunSubmissionInput, bundles: ReadonlyArray<{
|
|
118
117
|
readonly slot: string;
|
|
119
118
|
readonly bytes: Uint8Array;
|
|
120
119
|
readonly filename: string;
|