aicodeman 0.5.2 → 0.5.4

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.
Files changed (144) hide show
  1. package/dist/ai-checker-base.d.ts.map +1 -1
  2. package/dist/ai-checker-base.js +3 -2
  3. package/dist/ai-checker-base.js.map +1 -1
  4. package/dist/bash-tool-parser.d.ts +6 -0
  5. package/dist/bash-tool-parser.d.ts.map +1 -1
  6. package/dist/bash-tool-parser.js +87 -101
  7. package/dist/bash-tool-parser.js.map +1 -1
  8. package/dist/file-stream-manager.d.ts.map +1 -1
  9. package/dist/file-stream-manager.js +2 -1
  10. package/dist/file-stream-manager.js.map +1 -1
  11. package/dist/orchestrator-loop.d.ts +2 -0
  12. package/dist/orchestrator-loop.d.ts.map +1 -1
  13. package/dist/orchestrator-loop.js +27 -22
  14. package/dist/orchestrator-loop.js.map +1 -1
  15. package/dist/orchestrator-verifier.d.ts +1 -1
  16. package/dist/orchestrator-verifier.d.ts.map +1 -1
  17. package/dist/orchestrator-verifier.js +3 -2
  18. package/dist/orchestrator-verifier.js.map +1 -1
  19. package/dist/plan-orchestrator.d.ts +4 -1
  20. package/dist/plan-orchestrator.d.ts.map +1 -1
  21. package/dist/plan-orchestrator.js +66 -88
  22. package/dist/plan-orchestrator.js.map +1 -1
  23. package/dist/ralph-status-parser.d.ts +2 -0
  24. package/dist/ralph-status-parser.d.ts.map +1 -1
  25. package/dist/ralph-status-parser.js +98 -102
  26. package/dist/ralph-status-parser.js.map +1 -1
  27. package/dist/ralph-tracker.d.ts +9 -0
  28. package/dist/ralph-tracker.d.ts.map +1 -1
  29. package/dist/ralph-tracker.js +52 -60
  30. package/dist/ralph-tracker.js.map +1 -1
  31. package/dist/respawn-controller.d.ts +18 -1
  32. package/dist/respawn-controller.d.ts.map +1 -1
  33. package/dist/respawn-controller.js +215 -181
  34. package/dist/respawn-controller.js.map +1 -1
  35. package/dist/session-auto-ops.d.ts.map +1 -1
  36. package/dist/session-auto-ops.js +57 -55
  37. package/dist/session-auto-ops.js.map +1 -1
  38. package/dist/session.d.ts +5 -0
  39. package/dist/session.d.ts.map +1 -1
  40. package/dist/session.js +182 -218
  41. package/dist/session.js.map +1 -1
  42. package/dist/state-store.d.ts +6 -0
  43. package/dist/state-store.d.ts.map +1 -1
  44. package/dist/state-store.js +67 -79
  45. package/dist/state-store.js.map +1 -1
  46. package/dist/subagent-watcher.d.ts +24 -0
  47. package/dist/subagent-watcher.d.ts.map +1 -1
  48. package/dist/subagent-watcher.js +215 -220
  49. package/dist/subagent-watcher.js.map +1 -1
  50. package/dist/tmux-manager.d.ts +17 -0
  51. package/dist/tmux-manager.d.ts.map +1 -1
  52. package/dist/tmux-manager.js +57 -66
  53. package/dist/tmux-manager.js.map +1 -1
  54. package/dist/tunnel-manager.d.ts.map +1 -1
  55. package/dist/tunnel-manager.js +2 -1
  56. package/dist/tunnel-manager.js.map +1 -1
  57. package/dist/web/public/api-client.3adebdc2.js.gz +0 -0
  58. package/dist/web/public/app.16290ae3.js +26 -0
  59. package/dist/web/public/app.16290ae3.js.br +0 -0
  60. package/dist/web/public/app.16290ae3.js.gz +0 -0
  61. package/dist/web/public/constants.64161167.js.gz +0 -0
  62. package/dist/web/public/index.html +7 -7
  63. package/dist/web/public/index.html.br +0 -0
  64. package/dist/web/public/index.html.gz +0 -0
  65. package/dist/web/public/input-cjk.88082175.js.gz +0 -0
  66. package/dist/web/public/keyboard-accessory.9fb81db6.js.gz +0 -0
  67. package/dist/web/public/mobile-handlers.1e2a8ef8.js.gz +0 -0
  68. package/dist/web/public/mobile.0b213796.css.gz +0 -0
  69. package/dist/web/public/notification-manager.2d5ea8ec.js.gz +0 -0
  70. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  71. package/dist/web/public/{panels-ui.8204db1e.js → panels-ui.2d5b9703.js} +1 -1
  72. package/dist/web/public/panels-ui.2d5b9703.js.br +0 -0
  73. package/dist/web/public/panels-ui.2d5b9703.js.gz +0 -0
  74. package/dist/web/public/{ralph-panel.a2733fd5.js → ralph-panel.61076370.js} +1 -1
  75. package/dist/web/public/ralph-panel.61076370.js.br +0 -0
  76. package/dist/web/public/ralph-panel.61076370.js.gz +0 -0
  77. package/dist/web/public/ralph-wizard.f31ab90e.js.gz +0 -0
  78. package/dist/web/public/{respawn-ui.372c6ea7.js → respawn-ui.60be6ef5.js} +1 -1
  79. package/dist/web/public/respawn-ui.60be6ef5.js.br +0 -0
  80. package/dist/web/public/respawn-ui.60be6ef5.js.gz +0 -0
  81. package/dist/web/public/{session-ui.72f2f538.js → session-ui.554092ae.js} +1 -1
  82. package/dist/web/public/session-ui.554092ae.js.br +0 -0
  83. package/dist/web/public/session-ui.554092ae.js.gz +0 -0
  84. package/dist/web/public/{settings-ui.bd3eaadb.js → settings-ui.c58b0b9b.js} +7 -7
  85. package/dist/web/public/settings-ui.c58b0b9b.js.br +0 -0
  86. package/dist/web/public/settings-ui.c58b0b9b.js.gz +0 -0
  87. package/dist/web/public/styles.111ff326.css.gz +0 -0
  88. package/dist/web/public/subagent-windows.a366a4ad.js.gz +0 -0
  89. package/dist/web/public/sw.js.gz +0 -0
  90. package/dist/web/public/terminal-ui.474f79df.js.gz +0 -0
  91. package/dist/web/public/upload.html.gz +0 -0
  92. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  93. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  94. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  95. package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
  96. package/dist/web/public/vendor/xterm.css.gz +0 -0
  97. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  98. package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
  99. package/dist/web/respawn-event-wiring.d.ts +51 -0
  100. package/dist/web/respawn-event-wiring.d.ts.map +1 -0
  101. package/dist/web/respawn-event-wiring.js +280 -0
  102. package/dist/web/respawn-event-wiring.js.map +1 -0
  103. package/dist/web/route-helpers.d.ts +23 -0
  104. package/dist/web/route-helpers.d.ts.map +1 -1
  105. package/dist/web/route-helpers.js +53 -0
  106. package/dist/web/route-helpers.js.map +1 -1
  107. package/dist/web/routes/case-routes.d.ts.map +1 -1
  108. package/dist/web/routes/case-routes.js +2 -11
  109. package/dist/web/routes/case-routes.js.map +1 -1
  110. package/dist/web/routes/file-routes.d.ts.map +1 -1
  111. package/dist/web/routes/file-routes.js +8 -24
  112. package/dist/web/routes/file-routes.js.map +1 -1
  113. package/dist/web/routes/orchestrator-routes.d.ts.map +1 -1
  114. package/dist/web/routes/orchestrator-routes.js +23 -30
  115. package/dist/web/routes/orchestrator-routes.js.map +1 -1
  116. package/dist/web/routes/system-routes.d.ts.map +1 -1
  117. package/dist/web/routes/system-routes.js +17 -71
  118. package/dist/web/routes/system-routes.js.map +1 -1
  119. package/dist/web/server.d.ts +4 -51
  120. package/dist/web/server.d.ts.map +1 -1
  121. package/dist/web/server.js +98 -941
  122. package/dist/web/server.js.map +1 -1
  123. package/dist/web/session-listener-wiring.d.ts +89 -0
  124. package/dist/web/session-listener-wiring.d.ts.map +1 -0
  125. package/dist/web/session-listener-wiring.js +290 -0
  126. package/dist/web/session-listener-wiring.js.map +1 -0
  127. package/dist/web/sse-stream-manager.d.ts +91 -0
  128. package/dist/web/sse-stream-manager.d.ts.map +1 -0
  129. package/dist/web/sse-stream-manager.js +426 -0
  130. package/dist/web/sse-stream-manager.js.map +1 -0
  131. package/package.json +1 -1
  132. package/dist/web/public/app.e09fd4a6.js +0 -26
  133. package/dist/web/public/app.e09fd4a6.js.br +0 -0
  134. package/dist/web/public/app.e09fd4a6.js.gz +0 -0
  135. package/dist/web/public/panels-ui.8204db1e.js.br +0 -0
  136. package/dist/web/public/panels-ui.8204db1e.js.gz +0 -0
  137. package/dist/web/public/ralph-panel.a2733fd5.js.br +0 -0
  138. package/dist/web/public/ralph-panel.a2733fd5.js.gz +0 -0
  139. package/dist/web/public/respawn-ui.372c6ea7.js.br +0 -0
  140. package/dist/web/public/respawn-ui.372c6ea7.js.gz +0 -0
  141. package/dist/web/public/session-ui.72f2f538.js.br +0 -0
  142. package/dist/web/public/session-ui.72f2f538.js.gz +0 -0
  143. package/dist/web/public/settings-ui.bd3eaadb.js.br +0 -0
  144. package/dist/web/public/settings-ui.bd3eaadb.js.gz +0 -0
@@ -146,6 +146,24 @@ export declare class SubagentWatcher extends EventEmitter {
146
146
  * Also filters out very short descriptions that are likely internal or malformed.
147
147
  */
148
148
  private isInternalAgent;
149
+ /**
150
+ * Mark a subagent as completed: clear PID, set status, clean up pending tool calls, emit event.
151
+ */
152
+ private markSubagentAsCompleted;
153
+ /**
154
+ * Extract text from message content, handling both string and array formats.
155
+ * For array content, returns the text from the first 'text' block.
156
+ */
157
+ private extractFirstTextContent;
158
+ /**
159
+ * Process a tool_result content block: look up pending tool call, emit tool_result event.
160
+ */
161
+ private emitToolResult;
162
+ /**
163
+ * Find the oldest inactive (non-active) agent for LRU eviction.
164
+ * Returns the agent ID of the oldest inactive agent, or null if all are active.
165
+ */
166
+ private findOldestInactiveAgent;
149
167
  /**
150
168
  * Extract short model identifier from full model name
151
169
  */
@@ -294,6 +312,7 @@ export declare class SubagentWatcher extends EventEmitter {
294
312
  * Aims for ~40-50 chars that convey what the agent is doing
295
313
  */
296
314
  private extractSmartTitle;
315
+ private _resolveDescription;
297
316
  /**
298
317
  * Extract the short description from the parent session's transcript.
299
318
  * This is the most reliable method because it reads the actual Task tool result
@@ -343,6 +362,11 @@ export declare class SubagentWatcher extends EventEmitter {
343
362
  * Process a transcript entry and emit appropriate events
344
363
  */
345
364
  private processEntry;
365
+ private _processModelInfo;
366
+ private _processTokenInfo;
367
+ private _processDescription;
368
+ private _processAssistantContent;
369
+ private _processUserContent;
346
370
  /**
347
371
  * Extract text content from tool_result content field
348
372
  */
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-watcher.d.ts","sourceRoot":"","sources":["../src/subagent-watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subagent-watcher.d.ts","sourceRoot":"","sources":["../src/subagent-watcher.ts"],"names":[],"mappings":"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"}
@@ -106,6 +106,72 @@ export class SubagentWatcher extends EventEmitter {
106
106
  return true;
107
107
  return INTERNAL_AGENT_PATTERNS.some((pattern) => pattern.test(description));
108
108
  }
109
+ /**
110
+ * Mark a subagent as completed: clear PID, set status, clean up pending tool calls, emit event.
111
+ */
112
+ markSubagentAsCompleted(info) {
113
+ info.pid = undefined;
114
+ info.status = 'completed';
115
+ this.pendingToolCalls.delete(info.agentId);
116
+ this.emit('subagent:completed', info);
117
+ }
118
+ /**
119
+ * Extract text from message content, handling both string and array formats.
120
+ * For array content, returns the text from the first 'text' block.
121
+ */
122
+ extractFirstTextContent(content) {
123
+ if (!content)
124
+ return undefined;
125
+ if (typeof content === 'string') {
126
+ const trimmed = content.trim();
127
+ return trimmed.length > 0 ? trimmed : undefined;
128
+ }
129
+ if (Array.isArray(content)) {
130
+ const firstContent = content[0];
131
+ if (firstContent?.type === 'text' && firstContent.text) {
132
+ const trimmed = firstContent.text.trim();
133
+ return trimmed.length > 0 ? trimmed : undefined;
134
+ }
135
+ }
136
+ return undefined;
137
+ }
138
+ /**
139
+ * Process a tool_result content block: look up pending tool call, emit tool_result event.
140
+ */
141
+ emitToolResult(content, agentId, sessionId, timestamp) {
142
+ const resultContent = this.extractToolResultContent(content.content);
143
+ const agentPendingCalls = this.pendingToolCalls.get(agentId);
144
+ const pendingCall = agentPendingCalls?.get(content.tool_use_id);
145
+ const toolName = pendingCall?.toolName;
146
+ // Delete after lookup to prevent memory leak
147
+ agentPendingCalls?.delete(content.tool_use_id);
148
+ const toolResult = {
149
+ agentId,
150
+ sessionId,
151
+ timestamp,
152
+ toolUseId: content.tool_use_id,
153
+ tool: toolName,
154
+ preview: resultContent.substring(0, MESSAGE_TEXT_LIMIT),
155
+ contentLength: resultContent.length,
156
+ isError: content.is_error || false,
157
+ };
158
+ this.emit('subagent:tool_result', toolResult);
159
+ }
160
+ /**
161
+ * Find the oldest inactive (non-active) agent for LRU eviction.
162
+ * Returns the agent ID of the oldest inactive agent, or null if all are active.
163
+ */
164
+ findOldestInactiveAgent() {
165
+ let oldestId = null;
166
+ let oldestTime = Infinity;
167
+ for (const [id, existing] of this.agentInfo) {
168
+ if (existing.status !== 'active' && existing.lastActivityAt < oldestTime) {
169
+ oldestTime = existing.lastActivityAt;
170
+ oldestId = id;
171
+ }
172
+ }
173
+ return oldestId;
174
+ }
109
175
  /**
110
176
  * Extract short model identifier from full model name
111
177
  */
@@ -181,10 +247,7 @@ export class SubagentWatcher extends EventEmitter {
181
247
  continue;
182
248
  const alive = this.checkSubagentAliveFromPidMap(info, pidMap);
183
249
  if (!alive) {
184
- info.pid = undefined;
185
- info.status = 'completed';
186
- this.pendingToolCalls.delete(info.agentId);
187
- this.emit('subagent:completed', info);
250
+ this.markSubagentAsCompleted(info);
188
251
  }
189
252
  }
190
253
  }
@@ -512,10 +575,7 @@ export class SubagentWatcher extends EventEmitter {
512
575
  const pid = await this.findSubagentProcess(info.sessionId);
513
576
  if (pid) {
514
577
  process.kill(pid, 'SIGTERM');
515
- info.pid = undefined;
516
- info.status = 'completed';
517
- this.pendingToolCalls.delete(info.agentId);
518
- this.emit('subagent:completed', info);
578
+ this.markSubagentAsCompleted(info);
519
579
  return true;
520
580
  }
521
581
  }
@@ -523,10 +583,7 @@ export class SubagentWatcher extends EventEmitter {
523
583
  // Process may have already exited
524
584
  }
525
585
  // Mark as completed even if we couldn't find the process
526
- info.pid = undefined;
527
- info.status = 'completed';
528
- this.pendingToolCalls.delete(info.agentId);
529
- this.emit('subagent:completed', info);
586
+ this.markSubagentAsCompleted(info);
530
587
  return true;
531
588
  }
532
589
  /**
@@ -675,20 +732,9 @@ export class SubagentWatcher extends EventEmitter {
675
732
  }
676
733
  else if (entry.type === 'user' && entry.message?.content) {
677
734
  // Handle both string and array content formats
678
- if (typeof entry.message.content === 'string') {
679
- const text = entry.message.content.trim();
680
- if (text.length < 100 && !text.includes('{')) {
681
- lines.push(`${this.formatTime(entry.timestamp)} 📥 User: ${text.substring(0, USER_TEXT_PREVIEW_LENGTH)}`);
682
- }
683
- }
684
- else {
685
- const firstContent = entry.message.content[0];
686
- if (firstContent?.type === 'text' && firstContent.text) {
687
- const text = firstContent.text.trim();
688
- if (text.length < 100 && !text.includes('{')) {
689
- lines.push(`${this.formatTime(entry.timestamp)} 📥 User: ${text.substring(0, USER_TEXT_PREVIEW_LENGTH)}`);
690
- }
691
- }
735
+ const text = this.extractFirstTextContent(entry.message.content);
736
+ if (text && text.length < 100 && !text.includes('{')) {
737
+ lines.push(`${this.formatTime(entry.timestamp)} 📥 User: ${text.substring(0, USER_TEXT_PREVIEW_LENGTH)}`);
692
738
  }
693
739
  }
694
740
  }
@@ -753,6 +799,17 @@ export class SubagentWatcher extends EventEmitter {
753
799
  }
754
800
  return truncated.replace(/[.!?,:\s]+$/, '');
755
801
  }
802
+ async _resolveDescription(projectHash, sessionId, agentId, filePath, fallbackText) {
803
+ // First try parent transcript (most reliable)
804
+ const fromParent = await this.extractDescriptionFromParentTranscript(projectHash, sessionId, agentId);
805
+ if (fromParent)
806
+ return fromParent;
807
+ // Fallback: inline text (from processEntry) or file extraction
808
+ if (fallbackText) {
809
+ return this.extractSmartTitle(fallbackText);
810
+ }
811
+ return this.extractDescriptionFromFile(filePath);
812
+ }
756
813
  /**
757
814
  * Extract the short description from the parent session's transcript.
758
815
  * This is the most reliable method because it reads the actual Task tool result
@@ -843,16 +900,7 @@ export class SubagentWatcher extends EventEmitter {
843
900
  try {
844
901
  const entry = JSON.parse(line);
845
902
  if (entry.type === 'user' && entry.message?.content) {
846
- let text;
847
- if (typeof entry.message.content === 'string') {
848
- text = entry.message.content.trim();
849
- }
850
- else if (Array.isArray(entry.message.content)) {
851
- const firstContent = entry.message.content[0];
852
- if (firstContent?.type === 'text' && firstContent.text) {
853
- text = firstContent.text.trim();
854
- }
855
- }
903
+ const text = this.extractFirstTextContent(entry.message.content);
856
904
  if (text) {
857
905
  resolved = true;
858
906
  rl.close();
@@ -1012,14 +1060,8 @@ export class SubagentWatcher extends EventEmitter {
1012
1060
  }
1013
1061
  // Retry description extraction if missing (race condition fix)
1014
1062
  if (!existingInfo.description) {
1015
- // First try parent transcript (most reliable)
1016
- let extractedDescription = await this.extractDescriptionFromParentTranscript(existingInfo.projectHash, existingInfo.sessionId, agentId);
1017
- // Fallback to subagent file
1018
- if (!extractedDescription) {
1019
- extractedDescription = await this.extractDescriptionFromFile(filePath);
1020
- }
1063
+ const extractedDescription = await this._resolveDescription(existingInfo.projectHash, existingInfo.sessionId, agentId, filePath);
1021
1064
  if (extractedDescription) {
1022
- // Check if this is an internal agent - if so, remove it
1023
1065
  if (this.isInternalAgent(extractedDescription)) {
1024
1066
  this.removeAgent(agentId);
1025
1067
  return;
@@ -1061,12 +1103,7 @@ export class SubagentWatcher extends EventEmitter {
1061
1103
  }
1062
1104
  }
1063
1105
  // Extract description - prefer reading from parent transcript (most reliable)
1064
- // The parent transcript has the exact Task tool call with description parameter
1065
- let description = await this.extractDescriptionFromParentTranscript(projectHash, sessionId, agentId);
1066
- // Fallback: extract a smart title from the subagent's prompt if parent lookup failed
1067
- if (!description) {
1068
- description = await this.extractDescriptionFromFile(filePath);
1069
- }
1106
+ const description = await this._resolveDescription(projectHash, sessionId, agentId, filePath);
1070
1107
  // Skip internal Claude Code agents (e.g., suggestion mode) - not real subagents
1071
1108
  if (this.isInternalAgent(description)) {
1072
1109
  return;
@@ -1086,14 +1123,7 @@ export class SubagentWatcher extends EventEmitter {
1086
1123
  };
1087
1124
  // Enforce MAX_TRACKED_AGENTS during insertion — evict oldest inactive agent
1088
1125
  if (this.agentInfo.size >= MAX_TRACKED_AGENTS) {
1089
- let oldestId = null;
1090
- let oldestTime = Infinity;
1091
- for (const [id, existing] of this.agentInfo) {
1092
- if (existing.status !== 'active' && existing.lastActivityAt < oldestTime) {
1093
- oldestTime = existing.lastActivityAt;
1094
- oldestId = id;
1095
- }
1096
- }
1126
+ const oldestId = this.findOldestInactiveAgent();
1097
1127
  if (oldestId) {
1098
1128
  this.removeAgent(oldestId);
1099
1129
  }
@@ -1152,50 +1182,11 @@ export class SubagentWatcher extends EventEmitter {
1152
1182
  */
1153
1183
  async processEntry(entry, agentId, sessionId) {
1154
1184
  const info = this.agentInfo.get(agentId);
1155
- // Extract model from assistant messages (first one sets the model)
1156
- if (info && entry.type === 'assistant' && entry.message?.model && !info.model) {
1157
- info.model = entry.message.model;
1158
- info.modelShort = this.extractModelShort(entry.message.model);
1159
- this.emit('subagent:updated', info);
1160
- }
1161
- // Aggregate token usage from messages
1162
- if (info && entry.message?.usage) {
1163
- if (entry.message.usage.input_tokens) {
1164
- info.totalInputTokens = (info.totalInputTokens || 0) + entry.message.usage.input_tokens;
1165
- }
1166
- if (entry.message.usage.output_tokens) {
1167
- info.totalOutputTokens = (info.totalOutputTokens || 0) + entry.message.usage.output_tokens;
1168
- }
1169
- }
1170
- // Check if this is first user message and description is missing
1171
- if (info && !info.description && entry.type === 'user' && entry.message?.content) {
1172
- // First try parent transcript (most reliable)
1173
- let description = await this.extractDescriptionFromParentTranscript(info.projectHash, info.sessionId, agentId);
1174
- // Fallback: extract smart title from the prompt content
1175
- if (!description) {
1176
- let text;
1177
- if (typeof entry.message.content === 'string') {
1178
- text = entry.message.content.trim();
1179
- }
1180
- else if (Array.isArray(entry.message.content)) {
1181
- const firstContent = entry.message.content[0];
1182
- if (firstContent?.type === 'text' && firstContent.text) {
1183
- text = firstContent.text.trim();
1184
- }
1185
- }
1186
- if (text) {
1187
- description = this.extractSmartTitle(text);
1188
- }
1189
- }
1190
- if (description) {
1191
- // Check if this is an internal agent - if so, remove it
1192
- if (this.isInternalAgent(description)) {
1193
- this.removeAgent(agentId);
1194
- return;
1195
- }
1196
- info.description = description;
1197
- this.emit('subagent:updated', info);
1198
- }
1185
+ if (info) {
1186
+ this._processModelInfo(entry, info);
1187
+ this._processTokenInfo(entry, info);
1188
+ if (await this._processDescription(entry, agentId, info))
1189
+ return;
1199
1190
  }
1200
1191
  if (entry.type === 'progress' && entry.data) {
1201
1192
  const progress = {
@@ -1205,7 +1196,6 @@ export class SubagentWatcher extends EventEmitter {
1205
1196
  progressType: entry.data.type,
1206
1197
  query: entry.data.query,
1207
1198
  resultCount: entry.data.resultCount,
1208
- // Extract hook event info if present
1209
1199
  hookEvent: entry.data.hookEvent,
1210
1200
  hookName: entry.data.hookName ||
1211
1201
  (entry.data.hookEvent && entry.data.tool_name
@@ -1215,142 +1205,147 @@ export class SubagentWatcher extends EventEmitter {
1215
1205
  this.emit('subagent:progress', progress);
1216
1206
  }
1217
1207
  else if (entry.type === 'assistant' && entry.message?.content) {
1218
- // Handle both string and array content formats
1219
- if (typeof entry.message.content === 'string') {
1220
- const text = entry.message.content.trim();
1221
- if (text.length > 0) {
1222
- const message = {
1208
+ this._processAssistantContent(entry, agentId, sessionId);
1209
+ }
1210
+ else if (entry.type === 'user' && entry.message?.content) {
1211
+ this._processUserContent(entry, agentId, sessionId);
1212
+ }
1213
+ }
1214
+ _processModelInfo(entry, agent) {
1215
+ if (entry.type === 'assistant' && entry.message?.model && !agent.model) {
1216
+ agent.model = entry.message.model;
1217
+ agent.modelShort = this.extractModelShort(entry.message.model);
1218
+ this.emit('subagent:updated', agent);
1219
+ }
1220
+ }
1221
+ _processTokenInfo(entry, agent) {
1222
+ if (!entry.message?.usage)
1223
+ return;
1224
+ if (entry.message.usage.input_tokens) {
1225
+ agent.totalInputTokens = (agent.totalInputTokens || 0) + entry.message.usage.input_tokens;
1226
+ }
1227
+ if (entry.message.usage.output_tokens) {
1228
+ agent.totalOutputTokens = (agent.totalOutputTokens || 0) + entry.message.usage.output_tokens;
1229
+ }
1230
+ }
1231
+ async _processDescription(entry, agentId, agent) {
1232
+ if (agent.description || entry.type !== 'user' || !entry.message?.content)
1233
+ return false;
1234
+ const fallbackText = this.extractFirstTextContent(entry.message.content);
1235
+ const description = await this._resolveDescription(agent.projectHash, agent.sessionId, agentId, agent.filePath, fallbackText);
1236
+ if (description) {
1237
+ if (this.isInternalAgent(description)) {
1238
+ this.removeAgent(agentId);
1239
+ return true;
1240
+ }
1241
+ agent.description = description;
1242
+ this.emit('subagent:updated', agent);
1243
+ }
1244
+ return false;
1245
+ }
1246
+ _processAssistantContent(entry, agentId, sessionId) {
1247
+ const messageContent = entry.message.content;
1248
+ if (typeof messageContent === 'string') {
1249
+ const text = messageContent.trim();
1250
+ if (text.length > 0) {
1251
+ const message = {
1252
+ agentId,
1253
+ sessionId,
1254
+ timestamp: entry.timestamp,
1255
+ role: 'assistant',
1256
+ text: text.substring(0, MESSAGE_TEXT_LIMIT),
1257
+ };
1258
+ this.emit('subagent:message', message);
1259
+ }
1260
+ }
1261
+ else {
1262
+ for (const content of messageContent) {
1263
+ if (content.type === 'tool_use' && content.name) {
1264
+ // Store toolUseId for linking to results, with timestamp for TTL cleanup
1265
+ if (content.id) {
1266
+ if (!this.pendingToolCalls.has(agentId)) {
1267
+ this.pendingToolCalls.set(agentId, new Map());
1268
+ }
1269
+ const agentCalls = this.pendingToolCalls.get(agentId);
1270
+ // Enforce size limit to prevent memory leak from rapid tool calls
1271
+ if (agentCalls.size >= MAX_PENDING_TOOL_CALLS) {
1272
+ // FIFO eviction: delete first (oldest) entry using Map insertion order
1273
+ const firstKey = agentCalls.keys().next().value;
1274
+ if (firstKey !== undefined)
1275
+ agentCalls.delete(firstKey);
1276
+ }
1277
+ agentCalls.set(content.id, {
1278
+ toolName: content.name,
1279
+ timestamp: Date.now(),
1280
+ });
1281
+ }
1282
+ const toolCall = {
1223
1283
  agentId,
1224
1284
  sessionId,
1225
1285
  timestamp: entry.timestamp,
1226
- role: 'assistant',
1227
- text: text.substring(0, MESSAGE_TEXT_LIMIT),
1286
+ tool: content.name,
1287
+ input: this.getTruncatedInput(content.name, content.input || {}),
1288
+ toolUseId: content.id,
1289
+ fullInput: content.input || {},
1228
1290
  };
1229
- this.emit('subagent:message', message);
1230
- }
1231
- }
1232
- else {
1233
- for (const content of entry.message.content) {
1234
- if (content.type === 'tool_use' && content.name) {
1235
- // Store toolUseId for linking to results, with timestamp for TTL cleanup
1236
- if (content.id) {
1237
- if (!this.pendingToolCalls.has(agentId)) {
1238
- this.pendingToolCalls.set(agentId, new Map());
1239
- }
1240
- const agentCalls = this.pendingToolCalls.get(agentId);
1241
- // Enforce size limit to prevent memory leak from rapid tool calls
1242
- if (agentCalls.size >= MAX_PENDING_TOOL_CALLS) {
1243
- // FIFO eviction: delete first (oldest) entry using Map insertion order
1244
- const firstKey = agentCalls.keys().next().value;
1245
- if (firstKey !== undefined)
1246
- agentCalls.delete(firstKey);
1247
- }
1248
- agentCalls.set(content.id, {
1249
- toolName: content.name,
1250
- timestamp: Date.now(),
1251
- });
1252
- }
1253
- const toolCall = {
1254
- agentId,
1255
- sessionId,
1256
- timestamp: entry.timestamp,
1257
- tool: content.name,
1258
- input: this.getTruncatedInput(content.name, content.input || {}),
1259
- toolUseId: content.id,
1260
- fullInput: content.input || {},
1261
- };
1262
- this.emit('subagent:tool_call', toolCall);
1263
- // Update tool call count
1264
- const agentInfo = this.agentInfo.get(agentId);
1265
- if (agentInfo) {
1266
- agentInfo.toolCallCount++;
1267
- }
1291
+ this.emit('subagent:tool_call', toolCall);
1292
+ // Update tool call count
1293
+ const agentInfo = this.agentInfo.get(agentId);
1294
+ if (agentInfo) {
1295
+ agentInfo.toolCallCount++;
1268
1296
  }
1269
- else if (content.type === 'tool_result' && content.tool_use_id) {
1270
- // Extract tool result
1271
- const resultContent = this.extractToolResultContent(content.content);
1272
- const agentPendingCalls = this.pendingToolCalls.get(agentId);
1273
- const pendingCall = agentPendingCalls?.get(content.tool_use_id);
1274
- const toolName = pendingCall?.toolName;
1275
- // Delete after lookup to prevent memory leak
1276
- agentPendingCalls?.delete(content.tool_use_id);
1277
- const toolResult = {
1297
+ }
1298
+ else if (content.type === 'tool_result' && content.tool_use_id) {
1299
+ this.emitToolResult({ tool_use_id: content.tool_use_id, content: content.content, is_error: content.is_error }, agentId, sessionId, entry.timestamp);
1300
+ }
1301
+ else if (content.type === 'text' && content.text) {
1302
+ const text = content.text.trim();
1303
+ if (text.length > 0) {
1304
+ const message = {
1278
1305
  agentId,
1279
1306
  sessionId,
1280
1307
  timestamp: entry.timestamp,
1281
- toolUseId: content.tool_use_id,
1282
- tool: toolName,
1283
- preview: resultContent.substring(0, MESSAGE_TEXT_LIMIT),
1284
- contentLength: resultContent.length,
1285
- isError: content.is_error || false,
1308
+ role: 'assistant',
1309
+ text: text.substring(0, MESSAGE_TEXT_LIMIT),
1286
1310
  };
1287
- this.emit('subagent:tool_result', toolResult);
1288
- }
1289
- else if (content.type === 'text' && content.text) {
1290
- const text = content.text.trim();
1291
- if (text.length > 0) {
1292
- const message = {
1293
- agentId,
1294
- sessionId,
1295
- timestamp: entry.timestamp,
1296
- role: 'assistant',
1297
- text: text.substring(0, MESSAGE_TEXT_LIMIT), // Limit text length
1298
- };
1299
- this.emit('subagent:message', message);
1300
- }
1311
+ this.emit('subagent:message', message);
1301
1312
  }
1302
1313
  }
1303
1314
  }
1304
1315
  }
1305
- else if (entry.type === 'user' && entry.message?.content) {
1306
- // Handle both string and array content formats - also check for tool_result in user messages
1307
- if (typeof entry.message.content === 'string') {
1308
- const userText = entry.message.content.trim();
1309
- if (userText.length > 0 && userText.length < 500) {
1310
- const message = {
1311
- agentId,
1312
- sessionId,
1313
- timestamp: entry.timestamp,
1314
- role: 'user',
1315
- text: userText,
1316
- };
1317
- this.emit('subagent:message', message);
1318
- }
1316
+ }
1317
+ _processUserContent(entry, agentId, sessionId) {
1318
+ const messageContent = entry.message.content;
1319
+ if (typeof messageContent === 'string') {
1320
+ const userText = messageContent.trim();
1321
+ if (userText.length > 0 && userText.length < 500) {
1322
+ const message = {
1323
+ agentId,
1324
+ sessionId,
1325
+ timestamp: entry.timestamp,
1326
+ role: 'user',
1327
+ text: userText,
1328
+ };
1329
+ this.emit('subagent:message', message);
1319
1330
  }
1320
- else {
1321
- // Check for tool_result blocks in user messages (common pattern)
1322
- for (const content of entry.message.content) {
1323
- if (content.type === 'tool_result' && content.tool_use_id) {
1324
- const resultContent = this.extractToolResultContent(content.content);
1325
- const agentPendingCalls = this.pendingToolCalls.get(agentId);
1326
- const pendingCall = agentPendingCalls?.get(content.tool_use_id);
1327
- const toolName = pendingCall?.toolName;
1328
- // Delete after lookup to prevent memory leak
1329
- agentPendingCalls?.delete(content.tool_use_id);
1330
- const toolResult = {
1331
+ }
1332
+ else {
1333
+ // Check for tool_result blocks in user messages (common pattern)
1334
+ for (const content of messageContent) {
1335
+ if (content.type === 'tool_result' && content.tool_use_id) {
1336
+ this.emitToolResult({ tool_use_id: content.tool_use_id, content: content.content, is_error: content.is_error }, agentId, sessionId, entry.timestamp);
1337
+ }
1338
+ else if (content.type === 'text' && content.text) {
1339
+ const userText = content.text.trim();
1340
+ if (userText.length > 0 && userText.length < 500) {
1341
+ const message = {
1331
1342
  agentId,
1332
1343
  sessionId,
1333
1344
  timestamp: entry.timestamp,
1334
- toolUseId: content.tool_use_id,
1335
- tool: toolName,
1336
- preview: resultContent.substring(0, MESSAGE_TEXT_LIMIT),
1337
- contentLength: resultContent.length,
1338
- isError: content.is_error || false,
1345
+ role: 'user',
1346
+ text: userText,
1339
1347
  };
1340
- this.emit('subagent:tool_result', toolResult);
1341
- }
1342
- else if (content.type === 'text' && content.text) {
1343
- const userText = content.text.trim();
1344
- if (userText.length > 0 && userText.length < 500) {
1345
- const message = {
1346
- agentId,
1347
- sessionId,
1348
- timestamp: entry.timestamp,
1349
- role: 'user',
1350
- text: userText,
1351
- };
1352
- this.emit('subagent:message', message);
1353
- }
1348
+ this.emit('subagent:message', message);
1354
1349
  }
1355
1350
  }
1356
1351
  }