wave-agent-sdk 0.10.4 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/builtin/skills/init/SKILL.md +26 -0
  2. package/builtin/skills/loop/SKILL.md +53 -0
  3. package/builtin/skills/settings/ENV.md +64 -0
  4. package/builtin/skills/settings/HOOKS.md +94 -0
  5. package/builtin/skills/settings/MCP.md +55 -0
  6. package/builtin/skills/settings/MEMORY_RULES.md +60 -0
  7. package/{dist/builtin-skills → builtin/skills}/settings/SKILL.md +23 -16
  8. package/builtin/skills/settings/SKILLS.md +63 -0
  9. package/builtin/skills/settings/SUBAGENTS.md +60 -0
  10. package/builtin/subagents/bash.md +18 -0
  11. package/builtin/subagents/explore.md +42 -0
  12. package/builtin/subagents/general-purpose.md +20 -0
  13. package/builtin/subagents/plan.md +55 -0
  14. package/dist/agent.d.ts +8 -6
  15. package/dist/agent.d.ts.map +1 -1
  16. package/dist/agent.js +12 -9
  17. package/dist/constants/tools.d.ts +3 -0
  18. package/dist/constants/tools.d.ts.map +1 -1
  19. package/dist/constants/tools.js +3 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -0
  23. package/dist/managers/aiManager.d.ts +0 -2
  24. package/dist/managers/aiManager.d.ts.map +1 -1
  25. package/dist/managers/aiManager.js +53 -14
  26. package/dist/managers/cronManager.d.ts +19 -0
  27. package/dist/managers/cronManager.d.ts.map +1 -0
  28. package/dist/managers/cronManager.js +124 -0
  29. package/dist/managers/hookManager.d.ts.map +1 -1
  30. package/dist/managers/hookManager.js +21 -13
  31. package/dist/managers/liveConfigManager.js +1 -1
  32. package/dist/managers/mcpManager.d.ts +1 -1
  33. package/dist/managers/mcpManager.d.ts.map +1 -1
  34. package/dist/managers/mcpManager.js +10 -2
  35. package/dist/managers/messageManager.d.ts +0 -1
  36. package/dist/managers/messageManager.d.ts.map +1 -1
  37. package/dist/managers/permissionManager.d.ts +27 -7
  38. package/dist/managers/permissionManager.d.ts.map +1 -1
  39. package/dist/managers/permissionManager.js +119 -14
  40. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  41. package/dist/managers/slashCommandManager.js +7 -12
  42. package/dist/managers/subagentManager.d.ts +3 -0
  43. package/dist/managers/subagentManager.d.ts.map +1 -1
  44. package/dist/managers/subagentManager.js +10 -17
  45. package/dist/managers/toolManager.d.ts +1 -1
  46. package/dist/managers/toolManager.d.ts.map +1 -1
  47. package/dist/managers/toolManager.js +28 -4
  48. package/dist/prompts/index.d.ts +0 -5
  49. package/dist/prompts/index.d.ts.map +1 -1
  50. package/dist/prompts/index.js +1 -136
  51. package/dist/services/configurationService.d.ts.map +1 -1
  52. package/dist/services/configurationService.js +8 -7
  53. package/dist/services/hook.d.ts.map +1 -1
  54. package/dist/services/hook.js +3 -10
  55. package/dist/services/initializationService.js +2 -2
  56. package/dist/services/jsonlHandler.d.ts.map +1 -1
  57. package/dist/services/jsonlHandler.js +3 -0
  58. package/dist/services/reversionService.d.ts +2 -2
  59. package/dist/services/reversionService.d.ts.map +1 -1
  60. package/dist/services/reversionService.js +3 -3
  61. package/dist/services/session.d.ts.map +1 -1
  62. package/dist/services/session.js +18 -11
  63. package/dist/tools/agentTool.js +1 -1
  64. package/dist/tools/bashTool.d.ts.map +1 -1
  65. package/dist/tools/bashTool.js +5 -5
  66. package/dist/tools/cronCreateTool.d.ts +3 -0
  67. package/dist/tools/cronCreateTool.d.ts.map +1 -0
  68. package/dist/tools/cronCreateTool.js +59 -0
  69. package/dist/tools/cronDeleteTool.d.ts +3 -0
  70. package/dist/tools/cronDeleteTool.d.ts.map +1 -0
  71. package/dist/tools/cronDeleteTool.js +38 -0
  72. package/dist/tools/cronListTool.d.ts +3 -0
  73. package/dist/tools/cronListTool.d.ts.map +1 -0
  74. package/dist/tools/cronListTool.js +30 -0
  75. package/dist/tools/skillTool.d.ts +0 -3
  76. package/dist/tools/skillTool.d.ts.map +1 -1
  77. package/dist/tools/skillTool.js +4 -3
  78. package/dist/tools/taskOutputTool.d.ts.map +1 -1
  79. package/dist/tools/taskOutputTool.js +15 -8
  80. package/dist/tools/types.d.ts +2 -0
  81. package/dist/tools/types.d.ts.map +1 -1
  82. package/dist/types/agent.d.ts +10 -0
  83. package/dist/types/agent.d.ts.map +1 -1
  84. package/dist/types/configuration.d.ts +1 -1
  85. package/dist/types/configuration.d.ts.map +1 -1
  86. package/dist/types/cron.d.ts +10 -0
  87. package/dist/types/cron.d.ts.map +1 -0
  88. package/dist/types/cron.js +1 -0
  89. package/dist/types/hooks.d.ts +1 -5
  90. package/dist/types/hooks.d.ts.map +1 -1
  91. package/dist/types/hooks.js +1 -1
  92. package/dist/types/index.d.ts +1 -0
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/dist/types/index.js +1 -0
  95. package/dist/types/messaging.d.ts +1 -1
  96. package/dist/types/messaging.d.ts.map +1 -1
  97. package/dist/utils/configPaths.d.ts +4 -0
  98. package/dist/utils/configPaths.d.ts.map +1 -1
  99. package/dist/utils/configPaths.js +11 -9
  100. package/dist/utils/containerSetup.d.ts.map +1 -1
  101. package/dist/utils/containerSetup.js +40 -13
  102. package/dist/utils/fileSearch.d.ts.map +1 -1
  103. package/dist/utils/fileSearch.js +7 -1
  104. package/dist/utils/mcpUtils.d.ts +2 -2
  105. package/dist/utils/mcpUtils.d.ts.map +1 -1
  106. package/dist/utils/mcpUtils.js +1 -5
  107. package/dist/utils/subagentParser.d.ts.map +1 -1
  108. package/dist/utils/subagentParser.js +14 -4
  109. package/package.json +4 -2
  110. package/src/agent.ts +17 -12
  111. package/src/constants/tools.ts +3 -0
  112. package/src/index.ts +1 -0
  113. package/src/managers/aiManager.ts +72 -24
  114. package/src/managers/cronManager.ts +167 -0
  115. package/src/managers/hookManager.ts +27 -13
  116. package/src/managers/liveConfigManager.ts +2 -2
  117. package/src/managers/mcpManager.ts +23 -2
  118. package/src/managers/messageManager.ts +0 -6
  119. package/src/managers/permissionManager.ts +154 -18
  120. package/src/managers/slashCommandManager.ts +7 -14
  121. package/src/managers/subagentManager.ts +15 -19
  122. package/src/managers/toolManager.ts +37 -4
  123. package/src/prompts/index.ts +0 -144
  124. package/src/services/configurationService.ts +8 -7
  125. package/src/services/hook.ts +5 -11
  126. package/src/services/initializationService.ts +3 -3
  127. package/src/services/jsonlHandler.ts +4 -0
  128. package/src/services/reversionService.ts +9 -4
  129. package/src/services/session.ts +19 -12
  130. package/src/tools/agentTool.ts +1 -1
  131. package/src/tools/bashTool.ts +6 -5
  132. package/src/tools/cronCreateTool.ts +73 -0
  133. package/src/tools/cronDeleteTool.ts +47 -0
  134. package/src/tools/cronListTool.ts +38 -0
  135. package/src/tools/skillTool.ts +6 -4
  136. package/src/tools/taskOutputTool.ts +14 -8
  137. package/src/tools/types.ts +2 -0
  138. package/src/types/agent.ts +10 -0
  139. package/src/types/configuration.ts +1 -1
  140. package/src/types/cron.ts +9 -0
  141. package/src/types/hooks.ts +5 -9
  142. package/src/types/index.ts +1 -0
  143. package/src/types/messaging.ts +1 -1
  144. package/src/utils/configPaths.ts +12 -10
  145. package/src/utils/containerSetup.ts +50 -16
  146. package/src/utils/fileSearch.ts +7 -1
  147. package/src/utils/mcpUtils.ts +2 -5
  148. package/src/utils/subagentParser.ts +16 -6
  149. package/dist/builtin-skills/settings/HOOKS.md +0 -95
  150. package/dist/utils/builtinSubagents.d.ts +0 -7
  151. package/dist/utils/builtinSubagents.d.ts.map +0 -1
  152. package/dist/utils/builtinSubagents.js +0 -94
  153. package/src/builtin-skills/settings/HOOKS.md +0 -95
  154. package/src/builtin-skills/settings/SKILL.md +0 -86
  155. package/src/utils/builtinSubagents.ts +0 -122
@@ -19,7 +19,7 @@ export type HookEvent =
19
19
  | "UserPromptSubmit"
20
20
  | "Stop"
21
21
  | "SubagentStop"
22
- | "Notification"
22
+ | "PermissionRequest"
23
23
  | "WorktreeCreate";
24
24
 
25
25
  // Individual hook command configuration
@@ -100,7 +100,7 @@ export function isValidHookEvent(event: string): event is HookEvent {
100
100
  "UserPromptSubmit",
101
101
  "Stop",
102
102
  "SubagentStop",
103
- "Notification",
103
+ "PermissionRequest",
104
104
  "WorktreeCreate",
105
105
  ].includes(event);
106
106
  }
@@ -154,16 +154,14 @@ export interface HookJsonInput {
154
154
  session_id: string; // Format: "wave_session_{uuid}_{shortId}"
155
155
  transcript_path: string; // Format: "~/.wave/sessions/session_{shortId}.json"
156
156
  cwd: string; // Absolute path to current working directory
157
- hook_event_name: HookEvent; // "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "Notification"
157
+ hook_event_name: HookEvent; // "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "PermissionRequest" | "WorktreeCreate"
158
158
 
159
159
  // Optional fields based on event type
160
- tool_name?: string; // Present for PreToolUse, PostToolUse
161
- tool_input?: unknown; // Present for PreToolUse, PostToolUse
160
+ tool_name?: string; // Present for PreToolUse, PostToolUse, PermissionRequest
161
+ tool_input?: unknown; // Present for PreToolUse, PostToolUse, PermissionRequest
162
162
  tool_response?: unknown; // Present for PostToolUse only
163
163
  user_prompt?: string; // Present for UserPromptSubmit only
164
164
  subagent_type?: string; // Present when hook is executed by a subagent
165
- message?: string; // Present for Notification events
166
- notification_type?: string; // Present for Notification events
167
165
  name?: string; // Present for WorktreeCreate events
168
166
  }
169
167
 
@@ -177,8 +175,6 @@ export interface ExtendedHookExecutionContext extends HookExecutionContext {
177
175
  env?: Record<string, string>; // Additional environment variables (from configuration)
178
176
  userPrompt?: string; // User prompt text (UserPromptSubmit only)
179
177
  subagentType?: string; // Subagent type when hook is executed by a subagent
180
- message?: string; // Notification message (Notification only)
181
- notificationType?: string; // Notification type (Notification only)
182
178
  worktreeName?: string; // Worktree name (WorktreeCreate only)
183
179
  }
184
180
 
@@ -35,3 +35,4 @@ export * from "./memoryRule.js";
35
35
  export * from "./history.js";
36
36
  export * from "./tasks.js";
37
37
  export * from "./agent.js";
38
+ export * from "./cron.js";
@@ -11,7 +11,7 @@ export enum MessageSource {
11
11
  }
12
12
 
13
13
  export interface Message {
14
- id?: string; // Unique identifier for the message
14
+ id: string; // Unique identifier for the message
15
15
  role: "user" | "assistant";
16
16
  blocks: MessageBlock[];
17
17
  usage?: Usage; // Usage data for this message's AI operation (assistant messages only)
@@ -22,16 +22,18 @@ const __dirname = dirname(__filename);
22
22
  * Get the builtin skills directory path
23
23
  */
24
24
  export function getBuiltinSkillsDir(): string {
25
- // In development, it's in src/builtin-skills
26
- // In production (dist), it should be in dist/builtin-skills
27
- // We'll look for it relative to this file
28
- const devPath = join(__dirname, "..", "builtin-skills");
29
- const prodPath = join(__dirname, "builtin-skills");
30
-
31
- if (existsSync(devPath)) {
32
- return devPath;
33
- }
34
- return prodPath;
25
+ // Builtin skills are now in the 'builtin/skills' directory at the root of the package
26
+ // Relative to this file (src/utils/configPaths.ts), it's ../../builtin/skills
27
+ return join(__dirname, "..", "..", "builtin", "skills");
28
+ }
29
+
30
+ /**
31
+ * Get the builtin subagents directory path
32
+ */
33
+ export function getBuiltinSubagentsDir(): string {
34
+ // Builtin subagents are now in the 'builtin/subagents' directory at the root of the package
35
+ // Relative to this file (src/utils/configPaths.ts), it's ../../builtin/subagents
36
+ return join(__dirname, "..", "..", "builtin", "subagents");
35
37
  }
36
38
 
37
39
  /**
@@ -14,6 +14,7 @@ import { SkillManager } from "../managers/skillManager.js";
14
14
  import { SlashCommandManager } from "../managers/slashCommandManager.js";
15
15
  import { PluginManager } from "../managers/pluginManager.js";
16
16
  import { BangManager } from "../managers/bangManager.js";
17
+ import { CronManager } from "../managers/cronManager.js";
17
18
  import { MemoryRuleManager } from "../managers/MemoryRuleManager.js";
18
19
  import { ReversionManager } from "../managers/reversionManager.js";
19
20
  import { SubagentManager } from "../managers/subagentManager.js";
@@ -21,6 +22,7 @@ import { LiveConfigManager } from "../managers/liveConfigManager.js";
21
22
  import { ConfigurationService } from "../services/configurationService.js";
22
23
  import { ReversionService } from "../services/reversionService.js";
23
24
  import { MemoryService } from "../services/memory.js";
25
+ import { getGitMainRepoRoot } from "./gitUtils.js";
24
26
  import type { AgentOptions } from "../types/index.js";
25
27
  import type {
26
28
  PermissionMode,
@@ -69,11 +71,17 @@ export function setupAgentContainer(
69
71
 
70
72
  const callbacks = options.callbacks || {};
71
73
  const container = new Container();
74
+ container.register("AgentOptions", options);
72
75
 
73
76
  const foregroundTaskManager = new ForegroundTaskManager(container);
74
77
  container.register("ForegroundTaskManager", foregroundTaskManager);
75
78
  container.register("ConfigurationService", configurationService);
76
79
 
80
+ if (options.worktreeName) {
81
+ container.register("WorktreeName", options.worktreeName);
82
+ container.register("MainRepoRoot", getGitMainRepoRoot(workdir));
83
+ }
84
+
77
85
  const memoryService = new MemoryService(container);
78
86
  container.register("MemoryService", memoryService);
79
87
 
@@ -130,13 +138,17 @@ export function setupAgentContainer(
130
138
  const lspManager = options.lspManager || new LspManager(container);
131
139
  container.register("LspManager", lspManager);
132
140
 
133
- const permissionManager = new PermissionManager(container, { workdir });
141
+ const permissionManager = new PermissionManager(container, {
142
+ workdir,
143
+ instanceAllowedRules: options.allowedTools,
144
+ instanceDeniedRules: options.disallowedTools,
145
+ });
134
146
  if (configurationService.resolveAutoMemoryEnabled()) {
135
147
  const autoMemoryDir = memoryService.getAutoMemoryDirectory(workdir);
136
148
  permissionManager.addSystemAdditionalDirectory(autoMemoryDir);
137
149
  }
138
150
  container.register("PermissionManager", permissionManager);
139
- permissionManager.setOnConfiguredDefaultModeChange((mode) => {
151
+ permissionManager.setOnConfiguredPermissionModeChange((mode) => {
140
152
  handlePlanModeTransition(mode);
141
153
  onPermissionModeChange(mode);
142
154
  });
@@ -153,30 +165,45 @@ export function setupAgentContainer(
153
165
  });
154
166
  container.register("SkillManager", skillManager);
155
167
 
156
- container.register(
157
- "ReversionService",
158
- new ReversionService(messageManager.getTranscriptPath()),
159
- );
168
+ const rootSessionId = messageManager.getRootSessionId();
169
+
170
+ container.register("ReversionService", new ReversionService(rootSessionId));
160
171
  const reversionManager = new ReversionManager(container);
161
172
  container.register("ReversionManager", reversionManager);
162
173
 
163
- const canUseToolWithNotification = options.canUseTool
174
+ const canUseToolWithPermissionRequest = options.canUseTool
164
175
  ? async (context: ToolPermissionContext) => {
165
176
  try {
166
- const notificationMessage = `Claude needs your permission to use ${context.toolName}`;
167
- await hookManager.executeHooks("Notification", {
168
- event: "Notification",
177
+ const results = await hookManager.executeHooks("PermissionRequest", {
178
+ event: "PermissionRequest",
169
179
  projectDir: workdir,
170
180
  timestamp: new Date(),
171
181
  sessionId: messageManager.getSessionId(),
172
182
  transcriptPath: messageManager.getTranscriptPath(),
173
183
  cwd: workdir,
174
- message: notificationMessage,
175
- notificationType: "permission_prompt",
184
+ toolName: context.toolName,
185
+ toolInput: context.toolInput,
176
186
  env: configurationService.getEnvironmentVars(),
177
187
  });
188
+
189
+ if (results.length > 0) {
190
+ const processResult = hookManager.processHookResults(
191
+ "PermissionRequest",
192
+ results,
193
+ messageManager,
194
+ );
195
+
196
+ if (processResult.shouldBlock) {
197
+ return {
198
+ behavior: "deny",
199
+ message:
200
+ processResult.errorMessage ||
201
+ "Permission denied by hook execution",
202
+ };
203
+ }
204
+ }
178
205
  } catch (error) {
179
- logger.warn("Failed to execute notification hooks", {
206
+ logger.warn("Failed to execute permission request hooks", {
180
207
  toolName: context.toolName,
181
208
  error: error instanceof Error ? error.message : String(error),
182
209
  });
@@ -215,9 +242,9 @@ export function setupAgentContainer(
215
242
 
216
243
  container.register("PermissionMode", options.permissionMode);
217
244
  logger.info("Registering CanUseToolCallback", {
218
- hasCallback: !!canUseToolWithNotification,
245
+ hasCallback: !!canUseToolWithPermissionRequest,
219
246
  });
220
- container.register("CanUseToolCallback", canUseToolWithNotification);
247
+ container.register("CanUseToolCallback", canUseToolWithPermissionRequest);
221
248
 
222
249
  const liveConfigManager = new LiveConfigManager(container, { workdir });
223
250
  container.register("LiveConfigManager", liveConfigManager);
@@ -233,11 +260,14 @@ export function setupAgentContainer(
233
260
  onSubagentAssistantReasoningUpdated:
234
261
  callbacks.onSubagentAssistantReasoningUpdated,
235
262
  onSubagentToolBlockUpdated: callbacks.onSubagentToolBlockUpdated,
236
- onSubagentMessagesChange: callbacks.onSubagentMessagesChange,
263
+ onSubagentMessagesChange: (subagentId, messages) => {
264
+ callbacks.onSubagentMessagesChange?.(subagentId, messages);
265
+ },
237
266
  onSubagentLatestTotalTokensChange:
238
267
  callbacks.onSubagentLatestTotalTokensChange,
239
268
  },
240
269
  onUsageAdded: (usage: Usage) => addUsage(usage),
270
+ stream,
241
271
  });
242
272
  container.register("SubagentManager", subagentManager);
243
273
 
@@ -262,5 +292,9 @@ export function setupAgentContainer(
262
292
  const bangManager = new BangManager(container, { workdir });
263
293
  container.register("BangManager", bangManager);
264
294
 
295
+ const cronManager = new CronManager(container);
296
+ container.register("CronManager", cronManager);
297
+ cronManager.start();
298
+
265
299
  return container;
266
300
  }
@@ -4,6 +4,8 @@ import fuzzysort from "fuzzysort";
4
4
  import type { FileItem } from "../types/fileSearch.js";
5
5
  import { logger } from "./globalLogger.js";
6
6
 
7
+ const EXCLUDED_FILES = [".git", ".DS_Store"];
8
+
7
9
  /**
8
10
  * Execute ripgrep to get all file paths
9
11
  */
@@ -39,7 +41,11 @@ async function getAllFiles(workingDirectory: string): Promise<string[]> {
39
41
  const files = stdout
40
42
  .trim()
41
43
  .split("\n")
42
- .filter((f) => f.length > 0)
44
+ .filter((f) => {
45
+ if (f.length === 0) return false;
46
+ const parts = f.split(/[/\\]/);
47
+ return !parts.some((part) => EXCLUDED_FILES.includes(part));
48
+ })
43
49
  .map((f) => f.replace(/\\/g, "/")); // Normalize to forward slashes
44
50
  resolve(files);
45
51
  });
@@ -79,6 +79,7 @@ export function createMcpToolPlugin(
79
79
  executeTool: (
80
80
  name: string,
81
81
  args: Record<string, unknown>,
82
+ context?: ToolContext,
82
83
  ) => Promise<{
83
84
  success: boolean;
84
85
  content: string;
@@ -95,11 +96,7 @@ export function createMcpToolPlugin(
95
96
  context?: ToolContext,
96
97
  ): Promise<ToolResult> {
97
98
  try {
98
- // Context is available for future use when MCP tools need execution context
99
- if (context) {
100
- // Future: Could pass working directory or other context to MCP tools
101
- }
102
- const result = await executeTool(prefixedName, args);
99
+ const result = await executeTool(prefixedName, args, context);
103
100
  return {
104
101
  success: true,
105
102
  content: result.content || `Executed ${mcpTool.name}`,
@@ -1,6 +1,7 @@
1
1
  import { readFileSync, readdirSync, statSync } from "fs";
2
- import { join, extname } from "path";
2
+ import { join, extname, basename } from "path";
3
3
  import { logger } from "./globalLogger.js";
4
+ import { getBuiltinSubagentsDir } from "./configPaths.js";
4
5
 
5
6
  export interface SubagentConfiguration {
6
7
  name: string;
@@ -122,18 +123,27 @@ function validateConfiguration(
122
123
  */
123
124
  function parseSubagentFile(
124
125
  filePath: string,
125
- scope: "project" | "user",
126
+ scope: "project" | "user" | "builtin",
126
127
  ): SubagentConfiguration {
127
128
  try {
128
129
  const content = readFileSync(filePath, "utf-8");
129
130
  const { frontmatter, body } = parseFrontmatter(content);
130
131
 
132
+ // Use filename as default name if not specified in frontmatter
133
+ if (!frontmatter.name) {
134
+ frontmatter.name = basename(filePath, extname(filePath));
135
+ }
136
+
131
137
  validateConfiguration(frontmatter, filePath);
132
138
 
133
139
  if (!body.trim()) {
134
140
  throw new Error(`Empty system prompt in ${filePath}`);
135
141
  }
136
142
 
143
+ let priority = 1;
144
+ if (scope === "user") priority = 2;
145
+ if (scope === "builtin") priority = 3;
146
+
137
147
  return {
138
148
  name: frontmatter.name!,
139
149
  description: frontmatter.description!,
@@ -142,7 +152,7 @@ function parseSubagentFile(
142
152
  systemPrompt: body,
143
153
  filePath,
144
154
  scope,
145
- priority: scope === "project" ? 1 : 2,
155
+ priority,
146
156
  };
147
157
  } catch (error) {
148
158
  throw new Error(
@@ -156,7 +166,7 @@ function parseSubagentFile(
156
166
  */
157
167
  function scanSubagentDirectory(
158
168
  dirPath: string,
159
- scope: "project" | "user",
169
+ scope: "project" | "user" | "builtin",
160
170
  ): SubagentConfiguration[] {
161
171
  const configurations: SubagentConfiguration[] = [];
162
172
 
@@ -194,10 +204,10 @@ export async function loadSubagentConfigurations(
194
204
  ): Promise<SubagentConfiguration[]> {
195
205
  const projectDir = join(workdir, ".wave", "agents");
196
206
  const userDir = join(process.env.HOME || "~", ".wave", "agents");
207
+ const builtinDir = getBuiltinSubagentsDir();
197
208
 
198
209
  // Load configurations from all sources
199
- const { getBuiltinSubagents } = await import("./builtinSubagents.js");
200
- const builtinConfigs = getBuiltinSubagents();
210
+ const builtinConfigs = scanSubagentDirectory(builtinDir, "builtin");
201
211
  const projectConfigs = scanSubagentDirectory(projectDir, "project");
202
212
  const userConfigs = scanSubagentDirectory(userDir, "user");
203
213
 
@@ -1,95 +0,0 @@
1
- # Wave Hooks Configuration
2
-
3
- Hooks allow you to automate tasks when certain events occur in Wave. This document provides detailed guidance on how to configure complex hooks in `settings.json`.
4
-
5
- ## Hook Events
6
-
7
- Wave supports the following hook events:
8
-
9
- - `WorktreeCreate`: Triggered when a new worktree is created.
10
- - `TaskStart`: Triggered when a task starts.
11
- - `TaskComplete`: Triggered when a task is completed.
12
- - `TaskError`: Triggered when a task fails.
13
- - `SessionStart`: Triggered when a new session starts.
14
- - `SessionEnd`: Triggered when a session ends.
15
-
16
- ## Hook Configuration Structure
17
-
18
- Hooks are configured in the `hooks` field of `settings.json`. Each event can have multiple hook configurations.
19
-
20
- ```json
21
- {
22
- "hooks": {
23
- "WorktreeCreate": [
24
- {
25
- "command": "pnpm install",
26
- "description": "Install dependencies in new worktree",
27
- "blocking": true,
28
- "timeout": 300000
29
- }
30
- ],
31
- "TaskComplete": [
32
- {
33
- "command": "pnpm test",
34
- "description": "Run tests after task completion",
35
- "blocking": false
36
- }
37
- ]
38
- }
39
- }
40
- ```
41
-
42
- ## Hook Configuration Fields
43
-
44
- - `command`: The shell command to execute.
45
- - `description`: A brief description of the hook's purpose.
46
- - `blocking`: (Optional) Whether the hook should block the main agent's execution (default: `false`).
47
- - `timeout`: (Optional) Maximum execution time in milliseconds (default: `60000`).
48
- - `env`: (Optional) Environment variables specific to this hook.
49
- - `cwd`: (Optional) Working directory for the hook command.
50
-
51
- ## Advanced Hook Examples
52
-
53
- ### 1. Conditional Hooks
54
- You can use shell logic within the `command` field to create conditional hooks.
55
- ```json
56
- {
57
- "hooks": {
58
- "TaskComplete": [
59
- {
60
- "command": "if [ \"$WAVE_TASK_STATUS\" = \"completed\" ]; then pnpm lint; fi",
61
- "description": "Run linting only on successful task completion"
62
- }
63
- ]
64
- }
65
- }
66
- ```
67
-
68
- ### 2. Hook Chaining
69
- You can chain multiple commands in a single hook or define multiple hooks for the same event.
70
- ```json
71
- {
72
- "hooks": {
73
- "WorktreeCreate": [
74
- {
75
- "command": "pnpm install && pnpm build",
76
- "description": "Install and build in new worktree"
77
- }
78
- ]
79
- }
80
- }
81
- ```
82
-
83
- ### 3. Using Environment Variables
84
- Wave provides several environment variables to hooks:
85
- - `WAVE_PROJECT_DIR`: The root directory of the project.
86
- - `WAVE_SESSION_ID`: The current session ID.
87
- - `WAVE_TASK_ID`: The current task ID (if applicable).
88
- - `WAVE_TASK_STATUS`: The status of the task (for `TaskComplete` and `TaskError`).
89
-
90
- ## Best Practices
91
-
92
- - **Keep hooks fast**: Long-running hooks can slow down your workflow, especially if they are `blocking`.
93
- - **Use descriptive names**: Help yourself and others understand what each hook does.
94
- - **Test your hooks**: Run the commands manually first to ensure they work as expected.
95
- - **Use local overrides**: For machine-specific hooks, use `.wave/settings.local.json`.
@@ -1,7 +0,0 @@
1
- import type { SubagentConfiguration } from "./subagentParser.js";
2
- /**
3
- * Get all built-in subagent configurations
4
- * Built-in subagents have priority 3 (lowest) and can be overridden by user/project configs
5
- */
6
- export declare function getBuiltinSubagents(): SubagentConfiguration[];
7
- //# sourceMappingURL=builtinSubagents.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"builtinSubagents.d.ts","sourceRoot":"","sources":["../../src/utils/builtinSubagents.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,qBAAqB,EAAE,CAQ7D"}
@@ -1,94 +0,0 @@
1
- import { BASH_SUBAGENT_TYPE, EXPLORE_SUBAGENT_TYPE, PLAN_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, } from "../constants/subagents.js";
2
- import { BASH_SUBAGENT_SYSTEM_PROMPT, GENERAL_PURPOSE_SYSTEM_PROMPT, PLAN_SUBAGENT_SYSTEM_PROMPT, EXPLORE_SUBAGENT_SYSTEM_PROMPT, } from "../prompts/index.js";
3
- import { BASH_TOOL_NAME, GLOB_TOOL_NAME, GREP_TOOL_NAME, READ_TOOL_NAME, LSP_TOOL_NAME, } from "../constants/tools.js";
4
- /**
5
- * Get all built-in subagent configurations
6
- * Built-in subagents have priority 3 (lowest) and can be overridden by user/project configs
7
- */
8
- export function getBuiltinSubagents() {
9
- return [
10
- createBashSubagent(),
11
- createExploreSubagent(),
12
- createGeneralPurposeSubagent(),
13
- createPlanSubagent(),
14
- // Add more built-in subagents here as needed
15
- ];
16
- }
17
- /**
18
- * Create the Bash built-in subagent configuration
19
- * Specialized for executing bash commands and git operations
20
- */
21
- function createBashSubagent() {
22
- return {
23
- name: BASH_SUBAGENT_TYPE,
24
- description: "Command execution specialist for running bash commands. Use this for git operations, command execution, and other terminal tasks.",
25
- systemPrompt: BASH_SUBAGENT_SYSTEM_PROMPT,
26
- tools: [BASH_TOOL_NAME],
27
- model: "inherit",
28
- filePath: `<builtin:${BASH_SUBAGENT_TYPE}>`,
29
- scope: "builtin",
30
- priority: 3,
31
- };
32
- }
33
- /**
34
- * Create the General-Purpose built-in subagent configuration
35
- * Specialized for multi-step research and implementation tasks
36
- */
37
- function createGeneralPurposeSubagent() {
38
- return {
39
- name: GENERAL_PURPOSE_SUBAGENT_TYPE,
40
- description: "General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you.",
41
- systemPrompt: GENERAL_PURPOSE_SYSTEM_PROMPT,
42
- filePath: `<builtin:${GENERAL_PURPOSE_SUBAGENT_TYPE}>`,
43
- scope: "builtin",
44
- priority: 3,
45
- };
46
- }
47
- /**
48
- * Create the Explore built-in subagent configuration
49
- * Specialized for codebase exploration and file search tasks
50
- */
51
- function createExploreSubagent() {
52
- // Define allowed tools for read-only operations
53
- const allowedTools = [
54
- GLOB_TOOL_NAME,
55
- GREP_TOOL_NAME,
56
- READ_TOOL_NAME,
57
- BASH_TOOL_NAME,
58
- LSP_TOOL_NAME,
59
- ];
60
- return {
61
- name: EXPLORE_SUBAGENT_TYPE,
62
- description: 'Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. "src/components/**/*.tsx"), search code for keywords (eg. "API endpoints"), or answer questions about the codebase (eg. "how do API endpoints work?"). When calling this agent, specify the desired thoroughness level: "quick" for basic searches, "medium" for moderate exploration, or "very thorough" for comprehensive analysis across multiple locations and naming conventions.',
63
- systemPrompt: EXPLORE_SUBAGENT_SYSTEM_PROMPT,
64
- tools: allowedTools,
65
- model: "fastModel", // Special value that will use parent's fastModel
66
- filePath: `<builtin:${EXPLORE_SUBAGENT_TYPE}>`,
67
- scope: "builtin",
68
- priority: 3, // Lowest priority - can be overridden by user configs
69
- };
70
- }
71
- /**
72
- * Create the Plan built-in subagent configuration
73
- * Specialized for designing implementation plans and exploring codebases in read-only mode
74
- */
75
- function createPlanSubagent() {
76
- // Define allowed tools for read-only operations
77
- const allowedTools = [
78
- GLOB_TOOL_NAME,
79
- GREP_TOOL_NAME,
80
- READ_TOOL_NAME,
81
- BASH_TOOL_NAME,
82
- LSP_TOOL_NAME,
83
- ];
84
- return {
85
- name: PLAN_SUBAGENT_TYPE,
86
- description: "Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a task. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs.",
87
- systemPrompt: PLAN_SUBAGENT_SYSTEM_PROMPT,
88
- tools: allowedTools,
89
- model: "inherit", // Uses parent agent's model
90
- filePath: `<builtin:${PLAN_SUBAGENT_TYPE}>`,
91
- scope: "builtin",
92
- priority: 3, // Lowest priority - can be overridden by user configs
93
- };
94
- }
@@ -1,95 +0,0 @@
1
- # Wave Hooks Configuration
2
-
3
- Hooks allow you to automate tasks when certain events occur in Wave. This document provides detailed guidance on how to configure complex hooks in `settings.json`.
4
-
5
- ## Hook Events
6
-
7
- Wave supports the following hook events:
8
-
9
- - `WorktreeCreate`: Triggered when a new worktree is created.
10
- - `TaskStart`: Triggered when a task starts.
11
- - `TaskComplete`: Triggered when a task is completed.
12
- - `TaskError`: Triggered when a task fails.
13
- - `SessionStart`: Triggered when a new session starts.
14
- - `SessionEnd`: Triggered when a session ends.
15
-
16
- ## Hook Configuration Structure
17
-
18
- Hooks are configured in the `hooks` field of `settings.json`. Each event can have multiple hook configurations.
19
-
20
- ```json
21
- {
22
- "hooks": {
23
- "WorktreeCreate": [
24
- {
25
- "command": "pnpm install",
26
- "description": "Install dependencies in new worktree",
27
- "blocking": true,
28
- "timeout": 300000
29
- }
30
- ],
31
- "TaskComplete": [
32
- {
33
- "command": "pnpm test",
34
- "description": "Run tests after task completion",
35
- "blocking": false
36
- }
37
- ]
38
- }
39
- }
40
- ```
41
-
42
- ## Hook Configuration Fields
43
-
44
- - `command`: The shell command to execute.
45
- - `description`: A brief description of the hook's purpose.
46
- - `blocking`: (Optional) Whether the hook should block the main agent's execution (default: `false`).
47
- - `timeout`: (Optional) Maximum execution time in milliseconds (default: `60000`).
48
- - `env`: (Optional) Environment variables specific to this hook.
49
- - `cwd`: (Optional) Working directory for the hook command.
50
-
51
- ## Advanced Hook Examples
52
-
53
- ### 1. Conditional Hooks
54
- You can use shell logic within the `command` field to create conditional hooks.
55
- ```json
56
- {
57
- "hooks": {
58
- "TaskComplete": [
59
- {
60
- "command": "if [ \"$WAVE_TASK_STATUS\" = \"completed\" ]; then pnpm lint; fi",
61
- "description": "Run linting only on successful task completion"
62
- }
63
- ]
64
- }
65
- }
66
- ```
67
-
68
- ### 2. Hook Chaining
69
- You can chain multiple commands in a single hook or define multiple hooks for the same event.
70
- ```json
71
- {
72
- "hooks": {
73
- "WorktreeCreate": [
74
- {
75
- "command": "pnpm install && pnpm build",
76
- "description": "Install and build in new worktree"
77
- }
78
- ]
79
- }
80
- }
81
- ```
82
-
83
- ### 3. Using Environment Variables
84
- Wave provides several environment variables to hooks:
85
- - `WAVE_PROJECT_DIR`: The root directory of the project.
86
- - `WAVE_SESSION_ID`: The current session ID.
87
- - `WAVE_TASK_ID`: The current task ID (if applicable).
88
- - `WAVE_TASK_STATUS`: The status of the task (for `TaskComplete` and `TaskError`).
89
-
90
- ## Best Practices
91
-
92
- - **Keep hooks fast**: Long-running hooks can slow down your workflow, especially if they are `blocking`.
93
- - **Use descriptive names**: Help yourself and others understand what each hook does.
94
- - **Test your hooks**: Run the commands manually first to ensure they work as expected.
95
- - **Use local overrides**: For machine-specific hooks, use `.wave/settings.local.json`.