wave-agent-sdk 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +32 -20
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +209 -24
- package/dist/constants/events.d.ts +28 -0
- package/dist/constants/events.d.ts.map +1 -0
- package/dist/constants/events.js +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/managers/aiManager.d.ts +34 -1
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +248 -132
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +7 -6
- package/dist/managers/hookManager.d.ts +13 -16
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +81 -44
- package/dist/managers/liveConfigManager.d.ts +58 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -0
- package/dist/managers/liveConfigManager.js +160 -0
- package/dist/managers/messageManager.d.ts +41 -24
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +168 -49
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +9 -3
- package/dist/managers/subagentManager.d.ts +51 -0
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +190 -19
- package/dist/services/aiService.d.ts +13 -5
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +350 -74
- package/dist/services/configurationWatcher.d.ts +120 -0
- package/dist/services/configurationWatcher.d.ts.map +1 -0
- package/dist/services/configurationWatcher.js +439 -0
- package/dist/services/fileWatcher.d.ts +69 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +213 -0
- package/dist/services/hook.d.ts +91 -9
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +393 -43
- package/dist/services/jsonlHandler.d.ts +62 -0
- package/dist/services/jsonlHandler.d.ts.map +1 -0
- package/dist/services/jsonlHandler.js +257 -0
- package/dist/services/memory.d.ts +9 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +81 -12
- package/dist/services/memoryStore.d.ts +81 -0
- package/dist/services/memoryStore.d.ts.map +1 -0
- package/dist/services/memoryStore.js +200 -0
- package/dist/services/session.d.ts +64 -49
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +310 -132
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +5 -4
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +2 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +3 -2
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +4 -3
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +2 -1
- package/dist/tools/todoWriteTool.d.ts.map +1 -1
- package/dist/tools/todoWriteTool.js +3 -10
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +5 -6
- package/dist/types/commands.d.ts +4 -0
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/core.d.ts +35 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +42 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +21 -0
- package/dist/types/hooks.d.ts +8 -2
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +8 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/memoryStore.d.ts +82 -0
- package/dist/types/memoryStore.d.ts.map +1 -0
- package/dist/types/memoryStore.js +7 -0
- package/dist/types/messaging.d.ts +21 -9
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/messaging.js +5 -1
- package/dist/types/session.d.ts +20 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +7 -0
- package/dist/utils/bashHistory.d.ts.map +1 -1
- package/dist/utils/bashHistory.js +27 -26
- package/dist/utils/cacheControlUtils.d.ts +121 -0
- package/dist/utils/cacheControlUtils.d.ts.map +1 -0
- package/dist/utils/cacheControlUtils.js +367 -0
- package/dist/utils/commandPathResolver.d.ts +52 -0
- package/dist/utils/commandPathResolver.d.ts.map +1 -0
- package/dist/utils/commandPathResolver.js +145 -0
- package/dist/utils/configPaths.d.ts +85 -0
- package/dist/utils/configPaths.d.ts.map +1 -0
- package/dist/utils/configPaths.js +121 -0
- package/dist/utils/configResolver.d.ts +37 -10
- package/dist/utils/configResolver.d.ts.map +1 -1
- package/dist/utils/configResolver.js +127 -23
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +8 -13
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +66 -21
- package/dist/utils/fileUtils.d.ts +15 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +61 -0
- package/dist/utils/globalLogger.d.ts +102 -0
- package/dist/utils/globalLogger.d.ts.map +1 -0
- package/dist/utils/globalLogger.js +136 -0
- package/dist/utils/hookMatcher.d.ts +1 -6
- package/dist/utils/hookMatcher.d.ts.map +1 -1
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +25 -3
- package/dist/utils/messageOperations.d.ts +27 -27
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +46 -36
- package/dist/utils/pathEncoder.d.ts +104 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -0
- package/dist/utils/pathEncoder.js +272 -0
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +2 -1
- package/dist/utils/tokenCalculation.d.ts +26 -0
- package/dist/utils/tokenCalculation.d.ts.map +1 -0
- package/dist/utils/tokenCalculation.js +36 -0
- package/package.json +6 -3
- package/src/agent.ts +301 -37
- package/src/constants/events.ts +38 -0
- package/src/index.ts +2 -0
- package/src/managers/aiManager.ts +325 -173
- package/src/managers/backgroundBashManager.ts +7 -6
- package/src/managers/hookManager.ts +106 -84
- package/src/managers/liveConfigManager.ts +248 -0
- package/src/managers/messageManager.ts +237 -100
- package/src/managers/slashCommandManager.ts +9 -7
- package/src/managers/subagentManager.ts +284 -22
- package/src/services/aiService.ts +474 -83
- package/src/services/configurationWatcher.ts +622 -0
- package/src/services/fileWatcher.ts +301 -0
- package/src/services/hook.ts +538 -47
- package/src/services/jsonlHandler.ts +319 -0
- package/src/services/memory.ts +92 -12
- package/src/services/memoryStore.ts +279 -0
- package/src/services/session.ts +381 -157
- package/src/tools/bashTool.ts +5 -4
- package/src/tools/deleteFileTool.ts +2 -1
- package/src/tools/editTool.ts +3 -2
- package/src/tools/multiEditTool.ts +4 -3
- package/src/tools/readTool.ts +2 -1
- package/src/tools/todoWriteTool.ts +3 -11
- package/src/tools/writeTool.ts +7 -6
- package/src/types/commands.ts +6 -0
- package/src/types/core.ts +44 -0
- package/src/types/environment.ts +60 -0
- package/src/types/hooks.ts +21 -8
- package/src/types/index.ts +2 -0
- package/src/types/memoryStore.ts +94 -0
- package/src/types/messaging.ts +21 -10
- package/src/types/session.ts +25 -0
- package/src/utils/bashHistory.ts +27 -27
- package/src/utils/cacheControlUtils.ts +540 -0
- package/src/utils/commandPathResolver.ts +189 -0
- package/src/utils/configPaths.ts +163 -0
- package/src/utils/configResolver.ts +182 -22
- package/src/utils/constants.ts +1 -1
- package/src/utils/convertMessagesForAPI.ts +8 -14
- package/src/utils/customCommands.ts +90 -22
- package/src/utils/fileUtils.ts +65 -0
- package/src/utils/globalLogger.ts +145 -0
- package/src/utils/hookMatcher.ts +1 -12
- package/src/utils/mcpUtils.ts +34 -3
- package/src/utils/messageOperations.ts +77 -60
- package/src/utils/pathEncoder.ts +379 -0
- package/src/utils/subagentParser.ts +2 -1
- package/src/utils/tokenCalculation.ts +43 -0
- package/src/types/index.ts.backup +0 -357
|
@@ -4,24 +4,17 @@
|
|
|
4
4
|
* Central orchestrator for the hooks system. Handles configuration loading,
|
|
5
5
|
* validation, and hook execution across all supported events.
|
|
6
6
|
*/
|
|
7
|
-
import { type HookEvent, type
|
|
8
|
-
import {
|
|
7
|
+
import { type HookEvent, type WaveConfiguration, type PartialHookConfiguration, type HookExecutionContext, type ExtendedHookExecutionContext, type HookExecutionResult, type ValidationResult } from "../types/hooks.js";
|
|
8
|
+
import { HookMatcher } from "../utils/hookMatcher.js";
|
|
9
9
|
import type { Logger } from "../types/index.js";
|
|
10
10
|
import type { MessageManager } from "./messageManager.js";
|
|
11
|
-
export
|
|
12
|
-
loadConfiguration(userHooks?: PartialHookConfiguration, projectHooks?: PartialHookConfiguration): void;
|
|
13
|
-
loadConfigurationFromSettings(): void;
|
|
14
|
-
executeHooks(event: HookEvent, context: HookExecutionContext | ExtendedHookExecutionContext): Promise<HookExecutionResult[]>;
|
|
15
|
-
hasHooks(event: HookEvent, toolName?: string): boolean;
|
|
16
|
-
validateConfiguration(config: HookConfiguration): ValidationResult;
|
|
17
|
-
getConfiguration(): PartialHookConfiguration | undefined;
|
|
18
|
-
}
|
|
19
|
-
export declare class HookManager implements IHookManager {
|
|
11
|
+
export declare class HookManager {
|
|
20
12
|
private configuration;
|
|
13
|
+
private environmentVars;
|
|
21
14
|
private readonly matcher;
|
|
22
15
|
private readonly logger?;
|
|
23
16
|
private readonly workdir;
|
|
24
|
-
constructor(workdir: string, matcher?:
|
|
17
|
+
constructor(workdir: string, matcher?: HookMatcher, logger?: Logger);
|
|
25
18
|
/**
|
|
26
19
|
* Load and merge hook configurations from user and project settings
|
|
27
20
|
* Project settings take precedence over user settings
|
|
@@ -29,7 +22,7 @@ export declare class HookManager implements IHookManager {
|
|
|
29
22
|
loadConfiguration(userHooks?: PartialHookConfiguration, projectHooks?: PartialHookConfiguration): void;
|
|
30
23
|
/**
|
|
31
24
|
* Load configuration from filesystem settings
|
|
32
|
-
* Automatically loads and merges user and project hooks
|
|
25
|
+
* Automatically loads and merges user and project Wave configuration (hooks + environment)
|
|
33
26
|
*/
|
|
34
27
|
loadConfigurationFromSettings(): void;
|
|
35
28
|
/**
|
|
@@ -40,7 +33,7 @@ export declare class HookManager implements IHookManager {
|
|
|
40
33
|
* Process hook execution results and determine appropriate actions
|
|
41
34
|
* based on exit codes and hook event type
|
|
42
35
|
*/
|
|
43
|
-
processHookResults(event: HookEvent, results: HookExecutionResult[], messageManager?: MessageManager, toolId?: string,
|
|
36
|
+
processHookResults(event: HookEvent, results: HookExecutionResult[], messageManager?: MessageManager, toolId?: string, toolParameters?: string): {
|
|
44
37
|
shouldBlock: boolean;
|
|
45
38
|
errorMessage?: string;
|
|
46
39
|
};
|
|
@@ -61,9 +54,9 @@ export declare class HookManager implements IHookManager {
|
|
|
61
54
|
*/
|
|
62
55
|
hasHooks(event: HookEvent, toolName?: string): boolean;
|
|
63
56
|
/**
|
|
64
|
-
* Validate
|
|
57
|
+
* Validate Wave configuration structure and content
|
|
65
58
|
*/
|
|
66
|
-
validateConfiguration(config:
|
|
59
|
+
validateConfiguration(config: WaveConfiguration): ValidationResult;
|
|
67
60
|
/**
|
|
68
61
|
* Validate partial hook configuration structure and content
|
|
69
62
|
*/
|
|
@@ -72,6 +65,10 @@ export declare class HookManager implements IHookManager {
|
|
|
72
65
|
* Get current configuration
|
|
73
66
|
*/
|
|
74
67
|
getConfiguration(): PartialHookConfiguration | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Get current environment variables
|
|
70
|
+
*/
|
|
71
|
+
getEnvironmentVars(): Record<string, string> | undefined;
|
|
75
72
|
/**
|
|
76
73
|
* Clear current configuration
|
|
77
74
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hookManager.d.ts","sourceRoot":"","sources":["../../src/managers/hookManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAItB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"hookManager.d.ts","sourceRoot":"","sources":["../../src/managers/hookManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAItB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAG/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,WAA+B,EACxC,MAAM,CAAC,EAAE,MAAM;IAOjB;;;OAGG;IACH,iBAAiB,CACf,SAAS,CAAC,EAAE,wBAAwB,EACpC,YAAY,CAAC,EAAE,wBAAwB,GACtC,IAAI;IAyBP;;;OAGG;IACH,6BAA6B,IAAI,IAAI;IA6CrC;;OAEG;IACG,YAAY,CAChB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,GAC3D,OAAO,CAAC,mBAAmB,EAAE,CAAC;IA0HjC;;;OAGG;IACH,kBAAkB,CAChB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,mBAAmB,EAAE,EAC9B,cAAc,CAAC,EAAE,cAAc,EAC/B,MAAM,CAAC,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACtB;QACD,WAAW,EAAE,OAAO,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB;IAuCD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAyD3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAWtD;;OAEG;IACH,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,gBAAgB;IA8DlE;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAyCpC;;OAEG;IACH,gBAAgB,IAAI,wBAAwB,GAAG,SAAS;IAOxD;;OAEG;IACH,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IAOxD;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAmDhC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA8BhC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,aAAa;IA4BrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqC3B;;OAEG;IACH,qBAAqB,IAAI;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;KAC3C;CA6CF"}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { HookConfigurationError, isValidHookEvent, isValidHookEventConfig, } from "../types/hooks.js";
|
|
8
8
|
import { HookMatcher } from "../utils/hookMatcher.js";
|
|
9
|
-
import { executeCommand, isCommandSafe,
|
|
9
|
+
import { executeCommand, isCommandSafe, loadMergedWaveConfig, } from "../services/hook.js";
|
|
10
|
+
import { MessageSource } from "../types/index.js";
|
|
10
11
|
export class HookManager {
|
|
11
12
|
constructor(workdir, matcher = new HookMatcher(), logger) {
|
|
12
13
|
this.workdir = workdir;
|
|
@@ -36,26 +37,28 @@ export class HookManager {
|
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
39
|
* Load configuration from filesystem settings
|
|
39
|
-
* Automatically loads and merges user and project hooks
|
|
40
|
+
* Automatically loads and merges user and project Wave configuration (hooks + environment)
|
|
40
41
|
*/
|
|
41
42
|
loadConfigurationFromSettings() {
|
|
42
43
|
try {
|
|
43
44
|
this.logger?.debug(`[HookManager] Loading configuration...`);
|
|
44
|
-
const
|
|
45
|
-
this.logger?.debug(`[HookManager] Merged config result:`,
|
|
46
|
-
this.configuration =
|
|
45
|
+
const mergedWaveConfig = loadMergedWaveConfig(this.workdir);
|
|
46
|
+
this.logger?.debug(`[HookManager] Merged config result:`, mergedWaveConfig);
|
|
47
|
+
this.configuration = mergedWaveConfig?.hooks || undefined;
|
|
48
|
+
this.environmentVars = mergedWaveConfig?.env || undefined;
|
|
47
49
|
// Validate the loaded configuration if it exists
|
|
48
|
-
if (
|
|
49
|
-
const validation = this.validatePartialConfiguration(
|
|
50
|
+
if (mergedWaveConfig?.hooks) {
|
|
51
|
+
const validation = this.validatePartialConfiguration(mergedWaveConfig.hooks);
|
|
50
52
|
if (!validation.valid) {
|
|
51
53
|
throw new HookConfigurationError("filesystem settings", validation.errors);
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
|
-
this.logger?.debug(`[HookManager] Configuration loaded successfully with ${Object.keys(
|
|
56
|
+
this.logger?.debug(`[HookManager] Configuration loaded successfully with ${Object.keys(mergedWaveConfig?.hooks || {}).length} event types and ${Object.keys(this.environmentVars || {}).length} environment variables`);
|
|
55
57
|
}
|
|
56
58
|
catch (error) {
|
|
57
59
|
// If loading fails, start with undefined configuration (no hooks)
|
|
58
60
|
this.configuration = undefined;
|
|
61
|
+
this.environmentVars = undefined;
|
|
59
62
|
// Re-throw configuration errors, but handle file system errors gracefully
|
|
60
63
|
if (error instanceof HookConfigurationError) {
|
|
61
64
|
throw error;
|
|
@@ -107,14 +110,14 @@ export class HookManager {
|
|
|
107
110
|
const hookCommand = config.hooks[commandIndex];
|
|
108
111
|
try {
|
|
109
112
|
this.logger?.debug(`[HookManager] Executing command ${commandIndex + 1}/${config.hooks.length} in configuration ${configIndex + 1}`);
|
|
110
|
-
const result = await executeCommand(hookCommand.command, context);
|
|
113
|
+
const result = await executeCommand(hookCommand.command, context, undefined, this.environmentVars);
|
|
111
114
|
results.push(result);
|
|
112
115
|
// Report individual command result
|
|
113
116
|
if (result.success) {
|
|
114
117
|
this.logger?.debug(`[HookManager] Command ${commandIndex + 1} completed successfully in ${result.duration}ms`);
|
|
115
118
|
}
|
|
116
119
|
else {
|
|
117
|
-
this.logger?.
|
|
120
|
+
this.logger?.debug(`[HookManager] Command ${commandIndex + 1} failed in ${result.duration}ms (exit code: ${result.exitCode}, timed out: ${result.timedOut})`);
|
|
118
121
|
}
|
|
119
122
|
// Continue with next command even if this one fails
|
|
120
123
|
// This allows for non-critical hooks to fail without stopping the workflow
|
|
@@ -142,7 +145,7 @@ export class HookManager {
|
|
|
142
145
|
* Process hook execution results and determine appropriate actions
|
|
143
146
|
* based on exit codes and hook event type
|
|
144
147
|
*/
|
|
145
|
-
processHookResults(event, results, messageManager, toolId,
|
|
148
|
+
processHookResults(event, results, messageManager, toolId, toolParameters) {
|
|
146
149
|
if (!messageManager || results.length === 0) {
|
|
147
150
|
return { shouldBlock: false };
|
|
148
151
|
}
|
|
@@ -151,7 +154,7 @@ export class HookManager {
|
|
|
151
154
|
for (const result of results) {
|
|
152
155
|
if (result.exitCode === 2) {
|
|
153
156
|
// Handle blocking error immediately and return
|
|
154
|
-
return this.handleBlockingError(event, result, messageManager, toolId,
|
|
157
|
+
return this.handleBlockingError(event, result, messageManager, toolId, toolParameters);
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
160
|
// Second pass: Process all non-blocking results
|
|
@@ -177,14 +180,17 @@ export class HookManager {
|
|
|
177
180
|
handleHookSuccess(event, result, messageManager) {
|
|
178
181
|
if (event === "UserPromptSubmit" && result.stdout?.trim()) {
|
|
179
182
|
// Inject stdout as user message context for UserPromptSubmit
|
|
180
|
-
messageManager.addUserMessage(
|
|
183
|
+
messageManager.addUserMessage({
|
|
184
|
+
content: result.stdout.trim(),
|
|
185
|
+
source: MessageSource.HOOK,
|
|
186
|
+
});
|
|
181
187
|
}
|
|
182
188
|
// For other hook types (PreToolUse, PostToolUse, Stop), ignore stdout
|
|
183
189
|
}
|
|
184
190
|
/**
|
|
185
191
|
* Handle blocking error (exit code 2) - behavior varies by hook type
|
|
186
192
|
*/
|
|
187
|
-
handleBlockingError(event, result, messageManager, toolId,
|
|
193
|
+
handleBlockingError(event, result, messageManager, toolId, toolParameters) {
|
|
188
194
|
const errorMessage = result.stderr?.trim() || "Hook execution failed";
|
|
189
195
|
switch (event) {
|
|
190
196
|
case "UserPromptSubmit":
|
|
@@ -199,26 +205,28 @@ export class HookManager {
|
|
|
199
205
|
// Block tool execution and show error to Wave Agent via tool block
|
|
200
206
|
if (toolId) {
|
|
201
207
|
messageManager.updateToolBlock({
|
|
202
|
-
toolId,
|
|
208
|
+
id: toolId,
|
|
209
|
+
parameters: toolParameters || "",
|
|
203
210
|
result: errorMessage,
|
|
204
211
|
success: false,
|
|
205
212
|
error: "Hook blocked tool execution",
|
|
213
|
+
stage: "end", // Hook blocking results in end stage with error
|
|
206
214
|
});
|
|
207
215
|
}
|
|
208
216
|
return { shouldBlock: true };
|
|
209
217
|
case "PostToolUse":
|
|
210
|
-
// Show error to Wave Agent via
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
success: false,
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
+
// Show error to Wave Agent via user message and allow AI to continue
|
|
219
|
+
messageManager.addUserMessage({
|
|
220
|
+
content: errorMessage,
|
|
221
|
+
source: MessageSource.HOOK,
|
|
222
|
+
});
|
|
218
223
|
return { shouldBlock: false };
|
|
219
224
|
case "Stop":
|
|
220
225
|
// Show error to Wave Agent via user message and block stopping to continue conversation
|
|
221
|
-
messageManager.addUserMessage(
|
|
226
|
+
messageManager.addUserMessage({
|
|
227
|
+
content: errorMessage,
|
|
228
|
+
source: MessageSource.HOOK,
|
|
229
|
+
});
|
|
222
230
|
return { shouldBlock: true, errorMessage };
|
|
223
231
|
default:
|
|
224
232
|
return { shouldBlock: false };
|
|
@@ -243,35 +251,53 @@ export class HookManager {
|
|
|
243
251
|
return eventConfigs.some((config) => this.configApplies(config, event, toolName));
|
|
244
252
|
}
|
|
245
253
|
/**
|
|
246
|
-
* Validate
|
|
254
|
+
* Validate Wave configuration structure and content
|
|
247
255
|
*/
|
|
248
256
|
validateConfiguration(config) {
|
|
249
257
|
const errors = [];
|
|
250
258
|
if (!config || typeof config !== "object") {
|
|
251
259
|
return { valid: false, errors: ["Configuration must be an object"] };
|
|
252
260
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
errors
|
|
257
|
-
}
|
|
261
|
+
// Validate hooks if present
|
|
262
|
+
if (config.hooks) {
|
|
263
|
+
if (typeof config.hooks !== "object") {
|
|
264
|
+
errors.push("hooks property must be an object");
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
// Validate each hook event
|
|
268
|
+
for (const [eventName, eventConfigs] of Object.entries(config.hooks)) {
|
|
269
|
+
// Validate event name
|
|
270
|
+
if (!isValidHookEvent(eventName)) {
|
|
271
|
+
errors.push(`Invalid hook event: ${eventName}`);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
// Validate event configurations
|
|
275
|
+
if (!Array.isArray(eventConfigs)) {
|
|
276
|
+
errors.push(`Hook event ${eventName} must be an array of configurations`);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
eventConfigs.forEach((eventConfig, index) => {
|
|
280
|
+
const configErrors = this.validateEventConfig(eventName, eventConfig, index);
|
|
281
|
+
errors.push(...configErrors);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
258
285
|
}
|
|
259
|
-
// Validate
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
errors.push(`Invalid hook event: ${eventName}`);
|
|
264
|
-
continue;
|
|
286
|
+
// Validate environment variables if present
|
|
287
|
+
if (config.env) {
|
|
288
|
+
if (typeof config.env !== "object" || Array.isArray(config.env)) {
|
|
289
|
+
errors.push("env property must be an object");
|
|
265
290
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
291
|
+
else {
|
|
292
|
+
for (const [key, value] of Object.entries(config.env)) {
|
|
293
|
+
if (typeof key !== "string" || key.trim() === "") {
|
|
294
|
+
errors.push(`Invalid environment variable key: ${key}`);
|
|
295
|
+
}
|
|
296
|
+
if (typeof value !== "string") {
|
|
297
|
+
errors.push(`Environment variable ${key} must have a string value`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
270
300
|
}
|
|
271
|
-
eventConfigs.forEach((eventConfig, index) => {
|
|
272
|
-
const configErrors = this.validateEventConfig(eventName, eventConfig, index);
|
|
273
|
-
errors.push(...configErrors);
|
|
274
|
-
});
|
|
275
301
|
}
|
|
276
302
|
return {
|
|
277
303
|
valid: errors.length === 0,
|
|
@@ -317,6 +343,15 @@ export class HookManager {
|
|
|
317
343
|
// Deep clone to prevent external modification
|
|
318
344
|
return JSON.parse(JSON.stringify(this.configuration));
|
|
319
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Get current environment variables
|
|
348
|
+
*/
|
|
349
|
+
getEnvironmentVars() {
|
|
350
|
+
if (!this.environmentVars)
|
|
351
|
+
return undefined;
|
|
352
|
+
// Deep clone to prevent external modification
|
|
353
|
+
return JSON.parse(JSON.stringify(this.environmentVars));
|
|
354
|
+
}
|
|
320
355
|
/**
|
|
321
356
|
* Clear current configuration
|
|
322
357
|
*/
|
|
@@ -457,6 +492,7 @@ export class HookManager {
|
|
|
457
492
|
PostToolUse: 0,
|
|
458
493
|
UserPromptSubmit: 0,
|
|
459
494
|
Stop: 0,
|
|
495
|
+
SubagentStop: 0,
|
|
460
496
|
},
|
|
461
497
|
};
|
|
462
498
|
}
|
|
@@ -465,6 +501,7 @@ export class HookManager {
|
|
|
465
501
|
PostToolUse: 0,
|
|
466
502
|
UserPromptSubmit: 0,
|
|
467
503
|
Stop: 0,
|
|
504
|
+
SubagentStop: 0,
|
|
468
505
|
};
|
|
469
506
|
let totalConfigs = 0;
|
|
470
507
|
let totalCommands = 0;
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
import type { Logger } from "../types/index.js";
|
|
10
|
+
export interface LiveConfigManagerOptions {
|
|
11
|
+
workdir: string;
|
|
12
|
+
logger?: Logger;
|
|
13
|
+
onConfigurationChanged?: () => void;
|
|
14
|
+
onMemoryStoreFileChanged?: (filePath: string, changeType: "add" | "change" | "unlink") => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export declare class LiveConfigManager {
|
|
17
|
+
private readonly workdir;
|
|
18
|
+
private readonly logger?;
|
|
19
|
+
private readonly onConfigurationChanged?;
|
|
20
|
+
private readonly onMemoryStoreFileChanged?;
|
|
21
|
+
private configurationWatcher?;
|
|
22
|
+
private isInitialized;
|
|
23
|
+
constructor(options: LiveConfigManagerOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Initialize live configuration management
|
|
26
|
+
*/
|
|
27
|
+
initialize(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Shutdown live configuration management
|
|
30
|
+
*/
|
|
31
|
+
shutdown(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Initialize configuration watcher for hook settings
|
|
34
|
+
*/
|
|
35
|
+
private initializeConfigurationWatcher;
|
|
36
|
+
/**
|
|
37
|
+
* Initialize memory store watching for AGENTS.md files
|
|
38
|
+
*/
|
|
39
|
+
private initializeMemoryStoreWatching;
|
|
40
|
+
/**
|
|
41
|
+
* Handle configuration change events
|
|
42
|
+
*/
|
|
43
|
+
private handleConfigurationChange;
|
|
44
|
+
/**
|
|
45
|
+
* Handle AGENTS.md file change events
|
|
46
|
+
*/
|
|
47
|
+
private handleMemoryStoreFileChange;
|
|
48
|
+
/**
|
|
49
|
+
* Get initialization status
|
|
50
|
+
*/
|
|
51
|
+
get initialized(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Get configuration file paths for user and project settings
|
|
54
|
+
* Returns paths in priority order (local.json first, then .json)
|
|
55
|
+
*/
|
|
56
|
+
private getConfigurationPaths;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=liveConfigManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liveConfigManager.d.ts","sourceRoot":"","sources":["../../src/managers/liveConfigManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAehD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,wBAAwB,CAAC,EAAE,CACzB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,KACpC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAGvB;IACnB,OAAO,CAAC,oBAAoB,CAAC,CAAuB;IACpD,OAAO,CAAC,aAAa,CAAkB;gBAE3B,OAAO,EAAE,wBAAwB;IAO7C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BjC;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB/B;;OAEG;YACW,8BAA8B;IAoB5C;;OAEG;YACW,6BAA6B;IA4B3C;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA8BjC;;OAEG;YACW,2BAA2B;IA8BzC;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;OAGG;IACH,OAAO,CAAC,qBAAqB;CAQ9B"}
|
|
@@ -0,0 +1,160 @@
|
|
|
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
|
+
import { ConfigurationWatcher, } from "../services/configurationWatcher.js";
|
|
10
|
+
import { configResolver } from "../utils/configResolver.js";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import { getUserConfigPaths, getProjectConfigPaths, } from "../utils/configPaths.js";
|
|
13
|
+
import { CONFIGURATION_EVENTS } from "../constants/events.js";
|
|
14
|
+
export class LiveConfigManager {
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.isInitialized = false;
|
|
17
|
+
this.workdir = options.workdir;
|
|
18
|
+
this.logger = options.logger;
|
|
19
|
+
this.onConfigurationChanged = options.onConfigurationChanged;
|
|
20
|
+
this.onMemoryStoreFileChanged = options.onMemoryStoreFileChanged;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Initialize live configuration management
|
|
24
|
+
*/
|
|
25
|
+
async initialize() {
|
|
26
|
+
if (this.isInitialized) {
|
|
27
|
+
this.logger?.debug("[LiveConfigManager] Already initialized");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
// Initialize configuration watcher for hook settings
|
|
32
|
+
await this.initializeConfigurationWatcher();
|
|
33
|
+
// Initialize memory store watching for AGENTS.md if callback is available
|
|
34
|
+
if (this.onMemoryStoreFileChanged) {
|
|
35
|
+
await this.initializeMemoryStoreWatching();
|
|
36
|
+
}
|
|
37
|
+
this.isInitialized = true;
|
|
38
|
+
this.logger?.info("Live Config: Live configuration management initialized successfully");
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
this.logger?.error(`Live Config: Failed to initialize: ${error.message}`);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Shutdown live configuration management
|
|
47
|
+
*/
|
|
48
|
+
async shutdown() {
|
|
49
|
+
if (!this.isInitialized) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
if (this.configurationWatcher) {
|
|
54
|
+
await this.configurationWatcher.shutdown();
|
|
55
|
+
this.configurationWatcher = undefined;
|
|
56
|
+
}
|
|
57
|
+
this.isInitialized = false;
|
|
58
|
+
this.logger?.info("Live Config: Live configuration management shutdown completed");
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.logger?.error(`Live Config: Error during shutdown: ${error.message}`);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Initialize configuration watcher for hook settings
|
|
67
|
+
*/
|
|
68
|
+
async initializeConfigurationWatcher() {
|
|
69
|
+
this.configurationWatcher = new ConfigurationWatcher(this.workdir, this.logger);
|
|
70
|
+
// Set up configuration change handler using EventEmitter pattern
|
|
71
|
+
this.configurationWatcher.on(CONFIGURATION_EVENTS.CONFIGURATION_CHANGE, (event) => {
|
|
72
|
+
this.handleConfigurationChange(event);
|
|
73
|
+
});
|
|
74
|
+
// Initialize watching for user and project settings
|
|
75
|
+
const { userPaths, projectPaths } = this.getConfigurationPaths();
|
|
76
|
+
await this.configurationWatcher.initializeWatching(userPaths, projectPaths);
|
|
77
|
+
this.logger?.info("Live Config: Configuration watching initialized");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Initialize memory store watching for AGENTS.md files
|
|
81
|
+
*/
|
|
82
|
+
async initializeMemoryStoreWatching() {
|
|
83
|
+
if (!this.onMemoryStoreFileChanged || !this.configurationWatcher) {
|
|
84
|
+
this.logger?.debug("Live Config: Memory store callback or configuration watcher not available, skipping AGENTS.md watching");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const agentsFilePath = join(this.workdir, "AGENTS.md");
|
|
89
|
+
// Add AGENTS.md to file watcher
|
|
90
|
+
await this.configurationWatcher.watchAdditionalFile(agentsFilePath, async (event) => {
|
|
91
|
+
await this.handleMemoryStoreFileChange(event);
|
|
92
|
+
});
|
|
93
|
+
this.logger?.info("Live Config: AGENTS.md file watching initialized");
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
this.logger?.warn(`Live Config: Failed to initialize AGENTS.md watching: ${error.message}`);
|
|
97
|
+
// Don't throw - memory optimization is not critical for core functionality
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Handle configuration change events
|
|
102
|
+
*/
|
|
103
|
+
handleConfigurationChange(event) {
|
|
104
|
+
this.logger?.info(`Live Config: Configuration change detected: ${event.type} at ${event.path}`);
|
|
105
|
+
// Invalidate and refresh configuration cache for live environment variable updates
|
|
106
|
+
configResolver.invalidateCache(this.workdir);
|
|
107
|
+
configResolver.refreshCache(this.workdir);
|
|
108
|
+
// Trigger Agent configuration update callback if provided
|
|
109
|
+
if (this.onConfigurationChanged) {
|
|
110
|
+
try {
|
|
111
|
+
this.logger?.info("Live Config: Triggering Agent configuration update");
|
|
112
|
+
this.onConfigurationChanged();
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
this.logger?.error(`Live Config: Error in configuration change callback: ${error.message}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Log cache status after refresh
|
|
119
|
+
const cacheStatus = configResolver.getCacheStatus();
|
|
120
|
+
if (cacheStatus) {
|
|
121
|
+
this.logger?.info(`Live Config: Configuration cache refreshed - ${cacheStatus.envVarCount} environment variables loaded`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Handle AGENTS.md file change events
|
|
126
|
+
*/
|
|
127
|
+
async handleMemoryStoreFileChange(event) {
|
|
128
|
+
if (!this.onMemoryStoreFileChanged) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
this.logger?.info(`Live Config: AGENTS.md ${event.type} detected: ${event.path}`);
|
|
133
|
+
const changeType = event.type === "delete"
|
|
134
|
+
? "unlink"
|
|
135
|
+
: event.type === "create"
|
|
136
|
+
? "add"
|
|
137
|
+
: "change";
|
|
138
|
+
await this.onMemoryStoreFileChanged(event.path, changeType);
|
|
139
|
+
this.logger?.info(`Live Config: Memory store updated for AGENTS.md ${event.type}`);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
this.logger?.error(`Live Config: Failed to handle AGENTS.md file change: ${error.message}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get initialization status
|
|
147
|
+
*/
|
|
148
|
+
get initialized() {
|
|
149
|
+
return this.isInitialized;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get configuration file paths for user and project settings
|
|
153
|
+
* Returns paths in priority order (local.json first, then .json)
|
|
154
|
+
*/
|
|
155
|
+
getConfigurationPaths() {
|
|
156
|
+
const userPaths = getUserConfigPaths();
|
|
157
|
+
const projectPaths = getProjectConfigPaths(this.workdir);
|
|
158
|
+
return { userPaths, projectPaths };
|
|
159
|
+
}
|
|
160
|
+
}
|