wave-agent-sdk 0.0.7 → 0.0.8

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 (172) hide show
  1. package/dist/agent.d.ts +32 -20
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +202 -20
  4. package/dist/constants/events.d.ts +28 -0
  5. package/dist/constants/events.d.ts.map +1 -0
  6. package/dist/constants/events.js +27 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2 -0
  10. package/dist/managers/aiManager.d.ts +34 -1
  11. package/dist/managers/aiManager.d.ts.map +1 -1
  12. package/dist/managers/aiManager.js +243 -128
  13. package/dist/managers/backgroundBashManager.d.ts.map +1 -1
  14. package/dist/managers/backgroundBashManager.js +7 -6
  15. package/dist/managers/hookManager.d.ts +9 -4
  16. package/dist/managers/hookManager.d.ts.map +1 -1
  17. package/dist/managers/hookManager.js +62 -30
  18. package/dist/managers/liveConfigManager.d.ts +58 -0
  19. package/dist/managers/liveConfigManager.d.ts.map +1 -0
  20. package/dist/managers/liveConfigManager.js +160 -0
  21. package/dist/managers/messageManager.d.ts +38 -13
  22. package/dist/managers/messageManager.d.ts.map +1 -1
  23. package/dist/managers/messageManager.js +163 -30
  24. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  25. package/dist/managers/slashCommandManager.js +4 -1
  26. package/dist/managers/subagentManager.d.ts +51 -0
  27. package/dist/managers/subagentManager.d.ts.map +1 -1
  28. package/dist/managers/subagentManager.js +189 -18
  29. package/dist/services/aiService.d.ts +13 -5
  30. package/dist/services/aiService.d.ts.map +1 -1
  31. package/dist/services/aiService.js +350 -74
  32. package/dist/services/configurationWatcher.d.ts +120 -0
  33. package/dist/services/configurationWatcher.d.ts.map +1 -0
  34. package/dist/services/configurationWatcher.js +439 -0
  35. package/dist/services/fileWatcher.d.ts +69 -0
  36. package/dist/services/fileWatcher.d.ts.map +1 -0
  37. package/dist/services/fileWatcher.js +213 -0
  38. package/dist/services/hook.d.ts +91 -9
  39. package/dist/services/hook.d.ts.map +1 -1
  40. package/dist/services/hook.js +393 -43
  41. package/dist/services/jsonlHandler.d.ts +62 -0
  42. package/dist/services/jsonlHandler.d.ts.map +1 -0
  43. package/dist/services/jsonlHandler.js +257 -0
  44. package/dist/services/memory.d.ts +9 -0
  45. package/dist/services/memory.d.ts.map +1 -1
  46. package/dist/services/memory.js +81 -12
  47. package/dist/services/memoryStore.d.ts +81 -0
  48. package/dist/services/memoryStore.d.ts.map +1 -0
  49. package/dist/services/memoryStore.js +200 -0
  50. package/dist/services/session.d.ts +64 -49
  51. package/dist/services/session.d.ts.map +1 -1
  52. package/dist/services/session.js +310 -132
  53. package/dist/tools/bashTool.d.ts.map +1 -1
  54. package/dist/tools/bashTool.js +5 -4
  55. package/dist/tools/deleteFileTool.d.ts.map +1 -1
  56. package/dist/tools/deleteFileTool.js +2 -1
  57. package/dist/tools/editTool.d.ts.map +1 -1
  58. package/dist/tools/editTool.js +3 -2
  59. package/dist/tools/multiEditTool.d.ts.map +1 -1
  60. package/dist/tools/multiEditTool.js +4 -3
  61. package/dist/tools/readTool.d.ts.map +1 -1
  62. package/dist/tools/readTool.js +2 -1
  63. package/dist/tools/writeTool.d.ts.map +1 -1
  64. package/dist/tools/writeTool.js +5 -6
  65. package/dist/types/commands.d.ts +4 -0
  66. package/dist/types/commands.d.ts.map +1 -1
  67. package/dist/types/core.d.ts +35 -0
  68. package/dist/types/core.d.ts.map +1 -1
  69. package/dist/types/environment.d.ts +42 -0
  70. package/dist/types/environment.d.ts.map +1 -0
  71. package/dist/types/environment.js +21 -0
  72. package/dist/types/hooks.d.ts +8 -2
  73. package/dist/types/hooks.d.ts.map +1 -1
  74. package/dist/types/hooks.js +8 -2
  75. package/dist/types/index.d.ts +2 -0
  76. package/dist/types/index.d.ts.map +1 -1
  77. package/dist/types/index.js +2 -0
  78. package/dist/types/memoryStore.d.ts +82 -0
  79. package/dist/types/memoryStore.d.ts.map +1 -0
  80. package/dist/types/memoryStore.js +7 -0
  81. package/dist/types/messaging.d.ts +14 -2
  82. package/dist/types/messaging.d.ts.map +1 -1
  83. package/dist/types/session.d.ts +20 -0
  84. package/dist/types/session.d.ts.map +1 -0
  85. package/dist/types/session.js +7 -0
  86. package/dist/utils/bashHistory.d.ts.map +1 -1
  87. package/dist/utils/bashHistory.js +27 -26
  88. package/dist/utils/cacheControlUtils.d.ts +121 -0
  89. package/dist/utils/cacheControlUtils.d.ts.map +1 -0
  90. package/dist/utils/cacheControlUtils.js +367 -0
  91. package/dist/utils/commandPathResolver.d.ts +52 -0
  92. package/dist/utils/commandPathResolver.d.ts.map +1 -0
  93. package/dist/utils/commandPathResolver.js +145 -0
  94. package/dist/utils/configPaths.d.ts +85 -0
  95. package/dist/utils/configPaths.d.ts.map +1 -0
  96. package/dist/utils/configPaths.js +121 -0
  97. package/dist/utils/configResolver.d.ts +37 -10
  98. package/dist/utils/configResolver.d.ts.map +1 -1
  99. package/dist/utils/configResolver.js +127 -23
  100. package/dist/utils/constants.d.ts +1 -1
  101. package/dist/utils/constants.js +1 -1
  102. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  103. package/dist/utils/convertMessagesForAPI.js +7 -5
  104. package/dist/utils/customCommands.d.ts.map +1 -1
  105. package/dist/utils/customCommands.js +66 -21
  106. package/dist/utils/fileUtils.d.ts +15 -0
  107. package/dist/utils/fileUtils.d.ts.map +1 -0
  108. package/dist/utils/fileUtils.js +61 -0
  109. package/dist/utils/globalLogger.d.ts +102 -0
  110. package/dist/utils/globalLogger.d.ts.map +1 -0
  111. package/dist/utils/globalLogger.js +136 -0
  112. package/dist/utils/mcpUtils.d.ts.map +1 -1
  113. package/dist/utils/mcpUtils.js +25 -3
  114. package/dist/utils/messageOperations.d.ts +20 -8
  115. package/dist/utils/messageOperations.d.ts.map +1 -1
  116. package/dist/utils/messageOperations.js +25 -16
  117. package/dist/utils/pathEncoder.d.ts +104 -0
  118. package/dist/utils/pathEncoder.d.ts.map +1 -0
  119. package/dist/utils/pathEncoder.js +272 -0
  120. package/dist/utils/subagentParser.d.ts.map +1 -1
  121. package/dist/utils/subagentParser.js +2 -1
  122. package/dist/utils/tokenCalculation.d.ts +26 -0
  123. package/dist/utils/tokenCalculation.d.ts.map +1 -0
  124. package/dist/utils/tokenCalculation.js +36 -0
  125. package/package.json +6 -3
  126. package/src/agent.ts +298 -34
  127. package/src/constants/events.ts +38 -0
  128. package/src/index.ts +2 -0
  129. package/src/managers/aiManager.ts +323 -170
  130. package/src/managers/backgroundBashManager.ts +7 -6
  131. package/src/managers/hookManager.ts +83 -40
  132. package/src/managers/liveConfigManager.ts +248 -0
  133. package/src/managers/messageManager.ts +230 -63
  134. package/src/managers/slashCommandManager.ts +4 -1
  135. package/src/managers/subagentManager.ts +283 -21
  136. package/src/services/aiService.ts +474 -83
  137. package/src/services/configurationWatcher.ts +622 -0
  138. package/src/services/fileWatcher.ts +301 -0
  139. package/src/services/hook.ts +538 -47
  140. package/src/services/jsonlHandler.ts +319 -0
  141. package/src/services/memory.ts +92 -12
  142. package/src/services/memoryStore.ts +279 -0
  143. package/src/services/session.ts +381 -157
  144. package/src/tools/bashTool.ts +5 -4
  145. package/src/tools/deleteFileTool.ts +2 -1
  146. package/src/tools/editTool.ts +3 -2
  147. package/src/tools/multiEditTool.ts +4 -3
  148. package/src/tools/readTool.ts +2 -1
  149. package/src/tools/writeTool.ts +7 -6
  150. package/src/types/commands.ts +6 -0
  151. package/src/types/core.ts +44 -0
  152. package/src/types/environment.ts +60 -0
  153. package/src/types/hooks.ts +21 -8
  154. package/src/types/index.ts +2 -0
  155. package/src/types/memoryStore.ts +94 -0
  156. package/src/types/messaging.ts +14 -2
  157. package/src/types/session.ts +25 -0
  158. package/src/utils/bashHistory.ts +27 -27
  159. package/src/utils/cacheControlUtils.ts +540 -0
  160. package/src/utils/commandPathResolver.ts +189 -0
  161. package/src/utils/configPaths.ts +163 -0
  162. package/src/utils/configResolver.ts +182 -22
  163. package/src/utils/constants.ts +1 -1
  164. package/src/utils/convertMessagesForAPI.ts +7 -5
  165. package/src/utils/customCommands.ts +90 -22
  166. package/src/utils/fileUtils.ts +65 -0
  167. package/src/utils/globalLogger.ts +145 -0
  168. package/src/utils/mcpUtils.ts +34 -3
  169. package/src/utils/messageOperations.ts +42 -20
  170. package/src/utils/pathEncoder.ts +379 -0
  171. package/src/utils/subagentParser.ts +2 -1
  172. package/src/utils/tokenCalculation.ts +43 -0
@@ -1,4 +1,3 @@
1
- import { randomUUID } from "crypto";
2
1
  import {
3
2
  addAssistantMessageToMessages,
4
3
  updateToolBlockInMessage,
@@ -18,16 +17,21 @@ import {
18
17
  type UpdateSubagentBlockParams,
19
18
  type AgentToolBlockUpdateParams,
20
19
  } from "../utils/messageOperations.js";
20
+ import type { SubagentConfiguration } from "../utils/subagentParser.js";
21
21
  import type { Logger, Message, Usage } from "../types/index.js";
22
+ import { join } from "path";
22
23
  import {
23
- cleanupExpiredSessions,
24
- getLatestSession,
25
- loadSession,
26
- saveSession,
24
+ cleanupExpiredSessionsFromJsonl,
25
+ getLatestSessionFromJsonl,
26
+ loadSessionFromJsonl,
27
+ appendMessages,
28
+ createSession,
29
+ generateSessionId,
27
30
  SessionData,
28
- getSessionFilePath,
31
+ SESSION_DIR,
29
32
  } from "../services/session.js";
30
33
  import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
34
+ import { pathEncoder } from "../utils/pathEncoder.js";
31
35
 
32
36
  export interface MessageManagerCallbacks {
33
37
  onMessagesChange?: (messages: Message[]) => void;
@@ -37,10 +41,10 @@ export interface MessageManagerCallbacks {
37
41
  onUsagesChange?: (usages: Usage[]) => void;
38
42
  // Incremental callback
39
43
  onUserMessageAdded?: (params: UserMessageParams) => void;
40
- onAssistantMessageAdded?: (
41
- content?: string,
42
- toolCalls?: ChatCompletionMessageFunctionToolCall[],
43
- ) => void;
44
+ // MODIFIED: Remove arguments for separation of concerns
45
+ onAssistantMessageAdded?: () => void;
46
+ // NEW: Streaming content callback - FR-001: receives chunk and accumulated content
47
+ onAssistantContentUpdated?: (chunk: string, accumulated: string) => void;
44
48
  onToolBlockUpdated?: (params: AgentToolBlockUpdateParams) => void;
45
49
  onDiffBlockAdded?: (filePath: string, diffResult: string) => void;
46
50
  onErrorBlockAdded?: (error: string) => void;
@@ -67,7 +71,6 @@ export interface MessageManagerCallbacks {
67
71
  ) => void;
68
72
  onSubAgentBlockUpdated?: (
69
73
  subagentId: string,
70
- messages: Message[],
71
74
  status: "active" | "completed" | "error" | "aborted",
72
75
  ) => void;
73
76
  }
@@ -76,13 +79,9 @@ export interface MessageManagerOptions {
76
79
  callbacks: MessageManagerCallbacks;
77
80
  workdir: string;
78
81
  logger?: Logger;
79
-
80
- // New: Optional session directory override
81
- /**
82
- * Custom session directory path
83
- * @default join(homedir(), ".wave", "sessions")
84
- */
85
- sessionDir?: string;
82
+ sessionType?: "main" | "subagent";
83
+ parentSessionId?: string;
84
+ subagentType?: string;
86
85
  }
87
86
 
88
87
  export class MessageManager {
@@ -93,20 +92,32 @@ export class MessageManager {
93
92
  private userInputHistory: string[];
94
93
  private sessionStartTime: string;
95
94
  private workdir: string;
95
+ private encodedWorkdir: string; // Cached encoded workdir
96
96
  private logger?: Logger; // Add optional logger property
97
97
  private callbacks: MessageManagerCallbacks;
98
- private sessionDir?: string; // Add session directory property
98
+ private transcriptPath: string; // Cached transcript path
99
+ private savedMessageCount: number; // Track how many messages have been saved to prevent duplication
100
+ private sessionType: "main" | "subagent";
101
+ private parentSessionId?: string;
102
+ private subagentType?: string;
99
103
 
100
104
  constructor(options: MessageManagerOptions) {
101
- this.sessionId = randomUUID();
105
+ this.sessionId = generateSessionId();
102
106
  this.messages = [];
103
107
  this.latestTotalTokens = 0;
104
108
  this.userInputHistory = [];
105
109
  this.sessionStartTime = new Date().toISOString();
106
110
  this.workdir = options.workdir;
111
+ this.encodedWorkdir = pathEncoder.encodeSync(this.workdir); // Cache encoded workdir
107
112
  this.callbacks = options.callbacks;
108
113
  this.logger = options.logger;
109
- this.sessionDir = options.sessionDir;
114
+ this.savedMessageCount = 0; // Initialize saved message count tracker
115
+ this.sessionType = options.sessionType || "main";
116
+ this.parentSessionId = options.parentSessionId;
117
+ this.subagentType = options.subagentType;
118
+
119
+ // Compute and cache the transcript path
120
+ this.transcriptPath = this.computeTranscriptPath();
110
121
  }
111
122
 
112
123
  // Getter methods
@@ -126,18 +137,63 @@ export class MessageManager {
126
137
  return [...this.userInputHistory];
127
138
  }
128
139
 
140
+ public getSessionStartTime(): string {
141
+ return this.sessionStartTime;
142
+ }
143
+
144
+ public getWorkdir(): string {
145
+ return this.workdir;
146
+ }
147
+
148
+ public getSessionDir(): string {
149
+ return SESSION_DIR;
150
+ }
151
+
129
152
  public getTranscriptPath(): string {
130
- return getSessionFilePath(this.sessionId, this.sessionDir);
153
+ return this.transcriptPath;
154
+ }
155
+
156
+ /**
157
+ * Compute the transcript path using cached encoded workdir
158
+ * Called during construction and when sessionId changes
159
+ */
160
+ private computeTranscriptPath(): string {
161
+ const baseDir = join(SESSION_DIR, this.encodedWorkdir);
162
+
163
+ // All sessions now go in the same directory
164
+ // Session type is determined by metadata, not file path
165
+ return join(baseDir, `${this.sessionId}.jsonl`);
131
166
  }
132
167
 
133
168
  // Setter methods, will trigger callbacks
134
169
  public setSessionId(sessionId: string): void {
135
170
  if (this.sessionId !== sessionId) {
136
171
  this.sessionId = sessionId;
172
+ // Reset saved message count for new session
173
+ this.savedMessageCount = 0;
174
+ // Recompute transcript path since session ID changed
175
+ this.transcriptPath = this.computeTranscriptPath();
137
176
  this.callbacks.onSessionIdChange?.(sessionId);
138
177
  }
139
178
  }
140
179
 
180
+ /**
181
+ * Create session if needed (async helper)
182
+ */
183
+ private async createSessionIfNeeded(): Promise<void> {
184
+ try {
185
+ await createSession(
186
+ this.sessionId,
187
+ this.workdir,
188
+ this.sessionType,
189
+ this.parentSessionId,
190
+ this.subagentType,
191
+ );
192
+ } catch (error) {
193
+ this.logger?.error("Failed to create session:", error);
194
+ }
195
+ }
196
+
141
197
  public setMessages(messages: Message[]): void {
142
198
  this.messages = [...messages];
143
199
  this.callbacks.onMessagesChange?.([...messages]);
@@ -148,14 +204,29 @@ export class MessageManager {
148
204
  */
149
205
  public async saveSession(): Promise<void> {
150
206
  try {
151
- await saveSession(
207
+ // Only save messages that haven't been saved yet
208
+ const unsavedMessages = this.messages.slice(this.savedMessageCount);
209
+
210
+ if (unsavedMessages.length === 0) {
211
+ // No new messages to save
212
+ return;
213
+ }
214
+
215
+ // Create session if needed (only when we have messages to save)
216
+ if (this.savedMessageCount === 0) {
217
+ // This is the first time saving messages, so create the session
218
+ await this.createSessionIfNeeded();
219
+ }
220
+
221
+ // Use JSONL format for new sessions
222
+ await appendMessages(
152
223
  this.sessionId,
153
- this.messages,
224
+ unsavedMessages, // Only append new messages
154
225
  this.workdir,
155
- this.latestTotalTokens,
156
- this.sessionStartTime,
157
- this.sessionDir,
158
226
  );
227
+
228
+ // Update the saved message count
229
+ this.savedMessageCount = this.messages.length;
159
230
  } catch (error) {
160
231
  this.logger?.error("Failed to save session:", error);
161
232
  }
@@ -169,11 +240,9 @@ export class MessageManager {
169
240
  continueLastSession?: boolean,
170
241
  ): Promise<void> {
171
242
  // Clean up expired sessions first
172
- try {
173
- await cleanupExpiredSessions(this.workdir, this.sessionDir);
174
- } catch (error) {
243
+ cleanupExpiredSessionsFromJsonl(this.workdir).catch((error) => {
175
244
  this.logger?.warn("Failed to cleanup expired sessions:", error);
176
- }
245
+ });
177
246
 
178
247
  if (!restoreSessionId && !continueLastSession) {
179
248
  return;
@@ -183,16 +252,18 @@ export class MessageManager {
183
252
  let sessionToRestore: SessionData | null = null;
184
253
 
185
254
  if (restoreSessionId) {
186
- sessionToRestore = await loadSession(restoreSessionId, this.sessionDir);
255
+ // Use only JSONL format - no legacy support
256
+ sessionToRestore = await loadSessionFromJsonl(
257
+ restoreSessionId,
258
+ this.workdir,
259
+ );
187
260
  if (!sessionToRestore) {
188
261
  console.error(`Session not found: ${restoreSessionId}`);
189
262
  process.exit(1);
190
263
  }
191
264
  } else if (continueLastSession) {
192
- sessionToRestore = await getLatestSession(
193
- this.workdir,
194
- this.sessionDir,
195
- );
265
+ // Use only JSONL format - no legacy support
266
+ sessionToRestore = await getLatestSessionFromJsonl(this.workdir);
196
267
  if (!sessionToRestore) {
197
268
  console.error(
198
269
  `No previous session found for workdir: ${this.workdir}`,
@@ -205,11 +276,7 @@ export class MessageManager {
205
276
  console.log(`Restoring session: ${sessionToRestore.id}`);
206
277
 
207
278
  // Initialize from session data
208
- this.initializeFromSession(
209
- sessionToRestore.id,
210
- sessionToRestore.messages,
211
- sessionToRestore.metadata.latestTotalTokens,
212
- );
279
+ this.initializeFromSession(sessionToRestore);
213
280
  }
214
281
  } catch (error) {
215
282
  console.error("Failed to restore session:", error);
@@ -235,23 +302,27 @@ export class MessageManager {
235
302
  public clearMessages(): void {
236
303
  this.setMessages([]);
237
304
  this.setUserInputHistory([]);
238
- this.setSessionId(randomUUID());
305
+ this.setSessionId(generateSessionId());
239
306
  this.setlatestTotalTokens(0);
240
307
  this.sessionStartTime = new Date().toISOString();
308
+ this.savedMessageCount = 0; // Reset saved message count
241
309
  }
242
310
 
243
311
  // Initialize state from session data
244
- public initializeFromSession(
245
- sessionId: string,
246
- messages: Message[],
247
- latestTotalTokens: number,
248
- ): void {
249
- this.setSessionId(sessionId);
250
- this.setMessages([...messages]);
251
- this.setlatestTotalTokens(latestTotalTokens);
312
+ public initializeFromSession(sessionData: SessionData): void {
313
+ this.setSessionId(sessionData.id);
314
+ this.setMessages([...sessionData.messages]);
315
+ this.setlatestTotalTokens(sessionData.metadata.latestTotalTokens);
316
+
317
+ // Restore the original session start time
318
+ this.sessionStartTime = sessionData.metadata.startedAt;
252
319
 
253
320
  // Extract user input history from session messages
254
- this.setUserInputHistory(extractUserInputHistory(messages));
321
+ this.setUserInputHistory(extractUserInputHistory(sessionData.messages));
322
+
323
+ // Set saved message count to the number of loaded messages since they're already saved
324
+ // This must be done after setSessionId which resets it to 0
325
+ this.savedMessageCount = sessionData.messages.length;
255
326
  }
256
327
 
257
328
  // Add to input history
@@ -280,21 +351,64 @@ export class MessageManager {
280
351
  });
281
352
  this.setMessages(newMessages);
282
353
  this.callbacks.onUserMessageAdded?.(params);
354
+
355
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
283
356
  }
284
357
 
285
358
  public addAssistantMessage(
286
359
  content?: string,
287
360
  toolCalls?: ChatCompletionMessageFunctionToolCall[],
288
361
  usage?: Usage,
362
+ metadata?: Record<string, unknown>,
289
363
  ): void {
364
+ const metadataRecord = metadata
365
+ ? Object.fromEntries(
366
+ Object.entries(metadata).filter(([, value]) => value !== undefined),
367
+ )
368
+ : undefined;
369
+
290
370
  const newMessages = addAssistantMessageToMessages(
291
371
  this.messages,
292
372
  content,
293
373
  toolCalls,
294
374
  usage,
375
+ metadataRecord,
295
376
  );
296
377
  this.setMessages(newMessages);
297
- this.callbacks.onAssistantMessageAdded?.(content, toolCalls);
378
+ this.callbacks.onAssistantMessageAdded?.();
379
+
380
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
381
+ }
382
+
383
+ public mergeAssistantMetadata(metadata: Record<string, unknown>): void {
384
+ if (!metadata || Object.keys(metadata).length === 0) {
385
+ return;
386
+ }
387
+
388
+ const newMessages = [...this.messages];
389
+ for (let i = newMessages.length - 1; i >= 0; i--) {
390
+ const message = newMessages[i];
391
+ if (message.role === "assistant") {
392
+ const mergedMetadata = {
393
+ ...(message.metadata || {}),
394
+ } as Record<string, unknown>;
395
+
396
+ for (const [key, value] of Object.entries(metadata)) {
397
+ if (value === undefined) {
398
+ continue;
399
+ }
400
+ mergedMetadata[key] = value;
401
+ }
402
+
403
+ if (Object.keys(mergedMetadata).length === 0) {
404
+ return;
405
+ }
406
+
407
+ message.metadata = mergedMetadata;
408
+ this.setMessages(newMessages);
409
+ return;
410
+ }
411
+ }
298
412
  }
299
413
 
300
414
  public updateToolBlock(params: AgentToolBlockUpdateParams): void {
@@ -305,14 +419,17 @@ export class MessageManager {
305
419
  result: params.result,
306
420
  success: params.success,
307
421
  error: params.error,
308
- isRunning: params.isRunning,
422
+ stage: params.stage,
309
423
  name: params.name,
310
424
  shortResult: params.shortResult,
311
425
  images: params.images,
312
426
  compactParams: params.compactParams,
427
+ parametersChunk: params.parametersChunk,
313
428
  });
314
429
  this.setMessages(newMessages);
315
430
  this.callbacks.onToolBlockUpdated?.(params);
431
+
432
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
316
433
  }
317
434
 
318
435
  public addDiffBlock(
@@ -343,6 +460,7 @@ export class MessageManager {
343
460
  public compressMessagesAndUpdateSession(
344
461
  insertIndex: number,
345
462
  compressedContent: string,
463
+ usage?: Usage,
346
464
  ): void {
347
465
  const currentMessages = this.messages;
348
466
 
@@ -353,8 +471,10 @@ export class MessageManager {
353
471
  {
354
472
  type: "compress",
355
473
  content: compressedContent,
474
+ sessionId: this.sessionId,
356
475
  },
357
476
  ],
477
+ ...(usage && { usage }),
358
478
  };
359
479
 
360
480
  // Convert negative index to positive index
@@ -368,7 +488,7 @@ export class MessageManager {
368
488
  ];
369
489
 
370
490
  // Update sessionId
371
- this.setSessionId(randomUUID());
491
+ this.setSessionId(generateSessionId());
372
492
 
373
493
  // Set new message list
374
494
  this.setMessages(newMessages);
@@ -428,8 +548,9 @@ export class MessageManager {
428
548
  public addSubagentBlock(
429
549
  subagentId: string,
430
550
  subagentName: string,
551
+ sessionId: string,
552
+ configuration: SubagentConfiguration,
431
553
  status: "active" | "completed" | "error" = "active",
432
- subagentMessages: Message[] = [],
433
554
  parameters: {
434
555
  description: string;
435
556
  prompt: string;
@@ -440,8 +561,9 @@ export class MessageManager {
440
561
  messages: this.messages,
441
562
  subagentId,
442
563
  subagentName,
564
+ sessionId,
443
565
  status,
444
- subagentMessages,
566
+ configuration,
445
567
  };
446
568
  const updatedMessages = addSubagentBlockToMessage(params);
447
569
  this.setMessages(updatedMessages);
@@ -452,7 +574,7 @@ export class MessageManager {
452
574
  subagentId: string,
453
575
  updates: Partial<{
454
576
  status: "active" | "completed" | "error" | "aborted";
455
- messages: Message[];
577
+ sessionId: string;
456
578
  }>,
457
579
  ): void {
458
580
  const updatedMessages = updateSubagentBlockInMessage(
@@ -465,13 +587,8 @@ export class MessageManager {
465
587
  messages: this.messages,
466
588
  subagentId,
467
589
  status: updates.status || "active",
468
- subagentMessages: updates.messages || [],
469
590
  };
470
- this.callbacks.onSubAgentBlockUpdated?.(
471
- params.subagentId,
472
- params.messages,
473
- params.status,
474
- );
591
+ this.callbacks.onSubAgentBlockUpdated?.(params.subagentId, params.status);
475
592
  }
476
593
 
477
594
  /**
@@ -487,6 +604,56 @@ export class MessageManager {
487
604
  this.callbacks.onUsagesChange?.(usages);
488
605
  }
489
606
 
607
+ /**
608
+ * Update the current assistant message content during streaming
609
+ * This method updates the last assistant message's content without creating a new message
610
+ * FR-001: Tracks and provides both chunk (new content) and accumulated (total content)
611
+ */
612
+ public updateCurrentMessageContent(newAccumulatedContent: string): void {
613
+ if (this.messages.length === 0) return;
614
+
615
+ const lastMessage = this.messages[this.messages.length - 1];
616
+ if (lastMessage.role !== "assistant") return;
617
+
618
+ // Get the current content to calculate the chunk
619
+ const textBlockIndex = lastMessage.blocks.findIndex(
620
+ (block) => block.type === "text",
621
+ );
622
+ const currentContent =
623
+ textBlockIndex >= 0
624
+ ? (
625
+ lastMessage.blocks[textBlockIndex] as {
626
+ type: "text";
627
+ content: string;
628
+ }
629
+ ).content || ""
630
+ : "";
631
+
632
+ // Calculate the chunk (new content since last update)
633
+ const chunk = newAccumulatedContent.slice(currentContent.length);
634
+
635
+ if (textBlockIndex >= 0) {
636
+ // Update existing text block
637
+ lastMessage.blocks[textBlockIndex] = {
638
+ type: "text",
639
+ content: newAccumulatedContent,
640
+ };
641
+ } else {
642
+ // Add new text block if none exists
643
+ lastMessage.blocks.unshift({
644
+ type: "text",
645
+ content: newAccumulatedContent,
646
+ });
647
+ }
648
+
649
+ // FR-001: Trigger callbacks with chunk and accumulated content
650
+ this.callbacks.onAssistantContentUpdated?.(chunk, newAccumulatedContent);
651
+
652
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
653
+
654
+ this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
655
+ }
656
+
490
657
  /**
491
658
  * Remove the last user message from the conversation
492
659
  * Used for hook error handling when the user prompt needs to be erased
@@ -52,9 +52,12 @@ export class SlashCommandManager {
52
52
  this.registerCommand({
53
53
  id: "clear",
54
54
  name: "clear",
55
- description: "Clear the chat session",
55
+ description: "Clear the chat session and terminal",
56
56
  handler: () => {
57
+ // Clear chat messages
57
58
  this.messageManager.clearMessages();
59
+ // Clear terminal screen
60
+ process.stdout.write("\x1Bc");
58
61
  },
59
62
  });
60
63
  }