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
|
@@ -12,12 +12,6 @@ import { iterateSse } from "./sse.js";
|
|
|
12
12
|
* `references/development-principles.md` (Agent-first surface design,
|
|
13
13
|
* Concrete rule 3).
|
|
14
14
|
*/
|
|
15
|
-
export async function submitRun(http, request) {
|
|
16
|
-
return http.request("/api/runs", {
|
|
17
|
-
method: "POST",
|
|
18
|
-
body: JSON.stringify(request)
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
15
|
export async function getRun(http, runId) {
|
|
22
16
|
const result = await http.request(`/api/runs/${encodeURIComponent(runId)}`);
|
|
23
17
|
return hasRun(result) ? result.run : result;
|
|
@@ -27,7 +21,7 @@ export async function getRun(http, runId) {
|
|
|
27
21
|
* parsed submission inputs, attempts, indexed events (with
|
|
28
22
|
* pagination cursor for large runs), raw-event Storage manifest,
|
|
29
23
|
* outputs, capture failures, proxy-call audit, pinned skills,
|
|
30
|
-
* provider skills,
|
|
24
|
+
* provider skills, inline skills.
|
|
31
25
|
*
|
|
32
26
|
* Backed by the same `GET /api/runs/:runId` endpoint that
|
|
33
27
|
* `getRun` calls; this variant just narrows the return type to
|
|
@@ -222,22 +216,22 @@ export async function downloadRunArchive(http, runId) {
|
|
|
222
216
|
return response;
|
|
223
217
|
}
|
|
224
218
|
// ===========================================================================
|
|
225
|
-
//
|
|
219
|
+
// Run submission operations (Skill / McpServer / Blueprint composition)
|
|
226
220
|
// ===========================================================================
|
|
227
|
-
export async function
|
|
221
|
+
export async function submitRun(http, request) {
|
|
228
222
|
return http.request("/api/runs", {
|
|
229
223
|
method: "POST",
|
|
230
224
|
body: JSON.stringify(request)
|
|
231
225
|
});
|
|
232
226
|
}
|
|
233
227
|
/**
|
|
234
|
-
* Multipart variant of `
|
|
228
|
+
* Multipart variant of `submitRun` for runs that carry transient
|
|
235
229
|
* (per-run) skill bundles and/or transient AgentsMd content.
|
|
236
230
|
*
|
|
237
231
|
* The JSON submission travels as the `submission` part; each
|
|
238
|
-
* `
|
|
232
|
+
* `InlineSkillRef.slot` in `request.submission.skills` MUST be
|
|
239
233
|
* mirrored by exactly one `skill:<slot>` part with the bundle bytes.
|
|
240
|
-
* Each `
|
|
234
|
+
* Each `InlineAgentsMdRef.slot` in `request.submission.agentsMd`
|
|
241
235
|
* MUST be mirrored by exactly one `agentsmd:<slot>` part with the
|
|
242
236
|
* markdown text.
|
|
243
237
|
*
|
|
@@ -246,12 +240,12 @@ export async function submitRunFlat(http, request) {
|
|
|
246
240
|
*
|
|
247
241
|
* At least one of `bundles` or `agentsMdParts` must be non-empty.
|
|
248
242
|
*/
|
|
249
|
-
export async function
|
|
243
|
+
export async function submitRunMultipart(http, request, bundles, agentsMdParts, fileParts) {
|
|
250
244
|
const hasBundles = Array.isArray(bundles) && bundles.length > 0;
|
|
251
245
|
const hasAgentsMd = Array.isArray(agentsMdParts) && agentsMdParts.length > 0;
|
|
252
246
|
const hasFiles = Array.isArray(fileParts) && fileParts.length > 0;
|
|
253
247
|
if (!hasBundles && !hasAgentsMd && !hasFiles) {
|
|
254
|
-
throw new Error("
|
|
248
|
+
throw new Error("submitRunMultipart: bundles, agentsMdParts, or fileParts must be non-empty");
|
|
255
249
|
}
|
|
256
250
|
const form = new FormData();
|
|
257
251
|
// Submission rides as a typed JSON Blob so the BFF reads
|
|
@@ -261,10 +255,10 @@ export async function submitRunFlatMultipart(http, request, bundles, agentsMdPar
|
|
|
261
255
|
const seen = new Set();
|
|
262
256
|
for (const bundle of bundles) {
|
|
263
257
|
if (typeof bundle.slot !== "string" || !bundle.slot) {
|
|
264
|
-
throw new Error("
|
|
258
|
+
throw new Error("submitRunMultipart: each bundle must have a non-empty slot id");
|
|
265
259
|
}
|
|
266
260
|
if (seen.has(bundle.slot)) {
|
|
267
|
-
throw new Error(`
|
|
261
|
+
throw new Error(`submitRunMultipart: duplicate inline skill slot "${bundle.slot}"`);
|
|
268
262
|
}
|
|
269
263
|
seen.add(bundle.slot);
|
|
270
264
|
const blob = toBlob(bundle.bytes, "application/zip");
|
|
@@ -272,11 +266,11 @@ export async function submitRunFlatMultipart(http, request, bundles, agentsMdPar
|
|
|
272
266
|
}
|
|
273
267
|
for (const part of agentsMdParts ?? []) {
|
|
274
268
|
if (typeof part.slot !== "string" || !part.slot) {
|
|
275
|
-
throw new Error("
|
|
269
|
+
throw new Error("submitRunMultipart: each agentsMd part must have a non-empty slot id");
|
|
276
270
|
}
|
|
277
271
|
const partKey = `agentsmd:${part.slot}`;
|
|
278
272
|
if (seen.has(partKey)) {
|
|
279
|
-
throw new Error(`
|
|
273
|
+
throw new Error(`submitRunMultipart: duplicate agentsMd slot "${part.slot}"`);
|
|
280
274
|
}
|
|
281
275
|
seen.add(partKey);
|
|
282
276
|
const blob = new Blob([part.content], { type: "text/plain" });
|
|
@@ -284,11 +278,11 @@ export async function submitRunFlatMultipart(http, request, bundles, agentsMdPar
|
|
|
284
278
|
}
|
|
285
279
|
for (const part of fileParts ?? []) {
|
|
286
280
|
if (typeof part.slot !== "string" || !part.slot) {
|
|
287
|
-
throw new Error("
|
|
281
|
+
throw new Error("submitRunMultipart: each file part must have a non-empty slot id");
|
|
288
282
|
}
|
|
289
283
|
const partKey = `file:${part.slot}`;
|
|
290
284
|
if (seen.has(partKey)) {
|
|
291
|
-
throw new Error(`
|
|
285
|
+
throw new Error(`submitRunMultipart: duplicate file slot "${part.slot}"`);
|
|
292
286
|
}
|
|
293
287
|
seen.add(partKey);
|
|
294
288
|
const blob = toBlob(part.bytes, "application/zip");
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run Antpath provider proxy URL + bearer minting types.
|
|
3
|
+
*
|
|
4
|
+
* The provider proxy is the second of Antpath's two
|
|
5
|
+
* runtime-independent proxies (the other is the MCP proxy in
|
|
6
|
+
* `./mcp-proxy-url.ts`). It sits between the self-hosted runner and
|
|
7
|
+
* the customer's provider API — today that's DeepSeek's
|
|
8
|
+
* Anthropic-compatible endpoint, but the route is namespaced so
|
|
9
|
+
* additional providers slot in without a wire-format change.
|
|
10
|
+
*
|
|
11
|
+
* The runner container sees only `ANTHROPIC_BASE_URL=<proxy-url>` and
|
|
12
|
+
* `ANTHROPIC_AUTH_TOKEN=<scoped-bearer>`; the real provider key + base
|
|
13
|
+
* URL stay in the run Vault bundle. See
|
|
14
|
+
* `references/deepseek-runtime-mcp-plan.md` (Provider proxy +
|
|
15
|
+
* Security requirements).
|
|
16
|
+
*/
|
|
17
|
+
import type { RunProvider } from "./submission.js";
|
|
18
|
+
/**
|
|
19
|
+
* Platform-reserved key under which the per-run provider proxy bearer
|
|
20
|
+
* is folded into the Vault bundle. Distinct from
|
|
21
|
+
* `__antpath_proxy_token` (customer-declared HTTP proxy) and
|
|
22
|
+
* `__antpath_mcp_proxy_token` (MCP proxy) so the three capabilities
|
|
23
|
+
* are revoked independently. The shared `parseInlineSecrets` rejects
|
|
24
|
+
* any inbound submission whose `secrets` carries a key with the
|
|
25
|
+
* `__antpath_` prefix; only the BFF mutates this after the parser.
|
|
26
|
+
*/
|
|
27
|
+
export declare const PROVIDER_PROXY_BEARER_BUNDLE_KEY = "__antpath_provider_proxy_token";
|
|
28
|
+
/**
|
|
29
|
+
* Output of the per-run provider proxy bearer mint. Same primitive
|
|
30
|
+
* (high-entropy random + peppered SHA-256) as the customer-proxy +
|
|
31
|
+
* MCP-proxy mints; persisted in dedicated columns / Vault keys so
|
|
32
|
+
* the three capabilities don't share a fate.
|
|
33
|
+
*/
|
|
34
|
+
export interface MintedProviderProxyBearer {
|
|
35
|
+
readonly plaintext: string;
|
|
36
|
+
readonly hash: string;
|
|
37
|
+
readonly expiresAt: Date;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* DeepSeek's documented Anthropic-compatibility endpoint. Used by the
|
|
41
|
+
* provider proxy as the default upstream when the customer does not
|
|
42
|
+
* supply `secrets.deepseek.baseUrl`. Subject to DeepSeek's own
|
|
43
|
+
* upstream changes — see `references/deepseek-runtime-mcp-plan.md`
|
|
44
|
+
* (Source facts to re-check).
|
|
45
|
+
*/
|
|
46
|
+
export declare const DEEPSEEK_ANTHROPIC_COMPAT_DEFAULT_BASE_URL = "https://api.deepseek.com/anthropic";
|
|
47
|
+
/**
|
|
48
|
+
* Canonical URL path of the per-run provider proxy endpoint. The BFF
|
|
49
|
+
* route lives at `/api/runs/[runId]/provider-proxy/[providerName]`;
|
|
50
|
+
* the runner / runtime receives the absolute URL from
|
|
51
|
+
* {@link buildProviderProxyUrl}.
|
|
52
|
+
*/
|
|
53
|
+
export declare function providerProxyPath(runId: string, provider: RunProvider): string;
|
|
54
|
+
/**
|
|
55
|
+
* Build the absolute per-run, per-provider proxy URL. `baseUrl` is the
|
|
56
|
+
* configured Antpath API plane root (e.g. `https://api.antpath.ai`);
|
|
57
|
+
* the function strips any trailing slash and appends the canonical
|
|
58
|
+
* provider proxy path.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildProviderProxyUrl(args: {
|
|
61
|
+
readonly baseUrl: string;
|
|
62
|
+
readonly runId: string;
|
|
63
|
+
readonly provider: RunProvider;
|
|
64
|
+
}): string;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run Antpath provider proxy URL + bearer minting types.
|
|
3
|
+
*
|
|
4
|
+
* The provider proxy is the second of Antpath's two
|
|
5
|
+
* runtime-independent proxies (the other is the MCP proxy in
|
|
6
|
+
* `./mcp-proxy-url.ts`). It sits between the self-hosted runner and
|
|
7
|
+
* the customer's provider API — today that's DeepSeek's
|
|
8
|
+
* Anthropic-compatible endpoint, but the route is namespaced so
|
|
9
|
+
* additional providers slot in without a wire-format change.
|
|
10
|
+
*
|
|
11
|
+
* The runner container sees only `ANTHROPIC_BASE_URL=<proxy-url>` and
|
|
12
|
+
* `ANTHROPIC_AUTH_TOKEN=<scoped-bearer>`; the real provider key + base
|
|
13
|
+
* URL stay in the run Vault bundle. See
|
|
14
|
+
* `references/deepseek-runtime-mcp-plan.md` (Provider proxy +
|
|
15
|
+
* Security requirements).
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Platform-reserved key under which the per-run provider proxy bearer
|
|
19
|
+
* is folded into the Vault bundle. Distinct from
|
|
20
|
+
* `__antpath_proxy_token` (customer-declared HTTP proxy) and
|
|
21
|
+
* `__antpath_mcp_proxy_token` (MCP proxy) so the three capabilities
|
|
22
|
+
* are revoked independently. The shared `parseInlineSecrets` rejects
|
|
23
|
+
* any inbound submission whose `secrets` carries a key with the
|
|
24
|
+
* `__antpath_` prefix; only the BFF mutates this after the parser.
|
|
25
|
+
*/
|
|
26
|
+
export const PROVIDER_PROXY_BEARER_BUNDLE_KEY = "__antpath_provider_proxy_token";
|
|
27
|
+
/**
|
|
28
|
+
* DeepSeek's documented Anthropic-compatibility endpoint. Used by the
|
|
29
|
+
* provider proxy as the default upstream when the customer does not
|
|
30
|
+
* supply `secrets.deepseek.baseUrl`. Subject to DeepSeek's own
|
|
31
|
+
* upstream changes — see `references/deepseek-runtime-mcp-plan.md`
|
|
32
|
+
* (Source facts to re-check).
|
|
33
|
+
*/
|
|
34
|
+
export const DEEPSEEK_ANTHROPIC_COMPAT_DEFAULT_BASE_URL = "https://api.deepseek.com/anthropic";
|
|
35
|
+
/**
|
|
36
|
+
* Canonical URL path of the per-run provider proxy endpoint. The BFF
|
|
37
|
+
* route lives at `/api/runs/[runId]/provider-proxy/[providerName]`;
|
|
38
|
+
* the runner / runtime receives the absolute URL from
|
|
39
|
+
* {@link buildProviderProxyUrl}.
|
|
40
|
+
*/
|
|
41
|
+
export function providerProxyPath(runId, provider) {
|
|
42
|
+
if (!runId || typeof runId !== "string") {
|
|
43
|
+
throw new Error("providerProxyPath: runId must be a non-empty string");
|
|
44
|
+
}
|
|
45
|
+
if (provider !== "anthropic" && provider !== "deepseek") {
|
|
46
|
+
throw new Error(`providerProxyPath: unsupported provider ${JSON.stringify(provider)}`);
|
|
47
|
+
}
|
|
48
|
+
return `/api/runs/${encodeURIComponent(runId)}/provider-proxy/${provider}`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build the absolute per-run, per-provider proxy URL. `baseUrl` is the
|
|
52
|
+
* configured Antpath API plane root (e.g. `https://api.antpath.ai`);
|
|
53
|
+
* the function strips any trailing slash and appends the canonical
|
|
54
|
+
* provider proxy path.
|
|
55
|
+
*/
|
|
56
|
+
export function buildProviderProxyUrl(args) {
|
|
57
|
+
if (!args.baseUrl || typeof args.baseUrl !== "string") {
|
|
58
|
+
throw new Error("buildProviderProxyUrl: baseUrl must be a non-empty string");
|
|
59
|
+
}
|
|
60
|
+
let parsedBase;
|
|
61
|
+
try {
|
|
62
|
+
parsedBase = new URL(args.baseUrl);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new Error(`buildProviderProxyUrl: baseUrl is not a valid URL: ${args.baseUrl}`);
|
|
66
|
+
}
|
|
67
|
+
if (parsedBase.protocol !== "https:" && parsedBase.protocol !== "http:") {
|
|
68
|
+
throw new Error(`buildProviderProxyUrl: baseUrl protocol must be http or https (got ${parsedBase.protocol})`);
|
|
69
|
+
}
|
|
70
|
+
const trimmedBase = `${parsedBase.origin}${parsedBase.pathname.replace(/\/+$/, "")}`;
|
|
71
|
+
return `${trimmedBase}${providerProxyPath(args.runId, args.provider)}`;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=provider-proxy-url.js.map
|
|
@@ -14,6 +14,6 @@ export declare function validateProxyAuth(endpoints: readonly PlatformProxyEndpo
|
|
|
14
14
|
* caller is hand-rolling networking.
|
|
15
15
|
*/
|
|
16
16
|
export declare function buildPlatformAllowedHosts(input: {
|
|
17
|
-
readonly
|
|
17
|
+
readonly baseUrl: string;
|
|
18
18
|
readonly extraHosts?: readonly string[];
|
|
19
19
|
}): readonly string[];
|
|
@@ -37,10 +37,10 @@ export function validateProxyAuth(endpoints, auth) {
|
|
|
37
37
|
export function buildPlatformAllowedHosts(input) {
|
|
38
38
|
const result = [];
|
|
39
39
|
try {
|
|
40
|
-
result.push(new URL(input.
|
|
40
|
+
result.push(new URL(input.baseUrl).host);
|
|
41
41
|
}
|
|
42
42
|
catch {
|
|
43
|
-
throw new Error("buildPlatformAllowedHosts:
|
|
43
|
+
throw new Error("buildPlatformAllowedHosts: baseUrl must be an absolute URL");
|
|
44
44
|
}
|
|
45
45
|
for (const host of input.extraHosts ?? []) {
|
|
46
46
|
if (!result.includes(host))
|
|
@@ -19,36 +19,16 @@
|
|
|
19
19
|
* `rawEventPages` (manifest only; bytes downloaded out-of-band so the
|
|
20
20
|
* detail response stays bounded). The archive zip carries the bytes.
|
|
21
21
|
*/
|
|
22
|
-
import type { JsonValue, PlatformCleanupPolicy,
|
|
22
|
+
import type { JsonValue, PlatformCleanupPolicy, PlatformSubmission, PlatformProxyEndpoint } from "./submission.js";
|
|
23
23
|
/**
|
|
24
|
-
* Parsed view of `runs.template_snapshot` jsonb.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* - `kind: "flat"` (current): {kind:"flat", submission, cleanup?}
|
|
28
|
-
* written by `insertRunWithSkillSnapshots` for all new runs.
|
|
29
|
-
* - legacy template-shaped: {template, executionPayloadSecretId,
|
|
30
|
-
* variables?, cleanup?} written by `insertRun` before the flat
|
|
31
|
-
* pivot.
|
|
32
|
-
*
|
|
33
|
-
* The parser tolerates both and returns a discriminated union so
|
|
34
|
-
* consumers branch mechanically. New work targets `kind: "flat"`.
|
|
35
|
-
*
|
|
36
|
-
* Note on legacy redaction: historic template-shaped snapshots have
|
|
37
|
-
* `system` and `messages` replaced with `"[redacted]"` by
|
|
38
|
-
* `redactTemplateForMetadata`. That redaction predates the raw-event /
|
|
39
|
-
* raw-input policy update and we do not retroactively un-redact data we
|
|
40
|
-
* never stored. Flat-shape snapshots are verbatim.
|
|
24
|
+
* Parsed view of `runs.template_snapshot` jsonb. Stored shape is
|
|
25
|
+
* `{kind:"submission", submission, cleanup?}` written by
|
|
26
|
+
* `insertRunWithSkillSnapshots` for all runs.
|
|
41
27
|
*/
|
|
42
|
-
export type RunUnitSubmission = RunUnitFlatSubmission
|
|
28
|
+
export type RunUnitSubmission = RunUnitFlatSubmission;
|
|
43
29
|
export interface RunUnitFlatSubmission {
|
|
44
|
-
readonly kind: "
|
|
45
|
-
readonly submission:
|
|
46
|
-
readonly cleanup?: PlatformCleanupPolicy;
|
|
47
|
-
}
|
|
48
|
-
export interface RunUnitTemplateSubmission {
|
|
49
|
-
readonly kind: "template";
|
|
50
|
-
readonly template: PlatformTemplateSubmission;
|
|
51
|
-
readonly variables?: Record<string, JsonValue>;
|
|
30
|
+
readonly kind: "submission";
|
|
31
|
+
readonly submission: PlatformSubmission;
|
|
52
32
|
readonly cleanup?: PlatformCleanupPolicy;
|
|
53
33
|
}
|
|
54
34
|
export interface RunUnitAttempt {
|
|
@@ -157,7 +137,7 @@ export interface RunUnitProviderSkill {
|
|
|
157
137
|
readonly skillId: string;
|
|
158
138
|
readonly version?: string;
|
|
159
139
|
}
|
|
160
|
-
export interface
|
|
140
|
+
export interface RunUnitInlineSkill {
|
|
161
141
|
readonly id: string;
|
|
162
142
|
readonly slotId: string;
|
|
163
143
|
readonly skillName: string;
|
|
@@ -190,17 +170,24 @@ export interface RunUnit {
|
|
|
190
170
|
readonly proxyCalls: RunUnitProxyCallPage;
|
|
191
171
|
readonly skillSnapshots: readonly RunUnitSkillSnapshot[];
|
|
192
172
|
readonly providerSkills: readonly RunUnitProviderSkill[];
|
|
193
|
-
readonly
|
|
173
|
+
readonly inlineSkills: readonly RunUnitInlineSkill[];
|
|
174
|
+
/**
|
|
175
|
+
* Per-run, per-provider runtime manifest — derived from the validated
|
|
176
|
+
* submission + the chosen provider (`buildRuntimeManifest`). Tells
|
|
177
|
+
* SDK consumers where antpath placed things in-container and what
|
|
178
|
+
* env vars the agent will see. Undefined on responses from BFFs
|
|
179
|
+
* that predate Phase 2 of the runtime-environment rollout.
|
|
180
|
+
*/
|
|
181
|
+
readonly runtimeManifest?: import("./runtime-manifest.js").RuntimeManifest;
|
|
194
182
|
}
|
|
195
183
|
/**
|
|
196
|
-
* Parse a `runs.template_snapshot` jsonb payload into the typed
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* worker-side enrichment.
|
|
184
|
+
* Parse a `runs.template_snapshot` jsonb payload into the typed flat
|
|
185
|
+
* submission. Never throws on minor unknown keys so we can
|
|
186
|
+
* forward-compat with worker-side enrichment.
|
|
200
187
|
*
|
|
201
188
|
* Returns a typed shape even for malformed snapshots — the worst case
|
|
202
|
-
* is `{kind: "
|
|
203
|
-
* — because the dashboard must still render *something* for a
|
|
204
|
-
* historical row rather than 500ing the whole detail page.
|
|
189
|
+
* is `{kind: "submission", submission: {model: "", ...}}` with empty
|
|
190
|
+
* defaults — because the dashboard must still render *something* for a
|
|
191
|
+
* buggy historical row rather than 500ing the whole detail page.
|
|
205
192
|
*/
|
|
206
193
|
export declare function parseRunUnitSubmission(input: unknown): RunUnitSubmission;
|
package/dist/_shared/run-unit.js
CHANGED
|
@@ -24,29 +24,25 @@ import { parseMcpServerRef, parseSkillRef } from "./blueprint.js";
|
|
|
24
24
|
// Submission parser
|
|
25
25
|
// ---------------------------------------------------------------------------
|
|
26
26
|
/**
|
|
27
|
-
* Parse a `runs.template_snapshot` jsonb payload into the typed
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* worker-side enrichment.
|
|
27
|
+
* Parse a `runs.template_snapshot` jsonb payload into the typed flat
|
|
28
|
+
* submission. Never throws on minor unknown keys so we can
|
|
29
|
+
* forward-compat with worker-side enrichment.
|
|
31
30
|
*
|
|
32
31
|
* Returns a typed shape even for malformed snapshots — the worst case
|
|
33
|
-
* is `{kind: "
|
|
34
|
-
* — because the dashboard must still render *something* for a
|
|
35
|
-
* historical row rather than 500ing the whole detail page.
|
|
32
|
+
* is `{kind: "submission", submission: {model: "", ...}}` with empty
|
|
33
|
+
* defaults — because the dashboard must still render *something* for a
|
|
34
|
+
* buggy historical row rather than 500ing the whole detail page.
|
|
36
35
|
*/
|
|
37
36
|
export function parseRunUnitSubmission(input) {
|
|
38
37
|
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
39
38
|
return fallbackFlat();
|
|
40
39
|
}
|
|
41
40
|
const value = input;
|
|
42
|
-
if (value.kind === "
|
|
41
|
+
if (value.kind === "submission") {
|
|
43
42
|
return parseFlatProjection(value);
|
|
44
43
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
// Snapshot exists but matches neither shape — surface as an empty
|
|
49
|
-
// flat submission so consumers can still render lifecycle bits.
|
|
44
|
+
// Snapshot exists but does not match the flat shape — surface as an
|
|
45
|
+
// empty flat submission so consumers can still render lifecycle bits.
|
|
50
46
|
return fallbackFlat();
|
|
51
47
|
}
|
|
52
48
|
function parseFlatProjection(value) {
|
|
@@ -69,36 +65,14 @@ function parseFlatProjection(value) {
|
|
|
69
65
|
: {})
|
|
70
66
|
};
|
|
71
67
|
return {
|
|
72
|
-
kind: "
|
|
68
|
+
kind: "submission",
|
|
73
69
|
submission,
|
|
74
70
|
...(cleanup ? { cleanup } : {})
|
|
75
71
|
};
|
|
76
72
|
}
|
|
77
|
-
function parseTemplateProjection(value) {
|
|
78
|
-
const templateRaw = value.template;
|
|
79
|
-
const template = {
|
|
80
|
-
name: typeof templateRaw.name === "string" ? templateRaw.name : "",
|
|
81
|
-
model: typeof templateRaw.model === "string" ? templateRaw.model : "",
|
|
82
|
-
templateHash: typeof templateRaw.templateHash === "string" ? templateRaw.templateHash : "",
|
|
83
|
-
messages: toStringArray(templateRaw.messages),
|
|
84
|
-
...(typeof templateRaw.system === "string" ? { system: templateRaw.system } : {}),
|
|
85
|
-
...(isJsonRecord(templateRaw.metadata) ? { metadata: templateRaw.metadata } : {}),
|
|
86
|
-
...(parseEnvironment(templateRaw.environment)
|
|
87
|
-
? { environment: parseEnvironment(templateRaw.environment) }
|
|
88
|
-
: {})
|
|
89
|
-
};
|
|
90
|
-
const variables = isJsonRecord(value.variables) ? value.variables : undefined;
|
|
91
|
-
const cleanup = parseCleanup(value.cleanup);
|
|
92
|
-
return {
|
|
93
|
-
kind: "template",
|
|
94
|
-
template,
|
|
95
|
-
...(variables ? { variables } : {}),
|
|
96
|
-
...(cleanup ? { cleanup } : {})
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
73
|
function fallbackFlat() {
|
|
100
74
|
return {
|
|
101
|
-
kind: "
|
|
75
|
+
kind: "submission",
|
|
102
76
|
submission: {
|
|
103
77
|
model: "",
|
|
104
78
|
prompt: [],
|
|
@@ -140,7 +114,7 @@ function toSkillRefArray(value) {
|
|
|
140
114
|
const out = [];
|
|
141
115
|
for (let i = 0; i < value.length; i++) {
|
|
142
116
|
try {
|
|
143
|
-
out.push(parseSkillRef(value[i], `submission.skills[${i}]
|
|
117
|
+
out.push(parseSkillRef(value[i], `submission.skills[${i}]`));
|
|
144
118
|
}
|
|
145
119
|
catch {
|
|
146
120
|
// Skip malformed entries rather than failing the whole detail
|
|
@@ -195,7 +169,22 @@ function parseEnvironment(value) {
|
|
|
195
169
|
env.packages = pkgs;
|
|
196
170
|
}
|
|
197
171
|
}
|
|
198
|
-
|
|
172
|
+
// Lenient pass-through for envVars stored in already-validated
|
|
173
|
+
// snapshots. The strict parser in submission.ts enforces shape /
|
|
174
|
+
// size / reserved-prefix rules at submission time; here we just
|
|
175
|
+
// accept whatever shape was persisted.
|
|
176
|
+
if (isRecord(value.envVars)) {
|
|
177
|
+
const out = {};
|
|
178
|
+
for (const [k, v] of Object.entries(value.envVars)) {
|
|
179
|
+
if (typeof v === "string") {
|
|
180
|
+
out[k] = v;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (Object.keys(out).length > 0) {
|
|
184
|
+
env.envVars = out;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return env.networking || env.packages || env.envVars
|
|
199
188
|
? env
|
|
200
189
|
: undefined;
|
|
201
190
|
}
|
|
@@ -204,14 +193,9 @@ function parseCleanup(value) {
|
|
|
204
193
|
return undefined;
|
|
205
194
|
}
|
|
206
195
|
const session = value.session;
|
|
207
|
-
const claudeSession = value.claudeSession;
|
|
208
|
-
const out = {};
|
|
209
196
|
if (session === "retain" || session === "delete") {
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
if (claudeSession === "retain" || claudeSession === "delete") {
|
|
213
|
-
out.claudeSession = claudeSession;
|
|
197
|
+
return { session };
|
|
214
198
|
}
|
|
215
|
-
return
|
|
199
|
+
return undefined;
|
|
216
200
|
}
|
|
217
201
|
//# sourceMappingURL=run-unit.js.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified runner event schema. Both runtimes feed the same shape into
|
|
3
|
+
* the api.antpath.ai event pipeline:
|
|
4
|
+
*
|
|
5
|
+
* - **Anthropic Native** — the `AnthropicSseInbox` Durable Object
|
|
6
|
+
* consumes Anthropic's `/v1/messages/stream` SSE stream and uses
|
|
7
|
+
* the Anthropic adapter to translate each event into one or more
|
|
8
|
+
* `RunnerEvent`s.
|
|
9
|
+
* - **Goose Managed** — the per-run runner image POSTs batches of
|
|
10
|
+
* NDJSON events to `/runs/{id}/runner/events`; the Goose adapter
|
|
11
|
+
* translates each event into one or more `RunnerEvent`s.
|
|
12
|
+
*
|
|
13
|
+
* The downstream subscribers (dashboard, SDK `streamEvents`, observable
|
|
14
|
+
* spans) never see the runtime-specific wire shapes — they only see
|
|
15
|
+
* `RunnerEvent`s. This is the cutover boundary that makes the dual
|
|
16
|
+
* runtime invisible to customers.
|
|
17
|
+
*
|
|
18
|
+
* See `references/platform-rebuild-2026.md` (Wire contracts →
|
|
19
|
+
* runner-event).
|
|
20
|
+
*/
|
|
21
|
+
import type { JsonValue } from "./submission.js";
|
|
22
|
+
/**
|
|
23
|
+
* Schema version. Bump when the shape of `RunnerEvent`, its kind set,
|
|
24
|
+
* or the batch envelope changes. Subscribers gate on this so a future
|
|
25
|
+
* v2 wire shape can land behind a feature flag.
|
|
26
|
+
*/
|
|
27
|
+
export declare const RUNNER_EVENT_VERSION: 1;
|
|
28
|
+
/**
|
|
29
|
+
* The set of event kinds emitted into the unified stream. Adapters
|
|
30
|
+
* fold runtime-specific events into one of these — anything that
|
|
31
|
+
* doesn't fit is mapped to `notification` so the data is captured
|
|
32
|
+
* even when no UI handler exists yet.
|
|
33
|
+
*
|
|
34
|
+
* - `runtime_started` — either runtime announced "ready" (Fly
|
|
35
|
+
* machine running goose; Anthropic session
|
|
36
|
+
* accepted the first turn).
|
|
37
|
+
* - `assistant_text` — model text delta.
|
|
38
|
+
* - `tool_request` — model emitted a tool_use / function call.
|
|
39
|
+
* - `tool_response` — tool result delivered back to the model.
|
|
40
|
+
* - `skill_loaded` — a skill was loaded (Anthropic Skills API
|
|
41
|
+
* ref OR a workspace folder mount).
|
|
42
|
+
* - `file_uploaded` — a file became available to the agent
|
|
43
|
+
* (Files API id OR workspace path).
|
|
44
|
+
* - `notification` — runtime/extension notification; catch-all
|
|
45
|
+
* for diagnostic data.
|
|
46
|
+
* - `stream_error` — stream-level error (non-fatal). Subscribers
|
|
47
|
+
* may surface this as a UI warning; the run
|
|
48
|
+
* continues unless `runtime_terminal` follows.
|
|
49
|
+
* - `runtime_terminal` — the run reached a terminal state. The
|
|
50
|
+
* adapter MUST emit exactly one of these per
|
|
51
|
+
* run; subscribers gate on it for end-of-stream.
|
|
52
|
+
*/
|
|
53
|
+
export declare const RUNNER_EVENT_KINDS: readonly ["runtime_started", "assistant_text", "tool_request", "tool_response", "skill_loaded", "file_uploaded", "notification", "stream_error", "runtime_terminal"];
|
|
54
|
+
export type RunnerEventKind = (typeof RUNNER_EVENT_KINDS)[number];
|
|
55
|
+
/**
|
|
56
|
+
* One event in the unified stream. `seq` is monotonically increasing
|
|
57
|
+
* within a single run (the adapter is responsible for assigning seqs
|
|
58
|
+
* — no two events with the same `seq` for the same `runId`); `tMs` is
|
|
59
|
+
* a millisecond-resolution timestamp that is also monotonically
|
|
60
|
+
* non-decreasing within a single run (an event's `tMs` is never less
|
|
61
|
+
* than the previous event's `tMs`). `data` carries the runtime- and
|
|
62
|
+
* kind-specific payload, JSON-typed so the batch round-trips through
|
|
63
|
+
* the database column without ad-hoc serialization.
|
|
64
|
+
*/
|
|
65
|
+
export interface RunnerEvent {
|
|
66
|
+
readonly seq: number;
|
|
67
|
+
readonly tMs: number;
|
|
68
|
+
readonly kind: RunnerEventKind;
|
|
69
|
+
readonly data: Readonly<Record<string, JsonValue>>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Batch envelope. The runner ships one or more events per POST so the
|
|
73
|
+
* inbox writes them atomically. `events` MUST be sorted by `seq`
|
|
74
|
+
* ascending; api.antpath.ai rejects malformed batches before touching
|
|
75
|
+
* Postgres.
|
|
76
|
+
*/
|
|
77
|
+
export interface RunnerEventBatch {
|
|
78
|
+
readonly v: typeof RUNNER_EVENT_VERSION;
|
|
79
|
+
readonly runId: string;
|
|
80
|
+
readonly events: readonly RunnerEvent[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Maximum number of events per batch. Bounds the size of the body
|
|
84
|
+
* api.antpath.ai accepts and the size of the Durable Object write.
|
|
85
|
+
* Larger streams are split into multiple batches; the runner is
|
|
86
|
+
* responsible for chunking.
|
|
87
|
+
*/
|
|
88
|
+
export declare const RUNNER_EVENT_BATCH_MAX_EVENTS: 256;
|
|
89
|
+
/**
|
|
90
|
+
* Validation outcome for an inbound batch. The `ok` branch returns
|
|
91
|
+
* the parsed batch with frozen events; the `error` branch returns the
|
|
92
|
+
* code + a short human message suitable for an HTTP 400 body. Codes
|
|
93
|
+
* are stable strings — the dashboard / SDK may branch on them.
|
|
94
|
+
*/
|
|
95
|
+
export type RunnerEventBatchValidation = {
|
|
96
|
+
readonly ok: true;
|
|
97
|
+
readonly batch: RunnerEventBatch;
|
|
98
|
+
} | {
|
|
99
|
+
readonly ok: false;
|
|
100
|
+
readonly code: RunnerEventBatchValidationCode;
|
|
101
|
+
readonly message: string;
|
|
102
|
+
};
|
|
103
|
+
export declare const RUNNER_EVENT_BATCH_VALIDATION_CODES: readonly ["invalid_envelope", "version_mismatch", "missing_run_id", "empty_batch", "batch_too_large", "invalid_event", "seq_not_monotonic", "t_ms_not_monotonic"];
|
|
104
|
+
export type RunnerEventBatchValidationCode = (typeof RUNNER_EVENT_BATCH_VALIDATION_CODES)[number];
|
|
105
|
+
/**
|
|
106
|
+
* Parse + validate an inbound runner event batch (untrusted input).
|
|
107
|
+
* Used at the api.antpath.ai ingress so adapters never have to
|
|
108
|
+
* re-check the wire shape, and used by tests to assert the contract.
|
|
109
|
+
*
|
|
110
|
+
* Successful validation guarantees:
|
|
111
|
+
* - top-level envelope matches {@link RunnerEventBatch}
|
|
112
|
+
* - `v === RUNNER_EVENT_VERSION`
|
|
113
|
+
* - `runId` is a non-empty string
|
|
114
|
+
* - `events` is a non-empty array of at most
|
|
115
|
+
* {@link RUNNER_EVENT_BATCH_MAX_EVENTS} entries
|
|
116
|
+
* - each event is a {@link RunnerEvent} with a known `kind`
|
|
117
|
+
* - `seq` is strictly increasing across the batch
|
|
118
|
+
* - `tMs` is non-decreasing across the batch
|
|
119
|
+
*/
|
|
120
|
+
export declare function validateRunnerEventBatch(input: unknown): RunnerEventBatchValidation;
|