wave-agent-sdk 0.0.8 → 0.0.11

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 (236) hide show
  1. package/dist/agent.d.ts +92 -23
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +351 -137
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +3 -0
  7. package/dist/managers/aiManager.d.ts +14 -36
  8. package/dist/managers/aiManager.d.ts.map +1 -1
  9. package/dist/managers/aiManager.js +74 -77
  10. package/dist/managers/backgroundBashManager.d.ts.map +1 -1
  11. package/dist/managers/backgroundBashManager.js +4 -3
  12. package/dist/managers/hookManager.d.ts +3 -8
  13. package/dist/managers/hookManager.d.ts.map +1 -1
  14. package/dist/managers/hookManager.js +39 -29
  15. package/dist/managers/liveConfigManager.d.ts +55 -18
  16. package/dist/managers/liveConfigManager.d.ts.map +1 -1
  17. package/dist/managers/liveConfigManager.js +372 -90
  18. package/dist/managers/lspManager.d.ts +43 -0
  19. package/dist/managers/lspManager.d.ts.map +1 -0
  20. package/dist/managers/lspManager.js +326 -0
  21. package/dist/managers/messageManager.d.ts +8 -16
  22. package/dist/managers/messageManager.d.ts.map +1 -1
  23. package/dist/managers/messageManager.js +52 -74
  24. package/dist/managers/permissionManager.d.ts +75 -0
  25. package/dist/managers/permissionManager.d.ts.map +1 -0
  26. package/dist/managers/permissionManager.js +368 -0
  27. package/dist/managers/skillManager.d.ts +1 -0
  28. package/dist/managers/skillManager.d.ts.map +1 -1
  29. package/dist/managers/skillManager.js +2 -1
  30. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  31. package/dist/managers/slashCommandManager.js +0 -1
  32. package/dist/managers/subagentManager.d.ts +8 -23
  33. package/dist/managers/subagentManager.d.ts.map +1 -1
  34. package/dist/managers/subagentManager.js +97 -117
  35. package/dist/managers/toolManager.d.ts +38 -1
  36. package/dist/managers/toolManager.d.ts.map +1 -1
  37. package/dist/managers/toolManager.js +66 -2
  38. package/dist/services/aiService.d.ts +3 -1
  39. package/dist/services/aiService.d.ts.map +1 -1
  40. package/dist/services/aiService.js +123 -30
  41. package/dist/services/configurationService.d.ts +116 -0
  42. package/dist/services/configurationService.d.ts.map +1 -0
  43. package/dist/services/configurationService.js +585 -0
  44. package/dist/services/fileWatcher.d.ts.map +1 -1
  45. package/dist/services/fileWatcher.js +5 -6
  46. package/dist/services/hook.d.ts +7 -124
  47. package/dist/services/hook.d.ts.map +1 -1
  48. package/dist/services/hook.js +46 -458
  49. package/dist/services/jsonlHandler.d.ts +24 -15
  50. package/dist/services/jsonlHandler.d.ts.map +1 -1
  51. package/dist/services/jsonlHandler.js +67 -88
  52. package/dist/services/memory.d.ts +0 -9
  53. package/dist/services/memory.d.ts.map +1 -1
  54. package/dist/services/memory.js +2 -49
  55. package/dist/services/session.d.ts +82 -33
  56. package/dist/services/session.d.ts.map +1 -1
  57. package/dist/services/session.js +275 -181
  58. package/dist/tools/bashTool.d.ts.map +1 -1
  59. package/dist/tools/bashTool.js +109 -11
  60. package/dist/tools/deleteFileTool.d.ts.map +1 -1
  61. package/dist/tools/deleteFileTool.js +25 -0
  62. package/dist/tools/editTool.d.ts.map +1 -1
  63. package/dist/tools/editTool.js +30 -6
  64. package/dist/tools/lspTool.d.ts +6 -0
  65. package/dist/tools/lspTool.d.ts.map +1 -0
  66. package/dist/tools/lspTool.js +589 -0
  67. package/dist/tools/multiEditTool.d.ts.map +1 -1
  68. package/dist/tools/multiEditTool.js +26 -7
  69. package/dist/tools/readTool.d.ts.map +1 -1
  70. package/dist/tools/readTool.js +111 -2
  71. package/dist/tools/skillTool.js +2 -2
  72. package/dist/tools/todoWriteTool.d.ts.map +1 -1
  73. package/dist/tools/todoWriteTool.js +23 -0
  74. package/dist/tools/types.d.ts +11 -8
  75. package/dist/tools/types.d.ts.map +1 -1
  76. package/dist/tools/writeTool.d.ts.map +1 -1
  77. package/dist/tools/writeTool.js +25 -9
  78. package/dist/types/commands.d.ts +0 -1
  79. package/dist/types/commands.d.ts.map +1 -1
  80. package/dist/types/config.d.ts +4 -0
  81. package/dist/types/config.d.ts.map +1 -1
  82. package/dist/types/configuration.d.ts +69 -0
  83. package/dist/types/configuration.d.ts.map +1 -0
  84. package/dist/types/configuration.js +8 -0
  85. package/dist/types/core.d.ts +10 -0
  86. package/dist/types/core.d.ts.map +1 -1
  87. package/dist/types/environment.d.ts +41 -0
  88. package/dist/types/environment.d.ts.map +1 -1
  89. package/dist/types/fileSearch.d.ts +5 -0
  90. package/dist/types/fileSearch.d.ts.map +1 -0
  91. package/dist/types/fileSearch.js +1 -0
  92. package/dist/types/hooks.d.ts +11 -2
  93. package/dist/types/hooks.d.ts.map +1 -1
  94. package/dist/types/hooks.js +1 -7
  95. package/dist/types/index.d.ts +5 -0
  96. package/dist/types/index.d.ts.map +1 -1
  97. package/dist/types/index.js +5 -0
  98. package/dist/types/lsp.d.ts +90 -0
  99. package/dist/types/lsp.d.ts.map +1 -0
  100. package/dist/types/lsp.js +4 -0
  101. package/dist/types/messaging.d.ts +6 -11
  102. package/dist/types/messaging.d.ts.map +1 -1
  103. package/dist/types/permissions.d.ts +39 -0
  104. package/dist/types/permissions.d.ts.map +1 -0
  105. package/dist/types/permissions.js +12 -0
  106. package/dist/types/session.d.ts +1 -6
  107. package/dist/types/session.d.ts.map +1 -1
  108. package/dist/types/skills.d.ts +1 -0
  109. package/dist/types/skills.d.ts.map +1 -1
  110. package/dist/types/tools.d.ts +35 -0
  111. package/dist/types/tools.d.ts.map +1 -0
  112. package/dist/types/tools.js +4 -0
  113. package/dist/utils/abortUtils.d.ts +34 -0
  114. package/dist/utils/abortUtils.d.ts.map +1 -0
  115. package/dist/utils/abortUtils.js +92 -0
  116. package/dist/utils/bashHistory.d.ts +4 -0
  117. package/dist/utils/bashHistory.d.ts.map +1 -1
  118. package/dist/utils/bashHistory.js +21 -4
  119. package/dist/utils/bashParser.d.ts +24 -0
  120. package/dist/utils/bashParser.d.ts.map +1 -0
  121. package/dist/utils/bashParser.js +413 -0
  122. package/dist/utils/builtinSubagents.d.ts +7 -0
  123. package/dist/utils/builtinSubagents.d.ts.map +1 -0
  124. package/dist/utils/builtinSubagents.js +65 -0
  125. package/dist/utils/cacheControlUtils.d.ts +8 -33
  126. package/dist/utils/cacheControlUtils.d.ts.map +1 -1
  127. package/dist/utils/cacheControlUtils.js +83 -126
  128. package/dist/utils/constants.d.ts +0 -12
  129. package/dist/utils/constants.d.ts.map +1 -1
  130. package/dist/utils/constants.js +1 -13
  131. package/dist/utils/convertMessagesForAPI.d.ts +2 -1
  132. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  133. package/dist/utils/convertMessagesForAPI.js +33 -14
  134. package/dist/utils/fileSearch.d.ts +14 -0
  135. package/dist/utils/fileSearch.d.ts.map +1 -0
  136. package/dist/utils/fileSearch.js +88 -0
  137. package/dist/utils/fileUtils.d.ts +14 -2
  138. package/dist/utils/fileUtils.d.ts.map +1 -1
  139. package/dist/utils/fileUtils.js +101 -17
  140. package/dist/utils/globalLogger.d.ts +0 -14
  141. package/dist/utils/globalLogger.d.ts.map +1 -1
  142. package/dist/utils/globalLogger.js +0 -16
  143. package/dist/utils/markdownParser.d.ts.map +1 -1
  144. package/dist/utils/markdownParser.js +1 -17
  145. package/dist/utils/messageOperations.d.ts +1 -11
  146. package/dist/utils/messageOperations.d.ts.map +1 -1
  147. package/dist/utils/messageOperations.js +7 -24
  148. package/dist/utils/pathEncoder.d.ts +4 -0
  149. package/dist/utils/pathEncoder.d.ts.map +1 -1
  150. package/dist/utils/pathEncoder.js +16 -9
  151. package/dist/utils/pathSafety.d.ts +10 -0
  152. package/dist/utils/pathSafety.d.ts.map +1 -0
  153. package/dist/utils/pathSafety.js +23 -0
  154. package/dist/utils/subagentParser.d.ts +2 -2
  155. package/dist/utils/subagentParser.d.ts.map +1 -1
  156. package/dist/utils/subagentParser.js +10 -7
  157. package/package.json +9 -9
  158. package/src/agent.ts +475 -216
  159. package/src/index.ts +3 -0
  160. package/src/managers/aiManager.ts +107 -111
  161. package/src/managers/backgroundBashManager.ts +4 -3
  162. package/src/managers/hookManager.ts +44 -39
  163. package/src/managers/liveConfigManager.ts +524 -138
  164. package/src/managers/lspManager.ts +434 -0
  165. package/src/managers/messageManager.ts +73 -103
  166. package/src/managers/permissionManager.ts +480 -0
  167. package/src/managers/skillManager.ts +3 -1
  168. package/src/managers/slashCommandManager.ts +1 -2
  169. package/src/managers/subagentManager.ts +116 -159
  170. package/src/managers/toolManager.ts +95 -3
  171. package/src/services/aiService.ts +207 -26
  172. package/src/services/configurationService.ts +762 -0
  173. package/src/services/fileWatcher.ts +5 -6
  174. package/src/services/hook.ts +50 -631
  175. package/src/services/jsonlHandler.ts +84 -100
  176. package/src/services/memory.ts +2 -59
  177. package/src/services/session.ts +338 -213
  178. package/src/tools/bashTool.ts +126 -13
  179. package/src/tools/deleteFileTool.ts +36 -0
  180. package/src/tools/editTool.ts +41 -7
  181. package/src/tools/lspTool.ts +760 -0
  182. package/src/tools/multiEditTool.ts +37 -8
  183. package/src/tools/readTool.ts +125 -2
  184. package/src/tools/skillTool.ts +2 -2
  185. package/src/tools/todoWriteTool.ts +33 -1
  186. package/src/tools/types.ts +15 -9
  187. package/src/tools/writeTool.ts +36 -10
  188. package/src/types/commands.ts +0 -1
  189. package/src/types/config.ts +5 -0
  190. package/src/types/configuration.ts +73 -0
  191. package/src/types/core.ts +11 -0
  192. package/src/types/environment.ts +44 -0
  193. package/src/types/fileSearch.ts +4 -0
  194. package/src/types/hooks.ts +14 -11
  195. package/src/types/index.ts +5 -0
  196. package/src/types/lsp.ts +96 -0
  197. package/src/types/messaging.ts +8 -13
  198. package/src/types/permissions.ts +52 -0
  199. package/src/types/session.ts +3 -8
  200. package/src/types/skills.ts +1 -0
  201. package/src/types/tools.ts +38 -0
  202. package/src/utils/abortUtils.ts +118 -0
  203. package/src/utils/bashHistory.ts +28 -4
  204. package/src/utils/bashParser.ts +444 -0
  205. package/src/utils/builtinSubagents.ts +71 -0
  206. package/src/utils/cacheControlUtils.ts +106 -171
  207. package/src/utils/constants.ts +1 -16
  208. package/src/utils/convertMessagesForAPI.ts +38 -14
  209. package/src/utils/fileSearch.ts +107 -0
  210. package/src/utils/fileUtils.ts +114 -19
  211. package/src/utils/globalLogger.ts +0 -17
  212. package/src/utils/markdownParser.ts +1 -19
  213. package/src/utils/messageOperations.ts +7 -35
  214. package/src/utils/pathEncoder.ts +24 -9
  215. package/src/utils/pathSafety.ts +26 -0
  216. package/src/utils/subagentParser.ts +11 -8
  217. package/dist/constants/events.d.ts +0 -28
  218. package/dist/constants/events.d.ts.map +0 -1
  219. package/dist/constants/events.js +0 -27
  220. package/dist/services/configurationWatcher.d.ts +0 -120
  221. package/dist/services/configurationWatcher.d.ts.map +0 -1
  222. package/dist/services/configurationWatcher.js +0 -439
  223. package/dist/services/memoryStore.d.ts +0 -81
  224. package/dist/services/memoryStore.d.ts.map +0 -1
  225. package/dist/services/memoryStore.js +0 -200
  226. package/dist/types/memoryStore.d.ts +0 -82
  227. package/dist/types/memoryStore.d.ts.map +0 -1
  228. package/dist/types/memoryStore.js +0 -7
  229. package/dist/utils/configResolver.d.ts +0 -65
  230. package/dist/utils/configResolver.d.ts.map +0 -1
  231. package/dist/utils/configResolver.js +0 -210
  232. package/src/constants/events.ts +0 -38
  233. package/src/services/configurationWatcher.ts +0 -622
  234. package/src/services/memoryStore.ts +0 -279
  235. package/src/types/memoryStore.ts +0 -94
  236. package/src/utils/configResolver.ts +0 -302
@@ -5,17 +5,10 @@
5
5
  * to optimize token usage and reduce costs. Cache control is only applied to Claude
6
6
  * models and preserves backward compatibility with existing message formats.
7
7
  */
8
+ import { logger } from "./globalLogger.js";
8
9
  // ============================================================================
9
10
  // Default Configuration
10
11
  // ============================================================================
11
- /**
12
- * Default cache control configuration
13
- */
14
- export const DEFAULT_CACHE_CONTROL_CONFIG = {
15
- cacheSystemMessage: true,
16
- cacheUserMessageCount: 2,
17
- cacheLastTool: true,
18
- };
19
12
  // ============================================================================
20
13
  // Utility Functions (Basic Structure - to be implemented)
21
14
  // ============================================================================
@@ -48,6 +41,24 @@ export function isValidCacheControl(control) {
48
41
  "type" in control &&
49
42
  control.type === "ephemeral");
50
43
  }
44
+ /**
45
+ * Adds cache control to the last tool call in an array
46
+ * @param toolCalls - Array of tool calls
47
+ * @returns Tool calls array with cache control on the last tool call
48
+ */
49
+ function addCacheControlToLastToolCall(toolCalls) {
50
+ if (!toolCalls || toolCalls.length === 0) {
51
+ return toolCalls;
52
+ }
53
+ const result = [...toolCalls];
54
+ const lastIndex = result.length - 1;
55
+ // Add cache control to the last tool call
56
+ result[lastIndex] = {
57
+ ...result[lastIndex],
58
+ cache_control: { type: "ephemeral" },
59
+ };
60
+ return result;
61
+ }
51
62
  /**
52
63
  * Adds cache control markers to message content
53
64
  * @param content - Original content (string or structured)
@@ -66,7 +77,7 @@ export function addCacheControlToContent(content, shouldCache) {
66
77
  }
67
78
  // Validate array input
68
79
  if (!Array.isArray(content)) {
69
- console.warn("Invalid content type for cache control transformation:", typeof content);
80
+ logger.warn("Invalid content type for cache control transformation:", typeof content);
70
81
  return [];
71
82
  }
72
83
  // Filter and convert only text parts with validation
@@ -92,7 +103,7 @@ export function addCacheControlToContent(content, shouldCache) {
92
103
  }
93
104
  // Validate array input
94
105
  if (!Array.isArray(content)) {
95
- console.warn("Invalid content type for cache control transformation:", typeof content);
106
+ logger.warn("Invalid content type for cache control transformation:", typeof content);
96
107
  return [];
97
108
  }
98
109
  // Handle structured content - preserve existing structure, add cache control to text parts
@@ -122,17 +133,17 @@ export function addCacheControlToLastTool(tools) {
122
133
  // Validate tools structure
123
134
  const validTools = tools.filter((tool) => {
124
135
  if (!tool || typeof tool !== "object") {
125
- console.warn("Invalid tool structure detected, skipping:", tool);
136
+ logger.warn("Invalid tool structure detected, skipping:", tool);
126
137
  return false;
127
138
  }
128
139
  if (tool.type !== "function" || !tool.function) {
129
- console.warn("Tool is not a function type or missing function property:", tool);
140
+ logger.warn("Tool is not a function type or missing function property:", tool);
130
141
  return false;
131
142
  }
132
143
  return true;
133
144
  });
134
145
  if (validTools.length === 0) {
135
- console.warn("No valid tools found for cache control");
146
+ logger.warn("No valid tools found for cache control");
136
147
  return [];
137
148
  }
138
149
  // Create a copy of the valid tools array
@@ -148,16 +159,37 @@ export function addCacheControlToLastTool(tools) {
148
159
  return result;
149
160
  }
150
161
  /**
151
- * Transforms messages for Claude cache control
162
+ * Finds the latest message index at 20-message intervals (sliding window approach)
163
+ * @param messages - Array of chat completion messages
164
+ * @returns Index of the latest interval message (20th, 40th, 60th, etc.) or -1 if none
165
+ */
166
+ export function findIntervalMessageIndex(messages) {
167
+ if (!Array.isArray(messages) || messages.length === 0) {
168
+ return -1;
169
+ }
170
+ const interval = 20; // Hardcoded interval
171
+ const messageCount = messages.length;
172
+ // Find the largest interval that fits within the message count
173
+ // Math.floor(messageCount / interval) gives us how many complete intervals we have
174
+ // Multiply by interval to get the position of the latest interval message
175
+ const latestIntervalPosition = Math.floor(messageCount / interval) * interval;
176
+ // If no complete intervals exist, return -1
177
+ if (latestIntervalPosition === 0) {
178
+ return -1;
179
+ }
180
+ // Convert from 1-based position to 0-based index
181
+ return latestIntervalPosition - 1;
182
+ }
183
+ /**
184
+ * Transforms messages for Claude cache control with hardcoded strategy
152
185
  * @param messages - Original OpenAI message array
153
186
  * @param modelName - Model name for cache detection
154
- * @param config - Cache control configuration
155
187
  * @returns Messages with cache control markers applied
156
188
  */
157
- export function transformMessagesForClaudeCache(messages, modelName, config = DEFAULT_CACHE_CONTROL_CONFIG) {
189
+ export function transformMessagesForClaudeCache(messages, modelName) {
158
190
  // Validate inputs
159
191
  if (!messages || !Array.isArray(messages)) {
160
- console.warn("Invalid messages array provided to transformMessagesForClaudeCache");
192
+ logger.warn("Invalid messages array provided to transformMessagesForClaudeCache");
161
193
  return [];
162
194
  }
163
195
  if (messages.length === 0) {
@@ -167,40 +199,52 @@ export function transformMessagesForClaudeCache(messages, modelName, config = DE
167
199
  if (!isClaudeModel(modelName)) {
168
200
  return messages;
169
201
  }
170
- // Validate config
171
- if (!config || typeof config !== "object") {
172
- console.warn("Invalid cache control config, using defaults");
173
- config = DEFAULT_CACHE_CONTROL_CONFIG;
202
+ // Find the latest interval message index (20th, 40th, 60th, etc.)
203
+ const intervalMessageIndex = findIntervalMessageIndex(messages);
204
+ // Find last system message index
205
+ let lastSystemIndex = -1;
206
+ for (let i = messages.length - 1; i >= 0; i--) {
207
+ if (messages[i].role === "system") {
208
+ lastSystemIndex = i;
209
+ break;
210
+ }
174
211
  }
175
212
  const result = messages.map((message, index) => {
176
213
  // Validate message structure
177
214
  if (!message || typeof message !== "object" || !message.role) {
178
- console.warn("Invalid message structure at index", index, ":", message);
215
+ logger.warn("Invalid message structure at index", index, ":", message);
179
216
  return message; // Return as-is to avoid breaking the flow
180
217
  }
181
- // System message: cache if enabled in config
182
- if (message.role === "system" && config.cacheSystemMessage) {
218
+ // Last system message: always cached (hardcoded)
219
+ if (message.role === "system" && index === lastSystemIndex) {
183
220
  return {
184
221
  ...message,
185
- content: addCacheControlToContent(message.content, true),
222
+ content: addCacheControlToContent(message.content || "", true),
186
223
  };
187
224
  }
188
- // User messages: cache last N messages based on config
189
- if (message.role === "user" && config.cacheUserMessageCount > 0) {
190
- const userMessageIndices = [];
191
- messages.forEach((msg, idx) => {
192
- if (msg.role === "user") {
193
- userMessageIndices.push(idx);
194
- }
195
- });
196
- // Check if this user message is among the last N
197
- const isRecentUser = userMessageIndices
198
- .slice(-config.cacheUserMessageCount)
199
- .includes(index);
200
- if (isRecentUser) {
225
+ // Interval-based message caching: cache message at latest interval position (sliding window)
226
+ if (index === intervalMessageIndex) {
227
+ // If the message is a tool role, add cache control directly to the message
228
+ if (message.role === "tool") {
229
+ return {
230
+ ...message,
231
+ cache_control: { type: "ephemeral" },
232
+ };
233
+ }
234
+ // If the message has tool calls, cache the last tool call instead of content
235
+ else if (message.role === "assistant" &&
236
+ message.tool_calls &&
237
+ message.tool_calls.length > 0) {
238
+ return {
239
+ ...message,
240
+ tool_calls: addCacheControlToLastToolCall(message.tool_calls),
241
+ };
242
+ }
243
+ else {
244
+ // For other message types without tool calls, cache the content
201
245
  return {
202
246
  ...message,
203
- content: addCacheControlToContent(message.content, true),
247
+ content: addCacheControlToContent(message.content || "", true),
204
248
  };
205
249
  }
206
250
  }
@@ -278,90 +322,3 @@ export function isValidClaudeUsage(usage) {
278
322
  }
279
323
  return true;
280
324
  }
281
- /**
282
- * Adds cache control to the last N user messages in a conversation
283
- * This optimizes multi-turn conversations by caching recent user context
284
- *
285
- * @param messages - Array of chat completion messages
286
- * @param maxUserMessagesToCache - Maximum number of recent user messages to cache (default: 2)
287
- * @returns Modified messages array with cache control on recent user messages
288
- */
289
- export function addCacheControlToRecentUserMessages(messages, maxUserMessagesToCache = 2) {
290
- // Validate inputs
291
- if (!messages || !Array.isArray(messages)) {
292
- console.warn("Invalid messages array provided to addCacheControlToRecentUserMessages");
293
- return [];
294
- }
295
- if (messages.length === 0 || maxUserMessagesToCache <= 0) {
296
- return messages;
297
- }
298
- // Validate maxUserMessagesToCache is a reasonable number
299
- if (maxUserMessagesToCache > 100) {
300
- console.warn("maxUserMessagesToCache is unusually high:", maxUserMessagesToCache, "limiting to 100");
301
- maxUserMessagesToCache = 100;
302
- }
303
- // Find all user message indices in reverse order (most recent first)
304
- const userMessageIndices = [];
305
- for (let i = messages.length - 1; i >= 0; i--) {
306
- const message = messages[i];
307
- // Validate message structure
308
- if (!message || typeof message !== "object" || !message.role) {
309
- console.warn("Invalid message at index", i, ", skipping");
310
- continue;
311
- }
312
- if (message.role === "user") {
313
- userMessageIndices.push(i);
314
- if (userMessageIndices.length >= maxUserMessagesToCache) {
315
- break;
316
- }
317
- }
318
- }
319
- // If no user messages found, return unchanged
320
- if (userMessageIndices.length === 0) {
321
- return messages;
322
- }
323
- // Create a copy of messages and modify the identified user messages
324
- const modifiedMessages = [...messages];
325
- for (const index of userMessageIndices) {
326
- const message = modifiedMessages[index];
327
- if (message.role === "user" && message.content != null) {
328
- try {
329
- modifiedMessages[index] = {
330
- ...message,
331
- content: addCacheControlToContent(message.content, true),
332
- };
333
- }
334
- catch (error) {
335
- console.warn("Failed to add cache control to user message at index", index, ":", error);
336
- // Continue with original message if transformation fails
337
- }
338
- }
339
- }
340
- return modifiedMessages;
341
- }
342
- /**
343
- * Helper function to identify user message indices that should be cached
344
- * Used for testing and validation purposes
345
- *
346
- * @param messages - Array of chat completion messages
347
- * @param maxUserMessagesToCache - Maximum number of recent user messages to identify
348
- * @returns Array of indices for user messages that should be cached
349
- */
350
- export function findRecentUserMessageIndices(messages, maxUserMessagesToCache = 2) {
351
- if (!Array.isArray(messages) ||
352
- messages.length === 0 ||
353
- maxUserMessagesToCache <= 0) {
354
- return [];
355
- }
356
- const userMessageIndices = [];
357
- for (let i = messages.length - 1; i >= 0; i--) {
358
- if (messages[i].role === "user") {
359
- userMessageIndices.push(i);
360
- if (userMessageIndices.length >= maxUserMessagesToCache) {
361
- break;
362
- }
363
- }
364
- }
365
- // Return indices in original order (not reversed)
366
- return userMessageIndices.reverse();
367
- }
@@ -22,16 +22,4 @@ export declare const USER_MEMORY_FILE: string;
22
22
  * AI related constants
23
23
  */
24
24
  export declare const DEFAULT_TOKEN_LIMIT = 96000;
25
- /**
26
- * @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
27
- * They are maintained for backward compatibility with existing code that might still reference them,
28
- * but the actual AI services now use configuration injection.
29
- */
30
- export declare const FAST_MODEL_ID: string;
31
- /**
32
- * @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
33
- * They are maintained for backward compatibility with existing code that might still reference them,
34
- * but the actual AI services now use configuration injection.
35
- */
36
- export declare const AGENT_MODEL_ID: string;
37
25
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAmC,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAA0C,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAA8C,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAoD,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAC2B,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAmC,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAA0C,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AAEvE;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC"}
@@ -19,20 +19,8 @@ export const ERROR_LOG_DIRECTORY = path.join(DATA_DIRECTORY, "error-logs");
19
19
  /**
20
20
  * User-level memory file path
21
21
  */
22
- export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "user-memory.md");
22
+ export const USER_MEMORY_FILE = path.join(DATA_DIRECTORY, "AGENTS.md");
23
23
  /**
24
24
  * AI related constants
25
25
  */
26
26
  export const DEFAULT_TOKEN_LIMIT = 96000; // Default token limit
27
- /**
28
- * @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
29
- * They are maintained for backward compatibility with existing code that might still reference them,
30
- * but the actual AI services now use configuration injection.
31
- */
32
- export const FAST_MODEL_ID = process.env.AIGW_FAST_MODEL || "gemini-2.5-flash";
33
- /**
34
- * @deprecated These constants are now legacy. Use ModelConfig through Agent constructor instead.
35
- * They are maintained for backward compatibility with existing code that might still reference them,
36
- * but the actual AI services now use configuration injection.
37
- */
38
- export const AGENT_MODEL_ID = process.env.AIGW_MODEL || "claude-sonnet-4-20250514";
@@ -1,7 +1,8 @@
1
1
  import type { Message } from "../types/index.js";
2
2
  import { ChatCompletionMessageParam } from "openai/resources.js";
3
3
  /**
4
- * Convert message format to API call format, stopping when a compressed message is encountered
4
+ * Convert message format to API call format, stopping when a compressed message is encountered.
5
+ * Messages with no meaningful content or tool calls are filtered out.
5
6
  * @param messages Message list
6
7
  * @returns Converted API message format list
7
8
  */
@@ -1 +1 @@
1
- {"version":3,"file":"convertMessagesForAPI.d.ts","sourceRoot":"","sources":["../../src/utils/convertMessagesForAPI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIjD,OAAO,EAEL,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAwB7B;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,OAAO,EAAE,GAClB,0BAA0B,EAAE,CA+L9B"}
1
+ {"version":3,"file":"convertMessagesForAPI.d.ts","sourceRoot":"","sources":["../../src/utils/convertMessagesForAPI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIjD,OAAO,EAEL,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAwB7B;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,OAAO,EAAE,GAClB,0BAA0B,EAAE,CAsN9B"}
@@ -22,7 +22,8 @@ function safeToolArguments(args) {
22
22
  }
23
23
  }
24
24
  /**
25
- * Convert message format to API call format, stopping when a compressed message is encountered
25
+ * Convert message format to API call format, stopping when a compressed message is encountered.
26
+ * Messages with no meaningful content or tool calls are filtered out.
26
27
  * @param messages Message list
27
28
  * @returns Converted API message format list
28
29
  */
@@ -44,7 +45,7 @@ export function convertMessagesForAPI(messages) {
44
45
  }
45
46
  break;
46
47
  }
47
- // Skip empty assistant messages
48
+ // Skip empty assistant messages (no blocks or all blocks are empty)
48
49
  if (message.role === "assistant" && message.blocks.length === 0) {
49
50
  continue;
50
51
  }
@@ -101,10 +102,14 @@ export function convertMessagesForAPI(messages) {
101
102
  // Construct the content of the assistant message
102
103
  let content = "";
103
104
  let tool_calls = undefined;
104
- // Construct content from text blocks
105
- const textBlocks = message.blocks.filter((block) => block.type === "text");
105
+ // Construct content from text blocks - filter out empty content
106
+ const textBlocks = message.blocks.filter((block) => block.type === "text" &&
107
+ block.content &&
108
+ block.content.trim().length > 0);
106
109
  if (textBlocks.length > 0) {
107
- content = textBlocks.map((block) => block.content || "").join("\n");
110
+ content = textBlocks
111
+ .map((block) => (block.type === "text" ? block.content : ""))
112
+ .join("\n");
108
113
  }
109
114
  // Construct tool calls from tool blocks
110
115
  if (toolBlocks.length > 0) {
@@ -122,13 +127,15 @@ export function convertMessagesForAPI(messages) {
122
127
  tool_calls = undefined;
123
128
  }
124
129
  }
125
- // Construct assistant message - only add if there is content or tool calls
126
- if (content || tool_calls) {
130
+ // Construct assistant message - only add if there is meaningful content or tool calls
131
+ const hasContent = content && content.trim().length > 0;
132
+ const hasToolCalls = tool_calls && tool_calls.length > 0;
133
+ if (hasContent || hasToolCalls) {
127
134
  const assistantMessage = {
128
135
  role: "assistant",
129
- content,
136
+ content: hasContent ? content : undefined,
130
137
  tool_calls,
131
- ...(message.metadata ? { ...message.metadata } : {}),
138
+ ...(message.additionalFields ? { ...message.additionalFields } : {}),
132
139
  };
133
140
  recentMessages.unshift(assistantMessage);
134
141
  }
@@ -137,8 +144,10 @@ export function convertMessagesForAPI(messages) {
137
144
  // User messages converted to standard format
138
145
  const contentParts = [];
139
146
  message.blocks.forEach((block) => {
140
- // Add text content
141
- if (block.type === "text" && block.content) {
147
+ // Add text content - only if it has meaningful content
148
+ if (block.type === "text" &&
149
+ block.content &&
150
+ block.content.trim().length > 0) {
142
151
  contentParts.push({
143
152
  type: "text",
144
153
  text: block.customCommandContent || block.content,
@@ -172,11 +181,21 @@ export function convertMessagesForAPI(messages) {
172
181
  });
173
182
  }
174
183
  });
184
+ // Only add user message if there is meaningful content
175
185
  if (contentParts.length > 0) {
176
- recentMessages.unshift({
177
- role: "user",
178
- content: contentParts,
186
+ // Filter out empty text parts
187
+ const meaningfulParts = contentParts.filter((part) => {
188
+ if (part.type === "text") {
189
+ return part.text && part.text.trim().length > 0;
190
+ }
191
+ return true; // Keep image parts
179
192
  });
193
+ if (meaningfulParts.length > 0) {
194
+ recentMessages.unshift({
195
+ role: "user",
196
+ content: meaningfulParts,
197
+ });
198
+ }
180
199
  }
181
200
  }
182
201
  }
@@ -0,0 +1,14 @@
1
+ import { type Path } from "glob";
2
+ import type { FileItem } from "../types/fileSearch.js";
3
+ /**
4
+ * Convert Path objects to FileItem objects
5
+ */
6
+ export declare const convertPathsToFileItems: (paths: Path[]) => FileItem[];
7
+ /**
8
+ * Search files and directories using glob patterns
9
+ */
10
+ export declare const searchFiles: (query: string, options?: {
11
+ maxResults?: number;
12
+ workingDirectory?: string;
13
+ }) => Promise<FileItem[]>;
14
+ //# sourceMappingURL=fileSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileSearch.d.ts","sourceRoot":"","sources":["../../src/utils/fileSearch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,OAAO,IAAI,EAAE,KAAG,QAAQ,EAK/D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,MAAM,EACb,UAAU;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,KACA,OAAO,CAAC,QAAQ,EAAE,CAmFpB,CAAC"}
@@ -0,0 +1,88 @@
1
+ import { globIterate } from "glob";
2
+ import { getGlobIgnorePatterns } from "./fileFilter.js";
3
+ /**
4
+ * Convert Path objects to FileItem objects
5
+ */
6
+ export const convertPathsToFileItems = (paths) => {
7
+ return paths.map((pathObj) => ({
8
+ path: pathObj.relative(),
9
+ type: pathObj.isDirectory() ? "directory" : "file",
10
+ }));
11
+ };
12
+ /**
13
+ * Search files and directories using glob patterns
14
+ */
15
+ export const searchFiles = async (query, options) => {
16
+ const { maxResults = 10, workingDirectory = process.cwd() } = options || {};
17
+ try {
18
+ const globOptions = {
19
+ ignore: getGlobIgnorePatterns(workingDirectory),
20
+ maxDepth: 10,
21
+ nocase: true, // Case insensitive
22
+ dot: true, // Include hidden files and directories
23
+ cwd: workingDirectory, // Specify search root directory
24
+ withFileTypes: true, // Get Path objects instead of strings
25
+ };
26
+ // Build glob patterns based on query
27
+ let patterns = [];
28
+ if (!query.trim()) {
29
+ // When query is empty, show some common file types and directories
30
+ patterns = [
31
+ "**/*.{ts,tsx,js,jsx,json,py,java}", // Combine common file extensions
32
+ "*/", // First level directories
33
+ ];
34
+ }
35
+ else {
36
+ // Build multiple glob patterns to support more flexible search
37
+ patterns = [
38
+ // Match files with filenames containing query
39
+ `**/*${query}*`,
40
+ // Match files with query in path (match directory names)
41
+ `**/${query}*/**/*`,
42
+ // Match directory names containing query
43
+ `**/*${query}*/`,
44
+ // Match directories containing query in path
45
+ `**/${query}*/`,
46
+ ];
47
+ }
48
+ // Collect results until we reach maxResults
49
+ const collectedPaths = [];
50
+ const seenPaths = new Set();
51
+ // Process each pattern sequentially
52
+ for (const pattern of patterns) {
53
+ if (collectedPaths.length >= maxResults) {
54
+ break;
55
+ }
56
+ // Use globIterate to get results one by one
57
+ const iterator = globIterate(pattern, globOptions);
58
+ for await (const pathObj of iterator) {
59
+ if (collectedPaths.length >= maxResults) {
60
+ // Stop the iterator when we have enough results
61
+ break;
62
+ }
63
+ const relativePath = pathObj.relative();
64
+ if (!seenPaths.has(relativePath)) {
65
+ seenPaths.add(relativePath);
66
+ collectedPaths.push(pathObj);
67
+ }
68
+ }
69
+ }
70
+ // Sort collected paths: directories first, then files
71
+ collectedPaths.sort((a, b) => {
72
+ const aIsDir = a.isDirectory();
73
+ const bIsDir = b.isDirectory();
74
+ if (aIsDir && !bIsDir)
75
+ return -1;
76
+ if (!aIsDir && bIsDir)
77
+ return 1;
78
+ return a.relative().localeCompare(b.relative());
79
+ });
80
+ // Convert to FileItems
81
+ const fileItems = convertPathsToFileItems(collectedPaths);
82
+ return fileItems;
83
+ }
84
+ catch (error) {
85
+ console.error("Glob search error:", error);
86
+ return [];
87
+ }
88
+ };
@@ -6,10 +6,22 @@
6
6
  */
7
7
  export declare function readFirstLine(filePath: string): Promise<string>;
8
8
  /**
9
- * Reads a file from the end and returns the first non-empty line.
9
+ * Reads a file from the end and returns the last non-empty line.
10
+ *
11
+ * This version supports files that end with:
12
+ * - "\n" (Unix-style, including modern macOS)
13
+ * - "\r\n" (Windows-style)
14
+ * - "\r" (older Mac-style, HL7, etc.)
10
15
  *
11
16
  * @param {string} filePath - The path to the file.
17
+ * @param {number} [minLength=1] - Minimum length for the returned line.
12
18
  * @return {Promise<string>} - The last non-empty line of the file, or an empty string if no non-empty lines found.
13
19
  */
14
- export declare function getLastLine(filePath: string): Promise<string>;
20
+ export declare function getLastLine(filePath: string, minLength?: number): Promise<string>;
21
+ /**
22
+ * Ensures that a pattern is present in the global git ignore file.
23
+ *
24
+ * @param {string} pattern - The pattern to add to global git ignore.
25
+ */
26
+ export declare function ensureGlobalGitIgnore(pattern: string): Promise<void>;
15
27
  //# sourceMappingURL=fileUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fileUtils.d.ts","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBrE;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBnE"}
1
+ {"version":3,"file":"fileUtils.d.ts","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAI,GACZ,OAAO,CAAC,MAAM,CAAC,CA8DjB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC1E"}