antpath 0.10.15 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +16 -8
  3. package/dist/_shared/blueprint.d.ts +93 -108
  4. package/dist/_shared/blueprint.js +144 -78
  5. package/dist/_shared/cleanup-policy.d.ts +2 -2
  6. package/dist/_shared/cleanup-policy.js +2 -5
  7. package/dist/_shared/http.d.ts +2 -2
  8. package/dist/_shared/index.d.ts +5 -1
  9. package/dist/_shared/index.js +5 -1
  10. package/dist/_shared/mcp-proxy-url.d.ts +55 -0
  11. package/dist/_shared/mcp-proxy-url.js +65 -0
  12. package/dist/_shared/operations.d.ts +7 -8
  13. package/dist/_shared/operations.js +14 -20
  14. package/dist/_shared/provider-proxy-url.d.ts +64 -0
  15. package/dist/_shared/provider-proxy-url.js +73 -0
  16. package/dist/_shared/proxy-validation.d.ts +1 -1
  17. package/dist/_shared/proxy-validation.js +2 -2
  18. package/dist/_shared/run-unit.d.ts +23 -36
  19. package/dist/_shared/run-unit.js +30 -46
  20. package/dist/_shared/runner-event.d.ts +120 -0
  21. package/dist/_shared/runner-event.js +193 -0
  22. package/dist/_shared/runner-job.d.ts +159 -0
  23. package/dist/_shared/runner-job.js +54 -0
  24. package/dist/_shared/runtime-manifest.d.ts +191 -0
  25. package/dist/_shared/runtime-manifest.js +221 -0
  26. package/dist/_shared/runtime-types.d.ts +7 -16
  27. package/dist/_shared/stable.d.ts +15 -10
  28. package/dist/_shared/stable.js +15 -10
  29. package/dist/_shared/submission.d.ts +199 -73
  30. package/dist/_shared/submission.js +409 -210
  31. package/dist/_shared/telemetry.d.ts +2 -2
  32. package/dist/_shared/telemetry.js +2 -2
  33. package/dist/_shared/template/index.d.ts +0 -1
  34. package/dist/_shared/template/index.js +0 -1
  35. package/dist/agents-md.d.ts +25 -67
  36. package/dist/agents-md.js +35 -121
  37. package/dist/agents-md.js.map +1 -1
  38. package/dist/asset-upload.d.ts +34 -0
  39. package/dist/asset-upload.js +34 -0
  40. package/dist/asset-upload.js.map +1 -1
  41. package/dist/blueprint.d.ts +3 -3
  42. package/dist/bundle.d.ts +2 -2
  43. package/dist/bundle.js +1 -1
  44. package/dist/cli.mjs +191 -100
  45. package/dist/cli.mjs.sha256 +1 -1
  46. package/dist/client.d.ts +34 -19
  47. package/dist/client.js +142 -124
  48. package/dist/client.js.map +1 -1
  49. package/dist/file.d.ts +28 -94
  50. package/dist/file.js +35 -175
  51. package/dist/file.js.map +1 -1
  52. package/dist/index.d.ts +5 -5
  53. package/dist/index.js +4 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/mcp-server.d.ts +10 -2
  56. package/dist/mcp-server.js +17 -2
  57. package/dist/mcp-server.js.map +1 -1
  58. package/dist/skill.d.ts +44 -214
  59. package/dist/skill.js +50 -284
  60. package/dist/skill.js.map +1 -1
  61. package/dist/version.d.ts +1 -1
  62. package/dist/version.js +1 -1
  63. package/dist/version.js.map +1 -1
  64. package/docs/cleanup.md +1 -1
  65. package/docs/credentials.md +2 -2
  66. package/docs/events.md +8 -8
  67. package/docs/outputs.md +2 -0
  68. package/docs/quickstart.md +18 -2
  69. package/docs/skills.md +1 -3
  70. package/docs/templates.md +6 -5
  71. package/package.json +2 -1
  72. package/dist/_shared/secrets.d.ts +0 -7
  73. package/dist/_shared/secrets.js +0 -20
  74. package/dist/_shared/template/mapper.d.ts +0 -11
  75. 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
- * Slot id format: `^[a-z][a-z0-9_-]{0,63}$`. The SDK generates these
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 isTransientSkillRef(ref) {
106
- return ref.kind === "transient";
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
- export function isWorkspaceFileRef(ref) {
115
- return ref.kind === "workspace_file";
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 isTransientFileRef(ref) {
118
- return ref.kind === "transient_file";
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. Throws
123
- * with a precise path so the caller can surface a usable error.
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, options = {}) {
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 === "transient") {
169
- if (options.allowTransient === false) {
170
- throw new Error(`${path} carries a transient SkillRef, which cannot round-trip through JSON — ` +
171
- `transient skills must be supplied at submitRun time with their bytes attached`);
172
- }
173
- for (const key of Object.keys(record)) {
174
- if (key !== "kind" && key !== "slot" && key !== "name" && key !== "contentHash") {
175
- throw new Error(`${path} contains unexpected field for transient SkillRef: ${key}`);
176
- }
177
- }
178
- const slot = record.slot;
179
- if (typeof slot !== "string" || !TRANSIENT_SLOT_PATTERN.test(slot)) {
180
- throw new Error(`${path}.slot must match ${TRANSIENT_SLOT_PATTERN.source}`);
181
- }
182
- const name = record.name;
183
- if (typeof name !== "string" || !SKILL_NAME_PATTERN.test(name)) {
184
- throw new Error(`${path}.name must match ${SKILL_NAME_PATTERN.source}`);
185
- }
186
- const contentHash = record.contentHash;
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
- throw new Error(`${path}.kind must be 'workspace', 'provider', or 'transient'`);
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 caller
353
- // accidentally inlining `headers` into the non-secret half fail loudly
354
- // instead of silently dropping the field. `parseBlueprintMcpServer`
355
- // handles the headers case separately for Blueprint-level entries.
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
- return { name, url };
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 `parseFlatRunSubmissionRequest`,
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}]`, { allowTransient: false }));
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` (canonical) and falls back to legacy `cleanup.claudeSession`.
5
- * Returns the worker default for any malformed shape — never throws.
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` (canonical) and falls back to legacy `cleanup.claudeSession`.
5
- * Returns the worker default for any malformed shape — never throws.
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
@@ -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
- * Dashboard BFF root. Optional — defaults to `ANTPATH_DEFAULT_BASE_URL`
5
- * (`https://www.antpath.ai`). Self-hosted deployments override with their
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;
@@ -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";
@@ -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 { PlatformFlatRunSubmissionInput, PlatformRunSubmissionInput } from "./submission.js";
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, transient 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 submitRunFlat(http: HttpClient, request: PlatformFlatRunSubmissionInput): Promise<Run>;
99
+ export declare function submitRun(http: HttpClient, request: PlatformRunSubmissionInput): Promise<Run>;
101
100
  /**
102
- * Multipart variant of `submitRunFlat` for runs that carry transient
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
- * `TransientSkillRef.slot` in `request.submission.skills` MUST be
105
+ * `InlineSkillRef.slot` in `request.submission.skills` MUST be
107
106
  * mirrored by exactly one `skill:<slot>` part with the bundle bytes.
108
- * Each `TransientAgentsMdRef.slot` in `request.submission.agentsMd`
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 submitRunFlatMultipart(http: HttpClient, request: PlatformFlatRunSubmissionInput, bundles: ReadonlyArray<{
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;