@agentdeck/bridge 1.0.10 → 1.0.12
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/codex-rollout-response.d.ts +31 -4
- package/dist/codex-rollout-response.d.ts.map +1 -1
- package/dist/codex-rollout-response.js +67 -19
- package/dist/codex-rollout-response.js.map +1 -1
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +58 -7
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/dist/passive-observer.d.ts +14 -1
- package/dist/passive-observer.d.ts.map +1 -1
- package/dist/passive-observer.js +90 -15
- package/dist/passive-observer.js.map +1 -1
- package/dist/usage-event.d.ts.map +1 -1
- package/dist/usage-event.js +4 -1
- package/dist/usage-event.js.map +1 -1
- package/package.json +3 -3
|
@@ -22,10 +22,37 @@
|
|
|
22
22
|
/** Locate `rollout-*-<sessionId>.jsonl` under the newest day dirs. */
|
|
23
23
|
export declare function locateCodexRollout(sessionId: string, sessionsRoot?: string): string | null;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* What the rollout says happened on a turn.
|
|
26
|
+
*
|
|
27
|
+
* A turn ends one of two ways and the tail records both, but only one used to
|
|
28
|
+
* be read. `text` is the assistant's reply; `error` is the failure Codex wrote
|
|
29
|
+
* instead — quota exhausted, a model the account may not use, a stream that
|
|
30
|
+
* died. Codex does not run its `Stop` hook on a failed turn, so this file is
|
|
31
|
+
* the ONLY place the failure is observable, and dropping it is what left a
|
|
32
|
+
* turn spinning with its cause sitting unread on disk (issue: "ChatGPT free
|
|
33
|
+
* request fails, timeline stays in progress").
|
|
34
|
+
*/
|
|
35
|
+
export interface CodexTurnOutcome {
|
|
36
|
+
/** Assistant reply, empty when the turn produced none. */
|
|
37
|
+
text: string;
|
|
38
|
+
/** Human-readable failure text, when the turn ended in one. */
|
|
39
|
+
error?: string;
|
|
40
|
+
/** Codex's own classification, e.g. `usage_limit_exceeded`. */
|
|
41
|
+
errorKind?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse the rollout tail for how the turn ended, newest record first.
|
|
45
|
+
*
|
|
46
|
+
* The scan stops at the turn's own opening record (`task_started` /
|
|
47
|
+
* `user_message`). Without that stop a failed turn — which contributes no
|
|
48
|
+
* `agent_message` of its own — kept walking into the PREVIOUS turn and
|
|
49
|
+
* returned its reply as this one's, quietly attributing old text to a request
|
|
50
|
+
* that never produced any.
|
|
51
|
+
*/
|
|
52
|
+
export declare function codexTurnOutcomeFromRollout(sessionId: string, sessionsRoot?: string): CodexTurnOutcome;
|
|
53
|
+
/**
|
|
54
|
+
* Back-compat shim: the turn's reply text only.
|
|
55
|
+
* Prefer `codexTurnOutcomeFromRollout`, which also reports failures.
|
|
29
56
|
*/
|
|
30
57
|
export declare function lastAgentMessageFromCodexRollout(sessionId: string, sessionsRoot?: string): string;
|
|
31
58
|
//# sourceMappingURL=codex-rollout-response.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-rollout-response.d.ts","sourceRoot":"","sources":["../src/codex-rollout-response.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0BH,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmB1F;AAuBD
|
|
1
|
+
{"version":3,"file":"codex-rollout-response.d.ts","sourceRoot":"","sources":["../src/codex-rollout-response.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0BH,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmB1F;AAuBD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAqDtG;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAEjG"}
|
|
@@ -86,18 +86,44 @@ function readTail(path, maxBytes) {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
+
/** Longest error text worth carrying onto a timeline row. */
|
|
90
|
+
const MAX_ERROR_CHARS = 400;
|
|
91
|
+
function cleanErrorText(raw) {
|
|
92
|
+
if (typeof raw !== 'string')
|
|
93
|
+
return undefined;
|
|
94
|
+
let text = raw.trim();
|
|
95
|
+
if (!text)
|
|
96
|
+
return undefined;
|
|
97
|
+
// Codex nests the upstream JSON body inside `message` for HTTP failures.
|
|
98
|
+
// The useful sentence is the inner `message`; the envelope is noise.
|
|
99
|
+
if (text.startsWith('{')) {
|
|
100
|
+
try {
|
|
101
|
+
const inner = JSON.parse(text);
|
|
102
|
+
const nested = (inner.message ?? inner.error?.message);
|
|
103
|
+
if (typeof nested === 'string' && nested.trim())
|
|
104
|
+
text = nested.trim();
|
|
105
|
+
}
|
|
106
|
+
catch { /* not JSON after all — keep the raw text */ }
|
|
107
|
+
}
|
|
108
|
+
return text.length > MAX_ERROR_CHARS ? `${text.slice(0, MAX_ERROR_CHARS - 1)}…` : text;
|
|
109
|
+
}
|
|
89
110
|
/**
|
|
90
|
-
* Parse the rollout tail for the turn
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
111
|
+
* Parse the rollout tail for how the turn ended, newest record first.
|
|
112
|
+
*
|
|
113
|
+
* The scan stops at the turn's own opening record (`task_started` /
|
|
114
|
+
* `user_message`). Without that stop a failed turn — which contributes no
|
|
115
|
+
* `agent_message` of its own — kept walking into the PREVIOUS turn and
|
|
116
|
+
* returned its reply as this one's, quietly attributing old text to a request
|
|
117
|
+
* that never produced any.
|
|
94
118
|
*/
|
|
95
|
-
export function
|
|
119
|
+
export function codexTurnOutcomeFromRollout(sessionId, sessionsRoot) {
|
|
96
120
|
const path = locateCodexRollout(sessionId, sessionsRoot);
|
|
97
121
|
if (!path)
|
|
98
|
-
return '';
|
|
122
|
+
return { text: '' };
|
|
99
123
|
const lines = readTail(path, TAIL_BYTES).split('\n');
|
|
100
|
-
let
|
|
124
|
+
let text = '';
|
|
125
|
+
let error;
|
|
126
|
+
let errorKind;
|
|
101
127
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
102
128
|
const line = lines[i].trim();
|
|
103
129
|
if (!line)
|
|
@@ -114,22 +140,44 @@ export function lastAgentMessageFromCodexRollout(sessionId, sessionsRoot) {
|
|
|
114
140
|
const payload = record.payload;
|
|
115
141
|
if (!payload || typeof payload !== 'object')
|
|
116
142
|
continue;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
143
|
+
// Turn boundary — everything above belongs to an earlier turn.
|
|
144
|
+
if (payload.type === 'task_started' || payload.type === 'user_message')
|
|
145
|
+
break;
|
|
146
|
+
if (payload.type === 'error') {
|
|
147
|
+
error ??= cleanErrorText(payload.message);
|
|
148
|
+
if (typeof payload.codex_error_info === 'string')
|
|
149
|
+
errorKind ??= payload.codex_error_info;
|
|
150
|
+
continue;
|
|
120
151
|
}
|
|
121
|
-
if (
|
|
152
|
+
if (payload.type === 'task_complete') {
|
|
153
|
+
const failure = payload.error;
|
|
154
|
+
if (failure && typeof failure === 'object') {
|
|
155
|
+
error ??= cleanErrorText(failure.message);
|
|
156
|
+
if (typeof failure.codex_error_info === 'string')
|
|
157
|
+
errorKind ??= failure.codex_error_info;
|
|
158
|
+
}
|
|
159
|
+
if (typeof payload.last_agent_message === 'string' && payload.last_agent_message.trim()) {
|
|
160
|
+
return { text: payload.last_agent_message.trim(), error, errorKind };
|
|
161
|
+
}
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (!text && payload.type === 'agent_message'
|
|
122
165
|
&& typeof payload.message === 'string' && payload.message.trim()) {
|
|
123
|
-
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
// reached an agent_message first (scanning backwards) there is no
|
|
127
|
-
// newer task_complete — return immediately.
|
|
166
|
+
text = payload.message.trim();
|
|
167
|
+
// task_complete always FOLLOWS agent_message, so scanning backwards past
|
|
168
|
+
// this point can only reach older records.
|
|
128
169
|
break;
|
|
129
170
|
}
|
|
130
171
|
}
|
|
131
|
-
if (!
|
|
132
|
-
debug('codex-rollout', `no agent_message in tail of ${path}`);
|
|
133
|
-
return
|
|
172
|
+
if (!text && !error)
|
|
173
|
+
debug('codex-rollout', `no agent_message or error in tail of ${path}`);
|
|
174
|
+
return { text, error, errorKind };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Back-compat shim: the turn's reply text only.
|
|
178
|
+
* Prefer `codexTurnOutcomeFromRollout`, which also reports failures.
|
|
179
|
+
*/
|
|
180
|
+
export function lastAgentMessageFromCodexRollout(sessionId, sessionsRoot) {
|
|
181
|
+
return codexTurnOutcomeFromRollout(sessionId, sessionsRoot).text;
|
|
134
182
|
}
|
|
135
183
|
//# sourceMappingURL=codex-rollout-response.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-rollout-response.js","sourceRoot":"","sources":["../src/codex-rollout-response.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,oDAAoD;AACpD,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,yEAAyE;AACzE,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;AAE9B,SAAS,WAAW,CAAC,KAAe;IAClC,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAAC,SAAiB,EAAE,YAAqB;IACzE,IAAI,CAAC,SAAS,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,IAAI,GAAG,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,IAAI,SAAS,QAAQ,CAAC;IACrC,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAClD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,IAAI,EAAE,cAAc,GAAG,YAAY;oBAAE,OAAO,IAAI,CAAC;gBACjD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;gBACzC,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBACpC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;wBACzD,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;YAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9B,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;YACtC,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"codex-rollout-response.js","sourceRoot":"","sources":["../src/codex-rollout-response.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-server.d.ts","sourceRoot":"","sources":["../src/daemon-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,UAAU,EAA8B,MAAM,kBAAkB,CAAC;AAgH1E,OAAO,EAA8D,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA8P/G;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EAC5C,YAAY,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAClD,OAAO,CAST;AAkBD,iBAAS,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,GAAG,IAAI,CA+C1E;AAYD,iBAAS,yBAAyB,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAStD;AAED,iBAAS,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAsBlE;AA6ED,gBAAgB;AAChB,wBAAgB,uBAAuB,CAAC,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKzH;AACD,gBAAgB;AAChB,wBAAgB,wBAAwB,IAAI,IAAI,CAS/C;AACD,gBAAgB;AAChB,eAAO,MAAM,gBAAgB;;;;;CAK5B,CAAC;AAEF,iBAAe,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8F3H;AAoHD,iEAAiE;AACjE,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAsBtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EACnH,KAAK,EAAE,CAAC,GACP,CAAC,CAWH;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAA;CAAE,CAa3F;AAID,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA+HD,wBAAsB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"daemon-server.d.ts","sourceRoot":"","sources":["../src/daemon-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,UAAU,EAA8B,MAAM,kBAAkB,CAAC;AAgH1E,OAAO,EAA8D,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA8P/G;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EAC5C,YAAY,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAClD,OAAO,CAST;AAkBD,iBAAS,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,GAAG,IAAI,CA+C1E;AAYD,iBAAS,yBAAyB,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAStD;AAED,iBAAS,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAsBlE;AA6ED,gBAAgB;AAChB,wBAAgB,uBAAuB,CAAC,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKzH;AACD,gBAAgB;AAChB,wBAAgB,wBAAwB,IAAI,IAAI,CAS/C;AACD,gBAAgB;AAChB,eAAO,MAAM,gBAAgB;;;;;CAK5B,CAAC;AAEF,iBAAe,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8F3H;AAoHD,iEAAiE;AACjE,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAsBtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EACnH,KAAK,EAAE,CAAC,GACP,CAAC,CAWH;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAA;CAAE,CAa3F;AAID,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA+HD,wBAAsB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgkIpE"}
|
package/dist/daemon-server.js
CHANGED
|
@@ -84,7 +84,7 @@ import { readModelFromTranscript } from './apme/claude-transcript-reader.js';
|
|
|
84
84
|
import { transcriptTimelineForSession, lastAssistantTextFromTranscript, lastAssistantTextForSession, } from './session-transcript-timeline.js';
|
|
85
85
|
import { DeviceVoiceReplyRouter, speakableReply, spokenDigest, pcmFromWav, } from './device-voice-reply.js';
|
|
86
86
|
import { rawSessionId } from '@agentdeck/shared';
|
|
87
|
-
import { lastAgentMessageFromCodexRollout } from './codex-rollout-response.js';
|
|
87
|
+
import { codexTurnOutcomeFromRollout, lastAgentMessageFromCodexRollout } from './codex-rollout-response.js';
|
|
88
88
|
import { callFoundationModelsHelper } from './foundation-models-helper.js';
|
|
89
89
|
import { initModules, stopModules, createDefaultModules, } from './modules/index.js';
|
|
90
90
|
import { esp32ConnectionCount, getESP32DeviceInfo, onESP32Message, sendWifiProvisionToAll, handleESP32Wake, getESP32Ports, getSerialConnectionStatus, getSerialLastError, getSerialReachableBoards } from './esp32-serial.js';
|
|
@@ -998,6 +998,17 @@ export async function startDaemon(opts) {
|
|
|
998
998
|
// that is provably alive (agentic turns regularly outlive any fixed age
|
|
999
999
|
// threshold). Declared before the HTTP handlers that populate it.
|
|
1000
1000
|
const hookSessionsSeen = new Set();
|
|
1001
|
+
/**
|
|
1002
|
+
* When each session last posted a hook.
|
|
1003
|
+
*
|
|
1004
|
+
* `hookSessionsSeen` answers "has this session EVER been heard from", which
|
|
1005
|
+
* is the wrong question for the turn watchdog: the very prompt hook that
|
|
1006
|
+
* opens a chat_start also adds the session to that set, so the row it
|
|
1007
|
+
* created was permanently immune to the reaper meant to close it. A
|
|
1008
|
+
* timestamp lets the watchdog ask the answerable question instead — has
|
|
1009
|
+
* anything arrived SINCE this turn opened.
|
|
1010
|
+
*/
|
|
1011
|
+
const hookSessionLastSeenAt = new Map();
|
|
1001
1012
|
// Codex OTel span state. Declared before the HTTP server because the
|
|
1002
1013
|
// `/otel/v1/traces` handler closes over it — Codex's exporter can POST before
|
|
1003
1014
|
// the rest of daemon startup finishes.
|
|
@@ -1917,6 +1928,7 @@ export async function startDaemon(opts) {
|
|
|
1917
1928
|
// posts ANY hook after daemon startup is alive, and its open turn
|
|
1918
1929
|
// (even one persisted before the restart) must not be force-closed.
|
|
1919
1930
|
hookSessionsSeen.add(hookSid);
|
|
1931
|
+
hookSessionLastSeenAt.set(hookSid, Date.now());
|
|
1920
1932
|
// Claude hooks carry `cwd` (the worktree dir), not project_name/path —
|
|
1921
1933
|
// capture it so APME runs are attributable to a specific worktree.
|
|
1922
1934
|
const hookCwd = (typeof json.cwd === 'string' ? json.cwd
|
|
@@ -2085,9 +2097,10 @@ export async function startDaemon(opts) {
|
|
|
2085
2097
|
// authoritative source — the Codex counterpart of Claude's
|
|
2086
2098
|
// transcript tail. Read it whenever a completion row might be
|
|
2087
2099
|
// emitted (open turn, or a response-only close below).
|
|
2088
|
-
const
|
|
2089
|
-
?
|
|
2090
|
-
: '';
|
|
2100
|
+
const rolloutOutcome = hookAgentType === 'codex-cli' && !tp && !inlineResponse
|
|
2101
|
+
? codexTurnOutcomeFromRollout(hookSid)
|
|
2102
|
+
: { text: '', error: undefined, errorKind: undefined };
|
|
2103
|
+
const rolloutResponse = rolloutOutcome.text;
|
|
2091
2104
|
const responseText = tp
|
|
2092
2105
|
? stripUnsafeText(lastAssistantTextFromTranscript(tp))
|
|
2093
2106
|
: stripUnsafeText(inlineResponse || rolloutResponse);
|
|
@@ -2137,12 +2150,25 @@ export async function startDaemon(opts) {
|
|
|
2137
2150
|
});
|
|
2138
2151
|
}
|
|
2139
2152
|
else {
|
|
2140
|
-
// No readable response (interrupted / tool-only turn) —
|
|
2141
|
-
// close the row so the dashboards stop the spinner.
|
|
2153
|
+
// No readable response (interrupted / tool-only turn / failure) —
|
|
2154
|
+
// still close the row so the dashboards stop the spinner.
|
|
2142
2155
|
const durS = Math.max(0, Math.round((now - (lastStart.startedAt ?? lastStart.ts)) / 1000));
|
|
2156
|
+
// A turn that failed says so, in the words Codex used. The text
|
|
2157
|
+
// is on disk in the rollout and used to be dropped, so a quota
|
|
2158
|
+
// refusal read as an ordinary quiet turn.
|
|
2159
|
+
if (rolloutOutcome.error) {
|
|
2160
|
+
core.bridgeTimeline.addEntry({
|
|
2161
|
+
ts: now, type: 'error',
|
|
2162
|
+
raw: cleanRawText(rolloutOutcome.error.slice(0, 197)),
|
|
2163
|
+
detail: prepareMarkdownDetail(rolloutOutcome.error) || undefined,
|
|
2164
|
+
...base,
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2143
2167
|
core.bridgeTimeline.addEntry({
|
|
2144
2168
|
ts: now, type: 'chat_end',
|
|
2145
|
-
raw:
|
|
2169
|
+
raw: rolloutOutcome.error
|
|
2170
|
+
? `Failed · ${formatDurationSec(durS)}`
|
|
2171
|
+
: `Completed · ${formatDurationSec(durS)}`,
|
|
2146
2172
|
summaryKind: 'none',
|
|
2147
2173
|
...base,
|
|
2148
2174
|
});
|
|
@@ -2672,6 +2698,31 @@ export async function startDaemon(opts) {
|
|
|
2672
2698
|
log(`[agentdeck] Closed ${reapedTurns} orphaned chat_start rows as interrupted`);
|
|
2673
2699
|
}, 5 * 60_000);
|
|
2674
2700
|
chatReaperTimer.unref?.();
|
|
2701
|
+
// Standing watchdog for turns that end without a closing signal.
|
|
2702
|
+
//
|
|
2703
|
+
// The startup pass above only ever runs once, so a turn that wedges an
|
|
2704
|
+
// hour later is never revisited. Codex makes that the common case rather
|
|
2705
|
+
// than the exception: it does NOT run its `Stop` hook when a request
|
|
2706
|
+
// fails, so a rejected prompt (quota exhausted, a model the plan may not
|
|
2707
|
+
// use) leaves its chat_start open with nothing on the way to close it, and
|
|
2708
|
+
// every surface spins on it indefinitely. This sweeps for such rows and
|
|
2709
|
+
// closes them, but only where the session has gone quiet SINCE the turn
|
|
2710
|
+
// opened — a long-running turn that is still posting tool hooks is alive
|
|
2711
|
+
// and must be left alone.
|
|
2712
|
+
const TURN_WATCHDOG_INTERVAL_MS = 60_000;
|
|
2713
|
+
const TURN_WATCHDOG_SILENCE_MS = 3 * 60_000;
|
|
2714
|
+
const turnWatchdog = setInterval(() => {
|
|
2715
|
+
const now = Date.now();
|
|
2716
|
+
const active = new Set();
|
|
2717
|
+
for (const [sid, at] of hookSessionLastSeenAt) {
|
|
2718
|
+
if (now - at <= TURN_WATCHDOG_SILENCE_MS)
|
|
2719
|
+
active.add(sid);
|
|
2720
|
+
}
|
|
2721
|
+
const closed = core.bridgeTimeline.reapOrphanChatStarts(TURN_WATCHDOG_SILENCE_MS, now, active);
|
|
2722
|
+
if (closed > 0)
|
|
2723
|
+
log(`[agentdeck] Turn watchdog closed ${closed} stalled chat_start row(s)`);
|
|
2724
|
+
}, TURN_WATCHDOG_INTERVAL_MS);
|
|
2725
|
+
turnWatchdog.unref?.();
|
|
2675
2726
|
}
|
|
2676
2727
|
// Enabled AFTER rehydration + reaping so the first write carries the restored
|
|
2677
2728
|
// history instead of truncating the file to whatever this run has seen.
|