@wjarka/cezarion 0.14.8 → 0.14.9-dev.1004
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/README.md +129 -2
- package/dist/application-update/bin-recovery.d.ts +5 -0
- package/dist/application-update/bin-recovery.js +96 -0
- package/dist/application-update/bin-recovery.js.map +1 -0
- package/dist/application-update/discovery.d.ts +22 -0
- package/dist/application-update/discovery.js +91 -0
- package/dist/application-update/discovery.js.map +1 -0
- package/dist/application-update/helper.d.ts +57 -0
- package/dist/application-update/helper.js +374 -0
- package/dist/application-update/helper.js.map +1 -0
- package/dist/application-update/launcher.d.ts +8 -0
- package/dist/application-update/launcher.js +53 -0
- package/dist/application-update/launcher.js.map +1 -0
- package/dist/application-update/lock.d.ts +4 -0
- package/dist/application-update/lock.js +70 -0
- package/dist/application-update/lock.js.map +1 -0
- package/dist/application-update/npm-process.d.ts +17 -0
- package/dist/application-update/npm-process.js +133 -0
- package/dist/application-update/npm-process.js.map +1 -0
- package/dist/application-update/service.d.ts +69 -0
- package/dist/application-update/service.js +456 -0
- package/dist/application-update/service.js.map +1 -0
- package/dist/artifacts/cli.d.ts +1 -0
- package/dist/artifacts/cli.js +32 -0
- package/dist/artifacts/cli.js.map +1 -0
- package/dist/artifacts/lifecycle.d.ts +4 -0
- package/dist/artifacts/lifecycle.js +42 -0
- package/dist/artifacts/lifecycle.js.map +1 -0
- package/dist/artifacts/resolve.d.ts +18 -0
- package/dist/artifacts/resolve.js +102 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/artifacts/store.d.ts +8 -0
- package/dist/artifacts/store.js +323 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/automations/scheduler.d.ts +6 -0
- package/dist/automations/scheduler.js +45 -17
- package/dist/automations/scheduler.js.map +1 -1
- package/dist/automations/store.d.ts +12 -4
- package/dist/automations/store.js +199 -22
- package/dist/automations/store.js.map +1 -1
- package/dist/automations/types.d.ts +2 -0
- package/dist/automations/types.js +1 -0
- package/dist/automations/types.js.map +1 -1
- package/dist/ci-wait/mcp.d.ts +3 -0
- package/dist/ci-wait/mcp.js +14 -3
- package/dist/ci-wait/mcp.js.map +1 -1
- package/dist/contract/application-update.d.ts +32 -0
- package/dist/contract/artifacts.d.ts +83 -0
- package/dist/contract/ask-schema.d.ts +32 -0
- package/dist/contract/ask.d.ts +2 -32
- package/dist/contract/automations.d.ts +6 -0
- package/dist/contract/conversations.d.ts +165 -0
- package/dist/contract/delegation.d.ts +68 -0
- package/dist/contract/discovery.d.ts +134 -0
- package/dist/contract/events.d.ts +49 -0
- package/dist/contract/health.d.ts +12 -0
- package/dist/contract/index.d.ts +3 -0
- package/dist/contract/index.js +1654 -1454
- package/dist/contract/projects.d.ts +40 -0
- package/dist/contract/runs.d.ts +186 -0
- package/dist/contract/skills.d.ts +33 -0
- package/dist/core/agent-runner.d.ts +33 -4
- package/dist/core/agent-runner.js +5 -0
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/claude-cli-runner.d.ts +6 -12
- package/dist/core/claude-cli-runner.js +90 -20
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/codex-app-server-runner.d.ts +2 -1
- package/dist/core/codex-app-server-runner.js +327 -92
- package/dist/core/codex-app-server-runner.js.map +1 -1
- package/dist/core/codex-app-server-transport.d.ts +13 -1
- package/dist/core/codex-app-server-transport.js +58 -17
- package/dist/core/codex-app-server-transport.js.map +1 -1
- package/dist/core/cursor-acp-runner.d.ts +6 -1
- package/dist/core/cursor-acp-runner.js +162 -26
- package/dist/core/cursor-acp-runner.js.map +1 -1
- package/dist/core/cursor-provider-error.d.ts +3 -0
- package/dist/core/cursor-provider-error.js +16 -1
- package/dist/core/cursor-provider-error.js.map +1 -1
- package/dist/core/input-submissions.d.ts +14 -0
- package/dist/core/input-submissions.js +26 -0
- package/dist/core/input-submissions.js.map +1 -0
- package/dist/core/opencode-server-runner.d.ts +4 -1
- package/dist/core/opencode-server-runner.js +156 -26
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/pi-runner.d.ts +2 -1
- package/dist/core/pi-runner.js +88 -10
- package/dist/core/pi-runner.js.map +1 -1
- package/dist/core/provider-auth.d.ts +99 -1
- package/dist/core/provider-auth.js +203 -2
- package/dist/core/provider-auth.js.map +1 -1
- package/dist/delegation/cli.d.ts +1 -0
- package/dist/delegation/cli.js +103 -7
- package/dist/delegation/cli.js.map +1 -1
- package/dist/delegation/conversations.js +13 -5
- package/dist/delegation/conversations.js.map +1 -1
- package/dist/delegation/input.d.ts +2 -1
- package/dist/delegation/input.js +6 -1
- package/dist/delegation/input.js.map +1 -1
- package/dist/delegation/policy.d.ts +3 -2
- package/dist/delegation/policy.js +3 -1
- package/dist/delegation/policy.js.map +1 -1
- package/dist/delegation/process-liveness.d.ts +66 -0
- package/dist/delegation/process-liveness.js +215 -0
- package/dist/delegation/process-liveness.js.map +1 -0
- package/dist/delegation/provision.d.ts +1 -1
- package/dist/delegation/provision.js +10 -5
- package/dist/delegation/provision.js.map +1 -1
- package/dist/delegation/questions.d.ts +19 -0
- package/dist/delegation/questions.js +45 -0
- package/dist/delegation/questions.js.map +1 -0
- package/dist/delegation/results.d.ts +1 -1
- package/dist/delegation/results.js +33 -19
- package/dist/delegation/results.js.map +1 -1
- package/dist/delegation/routes.d.ts +185 -11
- package/dist/delegation/routes.js +6 -2
- package/dist/delegation/routes.js.map +1 -1
- package/dist/delegation/service.d.ts +16 -5
- package/dist/delegation/service.js +161 -13
- package/dist/delegation/service.js.map +1 -1
- package/dist/delegation/transport.d.ts +228 -65
- package/dist/discovery/catalog.d.ts +14 -0
- package/dist/discovery/catalog.js +31 -0
- package/dist/discovery/catalog.js.map +1 -0
- package/dist/discovery/cli.d.ts +8 -0
- package/dist/discovery/cli.js +104 -0
- package/dist/discovery/cli.js.map +1 -0
- package/dist/git-worktree.d.ts +3 -1
- package/dist/git-worktree.js +26 -4
- package/dist/git-worktree.js.map +1 -1
- package/dist/index.js +92 -26
- package/dist/index.js.map +1 -1
- package/dist/open-url.d.ts +2 -0
- package/dist/open-url.js +20 -0
- package/dist/open-url.js.map +1 -0
- package/dist/release/snapshot.d.ts +3 -3
- package/dist/release/snapshot.js +6 -6
- package/dist/release/snapshot.js.map +1 -1
- package/dist/runs/agent-tmpdir.d.ts +2 -0
- package/dist/runs/agent-tmpdir.js +5 -2
- package/dist/runs/agent-tmpdir.js.map +1 -1
- package/dist/runs/client-request.d.ts +11 -0
- package/dist/runs/client-request.js +26 -0
- package/dist/runs/client-request.js.map +1 -0
- package/dist/runs/delegation-state.d.ts +17 -0
- package/dist/runs/event-history.js +6 -0
- package/dist/runs/event-history.js.map +1 -1
- package/dist/runs/retention.d.ts +7 -2
- package/dist/runs/retention.js +39 -7
- package/dist/runs/retention.js.map +1 -1
- package/dist/runs/store.d.ts +100 -6
- package/dist/runs/store.js +245 -2
- package/dist/runs/store.js.map +1 -1
- package/dist/runs/webhook.d.ts +125 -0
- package/dist/runs/webhook.js +256 -0
- package/dist/runs/webhook.js.map +1 -0
- package/dist/server/provider-auth-runtime.d.ts +30 -4
- package/dist/server/provider-auth-runtime.js +71 -6
- package/dist/server/provider-auth-runtime.js.map +1 -1
- package/dist/server/server.d.ts +8226 -4860
- package/dist/server/server.js +309 -15
- package/dist/server/server.js.map +1 -1
- package/dist/server-install/platforms/ubuntu-vps.d.ts +5 -1
- package/dist/server-install/platforms/ubuntu-vps.js +160 -18
- package/dist/server-install/platforms/ubuntu-vps.js.map +1 -1
- package/dist/server-install/steps.d.ts +4 -2
- package/dist/server-install/steps.js +5 -4
- package/dist/server-install/steps.js.map +1 -1
- package/dist/skills-remote.d.ts +30 -5
- package/dist/skills-remote.js +122 -32
- package/dist/skills-remote.js.map +1 -1
- package/dist/skills.js +15 -6
- package/dist/skills.js.map +1 -1
- package/dist/task-cli/cli.d.ts +38 -0
- package/dist/task-cli/cli.js +580 -0
- package/dist/task-cli/cli.js.map +1 -0
- package/dist/task-cli/discovery.d.ts +22 -0
- package/dist/task-cli/discovery.js +96 -0
- package/dist/task-cli/discovery.js.map +1 -0
- package/dist/task-cli/http.d.ts +46 -0
- package/dist/task-cli/http.js +101 -0
- package/dist/task-cli/http.js.map +1 -0
- package/dist/task-cli/projections.d.ts +40 -0
- package/dist/task-cli/projections.js +45 -0
- package/dist/task-cli/projections.js.map +1 -0
- package/dist/task-cli/watch.d.ts +78 -0
- package/dist/task-cli/watch.js +336 -0
- package/dist/task-cli/watch.js.map +1 -0
- package/dist/workflows/run.d.ts +160 -2
- package/dist/workflows/run.js +1141 -108
- package/dist/workflows/run.js.map +1 -1
- package/dist/workspace/agent-profiles.d.ts +22 -0
- package/dist/workspace/agent-profiles.js +15 -0
- package/dist/workspace/agent-profiles.js.map +1 -1
- package/dist/workspace/config.d.ts +9 -0
- package/dist/workspace/config.js +13 -1
- package/dist/workspace/config.js.map +1 -1
- package/dist/workspace/projects-cli.js +1 -1
- package/dist/workspace/projects.d.ts +24 -1
- package/dist/workspace/projects.js +14 -1
- package/dist/workspace/projects.js.map +1 -1
- package/package.json +5 -5
- package/scripts/mock-claude.mjs +64 -2
- package/scripts/mock-codex-app-server.mjs +124 -1
- package/scripts/mock-cursor-acp.mjs +54 -3
- package/scripts/mock-cursor-hang-stdin-late.mjs +35 -0
- package/scripts/mock-cursor-hang-stdin.mjs +30 -0
- package/scripts/mock-opencode-serve.mjs +102 -2
- package/scripts/mock-pi-rpc.mjs +82 -3
- package/web/dist/assets/agent-accounts-CerclGiO.js +1 -0
- package/web/dist/assets/centered-state-DH8qtCz-.js +43 -0
- package/web/dist/assets/collapsible-De2G0xqQ.js +1 -0
- package/web/dist/assets/commit-list-CQubP1iS.js +1 -0
- package/web/dist/assets/compare-variants-C_NijJvg.js +1 -0
- package/web/dist/assets/{diff-tRE59UNb2.js → diff-8M5HlDxq2.js} +2 -2
- package/web/dist/assets/diff-controls-B6ok0TtQ.js +1 -0
- package/web/dist/assets/{diff-stat-Cgnl_hYF.js → diff-stat-D1AODN2a.js} +1 -1
- package/web/dist/assets/{diff-view-DN1ort7Q.js → diff-view-Bs5Gh7UF.js} +2 -2
- package/web/dist/assets/dropdown-menu-7KGQMoFj.js +1 -0
- package/web/dist/assets/git-toolbar-DqbapMXr.js +1 -0
- package/web/dist/assets/github-lMHiuYSx.js +1 -0
- package/web/dist/assets/{image-preview-C2JGcBlC.js → image-preview-jzHoEyLM.js} +1 -1
- package/web/dist/assets/index-D4OJTArJ.js +7 -0
- package/web/dist/assets/index-D5NkwqY7.css +1 -0
- package/web/dist/assets/markdown-DvbymqXz.js +2 -0
- package/web/dist/assets/pill-BL6ugwXo.js +1 -0
- package/web/dist/assets/project-router-ChC5Rb-Y.js +1 -0
- package/web/dist/assets/prompt-templates-j8qlK7c-.js +15 -0
- package/web/dist/assets/repo-git-BbPAgkqb.js +1 -0
- package/web/dist/assets/{run-diff-CyG0Nciv.js → run-diff-BuATgZpx.js} +2 -2
- package/web/dist/assets/run-header-DuAWswYM.js +1 -0
- package/web/dist/assets/skills-DiC2XrU1.js +1 -0
- package/web/dist/assets/{tab-link-BWNp3mLY.js → tab-link-BmGKj9Rt.js} +1 -1
- package/web/dist/assets/task-changes-CP9kPnsy.js +1 -0
- package/web/dist/assets/task-commits-D6NfTw5r.js +1 -0
- package/web/dist/assets/task-files-W-b_gtcb.js +2 -0
- package/web/dist/assets/task-thread-Bw_nQuTx.css +1 -0
- package/web/dist/assets/task-thread-Q7Nj33DH.js +9 -0
- package/web/dist/assets/textarea-ByZ-txS7.js +1 -0
- package/web/dist/assets/thread-loading-DHT9p5o5.js +1 -0
- package/web/dist/assets/token-metrics-k4XoovDS.js +1 -0
- package/web/dist/assets/utils-BTFBhZ55.js +64 -0
- package/web/dist/assets/workflows-DqQszPHJ.js +11 -0
- package/web/dist/assets/{zoomable-image-Z3JDnm0b.js → zoomable-image-Ba6y6Wyl.js} +1 -1
- package/web/dist/index.html +14 -14
- package/web/dist/assets/agent-accounts-BZm_2WAv.js +0 -1
- package/web/dist/assets/alert-dialog-B422RI-k.js +0 -43
- package/web/dist/assets/collapsible-Cy_Fmkrd.js +0 -1
- package/web/dist/assets/commit-list-Dcnk7TnI.js +0 -1
- package/web/dist/assets/compare-variants-Ciqwvd_f.js +0 -1
- package/web/dist/assets/diff-controls-BGrXGi7O.js +0 -1
- package/web/dist/assets/dropdown-menu-dwDGT8MM.js +0 -1
- package/web/dist/assets/git-toolbar-UiHnGvE0.js +0 -1
- package/web/dist/assets/github-D-MrkbJ7.js +0 -1
- package/web/dist/assets/ibm-plex-mono-regular-BF3vfe7_.ttf +0 -0
- package/web/dist/assets/index-BszfYvBq.js +0 -7
- package/web/dist/assets/index-CWh4pKP3.css +0 -1
- package/web/dist/assets/markdown-C_IcKVQd.js +0 -2
- package/web/dist/assets/pill-BsbO6G7y.js +0 -1
- package/web/dist/assets/project-router-DbLkll25.js +0 -1
- package/web/dist/assets/prompt-templates-BlTGJB5W.js +0 -15
- package/web/dist/assets/repo-git-Bm3s6Why.js +0 -1
- package/web/dist/assets/run-header-IFyIGCey.js +0 -1
- package/web/dist/assets/skills-C-C4DVFY.js +0 -1
- package/web/dist/assets/task-changes-D2PHtWUW.js +0 -1
- package/web/dist/assets/task-commits-N5u9U0_R.js +0 -1
- package/web/dist/assets/task-files-BS7c7CFm.js +0 -2
- package/web/dist/assets/task-thread-BQFdz1dJ.css +0 -1
- package/web/dist/assets/task-thread-DGM2dZV-.js +0 -9
- package/web/dist/assets/textarea-FjaU370i.js +0 -1
- package/web/dist/assets/thread-loading-77sJ8Yu_.js +0 -1
- package/web/dist/assets/token-metrics-Clxh03bE.js +0 -1
- package/web/dist/assets/utils-PYYcpCFZ.js +0 -64
- package/web/dist/assets/workflows-Czl0ZfXH.js +0 -11
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { apiRunSchema, runHistoryPageSchema, runRecordSchema, } from '../contract/index.js';
|
|
2
|
+
import { invalidResponse, refuse, request, TaskCliError } from './http.js';
|
|
3
|
+
import { SUCCESS_STATUSES, TERMINAL_STATUSES } from './projections.js';
|
|
4
|
+
/**
|
|
5
|
+
* Watching a task from a terminal (#504, spec 2026-09-24-cez-task-cli). Every loop here ends —
|
|
6
|
+
* on a terminal status or at the caller's deadline — because a bot's tool call that never
|
|
7
|
+
* returns is the failure this command family exists to prevent.
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_POLL_MS = 1_500;
|
|
10
|
+
const MAX_FIELD_CHARS = 2_000;
|
|
11
|
+
function entryFor(id, run) {
|
|
12
|
+
if (!run)
|
|
13
|
+
return { id, status: 'missing' };
|
|
14
|
+
return {
|
|
15
|
+
id,
|
|
16
|
+
status: run.status,
|
|
17
|
+
...(run.activity === undefined ? {} : { activity: run.activity }),
|
|
18
|
+
hasPendingHumanAsk: run.hasPendingHumanAsk ?? false,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Settled = nothing more will happen without a human; `missing` counts, it will never change. */
|
|
22
|
+
function isSettled(entry, until) {
|
|
23
|
+
if (entry.status === 'unknown')
|
|
24
|
+
return false;
|
|
25
|
+
if (entry.status === 'missing' || TERMINAL_STATUSES.includes(entry.status))
|
|
26
|
+
return true;
|
|
27
|
+
return until === 'attention' && (entry.status === 'waiting' || entry.hasPendingHumanAsk === true);
|
|
28
|
+
}
|
|
29
|
+
/** A failure is only a terminal non-success; stopping for attention is not one. */
|
|
30
|
+
function isFailure(entry) {
|
|
31
|
+
return entry.status === 'missing' || entry.status === 'failed' || entry.status === 'cancelled';
|
|
32
|
+
}
|
|
33
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
34
|
+
/**
|
|
35
|
+
* Grace for the millisecond race between a budget-bounded poll's abort and the
|
|
36
|
+
* deadline check (#538): `AbortSignal.timeout(budget)` can fire while
|
|
37
|
+
* `Date.now()` still reads just under the deadline, turning a timeout into an
|
|
38
|
+
* `unavailable` error (exit 2 instead of 3). A poll whose own abort consumed
|
|
39
|
+
* (almost) all of its budget failed *at* the deadline, so it answers "timed
|
|
40
|
+
* out". The grace never applies to other errors: a genuine failure stays
|
|
41
|
+
* `unavailable` even when it lands inside the grace window.
|
|
42
|
+
*/
|
|
43
|
+
export const TIMEOUT_GRACE_MS = 250;
|
|
44
|
+
export function pollHitDeadline(startedAt, budgetMs, now = Date.now()) {
|
|
45
|
+
return now - startedAt >= budgetMs - TIMEOUT_GRACE_MS;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* True when the wrapped cockpit error came from the poll's own abort (its
|
|
49
|
+
* budget running out) rather than a fast failure such as a refused
|
|
50
|
+
* connection. `fetchJson` folds every fetch failure into `unavailable`, so the
|
|
51
|
+
* abort surfaces only through the original message it preserves (`TimeoutError:
|
|
52
|
+
* The operation was aborted due to timeout`).
|
|
53
|
+
*/
|
|
54
|
+
export function abortedPoll(error) {
|
|
55
|
+
if (!(error instanceof TaskCliError))
|
|
56
|
+
return false;
|
|
57
|
+
const body = error.body;
|
|
58
|
+
return /abort|timeout/i.test(String(body.error ?? ''));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Polls `GET /runs`: one call covers any number of runs and holds no socket open. Each poll is
|
|
62
|
+
* bounded by what is left of the deadline, so a slow cockpit answers "timed out" on time rather
|
|
63
|
+
* than holding the caller for a full request timeout.
|
|
64
|
+
*/
|
|
65
|
+
export async function waitForRuns(cockpit, ids, options) {
|
|
66
|
+
const deadline = Date.now() + options.timeoutMs;
|
|
67
|
+
let entries = ids.map((id) => ({ id, status: 'unknown' }));
|
|
68
|
+
for (;;) {
|
|
69
|
+
const budget = deadline - Date.now();
|
|
70
|
+
if (budget <= 0)
|
|
71
|
+
return { exitCode: 3, runs: entries, timedOut: true };
|
|
72
|
+
const pollStart = Date.now();
|
|
73
|
+
let result;
|
|
74
|
+
try {
|
|
75
|
+
result = await request(cockpit, '/runs', { timeoutMs: budget });
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (Date.now() >= deadline)
|
|
79
|
+
return { exitCode: 3, runs: entries, timedOut: true };
|
|
80
|
+
if (abortedPoll(error) && pollHitDeadline(pollStart, budget))
|
|
81
|
+
return { exitCode: 3, runs: entries, timedOut: true };
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
if (result.status !== 200)
|
|
85
|
+
refuse(result);
|
|
86
|
+
const runs = apiRunSchema.array().safeParse(result.data);
|
|
87
|
+
if (!runs.success)
|
|
88
|
+
invalidResponse('run list');
|
|
89
|
+
const byId = new Map(runs.data.map((run) => [run.id, run]));
|
|
90
|
+
entries = ids.map((id) => entryFor(id, byId.get(id)));
|
|
91
|
+
const settled = entries.filter((entry) => isSettled(entry, options.until));
|
|
92
|
+
const done = options.mode === 'any' ? settled.length > 0 : settled.length === entries.length;
|
|
93
|
+
if (done) {
|
|
94
|
+
const judged = options.mode === 'any' ? settled : entries;
|
|
95
|
+
return { exitCode: judged.some(isFailure) && (options.mode === 'all' || judged.every(isFailure)) ? 1 : 0, runs: entries, timedOut: false };
|
|
96
|
+
}
|
|
97
|
+
const remaining = deadline - Date.now();
|
|
98
|
+
if (remaining <= 0)
|
|
99
|
+
return { exitCode: 3, runs: entries, timedOut: true };
|
|
100
|
+
await sleep(Math.min(options.pollMs ?? DEFAULT_POLL_MS, remaining));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const LOG_TYPES = new Set(['text', 'tool-call', 'tool-result', 'step-start', 'error', 'user-message']);
|
|
104
|
+
function clip(value) {
|
|
105
|
+
if (value === undefined)
|
|
106
|
+
return undefined;
|
|
107
|
+
const text = typeof value === 'string' ? value : JSON.stringify(value);
|
|
108
|
+
return text.length > MAX_FIELD_CHARS ? `${text.slice(0, MAX_FIELD_CHARS - 1)}…` : text;
|
|
109
|
+
}
|
|
110
|
+
/** One printable line per event the log keeps, or undefined for the rest. */
|
|
111
|
+
export function logLine(event) {
|
|
112
|
+
if (!LOG_TYPES.has(event.type))
|
|
113
|
+
return undefined;
|
|
114
|
+
const fields = {
|
|
115
|
+
seq: event.seq,
|
|
116
|
+
ts: event.ts,
|
|
117
|
+
type: event.type,
|
|
118
|
+
...(event.stepId === undefined ? {} : { stepId: event.stepId }),
|
|
119
|
+
};
|
|
120
|
+
switch (event.type) {
|
|
121
|
+
case 'text':
|
|
122
|
+
case 'user-message':
|
|
123
|
+
fields.text = clip(event.text);
|
|
124
|
+
break;
|
|
125
|
+
case 'tool-call':
|
|
126
|
+
fields.tool = event.tool;
|
|
127
|
+
fields.input = clip(event.input);
|
|
128
|
+
break;
|
|
129
|
+
case 'tool-result':
|
|
130
|
+
fields.result = clip(event.result);
|
|
131
|
+
break;
|
|
132
|
+
case 'step-start':
|
|
133
|
+
fields.name = event.name;
|
|
134
|
+
if (event.iteration !== undefined)
|
|
135
|
+
fields.iteration = event.iteration;
|
|
136
|
+
break;
|
|
137
|
+
case 'error':
|
|
138
|
+
fields.message = clip(event.message);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
return Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));
|
|
142
|
+
}
|
|
143
|
+
/** Keeps the newest lines within `maxChars` (counting the newline between lines). */
|
|
144
|
+
class LineTail {
|
|
145
|
+
maxChars;
|
|
146
|
+
lines = [];
|
|
147
|
+
size = 0;
|
|
148
|
+
constructor(maxChars) {
|
|
149
|
+
this.maxChars = maxChars;
|
|
150
|
+
}
|
|
151
|
+
push(line) {
|
|
152
|
+
this.lines.push(line);
|
|
153
|
+
this.size += line.length + (this.lines.length > 1 ? 1 : 0);
|
|
154
|
+
while (this.size > this.maxChars && this.lines.length) {
|
|
155
|
+
const dropped = this.lines.shift();
|
|
156
|
+
this.size -= dropped.length + (this.lines.length ? 1 : 0);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
drain() {
|
|
160
|
+
const lines = this.lines;
|
|
161
|
+
this.lines = [];
|
|
162
|
+
this.size = 0;
|
|
163
|
+
return lines;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** Minimal SSE framing: `event:` / `data:` fields, blank-line separated. */
|
|
167
|
+
async function* sseFrames(body) {
|
|
168
|
+
const decoder = new TextDecoder();
|
|
169
|
+
let buffer = '';
|
|
170
|
+
for await (const chunk of body) {
|
|
171
|
+
buffer += decoder.decode(chunk, { stream: true }).replace(/\r\n/g, '\n');
|
|
172
|
+
let boundary;
|
|
173
|
+
while ((boundary = buffer.indexOf('\n\n')) >= 0) {
|
|
174
|
+
const block = buffer.slice(0, boundary);
|
|
175
|
+
buffer = buffer.slice(boundary + 2);
|
|
176
|
+
let event = 'message';
|
|
177
|
+
const data = [];
|
|
178
|
+
for (const line of block.split('\n')) {
|
|
179
|
+
if (line.startsWith('event:'))
|
|
180
|
+
event = line.slice(6).trim();
|
|
181
|
+
else if (line.startsWith('data:'))
|
|
182
|
+
data.push(line.slice(5).replace(/^ /, ''));
|
|
183
|
+
}
|
|
184
|
+
yield { event, data: data.join('\n') };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* `log`, read from the run's SSE stream, which replays every event after `afterSeq` and then
|
|
190
|
+
* streams live. The route subscribes to live `run` updates BEFORE it replays, so a `run` frame
|
|
191
|
+
* says nothing about where the replay is; the only reliable boundary is a `seq`. So:
|
|
192
|
+
*
|
|
193
|
+
* - the replay ends at `asOfSeq`, the event file's high-water mark read from `GET /history` just
|
|
194
|
+
* before connecting — everything up to it is the tail, bounded to `maxChars`, and without
|
|
195
|
+
* `follow` the command ends there;
|
|
196
|
+
* - with `follow`, a terminal status ends the command only once the stream has caught up with a
|
|
197
|
+
* SECOND high-water read taken after that status arrived, so events the engine wrote just
|
|
198
|
+
* before finishing are not dropped when the status frame overtakes them (exit 0/1, final line
|
|
199
|
+
* is the status).
|
|
200
|
+
*
|
|
201
|
+
* One `deadline` bounds every request, the history reads included (exit 3). Deduped by `seq`.
|
|
202
|
+
* The stream rather than `GET /history` pages: a history page starts at its first transcript
|
|
203
|
+
* item, so it drops lifecycle events such as the opening `step-start`.
|
|
204
|
+
*/
|
|
205
|
+
export async function readLog(cockpit, id, options) {
|
|
206
|
+
const tail = new LineTail(options.maxChars);
|
|
207
|
+
const remaining = () => options.deadline - Date.now();
|
|
208
|
+
let lastSeq = options.afterSeq;
|
|
209
|
+
let seenSeq = options.afterSeq;
|
|
210
|
+
let status;
|
|
211
|
+
let drainSeq;
|
|
212
|
+
/** The event file's high-water mark, or undefined once the deadline has passed. */
|
|
213
|
+
const highWater = async () => {
|
|
214
|
+
const budget = remaining();
|
|
215
|
+
if (budget <= 0)
|
|
216
|
+
return undefined;
|
|
217
|
+
const startedAt = Date.now();
|
|
218
|
+
let history;
|
|
219
|
+
try {
|
|
220
|
+
history = await request(cockpit, `/runs/${encodeURIComponent(id)}/history`, { timeoutMs: budget });
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
if (remaining() <= 0)
|
|
224
|
+
return undefined;
|
|
225
|
+
if (abortedPoll(error) && pollHitDeadline(startedAt, budget))
|
|
226
|
+
return undefined;
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
if (history.status !== 200)
|
|
230
|
+
refuse(history);
|
|
231
|
+
const page = runHistoryPageSchema.safeParse(history.data);
|
|
232
|
+
return page.success ? page.data.asOfSeq : invalidResponse('history');
|
|
233
|
+
};
|
|
234
|
+
const boundarySeq = await highWater();
|
|
235
|
+
if (boundarySeq === undefined)
|
|
236
|
+
return timedOut();
|
|
237
|
+
let replaying = boundarySeq > options.afterSeq;
|
|
238
|
+
if (!replaying && !options.follow)
|
|
239
|
+
return 0;
|
|
240
|
+
const controller = new AbortController();
|
|
241
|
+
const timer = setTimeout(() => controller.abort(), Math.max(remaining(), 0));
|
|
242
|
+
try {
|
|
243
|
+
let response;
|
|
244
|
+
try {
|
|
245
|
+
response = await fetch(`${cockpit.api}/runs/${encodeURIComponent(id)}/events?afterSeq=${lastSeq}`, {
|
|
246
|
+
redirect: 'error', signal: controller.signal, headers: { accept: 'text/event-stream' },
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
if (controller.signal.aborted)
|
|
251
|
+
return timedOut();
|
|
252
|
+
throw new TaskCliError(2, { code: 'unavailable', error: `cockpit request failed: ${error instanceof Error ? error.message : String(error)}` });
|
|
253
|
+
}
|
|
254
|
+
if (!response.ok || !response.body) {
|
|
255
|
+
const text = await response.text().catch(() => '');
|
|
256
|
+
let data = text;
|
|
257
|
+
try {
|
|
258
|
+
data = JSON.parse(text);
|
|
259
|
+
}
|
|
260
|
+
catch { /* not JSON */ }
|
|
261
|
+
refuse({ status: response.status, data });
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
for await (const frame of sseFrames(response.body)) {
|
|
265
|
+
if (frame.event === 'run-event' || frame.event === 'ui-event') {
|
|
266
|
+
const event = JSON.parse(frame.data);
|
|
267
|
+
if (typeof event.seq !== 'number')
|
|
268
|
+
continue;
|
|
269
|
+
// Both streams share the file's seq space, so either one can reach a boundary;
|
|
270
|
+
// only v1 lines are printed, deduped by seq.
|
|
271
|
+
seenSeq = Math.max(seenSeq, event.seq);
|
|
272
|
+
if (frame.event === 'run-event' && event.seq > lastSeq) {
|
|
273
|
+
lastSeq = event.seq;
|
|
274
|
+
const line = logLine(event);
|
|
275
|
+
if (line) {
|
|
276
|
+
if (replaying)
|
|
277
|
+
tail.push(JSON.stringify(line));
|
|
278
|
+
else
|
|
279
|
+
options.print(JSON.stringify(line));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else if (frame.event === 'run') {
|
|
284
|
+
const run = runRecordSchema.safeParse(JSON.parse(frame.data));
|
|
285
|
+
if (run.success)
|
|
286
|
+
status = run.data.status;
|
|
287
|
+
}
|
|
288
|
+
let exit = step();
|
|
289
|
+
if (exit === 'drain') {
|
|
290
|
+
drainSeq = await highWater();
|
|
291
|
+
if (drainSeq === undefined)
|
|
292
|
+
return timedOut();
|
|
293
|
+
exit = step();
|
|
294
|
+
}
|
|
295
|
+
if (typeof exit === 'number')
|
|
296
|
+
return exit;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
if (!controller.signal.aborted)
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
if (controller.signal.aborted)
|
|
304
|
+
return timedOut();
|
|
305
|
+
throw new TaskCliError(2, { code: 'unavailable', error: 'the cockpit closed the event stream' });
|
|
306
|
+
}
|
|
307
|
+
finally {
|
|
308
|
+
clearTimeout(timer);
|
|
309
|
+
controller.abort();
|
|
310
|
+
}
|
|
311
|
+
/** Ends the replay at its boundary; then a terminal status ends the command once drained. */
|
|
312
|
+
function step() {
|
|
313
|
+
if (replaying && seenSeq >= boundarySeq) {
|
|
314
|
+
replaying = false;
|
|
315
|
+
for (const line of tail.drain())
|
|
316
|
+
options.print(line);
|
|
317
|
+
if (!options.follow)
|
|
318
|
+
return 0;
|
|
319
|
+
}
|
|
320
|
+
if (replaying || status === undefined || !TERMINAL_STATUSES.includes(status))
|
|
321
|
+
return undefined;
|
|
322
|
+
if (drainSeq === undefined)
|
|
323
|
+
return 'drain';
|
|
324
|
+
if (seenSeq < drainSeq)
|
|
325
|
+
return undefined;
|
|
326
|
+
options.print(JSON.stringify({ id, status, timedOut: false }));
|
|
327
|
+
return SUCCESS_STATUSES.includes(status) ? 0 : 1;
|
|
328
|
+
}
|
|
329
|
+
function timedOut() {
|
|
330
|
+
for (const line of tail.drain())
|
|
331
|
+
options.print(line);
|
|
332
|
+
options.print(JSON.stringify({ id, ...(status === undefined ? {} : { status }), timedOut: true }));
|
|
333
|
+
return 3;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/task-cli/watch.ts"],"names":[],"mappings":"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"}
|
package/dist/workflows/run.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export type DelegationExecutionSettings = {
|
|
|
37
37
|
cwd: string;
|
|
38
38
|
runner: RunnerId;
|
|
39
39
|
model?: string;
|
|
40
|
+
modelIdentity?: string;
|
|
40
41
|
effort?: string;
|
|
41
42
|
agentProfile: string;
|
|
42
43
|
accountBinding?: WorkerAccountBinding;
|
|
@@ -44,6 +45,10 @@ export type DelegationExecutionSettings = {
|
|
|
44
45
|
allowedTools?: string[];
|
|
45
46
|
bashAllowlist?: string[];
|
|
46
47
|
};
|
|
48
|
+
/** Safety cap on autonomous auto-continues per run — stops a stuck agent from nudging forever. */
|
|
49
|
+
/** #505: a real steer is read at the harness's next model step; a quiet boundary this long
|
|
50
|
+
* with input still unread means the harness will not read it without help. */
|
|
51
|
+
export declare const UNREAD_INPUT_GRACE_MS = 30000;
|
|
47
52
|
/**
|
|
48
53
|
* Auto-resume after a provider usage limit (spec 2026-08-03-auto-resume-after-usage-limit).
|
|
49
54
|
*
|
|
@@ -114,6 +119,8 @@ export interface StartRunInput {
|
|
|
114
119
|
* user — turn-ends auto-continue until the agent signals done or the safety
|
|
115
120
|
* cap is hit. No "needs you" is ever raised. */
|
|
116
121
|
autonomous?: boolean;
|
|
122
|
+
/** Task webhook opt-in (#589). Persisted on the record at creation; read from there after. */
|
|
123
|
+
notify?: boolean;
|
|
117
124
|
/** Follow-up inbox generation (spec 007, #444). Omitted means enabled for
|
|
118
125
|
* compatibility; the handoff journal runs either way. */
|
|
119
126
|
generateFollowups?: boolean;
|
|
@@ -213,6 +220,16 @@ export declare function pastedAttachmentsNote(attachments: PersistedAttachment[]
|
|
|
213
220
|
export declare const VARIANT_LETTERS: readonly ['A', 'B', 'C'];
|
|
214
221
|
/** Only an original workflow that has never executed may return to its queue. */
|
|
215
222
|
export declare function isUntouchedCancelledRun(run: RunRecord): boolean;
|
|
223
|
+
/** #469: why destroy could not prove a crashed generation's termination. */
|
|
224
|
+
export type WorkerTerminationBlocker = {
|
|
225
|
+
kind: 'unreadable';
|
|
226
|
+
} | {
|
|
227
|
+
kind: 'controller';
|
|
228
|
+
pid: number;
|
|
229
|
+
} | {
|
|
230
|
+
kind: 'processes';
|
|
231
|
+
pids: number[];
|
|
232
|
+
};
|
|
216
233
|
/**
|
|
217
234
|
* The mini workflow engine: executes a `WorkflowDef` against a repo, one step
|
|
218
235
|
* at a time, persisting every event to the RunStore (which the SSE endpoints
|
|
@@ -242,9 +259,53 @@ export declare class RunManager {
|
|
|
242
259
|
* exception or an interrupt request cannot stand in for session termination. */
|
|
243
260
|
private trackWorkerSessionResult;
|
|
244
261
|
private persistWorkerCompletion;
|
|
262
|
+
/** #469: the generation a dead controller left `starting`, if this manager may judge it. A
|
|
263
|
+
* generation this process controls is never judged here: the in-memory execution map owns it,
|
|
264
|
+
* and a disposed manager's still-running sessions look like orphans. `busy` is transient (this
|
|
265
|
+
* manager holds the run); `unknown` is a present record that proves nothing. */
|
|
266
|
+
private orphanState;
|
|
267
|
+
private orphanedWorkerGeneration;
|
|
268
|
+
/** Completes a crashed generation's proof once every one of its processes is proven gone (#469).
|
|
269
|
+
* Sync and signal-free; recovery, resume, delivery, collect and destroy then take their normal paths.
|
|
270
|
+
* A non-gone probe is cached briefly: on darwin the scan is a synchronous `lsof` on the event loop. */
|
|
271
|
+
settleOrphanedWorkerExecution(runId: string, opts?: {
|
|
272
|
+
admitting?: boolean;
|
|
273
|
+
fresh?: boolean;
|
|
274
|
+
}): boolean;
|
|
275
|
+
private readonly orphanProbes;
|
|
276
|
+
private readonly orphanReprobes;
|
|
277
|
+
private readonly orphanBlockers;
|
|
278
|
+
private readonly reportedOrphanBlockers;
|
|
279
|
+
private orphanReprobeMs;
|
|
280
|
+
private orphanReprobeLimitMs;
|
|
281
|
+
private orphanReprobeSlowMs;
|
|
282
|
+
private orphanTermGraceMs;
|
|
283
|
+
/** #469: a survivor that dies after recovery has no other wake source (no exit callback for a
|
|
284
|
+
* process another cezar spawned). Unref'd; finalization's `run` event then lets worker waits and
|
|
285
|
+
* outcomes observe it. Fast for the first window, then slow but uncapped, so a long-lived
|
|
286
|
+
* survivor is still noticed when it exits. A tick while this manager holds the run is skipped;
|
|
287
|
+
* only terminal reasons (proof settled, generation changed, run gone, unknown record, dispose)
|
|
288
|
+
* stop it. */
|
|
289
|
+
private armOrphanReprobe;
|
|
290
|
+
private clearOrphanReprobe;
|
|
291
|
+
/** Why the last destroy could not prove termination (#469), and whether that differs from the
|
|
292
|
+
* reason last reported, so a retry loop appends one lifecycle event per distinct blocker set. */
|
|
293
|
+
takeWorkerTerminationBlocker(runId: string): {
|
|
294
|
+
blocker: WorkerTerminationBlocker;
|
|
295
|
+
changed: boolean;
|
|
296
|
+
} | undefined;
|
|
297
|
+
/** Continue over a live orphan names what still runs; other refusals keep the generic text. */
|
|
298
|
+
private orphanAdmissionRefusal;
|
|
299
|
+
/** Destroy only (#469): signal the recorded, token-verified survivors of a generation whose
|
|
300
|
+
* controller is proven dead, then finalize on `gone`. Scan-only processes are never signalled. */
|
|
301
|
+
private reapOrphanedWorker;
|
|
302
|
+
/** Best effort: a failed write leaves the working-directory scan as this process's evidence. */
|
|
303
|
+
private recordWorkerProcess;
|
|
245
304
|
private trackTurnEnd;
|
|
246
305
|
requestWorkerStop(runId: string): WorkerStopResult;
|
|
247
|
-
awaitRunTermination(runId: string, timeoutMs: number
|
|
306
|
+
awaitRunTermination(runId: string, timeoutMs: number, opts?: {
|
|
307
|
+
reapOrphans?: boolean;
|
|
308
|
+
}): Promise<boolean>;
|
|
248
309
|
/** Private cleanup capability, never serialized. Obtain after stop/termination
|
|
249
310
|
* under the service's destroy lock; each invocation rechecks the same generation. */
|
|
250
311
|
getWorkerNoMaterializationProof(runId: string): WorkerNoMaterializationProof | undefined;
|
|
@@ -267,8 +328,11 @@ export declare class RunManager {
|
|
|
267
328
|
private readonly workerWakeAdmitted;
|
|
268
329
|
private readonly workerWakeQueuedAt;
|
|
269
330
|
private readonly workerWaitTimers;
|
|
331
|
+
private readonly inboxClaimTimers;
|
|
270
332
|
private reconcilingWorkers;
|
|
271
333
|
private recovering;
|
|
334
|
+
/** Quiet window before unread input is resubmitted or left unconfirmed (#505). */
|
|
335
|
+
private readonly unreadInputGraceMs;
|
|
272
336
|
private disposed;
|
|
273
337
|
private readonly onDelegationRun;
|
|
274
338
|
private readonly pendingJobs;
|
|
@@ -328,6 +392,7 @@ export declare class RunManager {
|
|
|
328
392
|
private readonly offSemaphore;
|
|
329
393
|
constructor(store: RunStore, repoRoot: string, options?: {
|
|
330
394
|
semaphore?: WorkspaceSemaphore;
|
|
395
|
+
unreadInputGraceMs?: number;
|
|
331
396
|
});
|
|
332
397
|
/**
|
|
333
398
|
* Release everything this manager owns without touching run records
|
|
@@ -432,10 +497,27 @@ export declare class RunManager {
|
|
|
432
497
|
model?: string;
|
|
433
498
|
effort?: string;
|
|
434
499
|
agentProfile?: string;
|
|
435
|
-
}): Promise<DelegationExecutionSettings>;
|
|
500
|
+
}, validateModel?: (settings: DelegationExecutionSettings) => Promise<void>): Promise<DelegationExecutionSettings>;
|
|
501
|
+
/**
|
|
502
|
+
* Idempotent start (#504, spec 2026-09-24-cez-task-cli). Lookup and create share one
|
|
503
|
+
* synchronous path, so the event loop serialises concurrent retries: the first creates, every
|
|
504
|
+
* later one with the same hash gets that run back, and a different hash is a conflict.
|
|
505
|
+
*/
|
|
506
|
+
startRunIdempotent(workflow: WorkflowDef, input: StartRunInput, request: {
|
|
507
|
+
id: string;
|
|
508
|
+
hash: string;
|
|
509
|
+
}): {
|
|
510
|
+
run: RunRecord;
|
|
511
|
+
created: boolean;
|
|
512
|
+
} | {
|
|
513
|
+
conflict: true;
|
|
514
|
+
};
|
|
436
515
|
startRun(workflow: WorkflowDef, input: StartRunInput, group?: {
|
|
437
516
|
groupId: string;
|
|
438
517
|
variant: string;
|
|
518
|
+
}, clientRequest?: {
|
|
519
|
+
id: string;
|
|
520
|
+
hash: string;
|
|
439
521
|
}): RunRecord;
|
|
440
522
|
/** Accept only the store's already-durable owned creation, never caller-supplied paths/workflows. */
|
|
441
523
|
enqueueOwnedRun(runId: string): void;
|
|
@@ -749,8 +831,43 @@ export declare class RunManager {
|
|
|
749
831
|
private hasUnansweredHumanAsk;
|
|
750
832
|
/** Both roles can select their own requests without acquiring worker-management authority. */
|
|
751
833
|
registerRequestWait(runId: string, request: RequestWaitRequest): WorkerWait;
|
|
834
|
+
/** A wait wake is only a pointer. Only provider submission/opening prompts own delivery. */
|
|
835
|
+
private providerOwnsInboxInput;
|
|
836
|
+
canClaimInboxInput(runId: string, id: string): boolean;
|
|
837
|
+
/** The service supplies authorized, bounded IDs; claim and flight reservations are synchronous. */
|
|
838
|
+
reserveInboxInputs(runId: string, generation: string, ids: readonly string[]): {
|
|
839
|
+
receiptId: string;
|
|
840
|
+
expiresAt: string;
|
|
841
|
+
inputIds: string[];
|
|
842
|
+
} | undefined;
|
|
843
|
+
acknowledgeInbox(runId: string, generation: string, receiptId: string): 'acknowledged' | 'already-acknowledged';
|
|
844
|
+
releaseInbox(runId: string, generation: string, receiptId: string): 'released';
|
|
845
|
+
/** Expiry is an independent wake source, including after the provider's last turn. */
|
|
846
|
+
private armInboxClaimExpiry;
|
|
752
847
|
/** Accepted conversation input uses the existing scheduler admission for idle recipients. */
|
|
753
848
|
deliverConversationInput(runId: string): void;
|
|
849
|
+
/** A worker's pending question goes to its owning parent as a conversation request
|
|
850
|
+
* (#505). The worker still parks on its ask; only the parent's reply, or a human after
|
|
851
|
+
* fallback, answers it. Routing is idempotent: the message ID derives from the ask seq. */
|
|
852
|
+
private routeWorkerQuestion;
|
|
853
|
+
/** A human answering a worker question its parent handed back (#505): the reviewing parent
|
|
854
|
+
* can no longer answer it, so it must not also block the human. */
|
|
855
|
+
private answersFallenBackAsk;
|
|
856
|
+
/** The worker's pending ask when it went to the parent and has not fallen back to a human. */
|
|
857
|
+
private routedAsk;
|
|
858
|
+
/** The parent's reply answers the routed question like a human answer would: through the
|
|
859
|
+
* live session's native answer seam, or by reopening a session that is gone (#505). */
|
|
860
|
+
private answerRoutedQuestion;
|
|
861
|
+
/** A routed question settled without a reply (its worker stopped, a deadline, fallback) can
|
|
862
|
+
* never be answered by the parent any more: hand it to the human on the worker (#505). */
|
|
863
|
+
private retireSettledQuestions;
|
|
864
|
+
/** Routed questions this parent has not answered yet, by asking worker. */
|
|
865
|
+
private unansweredQuestions;
|
|
866
|
+
/** The parent can no longer answer: its workers' routed questions go back to the human
|
|
867
|
+
* (#505). The outcome lands first, so a crash before the worker's event repeats this. */
|
|
868
|
+
private fallbackRoutedQuestions;
|
|
869
|
+
/** The parent can still read and answer a routed question; answering needs its steer grant. */
|
|
870
|
+
private parentCanReceive;
|
|
754
871
|
/** Cancel only the wait; persist its settlement before ordinary wake admission. */
|
|
755
872
|
cancelWorkerWait(parentId: string, waitId: string): WorkerWait;
|
|
756
873
|
private workerWait;
|
|
@@ -777,6 +894,37 @@ export declare class RunManager {
|
|
|
777
894
|
/** Accepted input may be temporarily refused while a backend HTTP ack is
|
|
778
895
|
* outstanding. That is not an empty queue and must not trigger automatic DONE. */
|
|
779
896
|
private hasQueuedAgentInputs;
|
|
897
|
+
/** Only the current session's observation writes consumedAt (#505). An ID reported
|
|
898
|
+
* before its acceptance checkpoint lands is applied when that checkpoint commits. */
|
|
899
|
+
private handleAgentInputConsumed;
|
|
900
|
+
/** #505: input the harness accepted but will never read returns to the queue, so
|
|
901
|
+
* DONE, auto-end and park see queued work. Out of a turn (an OpenCode lost wake)
|
|
902
|
+
* it is submitted right away; at a turn-end the handler's own flush submits it. */
|
|
903
|
+
private retireUnreadInputs;
|
|
904
|
+
/** #505: the harness started the opening turn, so the opening input was accepted.
|
|
905
|
+
* Its replay-prompt retirement still waits for that turn's successful end. */
|
|
906
|
+
private recordOpeningAccepted;
|
|
907
|
+
/** The conversation messages the next submission would carry, if nothing but
|
|
908
|
+
* conversation input leads the queue (lifecycle input stays a barrier). */
|
|
909
|
+
private pendingConversationBatch;
|
|
910
|
+
/** Bundled messages rode the answer's own write: delivered now, read when that turn ends. */
|
|
911
|
+
private commitBundledDelivery;
|
|
912
|
+
/** The turn that carried bundled messages has ended: the model read them. */
|
|
913
|
+
private readBundledInputs;
|
|
914
|
+
/** #505: the session closed without reporting it read (failure, stop, exit): the input
|
|
915
|
+
* goes back to the queue so a later session delivers it; never shown as delivered. */
|
|
916
|
+
private requeueUnreadAtClose;
|
|
917
|
+
/** An idle, open boundary with nothing left to deliver: DONE closes, otherwise the
|
|
918
|
+
* run parks as waiting or monitoring. Shared by acknowledgements that land after a
|
|
919
|
+
* turn ended and by the unread-input grace timer (#505). */
|
|
920
|
+
private settleIdleBoundary;
|
|
921
|
+
/** #505 liveness bound: a harness that accepted input and then neither read it nor ran
|
|
922
|
+
* another turn must not hold the run and its slot forever. After a quiet grace window the
|
|
923
|
+
* input is resubmitted once; after a second it is left delivered but unconfirmed. */
|
|
924
|
+
private armUnreadInputTimer;
|
|
925
|
+
private clearUnreadInputTimer;
|
|
926
|
+
/** #505: the harness accepted input this session has not reported reading yet. */
|
|
927
|
+
private harnessOwesInput;
|
|
780
928
|
/** A callback from an old/replaced/disposed session carries no authority. */
|
|
781
929
|
private handleAgentInputReady;
|
|
782
930
|
/** Reservation is synchronous; only an acknowledged transport may checkpoint delivery. */
|
|
@@ -811,6 +959,11 @@ export declare class RunManager {
|
|
|
811
959
|
private waitingBeforeFinalWorkflowStep;
|
|
812
960
|
/** Locate the original workflow step whose closed session a synthetic Continue is resuming. */
|
|
813
961
|
private waitingWorkflowStepIndex;
|
|
962
|
+
/**
|
|
963
|
+
* Session ids Cursor will accept on `session/load`. A launch UUID written
|
|
964
|
+
* before `session.started` is only for the step rail (#583).
|
|
965
|
+
*/
|
|
966
|
+
private resumableSessionId;
|
|
814
967
|
/**
|
|
815
968
|
* "Continue" (spec 003): reopen a finished run's claude session in-process
|
|
816
969
|
* (`claude --resume <sessionId>`) as a new synthetic step. The session then
|
|
@@ -829,6 +982,8 @@ export declare class RunManager {
|
|
|
829
982
|
/** Agent account for the reopened session (spec 2026-07-29-agent-profiles). Omitted = the
|
|
830
983
|
* account the run is already on. */
|
|
831
984
|
agentProfile?: string;
|
|
985
|
+
/** #505: the parent reply this continuation delivers as the answer to a routed question. */
|
|
986
|
+
answerInputId?: string;
|
|
832
987
|
},
|
|
833
988
|
/** Restart recovery may discover several interrupted tasks at once. Those
|
|
834
989
|
* continuations are queued; an explicit user Continue remains immediate. */
|
|
@@ -862,6 +1017,9 @@ export declare class RunManager {
|
|
|
862
1017
|
/** Persist the invocation checkpoint before launching a runner. A throw or
|
|
863
1018
|
* process exit before `turn.started` therefore leaves a durable mismatch. */
|
|
864
1019
|
private beginUsageInvocation;
|
|
1020
|
+
/** Claude's `total_cost_usd` is cumulative for the conversation, including
|
|
1021
|
+
* turns in Continue steps. Other runners emit per-message cost deltas. */
|
|
1022
|
+
private recordReportedCost;
|
|
865
1023
|
/** Fold backend-neutral completed-turn usage into the current step exactly
|
|
866
1024
|
* once. Invocation/turn counters are written before the event reaches the
|
|
867
1025
|
* NDJSON sink so crashes cannot preserve a falsely complete subtotal. */
|