wave-agent-sdk 0.7.1 → 0.8.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 (168) hide show
  1. package/dist/agent.d.ts +9 -79
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +85 -302
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -1
  7. package/dist/managers/aiManager.d.ts.map +1 -1
  8. package/dist/managers/aiManager.js +20 -13
  9. package/dist/managers/backgroundTaskManager.d.ts +1 -1
  10. package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
  11. package/dist/managers/backgroundTaskManager.js +1 -1
  12. package/dist/managers/{bashManager.d.ts → bangManager.d.ts} +4 -4
  13. package/dist/managers/{bashManager.d.ts.map → bangManager.d.ts.map} +1 -1
  14. package/dist/managers/{bashManager.js → bangManager.js} +5 -6
  15. package/dist/managers/hookManager.d.ts.map +1 -1
  16. package/dist/managers/hookManager.js +12 -3
  17. package/dist/managers/messageManager.d.ts +18 -6
  18. package/dist/managers/messageManager.d.ts.map +1 -1
  19. package/dist/managers/messageManager.js +42 -20
  20. package/dist/managers/permissionManager.d.ts +22 -1
  21. package/dist/managers/permissionManager.d.ts.map +1 -1
  22. package/dist/managers/permissionManager.js +106 -85
  23. package/dist/managers/planManager.d.ts +6 -0
  24. package/dist/managers/planManager.d.ts.map +1 -1
  25. package/dist/managers/planManager.js +21 -0
  26. package/dist/managers/skillManager.d.ts +7 -2
  27. package/dist/managers/skillManager.d.ts.map +1 -1
  28. package/dist/managers/skillManager.js +30 -10
  29. package/dist/managers/slashCommandManager.d.ts +7 -0
  30. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  31. package/dist/managers/slashCommandManager.js +57 -45
  32. package/dist/managers/subagentManager.d.ts +4 -0
  33. package/dist/managers/subagentManager.d.ts.map +1 -1
  34. package/dist/managers/subagentManager.js +47 -13
  35. package/dist/managers/toolManager.d.ts +7 -1
  36. package/dist/managers/toolManager.d.ts.map +1 -1
  37. package/dist/managers/toolManager.js +15 -2
  38. package/dist/prompts/index.d.ts +0 -4
  39. package/dist/prompts/index.d.ts.map +1 -1
  40. package/dist/prompts/index.js +0 -9
  41. package/dist/services/aiService.d.ts.map +1 -1
  42. package/dist/services/aiService.js +6 -6
  43. package/dist/services/configurationService.d.ts +2 -2
  44. package/dist/services/configurationService.d.ts.map +1 -1
  45. package/dist/services/configurationService.js +4 -4
  46. package/dist/services/hook.d.ts.map +1 -1
  47. package/dist/services/hook.js +6 -0
  48. package/dist/services/initializationService.d.ts +44 -0
  49. package/dist/services/initializationService.d.ts.map +1 -0
  50. package/dist/services/initializationService.js +170 -0
  51. package/dist/services/interactionService.d.ts +29 -0
  52. package/dist/services/interactionService.d.ts.map +1 -0
  53. package/dist/services/interactionService.js +97 -0
  54. package/dist/services/session.js +1 -1
  55. package/dist/services/taskManager.d.ts +5 -0
  56. package/dist/services/taskManager.d.ts.map +1 -1
  57. package/dist/services/taskManager.js +16 -2
  58. package/dist/tools/bashTool.d.ts.map +1 -1
  59. package/dist/tools/bashTool.js +7 -18
  60. package/dist/tools/editTool.js +1 -1
  61. package/dist/tools/exitPlanMode.js +1 -1
  62. package/dist/tools/lspTool.d.ts +2 -0
  63. package/dist/tools/lspTool.d.ts.map +1 -1
  64. package/dist/tools/lspTool.js +144 -52
  65. package/dist/tools/skillTool.d.ts.map +1 -1
  66. package/dist/tools/skillTool.js +97 -2
  67. package/dist/tools/taskManagementTools.d.ts.map +1 -1
  68. package/dist/tools/taskManagementTools.js +23 -2
  69. package/dist/tools/taskTool.d.ts.map +1 -1
  70. package/dist/tools/taskTool.js +9 -15
  71. package/dist/tools/types.d.ts +1 -2
  72. package/dist/tools/types.d.ts.map +1 -1
  73. package/dist/tools/writeTool.js +1 -1
  74. package/dist/types/agent.d.ts +64 -0
  75. package/dist/types/agent.d.ts.map +1 -0
  76. package/dist/types/agent.js +1 -0
  77. package/dist/types/commands.d.ts +0 -4
  78. package/dist/types/commands.d.ts.map +1 -1
  79. package/dist/types/config.d.ts +1 -1
  80. package/dist/types/config.d.ts.map +1 -1
  81. package/dist/types/hooks.d.ts +3 -1
  82. package/dist/types/hooks.d.ts.map +1 -1
  83. package/dist/types/hooks.js +1 -0
  84. package/dist/types/index.d.ts +1 -0
  85. package/dist/types/index.d.ts.map +1 -1
  86. package/dist/types/index.js +1 -0
  87. package/dist/types/messaging.d.ts +3 -3
  88. package/dist/types/messaging.d.ts.map +1 -1
  89. package/dist/types/skills.d.ts +13 -0
  90. package/dist/types/skills.d.ts.map +1 -1
  91. package/dist/utils/commandPathResolver.d.ts +3 -36
  92. package/dist/utils/commandPathResolver.d.ts.map +1 -1
  93. package/dist/utils/commandPathResolver.js +16 -93
  94. package/dist/utils/configValidator.d.ts +2 -2
  95. package/dist/utils/configValidator.d.ts.map +1 -1
  96. package/dist/utils/configValidator.js +4 -6
  97. package/dist/utils/containerSetup.d.ts +3 -4
  98. package/dist/utils/containerSetup.d.ts.map +1 -1
  99. package/dist/utils/containerSetup.js +14 -9
  100. package/dist/utils/customCommands.d.ts +2 -3
  101. package/dist/utils/customCommands.d.ts.map +1 -1
  102. package/dist/utils/customCommands.js +20 -60
  103. package/dist/utils/gitUtils.d.ts +25 -0
  104. package/dist/utils/gitUtils.d.ts.map +1 -1
  105. package/dist/utils/gitUtils.js +75 -0
  106. package/dist/utils/markdownParser.d.ts +4 -0
  107. package/dist/utils/markdownParser.d.ts.map +1 -1
  108. package/dist/utils/markdownParser.js +33 -0
  109. package/dist/utils/messageOperations.d.ts +16 -7
  110. package/dist/utils/messageOperations.d.ts.map +1 -1
  111. package/dist/utils/messageOperations.js +45 -20
  112. package/dist/utils/nameGenerator.d.ts +1 -1
  113. package/dist/utils/nameGenerator.d.ts.map +1 -1
  114. package/dist/utils/nameGenerator.js +10 -6
  115. package/dist/utils/skillParser.d.ts.map +1 -1
  116. package/dist/utils/skillParser.js +48 -0
  117. package/package.json +1 -1
  118. package/src/agent.ts +103 -458
  119. package/src/index.ts +2 -2
  120. package/src/managers/aiManager.ts +23 -17
  121. package/src/managers/backgroundTaskManager.ts +2 -2
  122. package/src/managers/{bashManager.ts → bangManager.ts} +11 -8
  123. package/src/managers/hookManager.ts +13 -3
  124. package/src/managers/messageManager.ts +55 -26
  125. package/src/managers/permissionManager.ts +121 -98
  126. package/src/managers/planManager.ts +26 -0
  127. package/src/managers/skillManager.ts +51 -14
  128. package/src/managers/slashCommandManager.ts +75 -55
  129. package/src/managers/subagentManager.ts +57 -13
  130. package/src/managers/toolManager.ts +22 -2
  131. package/src/prompts/index.ts +0 -15
  132. package/src/services/aiService.ts +9 -12
  133. package/src/services/configurationService.ts +4 -4
  134. package/src/services/hook.ts +7 -0
  135. package/src/services/initializationService.ts +291 -0
  136. package/src/services/interactionService.ts +171 -0
  137. package/src/services/session.ts +1 -1
  138. package/src/services/taskManager.ts +18 -2
  139. package/src/tools/bashTool.ts +8 -18
  140. package/src/tools/editTool.ts +1 -1
  141. package/src/tools/exitPlanMode.ts +1 -1
  142. package/src/tools/lsTool.ts +1 -1
  143. package/src/tools/lspTool.ts +184 -52
  144. package/src/tools/skillTool.ts +127 -2
  145. package/src/tools/taskManagementTools.ts +32 -2
  146. package/src/tools/taskTool.ts +13 -15
  147. package/src/tools/types.ts +1 -2
  148. package/src/tools/writeTool.ts +1 -1
  149. package/src/types/agent.ts +83 -0
  150. package/src/types/commands.ts +0 -6
  151. package/src/types/config.ts +1 -1
  152. package/src/types/hooks.ts +5 -1
  153. package/src/types/index.ts +1 -0
  154. package/src/types/messaging.ts +3 -3
  155. package/src/types/skills.ts +13 -0
  156. package/src/utils/commandPathResolver.ts +14 -117
  157. package/src/utils/configValidator.ts +5 -9
  158. package/src/utils/containerSetup.ts +17 -14
  159. package/src/utils/customCommands.ts +20 -83
  160. package/src/utils/gitUtils.ts +75 -0
  161. package/src/utils/markdownParser.ts +47 -0
  162. package/src/utils/messageOperations.ts +58 -28
  163. package/src/utils/nameGenerator.ts +10 -6
  164. package/src/utils/skillParser.ts +52 -0
  165. package/dist/managers/backgroundBashManager.d.ts +0 -27
  166. package/dist/managers/backgroundBashManager.d.ts.map +0 -1
  167. package/dist/managers/backgroundBashManager.js +0 -169
  168. package/src/managers/backgroundBashManager.ts +0 -206
@@ -12,6 +12,28 @@ import { splitBashCommand, stripEnvVars, stripRedirections, getSmartPrefix, DANG
12
12
  import { isPathInside } from "../utils/pathSafety.js";
13
13
  import { BASH_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, READ_TOOL_NAME, LS_TOOL_NAME, } from "../constants/tools.js";
14
14
  const SAFE_COMMANDS = ["cd", "ls", "pwd", "true", "false"];
15
+ const DEFAULT_ALLOWED_RULES = [
16
+ "Bash(git status*)",
17
+ "Bash(git diff*)",
18
+ "Bash(git log*)",
19
+ "Bash(git show*)",
20
+ "Bash(git branch*)",
21
+ "Bash(git tag*)",
22
+ "Bash(git remote*)",
23
+ "Bash(git ls-files*)",
24
+ "Bash(git rev-parse*)",
25
+ "Bash(git config --list*)",
26
+ "Bash(git config -l*)",
27
+ "Bash(git cat-file*)",
28
+ "Bash(git count-objects*)",
29
+ "Bash(echo*)",
30
+ "Bash(which*)",
31
+ "Bash(type*)",
32
+ "Bash(hostname*)",
33
+ "Bash(whoami*)",
34
+ "Bash(date*)",
35
+ "Bash(uptime*)",
36
+ ];
15
37
  import { logger } from "../utils/globalLogger.js";
16
38
  export class PermissionManager {
17
39
  constructor(container, options = {}) {
@@ -39,69 +61,71 @@ export class PermissionManager {
39
61
  */
40
62
  updateConfiguredDefaultMode(defaultMode) {
41
63
  const oldEffectiveMode = this.getCurrentEffectiveMode();
42
- logger?.debug("Updating configured default permission mode", {
43
- previous: this.configuredDefaultMode,
44
- new: defaultMode,
45
- });
46
64
  this.configuredDefaultMode = defaultMode;
47
65
  const newEffectiveMode = this.getCurrentEffectiveMode();
48
66
  if (oldEffectiveMode !== newEffectiveMode &&
49
67
  this.onConfiguredDefaultModeChange) {
50
- logger?.debug("Effective permission mode changed due to configuration update", {
51
- oldMode: oldEffectiveMode,
52
- newMode: newEffectiveMode,
53
- });
54
68
  this.onConfiguredDefaultModeChange(newEffectiveMode);
55
69
  }
56
70
  }
57
71
  /**
58
- * Get all currently allowed rules
72
+ * Get the configured default mode
73
+ */
74
+ getConfiguredDefaultMode() {
75
+ return this.configuredDefaultMode;
76
+ }
77
+ /**
78
+ * Get all currently allowed rules (user-defined)
59
79
  */
60
80
  getAllowedRules() {
61
81
  return [...this.allowedRules];
62
82
  }
83
+ /**
84
+ * Get all currently denied rules
85
+ */
86
+ getDeniedRules() {
87
+ return [...this.deniedRules];
88
+ }
89
+ /**
90
+ * Get all additional directories
91
+ */
92
+ getAdditionalDirectories() {
93
+ return [...this.additionalDirectories];
94
+ }
95
+ /**
96
+ * Get all default allowed rules
97
+ */
98
+ getDefaultAllowedRules() {
99
+ return [...DEFAULT_ALLOWED_RULES];
100
+ }
63
101
  /**
64
102
  * Update the allowed rules (e.g., when configuration reloads)
65
103
  */
66
104
  updateAllowedRules(rules) {
67
- logger?.debug("Updating allowed permission rules", {
68
- count: rules.length,
69
- });
70
105
  this.allowedRules = rules;
71
106
  }
72
107
  /**
73
108
  * Update the denied rules (e.g., when configuration reloads)
74
109
  */
75
110
  updateDeniedRules(rules) {
76
- logger?.debug("Updating denied permission rules", {
77
- count: rules.length,
78
- });
79
111
  this.deniedRules = rules;
80
112
  }
81
113
  /**
82
114
  * Add temporary rules for the current session
83
115
  */
84
116
  addTemporaryRules(rules) {
85
- logger?.debug("Adding temporary permission rules", {
86
- count: rules.length,
87
- rules,
88
- });
89
117
  this.temporaryRules.push(...rules);
90
118
  }
91
119
  /**
92
120
  * Clear all temporary rules
93
121
  */
94
122
  clearTemporaryRules() {
95
- logger?.debug("Clearing temporary permission rules");
96
123
  this.temporaryRules = [];
97
124
  }
98
125
  /**
99
126
  * Update the additional directories (e.g., when configuration reloads)
100
127
  */
101
128
  updateAdditionalDirectories(directories) {
102
- logger?.debug("Updating additional directories", {
103
- count: directories.length,
104
- });
105
129
  this.additionalDirectories = directories.map((dir) => {
106
130
  if (this.workdir && !path.isAbsolute(dir)) {
107
131
  return path.resolve(this.workdir, dir);
@@ -113,16 +137,12 @@ export class PermissionManager {
113
137
  * Update the working directory
114
138
  */
115
139
  updateWorkdir(workdir) {
116
- logger?.debug("Updating working directory", {
117
- workdir,
118
- });
119
140
  this.workdir = workdir;
120
141
  }
121
142
  /**
122
143
  * Set the current plan file path
123
144
  */
124
145
  setPlanFilePath(path) {
125
- logger?.debug("Setting plan file path", { path });
126
146
  this.planFilePath = path;
127
147
  }
128
148
  /**
@@ -150,11 +170,6 @@ export class PermissionManager {
150
170
  return { isInside: true, resolvedPath: absolutePath };
151
171
  }
152
172
  }
153
- logger?.debug("Path is outside Safe Zone", {
154
- absolutePath,
155
- workdir: effectiveWorkdir,
156
- additionalDirectories: this.additionalDirectories,
157
- });
158
173
  return { isInside: false, resolvedPath: absolutePath };
159
174
  }
160
175
  /**
@@ -169,21 +184,13 @@ export class PermissionManager {
169
184
  resolveEffectivePermissionMode(cliPermissionMode) {
170
185
  // CLI override takes highest precedence
171
186
  if (cliPermissionMode !== undefined) {
172
- logger?.debug("Using CLI permission mode override", {
173
- cliMode: cliPermissionMode,
174
- configuredDefault: this.configuredDefaultMode,
175
- });
176
187
  return cliPermissionMode;
177
188
  }
178
189
  // Use configured default mode if available
179
190
  if (this.configuredDefaultMode !== undefined) {
180
- logger?.debug("Using configured default permission mode", {
181
- configuredDefault: this.configuredDefaultMode,
182
- });
183
191
  return this.configuredDefaultMode;
184
192
  }
185
193
  // Fall back to system default
186
- logger?.debug("Using system default permission mode");
187
194
  return "default";
188
195
  }
189
196
  /**
@@ -191,11 +198,6 @@ export class PermissionManager {
191
198
  * Called by individual tools after validation/diff, before real operation
192
199
  */
193
200
  async checkPermission(context) {
194
- logger?.debug("Checking permission for tool", {
195
- toolName: context.toolName,
196
- permissionMode: context.permissionMode,
197
- hasCallback: !!context.canUseToolCallback,
198
- });
199
201
  // 0. Check denied rules first - Deny always takes precedence
200
202
  for (const rule of this.deniedRules) {
201
203
  if (this.matchesRule(context, rule)) {
@@ -211,9 +213,6 @@ export class PermissionManager {
211
213
  }
212
214
  // 1. If bypassPermissions mode, always allow
213
215
  if (context.permissionMode === "bypassPermissions") {
214
- logger?.debug("Permission bypassed for tool", {
215
- toolName: context.toolName,
216
- });
217
216
  return { behavior: "allow" };
218
217
  }
219
218
  // 1.1 If acceptEdits mode, allow Edit, Write
@@ -234,9 +233,6 @@ export class PermissionManager {
234
233
  // Fall through to normal permission check flow to trigger confirmation prompt
235
234
  }
236
235
  else {
237
- logger?.debug("Permission automatically accepted for tool in acceptEdits mode", {
238
- toolName: context.toolName,
239
- });
240
236
  return { behavior: "allow" };
241
237
  }
242
238
  }
@@ -244,9 +240,6 @@ export class PermissionManager {
244
240
  }
245
241
  // 1.2 Check if tool call is allowed by persistent or temporary rules
246
242
  if (this.isAllowedByRule(context)) {
247
- logger?.debug("Permission allowed by persistent rule", {
248
- toolName: context.toolName,
249
- });
250
243
  return { behavior: "allow" };
251
244
  }
252
245
  // 1.3 If plan mode, allow Read-only tools and Edit/Write for plan file
@@ -258,10 +251,6 @@ export class PermissionManager {
258
251
  const absoluteTargetPath = path.resolve(targetPath);
259
252
  const absolutePlanPath = path.resolve(this.planFilePath);
260
253
  if (absoluteTargetPath === absolutePlanPath) {
261
- logger?.debug("Allowing write to plan file in plan mode", {
262
- toolName: context.toolName,
263
- targetPath,
264
- });
265
254
  return { behavior: "allow" };
266
255
  }
267
256
  }
@@ -273,22 +262,18 @@ export class PermissionManager {
273
262
  }
274
263
  // 2. If not a restricted tool, always allow
275
264
  if (!this.isRestrictedTool(context.toolName)) {
276
- logger?.debug("Tool is not restricted, allowing", {
277
- toolName: context.toolName,
278
- });
279
265
  return { behavior: "allow" };
280
266
  }
281
267
  // 3. If custom callback provided, call it and return result
282
268
  if (context.canUseToolCallback) {
283
269
  try {
284
- logger?.debug("Calling custom permission callback for tool", {
285
- toolName: context.toolName,
286
- });
287
270
  const decision = await context.canUseToolCallback(context);
288
- logger?.debug("Custom callback returned decision", {
289
- toolName: context.toolName,
290
- decision,
291
- });
271
+ if (decision.behavior !== "allow") {
272
+ logger?.debug("Custom callback returned decision", {
273
+ toolName: context.toolName,
274
+ decision,
275
+ });
276
+ }
292
277
  return decision;
293
278
  }
294
279
  catch (error) {
@@ -317,12 +302,7 @@ export class PermissionManager {
317
302
  * Determine if a tool requires permission checks based on its name
318
303
  */
319
304
  isRestrictedTool(toolName) {
320
- const isRestricted = RESTRICTED_TOOLS.includes(toolName);
321
- logger?.debug("Checking if tool is restricted", {
322
- toolName,
323
- isRestricted,
324
- });
325
- return isRestricted;
305
+ return RESTRICTED_TOOLS.includes(toolName);
326
306
  }
327
307
  /**
328
308
  * Helper method to create a permission context for CLI integration
@@ -388,13 +368,6 @@ export class PermissionManager {
388
368
  context.hidePersistentOption = true;
389
369
  }
390
370
  }
391
- logger?.debug("Created permission context", {
392
- toolName,
393
- permissionMode,
394
- hasCallback: !!callback,
395
- hasToolInput: !!toolInput,
396
- suggestedPrefix,
397
- });
398
371
  return context;
399
372
  }
400
373
  /**
@@ -424,8 +397,9 @@ export class PermissionManager {
424
397
  const regexPattern = pattern
425
398
  .replace(/[.+^${}()|[\]\\?]/g, "\\$&") // Escape regex special chars including ?
426
399
  .replace(/\*/g, ".*"); // Replace * with .*
427
- const regex = new RegExp(`^${regexPattern}$`);
428
- return regex.test(processedPart);
400
+ const regex = new RegExp(`^${regexPattern}$`, "s");
401
+ const matched = regex.test(processedPart);
402
+ return matched;
429
403
  }
430
404
  // Handle path-based rules (e.g., "Read(**/*.env)")
431
405
  const pathTools = [
@@ -490,7 +464,9 @@ export class PermissionManager {
490
464
  ...ctx,
491
465
  toolInput: { ...ctx.toolInput, command: processedPart },
492
466
  };
493
- const allowedByRule = rules.some((rule) => this.matchesRule(partContext, rule));
467
+ const allowedByRule = rules.some((rule) => {
468
+ return this.matchesRule(partContext, rule);
469
+ });
494
470
  if (allowedByRule)
495
471
  return true;
496
472
  return !this.isRestrictedTool(ctx.toolName);
@@ -504,7 +480,11 @@ export class PermissionManager {
504
480
  return true;
505
481
  }
506
482
  // Check persistent allowed rules
507
- return isAllowedByRuleList(context, this.allowedRules);
483
+ if (isAllowedByRuleList(context, this.allowedRules)) {
484
+ return true;
485
+ }
486
+ // Check default allowed rules
487
+ return isAllowedByRuleList(context, DEFAULT_ALLOWED_RULES);
508
488
  }
509
489
  /**
510
490
  * Expand a bash command into individual permission rules, filtering out safe commands.
@@ -580,4 +560,45 @@ export class PermissionManager {
580
560
  }
581
561
  return rules;
582
562
  }
563
+ /**
564
+ * Add a persistent permission rule
565
+ * @param rule - The rule to add (e.g., "Bash(ls)")
566
+ */
567
+ async addPermissionRule(rule) {
568
+ if (!this.workdir) {
569
+ throw new Error("Working directory not set in PermissionManager");
570
+ }
571
+ // 1. Expand rule if it's a Bash command
572
+ let rulesToAdd = [rule];
573
+ const bashMatch = rule.match(/^Bash\((.*)\)$/);
574
+ if (bashMatch) {
575
+ const command = bashMatch[1];
576
+ rulesToAdd = this.expandBashRule(command, this.workdir);
577
+ }
578
+ const configurationService = this.container.get("ConfigurationService");
579
+ for (const ruleToAdd of rulesToAdd) {
580
+ // 2. Update PermissionManager state
581
+ const currentRules = this.getAllowedRules();
582
+ const defaultRules = this.getDefaultAllowedRules();
583
+ if (!currentRules.includes(ruleToAdd) &&
584
+ !defaultRules.includes(ruleToAdd)) {
585
+ this.updateAllowedRules([...currentRules, ruleToAdd]);
586
+ // 3. Persist to settings.local.json
587
+ try {
588
+ if (configurationService) {
589
+ await configurationService.addAllowedRule(this.workdir, ruleToAdd);
590
+ this._logger?.debug("Persistent permission rule added", {
591
+ rule: ruleToAdd,
592
+ });
593
+ }
594
+ }
595
+ catch (error) {
596
+ this._logger?.error("Failed to persist permission rule", {
597
+ rule: ruleToAdd,
598
+ error: error instanceof Error ? error.message : String(error),
599
+ });
600
+ }
601
+ }
602
+ }
603
+ }
583
604
  }
@@ -1,4 +1,5 @@
1
1
  import { Container } from "../utils/container.js";
2
+ import type { PermissionMode } from "../types/permissions.js";
2
3
  export declare class PlanManager {
3
4
  private container;
4
5
  private planDir;
@@ -15,5 +16,10 @@ export declare class PlanManager {
15
16
  * Returns the directory where plan files are stored
16
17
  */
17
18
  getPlanDir(): string;
19
+ /**
20
+ * Handle plan mode transition, generating or clearing plan file path
21
+ * @param mode - The current effective permission mode
22
+ */
23
+ handlePlanModeTransition(mode: PermissionMode): void;
18
24
  }
19
25
  //# sourceMappingURL=planManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"planManager.d.ts","sourceRoot":"","sources":["../../src/managers/planManager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOlD,qBAAa,WAAW;IAIV,OAAO,CAAC,SAAS;IAH7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,mBAAmB,CAAuB;gBAE9B,SAAS,EAAE,SAAS;IAIxC;;OAEG;IACU,yBAAyB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7D,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IA+BF;;OAEG;IACI,UAAU,IAAI,MAAM;CAG5B"}
1
+ {"version":3,"file":"planManager.d.ts","sourceRoot":"","sources":["../../src/managers/planManager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAO9D,qBAAa,WAAW;IAIV,OAAO,CAAC,SAAS;IAH7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,mBAAmB,CAAuB;gBAE9B,SAAS,EAAE,SAAS;IAIxC;;OAEG;IACU,yBAAyB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7D,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IA+BF;;OAEG;IACI,UAAU,IAAI,MAAM;IAI3B;;;OAGG;IACI,wBAAwB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;CAkB5D"}
@@ -46,4 +46,25 @@ export class PlanManager {
46
46
  getPlanDir() {
47
47
  return this.planDir;
48
48
  }
49
+ /**
50
+ * Handle plan mode transition, generating or clearing plan file path
51
+ * @param mode - The current effective permission mode
52
+ */
53
+ handlePlanModeTransition(mode) {
54
+ const permissionManager = this.container.get("PermissionManager");
55
+ const messageManager = this.container.get("MessageManager");
56
+ if (mode === "plan") {
57
+ this.getOrGeneratePlanFilePath(messageManager?.getRootSessionId())
58
+ .then(({ path }) => {
59
+ logger?.debug("Plan file path generated", { path });
60
+ permissionManager?.setPlanFilePath(path);
61
+ })
62
+ .catch((error) => {
63
+ logger?.error("Failed to generate plan file path", error);
64
+ });
65
+ }
66
+ else {
67
+ permissionManager?.setPlanFilePath(undefined);
68
+ }
69
+ }
49
70
  }
@@ -24,6 +24,10 @@ export declare class SkillManager {
24
24
  * Get all available skills metadata
25
25
  */
26
26
  getAvailableSkills(): SkillMetadata[];
27
+ /**
28
+ * Get metadata for a specific skill by name
29
+ */
30
+ getSkillMetadata(name: string): SkillMetadata | undefined;
27
31
  /**
28
32
  * Load a specific skill by name
29
33
  * Returns the skill content that was loaded during initialization
@@ -47,11 +51,12 @@ export declare class SkillManager {
47
51
  executeSkill(args: SkillToolArgs): Promise<{
48
52
  content: string;
49
53
  context?: SkillInvocationContext;
54
+ allowedTools?: string[];
50
55
  }>;
51
56
  /**
52
- * Format skill content for output
57
+ * Process skill content with arguments and bash commands
53
58
  */
54
- private formatSkillContent;
59
+ private processSkillContent;
55
60
  /**
56
61
  * Format available skills list for error messages
57
62
  */
@@ -1 +1 @@
1
- {"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAY;IAUrB,OAAO,CAAC,SAAS;IATnB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAS;gBAGlB,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,mBAAwB;IAQnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCjC;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IAkB5B;;OAEG;YACW,uBAAuB;IAiFrC;;OAEG;YACW,oBAAoB;IAkBlC;;OAEG;IACG,YAAY,CAChB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,sBAAsB,CAAA;KAAE,CAAC;IAqCjE;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;CAc5C"}
1
+ {"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAY;IAUrB,OAAO,CAAC,SAAS;IATnB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAS;gBAGlB,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,mBAAwB;IAQnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCjC;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAQzD;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IAkB5B;;OAEG;YACW,uBAAuB;IA8ErC;;OAEG;YACW,oBAAoB;IAkBlC;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,sBAAsB,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IA4CF;;OAEG;YACW,mBAAmB;IAyBjC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;CAe5C"}
@@ -2,6 +2,8 @@ import { readdir, stat } from "fs/promises";
2
2
  import { join } from "path";
3
3
  import { homedir } from "os";
4
4
  import { parseSkillFile, formatSkillError } from "../utils/skillParser.js";
5
+ import { substituteCommandParameters } from "../utils/commandArgumentParser.js";
6
+ import { parseBashCommands, replaceBashCommandsWithOutput, executeBashCommands, } from "../utils/markdownParser.js";
5
7
  import { logger } from "../utils/globalLogger.js";
6
8
  /**
7
9
  * Manages skill discovery and loading
@@ -64,6 +66,15 @@ export class SkillManager {
64
66
  }
65
67
  return Array.from(this.skillMetadata.values());
66
68
  }
69
+ /**
70
+ * Get metadata for a specific skill by name
71
+ */
72
+ getSkillMetadata(name) {
73
+ if (!this.initialized) {
74
+ throw new Error("SkillManager not initialized. Call initialize() first.");
75
+ }
76
+ return this.skillMetadata.get(name);
77
+ }
67
78
  /**
68
79
  * Load a specific skill by name
69
80
  * Returns the skill content that was loaded during initialization
@@ -129,10 +140,7 @@ export class SkillManager {
129
140
  };
130
141
  // Create full skill object with content
131
142
  const skill = {
132
- name: parsed.skillMetadata.name,
133
- description: parsed.skillMetadata.description,
134
- type: type, // Use the collection type
135
- skillPath: parsed.skillMetadata.skillPath,
143
+ ...skillMetadata,
136
144
  content: parsed.content,
137
145
  frontmatter: parsed.frontmatter,
138
146
  isValid: parsed.isValid,
@@ -185,8 +193,8 @@ export class SkillManager {
185
193
  * Execute a skill by name
186
194
  */
187
195
  async executeSkill(args) {
188
- const { skill_name } = args;
189
- logger?.debug(`Invoking skill: ${skill_name}`);
196
+ const { skill_name, args: skillArgs } = args;
197
+ logger?.debug(`Invoking skill: ${skill_name} with args: ${skillArgs}`);
190
198
  try {
191
199
  // Load the skill
192
200
  const skill = await this.loadSkill(skill_name);
@@ -201,12 +209,15 @@ export class SkillManager {
201
209
  content: `❌ **Skill validation failed**:\n\n\`\`\`\n${errorMsg}\n\`\`\``,
202
210
  };
203
211
  }
212
+ // Process skill content with arguments and bash commands
213
+ const processedContent = await this.processSkillContent(skill, skillArgs || "");
204
214
  // Return skill content with context
205
215
  return {
206
- content: this.formatSkillContent(skill),
216
+ content: processedContent,
207
217
  context: {
208
218
  skillName: skill_name,
209
219
  },
220
+ allowedTools: skill.allowedTools,
210
221
  };
211
222
  }
212
223
  catch (error) {
@@ -217,15 +228,23 @@ export class SkillManager {
217
228
  }
218
229
  }
219
230
  /**
220
- * Format skill content for output
231
+ * Process skill content with arguments and bash commands
221
232
  */
222
- formatSkillContent(skill) {
233
+ async processSkillContent(skill, argsString) {
223
234
  const header = `🧠 **${skill.name}** (${skill.type} skill)\n\n`;
224
235
  const description = `*${skill.description}*\n\n`;
225
236
  const skillPath = `📁 Skill location: \`${skill.skillPath}\`\n\n`;
226
237
  // Extract content after frontmatter
227
238
  const contentMatch = skill.content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
228
- const mainContent = contentMatch ? contentMatch[1].trim() : skill.content;
239
+ let mainContent = contentMatch ? contentMatch[1].trim() : skill.content;
240
+ // 1. Substitute parameters ($1, $ARGUMENTS, etc.)
241
+ mainContent = substituteCommandParameters(mainContent, argsString);
242
+ // 2. Parse and execute bash commands (!`command`)
243
+ const { commands } = parseBashCommands(mainContent);
244
+ if (commands.length > 0) {
245
+ const results = await executeBashCommands(commands, this.workdir);
246
+ mainContent = replaceBashCommandsWithOutput(mainContent, results);
247
+ }
229
248
  return header + description + skillPath + mainContent;
230
249
  }
231
250
  /**
@@ -250,6 +269,7 @@ export class SkillManager {
250
269
  description: skill.description,
251
270
  type: skill.type,
252
271
  skillPath: skill.skillPath,
272
+ allowedTools: skill.allowedTools,
253
273
  });
254
274
  this.skillContent.set(skill.name, skill);
255
275
  }
@@ -1,5 +1,6 @@
1
1
  import type { SlashCommand, CustomSlashCommand } from "../types/index.js";
2
2
  import { Container } from "../utils/container.js";
3
+ import type { SkillMetadata } from "../types/skills.js";
3
4
  export interface SlashCommandManagerOptions {
4
5
  workdir: string;
5
6
  }
@@ -7,6 +8,7 @@ export declare class SlashCommandManager {
7
8
  private container;
8
9
  private commands;
9
10
  private customCommands;
11
+ private skillCommandIds;
10
12
  private workdir;
11
13
  constructor(container: Container, options: SlashCommandManagerOptions);
12
14
  initialize(): void;
@@ -14,11 +16,16 @@ export declare class SlashCommandManager {
14
16
  private get aiManager();
15
17
  private get backgroundTaskManager();
16
18
  private get taskManager();
19
+ private get skillManager();
17
20
  private initializeBuiltinCommands;
18
21
  /**
19
22
  * Load custom commands from filesystem
20
23
  */
21
24
  private loadCustomCommands;
25
+ /**
26
+ * Register skills as slash commands
27
+ */
28
+ registerSkillCommands(skills: SkillMetadata[]): void;
22
29
  /**
23
30
  * Register commands from a plugin with namespacing
24
31
  */
@@ -1 +1 @@
1
- {"version":3,"file":"slashCommandManager.d.ts","sourceRoot":"","sources":["../../src/managers/slashCommandManager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQ1E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAclD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,mBAAmB;IAM5B,OAAO,CAAC,SAAS;IALnB,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,OAAO,CAAS;gBAGd,SAAS,EAAE,SAAS,EAC5B,OAAO,EAAE,0BAA0B;IAK9B,UAAU,IAAI,IAAI;IAKzB,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,qBAAqB,GAEhC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,CAAC,yBAAyB;IAsCjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyD1B;;OAEG;IACI,sBAAsB,CAC3B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,kBAAkB,EAAE,GAC7B,IAAI;IAwDP;;OAEG;IACI,oBAAoB,IAAI,IAAI;IAWnC;;OAEG;IACI,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAKnD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACI,WAAW,IAAI,YAAY,EAAE;IAIpC;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI9D;;OAEG;IACU,cAAc,CACzB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC;IAenB;;;OAGG;IACI,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG;QAClD,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;IAeD;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI7C;;OAEG;IACI,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI1E;;OAEG;IACI,iBAAiB,IAAI,kBAAkB,EAAE;IAIhD;;OAEG;YACW,+BAA+B;IA0E7C;;OAEG;IACI,mBAAmB,IAAI,IAAI;CAInC"}
1
+ {"version":3,"file":"slashCommandManager.d.ts","sourceRoot":"","sources":["../../src/managers/slashCommandManager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQ1E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAQlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,mBAAmB;IAO5B,OAAO,CAAC,SAAS;IANnB,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,OAAO,CAAS;gBAGd,SAAS,EAAE,SAAS,EAC5B,OAAO,EAAE,0BAA0B;IAK9B,UAAU,IAAI,IAAI;IAKzB,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,qBAAqB,GAEhC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,CAAC,yBAAyB;IAoBjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyD1B;;OAEG;IACI,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI;IAyD3D;;OAEG;IACI,sBAAsB,CAC3B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,kBAAkB,EAAE,GAC7B,IAAI;IAwDP;;OAEG;IACI,oBAAoB,IAAI,IAAI;IAWnC;;OAEG;IACI,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAKnD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACI,WAAW,IAAI,YAAY,EAAE;IAIpC;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI9D;;OAEG;IACU,cAAc,CACzB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC;IAenB;;;OAGG;IACI,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG;QAClD,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;IAeD;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI7C;;OAEG;IACI,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI1E;;OAEG;IACI,iBAAiB,IAAI,kBAAkB,EAAE;IAIhD;;OAEG;YACW,+BAA+B;IAiD7C;;OAEG;IACI,mBAAmB,IAAI,IAAI;CAInC"}