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
@@ -1,439 +0,0 @@
1
- /**
2
- * Configuration Watcher Service
3
- *
4
- * Orchestrates live configuration reload functionality by coordinating file watching,
5
- * configuration validation, and error recovery. Provides automatic reload of settings.json
6
- * changes without restart.
7
- */
8
- import { EventEmitter } from "events";
9
- import { existsSync } from "fs";
10
- import { FileWatcherService } from "./fileWatcher.js";
11
- import { loadMergedWaveConfigWithFallback } from "./hook.js";
12
- import { isValidHookEvent, isValidHookEventConfig } from "../types/hooks.js";
13
- import { CONFIGURATION_EVENTS, FILE_WATCHER_EVENTS, } from "../constants/events.js";
14
- export class ConfigurationWatcher extends EventEmitter {
15
- constructor(workdir, logger) {
16
- super();
17
- this.currentConfiguration = null;
18
- this.lastValidConfiguration = null;
19
- this.isWatching = false;
20
- this.reloadInProgress = false;
21
- this.workdir = workdir;
22
- this.logger = logger;
23
- this.fileWatcher = new FileWatcherService(logger);
24
- this.setupFileWatcherEvents();
25
- }
26
- /**
27
- * Initialize configuration watching
28
- * Maps to FR-004: System MUST watch settings.json files
29
- * Supports watching multiple file paths (e.g., settings.local.json and settings.json)
30
- */
31
- async initializeWatching(userPaths, projectPaths) {
32
- try {
33
- this.logger?.info("Live Config: Initializing configuration watching...");
34
- this.userConfigPaths = userPaths;
35
- this.projectConfigPaths = projectPaths;
36
- // Load initial configuration
37
- await this.reloadConfiguration();
38
- // Start watching user configs that exist
39
- for (const userPath of userPaths) {
40
- if (existsSync(userPath)) {
41
- this.logger?.debug(`Live Config: Starting to watch user config: ${userPath}`);
42
- await this.fileWatcher.watchFile(userPath, (event) => this.handleFileChange(event, "user"));
43
- }
44
- else {
45
- this.logger?.debug(`Live Config: User config file does not exist: ${userPath}`);
46
- }
47
- }
48
- // Start watching project configs that exist
49
- if (projectPaths) {
50
- for (const projectPath of projectPaths) {
51
- if (existsSync(projectPath)) {
52
- this.logger?.debug(`Live Config: Starting to watch project config: ${projectPath}`);
53
- await this.fileWatcher.watchFile(projectPath, (event) => this.handleFileChange(event, "project"));
54
- }
55
- else {
56
- this.logger?.debug(`Live Config: Project config file does not exist: ${projectPath}`);
57
- }
58
- }
59
- }
60
- this.isWatching = true;
61
- this.logger?.info("Live Config: Configuration watching initialized successfully");
62
- }
63
- catch (error) {
64
- const errorMessage = `Failed to initialize configuration watching: ${error.message}`;
65
- this.logger?.error(`Live Config: ${errorMessage}`);
66
- throw new Error(errorMessage);
67
- }
68
- }
69
- /**
70
- * Reload configuration from files
71
- * Maps to FR-008: Continue with previous valid configuration on errors
72
- */
73
- async reloadConfiguration() {
74
- if (this.reloadInProgress) {
75
- this.logger?.debug("Live Config: Reload already in progress, skipping");
76
- return this.currentConfiguration || {};
77
- }
78
- this.reloadInProgress = true;
79
- try {
80
- this.logger?.debug("Live Config: Reloading configuration from files...");
81
- // Load merged configuration with fallback support
82
- const loadResult = loadMergedWaveConfigWithFallback(this.workdir, this.lastValidConfiguration);
83
- const newConfig = loadResult.config;
84
- const timestamp = Date.now();
85
- // Check for errors during loading
86
- if (loadResult.errors.length > 0) {
87
- const errorMessage = `Configuration load errors: ${loadResult.errors.join("; ")}`;
88
- this.logger?.error(`Live Config: ${errorMessage}`);
89
- // Emit error event
90
- this.emit(CONFIGURATION_EVENTS.CONFIGURATION_CHANGE, {
91
- type: "settings_changed",
92
- path: this.getFirstExistingProjectPath() ||
93
- this.getFirstExistingUserPath() ||
94
- "unknown",
95
- timestamp,
96
- changes: { added: [], modified: [], removed: [] },
97
- isValid: false,
98
- errorMessage,
99
- });
100
- // Use fallback configuration if available
101
- if (loadResult.usedFallback && this.lastValidConfiguration) {
102
- this.logger?.warn("Live Config: Using previous valid configuration due to load errors");
103
- this.currentConfiguration = this.lastValidConfiguration;
104
- return this.currentConfiguration;
105
- }
106
- else {
107
- this.logger?.warn("Live Config: No previous valid configuration available, using empty config");
108
- this.currentConfiguration = {};
109
- return this.currentConfiguration;
110
- }
111
- }
112
- // Validate new configuration if it exists
113
- if (newConfig) {
114
- const validation = this.validateConfiguration(newConfig);
115
- if (!validation.valid) {
116
- const errorMessage = `Invalid configuration: ${validation.errors.join(", ")}`;
117
- this.logger?.error(`Live Config: ${errorMessage}`);
118
- // Emit error event but continue with previous valid config
119
- this.emit(CONFIGURATION_EVENTS.CONFIGURATION_CHANGE, {
120
- type: "settings_changed",
121
- path: this.getFirstExistingProjectPath() ||
122
- this.getFirstExistingUserPath() ||
123
- "unknown",
124
- timestamp,
125
- changes: { added: [], modified: [], removed: [] },
126
- isValid: false,
127
- errorMessage,
128
- });
129
- // Use previous valid configuration for error recovery
130
- if (this.lastValidConfiguration) {
131
- this.logger?.warn("Live Config: Using previous valid configuration due to validation errors");
132
- this.currentConfiguration = this.lastValidConfiguration;
133
- return this.currentConfiguration;
134
- }
135
- else {
136
- this.logger?.warn("Live Config: No previous valid configuration available, using empty config");
137
- this.currentConfiguration = {};
138
- return this.currentConfiguration;
139
- }
140
- }
141
- }
142
- // Detect changes between old and new configuration
143
- const changes = this.detectChanges(this.currentConfiguration, newConfig);
144
- // Update current configuration
145
- this.currentConfiguration = newConfig || {};
146
- // Save as last valid configuration if it's valid and not empty
147
- if (newConfig && (newConfig.hooks || newConfig.env)) {
148
- this.lastValidConfiguration = { ...newConfig };
149
- }
150
- this.logger?.info(`Live Config: Configuration reloaded successfully with ${Object.keys(newConfig?.hooks || {}).length} event types and ${Object.keys(newConfig?.env || {}).length} environment variables`);
151
- // Emit configuration change event
152
- this.emit(CONFIGURATION_EVENTS.CONFIGURATION_CHANGE, {
153
- type: "settings_changed",
154
- path: this.getFirstExistingProjectPath() ||
155
- this.getFirstExistingUserPath() ||
156
- "merged",
157
- timestamp,
158
- changes,
159
- isValid: true,
160
- });
161
- return this.currentConfiguration;
162
- }
163
- catch (error) {
164
- const errorMessage = `Failed to reload configuration: ${error.message}`;
165
- this.logger?.error(`Live Config: ${errorMessage}`);
166
- // Use previous valid configuration for error recovery
167
- if (this.lastValidConfiguration) {
168
- this.logger?.warn("Live Config: Using previous valid configuration due to reload error");
169
- this.currentConfiguration = this.lastValidConfiguration;
170
- }
171
- else {
172
- this.logger?.warn("Live Config: No previous valid configuration available, using empty config");
173
- this.currentConfiguration = {};
174
- }
175
- // Emit error event
176
- this.emit(CONFIGURATION_EVENTS.CONFIGURATION_CHANGE, {
177
- type: "settings_changed",
178
- path: "reload-error",
179
- timestamp: Date.now(),
180
- changes: { added: [], modified: [], removed: [] },
181
- isValid: false,
182
- errorMessage,
183
- });
184
- return this.currentConfiguration;
185
- }
186
- finally {
187
- this.reloadInProgress = false;
188
- }
189
- }
190
- /**
191
- * Get current effective configuration
192
- * Maps to FR-002: Merged configuration with project precedence
193
- */
194
- getCurrentConfiguration() {
195
- return this.currentConfiguration ? { ...this.currentConfiguration } : null;
196
- }
197
- /**
198
- * Validate environment variables
199
- * Maps to FR-003: Validate env field format
200
- */
201
- validateEnvironmentVariables(env) {
202
- const errors = [];
203
- const warnings = [];
204
- if (typeof env !== "object" || env === null) {
205
- errors.push("Environment variables must be an object");
206
- return { isValid: false, errors, warnings };
207
- }
208
- if (Array.isArray(env)) {
209
- errors.push("Environment variables cannot be an array");
210
- return { isValid: false, errors, warnings };
211
- }
212
- for (const [key, value] of Object.entries(env)) {
213
- // Validate key format
214
- if (typeof key !== "string" || key.trim() === "") {
215
- errors.push(`Invalid environment variable key: '${key}' (must be non-empty string)`);
216
- continue;
217
- }
218
- // Validate key naming convention (optional warning)
219
- if (!/^[A-Z_][A-Z0-9_]*$/i.test(key)) {
220
- warnings.push(`Environment variable '${key}' doesn't follow conventional naming (A-Z, 0-9, underscore)`);
221
- }
222
- // Validate value type
223
- if (typeof value !== "string") {
224
- errors.push(`Environment variable '${key}' must have a string value (got ${typeof value})`);
225
- }
226
- }
227
- return {
228
- isValid: errors.length === 0,
229
- errors,
230
- warnings,
231
- };
232
- }
233
- /**
234
- * Stop watching and cleanup resources
235
- * Maps to cleanup requirements
236
- */
237
- async shutdown() {
238
- this.logger?.info("Live Config: Shutting down configuration watcher...");
239
- this.isWatching = false;
240
- try {
241
- await this.fileWatcher.cleanup();
242
- this.removeAllListeners();
243
- this.logger?.info("Live Config: Configuration watcher shutdown completed");
244
- }
245
- catch (error) {
246
- this.logger?.error(`Live Config: Error during shutdown: ${error.message}`);
247
- throw error;
248
- }
249
- }
250
- /**
251
- * Watch an additional file (like AGENTS.md) for changes
252
- * Maps to T033: Add AGENTS.md file watching to HookManager
253
- */
254
- async watchAdditionalFile(filePath, callback) {
255
- try {
256
- await this.fileWatcher.watchFile(filePath, callback);
257
- this.logger?.info(`Live Config: Started watching additional file: ${filePath}`);
258
- }
259
- catch (error) {
260
- this.logger?.error(`Live Config: Failed to watch additional file ${filePath}: ${error.message}`);
261
- throw error;
262
- }
263
- }
264
- /**
265
- * Stop watching an additional file
266
- */
267
- async unwatchAdditionalFile(filePath) {
268
- try {
269
- await this.fileWatcher.unwatchFile(filePath);
270
- this.logger?.info(`Live Config: Stopped watching additional file: ${filePath}`);
271
- }
272
- catch (error) {
273
- this.logger?.warn(`Live Config: Failed to stop watching file ${filePath}: ${error.message}`);
274
- }
275
- }
276
- /**
277
- * Check if watching is active
278
- */
279
- isWatchingActive() {
280
- return this.isWatching;
281
- }
282
- /**
283
- * Get watcher status for monitoring
284
- */
285
- getWatcherStatus() {
286
- const statuses = this.fileWatcher.getAllWatcherStatuses();
287
- return {
288
- isActive: this.isWatching,
289
- configurationLoaded: this.currentConfiguration !== null,
290
- hasValidConfiguration: this.lastValidConfiguration !== null,
291
- reloadInProgress: this.reloadInProgress,
292
- watchedFiles: statuses.map((s) => ({
293
- path: s.path,
294
- isActive: s.isActive,
295
- method: s.method,
296
- errorCount: s.errorCount,
297
- })),
298
- };
299
- }
300
- setupFileWatcherEvents() {
301
- this.fileWatcher.on("watcherError", (error) => {
302
- this.logger?.error(`Live Config: File watcher error: ${error.message}`);
303
- this.emit(CONFIGURATION_EVENTS.WATCHER_ERROR, error);
304
- });
305
- }
306
- async handleFileChange(event, source) {
307
- this.logger?.debug(`Live Config: File ${event.type} detected for ${source} config: ${event.path}`);
308
- try {
309
- // Handle file deletion
310
- if (event.type === FILE_WATCHER_EVENTS.DELETE) {
311
- this.logger?.info(`Live Config: ${source} config file deleted: ${event.path}`);
312
- // Reload configuration without the deleted file
313
- await this.reloadConfiguration();
314
- return;
315
- }
316
- // Handle file creation or modification
317
- if (event.type === FILE_WATCHER_EVENTS.CHANGE ||
318
- event.type === FILE_WATCHER_EVENTS.CREATE) {
319
- this.logger?.info(`Live Config: ${source} config file ${event.type}: ${event.path}`);
320
- // Add small delay to ensure file write is complete
321
- await new Promise((resolve) => setTimeout(resolve, 50));
322
- // Reload configuration
323
- await this.reloadConfiguration();
324
- }
325
- }
326
- catch (error) {
327
- this.logger?.error(`Live Config: Error handling file change for ${source} config: ${error.message}`);
328
- }
329
- }
330
- /**
331
- * Validate configuration structure and content
332
- */
333
- validateConfiguration(config) {
334
- const errors = [];
335
- if (!config || typeof config !== "object") {
336
- return { valid: false, errors: ["Configuration must be an object"] };
337
- }
338
- // Validate hooks if present
339
- if (config.hooks) {
340
- if (typeof config.hooks !== "object") {
341
- errors.push("hooks property must be an object");
342
- }
343
- else {
344
- // Validate each hook event
345
- for (const [eventName, eventConfigs] of Object.entries(config.hooks)) {
346
- // Validate event name
347
- if (!isValidHookEvent(eventName)) {
348
- errors.push(`Invalid hook event: ${eventName}`);
349
- continue;
350
- }
351
- // Validate event configurations
352
- if (!Array.isArray(eventConfigs)) {
353
- errors.push(`Hook event ${eventName} must be an array of configurations`);
354
- continue;
355
- }
356
- eventConfigs.forEach((eventConfig, index) => {
357
- if (!isValidHookEventConfig(eventConfig)) {
358
- errors.push(`Invalid hook event configuration at ${eventName}[${index}]`);
359
- }
360
- });
361
- }
362
- }
363
- }
364
- // Validate environment variables if present
365
- if (config.env) {
366
- if (typeof config.env !== "object" || Array.isArray(config.env)) {
367
- errors.push("env property must be an object");
368
- }
369
- else {
370
- for (const [key, value] of Object.entries(config.env)) {
371
- if (typeof key !== "string" || key.trim() === "") {
372
- errors.push(`Invalid environment variable key: ${key}`);
373
- }
374
- if (typeof value !== "string") {
375
- errors.push(`Environment variable ${key} must have a string value`);
376
- }
377
- }
378
- }
379
- }
380
- return {
381
- valid: errors.length === 0,
382
- errors,
383
- };
384
- }
385
- detectChanges(oldConfig, newConfig) {
386
- const added = [];
387
- const modified = [];
388
- const removed = [];
389
- // Handle environment variables changes
390
- const oldEnv = oldConfig?.env || {};
391
- const newEnv = newConfig?.env || {};
392
- for (const key of Object.keys(newEnv)) {
393
- if (!(key in oldEnv)) {
394
- added.push(`env.${key}`);
395
- }
396
- else if (oldEnv[key] !== newEnv[key]) {
397
- modified.push(`env.${key}`);
398
- }
399
- }
400
- for (const key of Object.keys(oldEnv)) {
401
- if (!(key in newEnv)) {
402
- removed.push(`env.${key}`);
403
- }
404
- }
405
- // Handle hooks changes (simplified)
406
- const oldHooks = oldConfig?.hooks || {};
407
- const newHooks = newConfig?.hooks || {};
408
- for (const event of Object.keys(newHooks)) {
409
- if (isValidHookEvent(event)) {
410
- if (!(event in oldHooks)) {
411
- added.push(`hooks.${event}`);
412
- }
413
- else if (JSON.stringify(oldHooks[event]) !== JSON.stringify(newHooks[event])) {
414
- modified.push(`hooks.${event}`);
415
- }
416
- }
417
- }
418
- for (const event of Object.keys(oldHooks)) {
419
- if (isValidHookEvent(event) && !(event in newHooks)) {
420
- removed.push(`hooks.${event}`);
421
- }
422
- }
423
- return { added, modified, removed };
424
- }
425
- /**
426
- * Get the first existing user config path for error reporting
427
- */
428
- getFirstExistingUserPath() {
429
- return (this.userConfigPaths?.find((path) => existsSync(path)) ||
430
- this.userConfigPaths?.[0]);
431
- }
432
- /**
433
- * Get the first existing project config path for error reporting
434
- */
435
- getFirstExistingProjectPath() {
436
- return (this.projectConfigPaths?.find((path) => existsSync(path)) ||
437
- this.projectConfigPaths?.[0]);
438
- }
439
- }
@@ -1,81 +0,0 @@
1
- /**
2
- * Memory Store Service
3
- *
4
- * Provides in-memory storage for file content with automatic updates.
5
- * Optimizes performance by keeping frequently accessed files in memory.
6
- */
7
- import { EventEmitter } from "events";
8
- import type { Logger } from "../types/index.js";
9
- export interface MemoryStoreEntry {
10
- content: string;
11
- path: string;
12
- lastModified: number;
13
- isLoaded: boolean;
14
- }
15
- export interface MemoryStoreStats {
16
- contentSize: number;
17
- lastUpdated: number;
18
- updateCount: number;
19
- isLoaded: boolean;
20
- }
21
- export interface MemoryUpdateEvent {
22
- path: string;
23
- reason: "file_change" | "initial_load" | "manual_reload";
24
- timestamp: number;
25
- previousSize?: number;
26
- newSize: number;
27
- }
28
- export declare class MemoryStoreService extends EventEmitter {
29
- private store;
30
- private updateCounts;
31
- private logger?;
32
- constructor(logger?: Logger);
33
- /**
34
- * Get content from memory store (loads from file if not loaded)
35
- * Maps to FR-006: Keep AGENTS.md content in memory to avoid repeated reads
36
- */
37
- getContent(path: string): Promise<string>;
38
- /**
39
- * Update memory content from file
40
- * Maps to FR-007: Update memory content when file changes
41
- */
42
- updateContent(path: string): Promise<void>;
43
- /**
44
- * Get memory store statistics
45
- * For monitoring and debugging
46
- */
47
- getStats(path?: string): MemoryStoreStats;
48
- /**
49
- * Check if content is loaded in memory
50
- * For status checking
51
- */
52
- isLoaded(path: string): boolean;
53
- /**
54
- * Manually reload content from file
55
- * For force refresh scenarios
56
- */
57
- reloadContent(path: string): Promise<void>;
58
- /**
59
- * Remove content from memory store
60
- * For cleanup when file is deleted
61
- */
62
- removeContent(path: string): boolean;
63
- /**
64
- * Clear all content from memory store
65
- * For cleanup and testing
66
- */
67
- clear(): void;
68
- /**
69
- * Get all stored paths
70
- * For monitoring and debugging
71
- */
72
- getStoredPaths(): string[];
73
- /**
74
- * Check if file exists and is accessible
75
- */
76
- fileExists(path: string): Promise<boolean>;
77
- private loadFromFile;
78
- private incrementUpdateCount;
79
- private emitUpdateEvent;
80
- }
81
- //# sourceMappingURL=memoryStore.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memoryStore.d.ts","sourceRoot":"","sources":["../../src/services/memoryStore.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,GAAG,cAAc,GAAG,eAAe,CAAC;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,MAAM,CAAC,EAAE,MAAM;IAK3B;;;OAGG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY/C;;;OAGG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhD;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB;IAkCzC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAK/B;;;OAGG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhD;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAWpC;;;OAGG;IACH,KAAK,IAAI,IAAI;IAYb;;;OAGG;IACH,cAAc,IAAI,MAAM,EAAE;IAI1B;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YASlC,YAAY;IA2E1B,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,eAAe;CAmBxB"}