@dmsdc-ai/aigentry-telepty 0.1.61 → 0.1.62
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/package.json +1 -1
- package/tui.js +50 -2
package/package.json
CHANGED
package/tui.js
CHANGED
|
@@ -23,6 +23,7 @@ class TuiDashboard {
|
|
|
23
23
|
this.pollTimer = null;
|
|
24
24
|
this.busWs = null;
|
|
25
25
|
this.busLog = [];
|
|
26
|
+
this.sessionTasks = {}; // { sessionId: { summary, state, updatedAt } }
|
|
26
27
|
this.setupScreen();
|
|
27
28
|
this.startPolling();
|
|
28
29
|
this.connectBus();
|
|
@@ -248,6 +249,35 @@ class TuiDashboard {
|
|
|
248
249
|
this.screen.render();
|
|
249
250
|
}
|
|
250
251
|
|
|
252
|
+
// ── Task extraction from bus events ─────────────────────────
|
|
253
|
+
|
|
254
|
+
parseTaskInfo(content) {
|
|
255
|
+
if (!content || typeof content !== 'string') return null;
|
|
256
|
+
const firstLine = content.split('\n')[0].trim();
|
|
257
|
+
// Extract [tag] patterns: [P0 착수], [완료 보고], [telepty 관점], etc.
|
|
258
|
+
const tagMatch = firstLine.match(/\[([^\]]{2,30})\]/);
|
|
259
|
+
const tag = tagMatch ? tagMatch[1] : null;
|
|
260
|
+
// Detect state from keywords
|
|
261
|
+
let state = 'working';
|
|
262
|
+
if (/완료|complete|done|finish/i.test(firstLine)) state = 'done';
|
|
263
|
+
else if (/토론|deliberat|discuss|synthesis|합의/i.test(firstLine)) state = 'discussing';
|
|
264
|
+
else if (/동의|반대|vote|찬성/i.test(firstLine)) state = 'voting';
|
|
265
|
+
else if (/대기|standby|waiting|idle/i.test(firstLine)) state = 'idle';
|
|
266
|
+
// Build summary (tag or truncated first line)
|
|
267
|
+
const summary = tag || firstLine.replace(/\[.*?\]/g, '').trim().slice(0, 30);
|
|
268
|
+
return { summary, state };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
updateSessionTask(sessionId, content) {
|
|
272
|
+
const info = this.parseTaskInfo(content);
|
|
273
|
+
if (!info || !info.summary) return;
|
|
274
|
+
this.sessionTasks[sessionId] = {
|
|
275
|
+
summary: info.summary,
|
|
276
|
+
state: info.state,
|
|
277
|
+
updatedAt: Date.now()
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
251
281
|
// ── Event Bus ────────────────────────────────────────────────
|
|
252
282
|
|
|
253
283
|
connectBus() {
|
|
@@ -263,16 +293,20 @@ class TuiDashboard {
|
|
|
263
293
|
let line = `${ts} `;
|
|
264
294
|
if (msg.type === 'inject_written') {
|
|
265
295
|
line += `{cyan-fg}inject{/} -> ${msg.target || '?'}`;
|
|
296
|
+
// Track task from inject content
|
|
297
|
+
if (msg.target) this.updateSessionTask(msg.target, msg.content || msg.prompt);
|
|
266
298
|
} else if (msg.type === 'injection') {
|
|
267
299
|
line += `{cyan-fg}broadcast{/} -> ${msg.target_agent || 'all'}`;
|
|
268
300
|
} else if (msg.type === 'message_routed') {
|
|
269
301
|
line += `{yellow-fg}${msg.from || '?'}{/} -> {green-fg}${msg.to || '?'}{/}`;
|
|
302
|
+
if (msg.from) this.updateSessionTask(msg.from, msg.content || msg.prompt);
|
|
270
303
|
} else {
|
|
271
304
|
line += `{white-fg}${msg.type || 'event'}{/}`;
|
|
272
305
|
}
|
|
273
306
|
this.busLog.push(line);
|
|
274
307
|
if (this.busLog.length > 100) this.busLog.shift();
|
|
275
308
|
this.renderBusLog();
|
|
309
|
+
this.renderSessionList(); // refresh task info
|
|
276
310
|
} catch { /* ignore malformed */ }
|
|
277
311
|
});
|
|
278
312
|
this.busWs.on('close', () => {
|
|
@@ -428,9 +462,20 @@ class TuiDashboard {
|
|
|
428
462
|
getStatusInfo(session) {
|
|
429
463
|
const idle = session.idleSeconds;
|
|
430
464
|
const clients = session.active_clients || 0;
|
|
431
|
-
|
|
465
|
+
const task = this.sessionTasks[session.id];
|
|
466
|
+
// Task-aware state (bus events override idle heuristic)
|
|
432
467
|
if (clients === 0) return { icon: '{red-fg}✕{/}', label: '{red-fg}dead{/}' };
|
|
433
468
|
if (idle !== null && idle > STALE_THRESHOLD) return { icon: '{yellow-fg}○{/}', label: '{yellow-fg}stale{/}' };
|
|
469
|
+
if (task && (Date.now() - task.updatedAt) < 300000) { // 5min freshness
|
|
470
|
+
const stateMap = {
|
|
471
|
+
done: { icon: '{green-fg}✓{/}', label: '{green-fg}done{/}' },
|
|
472
|
+
discussing: { icon: '{magenta-fg}◉{/}', label: '{magenta-fg}discuss{/}' },
|
|
473
|
+
voting: { icon: '{magenta-fg}◎{/}', label: '{magenta-fg}vote{/}' },
|
|
474
|
+
working: { icon: '{cyan-fg}●{/}', label: '{cyan-fg}working{/}' },
|
|
475
|
+
idle: { icon: '{green-fg}●{/}', label: '{white-fg}idle{/}' }
|
|
476
|
+
};
|
|
477
|
+
return stateMap[task.state] || stateMap.working;
|
|
478
|
+
}
|
|
434
479
|
if (idle !== null && idle < 10) return { icon: '{green-fg}●{/}', label: '{green-fg}busy{/}' };
|
|
435
480
|
return { icon: '{green-fg}●{/}', label: '{white-fg}idle{/}' };
|
|
436
481
|
}
|
|
@@ -439,7 +484,10 @@ class TuiDashboard {
|
|
|
439
484
|
const items = this.sessions.map((s) => {
|
|
440
485
|
const { icon, label } = this.getStatusInfo(s);
|
|
441
486
|
const shortId = s.id.replace(/^aigentry-/, '').replace(/-claude$/, '');
|
|
442
|
-
|
|
487
|
+
const task = this.sessionTasks[s.id];
|
|
488
|
+
const taskStr = (task && (Date.now() - task.updatedAt) < 300000)
|
|
489
|
+
? ` {gray-fg}${task.summary.slice(0, 20)}{/}` : '';
|
|
490
|
+
return ` ${icon} ${shortId.padEnd(20)} ${label.padEnd(18)}${taskStr}`;
|
|
443
491
|
});
|
|
444
492
|
|
|
445
493
|
this.sessionList.setItems(items);
|