visionclaw 0.1.219-dev.codex-issue-2805-worker-runtime.3 → 0.1.219-dev.codex-2941-task-board-on-main.1
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/dist/agent/browser-launcher.d.ts +19 -1
- package/dist/agent/browser-launcher.d.ts.map +1 -1
- package/dist/agent/browser-launcher.js +40 -0
- package/dist/agent/browser-launcher.js.map +1 -1
- package/dist/agent/command-handlers.js +2 -2
- package/dist/agent/command-handlers.js.map +1 -1
- package/dist/agent/engines/claude/session.d.ts +6 -0
- package/dist/agent/engines/claude/session.d.ts.map +1 -1
- package/dist/agent/engines/claude/session.js +34 -2
- package/dist/agent/engines/claude/session.js.map +1 -1
- package/dist/agent/engines/pi/tools.d.ts.map +1 -1
- package/dist/agent/engines/pi/tools.js +2 -1
- package/dist/agent/engines/pi/tools.js.map +1 -1
- package/dist/agent/fund-league-hold.d.ts.map +1 -1
- package/dist/agent/fund-league-hold.js +5 -1
- package/dist/agent/fund-league-hold.js.map +1 -1
- package/dist/agent/interrupt-handler.d.ts.map +1 -1
- package/dist/agent/interrupt-handler.js +4 -1
- package/dist/agent/interrupt-handler.js.map +1 -1
- package/dist/agent/lifecycle-trace.d.ts +3 -2
- package/dist/agent/lifecycle-trace.d.ts.map +1 -1
- package/dist/agent/lifecycle-trace.js +4 -9
- package/dist/agent/lifecycle-trace.js.map +1 -1
- package/dist/agent/lifecycle-transitions.d.ts +42 -0
- package/dist/agent/lifecycle-transitions.d.ts.map +1 -1
- package/dist/agent/lifecycle-transitions.js +62 -6
- package/dist/agent/lifecycle-transitions.js.map +1 -1
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +99 -27
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/public-activity.d.ts +1 -1
- package/dist/agent/public-activity.d.ts.map +1 -1
- package/dist/agent/public-activity.js.map +1 -1
- package/dist/agent/runtime-context.d.ts +2 -0
- package/dist/agent/runtime-context.d.ts.map +1 -1
- package/dist/agent/runtime-context.js +4 -0
- package/dist/agent/runtime-context.js.map +1 -1
- package/dist/agent/service-gate.d.ts.map +1 -1
- package/dist/agent/service-gate.js +4 -1
- package/dist/agent/service-gate.js.map +1 -1
- package/dist/agent/state.d.ts +14 -0
- package/dist/agent/state.d.ts.map +1 -1
- package/dist/agent/state.js +13 -5
- package/dist/agent/state.js.map +1 -1
- package/dist/agent/status.d.ts.map +1 -1
- package/dist/agent/status.js +4 -1
- package/dist/agent/status.js.map +1 -1
- package/dist/agent/system-prompt.d.ts.map +1 -1
- package/dist/agent/system-prompt.js +11 -1
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/agent/tool-call-watchdog.d.ts +7 -0
- package/dist/agent/tool-call-watchdog.d.ts.map +1 -1
- package/dist/agent/tool-call-watchdog.js +32 -2
- package/dist/agent/tool-call-watchdog.js.map +1 -1
- package/dist/agent/wake-cycle-runner.d.ts +11 -0
- package/dist/agent/wake-cycle-runner.d.ts.map +1 -1
- package/dist/agent/wake-cycle-runner.js +42 -9
- package/dist/agent/wake-cycle-runner.js.map +1 -1
- package/dist/channels/interface.d.ts +18 -0
- package/dist/channels/interface.d.ts.map +1 -1
- package/dist/channels/interface.js.map +1 -1
- package/dist/channels/qq-status.d.ts.map +1 -1
- package/dist/channels/qq-status.js +1 -0
- package/dist/channels/qq-status.js.map +1 -1
- package/dist/channels/telegram-status.d.ts +22 -4
- package/dist/channels/telegram-status.d.ts.map +1 -1
- package/dist/channels/telegram-status.js +216 -39
- package/dist/channels/telegram-status.js.map +1 -1
- package/dist/channels/telegram-task-board.d.ts +79 -0
- package/dist/channels/telegram-task-board.d.ts.map +1 -0
- package/dist/channels/telegram-task-board.js +384 -0
- package/dist/channels/telegram-task-board.js.map +1 -0
- package/dist/channels/telegram.d.ts +6 -1
- package/dist/channels/telegram.d.ts.map +1 -1
- package/dist/channels/telegram.js +31 -2
- package/dist/channels/telegram.js.map +1 -1
- package/dist/i18n/messages.d.ts +248 -0
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/i18n/messages.js +79 -13
- package/dist/i18n/messages.js.map +1 -1
- package/dist/obs/tunnel.d.ts +9 -1
- package/dist/obs/tunnel.d.ts.map +1 -1
- package/dist/obs/tunnel.js +121 -54
- package/dist/obs/tunnel.js.map +1 -1
- package/dist/stt-client.d.ts +10 -0
- package/dist/stt-client.d.ts.map +1 -1
- package/dist/stt-client.js +64 -31
- package/dist/stt-client.js.map +1 -1
- package/dist/threads/foreground-task.d.ts +10 -2
- package/dist/threads/foreground-task.d.ts.map +1 -1
- package/dist/threads/foreground-task.js +18 -3
- package/dist/threads/foreground-task.js.map +1 -1
- package/dist/threads/foreman-host.d.ts +13 -1
- package/dist/threads/foreman-host.d.ts.map +1 -1
- package/dist/threads/foreman-host.js +79 -7
- package/dist/threads/foreman-host.js.map +1 -1
- package/dist/threads/foreman-protocol.d.ts +2 -0
- package/dist/threads/foreman-protocol.d.ts.map +1 -1
- package/dist/threads/foreman-protocol.js +3 -1
- package/dist/threads/foreman-protocol.js.map +1 -1
- package/dist/threads/process-group.js +7 -2
- package/dist/threads/process-group.js.map +1 -1
- package/dist/threads/relay-adapter.d.ts +2 -0
- package/dist/threads/relay-adapter.d.ts.map +1 -1
- package/dist/threads/relay-adapter.js +6 -0
- package/dist/threads/relay-adapter.js.map +1 -1
- package/dist/threads/task-settlement.d.ts +17 -0
- package/dist/threads/task-settlement.d.ts.map +1 -0
- package/dist/threads/task-settlement.js +34 -0
- package/dist/threads/task-settlement.js.map +1 -0
- package/dist/threads/thread-activity-controller.d.ts +21 -0
- package/dist/threads/thread-activity-controller.d.ts.map +1 -1
- package/dist/threads/thread-activity-controller.js +111 -3
- package/dist/threads/thread-activity-controller.js.map +1 -1
- package/dist/tools/browser-health.d.ts +2 -0
- package/dist/tools/browser-health.d.ts.map +1 -0
- package/dist/tools/browser-health.js +18 -0
- package/dist/tools/browser-health.js.map +1 -0
- package/dist/tools/browser-set-engine.js +1 -1
- package/dist/tools/browser-set-engine.js.map +1 -1
- package/dist/tools/delegation.d.ts +7 -0
- package/dist/tools/delegation.d.ts.map +1 -1
- package/dist/tools/delegation.js +30 -3
- package/dist/tools/delegation.js.map +1 -1
- package/dist/tools/fund-league.d.ts +4 -0
- package/dist/tools/fund-league.d.ts.map +1 -1
- package/dist/tools/fund-league.js +1 -1
- package/dist/tools/fund-league.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/upgrade.d.ts +2 -1
- package/dist/tools/upgrade.d.ts.map +1 -1
- package/dist/tools/upgrade.js +26 -8
- package/dist/tools/upgrade.js.map +1 -1
- package/dist/utils/restart.d.ts +6 -0
- package/dist/utils/restart.d.ts.map +1 -1
- package/dist/utils/restart.js +7 -1
- package/dist/utils/restart.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +19 -9
- package/dist/utils/version-check.js.map +1 -1
- package/dist-agent/bundle.cjs +2 -2
- package/package.json +1 -1
|
@@ -39,6 +39,7 @@ export type ForegroundPhase = "Idle" | "Running" | "Recovering" | "Stopping";
|
|
|
39
39
|
* only after that release.
|
|
40
40
|
*/
|
|
41
41
|
export declare function endForegroundWake(input: {
|
|
42
|
+
readonly state?: LifecyclePublication;
|
|
42
43
|
readonly from: Exclude<ForegroundPhase, "Idle" | "Stopping">;
|
|
43
44
|
readonly cleanup: () => void;
|
|
44
45
|
readonly release: () => void;
|
|
@@ -79,13 +80,54 @@ export declare function nextRecoveryPhase(input: {
|
|
|
79
80
|
readonly bucket: RecoveryBucket;
|
|
80
81
|
readonly spent: number;
|
|
81
82
|
}): "Recovering" | "Stopping";
|
|
83
|
+
/**
|
|
84
|
+
* The published lifecycle plus whether the host entry is held without an
|
|
85
|
+
* engine receipt. `entryHeld` is not a sixth state: Gated still requires the
|
|
86
|
+
* receipt, and a closed entry without one stays Idle but cannot take work.
|
|
87
|
+
*/
|
|
88
|
+
export interface PublishedLifecycle {
|
|
89
|
+
readonly lifecycle: LifecycleState;
|
|
90
|
+
readonly entryHeld: boolean;
|
|
91
|
+
}
|
|
92
|
+
/** What a caller may store. Scheduling and the dashboard read it back. */
|
|
93
|
+
export interface LifecyclePublication {
|
|
94
|
+
lifecycle?: LifecycleState;
|
|
95
|
+
entryHeld?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Move the published lifecycle. The transition table is checked against the
|
|
99
|
+
* state already stored, so a caller cannot skip Stopping or enter Gated from
|
|
100
|
+
* a running wake. Staying in the same state is not an edge.
|
|
101
|
+
*
|
|
102
|
+
* `barrierConfirmed` distinguishes Gated from a closed entry. Without the
|
|
103
|
+
* receipt the entry is held and the published state stays Idle.
|
|
104
|
+
*/
|
|
105
|
+
export declare function publishLifecycle(target: LifecyclePublication, next: LifecycleState, barrierConfirmed?: boolean): PublishedLifecycle;
|
|
106
|
+
/**
|
|
107
|
+
* Whether the thread loop may start new foreground work.
|
|
108
|
+
*
|
|
109
|
+
* Only a published Idle admits work, and Idle is not enough when the entry
|
|
110
|
+
* is held. Claude never confirms the barrier, so its service gate and
|
|
111
|
+
* fund-league hold stay refused until the entry reopens.
|
|
112
|
+
*/
|
|
113
|
+
export declare function canAdmitForegroundWork(state: LifecyclePublication): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* A mid-turn interrupt belongs to the wake that is already Running. Stopping,
|
|
116
|
+
* Recovering, and a closed entry do not drain queued chat into that turn.
|
|
117
|
+
*/
|
|
118
|
+
export declare function canDrainRunningTurn(state: LifecyclePublication & {
|
|
119
|
+
busy?: boolean;
|
|
120
|
+
gated?: boolean;
|
|
121
|
+
}): boolean;
|
|
82
122
|
/**
|
|
83
123
|
* How a host entry may close. A foreground run must stop before the entry is
|
|
84
124
|
* marked closed. An idle loop may close directly. Neither path confirms the
|
|
85
125
|
* engine barrier: that still needs an engine receipt, which this does not have.
|
|
86
126
|
*/
|
|
87
127
|
export declare function closeHostEntry(input: {
|
|
128
|
+
readonly state: LifecyclePublication;
|
|
88
129
|
readonly busy: boolean;
|
|
130
|
+
readonly barrierConfirmed?: boolean;
|
|
89
131
|
readonly requestStop: () => void;
|
|
90
132
|
readonly markClosed: () => void;
|
|
91
133
|
}): "Idle" | "Stopping";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle-transitions.d.ts","sourceRoot":"","sources":["../../src/agent/lifecycle-transitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,SAAS,cAAc,EAAE,CAAC,CAM7F,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,+BAA+B,EAAE,SAAS,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,EAMjG,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,GAAG,OAAO,CAExF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI,CAGxF;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC;AAE7E;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,eAAe,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CACrD,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"lifecycle-transitions.d.ts","sourceRoot":"","sources":["../../src/agent/lifecycle-transitions.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,10 +43,19 @@ export function assertLifecycleTransition(from, to) {
|
|
|
43
43
|
* only after that release.
|
|
44
44
|
*/
|
|
45
45
|
export function endForegroundWake(input) {
|
|
46
|
-
|
|
46
|
+
// A wake the loop already returned to Idle has nothing left to stop.
|
|
47
|
+
// Stopping is only entered from the run that still holds the slot.
|
|
48
|
+
const phase = input.state?.lifecycle;
|
|
49
|
+
if ((phase === "Running" || phase === "Recovering") && input.state)
|
|
50
|
+
publishLifecycle(input.state, "Stopping");
|
|
51
|
+
else if (!input.state)
|
|
52
|
+
assertLifecycleTransition(input.from, "Stopping");
|
|
47
53
|
input.onPhase?.("Stopping");
|
|
48
54
|
input.cleanup();
|
|
49
|
-
|
|
55
|
+
if (input.state?.lifecycle === "Stopping")
|
|
56
|
+
publishLifecycle(input.state, "Idle");
|
|
57
|
+
else if (!input.state)
|
|
58
|
+
assertLifecycleTransition("Stopping", "Idle");
|
|
50
59
|
input.release();
|
|
51
60
|
input.onPhase?.("Idle");
|
|
52
61
|
return "Idle";
|
|
@@ -112,20 +121,67 @@ export function nextRecoveryPhase(input) {
|
|
|
112
121
|
assertLifecycleTransition("Recovering", "Stopping");
|
|
113
122
|
return "Stopping";
|
|
114
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Move the published lifecycle. The transition table is checked against the
|
|
126
|
+
* state already stored, so a caller cannot skip Stopping or enter Gated from
|
|
127
|
+
* a running wake. Staying in the same state is not an edge.
|
|
128
|
+
*
|
|
129
|
+
* `barrierConfirmed` distinguishes Gated from a closed entry. Without the
|
|
130
|
+
* receipt the entry is held and the published state stays Idle.
|
|
131
|
+
*/
|
|
132
|
+
export function publishLifecycle(target, next, barrierConfirmed = false) {
|
|
133
|
+
// Gated without a receipt is not Gated. The legal edge is still checked,
|
|
134
|
+
// then the published state stays Idle with the entry held.
|
|
135
|
+
const published = next === "Gated" && !barrierConfirmed ? "Idle" : next;
|
|
136
|
+
const current = target.lifecycle ?? "Idle";
|
|
137
|
+
if (current !== next)
|
|
138
|
+
assertLifecycleTransition(current, next);
|
|
139
|
+
if (current !== published)
|
|
140
|
+
assertLifecycleTransition(current, published);
|
|
141
|
+
target.lifecycle = published;
|
|
142
|
+
target.entryHeld = next === "Gated" && !barrierConfirmed;
|
|
143
|
+
return { lifecycle: target.lifecycle, entryHeld: target.entryHeld };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Whether the thread loop may start new foreground work.
|
|
147
|
+
*
|
|
148
|
+
* Only a published Idle admits work, and Idle is not enough when the entry
|
|
149
|
+
* is held. Claude never confirms the barrier, so its service gate and
|
|
150
|
+
* fund-league hold stay refused until the entry reopens.
|
|
151
|
+
*/
|
|
152
|
+
export function canAdmitForegroundWork(state) {
|
|
153
|
+
return (state.lifecycle ?? "Idle") === "Idle" && !state.entryHeld;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A mid-turn interrupt belongs to the wake that is already Running. Stopping,
|
|
157
|
+
* Recovering, and a closed entry do not drain queued chat into that turn.
|
|
158
|
+
*/
|
|
159
|
+
export function canDrainRunningTurn(state) {
|
|
160
|
+
// A state that was never published still answers with the slot it holds.
|
|
161
|
+
// Once published, only Running with an open entry drains a mid-turn batch.
|
|
162
|
+
if (state.lifecycle === undefined)
|
|
163
|
+
return state.busy === true && state.gated !== true;
|
|
164
|
+
return state.lifecycle === "Running" && !state.entryHeld;
|
|
165
|
+
}
|
|
115
166
|
/**
|
|
116
167
|
* How a host entry may close. A foreground run must stop before the entry is
|
|
117
168
|
* marked closed. An idle loop may close directly. Neither path confirms the
|
|
118
169
|
* engine barrier: that still needs an engine receipt, which this does not have.
|
|
119
170
|
*/
|
|
120
171
|
export function closeHostEntry(input) {
|
|
121
|
-
|
|
122
|
-
|
|
172
|
+
const barrierConfirmed = input.barrierConfirmed === true;
|
|
173
|
+
// `busy` still says a run holds the slot after Stopping has been published.
|
|
174
|
+
// Stopping again would be an illegal edge, so only Running or Recovering
|
|
175
|
+
// takes that step. Idle closes directly.
|
|
176
|
+
const running = input.state.lifecycle === "Running" || input.state.lifecycle === "Recovering";
|
|
177
|
+
if (input.busy && running) {
|
|
178
|
+
publishLifecycle(input.state, "Stopping");
|
|
123
179
|
input.requestStop();
|
|
124
|
-
|
|
180
|
+
publishLifecycle(input.state, "Gated", barrierConfirmed);
|
|
125
181
|
input.markClosed();
|
|
126
182
|
return "Stopping";
|
|
127
183
|
}
|
|
128
|
-
|
|
184
|
+
publishLifecycle(input.state, "Gated", barrierConfirmed);
|
|
129
185
|
input.markClosed();
|
|
130
186
|
return "Idle";
|
|
131
187
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle-transitions.js","sourceRoot":"","sources":["../../src/agent/lifecycle-transitions.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAgE;IAChG,IAAI,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,OAAO,CAAC;IACxC,OAAO,EAAE,CAAC,YAAY,EAAE,UAAU,CAAC;IACnC,UAAU,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3B,KAAK,EAAE,CAAC,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAA2D;IACrG,CAAC,SAAS,EAAE,OAAO,CAAC;IACpB,CAAC,YAAY,EAAE,OAAO,CAAC;IACvB,CAAC,OAAO,EAAE,SAAS,CAAC;IACpB,CAAC,OAAO,EAAE,YAAY,CAAC;IACvB,CAAC,UAAU,EAAE,SAAS,CAAC;CACxB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,IAAoB,EAAE,EAAkB;IAC7E,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAoB,EAAE,EAAkB;IAChF,IAAI,sBAAsB,CAAC,IAAI,EAAE,EAAE,CAAC;QAAE,OAAO;IAC7C,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,OAAO,EAAE,EAAE,CAAC,CAAC;AACpE,CAAC;AASD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"lifecycle-transitions.js","sourceRoot":"","sources":["../../src/agent/lifecycle-transitions.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/loop.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,EAA+D,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAG1I,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,EAA+D,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAG1I,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAuBpD,OAAO,EAAkB,KAAK,UAAU,EAA6G,MAAM,YAAY,CAAC;AA4BxK,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAC;AAK9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAYtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAqChE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAS3C;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B;+DAC2D;IAC3D,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IACpD,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,uBAAuB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,cAAc,EAAE,cAAc,CAAC;QAAC,YAAY,EAAE,YAAY,CAAC;QAAC,WAAW,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3I;;;;OAIG;IACH,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,YAAY,CAAC;QACpB,yEAAyE;QACzE,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B,CAAC;CACH,GACA,OAAO,CAAC,IAAI,CAAC,CA0pDf"}
|
package/dist/agent/loop.js
CHANGED
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
* - ChannelManager: messaging channel adapters
|
|
14
14
|
*/
|
|
15
15
|
import { createDefaultExternalContextRegistry, ExternalContextRegistry } from "./external-context/registry.js";
|
|
16
|
-
import {
|
|
17
|
-
import { beginLifecycleRun, createLifecycleRunId,
|
|
18
|
-
import { closeHostEntry, endForegroundWake } from "./lifecycle-transitions.js";
|
|
16
|
+
import { randomUUID } from "node:crypto";
|
|
17
|
+
import { beginLifecycleRun, createLifecycleRunId, endLifecycleRun, traceLifecycle, traceShadowLifecycle } from "./lifecycle-trace.js";
|
|
18
|
+
import { canAdmitForegroundWork, closeHostEntry, endForegroundWake, publishLifecycle } from "./lifecycle-transitions.js";
|
|
19
19
|
import { isProactiveWakeEnabled, isTunnelEnabled, isWorkspaceEnabled } from "../config/types.js";
|
|
20
20
|
import { DEFAULT_THREAD_ID, normalizeChannelName, resolveThreadId } from "../channels/interface.js";
|
|
21
21
|
import { buildSystemPrompt } from "./system-prompt.js";
|
|
@@ -31,6 +31,7 @@ import { loadOwnerConfig, consumePendingUpgrade, consumePendingRestart, writePen
|
|
|
31
31
|
import { syncSystemTimezone } from "../utils/timezone.js";
|
|
32
32
|
import { logger } from "../logger.js";
|
|
33
33
|
import { cleanOldScreenshots } from "../tools/screenshot.js";
|
|
34
|
+
import { wakeDispatchId } from "../tools/delegation.js";
|
|
34
35
|
import { getEffectiveEngine, maybeStartApiProxy } from "./model-provider.js";
|
|
35
36
|
import { EngineFallbackManager, setActiveEngineFallback } from "./engine-fallback.js";
|
|
36
37
|
import { cleanupOldTranscripts } from "./session-trimmer.js";
|
|
@@ -91,6 +92,8 @@ import { retireLegacyServices } from "../service/retired-services.js";
|
|
|
91
92
|
import { backfillMissingThreadApplications, migrateLegacyThreadApplications, threadApplicationBackfillHealthEvent } from "../threads/application-migration.js";
|
|
92
93
|
import { currentApplicationContext, inheritThreadApplication, threadApplication } from "../threads/application-context.js";
|
|
93
94
|
import { ForemanHost } from "../threads/foreman-host.js";
|
|
95
|
+
import { onTaskSettled, reportTaskSettled, settledTaskState } from "../threads/task-settlement.js";
|
|
96
|
+
import { bindRuntimeContext } from "./runtime-context.js";
|
|
94
97
|
import { ForemanStore } from "../threads/foreman-store.js";
|
|
95
98
|
import { canDelegateTasks, foremanEventsOf, getForemanClient, installForemanClient, isForemanRuntime, supportsTaskRuntime } from "../threads/foreman-protocol.js";
|
|
96
99
|
import { ForegroundTaskTracker, installForegroundTaskTracker } from "../threads/foreground-task.js";
|
|
@@ -190,6 +193,22 @@ export async function startAgentLoop(config, options) {
|
|
|
190
193
|
channelManager.publishThreadActivity("default", activity, activity.workerInstanceId, deliveryTarget);
|
|
191
194
|
},
|
|
192
195
|
});
|
|
196
|
+
// The progress card waits for handed-off Tasks; it ends when they end,
|
|
197
|
+
// whether or not their result wakes this conversation.
|
|
198
|
+
const finishBackgroundCard = (taskId, state) => {
|
|
199
|
+
if (workerMode)
|
|
200
|
+
workerMode.relay.finishBackgroundActivity(taskId, state);
|
|
201
|
+
else
|
|
202
|
+
mainActivityController?.finishBackgroundTask(taskId, state);
|
|
203
|
+
};
|
|
204
|
+
const stopSettlementListener = onTaskSettled(bindRuntimeContext((threadId, taskId, state) => {
|
|
205
|
+
if (threadId === executionContext.threadId)
|
|
206
|
+
finishBackgroundCard(taskId, state);
|
|
207
|
+
}));
|
|
208
|
+
registerShutdownCallback(() => {
|
|
209
|
+
stopSettlementListener();
|
|
210
|
+
return Promise.resolve();
|
|
211
|
+
});
|
|
193
212
|
const finAppCapabilityState = {
|
|
194
213
|
runtimeReady: false,
|
|
195
214
|
active: null,
|
|
@@ -236,6 +255,13 @@ export async function startAgentLoop(config, options) {
|
|
|
236
255
|
?? Promise.resolve({ ok: false, text: "Business reads are unavailable" }),
|
|
237
256
|
});
|
|
238
257
|
supervisor.onExecutionEvent((event, caller) => {
|
|
258
|
+
// The board and the progress card are a view: never let them break delivery.
|
|
259
|
+
try {
|
|
260
|
+
foremanHost?.publishTaskState(event, caller);
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
logger.warn(`Background task state was not published: ${error instanceof Error ? error.message : String(error)}`);
|
|
264
|
+
}
|
|
239
265
|
if (caller.kind !== "tui")
|
|
240
266
|
return;
|
|
241
267
|
channelManager.getAdapter("tui")?.publishExecutionEvent(event);
|
|
@@ -272,6 +298,13 @@ export async function startAgentLoop(config, options) {
|
|
|
272
298
|
const owner = resolveOwnerDefaultTarget(config, loadOwnerConfig());
|
|
273
299
|
return owner ? { channel: owner.channel, to: owner.to } : null;
|
|
274
300
|
},
|
|
301
|
+
publishTask: (target, task) => {
|
|
302
|
+
const adapter = channelManager.getAdapter(target.channel);
|
|
303
|
+
// The board repairs rows whose final update was lost from the ledger.
|
|
304
|
+
adapter?.setBackgroundTaskLookup?.((taskId) => activeForemanHost?.taskView(taskId) ?? null);
|
|
305
|
+
adapter?.publishBackgroundTask?.(target, task);
|
|
306
|
+
},
|
|
307
|
+
settleTask: reportTaskSettled,
|
|
275
308
|
locale: () => resolveLocale(loadOwnerConfig().language),
|
|
276
309
|
});
|
|
277
310
|
const host = foremanHost;
|
|
@@ -508,7 +541,11 @@ export async function startAgentLoop(config, options) {
|
|
|
508
541
|
activityTracker,
|
|
509
542
|
busy: false,
|
|
510
543
|
stopRequested: false,
|
|
544
|
+
lifecycle: "Idle",
|
|
545
|
+
entryHeld: false,
|
|
511
546
|
requestStop: () => {
|
|
547
|
+
// Stopping is published by the caller that decided to end the wake.
|
|
548
|
+
// This only records the request and asks the engine to stop.
|
|
512
549
|
agentState.stopRequested = true;
|
|
513
550
|
requestSessionStop();
|
|
514
551
|
},
|
|
@@ -760,11 +797,11 @@ export async function startAgentLoop(config, options) {
|
|
|
760
797
|
wakeMainLoop();
|
|
761
798
|
return;
|
|
762
799
|
}
|
|
763
|
-
if (agentState
|
|
800
|
+
if (!canAdmitForegroundWork(agentState)) {
|
|
764
801
|
// Correlated internal requests are durable queued work, not chat
|
|
765
802
|
// interrupts. They must own a fresh turn for precise lifecycle and
|
|
766
|
-
// cancellation semantics.
|
|
767
|
-
if (typeof msg.meta?.tuiRequestId === "string")
|
|
803
|
+
// cancellation semantics. A closed entry is not a turn to interrupt.
|
|
804
|
+
if (typeof msg.meta?.tuiRequestId === "string" || agentState.entryHeld || agentState.lifecycle === "Gated")
|
|
768
805
|
return;
|
|
769
806
|
interruptHandler.schedule();
|
|
770
807
|
}
|
|
@@ -916,7 +953,7 @@ export async function startAgentLoop(config, options) {
|
|
|
916
953
|
logger.system("[nightly-maintenance] Dreaming needs the thread supervisor (multiThread); skipped on this profile");
|
|
917
954
|
nightlyMaintenance = new NightlyMaintenance({
|
|
918
955
|
tryAcquire: () => {
|
|
919
|
-
if (agentState
|
|
956
|
+
if (!canAdmitForegroundWork(agentState) || agentState.learning || agentState.compacting
|
|
920
957
|
|| !messageQueue.isEmpty() || readFundLeagueHold()
|
|
921
958
|
|| shouldEnforceServiceGate(heartbeat.lastServiceStatus))
|
|
922
959
|
return null;
|
|
@@ -930,6 +967,7 @@ export async function startAgentLoop(config, options) {
|
|
|
930
967
|
// Maintenance holds the slot the way a foreground wake does. Release
|
|
931
968
|
// it through Stopping so workers resume only after the slot is free.
|
|
932
969
|
endForegroundWake({
|
|
970
|
+
state: agentState,
|
|
933
971
|
from: "Running",
|
|
934
972
|
cleanup: () => { agentState.learning = false; },
|
|
935
973
|
release: () => {
|
|
@@ -1014,7 +1052,9 @@ export async function startAgentLoop(config, options) {
|
|
|
1014
1052
|
// held stops first; an idle loop closes the entry directly. Neither
|
|
1015
1053
|
// confirms an engine barrier.
|
|
1016
1054
|
closeHostEntry({
|
|
1055
|
+
state: agentState,
|
|
1017
1056
|
busy: agentState.busy,
|
|
1057
|
+
barrierConfirmed: session.executionBarrierConfirmed(),
|
|
1018
1058
|
requestStop: () => { agentState.requestStop(); },
|
|
1019
1059
|
markClosed: () => {
|
|
1020
1060
|
executionOwner.setBusy(false, "league_hold");
|
|
@@ -1030,8 +1070,12 @@ export async function startAgentLoop(config, options) {
|
|
|
1030
1070
|
// A task handed off in an earlier wake no longer blocks new foreground work.
|
|
1031
1071
|
foregroundTasks?.beginWake();
|
|
1032
1072
|
executionOwner.setBusy(false, "wake_reset");
|
|
1033
|
-
agentState.gated = false;
|
|
1034
1073
|
agentState.stopRequested = false;
|
|
1074
|
+
// The hold check above already continued. Reaching here means the entry
|
|
1075
|
+
// may open. A held entry returns through Idle, which is the only way out.
|
|
1076
|
+
if (agentState.lifecycle !== "Idle" || agentState.entryHeld)
|
|
1077
|
+
publishLifecycle(agentState, "Idle");
|
|
1078
|
+
agentState.gated = false;
|
|
1035
1079
|
agentState.activeTuiRequestId = undefined;
|
|
1036
1080
|
agentState.hasRepliedInCycle = false;
|
|
1037
1081
|
agentState.notifiedUserThisWake = false;
|
|
@@ -1207,6 +1251,14 @@ export async function startAgentLoop(config, options) {
|
|
|
1207
1251
|
if (!workerMode && shouldEnforceServiceGate(heartbeat.lastServiceStatus)) {
|
|
1208
1252
|
await runServiceGate(config, channelManager, heartbeat, messageQueue);
|
|
1209
1253
|
}
|
|
1254
|
+
// The five states admit a wake only from Idle, and a closed entry that
|
|
1255
|
+
// still lacks an engine receipt is not Idle enough. Sleep again instead of
|
|
1256
|
+
// taking the slot. Claude never confirms the barrier, so this is what
|
|
1257
|
+
// keeps a closed service gate or fund-league hold from starting work.
|
|
1258
|
+
if (!canAdmitForegroundWork(agentState)) {
|
|
1259
|
+
logger.system(`Foreground wake refused: ${agentState.lifecycle}${agentState.entryHeld ? " (entry held)" : ""}`);
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1210
1262
|
// The slot is taken only after the gate. A closed entry therefore does not
|
|
1211
1263
|
// overlap a foreground run, which would be Running → Gated.
|
|
1212
1264
|
executionOwner.setBusy(true, "wake", lifecycleRunId);
|
|
@@ -1218,19 +1270,12 @@ export async function startAgentLoop(config, options) {
|
|
|
1218
1270
|
const hasMessages = !messageQueue.isEmpty();
|
|
1219
1271
|
const trigger = hasMessages ? "message" : "heartbeat";
|
|
1220
1272
|
beginLifecycleRun(lifecycleRunId);
|
|
1221
|
-
const observeShadow = (phase
|
|
1273
|
+
const observeShadow = (phase) => {
|
|
1222
1274
|
traceShadowLifecycle({
|
|
1223
1275
|
runId: lifecycleRunId,
|
|
1224
1276
|
phase,
|
|
1225
|
-
state:
|
|
1226
|
-
|
|
1227
|
-
stopRequested: agentState.stopRequested,
|
|
1228
|
-
busy: agentState.busy,
|
|
1229
|
-
recovering,
|
|
1230
|
-
// Pi confirms this with `agent_settled`. An abort is not a receipt,
|
|
1231
|
-
// so an engine that cannot prove it stopped stays unconfirmed.
|
|
1232
|
-
barrierConfirmed: session.executionBarrierConfirmed(),
|
|
1233
|
-
}),
|
|
1277
|
+
state: agentState.lifecycle ?? "Idle",
|
|
1278
|
+
entryHeld: agentState.entryHeld,
|
|
1234
1279
|
legacy: {
|
|
1235
1280
|
busy: agentState.busy,
|
|
1236
1281
|
gated: agentState.gated,
|
|
@@ -1245,9 +1290,11 @@ export async function startAgentLoop(config, options) {
|
|
|
1245
1290
|
// A worker thread is the same loop: its busy flag lives on the
|
|
1246
1291
|
// supervisor, and it is cleared only after this cleanup.
|
|
1247
1292
|
endForegroundWake({
|
|
1248
|
-
|
|
1249
|
-
//
|
|
1250
|
-
|
|
1293
|
+
state: agentState,
|
|
1294
|
+
// A failed compaction is still this same foreground run. Recovering
|
|
1295
|
+
// publishes itself before the wake ends, and Stopping is legal from
|
|
1296
|
+
// either Running or Recovering.
|
|
1297
|
+
from: agentState.lifecycle === "Recovering" ? "Recovering" : "Running",
|
|
1251
1298
|
onPhase: (phase) => {
|
|
1252
1299
|
if (phase === "Stopping")
|
|
1253
1300
|
observeShadow("stopping");
|
|
@@ -1382,7 +1429,8 @@ export async function startAgentLoop(config, options) {
|
|
|
1382
1429
|
// long). Rotate with our bounded summarizer before the turn starts
|
|
1383
1430
|
// so this wake runs on a session that fits. The summary and the
|
|
1384
1431
|
// continuation hint are seeded inline; no extra wake is queued.
|
|
1385
|
-
|
|
1432
|
+
publishLifecycle(agentState, "Recovering");
|
|
1433
|
+
observeShadow("compaction_failed");
|
|
1386
1434
|
traceLifecycle({
|
|
1387
1435
|
runId: lifecycleRunId,
|
|
1388
1436
|
stage: "compaction",
|
|
@@ -1486,7 +1534,7 @@ export async function startAgentLoop(config, options) {
|
|
|
1486
1534
|
outcome: "started",
|
|
1487
1535
|
});
|
|
1488
1536
|
let releaseConversationTurn;
|
|
1489
|
-
agentState.currentDispatchId =
|
|
1537
|
+
agentState.currentDispatchId = wakeDispatchId(messages.map((message) => message.id), lifecycleRunId);
|
|
1490
1538
|
try {
|
|
1491
1539
|
if (!workerExecution) {
|
|
1492
1540
|
releaseConversationTurn = await (options?.acquireConversationTurn?.(options.signal)
|
|
@@ -1521,6 +1569,10 @@ export async function startAgentLoop(config, options) {
|
|
|
1521
1569
|
// Foreman: the background-task updates this turn handled, read before
|
|
1522
1570
|
// their claims are released (mid-turn interrupts included).
|
|
1523
1571
|
const handledForemanEvents = failoverRestartPending ? [] : foremanEventsOf(messageQueue.currentCycleClaims());
|
|
1572
|
+
// Every Task the host accepted this wake (one response can delegate
|
|
1573
|
+
// several, or a batch): the status card waits for all of them.
|
|
1574
|
+
const handedOffIds = [...(foregroundTasks?.handedOffTaskIds() ?? [])];
|
|
1575
|
+
const waitsForBackground = result.finished === true && result.terminalState === "completed" && handedOffIds.length > 0;
|
|
1524
1576
|
// A completed foreground wake acknowledges its claims. Accepted background
|
|
1525
1577
|
// work already belongs to the canonical Task ledger.
|
|
1526
1578
|
if (!failoverRestartPending)
|
|
@@ -1536,11 +1588,31 @@ export async function startAgentLoop(config, options) {
|
|
|
1536
1588
|
void getForemanClient()?.request({ type: "turn_ended", events: handledForemanEvents });
|
|
1537
1589
|
}
|
|
1538
1590
|
}
|
|
1539
|
-
if (
|
|
1540
|
-
|
|
1591
|
+
if (waitsForBackground) {
|
|
1592
|
+
for (const taskId of handedOffIds) {
|
|
1593
|
+
if (workerMode)
|
|
1594
|
+
workerMode.relay.markActivityWaitingForBackground(taskId);
|
|
1595
|
+
else
|
|
1596
|
+
mainActivityController?.markWaitingForBackground(taskId);
|
|
1597
|
+
}
|
|
1598
|
+
// A quick Task can end before this wake does; its notice came earlier.
|
|
1599
|
+
for (const taskId of handedOffIds) {
|
|
1600
|
+
const settled = settledTaskState(executionContext.threadId, taskId);
|
|
1601
|
+
if (settled)
|
|
1602
|
+
finishBackgroundCard(taskId, settled);
|
|
1603
|
+
}
|
|
1541
1604
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1605
|
+
for (const event of handledForemanEvents) {
|
|
1606
|
+
if (event.kind !== "result")
|
|
1607
|
+
continue;
|
|
1608
|
+
const state = event.status === "succeeded" ? "completed" : "failed";
|
|
1609
|
+
finishBackgroundCard(event.taskId, state);
|
|
1610
|
+
}
|
|
1611
|
+
if (!waitsForBackground) {
|
|
1612
|
+
if (workerMode)
|
|
1613
|
+
workerMode.relay.finishActivityRun(result.terminalState);
|
|
1614
|
+
else
|
|
1615
|
+
mainActivityController?.finishRun(result.terminalState);
|
|
1544
1616
|
}
|
|
1545
1617
|
tuiTerminalOutcome = resolveTuiTerminalOutcome(result.terminalState);
|
|
1546
1618
|
}
|