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.
- package/dist/agent.d.ts +32 -20
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +202 -20
- package/dist/constants/events.d.ts +28 -0
- package/dist/constants/events.d.ts.map +1 -0
- package/dist/constants/events.js +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/managers/aiManager.d.ts +34 -1
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +243 -128
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +7 -6
- package/dist/managers/hookManager.d.ts +9 -4
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +62 -30
- package/dist/managers/liveConfigManager.d.ts +58 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -0
- package/dist/managers/liveConfigManager.js +160 -0
- package/dist/managers/messageManager.d.ts +38 -13
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +163 -30
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +4 -1
- package/dist/managers/subagentManager.d.ts +51 -0
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +189 -18
- package/dist/services/aiService.d.ts +13 -5
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +350 -74
- package/dist/services/configurationWatcher.d.ts +120 -0
- package/dist/services/configurationWatcher.d.ts.map +1 -0
- package/dist/services/configurationWatcher.js +439 -0
- package/dist/services/fileWatcher.d.ts +69 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +213 -0
- package/dist/services/hook.d.ts +91 -9
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +393 -43
- package/dist/services/jsonlHandler.d.ts +62 -0
- package/dist/services/jsonlHandler.d.ts.map +1 -0
- package/dist/services/jsonlHandler.js +257 -0
- package/dist/services/memory.d.ts +9 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +81 -12
- package/dist/services/memoryStore.d.ts +81 -0
- package/dist/services/memoryStore.d.ts.map +1 -0
- package/dist/services/memoryStore.js +200 -0
- package/dist/services/session.d.ts +64 -49
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +310 -132
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +5 -4
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +2 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +3 -2
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +4 -3
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +2 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +5 -6
- package/dist/types/commands.d.ts +4 -0
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/core.d.ts +35 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +42 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +21 -0
- package/dist/types/hooks.d.ts +8 -2
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +8 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/memoryStore.d.ts +82 -0
- package/dist/types/memoryStore.d.ts.map +1 -0
- package/dist/types/memoryStore.js +7 -0
- package/dist/types/messaging.d.ts +14 -2
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/session.d.ts +20 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +7 -0
- package/dist/utils/bashHistory.d.ts.map +1 -1
- package/dist/utils/bashHistory.js +27 -26
- package/dist/utils/cacheControlUtils.d.ts +121 -0
- package/dist/utils/cacheControlUtils.d.ts.map +1 -0
- package/dist/utils/cacheControlUtils.js +367 -0
- package/dist/utils/commandPathResolver.d.ts +52 -0
- package/dist/utils/commandPathResolver.d.ts.map +1 -0
- package/dist/utils/commandPathResolver.js +145 -0
- package/dist/utils/configPaths.d.ts +85 -0
- package/dist/utils/configPaths.d.ts.map +1 -0
- package/dist/utils/configPaths.js +121 -0
- package/dist/utils/configResolver.d.ts +37 -10
- package/dist/utils/configResolver.d.ts.map +1 -1
- package/dist/utils/configResolver.js +127 -23
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +7 -5
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +66 -21
- package/dist/utils/fileUtils.d.ts +15 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +61 -0
- package/dist/utils/globalLogger.d.ts +102 -0
- package/dist/utils/globalLogger.d.ts.map +1 -0
- package/dist/utils/globalLogger.js +136 -0
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +25 -3
- package/dist/utils/messageOperations.d.ts +20 -8
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +25 -16
- package/dist/utils/pathEncoder.d.ts +104 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -0
- package/dist/utils/pathEncoder.js +272 -0
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +2 -1
- package/dist/utils/tokenCalculation.d.ts +26 -0
- package/dist/utils/tokenCalculation.d.ts.map +1 -0
- package/dist/utils/tokenCalculation.js +36 -0
- package/package.json +6 -3
- package/src/agent.ts +298 -34
- package/src/constants/events.ts +38 -0
- package/src/index.ts +2 -0
- package/src/managers/aiManager.ts +323 -170
- package/src/managers/backgroundBashManager.ts +7 -6
- package/src/managers/hookManager.ts +83 -40
- package/src/managers/liveConfigManager.ts +248 -0
- package/src/managers/messageManager.ts +230 -63
- package/src/managers/slashCommandManager.ts +4 -1
- package/src/managers/subagentManager.ts +283 -21
- package/src/services/aiService.ts +474 -83
- package/src/services/configurationWatcher.ts +622 -0
- package/src/services/fileWatcher.ts +301 -0
- package/src/services/hook.ts +538 -47
- package/src/services/jsonlHandler.ts +319 -0
- package/src/services/memory.ts +92 -12
- package/src/services/memoryStore.ts +279 -0
- package/src/services/session.ts +381 -157
- package/src/tools/bashTool.ts +5 -4
- package/src/tools/deleteFileTool.ts +2 -1
- package/src/tools/editTool.ts +3 -2
- package/src/tools/multiEditTool.ts +4 -3
- package/src/tools/readTool.ts +2 -1
- package/src/tools/writeTool.ts +7 -6
- package/src/types/commands.ts +6 -0
- package/src/types/core.ts +44 -0
- package/src/types/environment.ts +60 -0
- package/src/types/hooks.ts +21 -8
- package/src/types/index.ts +2 -0
- package/src/types/memoryStore.ts +94 -0
- package/src/types/messaging.ts +14 -2
- package/src/types/session.ts +25 -0
- package/src/utils/bashHistory.ts +27 -27
- package/src/utils/cacheControlUtils.ts +540 -0
- package/src/utils/commandPathResolver.ts +189 -0
- package/src/utils/configPaths.ts +163 -0
- package/src/utils/configResolver.ts +182 -22
- package/src/utils/constants.ts +1 -1
- package/src/utils/convertMessagesForAPI.ts +7 -5
- package/src/utils/customCommands.ts +90 -22
- package/src/utils/fileUtils.ts +65 -0
- package/src/utils/globalLogger.ts +145 -0
- package/src/utils/mcpUtils.ts +34 -3
- package/src/utils/messageOperations.ts +42 -20
- package/src/utils/pathEncoder.ts +379 -0
- package/src/utils/subagentParser.ts +2 -1
- 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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
cleanupExpiredSessionsFromJsonl,
|
|
25
|
+
getLatestSessionFromJsonl,
|
|
26
|
+
loadSessionFromJsonl,
|
|
27
|
+
appendMessages,
|
|
28
|
+
createSession,
|
|
29
|
+
generateSessionId,
|
|
27
30
|
SessionData,
|
|
28
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
193
|
-
|
|
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(
|
|
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
|
-
|
|
246
|
-
messages
|
|
247
|
-
latestTotalTokens
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
this.
|
|
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?.(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|