wave-agent-sdk 0.0.7 → 0.0.10
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 +105 -24
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +438 -53
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/managers/aiManager.d.ts +18 -7
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +254 -142
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +11 -9
- package/dist/managers/hookManager.d.ts +6 -6
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +81 -39
- package/dist/managers/liveConfigManager.d.ts +95 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -0
- package/dist/managers/liveConfigManager.js +442 -0
- package/dist/managers/lspManager.d.ts +43 -0
- package/dist/managers/lspManager.d.ts.map +1 -0
- package/dist/managers/lspManager.js +326 -0
- package/dist/managers/messageManager.d.ts +41 -24
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +184 -73
- package/dist/managers/permissionManager.d.ts +66 -0
- package/dist/managers/permissionManager.d.ts.map +1 -0
- package/dist/managers/permissionManager.js +208 -0
- package/dist/managers/skillManager.d.ts +1 -0
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +2 -1
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +4 -2
- package/dist/managers/subagentManager.d.ts +42 -6
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +213 -62
- package/dist/managers/toolManager.d.ts +38 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +66 -2
- package/dist/services/aiService.d.ts +15 -5
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +446 -77
- package/dist/services/configurationService.d.ts +116 -0
- package/dist/services/configurationService.d.ts.map +1 -0
- package/dist/services/configurationService.js +585 -0
- package/dist/services/fileWatcher.d.ts +69 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +212 -0
- package/dist/services/hook.d.ts +5 -40
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +47 -109
- package/dist/services/jsonlHandler.d.ts +71 -0
- package/dist/services/jsonlHandler.d.ts.map +1 -0
- package/dist/services/jsonlHandler.js +236 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +33 -11
- package/dist/services/session.d.ts +116 -52
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +415 -143
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +77 -17
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +27 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +33 -8
- package/dist/tools/lspTool.d.ts +6 -0
- package/dist/tools/lspTool.d.ts.map +1 -0
- package/dist/tools/lspTool.js +589 -0
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +30 -10
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +113 -3
- package/dist/tools/skillTool.js +2 -2
- package/dist/tools/todoWriteTool.d.ts.map +1 -1
- package/dist/tools/todoWriteTool.js +23 -0
- package/dist/tools/types.d.ts +11 -8
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +30 -15
- package/dist/types/commands.d.ts +4 -1
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/configuration.d.ts +69 -0
- package/dist/types/configuration.d.ts.map +1 -0
- package/dist/types/configuration.js +8 -0
- package/dist/types/core.d.ts +45 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +83 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +21 -0
- package/dist/types/fileSearch.d.ts +5 -0
- package/dist/types/fileSearch.d.ts.map +1 -0
- package/dist/types/fileSearch.js +1 -0
- package/dist/types/hooks.d.ts +18 -3
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +8 -8
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +7 -0
- package/dist/types/lsp.d.ts +90 -0
- package/dist/types/lsp.d.ts.map +1 -0
- package/dist/types/lsp.js +4 -0
- package/dist/types/messaging.d.ts +19 -12
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +35 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +12 -0
- package/dist/types/session.d.ts +15 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +7 -0
- package/dist/types/skills.d.ts +1 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/tools.d.ts +35 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +4 -0
- package/dist/utils/abortUtils.d.ts +34 -0
- package/dist/utils/abortUtils.d.ts.map +1 -0
- package/dist/utils/abortUtils.js +92 -0
- package/dist/utils/bashHistory.d.ts +4 -0
- package/dist/utils/bashHistory.d.ts.map +1 -1
- package/dist/utils/bashHistory.js +48 -30
- package/dist/utils/builtinSubagents.d.ts +7 -0
- package/dist/utils/builtinSubagents.d.ts.map +1 -0
- package/dist/utils/builtinSubagents.js +65 -0
- package/dist/utils/cacheControlUtils.d.ts +96 -0
- package/dist/utils/cacheControlUtils.d.ts.map +1 -0
- package/dist/utils/cacheControlUtils.js +324 -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/constants.d.ts +1 -13
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +2 -14
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +39 -18
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +66 -21
- package/dist/utils/fileSearch.d.ts +14 -0
- package/dist/utils/fileSearch.d.ts.map +1 -0
- package/dist/utils/fileSearch.js +88 -0
- package/dist/utils/fileUtils.d.ts +27 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +145 -0
- package/dist/utils/globalLogger.d.ts +88 -0
- package/dist/utils/globalLogger.d.ts.map +1 -0
- package/dist/utils/globalLogger.js +120 -0
- package/dist/utils/largeOutputHandler.d.ts +15 -0
- package/dist/utils/largeOutputHandler.d.ts.map +1 -0
- package/dist/utils/largeOutputHandler.js +40 -0
- package/dist/utils/markdownParser.d.ts.map +1 -1
- package/dist/utils/markdownParser.js +1 -17
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +25 -3
- package/dist/utils/messageOperations.d.ts +20 -18
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +30 -38
- package/dist/utils/pathEncoder.d.ts +108 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -0
- package/dist/utils/pathEncoder.js +279 -0
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +12 -8
- 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/dist/utils/tokenEstimator.d.ts +39 -0
- package/dist/utils/tokenEstimator.d.ts.map +1 -0
- package/dist/utils/tokenEstimator.js +55 -0
- package/package.json +6 -6
- package/src/agent.ts +586 -78
- package/src/index.ts +4 -0
- package/src/managers/aiManager.ts +341 -192
- package/src/managers/backgroundBashManager.ts +11 -9
- package/src/managers/hookManager.ts +102 -54
- package/src/managers/liveConfigManager.ts +634 -0
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +258 -121
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +5 -3
- package/src/managers/subagentManager.ts +295 -76
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +656 -84
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +300 -0
- package/src/services/hook.ts +54 -144
- package/src/services/jsonlHandler.ts +303 -0
- package/src/services/memory.ts +34 -11
- package/src/services/session.ts +522 -173
- package/src/tools/bashTool.ts +94 -20
- package/src/tools/deleteFileTool.ts +38 -1
- package/src/tools/editTool.ts +44 -9
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +41 -11
- package/src/tools/readTool.ts +127 -3
- package/src/tools/skillTool.ts +2 -2
- package/src/tools/todoWriteTool.ts +33 -1
- package/src/tools/types.ts +15 -9
- package/src/tools/writeTool.ts +43 -16
- package/src/types/commands.ts +6 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +55 -0
- package/src/types/environment.ts +104 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +32 -16
- package/src/types/index.ts +7 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +21 -14
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +20 -0
- package/src/types/skills.ts +1 -0
- package/src/types/tools.ts +38 -0
- package/src/utils/abortUtils.ts +118 -0
- package/src/utils/bashHistory.ts +55 -31
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +475 -0
- package/src/utils/commandPathResolver.ts +189 -0
- package/src/utils/configPaths.ts +163 -0
- package/src/utils/constants.ts +2 -17
- package/src/utils/convertMessagesForAPI.ts +44 -18
- package/src/utils/customCommands.ts +90 -22
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +160 -0
- package/src/utils/globalLogger.ts +128 -0
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/mcpUtils.ts +34 -3
- package/src/utils/messageOperations.ts +47 -53
- package/src/utils/pathEncoder.ts +394 -0
- package/src/utils/subagentParser.ts +13 -9
- package/src/utils/tokenCalculation.ts +43 -0
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/utils/configResolver.d.ts +0 -38
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -106
- package/src/utils/configResolver.ts +0 -142
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { randomUUID } from "crypto";
|
|
2
1
|
import {
|
|
3
2
|
addAssistantMessageToMessages,
|
|
4
3
|
updateToolBlockInMessage,
|
|
5
4
|
addErrorBlockToMessage,
|
|
6
|
-
addDiffBlockToMessage,
|
|
7
5
|
addUserMessageToMessages,
|
|
8
6
|
extractUserInputHistory,
|
|
9
7
|
addMemoryBlockToMessage,
|
|
@@ -18,16 +16,18 @@ import {
|
|
|
18
16
|
type UpdateSubagentBlockParams,
|
|
19
17
|
type AgentToolBlockUpdateParams,
|
|
20
18
|
} from "../utils/messageOperations.js";
|
|
19
|
+
import type { SubagentConfiguration } from "../utils/subagentParser.js";
|
|
21
20
|
import type { Logger, Message, Usage } from "../types/index.js";
|
|
21
|
+
import { join } from "path";
|
|
22
22
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
saveSession,
|
|
23
|
+
appendMessages,
|
|
24
|
+
createSession,
|
|
25
|
+
generateSessionId,
|
|
27
26
|
SessionData,
|
|
28
|
-
|
|
27
|
+
SESSION_DIR,
|
|
29
28
|
} from "../services/session.js";
|
|
30
29
|
import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
|
|
30
|
+
import { pathEncoder } from "../utils/pathEncoder.js";
|
|
31
31
|
|
|
32
32
|
export interface MessageManagerCallbacks {
|
|
33
33
|
onMessagesChange?: (messages: Message[]) => void;
|
|
@@ -37,12 +37,13 @@ export interface MessageManagerCallbacks {
|
|
|
37
37
|
onUsagesChange?: (usages: Usage[]) => void;
|
|
38
38
|
// Incremental callback
|
|
39
39
|
onUserMessageAdded?: (params: UserMessageParams) => void;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
) => void;
|
|
40
|
+
// MODIFIED: Remove arguments for separation of concerns
|
|
41
|
+
onAssistantMessageAdded?: () => void;
|
|
42
|
+
// NEW: Streaming content callback - FR-001: receives chunk and accumulated content
|
|
43
|
+
onAssistantContentUpdated?: (chunk: string, accumulated: string) => void;
|
|
44
|
+
// NEW: Streaming reasoning callback
|
|
45
|
+
onAssistantReasoningUpdated?: (chunk: string, accumulated: string) => void;
|
|
44
46
|
onToolBlockUpdated?: (params: AgentToolBlockUpdateParams) => void;
|
|
45
|
-
onDiffBlockAdded?: (filePath: string, diffResult: string) => void;
|
|
46
47
|
onErrorBlockAdded?: (error: string) => void;
|
|
47
48
|
onCompressBlockAdded?: (insertIndex: number, content: string) => void;
|
|
48
49
|
onCompressionStateChange?: (isCompressing: boolean) => void;
|
|
@@ -67,7 +68,6 @@ export interface MessageManagerCallbacks {
|
|
|
67
68
|
) => void;
|
|
68
69
|
onSubAgentBlockUpdated?: (
|
|
69
70
|
subagentId: string,
|
|
70
|
-
messages: Message[],
|
|
71
71
|
status: "active" | "completed" | "error" | "aborted",
|
|
72
72
|
) => void;
|
|
73
73
|
}
|
|
@@ -76,13 +76,8 @@ export interface MessageManagerOptions {
|
|
|
76
76
|
callbacks: MessageManagerCallbacks;
|
|
77
77
|
workdir: string;
|
|
78
78
|
logger?: Logger;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Custom session directory path
|
|
83
|
-
* @default join(homedir(), ".wave", "sessions")
|
|
84
|
-
*/
|
|
85
|
-
sessionDir?: string;
|
|
79
|
+
sessionType?: "main" | "subagent";
|
|
80
|
+
subagentType?: string;
|
|
86
81
|
}
|
|
87
82
|
|
|
88
83
|
export class MessageManager {
|
|
@@ -91,22 +86,30 @@ export class MessageManager {
|
|
|
91
86
|
private messages: Message[];
|
|
92
87
|
private latestTotalTokens: number;
|
|
93
88
|
private userInputHistory: string[];
|
|
94
|
-
private sessionStartTime: string;
|
|
95
89
|
private workdir: string;
|
|
90
|
+
private encodedWorkdir: string; // Cached encoded workdir
|
|
96
91
|
private logger?: Logger; // Add optional logger property
|
|
97
92
|
private callbacks: MessageManagerCallbacks;
|
|
98
|
-
private
|
|
93
|
+
private transcriptPath: string; // Cached transcript path
|
|
94
|
+
private savedMessageCount: number; // Track how many messages have been saved to prevent duplication
|
|
95
|
+
private sessionType: "main" | "subagent";
|
|
96
|
+
private subagentType?: string;
|
|
99
97
|
|
|
100
98
|
constructor(options: MessageManagerOptions) {
|
|
101
|
-
this.sessionId =
|
|
99
|
+
this.sessionId = generateSessionId();
|
|
102
100
|
this.messages = [];
|
|
103
101
|
this.latestTotalTokens = 0;
|
|
104
102
|
this.userInputHistory = [];
|
|
105
|
-
this.sessionStartTime = new Date().toISOString();
|
|
106
103
|
this.workdir = options.workdir;
|
|
104
|
+
this.encodedWorkdir = pathEncoder.encodeSync(this.workdir); // Cache encoded workdir
|
|
107
105
|
this.callbacks = options.callbacks;
|
|
108
106
|
this.logger = options.logger;
|
|
109
|
-
this.
|
|
107
|
+
this.savedMessageCount = 0; // Initialize saved message count tracker
|
|
108
|
+
this.sessionType = options.sessionType || "main";
|
|
109
|
+
this.subagentType = options.subagentType;
|
|
110
|
+
|
|
111
|
+
// Compute and cache the transcript path
|
|
112
|
+
this.transcriptPath = this.computeTranscriptPath();
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
// Getter methods
|
|
@@ -126,100 +129,97 @@ export class MessageManager {
|
|
|
126
129
|
return [...this.userInputHistory];
|
|
127
130
|
}
|
|
128
131
|
|
|
132
|
+
public getWorkdir(): string {
|
|
133
|
+
return this.workdir;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public getSessionDir(): string {
|
|
137
|
+
return SESSION_DIR;
|
|
138
|
+
}
|
|
139
|
+
|
|
129
140
|
public getTranscriptPath(): string {
|
|
130
|
-
return
|
|
141
|
+
return this.transcriptPath;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Compute the transcript path using cached encoded workdir
|
|
146
|
+
* Called during construction and when sessionId changes
|
|
147
|
+
*/
|
|
148
|
+
private computeTranscriptPath(): string {
|
|
149
|
+
const baseDir = join(SESSION_DIR, this.encodedWorkdir);
|
|
150
|
+
|
|
151
|
+
// All sessions now go in the same directory
|
|
152
|
+
// Session type is determined by metadata, not file path
|
|
153
|
+
return join(baseDir, `${this.sessionId}.jsonl`);
|
|
131
154
|
}
|
|
132
155
|
|
|
133
156
|
// Setter methods, will trigger callbacks
|
|
134
157
|
public setSessionId(sessionId: string): void {
|
|
135
158
|
if (this.sessionId !== sessionId) {
|
|
136
159
|
this.sessionId = sessionId;
|
|
160
|
+
// Reset saved message count for new session
|
|
161
|
+
this.savedMessageCount = 0;
|
|
162
|
+
// Recompute transcript path since session ID changed
|
|
163
|
+
this.transcriptPath = this.computeTranscriptPath();
|
|
164
|
+
|
|
137
165
|
this.callbacks.onSessionIdChange?.(sessionId);
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
168
|
|
|
141
|
-
public setMessages(messages: Message[]): void {
|
|
142
|
-
this.messages = [...messages];
|
|
143
|
-
this.callbacks.onMessagesChange?.([...messages]);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
169
|
/**
|
|
147
|
-
*
|
|
170
|
+
* Create session if needed (async helper)
|
|
148
171
|
*/
|
|
149
|
-
|
|
172
|
+
private async createSessionIfNeeded(): Promise<void> {
|
|
150
173
|
try {
|
|
151
|
-
await
|
|
152
|
-
this.sessionId,
|
|
153
|
-
this.messages,
|
|
154
|
-
this.workdir,
|
|
155
|
-
this.latestTotalTokens,
|
|
156
|
-
this.sessionStartTime,
|
|
157
|
-
this.sessionDir,
|
|
158
|
-
);
|
|
174
|
+
await createSession(this.sessionId, this.workdir, this.sessionType);
|
|
159
175
|
} catch (error) {
|
|
160
|
-
this.logger?.error("Failed to
|
|
176
|
+
this.logger?.error("Failed to create session:", error);
|
|
161
177
|
}
|
|
162
178
|
}
|
|
163
179
|
|
|
180
|
+
public setMessages(messages: Message[]): void {
|
|
181
|
+
this.messages = [...messages];
|
|
182
|
+
this.callbacks.onMessagesChange?.([...messages]);
|
|
183
|
+
}
|
|
184
|
+
|
|
164
185
|
/**
|
|
165
|
-
*
|
|
186
|
+
* Save current session
|
|
166
187
|
*/
|
|
167
|
-
public async
|
|
168
|
-
restoreSessionId?: string,
|
|
169
|
-
continueLastSession?: boolean,
|
|
170
|
-
): Promise<void> {
|
|
171
|
-
// Clean up expired sessions first
|
|
188
|
+
public async saveSession(): Promise<void> {
|
|
172
189
|
try {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this.logger?.warn("Failed to cleanup expired sessions:", error);
|
|
176
|
-
}
|
|
190
|
+
// Only save messages that haven't been saved yet
|
|
191
|
+
const unsavedMessages = this.messages.slice(this.savedMessageCount);
|
|
177
192
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
try {
|
|
183
|
-
let sessionToRestore: SessionData | null = null;
|
|
193
|
+
if (unsavedMessages.length === 0) {
|
|
194
|
+
// No new messages to save
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
184
197
|
|
|
185
|
-
if (
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
} else if (continueLastSession) {
|
|
192
|
-
sessionToRestore = await getLatestSession(
|
|
193
|
-
this.workdir,
|
|
194
|
-
this.sessionDir,
|
|
195
|
-
);
|
|
196
|
-
if (!sessionToRestore) {
|
|
197
|
-
console.error(
|
|
198
|
-
`No previous session found for workdir: ${this.workdir}`,
|
|
199
|
-
);
|
|
200
|
-
process.exit(1);
|
|
201
|
-
}
|
|
198
|
+
// Create session if needed (only when we have messages to save)
|
|
199
|
+
if (this.savedMessageCount === 0) {
|
|
200
|
+
// This is the first time saving messages, so create the session
|
|
201
|
+
await this.createSessionIfNeeded();
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
// Use JSONL format for new sessions
|
|
205
|
+
await appendMessages(
|
|
206
|
+
this.sessionId,
|
|
207
|
+
unsavedMessages, // Only append new messages
|
|
208
|
+
this.workdir,
|
|
209
|
+
this.sessionType,
|
|
210
|
+
);
|
|
206
211
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
sessionToRestore.id,
|
|
210
|
-
sessionToRestore.messages,
|
|
211
|
-
sessionToRestore.metadata.latestTotalTokens,
|
|
212
|
-
);
|
|
213
|
-
}
|
|
212
|
+
// Update the saved message count
|
|
213
|
+
this.savedMessageCount = this.messages.length;
|
|
214
214
|
} catch (error) {
|
|
215
|
-
|
|
216
|
-
process.exit(1);
|
|
215
|
+
this.logger?.error("Failed to save session:", error);
|
|
217
216
|
}
|
|
218
217
|
}
|
|
219
218
|
|
|
220
219
|
public setlatestTotalTokens(latestTotalTokens: number): void {
|
|
221
220
|
if (this.latestTotalTokens !== latestTotalTokens) {
|
|
222
221
|
this.latestTotalTokens = latestTotalTokens;
|
|
222
|
+
|
|
223
223
|
this.callbacks.onLatestTotalTokensChange?.(latestTotalTokens);
|
|
224
224
|
}
|
|
225
225
|
}
|
|
@@ -235,23 +235,23 @@ export class MessageManager {
|
|
|
235
235
|
public clearMessages(): void {
|
|
236
236
|
this.setMessages([]);
|
|
237
237
|
this.setUserInputHistory([]);
|
|
238
|
-
this.setSessionId(
|
|
238
|
+
this.setSessionId(generateSessionId());
|
|
239
239
|
this.setlatestTotalTokens(0);
|
|
240
|
-
this.
|
|
240
|
+
this.savedMessageCount = 0; // Reset saved message count
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
// Initialize state from session data
|
|
244
|
-
public initializeFromSession(
|
|
245
|
-
|
|
246
|
-
messages
|
|
247
|
-
latestTotalTokens
|
|
248
|
-
): void {
|
|
249
|
-
this.setSessionId(sessionId);
|
|
250
|
-
this.setMessages([...messages]);
|
|
251
|
-
this.setlatestTotalTokens(latestTotalTokens);
|
|
244
|
+
public initializeFromSession(sessionData: SessionData): void {
|
|
245
|
+
this.setSessionId(sessionData.id);
|
|
246
|
+
this.setMessages([...sessionData.messages]);
|
|
247
|
+
this.setlatestTotalTokens(sessionData.metadata.latestTotalTokens);
|
|
252
248
|
|
|
253
249
|
// Extract user input history from session messages
|
|
254
|
-
this.setUserInputHistory(extractUserInputHistory(messages));
|
|
250
|
+
this.setUserInputHistory(extractUserInputHistory(sessionData.messages));
|
|
251
|
+
|
|
252
|
+
// Set saved message count to the number of loaded messages since they're already saved
|
|
253
|
+
// This must be done after setSessionId which resets it to 0
|
|
254
|
+
this.savedMessageCount = sessionData.messages.length;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
// Add to input history
|
|
@@ -280,21 +280,68 @@ export class MessageManager {
|
|
|
280
280
|
});
|
|
281
281
|
this.setMessages(newMessages);
|
|
282
282
|
this.callbacks.onUserMessageAdded?.(params);
|
|
283
|
+
|
|
284
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
283
285
|
}
|
|
284
286
|
|
|
285
287
|
public addAssistantMessage(
|
|
286
288
|
content?: string,
|
|
287
289
|
toolCalls?: ChatCompletionMessageFunctionToolCall[],
|
|
288
290
|
usage?: Usage,
|
|
291
|
+
additionalFields?: Record<string, unknown>,
|
|
289
292
|
): void {
|
|
293
|
+
const additionalFieldsRecord = additionalFields
|
|
294
|
+
? Object.fromEntries(
|
|
295
|
+
Object.entries(additionalFields).filter(
|
|
296
|
+
([, value]) => value !== undefined,
|
|
297
|
+
),
|
|
298
|
+
)
|
|
299
|
+
: undefined;
|
|
300
|
+
|
|
290
301
|
const newMessages = addAssistantMessageToMessages(
|
|
291
302
|
this.messages,
|
|
292
303
|
content,
|
|
293
304
|
toolCalls,
|
|
294
305
|
usage,
|
|
306
|
+
additionalFieldsRecord,
|
|
295
307
|
);
|
|
296
308
|
this.setMessages(newMessages);
|
|
297
|
-
this.callbacks.onAssistantMessageAdded?.(
|
|
309
|
+
this.callbacks.onAssistantMessageAdded?.();
|
|
310
|
+
|
|
311
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
public mergeAssistantAdditionalFields(
|
|
315
|
+
additionalFields: Record<string, unknown>,
|
|
316
|
+
): void {
|
|
317
|
+
if (!additionalFields || Object.keys(additionalFields).length === 0) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const newMessages = [...this.messages];
|
|
322
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
323
|
+
const message = newMessages[i];
|
|
324
|
+
if (message.role === "assistant") {
|
|
325
|
+
const mergedAdditionalFields = {
|
|
326
|
+
...(message.additionalFields || {}),
|
|
327
|
+
} as Record<string, unknown>;
|
|
328
|
+
|
|
329
|
+
for (const [key, value] of Object.entries(additionalFields)) {
|
|
330
|
+
if (value === undefined) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
mergedAdditionalFields[key] = value;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (Object.keys(mergedAdditionalFields).length === 0) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
message.additionalFields = mergedAdditionalFields;
|
|
341
|
+
this.setMessages(newMessages);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
298
345
|
}
|
|
299
346
|
|
|
300
347
|
public updateToolBlock(params: AgentToolBlockUpdateParams): void {
|
|
@@ -305,27 +352,17 @@ export class MessageManager {
|
|
|
305
352
|
result: params.result,
|
|
306
353
|
success: params.success,
|
|
307
354
|
error: params.error,
|
|
308
|
-
|
|
355
|
+
stage: params.stage,
|
|
309
356
|
name: params.name,
|
|
310
357
|
shortResult: params.shortResult,
|
|
311
358
|
images: params.images,
|
|
312
359
|
compactParams: params.compactParams,
|
|
360
|
+
parametersChunk: params.parametersChunk,
|
|
313
361
|
});
|
|
314
362
|
this.setMessages(newMessages);
|
|
315
363
|
this.callbacks.onToolBlockUpdated?.(params);
|
|
316
|
-
}
|
|
317
364
|
|
|
318
|
-
|
|
319
|
-
filePath: string,
|
|
320
|
-
diffResult: Array<{ value: string; added?: boolean; removed?: boolean }>,
|
|
321
|
-
): void {
|
|
322
|
-
const newMessages = addDiffBlockToMessage({
|
|
323
|
-
messages: this.messages,
|
|
324
|
-
path: filePath,
|
|
325
|
-
diffResult,
|
|
326
|
-
});
|
|
327
|
-
this.setMessages(newMessages);
|
|
328
|
-
this.callbacks.onDiffBlockAdded?.(filePath, JSON.stringify(diffResult));
|
|
365
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
329
366
|
}
|
|
330
367
|
|
|
331
368
|
public addErrorBlock(error: string): void {
|
|
@@ -343,6 +380,7 @@ export class MessageManager {
|
|
|
343
380
|
public compressMessagesAndUpdateSession(
|
|
344
381
|
insertIndex: number,
|
|
345
382
|
compressedContent: string,
|
|
383
|
+
usage?: Usage,
|
|
346
384
|
): void {
|
|
347
385
|
const currentMessages = this.messages;
|
|
348
386
|
|
|
@@ -353,8 +391,10 @@ export class MessageManager {
|
|
|
353
391
|
{
|
|
354
392
|
type: "compress",
|
|
355
393
|
content: compressedContent,
|
|
394
|
+
sessionId: this.sessionId,
|
|
356
395
|
},
|
|
357
396
|
],
|
|
397
|
+
...(usage && { usage }),
|
|
358
398
|
};
|
|
359
399
|
|
|
360
400
|
// Convert negative index to positive index
|
|
@@ -368,7 +408,7 @@ export class MessageManager {
|
|
|
368
408
|
];
|
|
369
409
|
|
|
370
410
|
// Update sessionId
|
|
371
|
-
this.setSessionId(
|
|
411
|
+
this.setSessionId(generateSessionId());
|
|
372
412
|
|
|
373
413
|
// Set new message list
|
|
374
414
|
this.setMessages(newMessages);
|
|
@@ -428,8 +468,9 @@ export class MessageManager {
|
|
|
428
468
|
public addSubagentBlock(
|
|
429
469
|
subagentId: string,
|
|
430
470
|
subagentName: string,
|
|
471
|
+
sessionId: string,
|
|
472
|
+
configuration: SubagentConfiguration,
|
|
431
473
|
status: "active" | "completed" | "error" = "active",
|
|
432
|
-
subagentMessages: Message[] = [],
|
|
433
474
|
parameters: {
|
|
434
475
|
description: string;
|
|
435
476
|
prompt: string;
|
|
@@ -440,8 +481,9 @@ export class MessageManager {
|
|
|
440
481
|
messages: this.messages,
|
|
441
482
|
subagentId,
|
|
442
483
|
subagentName,
|
|
484
|
+
sessionId,
|
|
443
485
|
status,
|
|
444
|
-
|
|
486
|
+
configuration,
|
|
445
487
|
};
|
|
446
488
|
const updatedMessages = addSubagentBlockToMessage(params);
|
|
447
489
|
this.setMessages(updatedMessages);
|
|
@@ -452,7 +494,7 @@ export class MessageManager {
|
|
|
452
494
|
subagentId: string,
|
|
453
495
|
updates: Partial<{
|
|
454
496
|
status: "active" | "completed" | "error" | "aborted";
|
|
455
|
-
|
|
497
|
+
sessionId: string;
|
|
456
498
|
}>,
|
|
457
499
|
): void {
|
|
458
500
|
const updatedMessages = updateSubagentBlockInMessage(
|
|
@@ -465,13 +507,8 @@ export class MessageManager {
|
|
|
465
507
|
messages: this.messages,
|
|
466
508
|
subagentId,
|
|
467
509
|
status: updates.status || "active",
|
|
468
|
-
subagentMessages: updates.messages || [],
|
|
469
510
|
};
|
|
470
|
-
this.callbacks.onSubAgentBlockUpdated?.(
|
|
471
|
-
params.subagentId,
|
|
472
|
-
params.messages,
|
|
473
|
-
params.status,
|
|
474
|
-
);
|
|
511
|
+
this.callbacks.onSubAgentBlockUpdated?.(params.subagentId, params.status);
|
|
475
512
|
}
|
|
476
513
|
|
|
477
514
|
/**
|
|
@@ -487,6 +524,106 @@ export class MessageManager {
|
|
|
487
524
|
this.callbacks.onUsagesChange?.(usages);
|
|
488
525
|
}
|
|
489
526
|
|
|
527
|
+
/**
|
|
528
|
+
* Update the current assistant message content during streaming
|
|
529
|
+
* This method updates the last assistant message's content without creating a new message
|
|
530
|
+
* FR-001: Tracks and provides both chunk (new content) and accumulated (total content)
|
|
531
|
+
*/
|
|
532
|
+
public updateCurrentMessageContent(newAccumulatedContent: string): void {
|
|
533
|
+
if (this.messages.length === 0) return;
|
|
534
|
+
|
|
535
|
+
const lastMessage = this.messages[this.messages.length - 1];
|
|
536
|
+
if (lastMessage.role !== "assistant") return;
|
|
537
|
+
|
|
538
|
+
// Get the current content to calculate the chunk
|
|
539
|
+
const textBlockIndex = lastMessage.blocks.findIndex(
|
|
540
|
+
(block) => block.type === "text",
|
|
541
|
+
);
|
|
542
|
+
const currentContent =
|
|
543
|
+
textBlockIndex >= 0
|
|
544
|
+
? (
|
|
545
|
+
lastMessage.blocks[textBlockIndex] as {
|
|
546
|
+
type: "text";
|
|
547
|
+
content: string;
|
|
548
|
+
}
|
|
549
|
+
).content || ""
|
|
550
|
+
: "";
|
|
551
|
+
|
|
552
|
+
// Calculate the chunk (new content since last update)
|
|
553
|
+
const chunk = newAccumulatedContent.slice(currentContent.length);
|
|
554
|
+
|
|
555
|
+
if (textBlockIndex >= 0) {
|
|
556
|
+
// Update existing text block
|
|
557
|
+
lastMessage.blocks[textBlockIndex] = {
|
|
558
|
+
type: "text",
|
|
559
|
+
content: newAccumulatedContent,
|
|
560
|
+
};
|
|
561
|
+
} else {
|
|
562
|
+
// Add new text block if none exists
|
|
563
|
+
lastMessage.blocks.push({
|
|
564
|
+
type: "text",
|
|
565
|
+
content: newAccumulatedContent,
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// FR-001: Trigger callbacks with chunk and accumulated content
|
|
570
|
+
this.callbacks.onAssistantContentUpdated?.(chunk, newAccumulatedContent);
|
|
571
|
+
|
|
572
|
+
// Note: Subagent-specific callbacks are now handled by SubagentManager
|
|
573
|
+
|
|
574
|
+
this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Update the current assistant message reasoning during streaming
|
|
579
|
+
* This method updates the last assistant message's reasoning content without creating a new message
|
|
580
|
+
*/
|
|
581
|
+
public updateCurrentMessageReasoning(newAccumulatedReasoning: string): void {
|
|
582
|
+
if (this.messages.length === 0) return;
|
|
583
|
+
|
|
584
|
+
const lastMessage = this.messages[this.messages.length - 1];
|
|
585
|
+
if (lastMessage.role !== "assistant") return;
|
|
586
|
+
|
|
587
|
+
// Get the current reasoning content to calculate the chunk
|
|
588
|
+
const reasoningBlockIndex = lastMessage.blocks.findIndex(
|
|
589
|
+
(block) => block.type === "reasoning",
|
|
590
|
+
);
|
|
591
|
+
const currentReasoning =
|
|
592
|
+
reasoningBlockIndex >= 0
|
|
593
|
+
? (
|
|
594
|
+
lastMessage.blocks[reasoningBlockIndex] as {
|
|
595
|
+
type: "reasoning";
|
|
596
|
+
content: string;
|
|
597
|
+
}
|
|
598
|
+
).content || ""
|
|
599
|
+
: "";
|
|
600
|
+
|
|
601
|
+
// Calculate the chunk (new content since last update)
|
|
602
|
+
const chunk = newAccumulatedReasoning.slice(currentReasoning.length);
|
|
603
|
+
|
|
604
|
+
if (reasoningBlockIndex >= 0) {
|
|
605
|
+
// Update existing reasoning block
|
|
606
|
+
lastMessage.blocks[reasoningBlockIndex] = {
|
|
607
|
+
type: "reasoning",
|
|
608
|
+
content: newAccumulatedReasoning,
|
|
609
|
+
};
|
|
610
|
+
} else {
|
|
611
|
+
// Add new reasoning block if none exists
|
|
612
|
+
lastMessage.blocks.push({
|
|
613
|
+
type: "reasoning",
|
|
614
|
+
content: newAccumulatedReasoning,
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Trigger callbacks with chunk and accumulated reasoning content
|
|
619
|
+
this.callbacks.onAssistantReasoningUpdated?.(
|
|
620
|
+
chunk,
|
|
621
|
+
newAccumulatedReasoning,
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
this.callbacks.onMessagesChange?.([...this.messages]); // Still need to notify of changes
|
|
625
|
+
}
|
|
626
|
+
|
|
490
627
|
/**
|
|
491
628
|
* Remove the last user message from the conversation
|
|
492
629
|
* Used for hook error handling when the user prompt needs to be erased
|