wave-agent-sdk 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/dist/agent.d.ts +32 -20
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +202 -20
  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 +243 -128
  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 +9 -4
  16. package/dist/managers/hookManager.d.ts.map +1 -1
  17. package/dist/managers/hookManager.js +62 -30
  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 +38 -13
  22. package/dist/managers/messageManager.d.ts.map +1 -1
  23. package/dist/managers/messageManager.js +163 -30
  24. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  25. package/dist/managers/slashCommandManager.js +4 -1
  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 +189 -18
  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/writeTool.d.ts.map +1 -1
  64. package/dist/tools/writeTool.js +5 -6
  65. package/dist/types/commands.d.ts +4 -0
  66. package/dist/types/commands.d.ts.map +1 -1
  67. package/dist/types/core.d.ts +35 -0
  68. package/dist/types/core.d.ts.map +1 -1
  69. package/dist/types/environment.d.ts +42 -0
  70. package/dist/types/environment.d.ts.map +1 -0
  71. package/dist/types/environment.js +21 -0
  72. package/dist/types/hooks.d.ts +8 -2
  73. package/dist/types/hooks.d.ts.map +1 -1
  74. package/dist/types/hooks.js +8 -2
  75. package/dist/types/index.d.ts +2 -0
  76. package/dist/types/index.d.ts.map +1 -1
  77. package/dist/types/index.js +2 -0
  78. package/dist/types/memoryStore.d.ts +82 -0
  79. package/dist/types/memoryStore.d.ts.map +1 -0
  80. package/dist/types/memoryStore.js +7 -0
  81. package/dist/types/messaging.d.ts +14 -2
  82. package/dist/types/messaging.d.ts.map +1 -1
  83. package/dist/types/session.d.ts +20 -0
  84. package/dist/types/session.d.ts.map +1 -0
  85. package/dist/types/session.js +7 -0
  86. package/dist/utils/bashHistory.d.ts.map +1 -1
  87. package/dist/utils/bashHistory.js +27 -26
  88. package/dist/utils/cacheControlUtils.d.ts +121 -0
  89. package/dist/utils/cacheControlUtils.d.ts.map +1 -0
  90. package/dist/utils/cacheControlUtils.js +367 -0
  91. package/dist/utils/commandPathResolver.d.ts +52 -0
  92. package/dist/utils/commandPathResolver.d.ts.map +1 -0
  93. package/dist/utils/commandPathResolver.js +145 -0
  94. package/dist/utils/configPaths.d.ts +85 -0
  95. package/dist/utils/configPaths.d.ts.map +1 -0
  96. package/dist/utils/configPaths.js +121 -0
  97. package/dist/utils/configResolver.d.ts +37 -10
  98. package/dist/utils/configResolver.d.ts.map +1 -1
  99. package/dist/utils/configResolver.js +127 -23
  100. package/dist/utils/constants.d.ts +1 -1
  101. package/dist/utils/constants.js +1 -1
  102. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  103. package/dist/utils/convertMessagesForAPI.js +7 -5
  104. package/dist/utils/customCommands.d.ts.map +1 -1
  105. package/dist/utils/customCommands.js +66 -21
  106. package/dist/utils/fileUtils.d.ts +15 -0
  107. package/dist/utils/fileUtils.d.ts.map +1 -0
  108. package/dist/utils/fileUtils.js +61 -0
  109. package/dist/utils/globalLogger.d.ts +102 -0
  110. package/dist/utils/globalLogger.d.ts.map +1 -0
  111. package/dist/utils/globalLogger.js +136 -0
  112. package/dist/utils/mcpUtils.d.ts.map +1 -1
  113. package/dist/utils/mcpUtils.js +25 -3
  114. package/dist/utils/messageOperations.d.ts +20 -8
  115. package/dist/utils/messageOperations.d.ts.map +1 -1
  116. package/dist/utils/messageOperations.js +25 -16
  117. package/dist/utils/pathEncoder.d.ts +104 -0
  118. package/dist/utils/pathEncoder.d.ts.map +1 -0
  119. package/dist/utils/pathEncoder.js +272 -0
  120. package/dist/utils/subagentParser.d.ts.map +1 -1
  121. package/dist/utils/subagentParser.js +2 -1
  122. package/dist/utils/tokenCalculation.d.ts +26 -0
  123. package/dist/utils/tokenCalculation.d.ts.map +1 -0
  124. package/dist/utils/tokenCalculation.js +36 -0
  125. package/package.json +6 -3
  126. package/src/agent.ts +298 -34
  127. package/src/constants/events.ts +38 -0
  128. package/src/index.ts +2 -0
  129. package/src/managers/aiManager.ts +323 -170
  130. package/src/managers/backgroundBashManager.ts +7 -6
  131. package/src/managers/hookManager.ts +83 -40
  132. package/src/managers/liveConfigManager.ts +248 -0
  133. package/src/managers/messageManager.ts +230 -63
  134. package/src/managers/slashCommandManager.ts +4 -1
  135. package/src/managers/subagentManager.ts +283 -21
  136. package/src/services/aiService.ts +474 -83
  137. package/src/services/configurationWatcher.ts +622 -0
  138. package/src/services/fileWatcher.ts +301 -0
  139. package/src/services/hook.ts +538 -47
  140. package/src/services/jsonlHandler.ts +319 -0
  141. package/src/services/memory.ts +92 -12
  142. package/src/services/memoryStore.ts +279 -0
  143. package/src/services/session.ts +381 -157
  144. package/src/tools/bashTool.ts +5 -4
  145. package/src/tools/deleteFileTool.ts +2 -1
  146. package/src/tools/editTool.ts +3 -2
  147. package/src/tools/multiEditTool.ts +4 -3
  148. package/src/tools/readTool.ts +2 -1
  149. package/src/tools/writeTool.ts +7 -6
  150. package/src/types/commands.ts +6 -0
  151. package/src/types/core.ts +44 -0
  152. package/src/types/environment.ts +60 -0
  153. package/src/types/hooks.ts +21 -8
  154. package/src/types/index.ts +2 -0
  155. package/src/types/memoryStore.ts +94 -0
  156. package/src/types/messaging.ts +14 -2
  157. package/src/types/session.ts +25 -0
  158. package/src/utils/bashHistory.ts +27 -27
  159. package/src/utils/cacheControlUtils.ts +540 -0
  160. package/src/utils/commandPathResolver.ts +189 -0
  161. package/src/utils/configPaths.ts +163 -0
  162. package/src/utils/configResolver.ts +182 -22
  163. package/src/utils/constants.ts +1 -1
  164. package/src/utils/convertMessagesForAPI.ts +7 -5
  165. package/src/utils/customCommands.ts +90 -22
  166. package/src/utils/fileUtils.ts +65 -0
  167. package/src/utils/globalLogger.ts +145 -0
  168. package/src/utils/mcpUtils.ts +34 -3
  169. package/src/utils/messageOperations.ts +42 -20
  170. package/src/utils/pathEncoder.ts +379 -0
  171. package/src/utils/subagentParser.ts +2 -1
  172. package/src/utils/tokenCalculation.ts +43 -0
@@ -1,4 +1,5 @@
1
1
  import { spawn } from "child_process";
2
+ import { logger } from "../utils/globalLogger.js";
2
3
  import type { BackgroundShell } from "../types/index.js";
3
4
 
4
5
  export interface BackgroundBashManagerCallbacks {
@@ -127,8 +128,8 @@ export class BackgroundBashManager {
127
128
  .split("\n")
128
129
  .filter((line) => regex.test(line))
129
130
  .join("\n");
130
- } catch {
131
- // logger.warn(`Invalid filter regex: ${filter}`, error);
131
+ } catch (error) {
132
+ logger.warn(`Invalid filter regex: ${filter}`, error);
132
133
  }
133
134
  }
134
135
 
@@ -159,8 +160,8 @@ export class BackgroundBashManager {
159
160
  ) {
160
161
  try {
161
162
  process.kill(-shell.process.pid, "SIGKILL");
162
- } catch {
163
- // logger.error("Failed to force kill process:", error);
163
+ } catch (error) {
164
+ logger.error("Failed to force kill process:", error);
164
165
  }
165
166
  }
166
167
  }, 1000);
@@ -183,8 +184,8 @@ export class BackgroundBashManager {
183
184
  shell.runtime = Date.now() - shell.startTime;
184
185
  this.notifyShellsChange();
185
186
  return true;
186
- } catch {
187
- // logger.error("Failed to kill child process:", directKillError);
187
+ } catch (directKillError) {
188
+ logger.error("Failed to kill child process:", directKillError);
188
189
  return false;
189
190
  }
190
191
  }
@@ -8,7 +8,7 @@
8
8
  import {
9
9
  type HookEvent,
10
10
  type HookEventConfig,
11
- type HookConfiguration,
11
+ type WaveConfiguration,
12
12
  type PartialHookConfiguration,
13
13
  type HookExecutionContext,
14
14
  type ExtendedHookExecutionContext,
@@ -22,7 +22,7 @@ import { HookMatcher } from "../utils/hookMatcher.js";
22
22
  import {
23
23
  executeCommand,
24
24
  isCommandSafe,
25
- loadMergedHooksConfig,
25
+ loadMergedWaveConfig,
26
26
  } from "../services/hook.js";
27
27
  import type { Logger } from "../types/index.js";
28
28
  import { MessageSource } from "../types/index.js";
@@ -30,6 +30,7 @@ import type { MessageManager } from "./messageManager.js";
30
30
 
31
31
  export class HookManager {
32
32
  private configuration: PartialHookConfiguration | undefined;
33
+ private environmentVars: Record<string, string> | undefined;
33
34
  private readonly matcher: HookMatcher;
34
35
  private readonly logger?: Logger;
35
36
  private readonly workdir: string;
@@ -78,18 +79,25 @@ export class HookManager {
78
79
 
79
80
  /**
80
81
  * Load configuration from filesystem settings
81
- * Automatically loads and merges user and project hooks configuration
82
+ * Automatically loads and merges user and project Wave configuration (hooks + environment)
82
83
  */
83
84
  loadConfigurationFromSettings(): void {
84
85
  try {
85
86
  this.logger?.debug(`[HookManager] Loading configuration...`);
86
- const mergedConfig = loadMergedHooksConfig(this.workdir);
87
- this.logger?.debug(`[HookManager] Merged config result:`, mergedConfig);
88
- this.configuration = mergedConfig || undefined;
87
+ const mergedWaveConfig = loadMergedWaveConfig(this.workdir);
88
+ this.logger?.debug(
89
+ `[HookManager] Merged config result:`,
90
+ mergedWaveConfig,
91
+ );
92
+
93
+ this.configuration = mergedWaveConfig?.hooks || undefined;
94
+ this.environmentVars = mergedWaveConfig?.env || undefined;
89
95
 
90
96
  // Validate the loaded configuration if it exists
91
- if (mergedConfig) {
92
- const validation = this.validatePartialConfiguration(mergedConfig);
97
+ if (mergedWaveConfig?.hooks) {
98
+ const validation = this.validatePartialConfiguration(
99
+ mergedWaveConfig.hooks,
100
+ );
93
101
  if (!validation.valid) {
94
102
  throw new HookConfigurationError(
95
103
  "filesystem settings",
@@ -99,11 +107,12 @@ export class HookManager {
99
107
  }
100
108
 
101
109
  this.logger?.debug(
102
- `[HookManager] Configuration loaded successfully with ${Object.keys(mergedConfig || {}).length} event types`,
110
+ `[HookManager] Configuration loaded successfully with ${Object.keys(mergedWaveConfig?.hooks || {}).length} event types and ${Object.keys(this.environmentVars || {}).length} environment variables`,
103
111
  );
104
112
  } catch (error) {
105
113
  // If loading fails, start with undefined configuration (no hooks)
106
114
  this.configuration = undefined;
115
+ this.environmentVars = undefined;
107
116
 
108
117
  // Re-throw configuration errors, but handle file system errors gracefully
109
118
  if (error instanceof HookConfigurationError) {
@@ -194,7 +203,12 @@ export class HookManager {
194
203
  `[HookManager] Executing command ${commandIndex + 1}/${config.hooks.length} in configuration ${configIndex + 1}`,
195
204
  );
196
205
 
197
- const result = await executeCommand(hookCommand.command, context);
206
+ const result = await executeCommand(
207
+ hookCommand.command,
208
+ context,
209
+ undefined,
210
+ this.environmentVars,
211
+ );
198
212
  results.push(result);
199
213
 
200
214
  // Report individual command result
@@ -203,7 +217,7 @@ export class HookManager {
203
217
  `[HookManager] Command ${commandIndex + 1} completed successfully in ${result.duration}ms`,
204
218
  );
205
219
  } else {
206
- this.logger?.warn(
220
+ this.logger?.debug(
207
221
  `[HookManager] Command ${commandIndex + 1} failed in ${result.duration}ms (exit code: ${result.exitCode}, timed out: ${result.timedOut})`,
208
222
  );
209
223
  }
@@ -344,6 +358,7 @@ export class HookManager {
344
358
  result: errorMessage,
345
359
  success: false,
346
360
  error: "Hook blocked tool execution",
361
+ stage: "end", // Hook blocking results in end stage with error
347
362
  });
348
363
  }
349
364
  return { shouldBlock: true };
@@ -395,46 +410,62 @@ export class HookManager {
395
410
  }
396
411
 
397
412
  /**
398
- * Validate hook configuration structure and content
413
+ * Validate Wave configuration structure and content
399
414
  */
400
- validateConfiguration(config: HookConfiguration): ValidationResult {
415
+ validateConfiguration(config: WaveConfiguration): ValidationResult {
401
416
  const errors: string[] = [];
402
417
 
403
418
  if (!config || typeof config !== "object") {
404
419
  return { valid: false, errors: ["Configuration must be an object"] };
405
420
  }
406
421
 
407
- if (!config.hooks || typeof config.hooks !== "object") {
408
- return {
409
- valid: false,
410
- errors: ["Configuration must have a hooks property"],
411
- };
412
- }
422
+ // Validate hooks if present
423
+ if (config.hooks) {
424
+ if (typeof config.hooks !== "object") {
425
+ errors.push("hooks property must be an object");
426
+ } else {
427
+ // Validate each hook event
428
+ for (const [eventName, eventConfigs] of Object.entries(config.hooks)) {
429
+ // Validate event name
430
+ if (!isValidHookEvent(eventName)) {
431
+ errors.push(`Invalid hook event: ${eventName}`);
432
+ continue;
433
+ }
413
434
 
414
- // Validate each hook event
415
- for (const [eventName, eventConfigs] of Object.entries(config.hooks)) {
416
- // Validate event name
417
- if (!isValidHookEvent(eventName)) {
418
- errors.push(`Invalid hook event: ${eventName}`);
419
- continue;
420
- }
435
+ // Validate event configurations
436
+ if (!Array.isArray(eventConfigs)) {
437
+ errors.push(
438
+ `Hook event ${eventName} must be an array of configurations`,
439
+ );
440
+ continue;
441
+ }
421
442
 
422
- // Validate event configurations
423
- if (!Array.isArray(eventConfigs)) {
424
- errors.push(
425
- `Hook event ${eventName} must be an array of configurations`,
426
- );
427
- continue;
443
+ eventConfigs.forEach((eventConfig, index) => {
444
+ const configErrors = this.validateEventConfig(
445
+ eventName as HookEvent,
446
+ eventConfig,
447
+ index,
448
+ );
449
+ errors.push(...configErrors);
450
+ });
451
+ }
428
452
  }
453
+ }
429
454
 
430
- eventConfigs.forEach((eventConfig, index) => {
431
- const configErrors = this.validateEventConfig(
432
- eventName as HookEvent,
433
- eventConfig,
434
- index,
435
- );
436
- errors.push(...configErrors);
437
- });
455
+ // Validate environment variables if present
456
+ if (config.env) {
457
+ if (typeof config.env !== "object" || Array.isArray(config.env)) {
458
+ errors.push("env property must be an object");
459
+ } else {
460
+ for (const [key, value] of Object.entries(config.env)) {
461
+ if (typeof key !== "string" || key.trim() === "") {
462
+ errors.push(`Invalid environment variable key: ${key}`);
463
+ }
464
+ if (typeof value !== "string") {
465
+ errors.push(`Environment variable ${key} must have a string value`);
466
+ }
467
+ }
468
+ }
438
469
  }
439
470
 
440
471
  return {
@@ -497,6 +528,16 @@ export class HookManager {
497
528
  return JSON.parse(JSON.stringify(this.configuration));
498
529
  }
499
530
 
531
+ /**
532
+ * Get current environment variables
533
+ */
534
+ getEnvironmentVars(): Record<string, string> | undefined {
535
+ if (!this.environmentVars) return undefined;
536
+
537
+ // Deep clone to prevent external modification
538
+ return JSON.parse(JSON.stringify(this.environmentVars));
539
+ }
540
+
500
541
  /**
501
542
  * Clear current configuration
502
543
  */
@@ -697,6 +738,7 @@ export class HookManager {
697
738
  PostToolUse: 0,
698
739
  UserPromptSubmit: 0,
699
740
  Stop: 0,
741
+ SubagentStop: 0,
700
742
  },
701
743
  };
702
744
  }
@@ -706,6 +748,7 @@ export class HookManager {
706
748
  PostToolUse: 0,
707
749
  UserPromptSubmit: 0,
708
750
  Stop: 0,
751
+ SubagentStop: 0,
709
752
  };
710
753
 
711
754
  let totalConfigs = 0;
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Live Configuration Manager
3
+ *
4
+ * Orchestrates live configuration reload functionality including:
5
+ * - Hook configuration watching and reloading
6
+ * - Memory store management for AGENTS.md files
7
+ * - Coordination between file watchers and configuration updates
8
+ */
9
+
10
+ import type { Logger } from "../types/index.js";
11
+ import {
12
+ ConfigurationWatcher,
13
+ type ConfigurationChangeEvent,
14
+ } from "../services/configurationWatcher.js";
15
+
16
+ import { type FileWatchEvent } from "../services/fileWatcher.js";
17
+ import { configResolver } from "../utils/configResolver.js";
18
+ import { join } from "path";
19
+ import {
20
+ getUserConfigPaths,
21
+ getProjectConfigPaths,
22
+ } from "../utils/configPaths.js";
23
+ import { CONFIGURATION_EVENTS } from "../constants/events.js";
24
+
25
+ export interface LiveConfigManagerOptions {
26
+ workdir: string;
27
+ logger?: Logger;
28
+ onConfigurationChanged?: () => void; // Callback for when configuration changes
29
+ onMemoryStoreFileChanged?: (
30
+ filePath: string,
31
+ changeType: "add" | "change" | "unlink",
32
+ ) => Promise<void>; // Callback for memory store file changes
33
+ }
34
+
35
+ export class LiveConfigManager {
36
+ private readonly workdir: string;
37
+ private readonly logger?: Logger;
38
+ private readonly onConfigurationChanged?: () => void;
39
+ private readonly onMemoryStoreFileChanged?: (
40
+ filePath: string,
41
+ changeType: "add" | "change" | "unlink",
42
+ ) => Promise<void>;
43
+ private configurationWatcher?: ConfigurationWatcher;
44
+ private isInitialized: boolean = false;
45
+
46
+ constructor(options: LiveConfigManagerOptions) {
47
+ this.workdir = options.workdir;
48
+ this.logger = options.logger;
49
+ this.onConfigurationChanged = options.onConfigurationChanged;
50
+ this.onMemoryStoreFileChanged = options.onMemoryStoreFileChanged;
51
+ }
52
+
53
+ /**
54
+ * Initialize live configuration management
55
+ */
56
+ async initialize(): Promise<void> {
57
+ if (this.isInitialized) {
58
+ this.logger?.debug("[LiveConfigManager] Already initialized");
59
+ return;
60
+ }
61
+
62
+ try {
63
+ // Initialize configuration watcher for hook settings
64
+ await this.initializeConfigurationWatcher();
65
+
66
+ // Initialize memory store watching for AGENTS.md if callback is available
67
+ if (this.onMemoryStoreFileChanged) {
68
+ await this.initializeMemoryStoreWatching();
69
+ }
70
+
71
+ this.isInitialized = true;
72
+ this.logger?.info(
73
+ "Live Config: Live configuration management initialized successfully",
74
+ );
75
+ } catch (error) {
76
+ this.logger?.error(
77
+ `Live Config: Failed to initialize: ${(error as Error).message}`,
78
+ );
79
+ throw error;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Shutdown live configuration management
85
+ */
86
+ async shutdown(): Promise<void> {
87
+ if (!this.isInitialized) {
88
+ return;
89
+ }
90
+
91
+ try {
92
+ if (this.configurationWatcher) {
93
+ await this.configurationWatcher.shutdown();
94
+ this.configurationWatcher = undefined;
95
+ }
96
+
97
+ this.isInitialized = false;
98
+ this.logger?.info(
99
+ "Live Config: Live configuration management shutdown completed",
100
+ );
101
+ } catch (error) {
102
+ this.logger?.error(
103
+ `Live Config: Error during shutdown: ${(error as Error).message}`,
104
+ );
105
+ throw error;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Initialize configuration watcher for hook settings
111
+ */
112
+ private async initializeConfigurationWatcher(): Promise<void> {
113
+ this.configurationWatcher = new ConfigurationWatcher(
114
+ this.workdir,
115
+ this.logger,
116
+ );
117
+
118
+ // Set up configuration change handler using EventEmitter pattern
119
+ this.configurationWatcher.on(
120
+ CONFIGURATION_EVENTS.CONFIGURATION_CHANGE,
121
+ (event: ConfigurationChangeEvent) => {
122
+ this.handleConfigurationChange(event);
123
+ },
124
+ );
125
+
126
+ // Initialize watching for user and project settings
127
+ const { userPaths, projectPaths } = this.getConfigurationPaths();
128
+ await this.configurationWatcher.initializeWatching(userPaths, projectPaths);
129
+ this.logger?.info("Live Config: Configuration watching initialized");
130
+ }
131
+
132
+ /**
133
+ * Initialize memory store watching for AGENTS.md files
134
+ */
135
+ private async initializeMemoryStoreWatching(): Promise<void> {
136
+ if (!this.onMemoryStoreFileChanged || !this.configurationWatcher) {
137
+ this.logger?.debug(
138
+ "Live Config: Memory store callback or configuration watcher not available, skipping AGENTS.md watching",
139
+ );
140
+ return;
141
+ }
142
+
143
+ try {
144
+ const agentsFilePath = join(this.workdir, "AGENTS.md");
145
+
146
+ // Add AGENTS.md to file watcher
147
+ await this.configurationWatcher.watchAdditionalFile(
148
+ agentsFilePath,
149
+ async (event: FileWatchEvent) => {
150
+ await this.handleMemoryStoreFileChange(event);
151
+ },
152
+ );
153
+
154
+ this.logger?.info("Live Config: AGENTS.md file watching initialized");
155
+ } catch (error) {
156
+ this.logger?.warn(
157
+ `Live Config: Failed to initialize AGENTS.md watching: ${(error as Error).message}`,
158
+ );
159
+ // Don't throw - memory optimization is not critical for core functionality
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Handle configuration change events
165
+ */
166
+ private handleConfigurationChange(event: ConfigurationChangeEvent): void {
167
+ this.logger?.info(
168
+ `Live Config: Configuration change detected: ${event.type} at ${event.path}`,
169
+ );
170
+
171
+ // Invalidate and refresh configuration cache for live environment variable updates
172
+ configResolver.invalidateCache(this.workdir);
173
+ configResolver.refreshCache(this.workdir);
174
+
175
+ // Trigger Agent configuration update callback if provided
176
+ if (this.onConfigurationChanged) {
177
+ try {
178
+ this.logger?.info("Live Config: Triggering Agent configuration update");
179
+ this.onConfigurationChanged();
180
+ } catch (error) {
181
+ this.logger?.error(
182
+ `Live Config: Error in configuration change callback: ${(error as Error).message}`,
183
+ );
184
+ }
185
+ }
186
+
187
+ // Log cache status after refresh
188
+ const cacheStatus = configResolver.getCacheStatus();
189
+ if (cacheStatus) {
190
+ this.logger?.info(
191
+ `Live Config: Configuration cache refreshed - ${cacheStatus.envVarCount} environment variables loaded`,
192
+ );
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Handle AGENTS.md file change events
198
+ */
199
+ private async handleMemoryStoreFileChange(
200
+ event: FileWatchEvent,
201
+ ): Promise<void> {
202
+ if (!this.onMemoryStoreFileChanged) {
203
+ return;
204
+ }
205
+
206
+ try {
207
+ this.logger?.info(
208
+ `Live Config: AGENTS.md ${event.type} detected: ${event.path}`,
209
+ );
210
+
211
+ const changeType: "add" | "change" | "unlink" =
212
+ event.type === "delete"
213
+ ? "unlink"
214
+ : event.type === "create"
215
+ ? "add"
216
+ : "change";
217
+ await this.onMemoryStoreFileChanged(event.path, changeType);
218
+
219
+ this.logger?.info(
220
+ `Live Config: Memory store updated for AGENTS.md ${event.type}`,
221
+ );
222
+ } catch (error) {
223
+ this.logger?.error(
224
+ `Live Config: Failed to handle AGENTS.md file change: ${(error as Error).message}`,
225
+ );
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Get initialization status
231
+ */
232
+ get initialized(): boolean {
233
+ return this.isInitialized;
234
+ }
235
+
236
+ /**
237
+ * Get configuration file paths for user and project settings
238
+ * Returns paths in priority order (local.json first, then .json)
239
+ */
240
+ private getConfigurationPaths(): {
241
+ userPaths: string[];
242
+ projectPaths: string[];
243
+ } {
244
+ const userPaths = getUserConfigPaths();
245
+ const projectPaths = getProjectConfigPaths(this.workdir);
246
+ return { userPaths, projectPaths };
247
+ }
248
+ }