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,17 +1,24 @@
1
- import { randomUUID } from "crypto";
2
1
  import { addAssistantMessageToMessages, updateToolBlockInMessage, addErrorBlockToMessage, addDiffBlockToMessage, addUserMessageToMessages, extractUserInputHistory, addMemoryBlockToMessage, addCommandOutputMessage, updateCommandOutputInMessage, completeCommandInMessage, addSubagentBlockToMessage, updateSubagentBlockInMessage, removeLastUserMessage, } from "../utils/messageOperations.js";
3
- import { cleanupExpiredSessions, getLatestSession, loadSession, saveSession, getSessionFilePath, } from "../services/session.js";
2
+ import { join } from "path";
3
+ import { cleanupExpiredSessionsFromJsonl, getLatestSessionFromJsonl, loadSessionFromJsonl, appendMessages, createSession, generateSessionId, SESSION_DIR, } from "../services/session.js";
4
+ import { pathEncoder } from "../utils/pathEncoder.js";
4
5
  export class MessageManager {
5
6
  constructor(options) {
6
- this.sessionId = randomUUID();
7
+ this.sessionId = generateSessionId();
7
8
  this.messages = [];
8
9
  this.latestTotalTokens = 0;
9
10
  this.userInputHistory = [];
10
11
  this.sessionStartTime = new Date().toISOString();
11
12
  this.workdir = options.workdir;
13
+ this.encodedWorkdir = pathEncoder.encodeSync(this.workdir); // Cache encoded workdir
12
14
  this.callbacks = options.callbacks;
13
15
  this.logger = options.logger;
14
- this.sessionDir = options.sessionDir;
16
+ this.savedMessageCount = 0; // Initialize saved message count tracker
17
+ this.sessionType = options.sessionType || "main";
18
+ this.parentSessionId = options.parentSessionId;
19
+ this.subagentType = options.subagentType;
20
+ // Compute and cache the transcript path
21
+ this.transcriptPath = this.computeTranscriptPath();
15
22
  }
16
23
  // Getter methods
17
24
  getSessionId() {
@@ -26,16 +33,50 @@ export class MessageManager {
26
33
  getUserInputHistory() {
27
34
  return [...this.userInputHistory];
28
35
  }
36
+ getSessionStartTime() {
37
+ return this.sessionStartTime;
38
+ }
39
+ getWorkdir() {
40
+ return this.workdir;
41
+ }
42
+ getSessionDir() {
43
+ return SESSION_DIR;
44
+ }
29
45
  getTranscriptPath() {
30
- return getSessionFilePath(this.sessionId, this.sessionDir);
46
+ return this.transcriptPath;
47
+ }
48
+ /**
49
+ * Compute the transcript path using cached encoded workdir
50
+ * Called during construction and when sessionId changes
51
+ */
52
+ computeTranscriptPath() {
53
+ const baseDir = join(SESSION_DIR, this.encodedWorkdir);
54
+ // All sessions now go in the same directory
55
+ // Session type is determined by metadata, not file path
56
+ return join(baseDir, `${this.sessionId}.jsonl`);
31
57
  }
32
58
  // Setter methods, will trigger callbacks
33
59
  setSessionId(sessionId) {
34
60
  if (this.sessionId !== sessionId) {
35
61
  this.sessionId = sessionId;
62
+ // Reset saved message count for new session
63
+ this.savedMessageCount = 0;
64
+ // Recompute transcript path since session ID changed
65
+ this.transcriptPath = this.computeTranscriptPath();
36
66
  this.callbacks.onSessionIdChange?.(sessionId);
37
67
  }
38
68
  }
69
+ /**
70
+ * Create session if needed (async helper)
71
+ */
72
+ async createSessionIfNeeded() {
73
+ try {
74
+ await createSession(this.sessionId, this.workdir, this.sessionType, this.parentSessionId, this.subagentType);
75
+ }
76
+ catch (error) {
77
+ this.logger?.error("Failed to create session:", error);
78
+ }
79
+ }
39
80
  setMessages(messages) {
40
81
  this.messages = [...messages];
41
82
  this.callbacks.onMessagesChange?.([...messages]);
@@ -45,7 +86,22 @@ export class MessageManager {
45
86
  */
46
87
  async saveSession() {
47
88
  try {
48
- await saveSession(this.sessionId, this.messages, this.workdir, this.latestTotalTokens, this.sessionStartTime, this.sessionDir);
89
+ // Only save messages that haven't been saved yet
90
+ const unsavedMessages = this.messages.slice(this.savedMessageCount);
91
+ if (unsavedMessages.length === 0) {
92
+ // No new messages to save
93
+ return;
94
+ }
95
+ // Create session if needed (only when we have messages to save)
96
+ if (this.savedMessageCount === 0) {
97
+ // This is the first time saving messages, so create the session
98
+ await this.createSessionIfNeeded();
99
+ }
100
+ // Use JSONL format for new sessions
101
+ await appendMessages(this.sessionId, unsavedMessages, // Only append new messages
102
+ this.workdir);
103
+ // Update the saved message count
104
+ this.savedMessageCount = this.messages.length;
49
105
  }
50
106
  catch (error) {
51
107
  this.logger?.error("Failed to save session:", error);
@@ -56,26 +112,25 @@ export class MessageManager {
56
112
  */
57
113
  async handleSessionRestoration(restoreSessionId, continueLastSession) {
58
114
  // Clean up expired sessions first
59
- try {
60
- await cleanupExpiredSessions(this.workdir, this.sessionDir);
61
- }
62
- catch (error) {
115
+ cleanupExpiredSessionsFromJsonl(this.workdir).catch((error) => {
63
116
  this.logger?.warn("Failed to cleanup expired sessions:", error);
64
- }
117
+ });
65
118
  if (!restoreSessionId && !continueLastSession) {
66
119
  return;
67
120
  }
68
121
  try {
69
122
  let sessionToRestore = null;
70
123
  if (restoreSessionId) {
71
- sessionToRestore = await loadSession(restoreSessionId, this.sessionDir);
124
+ // Use only JSONL format - no legacy support
125
+ sessionToRestore = await loadSessionFromJsonl(restoreSessionId, this.workdir);
72
126
  if (!sessionToRestore) {
73
127
  console.error(`Session not found: ${restoreSessionId}`);
74
128
  process.exit(1);
75
129
  }
76
130
  }
77
131
  else if (continueLastSession) {
78
- sessionToRestore = await getLatestSession(this.workdir, this.sessionDir);
132
+ // Use only JSONL format - no legacy support
133
+ sessionToRestore = await getLatestSessionFromJsonl(this.workdir);
79
134
  if (!sessionToRestore) {
80
135
  console.error(`No previous session found for workdir: ${this.workdir}`);
81
136
  process.exit(1);
@@ -84,7 +139,7 @@ export class MessageManager {
84
139
  if (sessionToRestore) {
85
140
  console.log(`Restoring session: ${sessionToRestore.id}`);
86
141
  // Initialize from session data
87
- this.initializeFromSession(sessionToRestore.id, sessionToRestore.messages, sessionToRestore.metadata.latestTotalTokens);
142
+ this.initializeFromSession(sessionToRestore);
88
143
  }
89
144
  }
90
145
  catch (error) {
@@ -108,17 +163,23 @@ export class MessageManager {
108
163
  clearMessages() {
109
164
  this.setMessages([]);
110
165
  this.setUserInputHistory([]);
111
- this.setSessionId(randomUUID());
166
+ this.setSessionId(generateSessionId());
112
167
  this.setlatestTotalTokens(0);
113
168
  this.sessionStartTime = new Date().toISOString();
169
+ this.savedMessageCount = 0; // Reset saved message count
114
170
  }
115
171
  // Initialize state from session data
116
- initializeFromSession(sessionId, messages, latestTotalTokens) {
117
- this.setSessionId(sessionId);
118
- this.setMessages([...messages]);
119
- this.setlatestTotalTokens(latestTotalTokens);
172
+ initializeFromSession(sessionData) {
173
+ this.setSessionId(sessionData.id);
174
+ this.setMessages([...sessionData.messages]);
175
+ this.setlatestTotalTokens(sessionData.metadata.latestTotalTokens);
176
+ // Restore the original session start time
177
+ this.sessionStartTime = sessionData.metadata.startedAt;
120
178
  // Extract user input history from session messages
121
- this.setUserInputHistory(extractUserInputHistory(messages));
179
+ this.setUserInputHistory(extractUserInputHistory(sessionData.messages));
180
+ // Set saved message count to the number of loaded messages since they're already saved
181
+ // This must be done after setSessionId which resets it to 0
182
+ this.savedMessageCount = sessionData.messages.length;
122
183
  }
123
184
  // Add to input history
124
185
  addToInputHistory(input) {
@@ -142,11 +203,42 @@ export class MessageManager {
142
203
  });
143
204
  this.setMessages(newMessages);
144
205
  this.callbacks.onUserMessageAdded?.(params);
206
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
145
207
  }
146
- addAssistantMessage(content, toolCalls, usage) {
147
- const newMessages = addAssistantMessageToMessages(this.messages, content, toolCalls, usage);
208
+ addAssistantMessage(content, toolCalls, usage, metadata) {
209
+ const metadataRecord = metadata
210
+ ? Object.fromEntries(Object.entries(metadata).filter(([, value]) => value !== undefined))
211
+ : undefined;
212
+ const newMessages = addAssistantMessageToMessages(this.messages, content, toolCalls, usage, metadataRecord);
148
213
  this.setMessages(newMessages);
149
- this.callbacks.onAssistantMessageAdded?.(content, toolCalls);
214
+ this.callbacks.onAssistantMessageAdded?.();
215
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
216
+ }
217
+ mergeAssistantMetadata(metadata) {
218
+ if (!metadata || Object.keys(metadata).length === 0) {
219
+ return;
220
+ }
221
+ const newMessages = [...this.messages];
222
+ for (let i = newMessages.length - 1; i >= 0; i--) {
223
+ const message = newMessages[i];
224
+ if (message.role === "assistant") {
225
+ const mergedMetadata = {
226
+ ...(message.metadata || {}),
227
+ };
228
+ for (const [key, value] of Object.entries(metadata)) {
229
+ if (value === undefined) {
230
+ continue;
231
+ }
232
+ mergedMetadata[key] = value;
233
+ }
234
+ if (Object.keys(mergedMetadata).length === 0) {
235
+ return;
236
+ }
237
+ message.metadata = mergedMetadata;
238
+ this.setMessages(newMessages);
239
+ return;
240
+ }
241
+ }
150
242
  }
151
243
  updateToolBlock(params) {
152
244
  const newMessages = updateToolBlockInMessage({
@@ -156,14 +248,16 @@ export class MessageManager {
156
248
  result: params.result,
157
249
  success: params.success,
158
250
  error: params.error,
159
- isRunning: params.isRunning,
251
+ stage: params.stage,
160
252
  name: params.name,
161
253
  shortResult: params.shortResult,
162
254
  images: params.images,
163
255
  compactParams: params.compactParams,
256
+ parametersChunk: params.parametersChunk,
164
257
  });
165
258
  this.setMessages(newMessages);
166
259
  this.callbacks.onToolBlockUpdated?.(params);
260
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
167
261
  }
168
262
  addDiffBlock(filePath, diffResult) {
169
263
  const newMessages = addDiffBlockToMessage({
@@ -185,7 +279,7 @@ export class MessageManager {
185
279
  /**
186
280
  * Compress messages and update session, delete compressed messages, only keep compressed messages and subsequent messages
187
281
  */
188
- compressMessagesAndUpdateSession(insertIndex, compressedContent) {
282
+ compressMessagesAndUpdateSession(insertIndex, compressedContent, usage) {
189
283
  const currentMessages = this.messages;
190
284
  // Create compressed message
191
285
  const compressMessage = {
@@ -194,8 +288,10 @@ export class MessageManager {
194
288
  {
195
289
  type: "compress",
196
290
  content: compressedContent,
291
+ sessionId: this.sessionId,
197
292
  },
198
293
  ],
294
+ ...(usage && { usage }),
199
295
  };
200
296
  // Convert negative index to positive index
201
297
  const actualIndex = insertIndex < 0 ? currentMessages.length + insertIndex : insertIndex;
@@ -205,7 +301,7 @@ export class MessageManager {
205
301
  ...currentMessages.slice(actualIndex),
206
302
  ];
207
303
  // Update sessionId
208
- this.setSessionId(randomUUID());
304
+ this.setSessionId(generateSessionId());
209
305
  // Set new message list
210
306
  this.setMessages(newMessages);
211
307
  // Trigger compression callback, insertIndex remains unchanged
@@ -250,13 +346,14 @@ export class MessageManager {
250
346
  this.callbacks.onCompleteCommandMessage?.(command, exitCode);
251
347
  }
252
348
  // Subagent block methods
253
- addSubagentBlock(subagentId, subagentName, status = "active", subagentMessages = [], parameters) {
349
+ addSubagentBlock(subagentId, subagentName, sessionId, configuration, status = "active", parameters) {
254
350
  const params = {
255
351
  messages: this.messages,
256
352
  subagentId,
257
353
  subagentName,
354
+ sessionId,
258
355
  status,
259
- subagentMessages,
356
+ configuration,
260
357
  };
261
358
  const updatedMessages = addSubagentBlockToMessage(params);
262
359
  this.setMessages(updatedMessages);
@@ -269,9 +366,8 @@ export class MessageManager {
269
366
  messages: this.messages,
270
367
  subagentId,
271
368
  status: updates.status || "active",
272
- subagentMessages: updates.messages || [],
273
369
  };
274
- this.callbacks.onSubAgentBlockUpdated?.(params.subagentId, params.messages, params.status);
370
+ this.callbacks.onSubAgentBlockUpdated?.(params.subagentId, params.status);
275
371
  }
276
372
  /**
277
373
  * Trigger usage change callback with all usage data from assistant messages
@@ -285,6 +381,43 @@ export class MessageManager {
285
381
  }
286
382
  this.callbacks.onUsagesChange?.(usages);
287
383
  }
384
+ /**
385
+ * Update the current assistant message content during streaming
386
+ * This method updates the last assistant message's content without creating a new message
387
+ * FR-001: Tracks and provides both chunk (new content) and accumulated (total content)
388
+ */
389
+ updateCurrentMessageContent(newAccumulatedContent) {
390
+ if (this.messages.length === 0)
391
+ return;
392
+ const lastMessage = this.messages[this.messages.length - 1];
393
+ if (lastMessage.role !== "assistant")
394
+ return;
395
+ // Get the current content to calculate the chunk
396
+ const textBlockIndex = lastMessage.blocks.findIndex((block) => block.type === "text");
397
+ const currentContent = textBlockIndex >= 0
398
+ ? lastMessage.blocks[textBlockIndex].content || ""
399
+ : "";
400
+ // Calculate the chunk (new content since last update)
401
+ const chunk = newAccumulatedContent.slice(currentContent.length);
402
+ if (textBlockIndex >= 0) {
403
+ // Update existing text block
404
+ lastMessage.blocks[textBlockIndex] = {
405
+ type: "text",
406
+ content: newAccumulatedContent,
407
+ };
408
+ }
409
+ else {
410
+ // Add new text block if none exists
411
+ lastMessage.blocks.unshift({
412
+ type: "text",
413
+ content: newAccumulatedContent,
414
+ });
415
+ }
416
+ // FR-001: Trigger callbacks with chunk and accumulated content
417
+ this.callbacks.onAssistantContentUpdated?.(chunk, newAccumulatedContent);
418
+ // Note: Subagent-specific callbacks are now handled by SubagentManager
419
+ this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
420
+ }
288
421
  /**
289
422
  * Remove the last user message from the conversation
290
423
  * Used for hook error handling when the user prompt needs to be erased
@@ -1 +1 @@
1
- {"version":3,"file":"slashCommandManager.d.ts","sourceRoot":"","sources":["../../src/managers/slashCommandManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,MAAM,EACP,MAAM,mBAAmB,CAAC;AAkB3B,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,cAAc,CAAC;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,OAAO,EAAE,0BAA0B;IAU/C,OAAO,CAAC,yBAAyB;IAYjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwC1B;;OAEG;IACI,oBAAoB,IAAI,IAAI;IAWnC;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACI,WAAW,IAAI,YAAY,EAAE;IAIpC;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI9D;;OAEG;IACU,cAAc,CACzB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC;IAenB;;;OAGG;IACI,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG;QAClD,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;IAeD;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI7C;;OAEG;IACI,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI1E;;OAEG;IACI,iBAAiB,IAAI,kBAAkB,EAAE;IAIhD;;OAEG;YACW,+BAA+B;IA0E7C;;OAEG;IACI,mBAAmB,IAAI,IAAI;CAInC"}
1
+ {"version":3,"file":"slashCommandManager.d.ts","sourceRoot":"","sources":["../../src/managers/slashCommandManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,MAAM,EACP,MAAM,mBAAmB,CAAC;AAkB3B,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,cAAc,CAAC;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,OAAO,EAAE,0BAA0B;IAU/C,OAAO,CAAC,yBAAyB;IAejC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwC1B;;OAEG;IACI,oBAAoB,IAAI,IAAI;IAWnC;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACI,WAAW,IAAI,YAAY,EAAE;IAIpC;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI9D;;OAEG;IACU,cAAc,CACzB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC;IAenB;;;OAGG;IACI,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG;QAClD,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;IAeD;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI7C;;OAEG;IACI,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI1E;;OAEG;IACI,iBAAiB,IAAI,kBAAkB,EAAE;IAIhD;;OAEG;YACW,+BAA+B;IA0E7C;;OAEG;IACI,mBAAmB,IAAI,IAAI;CAInC"}
@@ -20,9 +20,12 @@ export class SlashCommandManager {
20
20
  this.registerCommand({
21
21
  id: "clear",
22
22
  name: "clear",
23
- description: "Clear the chat session",
23
+ description: "Clear the chat session and terminal",
24
24
  handler: () => {
25
+ // Clear chat messages
25
26
  this.messageManager.clearMessages();
27
+ // Clear terminal screen
28
+ process.stdout.write("\x1Bc");
26
29
  },
27
30
  });
28
31
  }
@@ -1,8 +1,23 @@
1
1
  import type { SubagentConfiguration } from "../utils/subagentParser.js";
2
2
  import type { Message, Logger, GatewayConfig, ModelConfig, Usage } from "../types/index.js";
3
+ import type { SessionData } from "../services/session.js";
3
4
  import { AIManager } from "./aiManager.js";
4
5
  import { MessageManager } from "./messageManager.js";
5
6
  import { ToolManager } from "./toolManager.js";
7
+ import { HookManager } from "./hookManager.js";
8
+ import { UserMessageParams, type AgentToolBlockUpdateParams } from "../utils/messageOperations.js";
9
+ export interface SubagentManagerCallbacks {
10
+ /** Triggered when subagent adds user message */
11
+ onSubagentUserMessageAdded?: (subagentId: string, params: UserMessageParams) => void;
12
+ /** Triggered when subagent creates assistant message */
13
+ onSubagentAssistantMessageAdded?: (subagentId: string) => void;
14
+ /** Triggered during subagent content streaming updates */
15
+ onSubagentAssistantContentUpdated?: (subagentId: string, chunk: string, accumulated: string) => void;
16
+ /** Triggered when subagent tool block is updated */
17
+ onSubagentToolBlockUpdated?: (subagentId: string, params: AgentToolBlockUpdateParams) => void;
18
+ /** Triggered when subagent messages change */
19
+ onSubagentMessagesChange?: (subagentId: string, messages: Message[]) => void;
20
+ }
6
21
  export interface SubagentInstance {
7
22
  subagentId: string;
8
23
  configuration: SubagentConfiguration;
@@ -11,15 +26,18 @@ export interface SubagentInstance {
11
26
  toolManager: ToolManager;
12
27
  status: "initializing" | "active" | "completed" | "error" | "aborted";
13
28
  messages: Message[];
29
+ subagentType: string;
14
30
  }
15
31
  export interface SubagentManagerOptions {
16
32
  workdir: string;
17
33
  parentToolManager: ToolManager;
18
34
  parentMessageManager: MessageManager;
35
+ callbacks?: SubagentManagerCallbacks;
19
36
  logger?: Logger;
20
37
  gatewayConfig: GatewayConfig;
21
38
  modelConfig: ModelConfig;
22
39
  tokenLimit: number;
40
+ hookManager?: HookManager;
23
41
  onUsageAdded?: (usage: Usage) => void;
24
42
  }
25
43
  export declare class SubagentManager {
@@ -28,10 +46,12 @@ export declare class SubagentManager {
28
46
  private workdir;
29
47
  private parentToolManager;
30
48
  private parentMessageManager;
49
+ private callbacks?;
31
50
  private logger?;
32
51
  private gatewayConfig;
33
52
  private modelConfig;
34
53
  private tokenLimit;
54
+ private hookManager?;
35
55
  private onUsageAdded?;
36
56
  constructor(options: SubagentManagerOptions);
37
57
  /**
@@ -89,5 +109,36 @@ export declare class SubagentManager {
89
109
  * Clean up all instances (for session end)
90
110
  */
91
111
  cleanup(): void;
112
+ /**
113
+ * Restore subagent instances from saved session data
114
+ * This method is called during agent initialization to restore previous subagent states
115
+ */
116
+ restoreSubagentSessions(subagentSessions: Array<{
117
+ sessionData: SessionData;
118
+ subagentId: string;
119
+ configuration: SubagentConfiguration;
120
+ }>): Promise<void>;
121
+ /**
122
+ * Create subagent callbacks for a specific subagent ID
123
+ * Extracted to reuse in both create and restore flows
124
+ */
125
+ private createSubagentCallbacks;
126
+ /**
127
+ * Update configuration for SubagentManager and all active subagents
128
+ * This method updates configuration for live config reload support
129
+ * @param newGatewayConfig - New gateway configuration
130
+ * @param newModelConfig - New model configuration
131
+ * @param newTokenLimit - New token limit
132
+ */
133
+ updateConfiguration(newGatewayConfig: GatewayConfig, newModelConfig: ModelConfig, newTokenLimit: number): void;
134
+ /**
135
+ * Get current configuration for debugging
136
+ */
137
+ getCurrentConfiguration(): {
138
+ gatewayConfig: GatewayConfig;
139
+ modelConfig: ModelConfig;
140
+ tokenLimit: number;
141
+ activeSubagents: number;
142
+ };
92
143
  }
93
144
  //# sourceMappingURL=subagentManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"subagentManager.d.ts","sourceRoot":"","sources":["../../src/managers/subagentManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EACN,aAAa,EACb,WAAW,EACX,KAAK,EACN,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACL,cAAc,EAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,qBAAqB,CAAC;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,cAAc,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;IACtE,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,WAAW,CAAC;IAC/B,oBAAoB,EAAE,cAAc,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACvC;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,oBAAoB,CAAwC;IAEpE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,oBAAoB,CAAiB;IAC7C,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAC,CAAyB;gBAElC,OAAO,EAAE,sBAAsB;IAW3C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAY5D;;OAEG;IACH,iBAAiB,IAAI,qBAAqB,EAAE;IAS5C;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM;IAK/B;;OAEG;IACG,cAAc,CAClB,aAAa,EAAE,qBAAqB,EACpC,UAAU,EAAE;QACV,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;KACvB,GACA,OAAO,CAAC,gBAAgB,CAAC;IAsF5B;;;;;OAKG;IACG,WAAW,CACf,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,MAAM,CAAC;IAsGlB;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAIxD;;OAEG;IACH,oBAAoB,CAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GACjC,IAAI;IAOP;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAOhE;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAYzC;;OAEG;IACH,kBAAkB,IAAI,gBAAgB,EAAE;IAOxC;;OAEG;IACH,OAAO,IAAI,IAAI;CAGhB"}
1
+ {"version":3,"file":"subagentManager.d.ts","sourceRoot":"","sources":["../../src/managers/subagentManager.ts"],"names":[],"mappings":"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"}