antpath 0.10.14 → 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.
- 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 +7 -1
- package/dist/_shared/index.js +6 -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 +55 -8
- package/dist/_shared/operations.js +163 -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/sse.d.ts +74 -0
- package/dist/_shared/sse.js +0 -0
- package/dist/_shared/stable.d.ts +15 -10
- package/dist/_shared/stable.js +15 -10
- package/dist/_shared/submission.d.ts +199 -73
- package/dist/_shared/submission.js +409 -210
- 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 +559 -105
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +53 -22
- package/dist/client.js +196 -130
- 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 +2 -1
- 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,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;
|
|
@@ -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
|