wave-agent-sdk 0.0.1

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 (170) hide show
  1. package/README.md +32 -0
  2. package/dist/agent.d.ts +96 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +286 -0
  5. package/dist/hooks/executor.d.ts +56 -0
  6. package/dist/hooks/executor.d.ts.map +1 -0
  7. package/dist/hooks/executor.js +312 -0
  8. package/dist/hooks/index.d.ts +17 -0
  9. package/dist/hooks/index.d.ts.map +1 -0
  10. package/dist/hooks/index.js +14 -0
  11. package/dist/hooks/manager.d.ts +90 -0
  12. package/dist/hooks/manager.d.ts.map +1 -0
  13. package/dist/hooks/manager.js +395 -0
  14. package/dist/hooks/matcher.d.ts +49 -0
  15. package/dist/hooks/matcher.d.ts.map +1 -0
  16. package/dist/hooks/matcher.js +147 -0
  17. package/dist/hooks/settings.d.ts +46 -0
  18. package/dist/hooks/settings.d.ts.map +1 -0
  19. package/dist/hooks/settings.js +100 -0
  20. package/dist/hooks/types.d.ts +80 -0
  21. package/dist/hooks/types.d.ts.map +1 -0
  22. package/dist/hooks/types.js +59 -0
  23. package/dist/index.d.ts +16 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +20 -0
  26. package/dist/managers/aiManager.d.ts +61 -0
  27. package/dist/managers/aiManager.d.ts.map +1 -0
  28. package/dist/managers/aiManager.js +415 -0
  29. package/dist/managers/backgroundBashManager.d.ts +27 -0
  30. package/dist/managers/backgroundBashManager.d.ts.map +1 -0
  31. package/dist/managers/backgroundBashManager.js +166 -0
  32. package/dist/managers/bashManager.d.ts +20 -0
  33. package/dist/managers/bashManager.d.ts.map +1 -0
  34. package/dist/managers/bashManager.js +66 -0
  35. package/dist/managers/mcpManager.d.ts +63 -0
  36. package/dist/managers/mcpManager.d.ts.map +1 -0
  37. package/dist/managers/mcpManager.js +378 -0
  38. package/dist/managers/messageManager.d.ts +85 -0
  39. package/dist/managers/messageManager.d.ts.map +1 -0
  40. package/dist/managers/messageManager.js +265 -0
  41. package/dist/managers/skillManager.d.ts +59 -0
  42. package/dist/managers/skillManager.d.ts.map +1 -0
  43. package/dist/managers/skillManager.js +317 -0
  44. package/dist/managers/slashCommandManager.d.ts +77 -0
  45. package/dist/managers/slashCommandManager.d.ts.map +1 -0
  46. package/dist/managers/slashCommandManager.js +208 -0
  47. package/dist/managers/toolManager.d.ts +23 -0
  48. package/dist/managers/toolManager.d.ts.map +1 -0
  49. package/dist/managers/toolManager.js +79 -0
  50. package/dist/services/aiService.d.ts +28 -0
  51. package/dist/services/aiService.d.ts.map +1 -0
  52. package/dist/services/aiService.js +180 -0
  53. package/dist/services/memory.d.ts +8 -0
  54. package/dist/services/memory.d.ts.map +1 -0
  55. package/dist/services/memory.js +128 -0
  56. package/dist/services/session.d.ts +54 -0
  57. package/dist/services/session.d.ts.map +1 -0
  58. package/dist/services/session.js +196 -0
  59. package/dist/tools/bashTool.d.ts +14 -0
  60. package/dist/tools/bashTool.d.ts.map +1 -0
  61. package/dist/tools/bashTool.js +351 -0
  62. package/dist/tools/deleteFileTool.d.ts +6 -0
  63. package/dist/tools/deleteFileTool.d.ts.map +1 -0
  64. package/dist/tools/deleteFileTool.js +67 -0
  65. package/dist/tools/editTool.d.ts +6 -0
  66. package/dist/tools/editTool.d.ts.map +1 -0
  67. package/dist/tools/editTool.js +168 -0
  68. package/dist/tools/globTool.d.ts +6 -0
  69. package/dist/tools/globTool.d.ts.map +1 -0
  70. package/dist/tools/globTool.js +113 -0
  71. package/dist/tools/grepTool.d.ts +6 -0
  72. package/dist/tools/grepTool.d.ts.map +1 -0
  73. package/dist/tools/grepTool.js +268 -0
  74. package/dist/tools/lsTool.d.ts +6 -0
  75. package/dist/tools/lsTool.d.ts.map +1 -0
  76. package/dist/tools/lsTool.js +160 -0
  77. package/dist/tools/multiEditTool.d.ts +6 -0
  78. package/dist/tools/multiEditTool.d.ts.map +1 -0
  79. package/dist/tools/multiEditTool.js +222 -0
  80. package/dist/tools/readTool.d.ts +6 -0
  81. package/dist/tools/readTool.d.ts.map +1 -0
  82. package/dist/tools/readTool.js +136 -0
  83. package/dist/tools/types.d.ts +35 -0
  84. package/dist/tools/types.d.ts.map +1 -0
  85. package/dist/tools/types.js +4 -0
  86. package/dist/tools/writeTool.d.ts +6 -0
  87. package/dist/tools/writeTool.d.ts.map +1 -0
  88. package/dist/tools/writeTool.js +138 -0
  89. package/dist/types.d.ts +212 -0
  90. package/dist/types.d.ts.map +1 -0
  91. package/dist/types.js +13 -0
  92. package/dist/utils/bashHistory.d.ts +46 -0
  93. package/dist/utils/bashHistory.d.ts.map +1 -0
  94. package/dist/utils/bashHistory.js +236 -0
  95. package/dist/utils/commandArgumentParser.d.ts +34 -0
  96. package/dist/utils/commandArgumentParser.d.ts.map +1 -0
  97. package/dist/utils/commandArgumentParser.js +123 -0
  98. package/dist/utils/constants.d.ts +27 -0
  99. package/dist/utils/constants.d.ts.map +1 -0
  100. package/dist/utils/constants.js +28 -0
  101. package/dist/utils/convertMessagesForAPI.d.ts +9 -0
  102. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -0
  103. package/dist/utils/convertMessagesForAPI.js +189 -0
  104. package/dist/utils/customCommands.d.ts +14 -0
  105. package/dist/utils/customCommands.d.ts.map +1 -0
  106. package/dist/utils/customCommands.js +71 -0
  107. package/dist/utils/fileFilter.d.ts +26 -0
  108. package/dist/utils/fileFilter.d.ts.map +1 -0
  109. package/dist/utils/fileFilter.js +177 -0
  110. package/dist/utils/markdownParser.d.ts +27 -0
  111. package/dist/utils/markdownParser.d.ts.map +1 -0
  112. package/dist/utils/markdownParser.js +109 -0
  113. package/dist/utils/mcpUtils.d.ts +24 -0
  114. package/dist/utils/mcpUtils.d.ts.map +1 -0
  115. package/dist/utils/mcpUtils.js +51 -0
  116. package/dist/utils/messageOperations.d.ts +118 -0
  117. package/dist/utils/messageOperations.d.ts.map +1 -0
  118. package/dist/utils/messageOperations.js +334 -0
  119. package/dist/utils/path.d.ts +25 -0
  120. package/dist/utils/path.d.ts.map +1 -0
  121. package/dist/utils/path.js +109 -0
  122. package/dist/utils/skillParser.d.ts +18 -0
  123. package/dist/utils/skillParser.d.ts.map +1 -0
  124. package/dist/utils/skillParser.js +147 -0
  125. package/dist/utils/stringUtils.d.ts +13 -0
  126. package/dist/utils/stringUtils.d.ts.map +1 -0
  127. package/dist/utils/stringUtils.js +44 -0
  128. package/package.json +51 -0
  129. package/src/agent.ts +405 -0
  130. package/src/hooks/executor.ts +440 -0
  131. package/src/hooks/index.ts +52 -0
  132. package/src/hooks/manager.ts +618 -0
  133. package/src/hooks/matcher.ts +187 -0
  134. package/src/hooks/settings.ts +129 -0
  135. package/src/hooks/types.ts +169 -0
  136. package/src/index.ts +24 -0
  137. package/src/managers/aiManager.ts +573 -0
  138. package/src/managers/backgroundBashManager.ts +203 -0
  139. package/src/managers/bashManager.ts +97 -0
  140. package/src/managers/mcpManager.ts +493 -0
  141. package/src/managers/messageManager.ts +415 -0
  142. package/src/managers/skillManager.ts +404 -0
  143. package/src/managers/slashCommandManager.ts +293 -0
  144. package/src/managers/toolManager.ts +106 -0
  145. package/src/services/aiService.ts +252 -0
  146. package/src/services/memory.ts +149 -0
  147. package/src/services/session.ts +265 -0
  148. package/src/tools/bashTool.ts +402 -0
  149. package/src/tools/deleteFileTool.ts +81 -0
  150. package/src/tools/editTool.ts +192 -0
  151. package/src/tools/globTool.ts +135 -0
  152. package/src/tools/grepTool.ts +326 -0
  153. package/src/tools/lsTool.ts +187 -0
  154. package/src/tools/multiEditTool.ts +268 -0
  155. package/src/tools/readTool.ts +165 -0
  156. package/src/tools/types.ts +47 -0
  157. package/src/tools/writeTool.ts +163 -0
  158. package/src/types.ts +260 -0
  159. package/src/utils/bashHistory.ts +303 -0
  160. package/src/utils/commandArgumentParser.ts +153 -0
  161. package/src/utils/constants.ts +37 -0
  162. package/src/utils/convertMessagesForAPI.ts +236 -0
  163. package/src/utils/customCommands.ts +85 -0
  164. package/src/utils/fileFilter.ts +202 -0
  165. package/src/utils/markdownParser.ts +156 -0
  166. package/src/utils/mcpUtils.ts +81 -0
  167. package/src/utils/messageOperations.ts +506 -0
  168. package/src/utils/path.ts +118 -0
  169. package/src/utils/skillParser.ts +188 -0
  170. package/src/utils/stringUtils.ts +50 -0
@@ -0,0 +1,440 @@
1
+ /**
2
+ * Hook Command Executor
3
+ *
4
+ * Handles the execution of hook commands in isolated processes with proper
5
+ * timeout handling, environment variable injection, and cross-platform support.
6
+ */
7
+
8
+ import { spawn, type ChildProcess } from "child_process";
9
+ import {
10
+ type HookExecutionContext,
11
+ type HookExecutionResult,
12
+ type HookExecutionOptions,
13
+ type ExtendedHookExecutionContext,
14
+ type HookJsonInput,
15
+ getSessionFilePath,
16
+ } from "./types.js";
17
+ import type { Logger } from "../types.js";
18
+
19
+ /**
20
+ * Build JSON input data for hook stdin
21
+ */
22
+ function buildHookJsonInput(
23
+ context: ExtendedHookExecutionContext,
24
+ ): HookJsonInput {
25
+ const jsonInput: HookJsonInput = {
26
+ session_id: context.sessionId || "unknown",
27
+ transcript_path:
28
+ context.transcriptPath ||
29
+ (context.sessionId ? getSessionFilePath(context.sessionId) : ""),
30
+ cwd: context.cwd || context.projectDir,
31
+ hook_event_name: context.event,
32
+ };
33
+
34
+ // Add optional fields based on event type
35
+ if (context.event === "PreToolUse" || context.event === "PostToolUse") {
36
+ if (context.toolName) {
37
+ jsonInput.tool_name = context.toolName;
38
+ }
39
+ if (context.toolInput !== undefined) {
40
+ jsonInput.tool_input = context.toolInput;
41
+ }
42
+ }
43
+
44
+ if (context.event === "PostToolUse" && context.toolResponse !== undefined) {
45
+ jsonInput.tool_response = context.toolResponse;
46
+ }
47
+
48
+ if (
49
+ context.event === "UserPromptSubmit" &&
50
+ context.userPrompt !== undefined
51
+ ) {
52
+ jsonInput.user_prompt = context.userPrompt;
53
+ }
54
+
55
+ return jsonInput;
56
+ }
57
+
58
+ export interface IHookExecutor {
59
+ // Execute a single hook command
60
+ executeCommand(
61
+ command: string,
62
+ context: HookExecutionContext | ExtendedHookExecutionContext,
63
+ options?: HookExecutionOptions,
64
+ ): Promise<HookExecutionResult>;
65
+
66
+ // Execute multiple commands in sequence
67
+ executeCommands(
68
+ commands: string[],
69
+ context: HookExecutionContext | ExtendedHookExecutionContext,
70
+ options?: HookExecutionOptions,
71
+ ): Promise<HookExecutionResult[]>;
72
+
73
+ // Validate command safety
74
+ isCommandSafe(command: string): boolean;
75
+ }
76
+
77
+ export class HookExecutor implements IHookExecutor {
78
+ private readonly defaultTimeout = 10000; // 10 seconds
79
+ private readonly maxTimeout = 300000; // 5 minutes
80
+ private readonly logger?: Logger;
81
+ private readonly skipExecution: boolean;
82
+
83
+ constructor(logger?: Logger, options?: { skipExecution?: boolean }) {
84
+ this.logger = logger;
85
+ // Skip execution in test environment unless we're specifically testing the executor
86
+ this.skipExecution =
87
+ options?.skipExecution ??
88
+ ((process.env.NODE_ENV === "test" || process.env.VITEST === "true") &&
89
+ !process.env.WAVE_TEST_HOOKS_EXECUTION);
90
+ }
91
+
92
+ /**
93
+ * Execute a single hook command in an isolated process
94
+ */
95
+ async executeCommand(
96
+ command: string,
97
+ context: HookExecutionContext | ExtendedHookExecutionContext,
98
+ options: HookExecutionOptions = {},
99
+ ): Promise<HookExecutionResult> {
100
+ const startTime = Date.now();
101
+ const timeout = Math.min(
102
+ options.timeout ?? this.defaultTimeout,
103
+ this.maxTimeout,
104
+ );
105
+ const cwd = options.cwd ?? context.projectDir;
106
+
107
+ // Skip command execution in test environment (unless specifically testing hooks)
108
+ if (this.skipExecution) {
109
+ this.logger?.debug(`[Hook] Skipping command execution: ${command}`);
110
+ return {
111
+ success: true,
112
+ exitCode: 0,
113
+ stdout: "Test environment: command execution skipped",
114
+ duration: Date.now() - startTime,
115
+ timedOut: false,
116
+ };
117
+ }
118
+
119
+ // Log hook execution start
120
+ this.logger?.debug(`[Hook] Executing ${context.event} hook: ${command}`);
121
+ this.logger?.debug(
122
+ `[Hook] Context: event=${context.event}, tool=${context.toolName || "N/A"}, cwd=${cwd}`,
123
+ );
124
+
125
+ // Validate command safety
126
+ if (!this.isCommandSafe(command)) {
127
+ const error = "Command contains potentially unsafe characters";
128
+ this.logger?.warn(`[Hook] Command safety validation failed: ${error}`);
129
+ return {
130
+ success: false,
131
+ exitCode: -1,
132
+ stderr: error,
133
+ duration: Date.now() - startTime,
134
+ timedOut: false,
135
+ };
136
+ }
137
+
138
+ // Prepare environment variables
139
+ const env = this.buildEnvironment(context);
140
+
141
+ // Resolve command with environment variables
142
+ const resolvedCommand = this.resolveEnvironmentVariables(command, env);
143
+
144
+ // Prepare JSON input for stdin (if extended context is provided)
145
+ const isExtendedContext =
146
+ "sessionId" in context ||
147
+ "toolInput" in context ||
148
+ "toolResponse" in context ||
149
+ "userPrompt" in context;
150
+ const jsonInput = isExtendedContext
151
+ ? buildHookJsonInput(context as ExtendedHookExecutionContext)
152
+ : null;
153
+
154
+ this.logger?.debug(`[Hook] Resolved command: ${resolvedCommand}`);
155
+ if (jsonInput) {
156
+ this.logger?.debug(`[Hook] JSON input: ${JSON.stringify(jsonInput)}`);
157
+ }
158
+
159
+ return new Promise((resolve) => {
160
+ let stdout = "";
161
+ let stderr = "";
162
+ let timedOut = false;
163
+ let childProcess: ChildProcess;
164
+
165
+ // Setup timeout
166
+ const timeoutId = setTimeout(() => {
167
+ timedOut = true;
168
+ this.logger?.warn(
169
+ `[Hook] Command timed out after ${timeout}ms: ${resolvedCommand}`,
170
+ );
171
+ if (childProcess && !childProcess.killed) {
172
+ childProcess.kill("SIGTERM");
173
+ // Force kill after 5 seconds if SIGTERM doesn't work
174
+ setTimeout(() => {
175
+ if (childProcess && !childProcess.killed) {
176
+ this.logger?.warn(
177
+ `[Hook] Force killing process: ${resolvedCommand}`,
178
+ );
179
+ childProcess.kill("SIGKILL");
180
+ }
181
+ }, 5000);
182
+ }
183
+ }, timeout);
184
+
185
+ try {
186
+ // Execute command using shell for cross-platform compatibility
187
+ const shell = process.platform === "win32" ? "cmd.exe" : "/bin/sh";
188
+ const shellArgs = process.platform === "win32" ? ["/c"] : ["-c"];
189
+
190
+ childProcess = spawn(shell, [...shellArgs, resolvedCommand], {
191
+ cwd,
192
+ env,
193
+ stdio: "pipe",
194
+ windowsHide: true, // Hide console window on Windows
195
+ });
196
+
197
+ this.logger?.debug(`[Hook] Process started (PID: ${childProcess.pid})`);
198
+
199
+ // Write JSON input to stdin if available
200
+ if (jsonInput && childProcess.stdin) {
201
+ try {
202
+ const jsonString = JSON.stringify(jsonInput, null, 2);
203
+ childProcess.stdin.write(jsonString);
204
+ childProcess.stdin.end();
205
+ this.logger?.debug(`[Hook] JSON input written to stdin`);
206
+ } catch (error) {
207
+ this.logger?.warn(`[Hook] Failed to write JSON to stdin: ${error}`);
208
+ }
209
+ }
210
+
211
+ // Collect stdout
212
+ childProcess.stdout?.on("data", (data) => {
213
+ stdout += data.toString();
214
+ });
215
+
216
+ // Collect stderr
217
+ childProcess.stderr?.on("data", (data) => {
218
+ stderr += data.toString();
219
+ });
220
+
221
+ // Handle process completion
222
+ childProcess.on("close", (exitCode) => {
223
+ clearTimeout(timeoutId);
224
+
225
+ const duration = Date.now() - startTime;
226
+ const success = !timedOut && exitCode === 0;
227
+
228
+ // Log execution result
229
+ if (success) {
230
+ this.logger?.debug(
231
+ `[Hook] Command completed successfully in ${duration}ms (exit code: ${exitCode})`,
232
+ );
233
+ } else {
234
+ this.logger?.warn(
235
+ `[Hook] Command failed in ${duration}ms (exit code: ${exitCode}, timed out: ${timedOut})`,
236
+ );
237
+ if (stderr) {
238
+ this.logger?.warn(`[Hook] stderr: ${stderr.trim()}`);
239
+ }
240
+ }
241
+
242
+ if (stdout && stdout.trim()) {
243
+ this.logger?.debug(`[Hook] stdout: ${stdout.trim()}`);
244
+ }
245
+
246
+ resolve({
247
+ success,
248
+ exitCode: exitCode ?? undefined,
249
+ stdout: stdout.trim() || undefined,
250
+ stderr: stderr.trim() || undefined,
251
+ duration,
252
+ timedOut,
253
+ });
254
+ });
255
+
256
+ // Handle process errors
257
+ childProcess.on("error", (error) => {
258
+ clearTimeout(timeoutId);
259
+
260
+ const duration = Date.now() - startTime;
261
+
262
+ this.logger?.error(
263
+ `[Hook] Process error in ${duration}ms: ${error.message}`,
264
+ );
265
+
266
+ resolve({
267
+ success: false,
268
+ stderr: error.message,
269
+ duration,
270
+ timedOut,
271
+ });
272
+ });
273
+ } catch (error) {
274
+ clearTimeout(timeoutId);
275
+
276
+ const duration = Date.now() - startTime;
277
+ const errorMessage =
278
+ error instanceof Error ? error.message : "Unknown execution error";
279
+
280
+ this.logger?.error(
281
+ `[Hook] Execution error in ${duration}ms: ${errorMessage}`,
282
+ );
283
+
284
+ resolve({
285
+ success: false,
286
+ stderr: errorMessage,
287
+ duration,
288
+ timedOut,
289
+ });
290
+ }
291
+ });
292
+ }
293
+
294
+ /**
295
+ * Execute multiple commands in sequence
296
+ * Stops on first failure unless configured otherwise
297
+ */
298
+ async executeCommands(
299
+ commands: string[],
300
+ context: HookExecutionContext | ExtendedHookExecutionContext,
301
+ options: HookExecutionOptions = {},
302
+ ): Promise<HookExecutionResult[]> {
303
+ const results: HookExecutionResult[] = [];
304
+
305
+ this.logger?.debug(
306
+ `[Hook] Executing ${commands.length} commands in sequence for ${context.event} event`,
307
+ );
308
+
309
+ for (let i = 0; i < commands.length; i++) {
310
+ const command = commands[i];
311
+ this.logger?.debug(
312
+ `[Hook] Command ${i + 1}/${commands.length}: ${command}`,
313
+ );
314
+
315
+ try {
316
+ const result = await this.executeCommand(command, context, options);
317
+ results.push(result);
318
+
319
+ // Stop on first failure to prevent cascading issues
320
+ if (!result.success) {
321
+ this.logger?.warn(
322
+ `[Hook] Stopping sequence at command ${i + 1} due to failure`,
323
+ );
324
+ break;
325
+ }
326
+ } catch (error) {
327
+ // This shouldn't happen as executeCommand handles all errors,
328
+ // but include defensive handling
329
+ const errorMessage =
330
+ error instanceof Error ? error.message : "Unknown error";
331
+ this.logger?.error(
332
+ `[Hook] Unexpected error in command ${i + 1}: ${errorMessage}`,
333
+ );
334
+
335
+ results.push({
336
+ success: false,
337
+ stderr: errorMessage,
338
+ duration: 0,
339
+ timedOut: false,
340
+ });
341
+ break;
342
+ }
343
+ }
344
+
345
+ const successCount = results.filter((r) => r.success).length;
346
+ this.logger?.debug(
347
+ `[Hook] Completed sequence: ${successCount}/${results.length} commands succeeded`,
348
+ );
349
+
350
+ return results;
351
+ }
352
+
353
+ /**
354
+ * Validate command safety to prevent injection attacks
355
+ */
356
+ isCommandSafe(command: string): boolean {
357
+ if (!command || typeof command !== "string") return false;
358
+
359
+ // Command cannot be empty
360
+ const trimmed = command.trim();
361
+ if (trimmed.length === 0) return false;
362
+
363
+ // Basic safety checks - these could be expanded based on security requirements
364
+ const dangerousPatterns = [
365
+ /\b(rm\s+-rf\s+\/|rm\s+-rf\s+~|rm\s+-rf\s+\*)/i, // Dangerous rm commands
366
+ /\bdd\s+if=/i, // dd commands that could be destructive
367
+ /:\(\)\{.*\}/, // Fork bomb patterns
368
+ /\beval\s*[(\s]/i, // Code evaluation
369
+ /\bexec\s+/i, // Process execution in shells
370
+ ];
371
+
372
+ // Check for obviously dangerous patterns
373
+ if (dangerousPatterns.some((pattern) => pattern.test(trimmed))) {
374
+ return false;
375
+ }
376
+
377
+ return true;
378
+ }
379
+
380
+ /**
381
+ * Build environment variables for hook execution
382
+ */
383
+ private buildEnvironment(context: HookExecutionContext): NodeJS.ProcessEnv {
384
+ return {
385
+ ...process.env, // Inherit parent environment
386
+ WAVE_PROJECT_DIR: context.projectDir,
387
+ };
388
+ }
389
+
390
+ /**
391
+ * Resolve environment variables in command string
392
+ */
393
+ private resolveEnvironmentVariables(
394
+ command: string,
395
+ env: NodeJS.ProcessEnv,
396
+ ): string {
397
+ let resolved = command;
398
+
399
+ // Replace $VAR and ${VAR} patterns
400
+ Object.entries(env).forEach(([key, value]) => {
401
+ if (value !== undefined) {
402
+ // Handle both $VAR and ${VAR} syntax
403
+ const dollarPattern = new RegExp(`\\$${key}\\b`, "g");
404
+ const bracesPattern = new RegExp(`\\$\\{${key}\\}`, "g");
405
+
406
+ resolved = resolved.replace(dollarPattern, value);
407
+ resolved = resolved.replace(bracesPattern, value);
408
+ }
409
+ });
410
+
411
+ return resolved;
412
+ }
413
+
414
+ /**
415
+ * Get process statistics for monitoring
416
+ */
417
+ getExecutionStats(): {
418
+ platform: NodeJS.Platform;
419
+ defaultTimeout: number;
420
+ maxTimeout: number;
421
+ } {
422
+ return {
423
+ platform: process.platform,
424
+ defaultTimeout: this.defaultTimeout,
425
+ maxTimeout: this.maxTimeout,
426
+ };
427
+ }
428
+
429
+ /**
430
+ * Test if the executor can run commands on this platform
431
+ */
432
+ isSupported(): boolean {
433
+ try {
434
+ // Try to detect shell availability - basic check could be enhanced with actual shell testing
435
+ return true;
436
+ } catch {
437
+ return false;
438
+ }
439
+ }
440
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Hooks System Entry Point
3
+ *
4
+ * Exports all public APIs for the Wave Code hooks system.
5
+ * This module provides a clean interface for integrating hooks
6
+ * into AI workflows and CLI applications.
7
+ */
8
+
9
+ // Core types and interfaces
10
+ export type {
11
+ HookEvent,
12
+ HookCommand,
13
+ HookEventConfig,
14
+ HookConfiguration,
15
+ HookExecutionContext,
16
+ HookExecutionResult,
17
+ HookExecutionOptions,
18
+ ValidationResult,
19
+ HookEnvironment,
20
+ } from "./types.js";
21
+
22
+ // Type guards and utility functions
23
+ export {
24
+ isValidHookEvent,
25
+ isValidHookCommand,
26
+ isValidHookEventConfig,
27
+ HookExecutionError,
28
+ HookConfigurationError,
29
+ } from "./types.js";
30
+
31
+ // Pattern matching functionality
32
+ export type { IHookMatcher } from "./matcher.js";
33
+ export { HookMatcher } from "./matcher.js";
34
+
35
+ // Command execution functionality
36
+ export type { IHookExecutor } from "./executor.js";
37
+ export { HookExecutor } from "./executor.js";
38
+
39
+ // Hook management and orchestration
40
+ export type { IHookManager } from "./manager.js";
41
+ export { HookManager } from "./manager.js";
42
+
43
+ // Settings and configuration loading
44
+ export {
45
+ getUserHooksConfigPath,
46
+ getProjectHooksConfigPath,
47
+ loadUserHooksConfig,
48
+ loadProjectHooksConfig,
49
+ loadMergedHooksConfig,
50
+ hasHooksConfiguration,
51
+ getHooksConfigurationInfo,
52
+ } from "./settings.js";