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
|
@@ -0,0 +1,193 @@
|
|
|
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
|
+
/**
|
|
22
|
+
* Schema version. Bump when the shape of `RunnerEvent`, its kind set,
|
|
23
|
+
* or the batch envelope changes. Subscribers gate on this so a future
|
|
24
|
+
* v2 wire shape can land behind a feature flag.
|
|
25
|
+
*/
|
|
26
|
+
export const RUNNER_EVENT_VERSION = 1;
|
|
27
|
+
/**
|
|
28
|
+
* The set of event kinds emitted into the unified stream. Adapters
|
|
29
|
+
* fold runtime-specific events into one of these — anything that
|
|
30
|
+
* doesn't fit is mapped to `notification` so the data is captured
|
|
31
|
+
* even when no UI handler exists yet.
|
|
32
|
+
*
|
|
33
|
+
* - `runtime_started` — either runtime announced "ready" (Fly
|
|
34
|
+
* machine running goose; Anthropic session
|
|
35
|
+
* accepted the first turn).
|
|
36
|
+
* - `assistant_text` — model text delta.
|
|
37
|
+
* - `tool_request` — model emitted a tool_use / function call.
|
|
38
|
+
* - `tool_response` — tool result delivered back to the model.
|
|
39
|
+
* - `skill_loaded` — a skill was loaded (Anthropic Skills API
|
|
40
|
+
* ref OR a workspace folder mount).
|
|
41
|
+
* - `file_uploaded` — a file became available to the agent
|
|
42
|
+
* (Files API id OR workspace path).
|
|
43
|
+
* - `notification` — runtime/extension notification; catch-all
|
|
44
|
+
* for diagnostic data.
|
|
45
|
+
* - `stream_error` — stream-level error (non-fatal). Subscribers
|
|
46
|
+
* may surface this as a UI warning; the run
|
|
47
|
+
* continues unless `runtime_terminal` follows.
|
|
48
|
+
* - `runtime_terminal` — the run reached a terminal state. The
|
|
49
|
+
* adapter MUST emit exactly one of these per
|
|
50
|
+
* run; subscribers gate on it for end-of-stream.
|
|
51
|
+
*/
|
|
52
|
+
export const RUNNER_EVENT_KINDS = [
|
|
53
|
+
"runtime_started",
|
|
54
|
+
"assistant_text",
|
|
55
|
+
"tool_request",
|
|
56
|
+
"tool_response",
|
|
57
|
+
"skill_loaded",
|
|
58
|
+
"file_uploaded",
|
|
59
|
+
"notification",
|
|
60
|
+
"stream_error",
|
|
61
|
+
"runtime_terminal"
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Maximum number of events per batch. Bounds the size of the body
|
|
65
|
+
* api.antpath.ai accepts and the size of the Durable Object write.
|
|
66
|
+
* Larger streams are split into multiple batches; the runner is
|
|
67
|
+
* responsible for chunking.
|
|
68
|
+
*/
|
|
69
|
+
export const RUNNER_EVENT_BATCH_MAX_EVENTS = 256;
|
|
70
|
+
export const RUNNER_EVENT_BATCH_VALIDATION_CODES = [
|
|
71
|
+
"invalid_envelope",
|
|
72
|
+
"version_mismatch",
|
|
73
|
+
"missing_run_id",
|
|
74
|
+
"empty_batch",
|
|
75
|
+
"batch_too_large",
|
|
76
|
+
"invalid_event",
|
|
77
|
+
"seq_not_monotonic",
|
|
78
|
+
"t_ms_not_monotonic"
|
|
79
|
+
];
|
|
80
|
+
/**
|
|
81
|
+
* Parse + validate an inbound runner event batch (untrusted input).
|
|
82
|
+
* Used at the api.antpath.ai ingress so adapters never have to
|
|
83
|
+
* re-check the wire shape, and used by tests to assert the contract.
|
|
84
|
+
*
|
|
85
|
+
* Successful validation guarantees:
|
|
86
|
+
* - top-level envelope matches {@link RunnerEventBatch}
|
|
87
|
+
* - `v === RUNNER_EVENT_VERSION`
|
|
88
|
+
* - `runId` is a non-empty string
|
|
89
|
+
* - `events` is a non-empty array of at most
|
|
90
|
+
* {@link RUNNER_EVENT_BATCH_MAX_EVENTS} entries
|
|
91
|
+
* - each event is a {@link RunnerEvent} with a known `kind`
|
|
92
|
+
* - `seq` is strictly increasing across the batch
|
|
93
|
+
* - `tMs` is non-decreasing across the batch
|
|
94
|
+
*/
|
|
95
|
+
export function validateRunnerEventBatch(input) {
|
|
96
|
+
if (!isRecord(input)) {
|
|
97
|
+
return invalid("invalid_envelope", "batch must be a JSON object");
|
|
98
|
+
}
|
|
99
|
+
if (input.v !== RUNNER_EVENT_VERSION) {
|
|
100
|
+
return invalid("version_mismatch", `batch.v must equal ${RUNNER_EVENT_VERSION} (got ${JSON.stringify(input.v)})`);
|
|
101
|
+
}
|
|
102
|
+
if (typeof input.runId !== "string" || input.runId.length === 0) {
|
|
103
|
+
return invalid("missing_run_id", "batch.runId must be a non-empty string");
|
|
104
|
+
}
|
|
105
|
+
if (!Array.isArray(input.events) || input.events.length === 0) {
|
|
106
|
+
return invalid("empty_batch", "batch.events must be a non-empty array");
|
|
107
|
+
}
|
|
108
|
+
if (input.events.length > RUNNER_EVENT_BATCH_MAX_EVENTS) {
|
|
109
|
+
return invalid("batch_too_large", `batch.events has ${input.events.length} entries; max is ${RUNNER_EVENT_BATCH_MAX_EVENTS}`);
|
|
110
|
+
}
|
|
111
|
+
let lastSeq = Number.NEGATIVE_INFINITY;
|
|
112
|
+
let lastTMs = Number.NEGATIVE_INFINITY;
|
|
113
|
+
const events = [];
|
|
114
|
+
for (let i = 0; i < input.events.length; i++) {
|
|
115
|
+
const evt = input.events[i];
|
|
116
|
+
if (!isRecord(evt)) {
|
|
117
|
+
return invalid("invalid_event", `events[${i}] must be a JSON object`);
|
|
118
|
+
}
|
|
119
|
+
if (typeof evt.seq !== "number" ||
|
|
120
|
+
!Number.isFinite(evt.seq) ||
|
|
121
|
+
!Number.isInteger(evt.seq) ||
|
|
122
|
+
evt.seq < 0) {
|
|
123
|
+
return invalid("invalid_event", `events[${i}].seq must be a non-negative integer`);
|
|
124
|
+
}
|
|
125
|
+
if (typeof evt.tMs !== "number" ||
|
|
126
|
+
!Number.isFinite(evt.tMs) ||
|
|
127
|
+
!Number.isInteger(evt.tMs) ||
|
|
128
|
+
evt.tMs < 0) {
|
|
129
|
+
return invalid("invalid_event", `events[${i}].tMs must be a non-negative integer`);
|
|
130
|
+
}
|
|
131
|
+
if (typeof evt.kind !== "string" ||
|
|
132
|
+
!RUNNER_EVENT_KINDS.includes(evt.kind)) {
|
|
133
|
+
return invalid("invalid_event", `events[${i}].kind must be one of: ${RUNNER_EVENT_KINDS.join(", ")} (got ${JSON.stringify(evt.kind)})`);
|
|
134
|
+
}
|
|
135
|
+
if (!isRecord(evt.data)) {
|
|
136
|
+
return invalid("invalid_event", `events[${i}].data must be a JSON object`);
|
|
137
|
+
}
|
|
138
|
+
if (!isJsonRecord(evt.data)) {
|
|
139
|
+
return invalid("invalid_event", `events[${i}].data must be JSON-serializable`);
|
|
140
|
+
}
|
|
141
|
+
if (evt.seq <= lastSeq) {
|
|
142
|
+
return invalid("seq_not_monotonic", `events[${i}].seq=${evt.seq} must be strictly greater than the previous seq=${lastSeq}`);
|
|
143
|
+
}
|
|
144
|
+
if (evt.tMs < lastTMs) {
|
|
145
|
+
return invalid("t_ms_not_monotonic", `events[${i}].tMs=${evt.tMs} must be >= the previous tMs=${lastTMs}`);
|
|
146
|
+
}
|
|
147
|
+
lastSeq = evt.seq;
|
|
148
|
+
lastTMs = evt.tMs;
|
|
149
|
+
events.push({
|
|
150
|
+
seq: evt.seq,
|
|
151
|
+
tMs: evt.tMs,
|
|
152
|
+
kind: evt.kind,
|
|
153
|
+
data: Object.freeze({ ...evt.data })
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
ok: true,
|
|
158
|
+
batch: { v: RUNNER_EVENT_VERSION, runId: input.runId, events: Object.freeze(events) }
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function invalid(code, message) {
|
|
162
|
+
return { ok: false, code, message };
|
|
163
|
+
}
|
|
164
|
+
function isRecord(input) {
|
|
165
|
+
return typeof input === "object" && input !== null && !Array.isArray(input);
|
|
166
|
+
}
|
|
167
|
+
function isJsonRecord(input) {
|
|
168
|
+
for (const value of Object.values(input)) {
|
|
169
|
+
if (!isJsonValue(value))
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
function isJsonValue(input) {
|
|
175
|
+
if (input === null)
|
|
176
|
+
return true;
|
|
177
|
+
const t = typeof input;
|
|
178
|
+
if (t === "string" || t === "boolean")
|
|
179
|
+
return true;
|
|
180
|
+
if (t === "number")
|
|
181
|
+
return Number.isFinite(input);
|
|
182
|
+
if (Array.isArray(input))
|
|
183
|
+
return input.every(isJsonValue);
|
|
184
|
+
if (isRecord(input)) {
|
|
185
|
+
for (const v of Object.values(input)) {
|
|
186
|
+
if (!isJsonValue(v))
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=runner-event.js.map
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run runner job for the Goose Managed runtime.
|
|
3
|
+
*
|
|
4
|
+
* The Goose Managed runtime runs a Goose CLI process inside a per-run
|
|
5
|
+
* Fly Machine. This module defines the substrate-independent surface
|
|
6
|
+
* the api.antpath.ai Workflow consumes: the lifecycle statuses, the
|
|
7
|
+
* spec the dispatcher hands to an executor, and the `RunnerJobExecutor`
|
|
8
|
+
* interface every substrate implements (Fly today; tests use an
|
|
9
|
+
* in-memory fake).
|
|
10
|
+
*
|
|
11
|
+
* The Anthropic Native runtime does NOT route through this surface —
|
|
12
|
+
* Anthropic hosts the runtime. Only providers whose runtime Antpath
|
|
13
|
+
* hosts (deepseek, openai, gemini, mistral, plus the customer opt-in
|
|
14
|
+
* `runtime: "managed"` for anthropic) consume the executor.
|
|
15
|
+
*
|
|
16
|
+
* See `references/platform-rebuild-2026.md` (Wire contracts → runner-job).
|
|
17
|
+
*/
|
|
18
|
+
import type { RunProvider } from "./submission.js";
|
|
19
|
+
/**
|
|
20
|
+
* Runner-job lifecycle statuses, in the order the api.antpath.ai
|
|
21
|
+
* Workflow walks them. The shared list is the source of truth — keep
|
|
22
|
+
* the DB CHECK constraint on `provider_runtime_jobs.status` in
|
|
23
|
+
* lockstep.
|
|
24
|
+
*/
|
|
25
|
+
export declare const PROVIDER_RUNTIME_JOB_STATUSES: readonly ["queued", "provisioning", "running", "stopping", "terminated", "failed"];
|
|
26
|
+
export type ProviderRuntimeJobStatus = (typeof PROVIDER_RUNTIME_JOB_STATUSES)[number];
|
|
27
|
+
/**
|
|
28
|
+
* Substrate identifier — the executor implementation behind the job.
|
|
29
|
+
* `fly` is the only kind today; the platform-rebuild-2026 migration
|
|
30
|
+
* dropped the `railway` kind. Listed as a tuple so adding a new
|
|
31
|
+
* substrate is one line + a matching executor implementation.
|
|
32
|
+
*/
|
|
33
|
+
export declare const PROVIDER_RUNTIME_KINDS: readonly ["fly"];
|
|
34
|
+
export type ProviderRuntimeKind = (typeof PROVIDER_RUNTIME_KINDS)[number];
|
|
35
|
+
/**
|
|
36
|
+
* What the api.antpath.ai Workflow hands an executor to start a new
|
|
37
|
+
* runner job. The runner-image, env vars, region, and resource budget
|
|
38
|
+
* are decided ahead of time so the executor only has to call the
|
|
39
|
+
* substrate API.
|
|
40
|
+
*/
|
|
41
|
+
export interface RunnerJobSpec {
|
|
42
|
+
readonly runId: string;
|
|
43
|
+
readonly workspaceId: string;
|
|
44
|
+
readonly provider: RunProvider;
|
|
45
|
+
/**
|
|
46
|
+
* Container image reference (Docker registry name + sha256 digest).
|
|
47
|
+
* Pinned by the Workflow at provision time; not derived from the
|
|
48
|
+
* submission so customers cannot select an arbitrary image.
|
|
49
|
+
*/
|
|
50
|
+
readonly image: string;
|
|
51
|
+
/**
|
|
52
|
+
* Environment variables the executor must set on the container.
|
|
53
|
+
* The Workflow injects:
|
|
54
|
+
* - `ANTPATH_RUN_ID` + `ANTPATH_API_BASE` + `ANTPATH_RUNNER_TOKEN`
|
|
55
|
+
* so the runner can call back to api.antpath.ai for manifests
|
|
56
|
+
* and event POSTs.
|
|
57
|
+
* - `ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN` (or the
|
|
58
|
+
* equivalent provider proxy URL + bearer) so Goose talks to
|
|
59
|
+
* LiteLLM through the run-scoped proxy.
|
|
60
|
+
* - `ANTPATH_MCP_BASE` if the submission carries MCP servers.
|
|
61
|
+
*/
|
|
62
|
+
readonly env: Readonly<Record<string, string>>;
|
|
63
|
+
/**
|
|
64
|
+
* Hard ceiling on the substrate-side run duration. The runner image
|
|
65
|
+
* also enforces its own timeout; this is the last line of defence
|
|
66
|
+
* against a wedged container.
|
|
67
|
+
*/
|
|
68
|
+
readonly maxRunDurationMs: number;
|
|
69
|
+
/**
|
|
70
|
+
* Substrate region (e.g. `"lhr"` for Fly London). Co-located with
|
|
71
|
+
* the LiteLLM gateway so the LLM call doesn't cross a region
|
|
72
|
+
* boundary inside the trust zone.
|
|
73
|
+
*/
|
|
74
|
+
readonly region: string;
|
|
75
|
+
/**
|
|
76
|
+
* Optional resource budget. Each substrate maps these to its own
|
|
77
|
+
* machine sizing primitives (Fly: `vm.cpus` + `vm.memory_mb`).
|
|
78
|
+
* Omitting accepts the substrate default.
|
|
79
|
+
*/
|
|
80
|
+
readonly resources?: {
|
|
81
|
+
readonly cpus: number;
|
|
82
|
+
readonly memoryMb: number;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Substrate-side identifiers for a started job. The Fly executor
|
|
87
|
+
* returns `appName` + `machineId`; tests with the in-memory fake
|
|
88
|
+
* return deterministic values. The handle MUST round-trip through
|
|
89
|
+
* Postgres (`provider_runtime_jobs.fly_app_name` /
|
|
90
|
+
* `.fly_machine_id`) so a restarted Worker can poll status without
|
|
91
|
+
* needing the in-memory executor state.
|
|
92
|
+
*/
|
|
93
|
+
export interface RunnerJobHandle {
|
|
94
|
+
readonly appName: string;
|
|
95
|
+
readonly machineId: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Optional resource metrics returned by `getStatus`. Surface what the
|
|
99
|
+
* substrate publishes; absent fields are reported as `undefined`. The
|
|
100
|
+
* Workflow forwards these into the `run_events` stream under the
|
|
101
|
+
* `notification` kind so dashboards have a cheap signal that the job
|
|
102
|
+
* is alive and within budget.
|
|
103
|
+
*/
|
|
104
|
+
export interface ResourceStats {
|
|
105
|
+
readonly cpuPercent?: number;
|
|
106
|
+
readonly memoryMb?: number;
|
|
107
|
+
readonly networkRxBytes?: number;
|
|
108
|
+
readonly networkTxBytes?: number;
|
|
109
|
+
}
|
|
110
|
+
export interface RunnerJobStatusSnapshot {
|
|
111
|
+
readonly status: ProviderRuntimeJobStatus;
|
|
112
|
+
readonly terminalErrorClass?: string;
|
|
113
|
+
readonly terminalErrorMessage?: string;
|
|
114
|
+
readonly resourceStats?: ResourceStats;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The substrate-independent runner-job surface. Implementations live
|
|
118
|
+
* in `apps/api/src/runtimes/goose/runners/<kind>/` (e.g.
|
|
119
|
+
* `runners/fly/`); test fakes live alongside.
|
|
120
|
+
*
|
|
121
|
+
* Method semantics:
|
|
122
|
+
* - `start(spec)` provisions the runtime container and returns the
|
|
123
|
+
* substrate-specific ids the Workflow should persist in
|
|
124
|
+
* `provider_runtime_jobs`. MUST be idempotent under retry by
|
|
125
|
+
* `spec.runId` — duplicate calls return the same ids.
|
|
126
|
+
* - `getStatus(handle)` polls the substrate for the current status
|
|
127
|
+
* plus any new terminal error info and optional resource metrics.
|
|
128
|
+
* - `stop(handle)` initiates a graceful shutdown of the container.
|
|
129
|
+
* Used on cancel, timeout, and at provider-terminal cleanup.
|
|
130
|
+
* MUST be idempotent — operators may invoke it manually on a
|
|
131
|
+
* stuck job. `graceMs` is an upper bound on the substrate's
|
|
132
|
+
* SIGTERM → SIGKILL window.
|
|
133
|
+
* - `tailLogs(handle, lines?)` returns the most recent stdout/err
|
|
134
|
+
* bytes from the container (best-effort; substrates without log
|
|
135
|
+
* retention may return `null`). Used by the dashboard "view logs"
|
|
136
|
+
* button.
|
|
137
|
+
* - `getConsoleUrl(handle)` returns a human-clickable URL into the
|
|
138
|
+
* substrate console for on-call debugging. Optional — substrates
|
|
139
|
+
* without a console simply omit the method.
|
|
140
|
+
*/
|
|
141
|
+
export interface RunnerJobExecutor {
|
|
142
|
+
start(spec: RunnerJobSpec): Promise<RunnerJobHandle>;
|
|
143
|
+
getStatus(handle: RunnerJobHandle): Promise<RunnerJobStatusSnapshot>;
|
|
144
|
+
stop(handle: RunnerJobHandle, opts?: {
|
|
145
|
+
readonly graceMs?: number;
|
|
146
|
+
}): Promise<void>;
|
|
147
|
+
tailLogs?(handle: RunnerJobHandle, lines?: number): Promise<string | null>;
|
|
148
|
+
getConsoleUrl?(handle: RunnerJobHandle): string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Thrown when a submission selects a provider whose runtime is not
|
|
152
|
+
* yet implemented (e.g. a future provider added to RUN_PROVIDERS
|
|
153
|
+
* before its executor lands). Surfaced uniformly so the dashboard
|
|
154
|
+
* and the SDK render the same error code.
|
|
155
|
+
*/
|
|
156
|
+
export declare class RunnerRuntimeNotImplementedError extends Error {
|
|
157
|
+
readonly provider: RunProvider;
|
|
158
|
+
constructor(provider: RunProvider);
|
|
159
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run runner job for the Goose Managed runtime.
|
|
3
|
+
*
|
|
4
|
+
* The Goose Managed runtime runs a Goose CLI process inside a per-run
|
|
5
|
+
* Fly Machine. This module defines the substrate-independent surface
|
|
6
|
+
* the api.antpath.ai Workflow consumes: the lifecycle statuses, the
|
|
7
|
+
* spec the dispatcher hands to an executor, and the `RunnerJobExecutor`
|
|
8
|
+
* interface every substrate implements (Fly today; tests use an
|
|
9
|
+
* in-memory fake).
|
|
10
|
+
*
|
|
11
|
+
* The Anthropic Native runtime does NOT route through this surface —
|
|
12
|
+
* Anthropic hosts the runtime. Only providers whose runtime Antpath
|
|
13
|
+
* hosts (deepseek, openai, gemini, mistral, plus the customer opt-in
|
|
14
|
+
* `runtime: "managed"` for anthropic) consume the executor.
|
|
15
|
+
*
|
|
16
|
+
* See `references/platform-rebuild-2026.md` (Wire contracts → runner-job).
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Runner-job lifecycle statuses, in the order the api.antpath.ai
|
|
20
|
+
* Workflow walks them. The shared list is the source of truth — keep
|
|
21
|
+
* the DB CHECK constraint on `provider_runtime_jobs.status` in
|
|
22
|
+
* lockstep.
|
|
23
|
+
*/
|
|
24
|
+
export const PROVIDER_RUNTIME_JOB_STATUSES = [
|
|
25
|
+
"queued",
|
|
26
|
+
"provisioning",
|
|
27
|
+
"running",
|
|
28
|
+
"stopping",
|
|
29
|
+
"terminated",
|
|
30
|
+
"failed"
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Substrate identifier — the executor implementation behind the job.
|
|
34
|
+
* `fly` is the only kind today; the platform-rebuild-2026 migration
|
|
35
|
+
* dropped the `railway` kind. Listed as a tuple so adding a new
|
|
36
|
+
* substrate is one line + a matching executor implementation.
|
|
37
|
+
*/
|
|
38
|
+
export const PROVIDER_RUNTIME_KINDS = ["fly"];
|
|
39
|
+
/**
|
|
40
|
+
* Thrown when a submission selects a provider whose runtime is not
|
|
41
|
+
* yet implemented (e.g. a future provider added to RUN_PROVIDERS
|
|
42
|
+
* before its executor lands). Surfaced uniformly so the dashboard
|
|
43
|
+
* and the SDK render the same error code.
|
|
44
|
+
*/
|
|
45
|
+
export class RunnerRuntimeNotImplementedError extends Error {
|
|
46
|
+
provider;
|
|
47
|
+
constructor(provider) {
|
|
48
|
+
super(`runner runtime for provider "${provider}" is not implemented yet — ` +
|
|
49
|
+
`see references/platform-rebuild-2026.md (implementation phases)`);
|
|
50
|
+
this.name = "RunnerRuntimeNotImplementedError";
|
|
51
|
+
this.provider = provider;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=runner-job.js.map
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime manifest: the per-run, per-provider description of where
|
|
3
|
+
* antpath places things inside the agent container, plus the merged
|
|
4
|
+
* env-var bag delivered via `RUNTIME.env` / `RUNTIME.json`.
|
|
5
|
+
*
|
|
6
|
+
* Two consumers, one source of truth:
|
|
7
|
+
*
|
|
8
|
+
* 1. The dashboard BFF computes a manifest at submitRun-response
|
|
9
|
+
* time (from the validated submission + the chosen provider)
|
|
10
|
+
* and echoes it on the wire as `Run.runtimeManifest`. The SDK
|
|
11
|
+
* exposes it as `RunRef.runtimeManifest` so caller code (broll's
|
|
12
|
+
* dispatcher, anyone rendering catalog markdown pre-submission)
|
|
13
|
+
* can substitute path strings without guessing.
|
|
14
|
+
*
|
|
15
|
+
* 2. The worker uses the same builder + the same `renderRuntimeEnv`
|
|
16
|
+
* / `renderRuntimeJson` helpers to materialise the two RUNTIME
|
|
17
|
+
* files mounted into every session, so the in-container view
|
|
18
|
+
* and the SDK-side view are byte-for-byte the same set of
|
|
19
|
+
* keys/values.
|
|
20
|
+
*
|
|
21
|
+
* Manifest values are derived: the BFF and worker both compute them
|
|
22
|
+
* from the same input (provider + customer envVars). Nothing is
|
|
23
|
+
* persisted separately — the source of truth for the customer half
|
|
24
|
+
* remains `submission.environment.envVars` on the run row; the antpath
|
|
25
|
+
* half is constant for a given provider+SDK-version pair.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Set of providers whose runtime contract antpath models. Today only
|
|
29
|
+
* `"anthropic"` ships; the field is on the manifest so forward-compat
|
|
30
|
+
* consumers can branch on it without us having to silently change
|
|
31
|
+
* what `runtimeManifest` means when we add a second provider.
|
|
32
|
+
*/
|
|
33
|
+
export type RuntimeProvider = "anthropic";
|
|
34
|
+
/**
|
|
35
|
+
* The in-container paths the agent and skill code reference at
|
|
36
|
+
* runtime. All fields are absolute, all reflect Anthropic Managed
|
|
37
|
+
* Agents' session-mount rebase rule (every `mount_path` lands under
|
|
38
|
+
* `/mnt/session/uploads/` regardless of the leading slash) — see
|
|
39
|
+
* `references/architecture-decisions.md`.
|
|
40
|
+
*
|
|
41
|
+
* `skillsRoot` is the location of Skills API-registered bundles, which
|
|
42
|
+
* the runtime auto-discovers under `/workspace/skills/<name>/` —
|
|
43
|
+
* empirically a separate root from the session-resource mounts, NOT
|
|
44
|
+
* under `/mnt/session/uploads/`.
|
|
45
|
+
*/
|
|
46
|
+
export interface RuntimeManifest {
|
|
47
|
+
readonly provider: RuntimeProvider;
|
|
48
|
+
/** Where Skills-API-registered bundles auto-discover (Anthropic). */
|
|
49
|
+
readonly skillsRoot: string;
|
|
50
|
+
/** Parent dir of File mounts: `<filesRoot>/<f_id>/<rel-path>`. */
|
|
51
|
+
readonly filesRoot: string;
|
|
52
|
+
/** Parent dir of non-SKILL.md asset mounts: `<assetsRoot>/<skl_id>/<rel-path>`. */
|
|
53
|
+
readonly assetsRoot: string;
|
|
54
|
+
/** Absolute path the agent writes output files into for capture. */
|
|
55
|
+
readonly outputsRoot: string;
|
|
56
|
+
/** Absolute path of the in-container antpath CLI (invoke via `node`). */
|
|
57
|
+
readonly antpathCli: string;
|
|
58
|
+
/** Absolute path of the per-run proxy-endpoints manifest. */
|
|
59
|
+
readonly indexJson: string;
|
|
60
|
+
/** Absolute path of the always-mounted antpath runtime contract README. */
|
|
61
|
+
readonly readme: string;
|
|
62
|
+
/** Absolute path of the machine-readable manifest mirror. */
|
|
63
|
+
readonly runtimeJson: string;
|
|
64
|
+
/** Absolute path of the POSIX-shell-sourceable runtime env file. */
|
|
65
|
+
readonly runtimeEnv: string;
|
|
66
|
+
/**
|
|
67
|
+
* Merged env-var bag: antpath-set runtime keys (with reserved
|
|
68
|
+
* `ANTPATH_` prefix) plus customer-supplied `environment.envVars`.
|
|
69
|
+
* Both `RUNTIME.env` and `RUNTIME.json` are rendered from this
|
|
70
|
+
* exact map; `__KEY__` substitution in agent-facing markdown
|
|
71
|
+
* resolves against this exact map.
|
|
72
|
+
*/
|
|
73
|
+
readonly envVars: Readonly<Record<string, string>>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Anthropic Managed Agents container paths. Kept here so the BFF and
|
|
77
|
+
* the worker render identical values; the worker's `proxy-bootstrap`
|
|
78
|
+
* constants are validated against these by a regression test
|
|
79
|
+
* (`packages/shared/test/runtime-manifest.test.ts`).
|
|
80
|
+
*
|
|
81
|
+
* Path facts (each verified at least once by a live session, locked
|
|
82
|
+
* in `references/architecture-decisions.md`):
|
|
83
|
+
* - Session resources mount under `/mnt/session/uploads/` (rebase).
|
|
84
|
+
* - Skills API places bundles under `/workspace/skills/<name>/`
|
|
85
|
+
* — a SEPARATE root from session-resource mounts.
|
|
86
|
+
* - Files API mounts file_ids at the requested mount_path, also
|
|
87
|
+
* rebased — antpath threads them under `<filesRoot>/<f_id>/<rel>`.
|
|
88
|
+
* - Only `/mnt/session/outputs` files are auto-registered with the
|
|
89
|
+
* Files API for terminal-time capture.
|
|
90
|
+
*/
|
|
91
|
+
declare const ANTHROPIC_PATHS: Readonly<{
|
|
92
|
+
readonly skillsRoot: "/workspace/skills";
|
|
93
|
+
readonly filesRoot: "/mnt/session/uploads/antpath/files";
|
|
94
|
+
readonly assetsRoot: "/mnt/session/uploads/antpath/assets";
|
|
95
|
+
readonly outputsRoot: "/mnt/session/outputs";
|
|
96
|
+
readonly antpathCli: "/mnt/session/uploads/antpath/antpath";
|
|
97
|
+
readonly indexJson: "/mnt/session/uploads/antpath/index.json";
|
|
98
|
+
readonly readme: "/mnt/session/uploads/antpath/SKILLS.md";
|
|
99
|
+
readonly runtimeJson: "/mnt/session/uploads/antpath/RUNTIME.json";
|
|
100
|
+
readonly runtimeEnv: "/mnt/session/uploads/antpath/RUNTIME.env";
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Container paths exposed for a given provider. Today only
|
|
104
|
+
* `"anthropic"` is recognised; calling with anything else throws so
|
|
105
|
+
* forward-compat surfaces the missing provider entry instead of
|
|
106
|
+
* silently emitting Anthropic paths.
|
|
107
|
+
*/
|
|
108
|
+
export declare function runtimePathsFor(provider: RuntimeProvider): typeof ANTHROPIC_PATHS;
|
|
109
|
+
export interface BuildRuntimeManifestInput {
|
|
110
|
+
readonly provider: RuntimeProvider;
|
|
111
|
+
/**
|
|
112
|
+
* Customer-supplied `environment.envVars` from the validated
|
|
113
|
+
* submission. Keys with the reserved `ANTPATH_` prefix are
|
|
114
|
+
* filtered out defensively — the strict submission parser already
|
|
115
|
+
* rejects them, but defence-in-depth means a malformed snapshot
|
|
116
|
+
* (or a future bypass) can't poison the manifest.
|
|
117
|
+
*/
|
|
118
|
+
readonly customerEnvVars?: Readonly<Record<string, string>> | undefined;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Build the runtime manifest for a single submission. Pure function:
|
|
122
|
+
* same input → same output → safe to call from the BFF response path
|
|
123
|
+
* and from the worker bootstrap path with identical results.
|
|
124
|
+
*/
|
|
125
|
+
export declare function buildRuntimeManifest(input: BuildRuntimeManifestInput): RuntimeManifest;
|
|
126
|
+
/**
|
|
127
|
+
* Render the RUNTIME.env file mounted into every session. POSIX-shell
|
|
128
|
+
* sourceable (`source /mnt/session/uploads/antpath/RUNTIME.env`).
|
|
129
|
+
* Values are double-quoted with `"`, `\`, `$`, and backtick escaped
|
|
130
|
+
* so any UTF-8 string survives a `source` invocation. Lines are LF
|
|
131
|
+
* (Unix), no trailing CR — the container is Linux regardless of
|
|
132
|
+
* caller platform.
|
|
133
|
+
*
|
|
134
|
+
* Output order: antpath keys first (in stable order from
|
|
135
|
+
* `buildRuntimeManifest`), then customer keys in insertion order.
|
|
136
|
+
* The same ordering is preserved in RUNTIME.json.
|
|
137
|
+
*/
|
|
138
|
+
export declare function renderRuntimeEnv(manifest: RuntimeManifest): string;
|
|
139
|
+
/**
|
|
140
|
+
* Render the RUNTIME.json file mounted into every session. Stable
|
|
141
|
+
* canonical JSON (2-space indent, key order matches the manifest)
|
|
142
|
+
* so the file is reviewable as a tracked artifact when captured into
|
|
143
|
+
* a run's output archive.
|
|
144
|
+
*/
|
|
145
|
+
export declare function renderRuntimeJson(manifest: RuntimeManifest): string;
|
|
146
|
+
/**
|
|
147
|
+
* Pattern matched by `substituteRuntimePlaceholders`. A placeholder is
|
|
148
|
+
* `__KEY__` where `KEY` matches POSIX shell key rules (uppercase, digits,
|
|
149
|
+
* underscores, starting with a letter or underscore). The literal form
|
|
150
|
+
* is deliberately conservative — no `{{ }}` templating, no expressions,
|
|
151
|
+
* no escape syntax. If a customer needs the literal string `__KEY__` in
|
|
152
|
+
* agent-facing markdown, they avoid the matching key in their envVars
|
|
153
|
+
* map.
|
|
154
|
+
*/
|
|
155
|
+
export declare const RUNTIME_PLACEHOLDER_PATTERN: RegExp;
|
|
156
|
+
/**
|
|
157
|
+
* Substitute `__KEY__` placeholders in agent-facing markdown against
|
|
158
|
+
* the manifest's envVars map. Fail-fast on unknown keys: the function
|
|
159
|
+
* throws `RuntimePlaceholderError` naming the offending key + filePath
|
|
160
|
+
* so the worker can surface a lint-style failure at materialization
|
|
161
|
+
* time, before the agent ever sees the file.
|
|
162
|
+
*
|
|
163
|
+
* Pure function; safe to call from the BFF, the worker materializer,
|
|
164
|
+
* or tests. The two callers in production are:
|
|
165
|
+
*
|
|
166
|
+
* - Worker materialization: rewrite SKILL.md / AGENTS.md / .md
|
|
167
|
+
* entries inside skill, file, and AgentsMd bundles before they
|
|
168
|
+
* mount or upload.
|
|
169
|
+
* - SDK / customer code: customers can apply the same helper in
|
|
170
|
+
* their dispatcher when they want to render templates locally
|
|
171
|
+
* before uploading. The merged envVars map is `runtimeManifest.envVars`.
|
|
172
|
+
*
|
|
173
|
+
* @param content The text to rewrite.
|
|
174
|
+
* @param envVars Map of allowed placeholder keys → values. Typically
|
|
175
|
+
* `runtimeManifest.envVars` from `buildRuntimeManifest`.
|
|
176
|
+
* @param filePath Optional path of the source file, included in the
|
|
177
|
+
* error message when a placeholder is unresolved.
|
|
178
|
+
* Helps the customer locate the offending line.
|
|
179
|
+
*/
|
|
180
|
+
export declare function substituteRuntimePlaceholders(content: string, envVars: Readonly<Record<string, string>>, filePath?: string): string;
|
|
181
|
+
/**
|
|
182
|
+
* Thrown by `substituteRuntimePlaceholders` when a `__KEY__` token in
|
|
183
|
+
* agent-facing markdown does not resolve against the merged env-var
|
|
184
|
+
* map. Surfaced at run materialization, before the run reaches the
|
|
185
|
+
* agent — the customer fixes the typo at the SDK call site, no
|
|
186
|
+
* tokens are spent on a misrouted run.
|
|
187
|
+
*/
|
|
188
|
+
export declare class RuntimePlaceholderError extends Error {
|
|
189
|
+
constructor(message: string);
|
|
190
|
+
}
|
|
191
|
+
export {};
|