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.
Files changed (240) hide show
  1. package/dist/agent.d.ts +105 -24
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +438 -53
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +4 -0
  7. package/dist/managers/aiManager.d.ts +18 -7
  8. package/dist/managers/aiManager.d.ts.map +1 -1
  9. package/dist/managers/aiManager.js +254 -142
  10. package/dist/managers/backgroundBashManager.d.ts.map +1 -1
  11. package/dist/managers/backgroundBashManager.js +11 -9
  12. package/dist/managers/hookManager.d.ts +6 -6
  13. package/dist/managers/hookManager.d.ts.map +1 -1
  14. package/dist/managers/hookManager.js +81 -39
  15. package/dist/managers/liveConfigManager.d.ts +95 -0
  16. package/dist/managers/liveConfigManager.d.ts.map +1 -0
  17. package/dist/managers/liveConfigManager.js +442 -0
  18. package/dist/managers/lspManager.d.ts +43 -0
  19. package/dist/managers/lspManager.d.ts.map +1 -0
  20. package/dist/managers/lspManager.js +326 -0
  21. package/dist/managers/messageManager.d.ts +41 -24
  22. package/dist/managers/messageManager.d.ts.map +1 -1
  23. package/dist/managers/messageManager.js +184 -73
  24. package/dist/managers/permissionManager.d.ts +66 -0
  25. package/dist/managers/permissionManager.d.ts.map +1 -0
  26. package/dist/managers/permissionManager.js +208 -0
  27. package/dist/managers/skillManager.d.ts +1 -0
  28. package/dist/managers/skillManager.d.ts.map +1 -1
  29. package/dist/managers/skillManager.js +2 -1
  30. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  31. package/dist/managers/slashCommandManager.js +4 -2
  32. package/dist/managers/subagentManager.d.ts +42 -6
  33. package/dist/managers/subagentManager.d.ts.map +1 -1
  34. package/dist/managers/subagentManager.js +213 -62
  35. package/dist/managers/toolManager.d.ts +38 -1
  36. package/dist/managers/toolManager.d.ts.map +1 -1
  37. package/dist/managers/toolManager.js +66 -2
  38. package/dist/services/aiService.d.ts +15 -5
  39. package/dist/services/aiService.d.ts.map +1 -1
  40. package/dist/services/aiService.js +446 -77
  41. package/dist/services/configurationService.d.ts +116 -0
  42. package/dist/services/configurationService.d.ts.map +1 -0
  43. package/dist/services/configurationService.js +585 -0
  44. package/dist/services/fileWatcher.d.ts +69 -0
  45. package/dist/services/fileWatcher.d.ts.map +1 -0
  46. package/dist/services/fileWatcher.js +212 -0
  47. package/dist/services/hook.d.ts +5 -40
  48. package/dist/services/hook.d.ts.map +1 -1
  49. package/dist/services/hook.js +47 -109
  50. package/dist/services/jsonlHandler.d.ts +71 -0
  51. package/dist/services/jsonlHandler.d.ts.map +1 -0
  52. package/dist/services/jsonlHandler.js +236 -0
  53. package/dist/services/memory.d.ts.map +1 -1
  54. package/dist/services/memory.js +33 -11
  55. package/dist/services/session.d.ts +116 -52
  56. package/dist/services/session.d.ts.map +1 -1
  57. package/dist/services/session.js +415 -143
  58. package/dist/tools/bashTool.d.ts.map +1 -1
  59. package/dist/tools/bashTool.js +77 -17
  60. package/dist/tools/deleteFileTool.d.ts.map +1 -1
  61. package/dist/tools/deleteFileTool.js +27 -1
  62. package/dist/tools/editTool.d.ts.map +1 -1
  63. package/dist/tools/editTool.js +33 -8
  64. package/dist/tools/lspTool.d.ts +6 -0
  65. package/dist/tools/lspTool.d.ts.map +1 -0
  66. package/dist/tools/lspTool.js +589 -0
  67. package/dist/tools/multiEditTool.d.ts.map +1 -1
  68. package/dist/tools/multiEditTool.js +30 -10
  69. package/dist/tools/readTool.d.ts.map +1 -1
  70. package/dist/tools/readTool.js +113 -3
  71. package/dist/tools/skillTool.js +2 -2
  72. package/dist/tools/todoWriteTool.d.ts.map +1 -1
  73. package/dist/tools/todoWriteTool.js +23 -0
  74. package/dist/tools/types.d.ts +11 -8
  75. package/dist/tools/types.d.ts.map +1 -1
  76. package/dist/tools/writeTool.d.ts.map +1 -1
  77. package/dist/tools/writeTool.js +30 -15
  78. package/dist/types/commands.d.ts +4 -1
  79. package/dist/types/commands.d.ts.map +1 -1
  80. package/dist/types/config.d.ts +4 -0
  81. package/dist/types/config.d.ts.map +1 -1
  82. package/dist/types/configuration.d.ts +69 -0
  83. package/dist/types/configuration.d.ts.map +1 -0
  84. package/dist/types/configuration.js +8 -0
  85. package/dist/types/core.d.ts +45 -0
  86. package/dist/types/core.d.ts.map +1 -1
  87. package/dist/types/environment.d.ts +83 -0
  88. package/dist/types/environment.d.ts.map +1 -0
  89. package/dist/types/environment.js +21 -0
  90. package/dist/types/fileSearch.d.ts +5 -0
  91. package/dist/types/fileSearch.d.ts.map +1 -0
  92. package/dist/types/fileSearch.js +1 -0
  93. package/dist/types/hooks.d.ts +18 -3
  94. package/dist/types/hooks.d.ts.map +1 -1
  95. package/dist/types/hooks.js +8 -8
  96. package/dist/types/index.d.ts +7 -0
  97. package/dist/types/index.d.ts.map +1 -1
  98. package/dist/types/index.js +7 -0
  99. package/dist/types/lsp.d.ts +90 -0
  100. package/dist/types/lsp.d.ts.map +1 -0
  101. package/dist/types/lsp.js +4 -0
  102. package/dist/types/messaging.d.ts +19 -12
  103. package/dist/types/messaging.d.ts.map +1 -1
  104. package/dist/types/permissions.d.ts +35 -0
  105. package/dist/types/permissions.d.ts.map +1 -0
  106. package/dist/types/permissions.js +12 -0
  107. package/dist/types/session.d.ts +15 -0
  108. package/dist/types/session.d.ts.map +1 -0
  109. package/dist/types/session.js +7 -0
  110. package/dist/types/skills.d.ts +1 -0
  111. package/dist/types/skills.d.ts.map +1 -1
  112. package/dist/types/tools.d.ts +35 -0
  113. package/dist/types/tools.d.ts.map +1 -0
  114. package/dist/types/tools.js +4 -0
  115. package/dist/utils/abortUtils.d.ts +34 -0
  116. package/dist/utils/abortUtils.d.ts.map +1 -0
  117. package/dist/utils/abortUtils.js +92 -0
  118. package/dist/utils/bashHistory.d.ts +4 -0
  119. package/dist/utils/bashHistory.d.ts.map +1 -1
  120. package/dist/utils/bashHistory.js +48 -30
  121. package/dist/utils/builtinSubagents.d.ts +7 -0
  122. package/dist/utils/builtinSubagents.d.ts.map +1 -0
  123. package/dist/utils/builtinSubagents.js +65 -0
  124. package/dist/utils/cacheControlUtils.d.ts +96 -0
  125. package/dist/utils/cacheControlUtils.d.ts.map +1 -0
  126. package/dist/utils/cacheControlUtils.js +324 -0
  127. package/dist/utils/commandPathResolver.d.ts +52 -0
  128. package/dist/utils/commandPathResolver.d.ts.map +1 -0
  129. package/dist/utils/commandPathResolver.js +145 -0
  130. package/dist/utils/configPaths.d.ts +85 -0
  131. package/dist/utils/configPaths.d.ts.map +1 -0
  132. package/dist/utils/configPaths.js +121 -0
  133. package/dist/utils/constants.d.ts +1 -13
  134. package/dist/utils/constants.d.ts.map +1 -1
  135. package/dist/utils/constants.js +2 -14
  136. package/dist/utils/convertMessagesForAPI.d.ts +2 -1
  137. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  138. package/dist/utils/convertMessagesForAPI.js +39 -18
  139. package/dist/utils/customCommands.d.ts.map +1 -1
  140. package/dist/utils/customCommands.js +66 -21
  141. package/dist/utils/fileSearch.d.ts +14 -0
  142. package/dist/utils/fileSearch.d.ts.map +1 -0
  143. package/dist/utils/fileSearch.js +88 -0
  144. package/dist/utils/fileUtils.d.ts +27 -0
  145. package/dist/utils/fileUtils.d.ts.map +1 -0
  146. package/dist/utils/fileUtils.js +145 -0
  147. package/dist/utils/globalLogger.d.ts +88 -0
  148. package/dist/utils/globalLogger.d.ts.map +1 -0
  149. package/dist/utils/globalLogger.js +120 -0
  150. package/dist/utils/largeOutputHandler.d.ts +15 -0
  151. package/dist/utils/largeOutputHandler.d.ts.map +1 -0
  152. package/dist/utils/largeOutputHandler.js +40 -0
  153. package/dist/utils/markdownParser.d.ts.map +1 -1
  154. package/dist/utils/markdownParser.js +1 -17
  155. package/dist/utils/mcpUtils.d.ts.map +1 -1
  156. package/dist/utils/mcpUtils.js +25 -3
  157. package/dist/utils/messageOperations.d.ts +20 -18
  158. package/dist/utils/messageOperations.d.ts.map +1 -1
  159. package/dist/utils/messageOperations.js +30 -38
  160. package/dist/utils/pathEncoder.d.ts +108 -0
  161. package/dist/utils/pathEncoder.d.ts.map +1 -0
  162. package/dist/utils/pathEncoder.js +279 -0
  163. package/dist/utils/subagentParser.d.ts +2 -2
  164. package/dist/utils/subagentParser.d.ts.map +1 -1
  165. package/dist/utils/subagentParser.js +12 -8
  166. package/dist/utils/tokenCalculation.d.ts +26 -0
  167. package/dist/utils/tokenCalculation.d.ts.map +1 -0
  168. package/dist/utils/tokenCalculation.js +36 -0
  169. package/dist/utils/tokenEstimator.d.ts +39 -0
  170. package/dist/utils/tokenEstimator.d.ts.map +1 -0
  171. package/dist/utils/tokenEstimator.js +55 -0
  172. package/package.json +6 -6
  173. package/src/agent.ts +586 -78
  174. package/src/index.ts +4 -0
  175. package/src/managers/aiManager.ts +341 -192
  176. package/src/managers/backgroundBashManager.ts +11 -9
  177. package/src/managers/hookManager.ts +102 -54
  178. package/src/managers/liveConfigManager.ts +634 -0
  179. package/src/managers/lspManager.ts +434 -0
  180. package/src/managers/messageManager.ts +258 -121
  181. package/src/managers/permissionManager.ts +276 -0
  182. package/src/managers/skillManager.ts +3 -1
  183. package/src/managers/slashCommandManager.ts +5 -3
  184. package/src/managers/subagentManager.ts +295 -76
  185. package/src/managers/toolManager.ts +95 -3
  186. package/src/services/aiService.ts +656 -84
  187. package/src/services/configurationService.ts +762 -0
  188. package/src/services/fileWatcher.ts +300 -0
  189. package/src/services/hook.ts +54 -144
  190. package/src/services/jsonlHandler.ts +303 -0
  191. package/src/services/memory.ts +34 -11
  192. package/src/services/session.ts +522 -173
  193. package/src/tools/bashTool.ts +94 -20
  194. package/src/tools/deleteFileTool.ts +38 -1
  195. package/src/tools/editTool.ts +44 -9
  196. package/src/tools/lspTool.ts +760 -0
  197. package/src/tools/multiEditTool.ts +41 -11
  198. package/src/tools/readTool.ts +127 -3
  199. package/src/tools/skillTool.ts +2 -2
  200. package/src/tools/todoWriteTool.ts +33 -1
  201. package/src/tools/types.ts +15 -9
  202. package/src/tools/writeTool.ts +43 -16
  203. package/src/types/commands.ts +6 -1
  204. package/src/types/config.ts +5 -0
  205. package/src/types/configuration.ts +73 -0
  206. package/src/types/core.ts +55 -0
  207. package/src/types/environment.ts +104 -0
  208. package/src/types/fileSearch.ts +4 -0
  209. package/src/types/hooks.ts +32 -16
  210. package/src/types/index.ts +7 -0
  211. package/src/types/lsp.ts +96 -0
  212. package/src/types/messaging.ts +21 -14
  213. package/src/types/permissions.ts +48 -0
  214. package/src/types/session.ts +20 -0
  215. package/src/types/skills.ts +1 -0
  216. package/src/types/tools.ts +38 -0
  217. package/src/utils/abortUtils.ts +118 -0
  218. package/src/utils/bashHistory.ts +55 -31
  219. package/src/utils/builtinSubagents.ts +71 -0
  220. package/src/utils/cacheControlUtils.ts +475 -0
  221. package/src/utils/commandPathResolver.ts +189 -0
  222. package/src/utils/configPaths.ts +163 -0
  223. package/src/utils/constants.ts +2 -17
  224. package/src/utils/convertMessagesForAPI.ts +44 -18
  225. package/src/utils/customCommands.ts +90 -22
  226. package/src/utils/fileSearch.ts +107 -0
  227. package/src/utils/fileUtils.ts +160 -0
  228. package/src/utils/globalLogger.ts +128 -0
  229. package/src/utils/largeOutputHandler.ts +55 -0
  230. package/src/utils/markdownParser.ts +1 -19
  231. package/src/utils/mcpUtils.ts +34 -3
  232. package/src/utils/messageOperations.ts +47 -53
  233. package/src/utils/pathEncoder.ts +394 -0
  234. package/src/utils/subagentParser.ts +13 -9
  235. package/src/utils/tokenCalculation.ts +43 -0
  236. package/src/utils/tokenEstimator.ts +68 -0
  237. package/dist/utils/configResolver.d.ts +0 -38
  238. package/dist/utils/configResolver.d.ts.map +0 -1
  239. package/dist/utils/configResolver.js +0 -106
  240. 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
+ }
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Hook Services
2
+ * Hook Execution Services
3
3
  *
4
- * Consolidated hook services providing both execution and configuration functionality.
5
- * Combines hook command execution and settings management into a single module.
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, type PartialHookConfiguration } from "../types/hooks.js";
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;;;;;GAKG;AAMH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAGjC,KAAK,wBAAwB,EAG9B,MAAM,mBAAmB,CAAC;AA6C3B;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CAiH9B;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;AAMD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,GACf,wBAAwB,GAAG,IAAI,CAcjC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,wBAAwB,GAAG,IAAI,CAErE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,GACd,wBAAwB,GAAG,IAAI,CAEjC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GACd,wBAAwB,GAAG,IAAI,CAiCjC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAK9D;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG;IAC1D,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CASA"}
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"}
@@ -1,26 +1,33 @@
1
1
  /**
2
- * Hook Services
2
+ * Hook Execution Services
3
3
  *
4
- * Consolidated hook services providing both execution and configuration functionality.
5
- * Combines hook command execution and settings management into a single module.
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 { existsSync, readFileSync } from "fs";
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: context.transcriptPath ||
22
- (context.sessionId ? getSessionFilePath(context.sessionId) : ""),
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 extended context
107
- if (childProcess.stdin && "sessionId" in context) {
138
+ // Send JSON input to stdin if we have prepared it
139
+ if (childProcess.stdin && jsonInput) {
108
140
  try {
109
- const jsonInput = buildHookJsonInput(context);
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"}