wave-agent-sdk 0.0.15 → 0.0.17-alpha.0

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 (204) hide show
  1. package/dist/agent.d.ts +11 -1
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +71 -11
  4. package/dist/constants/prompts.d.ts +14 -0
  5. package/dist/constants/prompts.d.ts.map +1 -0
  6. package/dist/constants/prompts.js +61 -0
  7. package/dist/constants/tools.d.ts +18 -0
  8. package/dist/constants/tools.d.ts.map +1 -0
  9. package/dist/constants/tools.js +17 -0
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +6 -0
  13. package/dist/managers/aiManager.d.ts +8 -2
  14. package/dist/managers/aiManager.d.ts.map +1 -1
  15. package/dist/managers/aiManager.js +52 -16
  16. package/dist/managers/hookManager.d.ts +7 -2
  17. package/dist/managers/hookManager.d.ts.map +1 -1
  18. package/dist/managers/hookManager.js +10 -0
  19. package/dist/managers/liveConfigManager.d.ts +1 -1
  20. package/dist/managers/liveConfigManager.d.ts.map +1 -1
  21. package/dist/managers/liveConfigManager.js +43 -22
  22. package/dist/managers/permissionManager.d.ts +50 -1
  23. package/dist/managers/permissionManager.d.ts.map +1 -1
  24. package/dist/managers/permissionManager.js +289 -58
  25. package/dist/managers/planManager.d.ts +21 -0
  26. package/dist/managers/planManager.d.ts.map +1 -0
  27. package/dist/managers/planManager.js +35 -0
  28. package/dist/managers/pluginManager.d.ts +57 -0
  29. package/dist/managers/pluginManager.d.ts.map +1 -0
  30. package/dist/managers/pluginManager.js +124 -0
  31. package/dist/managers/pluginScopeManager.d.ts +35 -0
  32. package/dist/managers/pluginScopeManager.d.ts.map +1 -0
  33. package/dist/managers/pluginScopeManager.js +39 -0
  34. package/dist/managers/skillManager.d.ts +4 -0
  35. package/dist/managers/skillManager.d.ts.map +1 -1
  36. package/dist/managers/skillManager.js +15 -0
  37. package/dist/managers/slashCommandManager.d.ts +4 -0
  38. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  39. package/dist/managers/slashCommandManager.js +45 -3
  40. package/dist/managers/subagentManager.d.ts.map +1 -1
  41. package/dist/managers/subagentManager.js +3 -1
  42. package/dist/managers/toolManager.d.ts +4 -0
  43. package/dist/managers/toolManager.d.ts.map +1 -1
  44. package/dist/managers/toolManager.js +24 -1
  45. package/dist/services/GitService.d.ts +16 -0
  46. package/dist/services/GitService.d.ts.map +1 -0
  47. package/dist/services/GitService.js +75 -0
  48. package/dist/services/MarketplaceService.d.ts +62 -0
  49. package/dist/services/MarketplaceService.d.ts.map +1 -0
  50. package/dist/services/MarketplaceService.js +320 -0
  51. package/dist/services/aiService.d.ts +1 -0
  52. package/dist/services/aiService.d.ts.map +1 -1
  53. package/dist/services/aiService.js +11 -11
  54. package/dist/services/configurationService.d.ts +11 -4
  55. package/dist/services/configurationService.d.ts.map +1 -1
  56. package/dist/services/configurationService.js +211 -67
  57. package/dist/services/fileWatcher.js +3 -3
  58. package/dist/services/hook.js +1 -1
  59. package/dist/services/pluginLoader.d.ts +35 -0
  60. package/dist/services/pluginLoader.d.ts.map +1 -0
  61. package/dist/services/pluginLoader.js +149 -0
  62. package/dist/tools/askUserQuestion.d.ts +3 -0
  63. package/dist/tools/askUserQuestion.d.ts.map +1 -0
  64. package/dist/tools/askUserQuestion.js +109 -0
  65. package/dist/tools/bashTool.d.ts.map +1 -1
  66. package/dist/tools/bashTool.js +37 -40
  67. package/dist/tools/deleteFileTool.d.ts.map +1 -1
  68. package/dist/tools/deleteFileTool.js +17 -19
  69. package/dist/tools/editTool.d.ts.map +1 -1
  70. package/dist/tools/editTool.js +29 -36
  71. package/dist/tools/exitPlanMode.d.ts +6 -0
  72. package/dist/tools/exitPlanMode.d.ts.map +1 -0
  73. package/dist/tools/exitPlanMode.js +76 -0
  74. package/dist/tools/globTool.d.ts.map +1 -1
  75. package/dist/tools/globTool.js +4 -3
  76. package/dist/tools/grepTool.d.ts.map +1 -1
  77. package/dist/tools/grepTool.js +5 -4
  78. package/dist/tools/lsTool.d.ts.map +1 -1
  79. package/dist/tools/lsTool.js +16 -3
  80. package/dist/tools/lspTool.d.ts.map +1 -1
  81. package/dist/tools/lspTool.js +3 -2
  82. package/dist/tools/multiEditTool.d.ts.map +1 -1
  83. package/dist/tools/multiEditTool.js +24 -31
  84. package/dist/tools/readTool.d.ts.map +1 -1
  85. package/dist/tools/readTool.js +16 -3
  86. package/dist/tools/skillTool.d.ts.map +1 -1
  87. package/dist/tools/skillTool.js +30 -27
  88. package/dist/tools/taskTool.d.ts.map +1 -1
  89. package/dist/tools/taskTool.js +36 -31
  90. package/dist/tools/todoWriteTool.d.ts.map +1 -1
  91. package/dist/tools/todoWriteTool.js +3 -2
  92. package/dist/tools/writeTool.d.ts.map +1 -1
  93. package/dist/tools/writeTool.js +13 -17
  94. package/dist/types/commands.d.ts +1 -0
  95. package/dist/types/commands.d.ts.map +1 -1
  96. package/dist/types/config.d.ts +2 -0
  97. package/dist/types/config.d.ts.map +1 -1
  98. package/dist/types/configuration.d.ts +36 -1
  99. package/dist/types/configuration.d.ts.map +1 -1
  100. package/dist/types/hooks.d.ts +2 -15
  101. package/dist/types/hooks.d.ts.map +1 -1
  102. package/dist/types/index.d.ts +3 -0
  103. package/dist/types/index.d.ts.map +1 -1
  104. package/dist/types/index.js +3 -0
  105. package/dist/types/marketplace.d.ts +43 -0
  106. package/dist/types/marketplace.d.ts.map +1 -0
  107. package/dist/types/marketplace.js +1 -0
  108. package/dist/types/permissions.d.ts +4 -2
  109. package/dist/types/permissions.d.ts.map +1 -1
  110. package/dist/types/permissions.js +8 -5
  111. package/dist/types/plugins.d.ts +35 -0
  112. package/dist/types/plugins.d.ts.map +1 -0
  113. package/dist/types/plugins.js +1 -0
  114. package/dist/types/tools.d.ts +17 -0
  115. package/dist/types/tools.d.ts.map +1 -1
  116. package/dist/utils/bashHistory.d.ts +3 -3
  117. package/dist/utils/bashHistory.d.ts.map +1 -1
  118. package/dist/utils/bashHistory.js +10 -8
  119. package/dist/utils/bashParser.d.ts.map +1 -1
  120. package/dist/utils/bashParser.js +63 -20
  121. package/dist/utils/configPaths.d.ts +4 -0
  122. package/dist/utils/configPaths.d.ts.map +1 -1
  123. package/dist/utils/configPaths.js +6 -0
  124. package/dist/utils/constants.d.ts +4 -0
  125. package/dist/utils/constants.d.ts.map +1 -1
  126. package/dist/utils/constants.js +4 -0
  127. package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
  128. package/dist/utils/convertMessagesForAPI.js +4 -2
  129. package/dist/utils/customCommands.d.ts +6 -0
  130. package/dist/utils/customCommands.d.ts.map +1 -1
  131. package/dist/utils/customCommands.js +1 -1
  132. package/dist/utils/editUtils.d.ts +17 -0
  133. package/dist/utils/editUtils.d.ts.map +1 -0
  134. package/dist/utils/editUtils.js +69 -0
  135. package/dist/utils/markdownParser.d.ts.map +1 -1
  136. package/dist/utils/markdownParser.js +25 -1
  137. package/dist/utils/messageOperations.d.ts.map +1 -1
  138. package/dist/utils/messageOperations.js +2 -1
  139. package/dist/utils/nameGenerator.d.ts +8 -0
  140. package/dist/utils/nameGenerator.d.ts.map +1 -0
  141. package/dist/utils/nameGenerator.js +75 -0
  142. package/dist/utils/openaiClient.d.ts.map +1 -1
  143. package/dist/utils/openaiClient.js +14 -2
  144. package/dist/utils/pathSafety.d.ts.map +1 -1
  145. package/dist/utils/pathSafety.js +17 -2
  146. package/package.json +6 -1
  147. package/src/agent.ts +95 -10
  148. package/src/constants/prompts.ts +93 -0
  149. package/src/constants/tools.ts +17 -0
  150. package/src/index.ts +8 -0
  151. package/src/managers/aiManager.ts +86 -18
  152. package/src/managers/hookManager.ts +23 -6
  153. package/src/managers/liveConfigManager.ts +56 -29
  154. package/src/managers/permissionManager.ts +361 -61
  155. package/src/managers/planManager.ts +45 -0
  156. package/src/managers/pluginManager.ts +182 -0
  157. package/src/managers/pluginScopeManager.ts +75 -0
  158. package/src/managers/skillManager.ts +18 -0
  159. package/src/managers/slashCommandManager.ts +67 -5
  160. package/src/managers/subagentManager.ts +3 -1
  161. package/src/managers/toolManager.ts +25 -3
  162. package/src/services/GitService.ts +97 -0
  163. package/src/services/MarketplaceService.ts +428 -0
  164. package/src/services/aiService.ts +33 -16
  165. package/src/services/configurationService.ts +244 -86
  166. package/src/services/fileWatcher.ts +3 -3
  167. package/src/services/hook.ts +1 -1
  168. package/src/services/pluginLoader.ts +181 -0
  169. package/src/tools/askUserQuestion.ts +128 -0
  170. package/src/tools/bashTool.ts +52 -49
  171. package/src/tools/deleteFileTool.ts +22 -28
  172. package/src/tools/editTool.ts +42 -48
  173. package/src/tools/exitPlanMode.ts +93 -0
  174. package/src/tools/globTool.ts +4 -4
  175. package/src/tools/grepTool.ts +9 -5
  176. package/src/tools/lsTool.ts +27 -4
  177. package/src/tools/lspTool.ts +3 -2
  178. package/src/tools/multiEditTool.ts +40 -42
  179. package/src/tools/readTool.ts +23 -4
  180. package/src/tools/skillTool.ts +35 -30
  181. package/src/tools/taskTool.ts +39 -33
  182. package/src/tools/todoWriteTool.ts +3 -2
  183. package/src/tools/writeTool.ts +19 -27
  184. package/src/types/commands.ts +1 -0
  185. package/src/types/config.ts +2 -0
  186. package/src/types/configuration.ts +42 -1
  187. package/src/types/hooks.ts +8 -25
  188. package/src/types/index.ts +3 -0
  189. package/src/types/marketplace.ts +52 -0
  190. package/src/types/permissions.ts +29 -6
  191. package/src/types/plugins.ts +37 -0
  192. package/src/types/tools.ts +20 -0
  193. package/src/utils/bashHistory.ts +9 -16
  194. package/src/utils/bashParser.ts +97 -46
  195. package/src/utils/configPaths.ts +7 -0
  196. package/src/utils/constants.ts +5 -0
  197. package/src/utils/convertMessagesForAPI.ts +4 -2
  198. package/src/utils/customCommands.ts +1 -1
  199. package/src/utils/editUtils.ts +82 -0
  200. package/src/utils/markdownParser.ts +28 -1
  201. package/src/utils/messageOperations.ts +2 -1
  202. package/src/utils/nameGenerator.ts +78 -0
  203. package/src/utils/openaiClient.ts +14 -2
  204. package/src/utils/pathSafety.ts +16 -2
@@ -3,6 +3,8 @@ import { getMessagesToCompress } from "../utils/messageOperations.js";
3
3
  import { convertMessagesForAPI } from "../utils/convertMessagesForAPI.js";
4
4
  import { calculateComprehensiveTotalTokens } from "../utils/tokenCalculation.js";
5
5
  import * as memory from "../services/memory.js";
6
+ import * as fs from "node:fs/promises";
7
+ import { DEFAULT_SYSTEM_PROMPT, buildSystemPrompt, } from "../constants/prompts.js";
6
8
  export class AIManager {
7
9
  constructor(options) {
8
10
  this.isLoading = false;
@@ -13,6 +15,7 @@ export class AIManager {
13
15
  this.toolManager = options.toolManager;
14
16
  this.backgroundBashManager = options.backgroundBashManager;
15
17
  this.hookManager = options.hookManager;
18
+ this.permissionManager = options.permissionManager;
16
19
  this.logger = options.logger;
17
20
  this.workdir = options.workdir;
18
21
  this.systemPrompt = options.systemPrompt;
@@ -36,16 +39,16 @@ export class AIManager {
36
39
  return this.getMaxInputTokensFn();
37
40
  }
38
41
  /**
39
- * Get filtered tool configuration
42
+ * Get filtered tool configuration based on tools list
40
43
  */
41
- getFilteredToolsConfig(allowedTools) {
44
+ getFilteredToolsConfig(tools) {
42
45
  const allTools = this.toolManager.getToolsConfig();
43
- // If no allowedTools specified, return all tools
44
- if (!allowedTools || allowedTools.length === 0) {
46
+ // If no tools specified, return all tools
47
+ if (!tools || tools.length === 0) {
45
48
  return allTools;
46
49
  }
47
- // Filter allowed tools
48
- return allTools.filter((tool) => allowedTools.includes(tool.function.name));
50
+ // Filter tools
51
+ return allTools.filter((tool) => tools.includes(tool.function.name));
49
52
  }
50
53
  setIsLoading(isLoading) {
51
54
  this.isLoading = isLoading;
@@ -90,7 +93,7 @@ export class AIManager {
90
93
  return "";
91
94
  }
92
95
  // Private method to handle token statistics and message compression
93
- async handleTokenUsageAndCompression(usage, abortController) {
96
+ async handleTokenUsageAndCompression(usage, abortController, model) {
94
97
  if (!usage)
95
98
  return;
96
99
  // Update token statistics - display comprehensive token usage including cache tokens
@@ -103,7 +106,7 @@ export class AIManager {
103
106
  this.getMaxInputTokens()) {
104
107
  this.logger?.debug(`Token usage exceeded ${this.getMaxInputTokens()}, compressing messages...`);
105
108
  // Check if messages need compression
106
- const { messagesToCompress, insertIndex } = getMessagesToCompress(this.messageManager.getMessages(), 7);
109
+ const { messagesToCompress, insertIndex } = getMessagesToCompress(this.messageManager.getMessages());
107
110
  // If there are messages to compress, perform compression
108
111
  if (messagesToCompress.length > 0) {
109
112
  const recentChatMessages = convertMessagesForAPI(messagesToCompress);
@@ -116,6 +119,7 @@ export class AIManager {
116
119
  modelConfig: this.getModelConfig(),
117
120
  messages: recentChatMessages,
118
121
  abortSignal: abortController.signal,
122
+ model: model,
119
123
  });
120
124
  // Handle usage tracking for compression operations
121
125
  let compressionUsage;
@@ -124,7 +128,7 @@ export class AIManager {
124
128
  prompt_tokens: compressionResult.usage.prompt_tokens,
125
129
  completion_tokens: compressionResult.usage.completion_tokens,
126
130
  total_tokens: compressionResult.usage.total_tokens,
127
- model: this.getModelConfig().fastModel,
131
+ model: model || this.getModelConfig().agentModel,
128
132
  operation_type: "compress",
129
133
  };
130
134
  }
@@ -155,7 +159,7 @@ export class AIManager {
155
159
  }
156
160
  }
157
161
  async sendAIMessage(options = {}) {
158
- const { recursionDepth = 0, model, allowedTools, maxTokens } = options;
162
+ const { recursionDepth = 0, model, allowedRules, tools, maxTokens, } = options;
159
163
  // Only check isLoading for the initial call (recursionDepth === 0)
160
164
  if (recursionDepth === 0 && this.isLoading) {
161
165
  return;
@@ -181,6 +185,9 @@ export class AIManager {
181
185
  // Only set loading state for the initial call
182
186
  if (recursionDepth === 0) {
183
187
  this.setIsLoading(true);
188
+ if (allowedRules && allowedRules.length > 0) {
189
+ this.permissionManager?.addTemporaryRules(allowedRules);
190
+ }
184
191
  }
185
192
  // Get recent message history
186
193
  const recentMessages = convertMessagesForAPI(this.messageManager.getMessages());
@@ -190,6 +197,25 @@ export class AIManager {
190
197
  // Track if assistant message has been created
191
198
  let assistantMessageCreated = false;
192
199
  this.logger?.debug("modelConfig in sendAIMessage", this.getModelConfig());
200
+ // Get current permission mode and plan file path
201
+ const currentMode = this.permissionManager?.getCurrentEffectiveMode(this.getModelConfig().permissionMode);
202
+ const toolsConfig = this.getFilteredToolsConfig(tools);
203
+ let effectiveSystemPrompt = buildSystemPrompt(this.systemPrompt || DEFAULT_SYSTEM_PROMPT, toolsConfig);
204
+ if (currentMode === "plan") {
205
+ const planFilePath = this.permissionManager?.getPlanFilePath();
206
+ if (planFilePath) {
207
+ let planExists = false;
208
+ try {
209
+ await fs.access(planFilePath);
210
+ planExists = true;
211
+ }
212
+ catch {
213
+ planExists = false;
214
+ }
215
+ const reminder = `\n\nPlan mode is active. The user indicated that they do not want you to execute yet -- you MUST NOT make any edits (with the exception of the plan file mentioned below), run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supercedes any other instructions you have received.\n\n## Plan File Info:\n${planExists ? `A plan file already exists at ${planFilePath}. You can read it and make incremental edits using the Edit tool if you need to.` : `No plan file exists yet. You should create your plan at ${planFilePath} using the Write tool if you need to.`}\nYou should build your plan incrementally by writing to or editing this file. NOTE that this is the only file you are allowed to edit - other than this you are only allowed to take READ-ONLY actions. You may also use the AskUserQuestion tool to gather requirements or clarify intent before finalizing your plan.`;
216
+ effectiveSystemPrompt = (effectiveSystemPrompt || "") + reminder;
217
+ }
218
+ }
193
219
  // Call AI service with streaming callbacks if enabled
194
220
  const callAgentOptions = {
195
221
  gatewayConfig: this.getGatewayConfig(),
@@ -199,9 +225,9 @@ export class AIManager {
199
225
  abortSignal: abortController.signal,
200
226
  memory: combinedMemory, // Pass combined memory content
201
227
  workdir: this.workdir, // Pass working directory
202
- tools: this.getFilteredToolsConfig(allowedTools), // Pass filtered tool configuration
228
+ tools: toolsConfig, // Pass filtered tool configuration
203
229
  model: model, // Use passed model
204
- systemPrompt: this.systemPrompt, // Pass custom system prompt
230
+ systemPrompt: effectiveSystemPrompt, // Pass custom system prompt
205
231
  maxTokens: maxTokens, // Pass max tokens override
206
232
  };
207
233
  // Add streaming callbacks only if streaming is enabled
@@ -253,7 +279,10 @@ export class AIManager {
253
279
  }
254
280
  // Log finish reason and response headers if available
255
281
  if (result.finish_reason) {
256
- this.logger?.debug(`AI response finished with reason: ${result.finish_reason}`);
282
+ // Log warning headers when finish reason is length
283
+ if (result.finish_reason === "length") {
284
+ this.logger?.warn("AI response truncated due to length limit. Response headers:", result.response_headers);
285
+ }
257
286
  }
258
287
  if (result.response_headers &&
259
288
  Object.keys(result.response_headers).length > 0) {
@@ -314,6 +343,9 @@ export class AIManager {
314
343
  }
315
344
  }
316
345
  }
346
+ if (result.finish_reason === "length" && toolCalls.length === 0) {
347
+ this.messageManager.addErrorBlock("AI response was truncated due to length limit. Please try to reduce the complexity of your request or split it into smaller parts.");
348
+ }
317
349
  if (toolCalls.length > 0) {
318
350
  // Execute all tools in parallel using Promise.all
319
351
  const toolExecutionPromises = toolCalls.map(async (functionToolCall) => {
@@ -417,7 +449,7 @@ export class AIManager {
417
449
  await Promise.all(toolExecutionPromises);
418
450
  }
419
451
  // Handle token statistics and message compression
420
- await this.handleTokenUsageAndCompression(result.usage, abortController);
452
+ await this.handleTokenUsageAndCompression(result.usage, abortController, model);
421
453
  // Check if there are tool operations, if so automatically initiate next AI service call
422
454
  if (toolCalls.length > 0) {
423
455
  // Check interruption status
@@ -427,7 +459,8 @@ export class AIManager {
427
459
  await this.sendAIMessage({
428
460
  recursionDepth: recursionDepth + 1,
429
461
  model,
430
- allowedTools,
462
+ allowedRules,
463
+ tools,
431
464
  maxTokens,
432
465
  });
433
466
  }
@@ -443,6 +476,8 @@ export class AIManager {
443
476
  await this.messageManager.saveSession();
444
477
  // Set loading to false first
445
478
  this.setIsLoading(false);
479
+ // Clear temporary rules
480
+ this.permissionManager?.clearTemporaryRules();
446
481
  // Clear abort controllers
447
482
  this.abortController = null;
448
483
  this.toolAbortController = null;
@@ -459,7 +494,8 @@ export class AIManager {
459
494
  await this.sendAIMessage({
460
495
  recursionDepth: 0,
461
496
  model,
462
- allowedTools,
497
+ allowedRules,
498
+ tools,
463
499
  maxTokens,
464
500
  });
465
501
  }
@@ -4,7 +4,8 @@
4
4
  * Central orchestrator for the hooks system. Handles configuration loading,
5
5
  * validation, and hook execution across all supported events.
6
6
  */
7
- import { type HookEvent, type WaveConfiguration, type PartialHookConfiguration, type HookExecutionContext, type ExtendedHookExecutionContext, type HookExecutionResult, type ValidationResult } from "../types/hooks.js";
7
+ import { type HookEvent, type HookExecutionContext, type ExtendedHookExecutionContext, type HookExecutionResult, type HookValidationResult } from "../types/hooks.js";
8
+ import type { WaveConfiguration, PartialHookConfiguration } from "../types/configuration.js";
8
9
  import { HookMatcher } from "../utils/hookMatcher.js";
9
10
  import type { Logger } from "../types/index.js";
10
11
  import type { MessageManager } from "./messageManager.js";
@@ -55,7 +56,7 @@ export declare class HookManager {
55
56
  /**
56
57
  * Validate Wave configuration structure and content
57
58
  */
58
- validateConfiguration(config: WaveConfiguration): ValidationResult;
59
+ validateConfiguration(config: WaveConfiguration): HookValidationResult;
59
60
  /**
60
61
  * Validate partial hook configuration structure and content
61
62
  */
@@ -97,5 +98,9 @@ export declare class HookManager {
97
98
  totalCommands: number;
98
99
  eventBreakdown: Record<HookEvent, number>;
99
100
  };
101
+ /**
102
+ * Register hooks provided by a plugin
103
+ */
104
+ registerPluginHooks(hooks: PartialHookConfiguration): void;
100
105
  }
101
106
  //# sourceMappingURL=hookManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hookManager.d.ts","sourceRoot":"","sources":["../../src/managers/hookManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAItB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAG/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,WAA+B,EACxC,MAAM,CAAC,EAAE,MAAM;IAOjB;;;OAGG;IACH,iBAAiB,CACf,SAAS,CAAC,EAAE,wBAAwB,EACpC,YAAY,CAAC,EAAE,wBAAwB,GACtC,IAAI;IAyBP;;;OAGG;IACH,+BAA+B,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI;IAqC3E;;OAEG;IACG,YAAY,CAChB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,GAC3D,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAyHjC;;;OAGG;IACH,kBAAkB,CAChB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,mBAAmB,EAAE,EAC9B,cAAc,CAAC,EAAE,cAAc,EAC/B,MAAM,CAAC,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACtB;QACD,WAAW,EAAE,OAAO,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB;IAuCD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsE3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAWtD;;OAEG;IACH,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,gBAAgB;IA8DlE;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAyCpC;;OAEG;IACH,gBAAgB,IAAI,wBAAwB,GAAG,SAAS;IAOxD;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAsDhC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA8BhC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,aAAa;IAiCrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA2C3B;;OAEG;IACH,qBAAqB,IAAI;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;KAC3C;CA+CF"}
1
+ {"version":3,"file":"hookManager.d.ts","sourceRoot":"","sources":["../../src/managers/hookManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAI1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAuC;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAG/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,WAA+B,EACxC,MAAM,CAAC,EAAE,MAAM;IAOjB;;;OAGG;IACH,iBAAiB,CACf,SAAS,CAAC,EAAE,wBAAwB,EACpC,YAAY,CAAC,EAAE,wBAAwB,GACtC,IAAI;IAyBP;;;OAGG;IACH,+BAA+B,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI;IAqC3E;;OAEG;IACG,YAAY,CAChB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,GAC3D,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAyHjC;;;OAGG;IACH,kBAAkB,CAChB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,mBAAmB,EAAE,EAC9B,cAAc,CAAC,EAAE,cAAc,EAC/B,MAAM,CAAC,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACtB;QACD,WAAW,EAAE,OAAO,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB;IAuCD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsE3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAWtD;;OAEG;IACH,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,oBAAoB;IA8DtE;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAyCpC;;OAEG;IACH,gBAAgB,IAAI,wBAAwB,GAAG,SAAS;IAOxD;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAsDhC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA8BhC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,aAAa;IAiCrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA2C3B;;OAEG;IACH,qBAAqB,IAAI;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;KAC3C;IAgDD;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI;CAW3D"}
@@ -529,4 +529,14 @@ export class HookManager {
529
529
  eventBreakdown,
530
530
  };
531
531
  }
532
+ /**
533
+ * Register hooks provided by a plugin
534
+ */
535
+ registerPluginHooks(hooks) {
536
+ if (!this.configuration) {
537
+ this.configuration = {};
538
+ }
539
+ this.mergeHooksConfiguration(this.configuration, hooks);
540
+ this.logger?.debug(`Registered plugin hooks. Total event types: ${Object.keys(this.configuration).length}`);
541
+ }
532
542
  }
@@ -9,8 +9,8 @@
9
9
  import type { Logger } from "../types/index.js";
10
10
  import type { HookManager } from "./hookManager.js";
11
11
  import type { PermissionManager } from "./permissionManager.js";
12
- import type { WaveConfiguration } from "../types/hooks.js";
13
12
  import { ConfigurationService } from "../services/configurationService.js";
13
+ import type { WaveConfiguration } from "../types/configuration.js";
14
14
  export interface LiveConfigManagerOptions {
15
15
  workdir: string;
16
16
  logger?: Logger;
@@ -1 +1 @@
1
- {"version":3,"file":"liveConfigManager.d.ts","sourceRoot":"","sources":["../../src/managers/liveConfigManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAKhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKhE,OAAO,KAAK,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAE7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAK3E,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAoB;IACvD,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAuB;IAG5D,OAAO,CAAC,oBAAoB,CAAkC;IAC9D,OAAO,CAAC,sBAAsB,CAAkC;IAGhE,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAW;IACnC,OAAO,CAAC,kBAAkB,CAAC,CAAW;IACtC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,gBAAgB,CAAkB;gBAE9B,OAAO,EAAE,wBAAwB;IAW7C;;;;OAIG;YACW,kBAAkB;IA6DhC;;OAEG;IACH,uBAAuB,IAAI,iBAAiB,GAAG,IAAI;IAInD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBjC;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB/B;;;OAGG;YACW,mBAAmB;IA8MjC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAK1C;;OAEG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;OAEG;IACH,gBAAgB;;;;;;;;;;;;IAgBhB,OAAO,CAAC,sBAAsB;YAMhB,gBAAgB;IA8C9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0E7B,OAAO,CAAC,aAAa;IAuDrB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;CAQ9B"}
1
+ {"version":3,"file":"liveConfigManager.d.ts","sourceRoot":"","sources":["../../src/managers/liveConfigManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAMhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAOhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAG3E,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAoB;IACvD,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAuB;IAG5D,OAAO,CAAC,oBAAoB,CAAkC;IAC9D,OAAO,CAAC,sBAAsB,CAAkC;IAGhE,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAW;IACnC,OAAO,CAAC,kBAAkB,CAAC,CAAW;IACtC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,gBAAgB,CAAkB;gBAE9B,OAAO,EAAE,wBAAwB;IAW7C;;;;OAIG;YACW,kBAAkB;IA6DhC;;OAEG;IACH,uBAAuB,IAAI,iBAAiB,GAAG,IAAI;IAInD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBjC;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB/B;;;OAGG;YACW,mBAAmB;IAmNjC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAK1C;;OAEG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;OAEG;IACH,gBAAgB;;;;;;;;;;;;IAgBhB,OAAO,CAAC,sBAAsB;YAMhB,gBAAgB;IA8C9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA4F7B,OAAO,CAAC,aAAa;IAuDrB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;CAQ9B"}
@@ -36,7 +36,7 @@ export class LiveConfigManager {
36
36
  */
37
37
  async initializeWatching(userPaths, projectPaths) {
38
38
  try {
39
- this.logger?.info("Live Config: Initializing configuration watching...");
39
+ this.logger?.debug("Live Config: Initializing configuration watching...");
40
40
  this.userConfigPaths = userPaths;
41
41
  this.projectConfigPaths = projectPaths;
42
42
  // Load initial configuration
@@ -67,7 +67,7 @@ export class LiveConfigManager {
67
67
  }
68
68
  }
69
69
  this.isWatching = true;
70
- this.logger?.info("Live Config: Configuration watching initialized successfully");
70
+ this.logger?.debug("Live Config: Configuration watching initialized successfully");
71
71
  }
72
72
  catch (error) {
73
73
  const errorMessage = `Failed to initialize configuration watching: ${error.message}`;
@@ -95,7 +95,7 @@ export class LiveConfigManager {
95
95
  // Initialize configuration watching
96
96
  await this.initializeWatching(userPaths, projectPaths);
97
97
  this.isInitialized = true;
98
- this.logger?.info("Live configuration management initialized with file watching");
98
+ this.logger?.debug("Live configuration management initialized with file watching");
99
99
  }
100
100
  catch (error) {
101
101
  this.logger?.error(`Failed to initialize: ${error.message}`);
@@ -110,7 +110,7 @@ export class LiveConfigManager {
110
110
  return;
111
111
  }
112
112
  try {
113
- this.logger?.info("Live Config: Shutting down configuration manager...");
113
+ this.logger?.debug("Live Config: Shutting down configuration manager...");
114
114
  this.isWatching = false;
115
115
  // Cleanup file watcher
116
116
  await this.fileWatcher.cleanup();
@@ -118,7 +118,7 @@ export class LiveConfigManager {
118
118
  this.currentConfiguration = null;
119
119
  this.lastValidConfiguration = null;
120
120
  this.isInitialized = false;
121
- this.logger?.info("Live configuration management shutdown completed");
121
+ this.logger?.debug("Live configuration management shutdown completed");
122
122
  }
123
123
  catch (error) {
124
124
  this.logger?.error(`Error during shutdown: ${error.message}`);
@@ -150,7 +150,7 @@ export class LiveConfigManager {
150
150
  }
151
151
  // Use fallback configuration if available
152
152
  if (this.lastValidConfiguration) {
153
- this.logger?.info("Live Config: Using previous valid configuration due to loading errors");
153
+ this.logger?.debug("Live Config: Using previous valid configuration due to loading errors");
154
154
  this.currentConfiguration = this.lastValidConfiguration;
155
155
  // Apply environment variables to configuration service if configured
156
156
  if (this.lastValidConfiguration.env) {
@@ -170,14 +170,14 @@ export class LiveConfigManager {
170
170
  }
171
171
  // Log success with detailed information
172
172
  if (newConfig) {
173
- this.logger?.info(`Live Config: Configuration loaded successfully from ${loadResult.sourcePath || "merged sources"}`);
173
+ this.logger?.debug(`Live Config: Configuration loaded successfully from ${loadResult.sourcePath || "merged sources"}`);
174
174
  // Log detailed configuration info
175
175
  const hookCount = Object.keys(newConfig.hooks || {}).length;
176
176
  const envCount = Object.keys(newConfig.env || {}).length;
177
177
  this.logger?.debug(`Live Config: Loaded ${hookCount} hook events and ${envCount} environment variables`);
178
178
  }
179
179
  else {
180
- this.logger?.info("Live Config: No configuration found (using empty configuration)");
180
+ this.logger?.debug("Live Config: No configuration found (using empty configuration)");
181
181
  }
182
182
  // Log warnings from successful loading
183
183
  if (loadResult.warnings && loadResult.warnings.length > 0) {
@@ -191,7 +191,7 @@ export class LiveConfigManager {
191
191
  this.logger?.error(`Live Config: ${errorMessage}`);
192
192
  // Use previous valid configuration for error recovery
193
193
  if (this.lastValidConfiguration) {
194
- this.logger?.info("Live Config: Using previous valid configuration due to validation errors");
194
+ this.logger?.debug("Live Config: Using previous valid configuration due to validation errors");
195
195
  this.currentConfiguration = this.lastValidConfiguration;
196
196
  // Apply environment variables to configuration service if configured
197
197
  if (this.lastValidConfiguration.env) {
@@ -227,14 +227,17 @@ export class LiveConfigManager {
227
227
  }
228
228
  // Update permission manager if available
229
229
  if (this.permissionManager) {
230
- if (this.currentConfiguration.defaultMode) {
231
- this.permissionManager.updateConfiguredDefaultMode(this.currentConfiguration.defaultMode);
230
+ if (this.currentConfiguration.permissions?.defaultMode) {
231
+ this.permissionManager.updateConfiguredDefaultMode(this.currentConfiguration.permissions.defaultMode);
232
232
  }
233
233
  if (this.currentConfiguration.permissions?.allow) {
234
234
  this.permissionManager.updateAllowedRules(this.currentConfiguration.permissions.allow);
235
235
  }
236
+ if (this.currentConfiguration.permissions?.additionalDirectories) {
237
+ this.permissionManager.updateAdditionalDirectories(this.currentConfiguration.permissions.additionalDirectories);
238
+ }
236
239
  }
237
- this.logger?.info(`Live Config: Configuration reload completed successfully with ${Object.keys(newConfig?.hooks || {}).length} event types and ${Object.keys(newConfig?.env || {}).length} environment variables`);
240
+ this.logger?.debug(`Live Config: Configuration reload completed successfully with ${Object.keys(newConfig?.hooks || {}).length} event types and ${Object.keys(newConfig?.env || {}).length} environment variables`);
238
241
  return this.currentConfiguration;
239
242
  }
240
243
  catch (error) {
@@ -242,7 +245,7 @@ export class LiveConfigManager {
242
245
  this.logger?.error(`Live Config: ${errorMessage}`);
243
246
  // Use previous valid configuration for error recovery
244
247
  if (this.lastValidConfiguration) {
245
- this.logger?.info("Live Config: Using previous valid configuration due to reload exception");
248
+ this.logger?.debug("Live Config: Using previous valid configuration due to reload exception");
246
249
  this.currentConfiguration = this.lastValidConfiguration;
247
250
  // Apply environment variables to configuration service if configured
248
251
  if (this.lastValidConfiguration.env) {
@@ -267,7 +270,7 @@ export class LiveConfigManager {
267
270
  * Reload configuration from files (public method)
268
271
  */
269
272
  async reload() {
270
- this.logger?.info("Manually reloading configuration...");
273
+ this.logger?.debug("Manually reloading configuration...");
271
274
  return await this.reloadConfiguration();
272
275
  }
273
276
  /**
@@ -304,14 +307,14 @@ export class LiveConfigManager {
304
307
  try {
305
308
  // Handle file deletion
306
309
  if (event.type === "delete") {
307
- this.logger?.info(`Live Config: ${source} config file deleted: ${event.path}`);
310
+ this.logger?.debug(`Live Config: ${source} config file deleted: ${event.path}`);
308
311
  // Reload configuration without the deleted file
309
312
  await this.reloadConfiguration();
310
313
  return;
311
314
  }
312
315
  // Handle file creation or modification
313
316
  if (event.type === "change" || event.type === "create") {
314
- this.logger?.info(`Live Config: ${source} config file ${event.type}: ${event.path}`);
317
+ this.logger?.debug(`Live Config: ${source} config file ${event.type}: ${event.path}`);
315
318
  if (source === "project" &&
316
319
  event.path.endsWith("settings.local.json") &&
317
320
  event.type === "create") {
@@ -335,12 +338,30 @@ export class LiveConfigManager {
335
338
  if (!config || typeof config !== "object") {
336
339
  return { valid: false, errors: ["Configuration must be an object"] };
337
340
  }
338
- // Validate defaultMode if present
339
- if (config.defaultMode !== undefined) {
340
- if (config.defaultMode !== "default" &&
341
- config.defaultMode !== "bypassPermissions" &&
342
- config.defaultMode !== "acceptEdits") {
343
- errors.push(`Invalid defaultMode: "${config.defaultMode}". Must be "default", "bypassPermissions" or "acceptEdits"`);
341
+ // Validate permissions if present
342
+ if (config.permissions) {
343
+ if (typeof config.permissions !== "object") {
344
+ errors.push("permissions property must be an object");
345
+ }
346
+ else {
347
+ // Validate defaultMode if present
348
+ if (config.permissions.defaultMode !== undefined) {
349
+ const validModes = [
350
+ "default",
351
+ "bypassPermissions",
352
+ "acceptEdits",
353
+ "plan",
354
+ ];
355
+ if (!validModes.includes(config.permissions.defaultMode)) {
356
+ errors.push(`Invalid defaultMode: "${config.permissions.defaultMode}". Must be one of: ${validModes.join(", ")}`);
357
+ }
358
+ }
359
+ // Validate allow if present
360
+ if (config.permissions.allow) {
361
+ if (!Array.isArray(config.permissions.allow)) {
362
+ errors.push("permissions.allow must be an array");
363
+ }
364
+ }
344
365
  }
345
366
  }
346
367
  // Validate hooks if present
@@ -14,11 +14,24 @@ export interface PermissionManagerOptions {
14
14
  configuredDefaultMode?: PermissionMode;
15
15
  /** Allowed rules from settings */
16
16
  allowedRules?: string[];
17
+ /** Denied rules from settings */
18
+ deniedRules?: string[];
19
+ /** Additional directories considered part of the Safe Zone */
20
+ additionalDirectories?: string[];
21
+ /** The main working directory */
22
+ workdir?: string;
23
+ /** Path to the current plan file */
24
+ planFilePath?: string;
17
25
  }
18
26
  export declare class PermissionManager {
19
27
  private logger?;
20
28
  private configuredDefaultMode?;
21
29
  private allowedRules;
30
+ private deniedRules;
31
+ private temporaryRules;
32
+ private additionalDirectories;
33
+ private workdir?;
34
+ private planFilePath?;
22
35
  private onConfiguredDefaultModeChange?;
23
36
  constructor(options?: PermissionManagerOptions);
24
37
  /**
@@ -37,6 +50,38 @@ export declare class PermissionManager {
37
50
  * Update the allowed rules (e.g., when configuration reloads)
38
51
  */
39
52
  updateAllowedRules(rules: string[]): void;
53
+ /**
54
+ * Update the denied rules (e.g., when configuration reloads)
55
+ */
56
+ updateDeniedRules(rules: string[]): void;
57
+ /**
58
+ * Add temporary rules for the current session
59
+ */
60
+ addTemporaryRules(rules: string[]): void;
61
+ /**
62
+ * Clear all temporary rules
63
+ */
64
+ clearTemporaryRules(): void;
65
+ /**
66
+ * Update the additional directories (e.g., when configuration reloads)
67
+ */
68
+ updateAdditionalDirectories(directories: string[]): void;
69
+ /**
70
+ * Update the working directory
71
+ */
72
+ updateWorkdir(workdir: string): void;
73
+ /**
74
+ * Set the current plan file path
75
+ */
76
+ setPlanFilePath(path: string | undefined): void;
77
+ /**
78
+ * Get the current plan file path
79
+ */
80
+ getPlanFilePath(): string | undefined;
81
+ /**
82
+ * Check if a path is inside the Safe Zone (workdir + additionalDirectories)
83
+ */
84
+ private isInsideSafeZone;
40
85
  /**
41
86
  * Get the current effective permission mode for tool execution context
42
87
  */
@@ -59,7 +104,11 @@ export declare class PermissionManager {
59
104
  */
60
105
  createContext(toolName: string, permissionMode: PermissionMode, callback?: PermissionCallback, toolInput?: Record<string, unknown>): ToolPermissionContext;
61
106
  /**
62
- * Check if a tool call is allowed by persistent rules
107
+ * Check if a tool call matches a specific permission rule
108
+ */
109
+ private matchesRule;
110
+ /**
111
+ * Check if a tool call is allowed by persistent or temporary rules
63
112
  */
64
113
  private isAllowedByRule;
65
114
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"permissionManager.d.ts","sourceRoot":"","sources":["../../src/managers/permissionManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAYhD,MAAM,WAAW,wBAAwB;IACvC,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,qBAAqB,CAAC,EAAE,cAAc,CAAC;IACvC,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,qBAAqB,CAAC,CAAiB;IAC/C,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,6BAA6B,CAAC,CAAiC;gBAE3D,OAAO,GAAE,wBAA6B;IAMlD;;OAEG;IACI,gCAAgC,CACrC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,GACvC,IAAI;IAIP;;OAEG;IACH,2BAA2B,CAAC,WAAW,CAAC,EAAE,cAAc,GAAG,IAAI;IAyB/D;;OAEG;IACI,eAAe,IAAI,MAAM,EAAE;IAIlC;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAOzC;;OAEG;IACH,uBAAuB,CAAC,iBAAiB,CAAC,EAAE,cAAc,GAAG,cAAc;IAI3E;;OAEG;IACH,8BAA8B,CAC5B,iBAAiB,CAAC,EAAE,cAAc,GACjC,cAAc;IAuBjB;;;OAGG;IACG,eAAe,CACnB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,kBAAkB,CAAC;IAqF9B;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAW3C;;OAEG;IACH,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,QAAQ,CAAC,EAAE,kBAAkB,EAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,qBAAqB;IAuExB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiEvB;;;;;;;OAOG;IACI,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;CAiFlE"}
1
+ {"version":3,"file":"permissionManager.d.ts","sourceRoot":"","sources":["../../src/managers/permissionManager.ts"],"names":[],"mappings":"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"}