wave-agent-sdk 0.0.6 → 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 (180) hide show
  1. package/dist/agent.d.ts +32 -20
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +209 -24
  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 +248 -132
  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 +13 -16
  16. package/dist/managers/hookManager.d.ts.map +1 -1
  17. package/dist/managers/hookManager.js +81 -44
  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 +41 -24
  22. package/dist/managers/messageManager.d.ts.map +1 -1
  23. package/dist/managers/messageManager.js +168 -49
  24. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  25. package/dist/managers/slashCommandManager.js +9 -3
  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 +190 -19
  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/todoWriteTool.d.ts.map +1 -1
  64. package/dist/tools/todoWriteTool.js +3 -10
  65. package/dist/tools/writeTool.d.ts.map +1 -1
  66. package/dist/tools/writeTool.js +5 -6
  67. package/dist/types/commands.d.ts +4 -0
  68. package/dist/types/commands.d.ts.map +1 -1
  69. package/dist/types/core.d.ts +35 -0
  70. package/dist/types/core.d.ts.map +1 -1
  71. package/dist/types/environment.d.ts +42 -0
  72. package/dist/types/environment.d.ts.map +1 -0
  73. package/dist/types/environment.js +21 -0
  74. package/dist/types/hooks.d.ts +8 -2
  75. package/dist/types/hooks.d.ts.map +1 -1
  76. package/dist/types/hooks.js +8 -2
  77. package/dist/types/index.d.ts +2 -0
  78. package/dist/types/index.d.ts.map +1 -1
  79. package/dist/types/index.js +2 -0
  80. package/dist/types/memoryStore.d.ts +82 -0
  81. package/dist/types/memoryStore.d.ts.map +1 -0
  82. package/dist/types/memoryStore.js +7 -0
  83. package/dist/types/messaging.d.ts +21 -9
  84. package/dist/types/messaging.d.ts.map +1 -1
  85. package/dist/types/messaging.js +5 -1
  86. package/dist/types/session.d.ts +20 -0
  87. package/dist/types/session.d.ts.map +1 -0
  88. package/dist/types/session.js +7 -0
  89. package/dist/utils/bashHistory.d.ts.map +1 -1
  90. package/dist/utils/bashHistory.js +27 -26
  91. package/dist/utils/cacheControlUtils.d.ts +121 -0
  92. package/dist/utils/cacheControlUtils.d.ts.map +1 -0
  93. package/dist/utils/cacheControlUtils.js +367 -0
  94. package/dist/utils/commandPathResolver.d.ts +52 -0
  95. package/dist/utils/commandPathResolver.d.ts.map +1 -0
  96. package/dist/utils/commandPathResolver.js +145 -0
  97. package/dist/utils/configPaths.d.ts +85 -0
  98. package/dist/utils/configPaths.d.ts.map +1 -0
  99. package/dist/utils/configPaths.js +121 -0
  100. package/dist/utils/configResolver.d.ts +37 -10
  101. package/dist/utils/configResolver.d.ts.map +1 -1
  102. package/dist/utils/configResolver.js +127 -23
  103. package/dist/utils/constants.d.ts +1 -1
  104. package/dist/utils/constants.js +1 -1
  105. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  106. package/dist/utils/convertMessagesForAPI.js +8 -13
  107. package/dist/utils/customCommands.d.ts.map +1 -1
  108. package/dist/utils/customCommands.js +66 -21
  109. package/dist/utils/fileUtils.d.ts +15 -0
  110. package/dist/utils/fileUtils.d.ts.map +1 -0
  111. package/dist/utils/fileUtils.js +61 -0
  112. package/dist/utils/globalLogger.d.ts +102 -0
  113. package/dist/utils/globalLogger.d.ts.map +1 -0
  114. package/dist/utils/globalLogger.js +136 -0
  115. package/dist/utils/hookMatcher.d.ts +1 -6
  116. package/dist/utils/hookMatcher.d.ts.map +1 -1
  117. package/dist/utils/mcpUtils.d.ts.map +1 -1
  118. package/dist/utils/mcpUtils.js +25 -3
  119. package/dist/utils/messageOperations.d.ts +27 -27
  120. package/dist/utils/messageOperations.d.ts.map +1 -1
  121. package/dist/utils/messageOperations.js +46 -36
  122. package/dist/utils/pathEncoder.d.ts +104 -0
  123. package/dist/utils/pathEncoder.d.ts.map +1 -0
  124. package/dist/utils/pathEncoder.js +272 -0
  125. package/dist/utils/subagentParser.d.ts.map +1 -1
  126. package/dist/utils/subagentParser.js +2 -1
  127. package/dist/utils/tokenCalculation.d.ts +26 -0
  128. package/dist/utils/tokenCalculation.d.ts.map +1 -0
  129. package/dist/utils/tokenCalculation.js +36 -0
  130. package/package.json +6 -3
  131. package/src/agent.ts +301 -37
  132. package/src/constants/events.ts +38 -0
  133. package/src/index.ts +2 -0
  134. package/src/managers/aiManager.ts +325 -173
  135. package/src/managers/backgroundBashManager.ts +7 -6
  136. package/src/managers/hookManager.ts +106 -84
  137. package/src/managers/liveConfigManager.ts +248 -0
  138. package/src/managers/messageManager.ts +237 -100
  139. package/src/managers/slashCommandManager.ts +9 -7
  140. package/src/managers/subagentManager.ts +284 -22
  141. package/src/services/aiService.ts +474 -83
  142. package/src/services/configurationWatcher.ts +622 -0
  143. package/src/services/fileWatcher.ts +301 -0
  144. package/src/services/hook.ts +538 -47
  145. package/src/services/jsonlHandler.ts +319 -0
  146. package/src/services/memory.ts +92 -12
  147. package/src/services/memoryStore.ts +279 -0
  148. package/src/services/session.ts +381 -157
  149. package/src/tools/bashTool.ts +5 -4
  150. package/src/tools/deleteFileTool.ts +2 -1
  151. package/src/tools/editTool.ts +3 -2
  152. package/src/tools/multiEditTool.ts +4 -3
  153. package/src/tools/readTool.ts +2 -1
  154. package/src/tools/todoWriteTool.ts +3 -11
  155. package/src/tools/writeTool.ts +7 -6
  156. package/src/types/commands.ts +6 -0
  157. package/src/types/core.ts +44 -0
  158. package/src/types/environment.ts +60 -0
  159. package/src/types/hooks.ts +21 -8
  160. package/src/types/index.ts +2 -0
  161. package/src/types/memoryStore.ts +94 -0
  162. package/src/types/messaging.ts +21 -10
  163. package/src/types/session.ts +25 -0
  164. package/src/utils/bashHistory.ts +27 -27
  165. package/src/utils/cacheControlUtils.ts +540 -0
  166. package/src/utils/commandPathResolver.ts +189 -0
  167. package/src/utils/configPaths.ts +163 -0
  168. package/src/utils/configResolver.ts +182 -22
  169. package/src/utils/constants.ts +1 -1
  170. package/src/utils/convertMessagesForAPI.ts +8 -14
  171. package/src/utils/customCommands.ts +90 -22
  172. package/src/utils/fileUtils.ts +65 -0
  173. package/src/utils/globalLogger.ts +145 -0
  174. package/src/utils/hookMatcher.ts +1 -12
  175. package/src/utils/mcpUtils.ts +34 -3
  176. package/src/utils/messageOperations.ts +77 -60
  177. package/src/utils/pathEncoder.ts +379 -0
  178. package/src/utils/subagentParser.ts +2 -1
  179. package/src/utils/tokenCalculation.ts +43 -0
  180. package/src/types/index.ts.backup +0 -357
@@ -0,0 +1,319 @@
1
+ /**
2
+ * JSONL file operations service
3
+ * Handles reading and writing JSONL (JSON Lines) session files for improved performance
4
+ */
5
+
6
+ import { appendFile, readFile, writeFile, stat, mkdir } from "fs/promises";
7
+ import { dirname } from "path";
8
+ import { getLastLine, readFirstLine } from "../utils/fileUtils.js";
9
+
10
+ import type { Message } from "../types/index.js";
11
+ import type { SessionMessage, SessionMetadataLine } from "../types/session.js";
12
+
13
+ /**
14
+ * JSONL write options
15
+ */
16
+ export interface JsonlWriteOptions {
17
+ // Safety options
18
+ atomic?: boolean; // Default: true (write to temp file first)
19
+ }
20
+
21
+ /**
22
+ * JSONL handler class for message persistence operations
23
+ */
24
+ export class JsonlHandler {
25
+ private readonly defaultWriteOptions: Required<JsonlWriteOptions>;
26
+
27
+ constructor() {
28
+ this.defaultWriteOptions = {
29
+ atomic: true,
30
+ };
31
+ }
32
+
33
+ /**
34
+ * Create a new session file with metadata header
35
+ */
36
+ async createSession(
37
+ filePath: string,
38
+ sessionId: string,
39
+ workdir: string,
40
+ sessionType: "main" | "subagent" = "main",
41
+ parentSessionId?: string,
42
+ subagentType?: string,
43
+ ): Promise<void> {
44
+ const metadataLine: SessionMetadataLine = {
45
+ __meta__: true,
46
+ sessionId,
47
+ sessionType,
48
+ ...(parentSessionId && { parentSessionId }),
49
+ ...(subagentType && { subagentType }),
50
+ workdir,
51
+ startedAt: new Date().toISOString(),
52
+ };
53
+
54
+ // Ensure directory exists
55
+ await this.ensureDirectory(dirname(filePath));
56
+
57
+ // Write metadata line as first line
58
+ await writeFile(filePath, JSON.stringify(metadataLine) + "\n", "utf8");
59
+ }
60
+
61
+ /**
62
+ * Append a single message to JSONL file
63
+ */
64
+ async appendMessage(filePath: string, message: Message): Promise<void> {
65
+ return this.appendMessages(filePath, [message]);
66
+ }
67
+
68
+ /**
69
+ * Append multiple messages to JSONL file
70
+ */
71
+ async appendMessages(filePath: string, messages: Message[]): Promise<void> {
72
+ if (messages.length === 0) {
73
+ return;
74
+ }
75
+
76
+ // Convert to SessionMessage format with timestamps
77
+ const sessionMessages: SessionMessage[] = messages.map((message) => ({
78
+ ...message,
79
+ timestamp: new Date().toISOString(),
80
+ }));
81
+
82
+ return this.append(filePath, sessionMessages);
83
+ }
84
+
85
+ /**
86
+ * Append messages to JSONL file
87
+ */
88
+ async append(
89
+ filePath: string,
90
+ messages: SessionMessage[],
91
+ options?: JsonlWriteOptions,
92
+ ): Promise<void> {
93
+ if (messages.length === 0) {
94
+ return;
95
+ }
96
+
97
+ const opts = { ...this.defaultWriteOptions, ...options };
98
+
99
+ // Validate messages (always enabled for data integrity)
100
+ this.validateMessages(messages);
101
+
102
+ // Ensure directory exists
103
+ await this.ensureDirectory(dirname(filePath));
104
+
105
+ // Convert messages to JSONL lines (always compact JSON)
106
+ const lines = messages.map((message) => {
107
+ const { timestamp: existingTimestamp, ...messageWithoutTimestamp } =
108
+ message;
109
+ const messageWithTimestamp = {
110
+ timestamp: existingTimestamp || new Date().toISOString(),
111
+ ...messageWithoutTimestamp,
112
+ };
113
+
114
+ return JSON.stringify(messageWithTimestamp);
115
+ });
116
+
117
+ const content = lines.join("\n") + "\n";
118
+
119
+ if (opts.atomic) {
120
+ // Write to temp file first, then rename
121
+ const tempPath = `${filePath}.tmp`;
122
+ await writeFile(tempPath, content, "utf8");
123
+
124
+ // Atomic rename
125
+ const { rename } = await import("fs/promises");
126
+ await rename(tempPath, filePath);
127
+ } else {
128
+ // Direct append
129
+ await appendFile(filePath, content, "utf8");
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Read all messages from JSONL file
135
+ * Includes metadata handling for backward compatibility
136
+ */
137
+ async read(filePath: string): Promise<SessionMessage[]> {
138
+ try {
139
+ const content = await readFile(filePath, "utf8");
140
+ const lines = content
141
+ .split(/\r?\n/)
142
+ .map((line: string) => line.trim())
143
+ .filter((line: string) => line.length > 0);
144
+
145
+ if (lines.length === 0) {
146
+ return [];
147
+ }
148
+
149
+ const allMessages: SessionMessage[] = [];
150
+
151
+ // Skip metadata line if present (first line with __meta__: true)
152
+ let startIndex = 0;
153
+ if (lines.length > 0) {
154
+ try {
155
+ const firstLine = JSON.parse(lines[0]);
156
+ if (firstLine.__meta__ === true) {
157
+ startIndex = 1; // Skip metadata line
158
+ }
159
+ } catch (error) {
160
+ // If first line is not valid JSON, throw error with line number
161
+ if (lines[0].trim().length > 0) {
162
+ // Only throw if line is not empty
163
+ throw new Error(`Invalid JSON at line 1: ${error}`);
164
+ }
165
+ }
166
+ }
167
+
168
+ // Parse all messages
169
+ for (let i = startIndex; i < lines.length; i++) {
170
+ const line = lines[i];
171
+
172
+ try {
173
+ const message = JSON.parse(line) as SessionMessage;
174
+ allMessages.push(message);
175
+ } catch (error) {
176
+ // Throw error for invalid JSON lines with line number
177
+ throw new Error(`Invalid JSON at line ${i + 1}: ${error}`);
178
+ }
179
+ }
180
+
181
+ return allMessages;
182
+ } catch (error) {
183
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
184
+ return [];
185
+ }
186
+ throw new Error(`Failed to read JSONL file "${filePath}": ${error}`);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Get the last message from JSONL file using efficient file reading
192
+ */
193
+ async getLastMessage(filePath: string): Promise<SessionMessage | null> {
194
+ try {
195
+ // First check if file exists
196
+ try {
197
+ await stat(filePath);
198
+ } catch (err) {
199
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") {
200
+ return null;
201
+ }
202
+ throw err;
203
+ }
204
+
205
+ // Use our elegant utility to get the last line
206
+ const lastLine = await getLastLine(filePath);
207
+
208
+ if (!lastLine) {
209
+ return null;
210
+ }
211
+
212
+ try {
213
+ const parsed = JSON.parse(lastLine);
214
+
215
+ // Skip metadata line
216
+ if (parsed.__meta__ === true) {
217
+ // If the last line is metadata, the file only contains metadata
218
+ return null;
219
+ }
220
+
221
+ // Found a valid message
222
+ return parsed as SessionMessage;
223
+ } catch (error) {
224
+ throw new Error(`Invalid JSON in last line of "${filePath}": ${error}`);
225
+ }
226
+ } catch (error) {
227
+ throw new Error(
228
+ `Failed to get last message from "${filePath}": ${error}`,
229
+ );
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Read session metadata from first line (streaming - only reads first line)
235
+ */
236
+ async readMetadata(filePath: string): Promise<SessionMetadataLine | null> {
237
+ try {
238
+ // First check if file exists
239
+ try {
240
+ await stat(filePath);
241
+ } catch (err) {
242
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") {
243
+ return null;
244
+ }
245
+ throw err;
246
+ }
247
+
248
+ // Read the first line efficiently
249
+ const firstLine = await readFirstLine(filePath);
250
+
251
+ if (!firstLine) {
252
+ return null; // Empty file or first line
253
+ }
254
+
255
+ try {
256
+ const parsed = JSON.parse(firstLine);
257
+ if (parsed.__meta__ === true) {
258
+ return parsed as SessionMetadataLine;
259
+ } else {
260
+ return null; // First line is not metadata
261
+ }
262
+ } catch {
263
+ return null; // Invalid JSON on first line
264
+ }
265
+ } catch (error) {
266
+ throw new Error(`Failed to read metadata from "${filePath}": ${error}`);
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Check if a session file has metadata (first line check only)
272
+ * Very efficient - only reads first line
273
+ */
274
+ async hasMetadata(filePath: string): Promise<boolean> {
275
+ const metadata = await this.readMetadata(filePath);
276
+ return metadata !== null;
277
+ }
278
+
279
+ /**
280
+ * Validate messages before writing
281
+ */
282
+ private validateMessages(messages: SessionMessage[]): void {
283
+ for (let i = 0; i < messages.length; i++) {
284
+ const message = messages[i];
285
+
286
+ if (!message.role) {
287
+ throw new Error(
288
+ `Message at index ${i} is missing required field: role`,
289
+ );
290
+ }
291
+
292
+ if (!message.blocks) {
293
+ throw new Error(
294
+ `Message at index ${i} is missing required field: blocks`,
295
+ );
296
+ }
297
+
298
+ if (!Array.isArray(message.blocks)) {
299
+ throw new Error(
300
+ `Message at index ${i} has invalid blocks field: must be an array`,
301
+ );
302
+ }
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Ensure directory exists for the given file path
308
+ */
309
+ private async ensureDirectory(dirPath: string): Promise<void> {
310
+ try {
311
+ await mkdir(dirPath, { recursive: true });
312
+ } catch (error) {
313
+ const err = error as NodeJS.ErrnoException;
314
+ if (err.code !== "EEXIST") {
315
+ throw error;
316
+ }
317
+ }
318
+ }
319
+ }
@@ -1,6 +1,27 @@
1
1
  import { promises as fs } from "fs";
2
2
  import path from "path";
3
3
  import { USER_MEMORY_FILE, DATA_DIRECTORY } from "../utils/constants.js";
4
+ import { MemoryStoreService } from "./memoryStore.js";
5
+ import { logger } from "../utils/globalLogger.js";
6
+
7
+ // Global memory store instance for project memory files
8
+ let globalMemoryStore: MemoryStoreService | null = null;
9
+
10
+ /**
11
+ * Initialize global memory store
12
+ */
13
+ export const initializeMemoryStore = (
14
+ memoryStore: MemoryStoreService,
15
+ ): void => {
16
+ globalMemoryStore = memoryStore;
17
+ };
18
+
19
+ /**
20
+ * Get current memory store instance
21
+ */
22
+ export const getMemoryStore = (): MemoryStoreService | null => {
23
+ return globalMemoryStore;
24
+ };
4
25
 
5
26
  // Project memory related methods
6
27
  export const isMemoryMessage = (message: string): boolean => {
@@ -28,6 +49,9 @@ export const addMemory = async (
28
49
  } catch (error) {
29
50
  // File does not exist, create new file
30
51
  if ((error as NodeJS.ErrnoException).code === "ENOENT") {
52
+ logger.info("Memory file does not exist, will create new one", {
53
+ memoryFilePath,
54
+ });
31
55
  existingContent =
32
56
  "# Memory\n\nThis is the AI assistant's memory file, recording important information and context.\n\n";
33
57
  } else {
@@ -41,9 +65,23 @@ export const addMemory = async (
41
65
  // Write file
42
66
  await fs.writeFile(memoryFilePath, updatedContent, "utf-8");
43
67
 
44
- // logger.debug(`Memory added to ${memoryFilePath}:`, message);
68
+ // Update memory store if available
69
+ if (globalMemoryStore) {
70
+ try {
71
+ await globalMemoryStore.updateContent(memoryFilePath);
72
+ } catch (error) {
73
+ logger.warn(
74
+ `Failed to update memory store for ${memoryFilePath}:`,
75
+ error,
76
+ );
77
+ }
78
+ } else {
79
+ logger.debug("No global memory store available, skipping store update");
80
+ }
81
+
82
+ logger.debug(`Memory added to ${memoryFilePath}:`, message);
45
83
  } catch (error) {
46
- // logger.error("Failed to add memory:", error);
84
+ logger.error("Failed to add memory:", error);
47
85
  throw new Error(`Failed to add memory: ${(error as Error).message}`);
48
86
  }
49
87
  };
@@ -60,16 +98,19 @@ export const ensureUserMemoryFile = async (): Promise<void> => {
60
98
  } catch (error) {
61
99
  // File does not exist, create new file
62
100
  if ((error as NodeJS.ErrnoException).code === "ENOENT") {
101
+ logger.info("Creating new user memory file", {
102
+ userMemoryFile: USER_MEMORY_FILE,
103
+ });
63
104
  const initialContent =
64
105
  "# User Memory\n\nThis is the user-level memory file, recording important information and context across projects.\n\n";
65
106
  await fs.writeFile(USER_MEMORY_FILE, initialContent, "utf-8");
66
- // logger.debug(`Created user memory file: ${USER_MEMORY_FILE}`);
107
+ logger.debug(`Created user memory file: ${USER_MEMORY_FILE}`);
67
108
  } else {
68
109
  throw error;
69
110
  }
70
111
  }
71
112
  } catch (error) {
72
- // logger.error("Failed to ensure user memory file:", error);
113
+ logger.error("Failed to ensure user memory file:", error);
73
114
  throw new Error(
74
115
  `Failed to ensure user memory file: ${(error as Error).message}`,
75
116
  );
@@ -93,9 +134,9 @@ export const addUserMemory = async (message: string): Promise<void> => {
93
134
  // Write file
94
135
  await fs.writeFile(USER_MEMORY_FILE, updatedContent, "utf-8");
95
136
 
96
- // logger.debug(`User memory added to ${USER_MEMORY_FILE}:`, message);
137
+ logger.debug(`User memory added to ${USER_MEMORY_FILE}:`, message);
97
138
  } catch (error) {
98
- // logger.error("Failed to add user memory:", error);
139
+ logger.error("Failed to add user memory:", error);
99
140
  throw new Error(`Failed to add user memory: ${(error as Error).message}`);
100
141
  }
101
142
  };
@@ -103,22 +144,61 @@ export const addUserMemory = async (message: string): Promise<void> => {
103
144
  export const getUserMemoryContent = async (): Promise<string> => {
104
145
  try {
105
146
  await ensureUserMemoryFile();
106
- return await fs.readFile(USER_MEMORY_FILE, "utf-8");
107
- } catch {
108
- // logger.error("Failed to read user memory:", error);
147
+ const content = await fs.readFile(USER_MEMORY_FILE, "utf-8");
148
+ logger.debug("User memory content read successfully", {
149
+ userMemoryFile: USER_MEMORY_FILE,
150
+ contentLength: content.length,
151
+ });
152
+ return content;
153
+ } catch (error) {
154
+ logger.error("Failed to read user memory:", error);
109
155
  return "";
110
156
  }
111
157
  };
112
158
 
113
- // Read project memory file content
159
+ // Read project memory file content with memory store optimization
114
160
  export const readMemoryFile = async (workdir: string): Promise<string> => {
161
+ const memoryFilePath = path.join(workdir, "AGENTS.md");
162
+
163
+ // Use memory store if available for optimized access
164
+ if (globalMemoryStore) {
165
+ logger.debug("Using memory store for optimized access", { memoryFilePath });
166
+ try {
167
+ const content = await globalMemoryStore.getContent(memoryFilePath);
168
+ logger.debug("Memory content retrieved from store successfully", {
169
+ memoryFilePath,
170
+ contentLength: content.length,
171
+ });
172
+ return content;
173
+ } catch (error) {
174
+ // Fallback to direct file access on memory store error
175
+ logger.warn(
176
+ `Memory store access failed for ${memoryFilePath}, falling back to file system:`,
177
+ error,
178
+ );
179
+ }
180
+ } else {
181
+ logger.debug("No memory store available, using direct file access", {
182
+ memoryFilePath,
183
+ });
184
+ }
185
+
186
+ // Fallback to direct file access (original behavior)
115
187
  try {
116
- const memoryFilePath = path.join(workdir, "AGENTS.md");
117
- return await fs.readFile(memoryFilePath, "utf-8");
188
+ const content = await fs.readFile(memoryFilePath, "utf-8");
189
+ logger.debug("Memory file read successfully via direct file access", {
190
+ memoryFilePath,
191
+ contentLength: content.length,
192
+ });
193
+ return content;
118
194
  } catch (error) {
119
195
  if ((error as NodeJS.ErrnoException).code === "ENOENT") {
196
+ logger.debug("Memory file does not exist, returning empty content", {
197
+ memoryFilePath,
198
+ });
120
199
  return "";
121
200
  }
201
+ logger.error("Failed to read memory file", { memoryFilePath, error });
122
202
  throw error;
123
203
  }
124
204
  };