wave-agent-sdk 0.0.7 → 0.0.10
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 +105 -24
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +438 -53
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/managers/aiManager.d.ts +18 -7
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +254 -142
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +11 -9
- package/dist/managers/hookManager.d.ts +6 -6
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +81 -39
- package/dist/managers/liveConfigManager.d.ts +95 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -0
- package/dist/managers/liveConfigManager.js +442 -0
- package/dist/managers/lspManager.d.ts +43 -0
- package/dist/managers/lspManager.d.ts.map +1 -0
- package/dist/managers/lspManager.js +326 -0
- package/dist/managers/messageManager.d.ts +41 -24
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +184 -73
- package/dist/managers/permissionManager.d.ts +66 -0
- package/dist/managers/permissionManager.d.ts.map +1 -0
- package/dist/managers/permissionManager.js +208 -0
- package/dist/managers/skillManager.d.ts +1 -0
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +2 -1
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +4 -2
- package/dist/managers/subagentManager.d.ts +42 -6
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +213 -62
- package/dist/managers/toolManager.d.ts +38 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +66 -2
- package/dist/services/aiService.d.ts +15 -5
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +446 -77
- package/dist/services/configurationService.d.ts +116 -0
- package/dist/services/configurationService.d.ts.map +1 -0
- package/dist/services/configurationService.js +585 -0
- package/dist/services/fileWatcher.d.ts +69 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +212 -0
- package/dist/services/hook.d.ts +5 -40
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +47 -109
- package/dist/services/jsonlHandler.d.ts +71 -0
- package/dist/services/jsonlHandler.d.ts.map +1 -0
- package/dist/services/jsonlHandler.js +236 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +33 -11
- package/dist/services/session.d.ts +116 -52
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +415 -143
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +77 -17
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +27 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +33 -8
- package/dist/tools/lspTool.d.ts +6 -0
- package/dist/tools/lspTool.d.ts.map +1 -0
- package/dist/tools/lspTool.js +589 -0
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +30 -10
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +113 -3
- package/dist/tools/skillTool.js +2 -2
- package/dist/tools/todoWriteTool.d.ts.map +1 -1
- package/dist/tools/todoWriteTool.js +23 -0
- package/dist/tools/types.d.ts +11 -8
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +30 -15
- package/dist/types/commands.d.ts +4 -1
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/configuration.d.ts +69 -0
- package/dist/types/configuration.d.ts.map +1 -0
- package/dist/types/configuration.js +8 -0
- package/dist/types/core.d.ts +45 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +83 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +21 -0
- package/dist/types/fileSearch.d.ts +5 -0
- package/dist/types/fileSearch.d.ts.map +1 -0
- package/dist/types/fileSearch.js +1 -0
- package/dist/types/hooks.d.ts +18 -3
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +8 -8
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +7 -0
- package/dist/types/lsp.d.ts +90 -0
- package/dist/types/lsp.d.ts.map +1 -0
- package/dist/types/lsp.js +4 -0
- package/dist/types/messaging.d.ts +19 -12
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +35 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +12 -0
- package/dist/types/session.d.ts +15 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +7 -0
- package/dist/types/skills.d.ts +1 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/tools.d.ts +35 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +4 -0
- package/dist/utils/abortUtils.d.ts +34 -0
- package/dist/utils/abortUtils.d.ts.map +1 -0
- package/dist/utils/abortUtils.js +92 -0
- package/dist/utils/bashHistory.d.ts +4 -0
- package/dist/utils/bashHistory.d.ts.map +1 -1
- package/dist/utils/bashHistory.js +48 -30
- package/dist/utils/builtinSubagents.d.ts +7 -0
- package/dist/utils/builtinSubagents.d.ts.map +1 -0
- package/dist/utils/builtinSubagents.js +65 -0
- package/dist/utils/cacheControlUtils.d.ts +96 -0
- package/dist/utils/cacheControlUtils.d.ts.map +1 -0
- package/dist/utils/cacheControlUtils.js +324 -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/constants.d.ts +1 -13
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +2 -14
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +39 -18
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +66 -21
- package/dist/utils/fileSearch.d.ts +14 -0
- package/dist/utils/fileSearch.d.ts.map +1 -0
- package/dist/utils/fileSearch.js +88 -0
- package/dist/utils/fileUtils.d.ts +27 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +145 -0
- package/dist/utils/globalLogger.d.ts +88 -0
- package/dist/utils/globalLogger.d.ts.map +1 -0
- package/dist/utils/globalLogger.js +120 -0
- package/dist/utils/largeOutputHandler.d.ts +15 -0
- package/dist/utils/largeOutputHandler.d.ts.map +1 -0
- package/dist/utils/largeOutputHandler.js +40 -0
- package/dist/utils/markdownParser.d.ts.map +1 -1
- package/dist/utils/markdownParser.js +1 -17
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +25 -3
- package/dist/utils/messageOperations.d.ts +20 -18
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +30 -38
- package/dist/utils/pathEncoder.d.ts +108 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -0
- package/dist/utils/pathEncoder.js +279 -0
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +12 -8
- 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/dist/utils/tokenEstimator.d.ts +39 -0
- package/dist/utils/tokenEstimator.d.ts.map +1 -0
- package/dist/utils/tokenEstimator.js +55 -0
- package/package.json +6 -6
- package/src/agent.ts +586 -78
- package/src/index.ts +4 -0
- package/src/managers/aiManager.ts +341 -192
- package/src/managers/backgroundBashManager.ts +11 -9
- package/src/managers/hookManager.ts +102 -54
- package/src/managers/liveConfigManager.ts +634 -0
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +258 -121
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +5 -3
- package/src/managers/subagentManager.ts +295 -76
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +656 -84
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +300 -0
- package/src/services/hook.ts +54 -144
- package/src/services/jsonlHandler.ts +303 -0
- package/src/services/memory.ts +34 -11
- package/src/services/session.ts +522 -173
- package/src/tools/bashTool.ts +94 -20
- package/src/tools/deleteFileTool.ts +38 -1
- package/src/tools/editTool.ts +44 -9
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +41 -11
- package/src/tools/readTool.ts +127 -3
- package/src/tools/skillTool.ts +2 -2
- package/src/tools/todoWriteTool.ts +33 -1
- package/src/tools/types.ts +15 -9
- package/src/tools/writeTool.ts +43 -16
- package/src/types/commands.ts +6 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +55 -0
- package/src/types/environment.ts +104 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +32 -16
- package/src/types/index.ts +7 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +21 -14
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +20 -0
- package/src/types/skills.ts +1 -0
- package/src/types/tools.ts +38 -0
- package/src/utils/abortUtils.ts +118 -0
- package/src/utils/bashHistory.ts +55 -31
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +475 -0
- package/src/utils/commandPathResolver.ts +189 -0
- package/src/utils/configPaths.ts +163 -0
- package/src/utils/constants.ts +2 -17
- package/src/utils/convertMessagesForAPI.ts +44 -18
- package/src/utils/customCommands.ts +90 -22
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +160 -0
- package/src/utils/globalLogger.ts +128 -0
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/mcpUtils.ts +34 -3
- package/src/utils/messageOperations.ts +47 -53
- package/src/utils/pathEncoder.ts +394 -0
- package/src/utils/subagentParser.ts +13 -9
- package/src/utils/tokenCalculation.ts +43 -0
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/utils/configResolver.d.ts +0 -38
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -106
- package/src/utils/configResolver.ts +0 -142
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Watcher Service
|
|
3
|
+
*
|
|
4
|
+
* Provides robust cross-platform file watching using Chokidar library.
|
|
5
|
+
* Handles file watching with debouncing, error recovery, and graceful fallbacks.
|
|
6
|
+
*/
|
|
7
|
+
import * as chokidar from "chokidar";
|
|
8
|
+
import { EventEmitter } from "events";
|
|
9
|
+
export class FileWatcherService extends EventEmitter {
|
|
10
|
+
constructor(logger, config) {
|
|
11
|
+
super();
|
|
12
|
+
this.watchers = new Map();
|
|
13
|
+
this.globalWatcher = null;
|
|
14
|
+
this.logger = logger;
|
|
15
|
+
this.defaultConfig = {
|
|
16
|
+
stabilityThreshold: 300,
|
|
17
|
+
pollInterval: 100,
|
|
18
|
+
maxRetries: 3,
|
|
19
|
+
fallbackPolling: false,
|
|
20
|
+
ignoreTempFiles: true,
|
|
21
|
+
...config,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Start watching a file
|
|
26
|
+
* Maps to FR-010: Handle file deletion, creation, and modification
|
|
27
|
+
*/
|
|
28
|
+
async watchFile(path, callback) {
|
|
29
|
+
try {
|
|
30
|
+
if (this.watchers.has(path)) {
|
|
31
|
+
// Add callback to existing watcher
|
|
32
|
+
const entry = this.watchers.get(path);
|
|
33
|
+
entry.callbacks.add(callback);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// Create new watcher entry
|
|
37
|
+
const entry = {
|
|
38
|
+
path,
|
|
39
|
+
watcher: null,
|
|
40
|
+
isActive: false,
|
|
41
|
+
lastEvent: Date.now(),
|
|
42
|
+
errorCount: 0,
|
|
43
|
+
lastError: undefined,
|
|
44
|
+
callbacks: new Set([callback]),
|
|
45
|
+
config: { ...this.defaultConfig },
|
|
46
|
+
};
|
|
47
|
+
this.watchers.set(path, entry);
|
|
48
|
+
await this.initializeWatcher(entry);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
this.logger?.error(`Live Config: Failed to watch file ${path}: ${error.message}`);
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Stop watching a file
|
|
57
|
+
* Resource cleanup
|
|
58
|
+
*/
|
|
59
|
+
async unwatchFile(path) {
|
|
60
|
+
const entry = this.watchers.get(path);
|
|
61
|
+
if (!entry)
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
if (entry.watcher) {
|
|
65
|
+
entry.watcher.unwatch(path);
|
|
66
|
+
}
|
|
67
|
+
this.watchers.delete(path);
|
|
68
|
+
this.logger?.info(`Live Config: Stopped watching file: ${path}`);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
this.logger?.warn(`Live Config: Error unwatching file ${path}: ${error.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get watcher status
|
|
76
|
+
* Maps to FR-012: Handle watcher initialization failures
|
|
77
|
+
*/
|
|
78
|
+
getWatcherStatus(path) {
|
|
79
|
+
const entry = this.watchers.get(path);
|
|
80
|
+
if (!entry)
|
|
81
|
+
return null;
|
|
82
|
+
return {
|
|
83
|
+
isActive: entry.isActive,
|
|
84
|
+
path: entry.path,
|
|
85
|
+
method: entry.errorCount > 0
|
|
86
|
+
? "failed"
|
|
87
|
+
: entry.config.fallbackPolling
|
|
88
|
+
? "polling"
|
|
89
|
+
: "native",
|
|
90
|
+
errorCount: entry.errorCount,
|
|
91
|
+
lastError: entry.lastError,
|
|
92
|
+
lastEvent: entry.lastEvent > 0
|
|
93
|
+
? {
|
|
94
|
+
type: "change",
|
|
95
|
+
path: entry.path,
|
|
96
|
+
timestamp: entry.lastEvent,
|
|
97
|
+
}
|
|
98
|
+
: undefined,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get all watcher statuses
|
|
103
|
+
* For monitoring and debugging
|
|
104
|
+
*/
|
|
105
|
+
getAllWatcherStatuses() {
|
|
106
|
+
return Array.from(this.watchers.keys())
|
|
107
|
+
.map((path) => this.getWatcherStatus(path))
|
|
108
|
+
.filter((status) => status !== null);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Configure watcher behavior
|
|
112
|
+
* Runtime configuration updates
|
|
113
|
+
*/
|
|
114
|
+
updateConfig(config) {
|
|
115
|
+
this.defaultConfig = { ...this.defaultConfig, ...config };
|
|
116
|
+
// Update existing watchers with new config
|
|
117
|
+
for (const entry of this.watchers.values()) {
|
|
118
|
+
entry.config = { ...entry.config, ...config };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Cleanup all watchers
|
|
123
|
+
*/
|
|
124
|
+
async cleanup() {
|
|
125
|
+
const paths = Array.from(this.watchers.keys());
|
|
126
|
+
await Promise.all(paths.map((path) => this.unwatchFile(path)));
|
|
127
|
+
if (this.globalWatcher) {
|
|
128
|
+
await this.globalWatcher.close();
|
|
129
|
+
this.globalWatcher = null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async initializeWatcher(entry) {
|
|
133
|
+
try {
|
|
134
|
+
// Initialize global watcher if needed
|
|
135
|
+
if (!this.globalWatcher) {
|
|
136
|
+
this.globalWatcher = chokidar.watch([], {
|
|
137
|
+
persistent: true,
|
|
138
|
+
ignoreInitial: true,
|
|
139
|
+
awaitWriteFinish: {
|
|
140
|
+
stabilityThreshold: entry.config.stabilityThreshold,
|
|
141
|
+
pollInterval: entry.config.pollInterval,
|
|
142
|
+
},
|
|
143
|
+
usePolling: entry.config.fallbackPolling,
|
|
144
|
+
interval: entry.config.pollInterval,
|
|
145
|
+
});
|
|
146
|
+
this.setupGlobalWatcherEvents();
|
|
147
|
+
}
|
|
148
|
+
// Add path to global watcher
|
|
149
|
+
this.globalWatcher.add(entry.path);
|
|
150
|
+
entry.watcher = this.globalWatcher;
|
|
151
|
+
entry.isActive = true;
|
|
152
|
+
entry.errorCount = 0;
|
|
153
|
+
this.logger?.info(`Live Config: Started watching file: ${entry.path}`);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
entry.errorCount++;
|
|
157
|
+
entry.isActive = false;
|
|
158
|
+
entry.lastError = error.message;
|
|
159
|
+
this.logger?.error(`Live Config: Failed to initialize watcher for ${entry.path}: ${error.message}`);
|
|
160
|
+
// Try fallback polling if not already using it
|
|
161
|
+
if (!entry.config.fallbackPolling &&
|
|
162
|
+
entry.errorCount < entry.config.maxRetries) {
|
|
163
|
+
this.logger?.info(`Live Config: Attempting polling fallback for ${entry.path}`);
|
|
164
|
+
entry.config.fallbackPolling = true;
|
|
165
|
+
await this.initializeWatcher(entry);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
setupGlobalWatcherEvents() {
|
|
173
|
+
if (!this.globalWatcher)
|
|
174
|
+
return;
|
|
175
|
+
this.globalWatcher.on("change", (filePath, stats) => {
|
|
176
|
+
this.handleFileEvent("change", filePath, stats);
|
|
177
|
+
});
|
|
178
|
+
this.globalWatcher.on("add", (filePath, stats) => {
|
|
179
|
+
this.handleFileEvent("create", filePath, stats);
|
|
180
|
+
});
|
|
181
|
+
this.globalWatcher.on("unlink", (filePath) => {
|
|
182
|
+
this.handleFileEvent("delete", filePath);
|
|
183
|
+
});
|
|
184
|
+
this.globalWatcher.on("error", (err) => {
|
|
185
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
186
|
+
this.logger?.error(`Live Config: File watcher error: ${error.message}`);
|
|
187
|
+
this.emit("watcherError", error);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
handleFileEvent(type, filePath, stats) {
|
|
191
|
+
const entry = this.watchers.get(filePath);
|
|
192
|
+
if (!entry)
|
|
193
|
+
return;
|
|
194
|
+
const event = {
|
|
195
|
+
type,
|
|
196
|
+
path: filePath,
|
|
197
|
+
timestamp: Date.now(),
|
|
198
|
+
size: stats?.size,
|
|
199
|
+
};
|
|
200
|
+
entry.lastEvent = event.timestamp;
|
|
201
|
+
// Notify all callbacks for this file
|
|
202
|
+
for (const callback of entry.callbacks) {
|
|
203
|
+
try {
|
|
204
|
+
callback(event);
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
this.logger?.error(`Live Config: Error in file watch callback for ${filePath}: ${error.message}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
this.logger?.debug(`Live Config: File ${type} event for ${filePath}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
package/dist/services/hook.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Hook Services
|
|
2
|
+
* Hook Execution Services
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Provides hook command execution functionality and hook-specific configuration loading.
|
|
5
|
+
* This module focuses on hook execution while delegating general Wave configuration
|
|
6
|
+
* management to ConfigurationService.
|
|
6
7
|
*/
|
|
7
|
-
import { type HookExecutionContext, type HookExecutionResult, type HookExecutionOptions, type ExtendedHookExecutionContext
|
|
8
|
+
import { type HookExecutionContext, type HookExecutionResult, type HookExecutionOptions, type ExtendedHookExecutionContext } from "../types/hooks.js";
|
|
8
9
|
/**
|
|
9
10
|
* Execute a single hook command
|
|
10
11
|
*/
|
|
@@ -17,40 +18,4 @@ export declare function executeCommands(commands: string[], context: HookExecuti
|
|
|
17
18
|
* Validate command safety (basic checks)
|
|
18
19
|
*/
|
|
19
20
|
export declare function isCommandSafe(command: string): boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Get the user-specific hooks configuration file path
|
|
22
|
-
*/
|
|
23
|
-
export declare function getUserHooksConfigPath(): string;
|
|
24
|
-
/**
|
|
25
|
-
* Get the project-specific hooks configuration file path
|
|
26
|
-
*/
|
|
27
|
-
export declare function getProjectHooksConfigPath(workdir: string): string;
|
|
28
|
-
/**
|
|
29
|
-
* Load hooks configuration from a JSON file
|
|
30
|
-
*/
|
|
31
|
-
export declare function loadHooksConfigFromFile(filePath: string): PartialHookConfiguration | null;
|
|
32
|
-
/**
|
|
33
|
-
* Load user-specific hooks configuration
|
|
34
|
-
*/
|
|
35
|
-
export declare function loadUserHooksConfig(): PartialHookConfiguration | null;
|
|
36
|
-
/**
|
|
37
|
-
* Load project-specific hooks configuration
|
|
38
|
-
*/
|
|
39
|
-
export declare function loadProjectHooksConfig(workdir: string): PartialHookConfiguration | null;
|
|
40
|
-
/**
|
|
41
|
-
* Load and merge hooks configuration from both user and project sources
|
|
42
|
-
*/
|
|
43
|
-
export declare function loadMergedHooksConfig(workdir: string): PartialHookConfiguration | null;
|
|
44
|
-
/**
|
|
45
|
-
* Check if hooks configuration exists (user or project)
|
|
46
|
-
*/
|
|
47
|
-
export declare function hasHooksConfiguration(workdir: string): boolean;
|
|
48
|
-
/**
|
|
49
|
-
* Get hooks configuration information for debugging
|
|
50
|
-
*/
|
|
51
|
-
export declare function getHooksConfigurationInfo(workdir: string): {
|
|
52
|
-
hasUser: boolean;
|
|
53
|
-
hasProject: boolean;
|
|
54
|
-
paths: string[];
|
|
55
|
-
};
|
|
56
21
|
//# sourceMappingURL=hook.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;AAyE3B;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA4H9B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAchC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBtD"}
|
package/dist/services/hook.js
CHANGED
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Hook Services
|
|
2
|
+
* Hook Execution Services
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Provides hook command execution functionality and hook-specific configuration loading.
|
|
5
|
+
* This module focuses on hook execution while delegating general Wave configuration
|
|
6
|
+
* management to ConfigurationService.
|
|
6
7
|
*/
|
|
7
8
|
import { spawn } from "child_process";
|
|
8
|
-
import {
|
|
9
|
-
import { join } from "path";
|
|
10
|
-
import { homedir } from "os";
|
|
11
|
-
import { getSessionFilePath, isValidHookEvent, } from "../types/hooks.js";
|
|
9
|
+
import { generateSessionFilePath } from "./session.js";
|
|
12
10
|
// =============================================================================
|
|
13
11
|
// Hook Execution Functions
|
|
14
12
|
// =============================================================================
|
|
15
13
|
/**
|
|
16
14
|
* Build JSON input data for hook stdin
|
|
17
15
|
*/
|
|
18
|
-
function buildHookJsonInput(context) {
|
|
16
|
+
async function buildHookJsonInput(context) {
|
|
17
|
+
const workdir = context.cwd || context.projectDir || process.cwd();
|
|
18
|
+
let transcriptPath = context.transcriptPath;
|
|
19
|
+
if (!transcriptPath && context.sessionId) {
|
|
20
|
+
try {
|
|
21
|
+
transcriptPath = await generateSessionFilePath(context.sessionId, workdir);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
transcriptPath = "";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
19
27
|
const jsonInput = {
|
|
20
28
|
session_id: context.sessionId || "unknown",
|
|
21
|
-
transcript_path:
|
|
22
|
-
|
|
23
|
-
cwd: context.cwd || context.projectDir,
|
|
29
|
+
transcript_path: transcriptPath || "",
|
|
30
|
+
cwd: workdir,
|
|
24
31
|
hook_event_name: context.event,
|
|
25
32
|
};
|
|
26
33
|
// Add optional fields based on event type
|
|
@@ -39,6 +46,19 @@ function buildHookJsonInput(context) {
|
|
|
39
46
|
context.userPrompt !== undefined) {
|
|
40
47
|
jsonInput.user_prompt = context.userPrompt;
|
|
41
48
|
}
|
|
49
|
+
// Add subagent_type if present
|
|
50
|
+
if (context.subagentType !== undefined) {
|
|
51
|
+
jsonInput.subagent_type = context.subagentType;
|
|
52
|
+
}
|
|
53
|
+
// Add notification fields for Notification events
|
|
54
|
+
if (context.event === "Notification") {
|
|
55
|
+
if (context.message !== undefined) {
|
|
56
|
+
jsonInput.message = context.message;
|
|
57
|
+
}
|
|
58
|
+
if (context.notificationType !== undefined) {
|
|
59
|
+
jsonInput.notification_type = context.notificationType;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
42
62
|
return jsonInput;
|
|
43
63
|
}
|
|
44
64
|
/**
|
|
@@ -62,6 +82,17 @@ export async function executeCommand(command, context, options) {
|
|
|
62
82
|
timedOut: false,
|
|
63
83
|
};
|
|
64
84
|
}
|
|
85
|
+
// Prepare JSON input for hooks that need it
|
|
86
|
+
let jsonInput = null;
|
|
87
|
+
if ("sessionId" in context) {
|
|
88
|
+
try {
|
|
89
|
+
const hookJsonInput = await buildHookJsonInput(context);
|
|
90
|
+
jsonInput = JSON.stringify(hookJsonInput, null, 2);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Continue execution even if JSON input preparation fails
|
|
94
|
+
}
|
|
95
|
+
}
|
|
65
96
|
return new Promise((resolve) => {
|
|
66
97
|
let stdout = "";
|
|
67
98
|
let stderr = "";
|
|
@@ -74,7 +105,8 @@ export async function executeCommand(command, context, options) {
|
|
|
74
105
|
stdio: ["pipe", "pipe", "pipe"],
|
|
75
106
|
cwd: context.projectDir,
|
|
76
107
|
env: {
|
|
77
|
-
...process.env,
|
|
108
|
+
...process.env, // Environment variables from process.env
|
|
109
|
+
...("env" in context ? context.env || {} : {}), // Additional environment variables from configuration (if ExtendedHookExecutionContext)
|
|
78
110
|
HOOK_EVENT: context.event,
|
|
79
111
|
HOOK_TOOL_NAME: context.toolName || "",
|
|
80
112
|
HOOK_PROJECT_DIR: context.projectDir,
|
|
@@ -103,11 +135,10 @@ export async function executeCommand(command, context, options) {
|
|
|
103
135
|
stderr += data.toString();
|
|
104
136
|
});
|
|
105
137
|
}
|
|
106
|
-
// Send JSON input to stdin if we have
|
|
107
|
-
if (childProcess.stdin &&
|
|
138
|
+
// Send JSON input to stdin if we have prepared it
|
|
139
|
+
if (childProcess.stdin && jsonInput) {
|
|
108
140
|
try {
|
|
109
|
-
|
|
110
|
-
childProcess.stdin.write(JSON.stringify(jsonInput, null, 2));
|
|
141
|
+
childProcess.stdin.write(jsonInput);
|
|
111
142
|
childProcess.stdin.end();
|
|
112
143
|
}
|
|
113
144
|
catch {
|
|
@@ -181,96 +212,3 @@ export function isCommandSafe(command) {
|
|
|
181
212
|
];
|
|
182
213
|
return !dangerousPatterns.some((pattern) => pattern.test(trimmed.toLowerCase()));
|
|
183
214
|
}
|
|
184
|
-
// =============================================================================
|
|
185
|
-
// Hook Settings Functions
|
|
186
|
-
// =============================================================================
|
|
187
|
-
/**
|
|
188
|
-
* Get the user-specific hooks configuration file path
|
|
189
|
-
*/
|
|
190
|
-
export function getUserHooksConfigPath() {
|
|
191
|
-
return join(homedir(), ".wave", "settings.json");
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Get the project-specific hooks configuration file path
|
|
195
|
-
*/
|
|
196
|
-
export function getProjectHooksConfigPath(workdir) {
|
|
197
|
-
return join(workdir, ".wave", "settings.json");
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Load hooks configuration from a JSON file
|
|
201
|
-
*/
|
|
202
|
-
export function loadHooksConfigFromFile(filePath) {
|
|
203
|
-
if (!existsSync(filePath)) {
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
const content = readFileSync(filePath, "utf-8");
|
|
207
|
-
const config = JSON.parse(content);
|
|
208
|
-
// Validate basic structure
|
|
209
|
-
if (!config || typeof config !== "object" || !config.hooks) {
|
|
210
|
-
throw new Error(`Invalid hooks configuration structure in ${filePath}`);
|
|
211
|
-
}
|
|
212
|
-
return config.hooks;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Load user-specific hooks configuration
|
|
216
|
-
*/
|
|
217
|
-
export function loadUserHooksConfig() {
|
|
218
|
-
return loadHooksConfigFromFile(getUserHooksConfigPath());
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Load project-specific hooks configuration
|
|
222
|
-
*/
|
|
223
|
-
export function loadProjectHooksConfig(workdir) {
|
|
224
|
-
return loadHooksConfigFromFile(getProjectHooksConfigPath(workdir));
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Load and merge hooks configuration from both user and project sources
|
|
228
|
-
*/
|
|
229
|
-
export function loadMergedHooksConfig(workdir) {
|
|
230
|
-
const userConfig = loadUserHooksConfig();
|
|
231
|
-
const projectConfig = loadProjectHooksConfig(workdir);
|
|
232
|
-
// No configuration found
|
|
233
|
-
if (!userConfig && !projectConfig) {
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
// Only one configuration found
|
|
237
|
-
if (!userConfig)
|
|
238
|
-
return projectConfig;
|
|
239
|
-
if (!projectConfig)
|
|
240
|
-
return userConfig;
|
|
241
|
-
// Merge configurations (project overrides user)
|
|
242
|
-
const merged = {};
|
|
243
|
-
// Combine all hook events
|
|
244
|
-
const allEvents = new Set([
|
|
245
|
-
...Object.keys(userConfig),
|
|
246
|
-
...Object.keys(projectConfig),
|
|
247
|
-
]);
|
|
248
|
-
for (const event of allEvents) {
|
|
249
|
-
if (!isValidHookEvent(event))
|
|
250
|
-
continue;
|
|
251
|
-
const userEventConfigs = userConfig[event] || [];
|
|
252
|
-
const projectEventConfigs = projectConfig[event] || [];
|
|
253
|
-
// Project configurations take precedence
|
|
254
|
-
merged[event] = [...userEventConfigs, ...projectEventConfigs];
|
|
255
|
-
}
|
|
256
|
-
return merged;
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Check if hooks configuration exists (user or project)
|
|
260
|
-
*/
|
|
261
|
-
export function hasHooksConfiguration(workdir) {
|
|
262
|
-
return (existsSync(getUserHooksConfigPath()) ||
|
|
263
|
-
existsSync(getProjectHooksConfigPath(workdir)));
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Get hooks configuration information for debugging
|
|
267
|
-
*/
|
|
268
|
-
export function getHooksConfigurationInfo(workdir) {
|
|
269
|
-
const userPath = getUserHooksConfigPath();
|
|
270
|
-
const projectPath = getProjectHooksConfigPath(workdir);
|
|
271
|
-
return {
|
|
272
|
-
hasUser: existsSync(userPath),
|
|
273
|
-
hasProject: existsSync(projectPath),
|
|
274
|
-
paths: [userPath, projectPath],
|
|
275
|
-
};
|
|
276
|
-
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSONL file operations service
|
|
3
|
+
* Handles reading and writing JSONL (JSON Lines) session files for improved performance
|
|
4
|
+
*/
|
|
5
|
+
import type { Message } from "../types/index.js";
|
|
6
|
+
import type { SessionMessage, SessionFilename } from "../types/session.js";
|
|
7
|
+
/**
|
|
8
|
+
* JSONL write options
|
|
9
|
+
*/
|
|
10
|
+
export interface JsonlWriteOptions {
|
|
11
|
+
atomic?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* JSONL handler class for message persistence operations
|
|
15
|
+
*/
|
|
16
|
+
export declare class JsonlHandler {
|
|
17
|
+
private readonly defaultWriteOptions;
|
|
18
|
+
constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Create a new session file (simplified - no metadata header)
|
|
21
|
+
*/
|
|
22
|
+
createSession(filePath: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Append a single message to JSONL file
|
|
25
|
+
*/
|
|
26
|
+
appendMessage(filePath: string, message: Message): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Append multiple messages to JSONL file
|
|
29
|
+
*/
|
|
30
|
+
appendMessages(filePath: string, messages: Message[]): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Append messages to JSONL file
|
|
33
|
+
*/
|
|
34
|
+
append(filePath: string, messages: SessionMessage[], options?: JsonlWriteOptions): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Read all messages from JSONL file (simplified - no metadata handling)
|
|
37
|
+
*/
|
|
38
|
+
read(filePath: string): Promise<SessionMessage[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Get the last message from JSONL file using efficient file reading (simplified)
|
|
41
|
+
*/
|
|
42
|
+
getLastMessage(filePath: string): Promise<SessionMessage | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Validate messages before writing
|
|
45
|
+
*/
|
|
46
|
+
private validateMessages;
|
|
47
|
+
/**
|
|
48
|
+
* Ensure directory exists for the given file path
|
|
49
|
+
*/
|
|
50
|
+
private ensureDirectory;
|
|
51
|
+
/**
|
|
52
|
+
* Parse session metadata from filename
|
|
53
|
+
* @param filePath - Path to the session file
|
|
54
|
+
* @returns Parsed session filename metadata
|
|
55
|
+
*/
|
|
56
|
+
parseSessionFilename(filePath: string): SessionFilename;
|
|
57
|
+
/**
|
|
58
|
+
* Validate filename format
|
|
59
|
+
* @param filename - Filename to validate
|
|
60
|
+
* @returns True if valid, false otherwise
|
|
61
|
+
*/
|
|
62
|
+
isValidSessionFilename(filename: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Generate simple filename for sessions
|
|
65
|
+
* @param sessionId - UUID session identifier
|
|
66
|
+
* @param sessionType - Type of session ("main" or "subagent")
|
|
67
|
+
* @returns Generated filename
|
|
68
|
+
*/
|
|
69
|
+
generateSessionFilename(sessionId: string, sessionType: "main" | "subagent"): string;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=jsonlHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonlHandler.d.ts","sourceRoot":"","sources":["../../src/services/jsonlHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAEhC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA8B;;IAQlE;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpD;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAc1E;;OAEG;IACG,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EAAE,EAC1B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAyChB;;OAEG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAoCvD;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAgCtE;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAwBxB;;OAEG;YACW,eAAe;IAW7B;;;;OAIG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe;IA6BvD;;;;OAIG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAUjD;;;;;OAKG;IACH,uBAAuB,CACrB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,UAAU,GAC/B,MAAM;CAcV"}
|