fix: correct Task tool description extraction for subagent window titles

- Add parseTaskDescriptionsFromTerminalData() to parse raw terminal data in
  interactive sessions (not just one-shot mode)
- Strip ANSI codes before regex matching since terminal output has embedded
  codes like [1mExplore[0m
- Fix getTaskDescriptionForSubagent() to check ALL sessions with matching
  project hash (not just the first one found) since multiple sessions can
  share the same working directory
- Add tool_result event forwarding for subagent SSE broadcasts

The pattern Explore(Description) in terminal output is now correctly parsed
and used as the subagent window title instead of extracting from the prompt.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-26 10:42:04 +01:00
co-authored by Claude Opus 4.5
parent f06240f4ef
commit fc940e153b
5 changed files with 519 additions and 54 deletions
+14 -26
View File
@@ -28,7 +28,7 @@ import { getStore } from '../state-store.js';
import { generateClaudeMd } from '../templates/claude-md.js';
import { parseRalphLoopConfig, extractCompletionPhrase } from '../ralph-config.js';
import { writeHooksConfig } from '../hooks-config.js';
import { subagentWatcher, type SubagentInfo, type SubagentToolCall, type SubagentProgress, type SubagentMessage } from '../subagent-watcher.js';
import { subagentWatcher, type SubagentInfo, type SubagentToolCall, type SubagentProgress, type SubagentMessage, type SubagentToolResult } from '../subagent-watcher.js';
import { TranscriptWatcher } from '../transcript-watcher.js';
import { v4 as uuidv4 } from 'uuid';
import { createRequire } from 'node:module';
@@ -339,6 +339,10 @@ export class WebServer extends EventEmitter {
this.broadcast('subagent:tool_call', data);
});
subagentWatcher.on('subagent:tool_result', (data: SubagentToolResult) => {
this.broadcast('subagent:tool_result', data);
});
subagentWatcher.on('subagent:progress', (data: SubagentProgress) => {
this.broadcast('subagent:progress', data);
});
@@ -370,35 +374,19 @@ export class WebServer extends EventEmitter {
* matches the subagent's project hash, then checking for recent tasks.
*/
private getTaskDescriptionForSubagent(info: SubagentInfo): string | undefined {
// Find the session whose working directory matches this subagent's project
// Find sessions whose working directory matches this subagent's project
// Check ALL matching sessions since multiple sessions may have the same working directory
const subagentStartTime = new Date(info.startedAt).getTime();
for (const session of this.sessions.values()) {
const sessionProjectHash = subagentWatcher.getProjectHashForDir(session.workingDir);
if (sessionProjectHash === info.projectHash) {
// Found the owning session - check its TaskTracker for recent tasks
// Get all tasks from the tracker
const allTasks = Array.from(session.taskTracker.getAllTasks().values());
if (allTasks.length > 0) {
// Sort by start time descending to get most recent first
const recentTasks = allTasks.sort((a, b) => (b.startTime || 0) - (a.startTime || 0));
// Check if there's a task that started recently (within 5 seconds of subagent discovery)
const subagentStartTime = new Date(info.startedAt).getTime();
for (const task of recentTasks) {
const taskStartTime = task.startTime || 0;
const timeDiff = Math.abs(subagentStartTime - taskStartTime);
// If the task started within 5 seconds of the subagent, use its description
if (timeDiff < 5000 && task.description) {
return task.description;
}
}
// Fallback: use the most recent running task's description
const runningTask = recentTasks.find(t => t.status === 'running');
if (runningTask?.description) {
return runningTask.description;
}
// Found a matching session - check for recent task descriptions parsed from terminal
// The Session parses "Explore(Description)" patterns from Claude Code output
const description = session.findTaskDescriptionNear(subagentStartTime, 15000);
if (description) {
return description;
}
break; // Found the session, no need to continue
}
}
return undefined;