toolroll 0.9.60 → 0.9.62
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 +32 -0
- package/dist/agent-board.d.ts +208 -0
- package/dist/agent-board.js +454 -0
- package/dist/agent-fence.d.ts +19 -0
- package/dist/agent-fence.js +100 -8
- package/dist/agent-pulse.d.ts +43 -0
- package/dist/agent-pulse.js +214 -0
- package/dist/agent-turns.d.ts +52 -0
- package/dist/agent-turns.js +137 -0
- package/dist/agents-board.d.ts +101 -0
- package/dist/agents-board.js +225 -0
- package/dist/assignment-adapters.d.ts +1 -0
- package/dist/assignment-status.d.ts +1 -1
- package/dist/assignment.d.ts +4 -0
- package/dist/assignment.js +8 -6
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +29 -25
- package/dist/browser-crew.js +2 -0
- package/dist/browser-workspace.d.ts +79 -1
- package/dist/browser-workspace.js +1 -0
- package/dist/builder.d.ts +8 -0
- package/dist/builder.js +113 -13
- package/dist/chat-channel.js +9 -0
- package/dist/chat-core.d.ts +6 -0
- package/dist/chat-core.js +8 -0
- package/dist/chat-delivery.js +22 -0
- package/dist/chat-messages.js +8 -1
- package/dist/chat-quiet.js +1 -0
- package/dist/chat-voice.d.ts +2 -0
- package/dist/chat-voice.js +2 -0
- package/dist/checkout-cleanup.d.ts +3 -0
- package/dist/checkout-cleanup.js +11 -2
- package/dist/cli.js +28 -11
- package/dist/contracts/console-api.d.ts +3 -1
- package/dist/contracts/console-api.js +5 -1
- package/dist/contracts/lead-tools.d.ts +16 -2
- package/dist/contracts/lead-tools.js +5 -1
- package/dist/desktop-update.d.ts +1 -1
- package/dist/evidence-pack.js +1 -1
- package/dist/evidence.d.ts +6 -0
- package/dist/evidence.js +14 -3
- package/dist/exec.d.ts +32 -0
- package/dist/exec.js +229 -10
- package/dist/invoke.js +110 -18
- package/dist/landed-cleanup.d.ts +170 -0
- package/dist/landed-cleanup.js +814 -0
- package/dist/lead-cli.js +22 -19
- package/dist/lead-contract.d.ts +1 -1
- package/dist/lead-contract.js +4 -4
- package/dist/lead-doors.js +45 -1
- package/dist/lead-tools.js +40 -7
- package/dist/live-input.d.ts +68 -0
- package/dist/live-input.js +254 -0
- package/dist/live.d.ts +1 -1
- package/dist/live.js +4 -2
- package/dist/maintenance.d.ts +2 -0
- package/dist/maintenance.js +5 -2
- package/dist/operate-remote-arguments.js +5 -1
- package/dist/operate-remote.js +1 -1
- package/dist/operate.d.ts +1 -1
- package/dist/operate.js +249 -26
- package/dist/orphan-sweep.d.ts +2 -0
- package/dist/orphan-sweep.js +5 -3
- package/dist/project-admission.d.ts +10 -6
- package/dist/project-admission.js +33 -11
- package/dist/project-delete-ui.d.ts +12 -0
- package/dist/project-delete-ui.js +32 -2
- package/dist/project-tools.d.ts +7 -11
- package/dist/project-tools.js +13 -37
- package/dist/provider.d.ts +65 -8
- package/dist/provider.js +80 -21
- package/dist/remote-main.d.ts +57 -0
- package/dist/remote-main.js +179 -0
- package/dist/result-completion.d.ts +7 -0
- package/dist/result-completion.js +9 -0
- package/dist/runner.d.ts +4 -2
- package/dist/runner.js +3 -3
- package/dist/serve.js +19 -1
- package/dist/server/live.d.ts +3 -0
- package/dist/server/live.js +35 -2
- package/dist/server/pages.js +59 -35
- package/dist/server/render-chat.js +12 -0
- package/dist/server/render-tasks.d.ts +15 -2
- package/dist/server/render-tasks.js +30 -7
- package/dist/server/route-table.js +4 -1
- package/dist/server/settings.js +5 -3
- package/dist/server/task-views.js +11 -0
- package/dist/server/tasks.js +63 -0
- package/dist/shared-deps.d.ts +9 -4
- package/dist/shared-deps.js +89 -13
- package/dist/staged-runtimes.d.ts +16 -4
- package/dist/staged-runtimes.js +160 -38
- package/dist/steer-live.d.ts +19 -0
- package/dist/steer-live.js +93 -0
- package/dist/steer-status.d.ts +8 -2
- package/dist/steer-status.js +19 -5
- package/dist/storage-sweep-child.d.ts +1 -0
- package/dist/storage-sweep-child.js +76 -0
- package/dist/storage-sweep-process.d.ts +48 -0
- package/dist/storage-sweep-process.js +204 -0
- package/dist/storage-sweep-schedule.d.ts +30 -0
- package/dist/storage-sweep-schedule.js +164 -0
- package/dist/storage-sweep.d.ts +31 -6
- package/dist/storage-sweep.js +165 -39
- package/dist/storage-ui.d.ts +4 -0
- package/dist/storage-ui.js +22 -7
- package/dist/storage.d.ts +6 -0
- package/dist/storage.js +35 -0
- package/dist/store.d.ts +200 -3
- package/dist/store.js +443 -17
- package/dist/surface.js +8 -4
- package/dist/sweep-quarantine.d.ts +28 -0
- package/dist/sweep-quarantine.js +153 -0
- package/dist/task-base.d.ts +35 -0
- package/dist/task-base.js +51 -0
- package/dist/task-status.d.ts +2 -0
- package/dist/task-status.js +5 -1
- package/dist/test-temp.d.ts +6 -3
- package/dist/test-temp.js +15 -9
- package/dist/toolroll-update.js +4 -2
- package/dist/work-index.d.ts +1 -0
- package/dist/work-index.js +32 -12
- package/dist/work-summary.d.ts +2 -2
- package/dist/workspace-revision.js +3 -1
- package/dist/worktree.d.ts +57 -3
- package/dist/worktree.js +201 -23
- package/package.json +1 -1
- package/scripts/provider-canary.mjs +235 -147
package/dist/cli.js
CHANGED
|
@@ -506,7 +506,14 @@ async function runReposCommand(argv, write, onboard) {
|
|
|
506
506
|
const tokenAt = argv.indexOf("--token");
|
|
507
507
|
const tokenFlag = tokenAt === -1 ? undefined : argv[tokenAt + 1];
|
|
508
508
|
const bare = argv.filter((argument, index) => argument !== "--json" && (tokenAt === -1 || (index !== tokenAt && index !== tokenAt + 1)));
|
|
509
|
-
const
|
|
509
|
+
const remoteAt = bare.indexOf("--remote");
|
|
510
|
+
const remoteUrl = remoteAt === -1 ? undefined : bare[remoteAt + 1];
|
|
511
|
+
const [action, ...paths] = bare.filter((_, i) => remoteAt === -1 || (i !== remoteAt && i !== remoteAt + 1));
|
|
512
|
+
if (remoteAt !== -1 && (action !== "add" || bare.filter(v => v === "--remote").length !== 1 || remoteUrl === undefined || remoteUrl.startsWith("-") || paths.length > 1)) {
|
|
513
|
+
const message = "Use repos add <project> --remote <url> for one project.";
|
|
514
|
+
write(json ? envelopeJson({ ok: false, command: "repos", reason: "usage", message }) : message);
|
|
515
|
+
return USAGE_EXIT;
|
|
516
|
+
}
|
|
510
517
|
const databaseFile = databasePath(process.env, homedir());
|
|
511
518
|
const file = registryBeside(databaseFile);
|
|
512
519
|
if (tokenAt !== -1 && (tokenFlag === undefined || tokenFlag.startsWith("-"))) {
|
|
@@ -529,11 +536,18 @@ async function runReposCommand(argv, write, onboard) {
|
|
|
529
536
|
return 1;
|
|
530
537
|
}
|
|
531
538
|
if (action === undefined) {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
539
|
+
const store = openStore(databaseFile);
|
|
540
|
+
try {
|
|
541
|
+
const projects = loaded.repos.map(repo => ({ repo, remoteUrl: store.projectRemote(repo) }));
|
|
542
|
+
if (json) {
|
|
543
|
+
write(envelopeJson({ ok: true, command: "repos", count: loaded.repos.length, repos: loaded.repos, projects, file }));
|
|
544
|
+
return 0;
|
|
545
|
+
}
|
|
546
|
+
return listRepos(loaded.repos, file, write, new Map(projects.map(p => [p.repo, p.remoteUrl])));
|
|
547
|
+
}
|
|
548
|
+
finally {
|
|
549
|
+
store.close();
|
|
535
550
|
}
|
|
536
|
-
return listRepos(loaded.repos, file, write);
|
|
537
551
|
}
|
|
538
552
|
if (action !== "add" && action !== "remove") {
|
|
539
553
|
const message = `unknown command \`repos ${action}\` — try \`repos\`, \`repos add\`, \`repos remove\`, or \`repos add-from-github <owner/name>\``;
|
|
@@ -545,7 +559,7 @@ async function runReposCommand(argv, write, onboard) {
|
|
|
545
559
|
const lines = [];
|
|
546
560
|
const said = {};
|
|
547
561
|
const say = json ? (line) => lines.push(line) : write;
|
|
548
|
-
const code = await withAdmission({ databaseFile, registryFile: file, ...(leadToken === undefined ? {} : { leadToken }) }, say, said, admission => action === "add" ? addToRepos(admission, targets, say, said) : removeFromRepos(admission, targets, say, said));
|
|
562
|
+
const code = await withAdmission({ databaseFile, registryFile: file, ...(leadToken === undefined ? {} : { leadToken }) }, say, said, admission => action === "add" ? addToRepos(admission, targets, say, said, remoteUrl) : removeFromRepos(admission, targets, say, said));
|
|
549
563
|
if (json) {
|
|
550
564
|
write(envelopeJson({
|
|
551
565
|
ok: code === 0,
|
|
@@ -582,7 +596,7 @@ async function withAdmission(where, write, said, body) {
|
|
|
582
596
|
store.close();
|
|
583
597
|
}
|
|
584
598
|
}
|
|
585
|
-
function listRepos(repos, file, write) {
|
|
599
|
+
function listRepos(repos, file, write, remotes) {
|
|
586
600
|
if (repos.length === 0) {
|
|
587
601
|
write("No repositories connected. Toolroll reports on everything it can find.");
|
|
588
602
|
write("");
|
|
@@ -592,8 +606,10 @@ function listRepos(repos, file, write) {
|
|
|
592
606
|
return 0;
|
|
593
607
|
}
|
|
594
608
|
write(`${repos.length === 1 ? "1 repository" : `${repos.length} repositories`} connected:`);
|
|
595
|
-
for (const repo of repos)
|
|
609
|
+
for (const repo of repos) {
|
|
596
610
|
write(` ${repo}${existsSync(repo) ? "" : " (missing)"}`);
|
|
611
|
+
write(` Recorded remote: ${remotes.get(repo) ?? "None"}`);
|
|
612
|
+
}
|
|
597
613
|
write("");
|
|
598
614
|
write(" toolroll repos add <path> add another; it is in the console at once");
|
|
599
615
|
write(" toolroll repos remove <path> take one out of the console; its tasks stay");
|
|
@@ -606,7 +622,7 @@ function listRepos(repos, file, write) {
|
|
|
606
622
|
function admissionExit(reason) {
|
|
607
623
|
return reason === "not-git" || reason === "unavailable" ? USAGE_EXIT : 1;
|
|
608
624
|
}
|
|
609
|
-
async function addToRepos(admission, targets, write, said) {
|
|
625
|
+
async function addToRepos(admission, targets, write, said, remoteUrl) {
|
|
610
626
|
// Every folder is proved before anything is written: one that is not a
|
|
611
627
|
// repository fails here, not later and further away.
|
|
612
628
|
let refused = false;
|
|
@@ -624,7 +640,7 @@ async function addToRepos(admission, targets, write, said) {
|
|
|
624
640
|
const running = consoleRunning(admission.store, now);
|
|
625
641
|
const projects = [];
|
|
626
642
|
for (const path of targets) {
|
|
627
|
-
const admitted = await admitProject(admission.store, { registryFile: admission.registryFile, path, actor: admission.actor, now });
|
|
643
|
+
const admitted = await admitProject(admission.store, { registryFile: admission.registryFile, path, actor: admission.actor, now, captureOrigin: true, ...(remoteUrl === undefined ? {} : { remoteUrl }) });
|
|
628
644
|
if (!admitted.ok) {
|
|
629
645
|
// The updater's own taxonomy survives (verification finding 4): a held
|
|
630
646
|
// lock or a malformed registry is an operational fact, never "usage".
|
|
@@ -633,8 +649,9 @@ async function addToRepos(admission, targets, write, said) {
|
|
|
633
649
|
write(admitted.message);
|
|
634
650
|
return admissionExit(admitted.reason);
|
|
635
651
|
}
|
|
636
|
-
projects.push({ repo: admitted.repo, name: admitted.name, added: admitted.added });
|
|
652
|
+
projects.push({ repo: admitted.repo, name: admitted.name, added: admitted.added, remoteUrl: admitted.remote.url });
|
|
637
653
|
write(addedWords(admitted.name, admitted.added, running));
|
|
654
|
+
write(`Recorded remote: ${admitted.remote.url ?? "None. Use repos add <project> --remote <url> to record one."}`);
|
|
638
655
|
}
|
|
639
656
|
said.projects = projects;
|
|
640
657
|
return 0;
|
|
@@ -156,7 +156,8 @@ export declare const CONSOLE_FORMS: {
|
|
|
156
156
|
readonly revise: FormContract<"batch" | "return" | "source">;
|
|
157
157
|
readonly followUp: FormContract<"level" | "return">;
|
|
158
158
|
readonly resolveIncident: FormContract<"return">;
|
|
159
|
-
readonly taskSteer: FormContract<"note">;
|
|
159
|
+
readonly taskSteer: FormContract<"note" | "return" | "run">;
|
|
160
|
+
readonly taskReply: FormContract<"answer" | "question">;
|
|
160
161
|
readonly taskHold: FormContract<"reason">;
|
|
161
162
|
readonly taskBlock: FormContract<"on">;
|
|
162
163
|
readonly taskRepairDependency: FormContract<"blocker" | "operation" | "replacement">;
|
|
@@ -173,6 +174,7 @@ export declare const CONSOLE_FORMS: {
|
|
|
173
174
|
readonly taskAcceptProof: FormContract<"note" | "return" | "run">;
|
|
174
175
|
readonly taskComplete: FormContract<"accept" | "note" | "publish" | "receipt" | "return" | "run">;
|
|
175
176
|
readonly taskStop: FormContract<"return" | "run">;
|
|
177
|
+
readonly taskPause: FormContract<"mode" | "note" | "request" | "return" | "run">;
|
|
176
178
|
readonly taskResume: FormContract<"nonce" | "return" | "run" | "token">;
|
|
177
179
|
};
|
|
178
180
|
export type ConsoleFormName = keyof typeof CONSOLE_FORMS;
|
|
@@ -167,7 +167,8 @@ export const CONSOLE_FORMS = {
|
|
|
167
167
|
followUp: formContract("POST /r/<run>/checks|add-tests", ["return", "level"]),
|
|
168
168
|
resolveIncident: formContract("POST /i/<id>/resolve", ["return"]),
|
|
169
169
|
// A task's verbs (/t/<task>/<verb>), one body each.
|
|
170
|
-
taskSteer: formContract("POST /t/<task>/steer", ["note"]),
|
|
170
|
+
taskSteer: formContract("POST /t/<task>/steer", ["note", "return", "run"]),
|
|
171
|
+
taskReply: formContract("POST /t/<task>/reply", ["question", "answer"]),
|
|
171
172
|
taskHold: formContract("POST /t/<task>/hold", ["reason"]),
|
|
172
173
|
taskBlock: formContract("POST /t/<task>/block|unblock", ["on"]),
|
|
173
174
|
taskRepairDependency: formContract("POST /t/<task>/repair-dependency", ["blocker", "operation", "replacement"]),
|
|
@@ -184,6 +185,9 @@ export const CONSOLE_FORMS = {
|
|
|
184
185
|
taskAcceptProof: formContract("POST /t/<task>/accept-proof", ["run", "note", "return"]),
|
|
185
186
|
taskComplete: formContract("POST /t/<task>/complete", ["receipt", "run", "accept", "note", "publish", "return"]),
|
|
186
187
|
taskStop: formContract("POST /t/<task>/stop", ["run", "return"]),
|
|
188
|
+
// Pause, or Pause and steer when a note rides along, or Resume (mode=resume): the exact run shown, and the page's own
|
|
189
|
+
// request id.
|
|
190
|
+
taskPause: formContract("POST /t/<task>/pause", ["run", "request", "note", "mode", "return"]),
|
|
187
191
|
taskResume: formContract("POST /t/<task>/resume|resume-arm", ["run", "token", "nonce", "return"]),
|
|
188
192
|
};
|
|
189
193
|
/** The console POSTs whose handlers read no field (sign-out not even the shared guard): their contract is the empty form. */
|
|
@@ -656,7 +656,14 @@ export declare const LEAD_TOOL_INPUTS: {
|
|
|
656
656
|
}, z.core.$strict>;
|
|
657
657
|
readonly propose_steer: z.ZodObject<{
|
|
658
658
|
task: z.ZodString;
|
|
659
|
-
note: z.ZodString
|
|
659
|
+
note: z.ZodOptional<z.ZodString>;
|
|
660
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
661
|
+
note: "note";
|
|
662
|
+
pause: "pause";
|
|
663
|
+
"pause-and-steer": "pause-and-steer";
|
|
664
|
+
resume: "resume";
|
|
665
|
+
}>>;
|
|
666
|
+
question: z.ZodOptional<z.ZodNumber>;
|
|
660
667
|
}, z.core.$strict>;
|
|
661
668
|
readonly propose_dependency_repair: z.ZodObject<{
|
|
662
669
|
task: z.ZodString;
|
|
@@ -1318,7 +1325,14 @@ export declare const LEAD_TOOL_READ_INPUTS: {
|
|
|
1318
1325
|
}, z.core.$strict>;
|
|
1319
1326
|
readonly propose_steer: z.ZodObject<{
|
|
1320
1327
|
task: z.ZodString;
|
|
1321
|
-
note: z.ZodString
|
|
1328
|
+
note: z.ZodOptional<z.ZodString>;
|
|
1329
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
1330
|
+
note: "note";
|
|
1331
|
+
pause: "pause";
|
|
1332
|
+
"pause-and-steer": "pause-and-steer";
|
|
1333
|
+
resume: "resume";
|
|
1334
|
+
}>>;
|
|
1335
|
+
question: z.ZodOptional<z.ZodNumber>;
|
|
1322
1336
|
}, z.core.$strict>;
|
|
1323
1337
|
readonly propose_dependency_repair: z.ZodObject<{
|
|
1324
1338
|
task: z.ZodString;
|
|
@@ -130,7 +130,11 @@ export const LEAD_TOOL_INPUTS = {
|
|
|
130
130
|
propose_reserve: z.strictObject({ task: taskRef, worker: text("workerName").nullable() }),
|
|
131
131
|
propose_hold: z.strictObject({ task: taskRef, reason: text("proposalReason") }),
|
|
132
132
|
propose_unhold: z.strictObject({ task: taskRef }),
|
|
133
|
-
|
|
133
|
+
// mode: a note (the default), Pause (stop a running Claude build's turn, keep the build), Pause and steer, or Resume
|
|
134
|
+
// (a paused build goes on where it stopped, without a note).
|
|
135
|
+
// question: a running agent's open question (Agents board); the note is its reply, sent as an ordinary note.
|
|
136
|
+
propose_steer: z.strictObject({ task: taskRef, note: note.optional(), mode: z.enum(["note", "pause", "pause-and-steer", "resume"]).optional(),
|
|
137
|
+
question: z.number().int().positive().optional().describe("A running agent's open question (get_task agentQuestions): the note becomes its reply and closes it.") }),
|
|
134
138
|
propose_dependency_repair: z.strictObject({ task: taskRef, blocker: taskRef, operation: z.enum(["retry", "unlink", "replace"]), replacement: taskRef.optional() }),
|
|
135
139
|
propose_scope: z.strictObject({ task: taskRef, goal: scopeText, not: scopeText.nullable().optional(), touches: touches.optional(), acceptance }),
|
|
136
140
|
propose_agents: z.strictObject({
|
package/dist/desktop-update.d.ts
CHANGED
|
@@ -94,7 +94,6 @@ export declare function prepareDesktopUpdate(stateDir: string, installed: string
|
|
|
94
94
|
export declare function sqliteLock(file: string, busyTimeoutMs?: number): DatabaseSync | null;
|
|
95
95
|
export declare const installationLock: (j: UpdateJournal) => DatabaseSync | null;
|
|
96
96
|
export declare function desktopUpdateStatus(stateDir: string): {
|
|
97
|
-
version?: never;
|
|
98
97
|
active: boolean;
|
|
99
98
|
phase: string;
|
|
100
99
|
detail: string;
|
|
@@ -108,6 +107,7 @@ export declare function desktopUpdateStatus(stateDir: string): {
|
|
|
108
107
|
wasRunning?: never;
|
|
109
108
|
backupPath?: never;
|
|
110
109
|
updateId?: never;
|
|
110
|
+
version?: never;
|
|
111
111
|
buildId?: never;
|
|
112
112
|
workDir?: never;
|
|
113
113
|
} | {
|
package/dist/evidence-pack.js
CHANGED
|
@@ -84,7 +84,7 @@ export function evidencePack(store, taskId, access, who, now, evidenceRoot, chec
|
|
|
84
84
|
result: receipt === null ? null : {
|
|
85
85
|
runId: receipt.runId, base: receipt.base, head: receipt.head, kind: receipt.completionKind,
|
|
86
86
|
checks: { status: receipt.checks.status, command: receipt.checks.command, exitCode: receipt.checks.exitCode, detail: receipt.checks.detail },
|
|
87
|
-
completedBy: assignment?.completion?.actor ?? null, completedAt: assignment?.completion?.at ?? null, caveats: receipt.caveats,
|
|
87
|
+
completedBy: assignment?.completion?.landed !== undefined ? `Toolroll, automatically: ${assignment.completion.landed}` : assignment?.completion?.actor ?? null, completedAt: assignment?.completion?.at ?? null, caveats: receipt.caveats,
|
|
88
88
|
publication: assignment?.publication ?? null,
|
|
89
89
|
},
|
|
90
90
|
totals: { runs: allRuns.length, costUsd: Math.round(sum(run => run.costUsd) * 1e6) / 1e6, tokensIn: sum(run => run.tokensIn), tokensOut: sum(run => run.tokensOut) },
|
package/dist/evidence.d.ts
CHANGED
|
@@ -51,6 +51,9 @@ export declare const PROPOSAL_PREFIX = "STANDING-ORDERS-PROPOSAL-";
|
|
|
51
51
|
* writes each operator note into it as NNN.json (a temp name, then a
|
|
52
52
|
* rename); the agent acknowledges a note by moving it into `handled/`. */
|
|
53
53
|
export declare const STEER_PREFIX = "STANDING-ORDERS-STEER-";
|
|
54
|
+
/** The running build's status file (Agents board): JSON lines the agent appends
|
|
55
|
+
* (working, needs-decision, blocked, done), read forward by the pulse. */
|
|
56
|
+
export declare const STATUS_PREFIX = "STANDING-ORDERS-STATUS-";
|
|
54
57
|
export declare const MAILBOX_SUFFIX = ".json";
|
|
55
58
|
/** v105: left in a run's evidence folder when the retention setting removed its files (retention.ts). */
|
|
56
59
|
export declare const RETENTION_NOTE = "REMOVED-BY-RETENTION";
|
|
@@ -86,6 +89,9 @@ export declare function looksLikeProtocolFile(name: string): boolean;
|
|
|
86
89
|
* `git status` names it: an untracked folder is reported with a trailing
|
|
87
90
|
* slash, or file by file where a repository shows every untracked file. */
|
|
88
91
|
export declare function looksLikeSteerFolder(name: string): boolean;
|
|
92
|
+
/** An agent status file (Agents board), by its exact nonce-shaped name. */
|
|
93
|
+
export declare function looksLikeStatusFile(name: string): boolean;
|
|
94
|
+
export declare function statusFileName(): string;
|
|
89
95
|
export declare function steerFolderName(): string;
|
|
90
96
|
export declare function handoffName(): string;
|
|
91
97
|
export declare function planFileName(): string;
|
package/dist/evidence.js
CHANGED
|
@@ -54,6 +54,9 @@ export const PROPOSAL_PREFIX = "STANDING-ORDERS-PROPOSAL-";
|
|
|
54
54
|
* writes each operator note into it as NNN.json (a temp name, then a
|
|
55
55
|
* rename); the agent acknowledges a note by moving it into `handled/`. */
|
|
56
56
|
export const STEER_PREFIX = "STANDING-ORDERS-STEER-";
|
|
57
|
+
/** The running build's status file (Agents board): JSON lines the agent appends
|
|
58
|
+
* (working, needs-decision, blocked, done), read forward by the pulse. */
|
|
59
|
+
export const STATUS_PREFIX = "STANDING-ORDERS-STATUS-";
|
|
57
60
|
export const MAILBOX_SUFFIX = ".json";
|
|
58
61
|
/** v105: left in a run's evidence folder when the retention setting removed its files (retention.ts). */
|
|
59
62
|
export const RETENTION_NOTE = "REMOVED-BY-RETENTION";
|
|
@@ -132,7 +135,7 @@ export function looksLikeMailbox(name) {
|
|
|
132
135
|
* The pre-rename NIGHTORDERS- prefix stays recognized here — a worktree cut
|
|
133
136
|
* down before 2026-08-13 may still hold one, and cleanup has no vintage. */
|
|
134
137
|
export function looksLikeProtocolFile(name) {
|
|
135
|
-
if (looksLikeSteerFolder(name))
|
|
138
|
+
if (looksLikeSteerFolder(name) || looksLikeStatusFile(name))
|
|
136
139
|
return true;
|
|
137
140
|
return ((name.startsWith(MAILBOX_PREFIX) ||
|
|
138
141
|
name.startsWith(HANDOFF_PREFIX) ||
|
|
@@ -153,6 +156,13 @@ export function looksLikeProtocolFile(name) {
|
|
|
153
156
|
export function looksLikeSteerFolder(name) {
|
|
154
157
|
return /^STANDING-ORDERS-STEER-[0-9a-f]{16}(?:\/.*)?$/.test(name);
|
|
155
158
|
}
|
|
159
|
+
/** An agent status file (Agents board), by its exact nonce-shaped name. */
|
|
160
|
+
export function looksLikeStatusFile(name) {
|
|
161
|
+
return /^STANDING-ORDERS-STATUS-[0-9a-f]{16}\.jsonl$/.test(name);
|
|
162
|
+
}
|
|
163
|
+
export function statusFileName() {
|
|
164
|
+
return `${STATUS_PREFIX}${randomBytes(8).toString("hex")}.jsonl`;
|
|
165
|
+
}
|
|
156
166
|
export function steerFolderName() {
|
|
157
167
|
return `${STEER_PREFIX}${randomBytes(8).toString("hex")}`;
|
|
158
168
|
}
|
|
@@ -550,8 +560,9 @@ export function quarantineMailboxes(worktree, root, runId) {
|
|
|
550
560
|
const path = join(worktree, name);
|
|
551
561
|
// An earlier attempt's steering folder holds copies of notes the
|
|
552
562
|
// database already keeps: removed whole (a symlink is removed, never
|
|
553
|
-
// followed), never quarantined.
|
|
554
|
-
|
|
563
|
+
// followed), never quarantined. So is its status file: the database
|
|
564
|
+
// already read every line it will ever need.
|
|
565
|
+
if (looksLikeSteerFolder(name) || looksLikeStatusFile(name)) {
|
|
555
566
|
try {
|
|
556
567
|
rmSync(path, { recursive: true, force: true });
|
|
557
568
|
swept.push(name);
|
package/dist/exec.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { type ProcessTreeObserver } from "./process-tree.js";
|
|
10
10
|
import { type ContainmentBackendId } from "./containment.js";
|
|
11
11
|
import type { Store } from "./store.js";
|
|
12
|
+
import type { LiveInput } from "./live-input.js";
|
|
12
13
|
export type ExecResult = {
|
|
13
14
|
/** Process exit code, or one of the synthetic codes below. */
|
|
14
15
|
code: number;
|
|
@@ -112,6 +113,15 @@ export type RunOptions = ProcessTreeObserver & {
|
|
|
112
113
|
* currently only the streaming transport can deliver this early).
|
|
113
114
|
*/
|
|
114
115
|
onSessionId?: (id: string) => void;
|
|
116
|
+
/**
|
|
117
|
+
* Live input (live-input.ts): a Claude transport that declares `streamInput`
|
|
118
|
+
* keeps stdin piped and open, hands it to this session, and shows it every
|
|
119
|
+
* stdout event. The session sends the brief first and decides when stdin
|
|
120
|
+
* closes; the run then ends with the process, and the LAST primary result
|
|
121
|
+
* is the accounting envelope (one result per turn), with every main
|
|
122
|
+
* result's usage and turns added up (cumulativeLiveResult).
|
|
123
|
+
*/
|
|
124
|
+
liveInput?: LiveInput;
|
|
115
125
|
/** Fires once the child exists, with its pid (the process-group id when
|
|
116
126
|
* processGroup is set) — the slot ledger records it (v14 finding 26). */
|
|
117
127
|
onSpawn?: (pid: number) => void;
|
|
@@ -202,6 +212,17 @@ export declare function run(file: string, args: readonly string[], options?: Run
|
|
|
202
212
|
* worst useful case while remaining a hard, per-event memory boundary.
|
|
203
213
|
*/
|
|
204
214
|
export declare const JSONL_EVENT_HARD_CAP: number;
|
|
215
|
+
/**
|
|
216
|
+
* The accounting an oversized Claude result still carries, read by a bounded scan of its kept prefix and tail: the
|
|
217
|
+
* session's running `total_cost_usd`, its `usage` and `num_turns`, and whether it is a main result at all (an
|
|
218
|
+
* `origin` naming anything but a person makes it a background task's). Anything unreadable or seen twice is absent.
|
|
219
|
+
*/
|
|
220
|
+
export declare function scanOversizedClaudeResult(prefix: Buffer, tail: Buffer | undefined): {
|
|
221
|
+
primary: boolean;
|
|
222
|
+
account: Record<string, unknown>;
|
|
223
|
+
};
|
|
224
|
+
/** Marks a Claude result whose session cost could not be read: the gateway charges the run's dollar cap instead. */
|
|
225
|
+
export declare const CLAUDE_COST_UNKNOWN = "standing_orders_cost_unknown";
|
|
205
226
|
export declare function runStreamJsonl(file: string, args: readonly string[], options?: RunOptions): Promise<ExecResult>;
|
|
206
227
|
/**
|
|
207
228
|
* The streaming transport for gemini's stream-json dialect (Phase 3 D1/A7).
|
|
@@ -225,4 +246,15 @@ export declare function runStreamJsonl(file: string, args: readonly string[], op
|
|
|
225
246
|
* semantics match `runStreamJsonl`.
|
|
226
247
|
*/
|
|
227
248
|
export declare function runGeminiStreamJsonl(file: string, args: readonly string[], options?: RunOptions): Promise<ExecResult>;
|
|
249
|
+
/**
|
|
250
|
+
* A live session's account so far (one main result per turn, checked on Claude Code 2.1.290): the latest result's
|
|
251
|
+
* session, ending, words and cost — `total_cost_usd` is already the session's running total — with the usage token
|
|
252
|
+
* fields and `num_turns`, which count only their own message, added up across every main result. A field that is not
|
|
253
|
+
* a non-negative number adds nothing.
|
|
254
|
+
*/
|
|
255
|
+
export declare function cumulativeLiveResult(previous: Record<string, unknown>, latest: Record<string, unknown>): Record<string, unknown>;
|
|
256
|
+
/** This transport can keep stdin open for a live session (RunOptions.liveInput). */
|
|
257
|
+
export declare const STREAM_INPUT: unique symbol;
|
|
258
|
+
/** Whether a runner declares it keeps stdin open for a live session; an injected runner opts in by carrying the mark. */
|
|
259
|
+
export declare const streamsInput: (runner: unknown) => boolean;
|
|
228
260
|
export declare function runClaudeStreamJsonl(file: string, args: readonly string[], options?: RunOptions): Promise<ExecResult>;
|