harness-dispatch 0.5.0 → 0.6.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/CHANGELOG.md +152 -0
- package/README.md +5 -2
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +1 -175
- package/dist/bin.js.map +1 -1
- package/dist/config/route-fields.d.ts +72 -0
- package/dist/config/route-fields.d.ts.map +1 -0
- package/dist/config/route-fields.js +128 -0
- package/dist/config/route-fields.js.map +1 -0
- package/dist/config/validation.js +1 -1
- package/dist/config/validation.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +32 -171
- package/dist/config.js.map +1 -1
- package/dist/configure-yaml.d.ts +23 -0
- package/dist/configure-yaml.d.ts.map +1 -0
- package/dist/configure-yaml.js +193 -0
- package/dist/configure-yaml.js.map +1 -0
- package/dist/dispatchers/base.d.ts +3 -0
- package/dist/dispatchers/base.d.ts.map +1 -1
- package/dist/dispatchers/base.js.map +1 -1
- package/dist/dispatchers/generic-cli.d.ts.map +1 -1
- package/dist/dispatchers/generic-cli.js +4 -0
- package/dist/dispatchers/generic-cli.js.map +1 -1
- package/dist/dispatchers/openai-compatible.d.ts.map +1 -1
- package/dist/dispatchers/openai-compatible.js +18 -0
- package/dist/dispatchers/openai-compatible.js.map +1 -1
- package/dist/dispatchers/shared/stream-subprocess.d.ts +11 -0
- package/dist/dispatchers/shared/stream-subprocess.d.ts.map +1 -1
- package/dist/dispatchers/shared/stream-subprocess.js +57 -35
- package/dist/dispatchers/shared/stream-subprocess.js.map +1 -1
- package/dist/http/parse.d.ts +64 -0
- package/dist/http/parse.d.ts.map +1 -0
- package/dist/http/parse.js +230 -0
- package/dist/http/parse.js.map +1 -0
- package/dist/http/server.d.ts +2 -11
- package/dist/http/server.d.ts.map +1 -1
- package/dist/http/server.js +26 -232
- package/dist/http/server.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/jobs/context.d.ts +17 -0
- package/dist/jobs/context.d.ts.map +1 -0
- package/dist/jobs/context.js +84 -0
- package/dist/jobs/context.js.map +1 -0
- package/dist/jobs/store.d.ts +80 -0
- package/dist/jobs/store.d.ts.map +1 -0
- package/dist/jobs/store.js +279 -0
- package/dist/jobs/store.js.map +1 -0
- package/dist/jobs/types.d.ts +135 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +11 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/jobs.d.ts +113 -123
- package/dist/jobs.d.ts.map +1 -1
- package/dist/jobs.js +314 -309
- package/dist/jobs.js.map +1 -1
- package/dist/mcp/tool-schemas.d.ts +194 -0
- package/dist/mcp/tool-schemas.d.ts.map +1 -0
- package/dist/mcp/tool-schemas.js +311 -0
- package/dist/mcp/tool-schemas.js.map +1 -0
- package/dist/mcp/tools.d.ts +15 -59
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +63 -239
- package/dist/mcp/tools.js.map +1 -1
- package/dist/quota.d.ts +19 -1
- package/dist/quota.d.ts.map +1 -1
- package/dist/quota.js +39 -4
- package/dist/quota.js.map +1 -1
- package/dist/router.d.ts +4 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +8 -0
- package/dist/router.js.map +1 -1
- package/dist/status.d.ts +13 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +6 -0
- package/dist/status.js.map +1 -1
- package/dist/types.d.ts +24 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workspace-resolve.d.ts +98 -0
- package/dist/workspace-resolve.d.ts.map +1 -0
- package/dist/workspace-resolve.js +382 -0
- package/dist/workspace-resolve.js.map +1 -0
- package/dist/workspaces.d.ts +1 -0
- package/dist/workspaces.d.ts.map +1 -1
- package/dist/workspaces.js +67 -15
- package/dist/workspaces.js.map +1 -1
- package/package.json +5 -4
- package/dist/dashboard/live.d.ts +0 -49
- package/dist/dashboard/live.d.ts.map +0 -1
- package/dist/dashboard/live.js +0 -149
- package/dist/dashboard/live.js.map +0 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The job store: where a job lives on disk and how it is written.
|
|
3
|
+
*
|
|
4
|
+
* Split out of jobs.ts. These are the primitives every other part of the job
|
|
5
|
+
* system sits on — path resolution, atomic writes, status reads, retention —
|
|
6
|
+
* and they depend on nothing above them, so they lift out cleanly and can be
|
|
7
|
+
* reasoned about (and tested) without starting a dispatch.
|
|
8
|
+
*
|
|
9
|
+
* The atomicity here is load-bearing rather than incidental: a status file
|
|
10
|
+
* half-written when a reader arrives is indistinguishable from a crashed
|
|
11
|
+
* runner, which is why every write goes through tmp+rename with a retry for
|
|
12
|
+
* Windows EPERM.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { chmod, copyFile, mkdir, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
16
|
+
import { randomUUID } from "node:crypto";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
19
|
+
import { stateRoot } from "../state-dir.js";
|
|
20
|
+
/**
|
|
21
|
+
* Dispatcher error strings are unbounded (a corrupted downstream config once
|
|
22
|
+
* produced a 173KB parse error). Full text always lands in stderr.log; the
|
|
23
|
+
* JSON surfaces returned over MCP carry a bounded copy.
|
|
24
|
+
*/
|
|
25
|
+
const MAX_JSON_ERROR_CHARS = 4000;
|
|
26
|
+
/** Suggested delay before an agent checks `job_status` again. */
|
|
27
|
+
export const SUGGESTED_POLL_SECONDS = 300;
|
|
28
|
+
/**
|
|
29
|
+
* A "running" status whose updatedAt is older than this is a lie — the
|
|
30
|
+
* process that owned the run is gone (several missed heartbeats), so
|
|
31
|
+
* readers report the job as orphaned instead of keeping callers polling a
|
|
32
|
+
* corpse forever. Generous multiple of the heartbeat so an event-loop
|
|
33
|
+
* stall can't produce false orphans.
|
|
34
|
+
*/
|
|
35
|
+
export const ORPHAN_THRESHOLD_MS = 90_000;
|
|
36
|
+
/**
|
|
37
|
+
* Compute-on-read orphan detection. Never writes the verdict back — the
|
|
38
|
+
* status file stays whatever the (dead) owner last wrote, so a future
|
|
39
|
+
* attach/recovery feature keeps its evidence intact.
|
|
40
|
+
*/
|
|
41
|
+
export function withOrphanCheck(status) {
|
|
42
|
+
// Waiting for a concurrency slot is not death: nothing is heartbeating for
|
|
43
|
+
// it by design, so the staleness rule below would misreport every job that
|
|
44
|
+
// waits longer than 90s. drainSlotQueue() is what moves it forward.
|
|
45
|
+
if (status.slotQueued)
|
|
46
|
+
return status;
|
|
47
|
+
if (status.status !== "running" && status.status !== "queued")
|
|
48
|
+
return status;
|
|
49
|
+
const beat = Date.parse(status.updatedAt);
|
|
50
|
+
if (Number.isFinite(beat) && Date.now() - beat <= ORPHAN_THRESHOLD_MS)
|
|
51
|
+
return status;
|
|
52
|
+
return {
|
|
53
|
+
...status,
|
|
54
|
+
status: "orphaned",
|
|
55
|
+
success: false,
|
|
56
|
+
error: "The dispatch server that started this job exited before the run finished — " +
|
|
57
|
+
"the background run died with it. Re-dispatch the task; this job will never complete.",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function boundedError(error) {
|
|
61
|
+
if (error === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
if (error.length <= MAX_JSON_ERROR_CHARS)
|
|
64
|
+
return error;
|
|
65
|
+
return (error.slice(0, MAX_JSON_ERROR_CHARS) +
|
|
66
|
+
` … [truncated ${error.length - MAX_JSON_ERROR_CHARS} chars — full text in output/stderr.log]`);
|
|
67
|
+
}
|
|
68
|
+
export function pollInstructions(jobId) {
|
|
69
|
+
return (`Job runs in the background; CLI harnesses typically take 3-15 minutes. ` +
|
|
70
|
+
`Wait ~${Math.round(SUGGESTED_POLL_SECONDS / 60)} minutes (e.g. sleep), then call ` +
|
|
71
|
+
`job_status with jobId=${jobId}. While status is "running", partialOutput shows ` +
|
|
72
|
+
`progress; check again until status is "completed" or "failed". Results persist ` +
|
|
73
|
+
`on disk, so checking late loses nothing.`);
|
|
74
|
+
}
|
|
75
|
+
export function jobsRoot() {
|
|
76
|
+
return process.env.HARNESS_DISPATCH_JOBS_DIR ?? path.join(stateRoot(), "jobs");
|
|
77
|
+
}
|
|
78
|
+
const DEFAULT_JOB_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
79
|
+
let configuredJobMaxAgeMs;
|
|
80
|
+
/**
|
|
81
|
+
* Config-driven retention (`retention: { jobs_days: N }` in config.yaml) —
|
|
82
|
+
* set at runtime bootstrap and on every hot reload. Precedence:
|
|
83
|
+
* HARNESS_DISPATCH_JOB_MAX_AGE_MS env > config > 7-day default.
|
|
84
|
+
*/
|
|
85
|
+
export function setJobRetentionDays(days) {
|
|
86
|
+
configuredJobMaxAgeMs =
|
|
87
|
+
days !== undefined && Number.isFinite(days) && days >= 0
|
|
88
|
+
? days * 24 * 60 * 60 * 1000
|
|
89
|
+
: undefined;
|
|
90
|
+
}
|
|
91
|
+
export function jobMaxAgeMs() {
|
|
92
|
+
const raw = process.env.HARNESS_DISPATCH_JOB_MAX_AGE_MS;
|
|
93
|
+
const parsed = raw ? Number(raw) : NaN;
|
|
94
|
+
if (Number.isFinite(parsed) && parsed >= 0)
|
|
95
|
+
return parsed;
|
|
96
|
+
return configuredJobMaxAgeMs ?? DEFAULT_JOB_MAX_AGE_MS;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Nothing ever pruned old job directories — status.json/result.json/output
|
|
100
|
+
* logs and every snapshotted context file accumulated under jobsRoot()
|
|
101
|
+
* forever. Prune anything with no activity for the retention window
|
|
102
|
+
* (default 7 days, override via HARNESS_DISPATCH_JOB_MAX_AGE_MS) each time a
|
|
103
|
+
* new job is about to start. Job directory mtime is a reasonable proxy for
|
|
104
|
+
* "last activity": writeJson's tmp-then-rename touches the job dir on every
|
|
105
|
+
* status update, so a running (or freshly completed but unpolled) job keeps
|
|
106
|
+
* bumping it — only genuinely abandoned jobs go stale. Best effort: a prune
|
|
107
|
+
* failure must never block starting the job that was actually requested.
|
|
108
|
+
*/
|
|
109
|
+
export async function pruneStaleJobs() {
|
|
110
|
+
const maxAgeMs = jobMaxAgeMs();
|
|
111
|
+
// 0 means KEEP FOREVER, not "prune immediately". The same config file
|
|
112
|
+
// establishes `max_concurrent_runs: 0` as "disable the bound", inviting the
|
|
113
|
+
// same reading here — and the old behaviour deleted RUNNING jobs out from
|
|
114
|
+
// under their runners (a job dir's mtime only moves on a 15s heartbeat, so
|
|
115
|
+
// at age 0 every beat gap was fatal): the runner's next write failed and
|
|
116
|
+
// the caller's jobId turned into "No such job".
|
|
117
|
+
if (maxAgeMs === 0)
|
|
118
|
+
return;
|
|
119
|
+
const root = jobsRoot();
|
|
120
|
+
let entries;
|
|
121
|
+
try {
|
|
122
|
+
entries = await readdir(root, { withFileTypes: true });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
for (const entry of entries) {
|
|
129
|
+
if (!entry.isDirectory())
|
|
130
|
+
continue;
|
|
131
|
+
const jobDir = path.join(root, entry.name);
|
|
132
|
+
try {
|
|
133
|
+
const info = await stat(jobDir);
|
|
134
|
+
if (now - info.mtimeMs <= maxAgeMs)
|
|
135
|
+
continue;
|
|
136
|
+
// mtime is a proxy for activity; never delete a job that is
|
|
137
|
+
// demonstrably in flight. A live runner heartbeats status.json inside
|
|
138
|
+
// the orphan window, so running/queued with a fresh beat means "working
|
|
139
|
+
// right now", whatever retention says. An unreadable status file falls
|
|
140
|
+
// through to the mtime rule — that is the abandoned case.
|
|
141
|
+
try {
|
|
142
|
+
const status = JSON.parse(await readFile(path.join(jobDir, "status.json"), "utf8"));
|
|
143
|
+
const beat = Date.parse(status.updatedAt ?? "");
|
|
144
|
+
if ((status.status === "running" || status.status === "queued") &&
|
|
145
|
+
Number.isFinite(beat) &&
|
|
146
|
+
now - beat <= ORPHAN_THRESHOLD_MS) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Fall through to the mtime rule.
|
|
152
|
+
}
|
|
153
|
+
await rm(jobDir, { recursive: true, force: true });
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// best effort — a locked/already-gone/permission-denied entry is skipped
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export function timestamp() {
|
|
161
|
+
return new Date().toISOString();
|
|
162
|
+
}
|
|
163
|
+
export function safeBaseName(filePath) {
|
|
164
|
+
return path.basename(filePath).replace(/[^A-Za-z0-9_.-]/g, "_");
|
|
165
|
+
}
|
|
166
|
+
export async function writeJson(filePath, value) {
|
|
167
|
+
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.${randomUUID().slice(0, 8)}.tmp`;
|
|
168
|
+
await writeFile(tmpPath, `${JSON.stringify(value, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
169
|
+
await renameWithRetry(tmpPath, filePath);
|
|
170
|
+
}
|
|
171
|
+
async function renameWithRetry(tmpPath, filePath) {
|
|
172
|
+
for (let attempt = 0; attempt < 8; attempt += 1) {
|
|
173
|
+
try {
|
|
174
|
+
await rename(tmpPath, filePath);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
const code = typeof err === "object" && err !== null ? err.code : undefined;
|
|
179
|
+
if (code !== "EPERM" && code !== "EACCES" && code !== "EBUSY")
|
|
180
|
+
throw err;
|
|
181
|
+
await delay(25 * (attempt + 1));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
await rename(tmpPath, filePath);
|
|
185
|
+
}
|
|
186
|
+
export async function readJson(filePath) {
|
|
187
|
+
return JSON.parse(await readFile(filePath, "utf8"));
|
|
188
|
+
}
|
|
189
|
+
export async function updateStatus(jobDir, status) {
|
|
190
|
+
await writeJson(path.join(jobDir, "status.json"), {
|
|
191
|
+
...status,
|
|
192
|
+
updatedAt: timestamp(),
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
export async function snapshotFiles(jobDir, files) {
|
|
196
|
+
const out = [];
|
|
197
|
+
const filesDir = path.join(jobDir, "context", "files");
|
|
198
|
+
await mkdir(filesDir, { recursive: true, mode: 0o700 });
|
|
199
|
+
for (const [index, originalPath] of files.entries()) {
|
|
200
|
+
const item = { originalPath };
|
|
201
|
+
try {
|
|
202
|
+
const fileStat = await stat(originalPath);
|
|
203
|
+
if (!fileStat.isFile()) {
|
|
204
|
+
item.error = "not a regular file";
|
|
205
|
+
out.push(item);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const snapshotName = `${String(index + 1).padStart(3, "0")}-${safeBaseName(originalPath)}`;
|
|
209
|
+
const snapshotPath = path.join(filesDir, snapshotName);
|
|
210
|
+
await copyFile(originalPath, snapshotPath);
|
|
211
|
+
await chmod(snapshotPath, 0o600);
|
|
212
|
+
item.snapshotPath = snapshotPath;
|
|
213
|
+
item.sizeBytes = fileStat.size;
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
item.error = err instanceof Error ? err.message : String(err);
|
|
217
|
+
}
|
|
218
|
+
out.push(item);
|
|
219
|
+
}
|
|
220
|
+
await writeJson(path.join(jobDir, "context", "files.json"), out);
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The only jobId shape this module ever produces. Kept adjacent to
|
|
225
|
+
* `assertValidJobId` so the two cannot drift.
|
|
226
|
+
*/
|
|
227
|
+
export function newJobId() {
|
|
228
|
+
return `job-${Date.now()}-${randomUUID().slice(0, 8)}`;
|
|
229
|
+
}
|
|
230
|
+
export const JOB_ID_RE = /^job-\d+-[0-9a-f]{8}$/;
|
|
231
|
+
/**
|
|
232
|
+
* Reject anything that isn't a jobId we generated, BEFORE it reaches
|
|
233
|
+
* path.join.
|
|
234
|
+
*
|
|
235
|
+
* The MCP schema validates this too, but the check belongs here as well:
|
|
236
|
+
* path.join(jobsRoot(), "../../etc/hosts") escapes the jobs root, and this
|
|
237
|
+
* function is reachable from more than one caller. Validating only at the
|
|
238
|
+
* schema would mean any future caller silently reintroduces the traversal.
|
|
239
|
+
*/
|
|
240
|
+
export function assertValidJobId(jobId) {
|
|
241
|
+
if (!JOB_ID_RE.test(jobId)) {
|
|
242
|
+
throw new Error(`Invalid jobId ${JSON.stringify(jobId)} — expected job-<timestamp>-<8 hex chars>.`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Cancellation is COOPERATIVE, by a marker file rather than a signal.
|
|
247
|
+
*
|
|
248
|
+
* Killing a pid is not available here: jobs run inside pooled supervisors
|
|
249
|
+
* (SUPERVISOR_POOL_SIZE), and one supervisor runs several jobs at once, so
|
|
250
|
+
* the only pid recorded against a job belongs to a process that is also
|
|
251
|
+
* running other people's work. Signalling it would cancel jobs nobody asked
|
|
252
|
+
* to cancel.
|
|
253
|
+
*
|
|
254
|
+
* So the canceller writes a marker and the RUN tears itself down: it drops
|
|
255
|
+
* out of its event stream, which triggers the dispatcher's own teardown
|
|
256
|
+
* (killTree on the agent CLI and its children) and releases the workspace
|
|
257
|
+
* lock through the same path a normal finish uses. The cost is that
|
|
258
|
+
* cancellation is not instant — it lands within one poll interval.
|
|
259
|
+
*/
|
|
260
|
+
const CANCEL_MARKER = "cancel.json";
|
|
261
|
+
export async function requestCancel(jobDir, reason) {
|
|
262
|
+
await writeFile(path.join(jobDir, CANCEL_MARKER), JSON.stringify({ at: timestamp(), ...(reason !== undefined ? { reason } : {}) }), { encoding: "utf8", mode: 0o600 });
|
|
263
|
+
}
|
|
264
|
+
/** True once a cancel has been requested for this job. Cheap enough to poll. */
|
|
265
|
+
export function cancelRequested(jobDir) {
|
|
266
|
+
return existsSync(path.join(jobDir, CANCEL_MARKER));
|
|
267
|
+
}
|
|
268
|
+
/** The reason recorded with a cancel request, if one was given. */
|
|
269
|
+
export async function cancelReason(jobDir) {
|
|
270
|
+
try {
|
|
271
|
+
const raw = await readFile(path.join(jobDir, CANCEL_MARKER), "utf8");
|
|
272
|
+
const parsed = JSON.parse(raw);
|
|
273
|
+
return typeof parsed.reason === "string" ? parsed.reason : undefined;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/jobs/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shapes a job is written and read as.
|
|
3
|
+
*
|
|
4
|
+
* Split out of jobs.ts so the store, the supervisor and the dispatch path can
|
|
5
|
+
* share them without importing each other. These types are the actual
|
|
6
|
+
* contract between processes — a detached runner rebuilds its whole input
|
|
7
|
+
* from JobManifest, and every reader of a job's state goes through JobStatus
|
|
8
|
+
* — so they are the one part of the job system that must stay stable.
|
|
9
|
+
*/
|
|
10
|
+
import type { DispatchResult, DispatcherEvent, RouteHints, RoutingDecision, WorkspacePolicy } from "../types.js";
|
|
11
|
+
import type { RuntimeHolder } from "../mcp/config-hot-reload.js";
|
|
12
|
+
export interface JobDeps {
|
|
13
|
+
holder: RuntimeHolder;
|
|
14
|
+
}
|
|
15
|
+
export interface StartJobInput {
|
|
16
|
+
prompt: string;
|
|
17
|
+
/**
|
|
18
|
+
* Earlier jobs whose results this one should be able to see.
|
|
19
|
+
*
|
|
20
|
+
* A delegate previously received a prompt and a file list and nothing else,
|
|
21
|
+
* so a second delegated step could not see what the first produced. The only
|
|
22
|
+
* way to chain work was for the orchestrator to read job A's output into its
|
|
23
|
+
* OWN context and re-summarise it into job B's prompt — spending exactly the
|
|
24
|
+
* context that delegating was meant to save, and losing detail in the
|
|
25
|
+
* retelling.
|
|
26
|
+
*
|
|
27
|
+
* Naming the prior jobs instead moves that transfer into the tool: their
|
|
28
|
+
* prompts and outputs are rendered into B's prompt directly, at full
|
|
29
|
+
* fidelity, without passing through the orchestrator.
|
|
30
|
+
*/
|
|
31
|
+
contextJobs?: string[];
|
|
32
|
+
files?: string[];
|
|
33
|
+
workingDir?: string;
|
|
34
|
+
hints?: RouteHints;
|
|
35
|
+
workspacePolicy?: WorkspacePolicy;
|
|
36
|
+
service?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The job this one is a retry of.
|
|
39
|
+
*
|
|
40
|
+
* Recorded so a chain of attempts is traceable after the fact — without it,
|
|
41
|
+
* three attempts at the same task look like three unrelated jobs, and the
|
|
42
|
+
* one that finally worked cannot be connected to the two that did not.
|
|
43
|
+
*/
|
|
44
|
+
retryOf?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Live dispatcher-event tap, used by the `dispatch` tool to forward MCP
|
|
47
|
+
* progress notifications during its inline grace window. Never serialized
|
|
48
|
+
* (the manifest lists its fields explicitly), never awaited, and a throw
|
|
49
|
+
* here must not fail the job.
|
|
50
|
+
*/
|
|
51
|
+
onEvent?: (event: DispatcherEvent) => void;
|
|
52
|
+
}
|
|
53
|
+
export interface JobStatus {
|
|
54
|
+
jobId: string;
|
|
55
|
+
/**
|
|
56
|
+
* "orphaned" is never written to disk — it's computed on read: a job
|
|
57
|
+
* whose status file says "running" but whose heartbeat (updatedAt) has
|
|
58
|
+
* gone stale means the server process that owned the background run
|
|
59
|
+
* exited (session restart, crash) and the run died with it. Reporting it
|
|
60
|
+
* as still "running" forever is a lie that makes callers poll a corpse.
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* "cancelled" is terminal and deliberate: someone asked for this run to
|
|
64
|
+
* stop. It is distinct from "failed" because the run did not go wrong —
|
|
65
|
+
* treating a cancellation as a failure would charge the route's breaker and
|
|
66
|
+
* failure count for the caller changing their mind.
|
|
67
|
+
*/
|
|
68
|
+
status: "queued" | "running" | "completed" | "failed" | "orphaned" | "cancelled";
|
|
69
|
+
createdAt: string;
|
|
70
|
+
updatedAt: string;
|
|
71
|
+
jobDir: string;
|
|
72
|
+
service?: string;
|
|
73
|
+
route?: string;
|
|
74
|
+
success?: boolean;
|
|
75
|
+
/** Bounded copy — full text in output/stderr.log. */
|
|
76
|
+
error?: string;
|
|
77
|
+
/**
|
|
78
|
+
* END-TO-END milliseconds for the run: routing, workspace preparation and
|
|
79
|
+
* any workspace-lock wait included. Deliberately NOT the same number as
|
|
80
|
+
* result.durationMs, which times the harness attempt alone — one job
|
|
81
|
+
* legitimately reports 116ms there and 15s here when it queued behind a
|
|
82
|
+
* shared_locked workspace. Both are real; they answer different questions.
|
|
83
|
+
*/
|
|
84
|
+
durationMs?: number;
|
|
85
|
+
/** Suggested seconds to wait before polling action=get again. */
|
|
86
|
+
nextPollSeconds?: number;
|
|
87
|
+
/** Agent-facing guidance on how to collect the result. */
|
|
88
|
+
instructions?: string;
|
|
89
|
+
/** Set when workingDir was omitted and defaulted to the router's own cwd. */
|
|
90
|
+
warning?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Queued because the machine is at `max_concurrent_runs`, NOT because its
|
|
93
|
+
* owner died. Load-bearing for orphan detection: a slot-queued job has no
|
|
94
|
+
* process heartbeating for it, so without this flag the 90s staleness rule
|
|
95
|
+
* would report a job that is merely waiting its turn as a dead one.
|
|
96
|
+
* Cleared the moment a slot frees and its runner is spawned.
|
|
97
|
+
*/
|
|
98
|
+
slotQueued?: true;
|
|
99
|
+
}
|
|
100
|
+
export interface JobManifest {
|
|
101
|
+
jobId: string;
|
|
102
|
+
createdAt: string;
|
|
103
|
+
workingDir: string;
|
|
104
|
+
promptPath: string;
|
|
105
|
+
files: Array<{
|
|
106
|
+
originalPath: string;
|
|
107
|
+
snapshotPath?: string;
|
|
108
|
+
sizeBytes?: number;
|
|
109
|
+
error?: string;
|
|
110
|
+
}>;
|
|
111
|
+
hints?: RouteHints;
|
|
112
|
+
workspacePolicy?: WorkspacePolicy;
|
|
113
|
+
service?: string;
|
|
114
|
+
/** The job this one retries — see StartJobInput.retryOf. */
|
|
115
|
+
retryOf?: string;
|
|
116
|
+
/** Set when workingDir was omitted and defaulted to the router's own cwd. */
|
|
117
|
+
warning?: string;
|
|
118
|
+
}
|
|
119
|
+
export interface JobResultPayload {
|
|
120
|
+
jobId: string;
|
|
121
|
+
result: DispatchResult;
|
|
122
|
+
decision: RoutingDecision | null;
|
|
123
|
+
}
|
|
124
|
+
export interface StartedJob {
|
|
125
|
+
status: JobStatus;
|
|
126
|
+
/**
|
|
127
|
+
* Resolves once the run has reached a terminal state on disk (result.json
|
|
128
|
+
* or a failed/orphaned status). Never rejects. In detached mode this is a
|
|
129
|
+
* disk watcher on the job directory — the run itself lives in a separate
|
|
130
|
+
* job-runner process; in in-process mode (HARNESS_DISPATCH_INPROC_JOBS=1,
|
|
131
|
+
* used by unit tests with injected fakes) it is the runJob promise itself.
|
|
132
|
+
*/
|
|
133
|
+
completion: Promise<void>;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/jobs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH;;;;;OAKG;IACH,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;QACX,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,CAAC;IAClB;;;;;;OAMG;IACH,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shapes a job is written and read as.
|
|
3
|
+
*
|
|
4
|
+
* Split out of jobs.ts so the store, the supervisor and the dispatch path can
|
|
5
|
+
* share them without importing each other. These types are the actual
|
|
6
|
+
* contract between processes — a detached runner rebuilds its whole input
|
|
7
|
+
* from JobManifest, and every reader of a job's state goes through JobStatus
|
|
8
|
+
* — so they are the one part of the job system that must stay stable.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/jobs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|