clideck 1.30.1 → 1.30.3
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/agent-presets.json +2 -2
- package/config.js +6 -3
- package/handlers.js +1 -1
- package/package.json +1 -1
- package/plugin-loader.js +1 -1
- package/plugins/autopilot/clideck-plugin.json +1 -1
- package/plugins/autopilot/index.js +537 -91
- package/plugins/autopilot/prompt.md +23 -21
- package/public/fx/bold-beep-idle.mp3 +0 -0
- package/public/fx/default-beep.mp3 +0 -0
- package/public/fx/echo-beep-idle.mp3 +0 -0
- package/public/fx/musical-beep-idle.mp3 +0 -0
- package/public/fx/small-bleep-idle.mp3 +0 -0
- package/public/fx/soft-beep.mp3 +0 -0
- package/public/fx/space-idle.mp3 +0 -0
- package/public/index.html +0 -5
- package/public/js/app.js +29 -16
- package/public/js/creator.js +45 -87
- package/public/js/nav.js +2 -2
- package/public/js/terminals.js +77 -17
- package/public/tailwind.css +1 -1
- package/sessions.js +8 -2
- package/skills/research-experiment/SKILL.md +224 -0
- package/skills/research-experiment/agents/openai.yaml +4 -0
- package/telemetry-receiver.js +51 -15
- package/transcript.js +27 -16
package/telemetry-receiver.js
CHANGED
|
@@ -10,10 +10,42 @@ const codexMenuPoll = new Map(); // sessionId → interval (polling for menu aft
|
|
|
10
10
|
const codexPendingStop = new Map(); // sessionId → ts (notify hook arrived; wait for next response.completed)
|
|
11
11
|
const codexOutputDone = new Map(); // sessionId → ts (fallback if notify never fires)
|
|
12
12
|
const codexPendingIdle = new Map(); // sessionId → timer (tiny settle before committing idle)
|
|
13
|
-
const
|
|
13
|
+
const codexToolPhasePending = new Set(); // sessionId set once Codex has announced a tool-call phase, cleared when the phase resolves
|
|
14
|
+
const codexPendingTools = new Map(); // sessionId → Set(callId) for approved Codex tool calls still awaiting a result
|
|
14
15
|
let broadcastFn = null;
|
|
15
16
|
let sessionsFn = null;
|
|
16
17
|
|
|
18
|
+
function getPendingToolSet(id) {
|
|
19
|
+
let set = codexPendingTools.get(id);
|
|
20
|
+
if (!set) { set = new Set(); codexPendingTools.set(id, set); }
|
|
21
|
+
return set;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function clearPendingTools(id) {
|
|
25
|
+
codexPendingTools.delete(id);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function addPendingTool(id, callId) {
|
|
29
|
+
if (!callId) return;
|
|
30
|
+
getPendingToolSet(id).add(callId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolvePendingTool(id, callId) {
|
|
34
|
+
if (!callId) return;
|
|
35
|
+
const set = codexPendingTools.get(id);
|
|
36
|
+
if (!set) return;
|
|
37
|
+
set.delete(callId);
|
|
38
|
+
if (!set.size) codexPendingTools.delete(id);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function hasPendingTools(id) {
|
|
42
|
+
return !!codexPendingTools.get(id)?.size;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function hasPendingToolState(id) {
|
|
46
|
+
return codexToolPhasePending.has(id) || hasPendingTools(id);
|
|
47
|
+
}
|
|
48
|
+
|
|
17
49
|
function init(broadcast, getSessions) {
|
|
18
50
|
broadcastFn = broadcast;
|
|
19
51
|
sessionsFn = getSessions;
|
|
@@ -78,11 +110,8 @@ function handleLogs(req, res) {
|
|
|
78
110
|
// Debug telemetry logs — uncomment as needed, do not delete
|
|
79
111
|
// if (serviceName === 'claude-code' && eventName) console.log(`[telemetry:claude] ${eventName}`);
|
|
80
112
|
// if (serviceName === 'codex_cli_rs' && eventName) {
|
|
81
|
-
// const
|
|
82
|
-
//
|
|
83
|
-
// .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
84
|
-
// .join(' ');
|
|
85
|
-
// console.log(`[telemetry:codex] ${eventName} session=${resolvedId.slice(0,8)}${details ? ' ' + details : ''}`);
|
|
113
|
+
// const kind = attrs['event.kind'] ? ` kind=${attrs['event.kind']}` : '';
|
|
114
|
+
// console.log(`[telemetry:codex] ${eventName}${kind} session=${resolvedId.slice(0,8)}`);
|
|
86
115
|
// }
|
|
87
116
|
// if (serviceName === 'gemini-cli' && eventName) console.log(`[telemetry:gemini] ${eventName}`);
|
|
88
117
|
|
|
@@ -101,15 +130,16 @@ function handleLogs(req, res) {
|
|
|
101
130
|
if (eventName === 'codex.user_prompt') {
|
|
102
131
|
codexPendingStop.delete(resolvedId);
|
|
103
132
|
codexOutputDone.delete(resolvedId);
|
|
104
|
-
|
|
133
|
+
codexToolPhasePending.delete(resolvedId);
|
|
134
|
+
clearPendingTools(resolvedId);
|
|
105
135
|
broadcastFn?.({ type: 'session.status', id: resolvedId, working: true, source: 'telemetry' });
|
|
106
136
|
}
|
|
107
137
|
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
138
|
+
// Codex can announce a function-call phase before the later tool_decision
|
|
139
|
+
// event carries a call_id. Block idle as soon as the tool phase is known,
|
|
140
|
+
// then refine it to call-specific tracking when tool_decision arrives.
|
|
111
141
|
if (eventName === 'codex.websocket_event' && attrs['event.kind'] === 'response.function_call_arguments.done') {
|
|
112
|
-
|
|
142
|
+
codexToolPhasePending.add(resolvedId);
|
|
113
143
|
}
|
|
114
144
|
|
|
115
145
|
// Fallback: when notify does not fire, require an output item to finish
|
|
@@ -122,7 +152,7 @@ function handleLogs(req, res) {
|
|
|
122
152
|
// Also poll briefly for a visible choice menu.
|
|
123
153
|
if (eventName === 'codex.sse_event' && attrs['event.kind'] === 'response.completed') {
|
|
124
154
|
const pendingStopAt = codexPendingStop.get(resolvedId);
|
|
125
|
-
if (
|
|
155
|
+
if (hasPendingToolState(resolvedId)) {
|
|
126
156
|
// Tool execution is still in-flight; this completion only closed the
|
|
127
157
|
// function-call phase, not the user's full turn.
|
|
128
158
|
} else if (pendingStopAt && Date.now() - pendingStopAt <= 5000) {
|
|
@@ -146,12 +176,17 @@ function handleLogs(req, res) {
|
|
|
146
176
|
if (eventName === 'codex.tool_decision') {
|
|
147
177
|
codexPendingStop.delete(resolvedId);
|
|
148
178
|
codexOutputDone.delete(resolvedId);
|
|
149
|
-
|
|
179
|
+
if ((attrs.decision || '').toLowerCase() !== 'denied') {
|
|
180
|
+
addPendingTool(resolvedId, attrs.call_id || attrs['call.id']);
|
|
181
|
+
} else {
|
|
182
|
+
codexToolPhasePending.delete(resolvedId);
|
|
183
|
+
}
|
|
150
184
|
cancelCodexMenuPoll(resolvedId);
|
|
151
185
|
broadcastFn?.({ type: 'session.status', id: resolvedId, working: true, source: 'telemetry' });
|
|
152
186
|
}
|
|
153
187
|
if (eventName === 'codex.tool_result') {
|
|
154
|
-
|
|
188
|
+
codexToolPhasePending.delete(resolvedId);
|
|
189
|
+
resolvePendingTool(resolvedId, attrs.call_id || attrs['call.id']);
|
|
155
190
|
}
|
|
156
191
|
// Codex: user_prompt or next sse_event cancels menu poll
|
|
157
192
|
if ((eventName === 'codex.user_prompt' || (eventName === 'codex.sse_event' && attrs['event.kind'] !== 'response.completed'))) {
|
|
@@ -244,7 +279,8 @@ function clear(id) {
|
|
|
244
279
|
cancelCodexPendingIdle(id);
|
|
245
280
|
codexPendingStop.delete(id);
|
|
246
281
|
codexOutputDone.delete(id);
|
|
247
|
-
|
|
282
|
+
codexToolPhasePending.delete(id);
|
|
283
|
+
clearPendingTools(id);
|
|
248
284
|
const pending = pendingSetup.get(id);
|
|
249
285
|
if (pending) { clearTimeout(pending.timer); pendingSetup.delete(id); }
|
|
250
286
|
}
|
package/transcript.js
CHANGED
|
@@ -188,27 +188,38 @@ function getUsers(id) {
|
|
|
188
188
|
return (entriesById[id] || []).filter(e => e.role === 'user').map(e => e.text);
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
function
|
|
192
|
-
n = n || 4;
|
|
191
|
+
function readEntries(id) {
|
|
193
192
|
const file = fpath(id);
|
|
194
193
|
if (!existsSync(file)) return [];
|
|
195
194
|
try {
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
try { entry = JSON.parse(lines[i]); } catch { continue; }
|
|
201
|
-
if (turns.length && turns[turns.length - 1].role === entry.role) {
|
|
202
|
-
turns[turns.length - 1].text = entry.text + '\n' + turns[turns.length - 1].text;
|
|
203
|
-
} else {
|
|
204
|
-
turns.push({ role: entry.role, text: entry.text });
|
|
205
|
-
if (turns.length >= n) break;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return turns.reverse();
|
|
195
|
+
const cached = entriesById[id];
|
|
196
|
+
if (Array.isArray(cached) && cached.length) return cached;
|
|
197
|
+
const lines = readFileSync(file, 'utf8').trim().split('\n').filter(Boolean);
|
|
198
|
+
return lines.map(line => { try { return JSON.parse(line); } catch { return null; } }).filter(Boolean);
|
|
209
199
|
} catch { return []; }
|
|
210
200
|
}
|
|
211
201
|
|
|
202
|
+
function foldTurns(entries, n, order) {
|
|
203
|
+
const turns = [];
|
|
204
|
+
const fromStart = order === 'start';
|
|
205
|
+
const list = fromStart ? entries : [...entries].reverse();
|
|
206
|
+
for (const entry of list) {
|
|
207
|
+
if (turns.length && turns[turns.length - 1].role === entry.role) {
|
|
208
|
+
if (fromStart) turns[turns.length - 1].text += '\n' + entry.text;
|
|
209
|
+
else turns[turns.length - 1].text = entry.text + '\n' + turns[turns.length - 1].text;
|
|
210
|
+
} else {
|
|
211
|
+
turns.push({ role: entry.role, text: entry.text });
|
|
212
|
+
if (turns.length >= n) break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return fromStart ? turns : turns.reverse();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function getTurns(id, n, order) {
|
|
219
|
+
n = n || 4;
|
|
220
|
+
return foldTurns(readEntries(id), n, order || 'end');
|
|
221
|
+
}
|
|
222
|
+
|
|
212
223
|
function getCache() { return { ...cache }; }
|
|
213
224
|
|
|
214
225
|
function getReplayText(id, presetId) {
|
|
@@ -265,4 +276,4 @@ function detectMenu(lines, presetId) {
|
|
|
265
276
|
return choices.length ? choices : null;
|
|
266
277
|
}
|
|
267
278
|
|
|
268
|
-
module.exports = { init, trackInput, recordInjectedInput, trackOutput, updateAgentCandidate, commitAgentCandidate, clearAgentCandidate, parseTurnsFromLines,
|
|
279
|
+
module.exports = { init, trackInput, recordInjectedInput, trackOutput, updateAgentCandidate, commitAgentCandidate, clearAgentCandidate, parseTurnsFromLines, getTurns, getCache, getReplayText, clear, setPrefix, setFinalizeOnIdle, detectMenu };
|