claude-code-watch 0.0.11 → 0.0.14
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/bin/claude-watch.js +75 -59
- package/package.json +1 -1
- package/public/index.html +27 -12
- package/src/server/server.js +14 -4
- package/src/watcher/watcher.js +21 -7
package/bin/claude-watch.js
CHANGED
|
@@ -113,9 +113,8 @@ async function runUpdate() {
|
|
|
113
113
|
console.log(` Latest version: v${latest}`);
|
|
114
114
|
console.log(' Running npm install -g claude-code-watch@latest...\n');
|
|
115
115
|
|
|
116
|
-
const { execSync } = require('child_process');
|
|
117
116
|
try {
|
|
118
|
-
execSync('npm install -g claude-code-watch@latest', { stdio: 'inherit' });
|
|
117
|
+
cp.execSync('npm install -g claude-code-watch@latest', { stdio: 'inherit' });
|
|
119
118
|
console.log(`\n Updated to v${latest}. Restart to use the new version.`);
|
|
120
119
|
} catch {
|
|
121
120
|
console.error('\n Update failed. Try manually: npm install -g claude-code-watch@latest');
|
|
@@ -139,9 +138,16 @@ async function main() {
|
|
|
139
138
|
openBrowser: true,
|
|
140
139
|
};
|
|
141
140
|
|
|
142
|
-
//
|
|
141
|
+
// Action flags
|
|
142
|
+
let listSessionsLimit = 0; // 0 = no list, >0 = limit
|
|
143
|
+
let listActiveLimit = 0; // 0 = no list, >0 = limit, -1 = all
|
|
144
|
+
let showVersion = false;
|
|
145
|
+
let showHelp = false;
|
|
146
|
+
let doUpdate = false;
|
|
147
|
+
|
|
143
148
|
for (let i = 0; i < args.length; i++) {
|
|
144
|
-
|
|
149
|
+
const arg = args[i];
|
|
150
|
+
switch (arg) {
|
|
145
151
|
case '-s':
|
|
146
152
|
options.sessionID = args[++i] || '';
|
|
147
153
|
break;
|
|
@@ -151,7 +157,7 @@ async function main() {
|
|
|
151
157
|
case '-p':
|
|
152
158
|
case '--port': {
|
|
153
159
|
if (i + 1 >= args.length || args[i + 1].startsWith('-')) {
|
|
154
|
-
console.error(`Error: ${
|
|
160
|
+
console.error(`Error: ${arg} requires a port number`);
|
|
155
161
|
process.exit(1);
|
|
156
162
|
}
|
|
157
163
|
const pv = parseInt(args[++i], 10);
|
|
@@ -165,7 +171,7 @@ async function main() {
|
|
|
165
171
|
case '-h':
|
|
166
172
|
case '--host':
|
|
167
173
|
if (i + 1 >= args.length || args[i + 1].startsWith('-')) {
|
|
168
|
-
console.error(`Error: ${
|
|
174
|
+
console.error(`Error: ${arg} requires a host address`);
|
|
169
175
|
process.exit(1);
|
|
170
176
|
}
|
|
171
177
|
options.host = args[++i];
|
|
@@ -196,75 +202,85 @@ async function main() {
|
|
|
196
202
|
case '--no-open':
|
|
197
203
|
options.openBrowser = false;
|
|
198
204
|
break;
|
|
199
|
-
default:
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Second pass: execute action flags with fully resolved options
|
|
205
|
-
for (let i = 0; i < args.length; i++) {
|
|
206
|
-
switch (args[i]) {
|
|
207
205
|
case '-l': {
|
|
208
|
-
const
|
|
209
|
-
const
|
|
206
|
+
const next = args[i + 1];
|
|
207
|
+
const v = parseInt(next);
|
|
208
|
+
listSessionsLimit = !isNaN(v) ? v : 10;
|
|
210
209
|
if (!isNaN(v)) i++;
|
|
211
|
-
|
|
212
|
-
if (sessions.length === 0) {
|
|
213
|
-
console.log('No sessions found.');
|
|
214
|
-
} else {
|
|
215
|
-
const now = Date.now();
|
|
216
|
-
for (const s of sessions) {
|
|
217
|
-
const age = Math.round((now - new Date(s.modified).getTime()) / 1000);
|
|
218
|
-
const ageStr = age < 60 ? `${age}s ago` : age < 3600 ? `${Math.floor(age / 60)}m ago` : `${Math.floor(age / 3600)}h ago`;
|
|
219
|
-
const active = s.isActive ? '●' : '○';
|
|
220
|
-
const id = s.id.length > 40 ? s.id.slice(0, 37) + '...' : s.id;
|
|
221
|
-
console.log(`${active} ${id} ${s.projectPath || '?'} ${ageStr}`);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return;
|
|
210
|
+
break;
|
|
225
211
|
}
|
|
226
212
|
case '-a': {
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
if (!isNaN(v)) i++;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (result.length === 0) {
|
|
233
|
-
console.log('No active sessions found.');
|
|
234
|
-
} else {
|
|
235
|
-
const now = Date.now();
|
|
236
|
-
for (const s of result) {
|
|
237
|
-
const age = Math.round((now - new Date(s.modified).getTime()) / 1000);
|
|
238
|
-
const ageStr = age < 60 ? `${age}s ago` : age < 3600 ? `${Math.floor(age / 60)}m ago` : `${Math.floor(age / 3600)}h ago`;
|
|
239
|
-
const id = s.id.length > 40 ? s.id.slice(0, 37) + '...' : s.id;
|
|
240
|
-
console.log(`● ${id} ${s.projectPath || '?'} ${ageStr}`);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return;
|
|
213
|
+
const next = args[i + 1];
|
|
214
|
+
const v = parseInt(next);
|
|
215
|
+
if (!isNaN(v)) { listActiveLimit = v; i++; }
|
|
216
|
+
else { listActiveLimit = -1; }
|
|
217
|
+
break;
|
|
244
218
|
}
|
|
245
219
|
case '-v':
|
|
246
|
-
|
|
247
|
-
|
|
220
|
+
showVersion = true;
|
|
221
|
+
break;
|
|
248
222
|
case '--help':
|
|
249
|
-
|
|
250
|
-
|
|
223
|
+
showHelp = true;
|
|
224
|
+
break;
|
|
251
225
|
case 'update':
|
|
252
|
-
|
|
253
|
-
return;
|
|
254
|
-
// Skip option flags already handled in first pass
|
|
255
|
-
case '-s': case '-n': case '-p': case '--port':
|
|
256
|
-
case '-h': case '--host': case '-w': case '-c':
|
|
257
|
-
case '-m': case '-D': case '--poll': case '--no-open':
|
|
226
|
+
doUpdate = true;
|
|
258
227
|
break;
|
|
259
228
|
default:
|
|
260
|
-
if (
|
|
261
|
-
console.error(`Unknown option: ${
|
|
229
|
+
if (arg.startsWith('-')) {
|
|
230
|
+
console.error(`Unknown option: ${arg}`);
|
|
262
231
|
printHelp();
|
|
263
232
|
process.exit(1);
|
|
264
233
|
}
|
|
265
234
|
}
|
|
266
235
|
}
|
|
267
236
|
|
|
237
|
+
// Execute action flags
|
|
238
|
+
if (showVersion) {
|
|
239
|
+
printVersion();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (showHelp) {
|
|
243
|
+
printHelp();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (doUpdate) {
|
|
247
|
+
await runUpdate();
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (listSessionsLimit > 0) {
|
|
251
|
+
const sessions = await listSessions(listSessionsLimit);
|
|
252
|
+
if (sessions.length === 0) {
|
|
253
|
+
console.log('No sessions found.');
|
|
254
|
+
} else {
|
|
255
|
+
const now = Date.now();
|
|
256
|
+
for (const s of sessions) {
|
|
257
|
+
const age = Math.round((now - new Date(s.modified).getTime()) / 1000);
|
|
258
|
+
const ageStr = age < 60 ? `${age}s ago` : age < 3600 ? `${Math.floor(age / 60)}m ago` : `${Math.floor(age / 3600)}h ago`;
|
|
259
|
+
const active = s.isActive ? '●' : '○';
|
|
260
|
+
const id = s.id.length > 40 ? s.id.slice(0, 37) + '...' : s.id;
|
|
261
|
+
console.log(`${active} ${id} ${s.projectPath || '?'} ${ageStr}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (listActiveLimit !== 0) {
|
|
267
|
+
const limit = listActiveLimit > 0 ? listActiveLimit : 0;
|
|
268
|
+
const sessions = await listActiveSessions(options.activeWindow);
|
|
269
|
+
const result = limit > 0 ? sessions.slice(0, limit) : sessions;
|
|
270
|
+
if (result.length === 0) {
|
|
271
|
+
console.log('No active sessions found.');
|
|
272
|
+
} else {
|
|
273
|
+
const now = Date.now();
|
|
274
|
+
for (const s of result) {
|
|
275
|
+
const age = Math.round((now - new Date(s.modified).getTime()) / 1000);
|
|
276
|
+
const ageStr = age < 60 ? `${age}s ago` : age < 3600 ? `${Math.floor(age / 60)}m ago` : `${Math.floor(age / 3600)}h ago`;
|
|
277
|
+
const id = s.id.length > 40 ? s.id.slice(0, 37) + '...' : s.id;
|
|
278
|
+
console.log(`● ${id} ${s.projectPath || '?'} ${ageStr}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
268
284
|
checkForUpdate();
|
|
269
285
|
startServer(options);
|
|
270
286
|
}
|
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -194,9 +194,11 @@ body {
|
|
|
194
194
|
.stream-line.diag { color: var(--red); }
|
|
195
195
|
.stream-line.debug { color: var(--gray); }
|
|
196
196
|
.stream-line.marker { color: var(--dim); }
|
|
197
|
-
.stream-line.agent-tag { font-weight: bold; }
|
|
197
|
+
.stream-line.agent-tag { font-weight: bold; display: flex; justify-content: space-between; align-items: baseline; white-space: nowrap; }
|
|
198
198
|
.stream-line.agent-main { color: var(--blue); }
|
|
199
199
|
.stream-line.agent-sub { color: var(--magenta); }
|
|
200
|
+
.stream-line.agent-tag .tag-label { flex-shrink: 0; }
|
|
201
|
+
.stream-line.agent-tag .timestamp { font-weight: normal; font-size: 0.85em; color: var(--dim); white-space: nowrap; }
|
|
200
202
|
.stream-line.separator { color: var(--dim); }
|
|
201
203
|
|
|
202
204
|
/* ── Footer ── */
|
|
@@ -393,16 +395,19 @@ let needsFullRender = true;
|
|
|
393
395
|
// ══════════════════════════════════════════════════════════════════════════════
|
|
394
396
|
|
|
395
397
|
const mdRenderer = new marked.Renderer();
|
|
396
|
-
mdRenderer.code = function (
|
|
398
|
+
mdRenderer.code = function (codeOrObj, langOrEsc) {
|
|
399
|
+
// marked v4: code(text, lang, escaped) — marked v5+: code({ text, lang })
|
|
400
|
+
const text = typeof codeOrObj === 'object' ? codeOrObj.text : codeOrObj;
|
|
401
|
+
const lang = typeof codeOrObj === 'object' ? codeOrObj.lang : langOrEsc;
|
|
397
402
|
let highlighted;
|
|
398
403
|
if (lang && hljs.getLanguage(lang)) {
|
|
399
404
|
try {
|
|
400
|
-
highlighted = hljs.highlight(
|
|
405
|
+
highlighted = hljs.highlight(text, { language: lang }).value;
|
|
401
406
|
} catch {
|
|
402
|
-
highlighted = hljs.highlightAuto(
|
|
407
|
+
highlighted = hljs.highlightAuto(text).value;
|
|
403
408
|
}
|
|
404
409
|
} else {
|
|
405
|
-
highlighted = hljs.highlightAuto(
|
|
410
|
+
highlighted = hljs.highlightAuto(text).value;
|
|
406
411
|
}
|
|
407
412
|
const langTag = lang ? `<span class="lang-tag">${esc(lang)}</span>` : '';
|
|
408
413
|
return `<div class="code-block-wrapper">
|
|
@@ -891,14 +896,15 @@ function renderItem(item) {
|
|
|
891
896
|
}
|
|
892
897
|
|
|
893
898
|
const agentName = item.agentName || 'Main';
|
|
899
|
+
const tsHtml = item.timestamp ? `<span class="timestamp">${fmtTimestamp(item.timestamp)}</span>` : '';
|
|
894
900
|
|
|
895
901
|
switch (item.type) {
|
|
896
902
|
case 'thinking':
|
|
897
|
-
lines.push({ cls: agentTagCls, text: agentName + sep + '🧠 Thinking' });
|
|
903
|
+
lines.push({ cls: agentTagCls, text: `<span class="tag-label">${esc(agentName + sep + '🧠 Thinking')}</span>${tsHtml}`, html: true });
|
|
898
904
|
for (const l of truncContent(item.content)) lines.push({ cls: 'stream-line thinking', text: l });
|
|
899
905
|
break;
|
|
900
906
|
case 'tool_input':
|
|
901
|
-
lines.push({ cls: agentTagCls, text: agentName + sep + `🔧 ${item.toolName || ''}` });
|
|
907
|
+
lines.push({ cls: agentTagCls, text: `<span class="tag-label">${esc(agentName + sep + `🔧 ${item.toolName || ''}`)}</span>${tsHtml}`, html: true });
|
|
902
908
|
for (const l of truncContent(item.content)) lines.push({ cls: 'stream-line tool-input', text: l });
|
|
903
909
|
break;
|
|
904
910
|
case 'tool_output': {
|
|
@@ -908,33 +914,33 @@ function renderItem(item) {
|
|
|
908
914
|
}
|
|
909
915
|
let label = tn ? `📤 ${tn} result` : '📤 Output';
|
|
910
916
|
if (item.durationMs > 0) label += ' ' + fmtDur(item.durationMs);
|
|
911
|
-
lines.push({ cls: agentTagCls, text: agentName + sep + label });
|
|
917
|
+
lines.push({ cls: agentTagCls, text: `<span class="tag-label">${esc(agentName + sep + label)}</span>${tsHtml}`, html: true });
|
|
912
918
|
for (const l of truncContent(item.content)) lines.push({ cls: 'stream-line tool-output', text: l });
|
|
913
919
|
break;
|
|
914
920
|
}
|
|
915
921
|
case 'text':
|
|
916
|
-
lines.push({ cls: agentTagCls, text: agentName + sep + '💬 Response' });
|
|
922
|
+
lines.push({ cls: agentTagCls, text: `<span class="tag-label">${esc(agentName + sep + '💬 Response')}</span>${tsHtml}`, html: true });
|
|
917
923
|
lines.push({ cls: 'stream-line text md-content', text: mdRender(item.content), html: true });
|
|
918
924
|
break;
|
|
919
925
|
case 'hook_output': {
|
|
920
926
|
let label = '🪝 Hook';
|
|
921
927
|
if (item.toolName) label += ' ' + item.toolName;
|
|
922
928
|
if (item.durationMs > 0) label += ' ' + fmtDur(item.durationMs);
|
|
923
|
-
lines.push({ cls: agentTagCls, text: agentName + sep + label });
|
|
929
|
+
lines.push({ cls: agentTagCls, text: `<span class="tag-label">${esc(agentName + sep + label)}</span>${tsHtml}`, html: true });
|
|
924
930
|
for (const l of truncContent(item.content)) lines.push({ cls: 'stream-line hook', text: l });
|
|
925
931
|
break;
|
|
926
932
|
}
|
|
927
933
|
case 'diagnostics': {
|
|
928
934
|
let label = '⚠ Diagnostics';
|
|
929
935
|
if (item.toolName) label += ' ' + item.toolName;
|
|
930
|
-
lines.push({ cls: agentTagCls, text: agentName + sep + label });
|
|
936
|
+
lines.push({ cls: agentTagCls, text: `<span class="tag-label">${esc(agentName + sep + label)}</span>${tsHtml}`, html: true });
|
|
931
937
|
for (const l of truncContent(item.content)) lines.push({ cls: 'stream-line diag', text: l });
|
|
932
938
|
break;
|
|
933
939
|
}
|
|
934
940
|
case 'debug': {
|
|
935
941
|
let label = '🔍 Debug';
|
|
936
942
|
if (item.toolName) label += ' ' + item.toolName;
|
|
937
|
-
lines.push({ cls: agentTagCls, text: agentName + sep + label });
|
|
943
|
+
lines.push({ cls: agentTagCls, text: `<span class="tag-label">${esc(agentName + sep + label)}</span>${tsHtml}`, html: true });
|
|
938
944
|
for (const l of truncContent(item.content)) lines.push({ cls: 'stream-line debug', text: l });
|
|
939
945
|
break;
|
|
940
946
|
}
|
|
@@ -1269,6 +1275,15 @@ function fmtDur(ms) {
|
|
|
1269
1275
|
return `(${(ms / 60000).toFixed(1)}m)`;
|
|
1270
1276
|
}
|
|
1271
1277
|
|
|
1278
|
+
function fmtTimestamp(ts) {
|
|
1279
|
+
if (!ts) return '';
|
|
1280
|
+
const d = ts instanceof Date ? ts : new Date(ts);
|
|
1281
|
+
if (isNaN(d.getTime())) return '';
|
|
1282
|
+
const pad = (n, len) => String(n).padStart(len, '0');
|
|
1283
|
+
const ms = pad(d.getMilliseconds(), 3);
|
|
1284
|
+
return `${pad(d.getFullYear(),4)}-${pad(d.getMonth()+1,2)}-${pad(d.getDate(),2)} ${pad(d.getHours(),2)}:${pad(d.getMinutes(),2)}:${pad(d.getSeconds(),2)}.${ms}`;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1272
1287
|
function fmtTok(n) {
|
|
1273
1288
|
if (!n) return '0';
|
|
1274
1289
|
if (n < 1000) return String(n);
|
package/src/server/server.js
CHANGED
|
@@ -55,6 +55,8 @@ class DashboardServer {
|
|
|
55
55
|
ctx = { inputTokens: 0, outputTokens: 0, cacheCreation: 0, cacheRead: 0, model: '', contextWindow: 200000, lastActivity: Date.now() };
|
|
56
56
|
this.contextMap.set(key, ctx);
|
|
57
57
|
}
|
|
58
|
+
// inputTokens: Claude API returns cumulative total per call, not incremental — use Math.max
|
|
59
|
+
// outputTokens/cache tokens: API returns incremental values — use +=
|
|
58
60
|
if (item.inputTokens) ctx.inputTokens = Math.max(ctx.inputTokens, item.inputTokens);
|
|
59
61
|
if (item.outputTokens) ctx.outputTokens += item.outputTokens;
|
|
60
62
|
if (item.cacheCreationTokens) ctx.cacheCreation += item.cacheCreationTokens;
|
|
@@ -101,7 +103,9 @@ class DashboardServer {
|
|
|
101
103
|
}
|
|
102
104
|
for (const ws of toRemove) {
|
|
103
105
|
this.clients.delete(ws);
|
|
104
|
-
try { ws.terminate(); } catch {
|
|
106
|
+
try { ws.terminate(); } catch (err) {
|
|
107
|
+
if (this.debugAll) console.error('[server] terminate error:', err.message);
|
|
108
|
+
}
|
|
105
109
|
}
|
|
106
110
|
}
|
|
107
111
|
|
|
@@ -224,7 +228,9 @@ class DashboardServer {
|
|
|
224
228
|
try {
|
|
225
229
|
const cmd = JSON.parse(data.toString('utf-8'));
|
|
226
230
|
this.handleCommand(ws, cmd);
|
|
227
|
-
} catch {
|
|
231
|
+
} catch (err) {
|
|
232
|
+
if (this.debugAll) console.error('[server] WS message error:', err.message);
|
|
233
|
+
}
|
|
228
234
|
});
|
|
229
235
|
|
|
230
236
|
ws.on('close', () => {
|
|
@@ -373,7 +379,9 @@ class DashboardServer {
|
|
|
373
379
|
} else {
|
|
374
380
|
process.kill(parsedPid, 'SIGTERM');
|
|
375
381
|
}
|
|
376
|
-
} catch {
|
|
382
|
+
} catch (err) {
|
|
383
|
+
console.error(`[server] Failed to SIGTERM pid ${parsedPid}: ${err.message}`);
|
|
384
|
+
}
|
|
377
385
|
}
|
|
378
386
|
}
|
|
379
387
|
|
|
@@ -383,7 +391,9 @@ class DashboardServer {
|
|
|
383
391
|
for (const pid of pids) {
|
|
384
392
|
const parsedPid = parseInt(pid, 10);
|
|
385
393
|
if (Number.isInteger(parsedPid) && parsedPid > 1 && parsedPid !== myPid) {
|
|
386
|
-
try { process.kill(parsedPid, 0); process.kill(parsedPid, 'SIGKILL'); } catch {
|
|
394
|
+
try { process.kill(parsedPid, 0); process.kill(parsedPid, 'SIGKILL'); } catch {
|
|
395
|
+
// Process already gone — nothing to do
|
|
396
|
+
}
|
|
387
397
|
}
|
|
388
398
|
}
|
|
389
399
|
}
|
package/src/watcher/watcher.js
CHANGED
|
@@ -424,15 +424,21 @@ class Watcher extends EventEmitter {
|
|
|
424
424
|
|
|
425
425
|
if (p.endsWith('.jsonl')) {
|
|
426
426
|
if (p.includes('/subagents/')) {
|
|
427
|
-
this._handleNewSubagentFile(p)
|
|
427
|
+
this._handleNewSubagentFile(p).catch(err => {
|
|
428
|
+
if (this.debug) console.error('[watcher] _handleNewSubagentFile error:', err.message);
|
|
429
|
+
});
|
|
428
430
|
} else if (this.watchActive) {
|
|
429
|
-
this._handleNewSessionFile(p)
|
|
431
|
+
this._handleNewSessionFile(p).catch(err => {
|
|
432
|
+
if (this.debug) console.error('[watcher] _handleNewSessionFile error:', err.message);
|
|
433
|
+
});
|
|
430
434
|
}
|
|
431
435
|
return;
|
|
432
436
|
}
|
|
433
437
|
|
|
434
438
|
if (p.endsWith('.txt') && p.includes('/tool-results/')) {
|
|
435
|
-
this._handleNewToolResultFile(p)
|
|
439
|
+
this._handleNewToolResultFile(p).catch(err => {
|
|
440
|
+
if (this.debug) console.error('[watcher] _handleNewToolResultFile error:', err.message);
|
|
441
|
+
});
|
|
436
442
|
}
|
|
437
443
|
}
|
|
438
444
|
|
|
@@ -448,9 +454,13 @@ class Watcher extends EventEmitter {
|
|
|
448
454
|
continue;
|
|
449
455
|
}
|
|
450
456
|
if (base === 'subagents' && entry.name.endsWith('.jsonl')) {
|
|
451
|
-
this._handleNewSubagentFile(fullPath)
|
|
457
|
+
this._handleNewSubagentFile(fullPath).catch(err => {
|
|
458
|
+
if (this.debug) console.error('[watcher] _handleNewSubagentFile error:', err.message);
|
|
459
|
+
});
|
|
452
460
|
} else if (base === 'tool-results' && entry.name.endsWith('.txt')) {
|
|
453
|
-
this._handleNewToolResultFile(fullPath)
|
|
461
|
+
this._handleNewToolResultFile(fullPath).catch(err => {
|
|
462
|
+
if (this.debug) console.error('[watcher] _handleNewToolResultFile error:', err.message);
|
|
463
|
+
});
|
|
454
464
|
}
|
|
455
465
|
}
|
|
456
466
|
}
|
|
@@ -542,7 +552,9 @@ class Watcher extends EventEmitter {
|
|
|
542
552
|
this.pendingSubagents.delete(session.id);
|
|
543
553
|
for (const sp of pending) {
|
|
544
554
|
const agentID = path.basename(sp).replace(/^agent-/, '').replace(/\.jsonl$/, '');
|
|
545
|
-
this._registerSubagent(session, session.id, agentID, sp)
|
|
555
|
+
this._registerSubagent(session, session.id, agentID, sp).catch(err => {
|
|
556
|
+
if (this.debug) console.error('[watcher] _registerSubagent error (pending):', err.message);
|
|
557
|
+
});
|
|
546
558
|
}
|
|
547
559
|
}
|
|
548
560
|
}
|
|
@@ -561,7 +573,9 @@ class Watcher extends EventEmitter {
|
|
|
561
573
|
return;
|
|
562
574
|
}
|
|
563
575
|
|
|
564
|
-
this._registerSubagent(session, sessionID, agentID, p)
|
|
576
|
+
this._registerSubagent(session, sessionID, agentID, p).catch(err => {
|
|
577
|
+
if (this.debug) console.error('[watcher] _registerSubagent error:', err.message);
|
|
578
|
+
});
|
|
565
579
|
}
|
|
566
580
|
|
|
567
581
|
async _registerSubagent(session, sessionID, agentID, p) {
|