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.
- package/builtin/skills/init/SKILL.md +26 -0
- package/builtin/skills/loop/SKILL.md +53 -0
- package/builtin/skills/settings/ENV.md +64 -0
- package/builtin/skills/settings/HOOKS.md +94 -0
- package/builtin/skills/settings/MCP.md +55 -0
- package/builtin/skills/settings/MEMORY_RULES.md +60 -0
- package/{dist/builtin-skills → builtin/skills}/settings/SKILL.md +23 -16
- package/builtin/skills/settings/SKILLS.md +63 -0
- package/builtin/skills/settings/SUBAGENTS.md +60 -0
- package/builtin/subagents/bash.md +18 -0
- package/builtin/subagents/explore.md +42 -0
- package/builtin/subagents/general-purpose.md +20 -0
- package/builtin/subagents/plan.md +55 -0
- package/dist/agent.d.ts +8 -6
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +12 -9
- package/dist/constants/tools.d.ts +3 -0
- package/dist/constants/tools.d.ts.map +1 -1
- package/dist/constants/tools.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/managers/aiManager.d.ts +0 -2
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +53 -14
- package/dist/managers/cronManager.d.ts +19 -0
- package/dist/managers/cronManager.d.ts.map +1 -0
- package/dist/managers/cronManager.js +124 -0
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +21 -13
- package/dist/managers/liveConfigManager.js +1 -1
- package/dist/managers/mcpManager.d.ts +1 -1
- package/dist/managers/mcpManager.d.ts.map +1 -1
- package/dist/managers/mcpManager.js +10 -2
- package/dist/managers/messageManager.d.ts +0 -1
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.d.ts +27 -7
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +119 -14
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +7 -12
- package/dist/managers/subagentManager.d.ts +3 -0
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +10 -17
- package/dist/managers/toolManager.d.ts +1 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +28 -4
- package/dist/prompts/index.d.ts +0 -5
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +1 -136
- package/dist/services/configurationService.d.ts.map +1 -1
- package/dist/services/configurationService.js +8 -7
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +3 -10
- package/dist/services/initializationService.js +2 -2
- package/dist/services/jsonlHandler.d.ts.map +1 -1
- package/dist/services/jsonlHandler.js +3 -0
- package/dist/services/reversionService.d.ts +2 -2
- package/dist/services/reversionService.d.ts.map +1 -1
- package/dist/services/reversionService.js +3 -3
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +18 -11
- package/dist/tools/agentTool.js +1 -1
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +5 -5
- package/dist/tools/cronCreateTool.d.ts +3 -0
- package/dist/tools/cronCreateTool.d.ts.map +1 -0
- package/dist/tools/cronCreateTool.js +59 -0
- package/dist/tools/cronDeleteTool.d.ts +3 -0
- package/dist/tools/cronDeleteTool.d.ts.map +1 -0
- package/dist/tools/cronDeleteTool.js +38 -0
- package/dist/tools/cronListTool.d.ts +3 -0
- package/dist/tools/cronListTool.d.ts.map +1 -0
- package/dist/tools/cronListTool.js +30 -0
- package/dist/tools/skillTool.d.ts +0 -3
- package/dist/tools/skillTool.d.ts.map +1 -1
- package/dist/tools/skillTool.js +4 -3
- package/dist/tools/taskOutputTool.d.ts.map +1 -1
- package/dist/tools/taskOutputTool.js +15 -8
- package/dist/tools/types.d.ts +2 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/types/agent.d.ts +10 -0
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/configuration.d.ts +1 -1
- package/dist/types/configuration.d.ts.map +1 -1
- package/dist/types/cron.d.ts +10 -0
- package/dist/types/cron.d.ts.map +1 -0
- package/dist/types/cron.js +1 -0
- package/dist/types/hooks.d.ts +1 -5
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/messaging.d.ts +1 -1
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/utils/configPaths.d.ts +4 -0
- package/dist/utils/configPaths.d.ts.map +1 -1
- package/dist/utils/configPaths.js +11 -9
- package/dist/utils/containerSetup.d.ts.map +1 -1
- package/dist/utils/containerSetup.js +40 -13
- package/dist/utils/fileSearch.d.ts.map +1 -1
- package/dist/utils/fileSearch.js +7 -1
- package/dist/utils/mcpUtils.d.ts +2 -2
- package/dist/utils/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +1 -5
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +14 -4
- package/package.json +4 -2
- package/src/agent.ts +17 -12
- package/src/constants/tools.ts +3 -0
- package/src/index.ts +1 -0
- package/src/managers/aiManager.ts +72 -24
- package/src/managers/cronManager.ts +167 -0
- package/src/managers/hookManager.ts +27 -13
- package/src/managers/liveConfigManager.ts +2 -2
- package/src/managers/mcpManager.ts +23 -2
- package/src/managers/messageManager.ts +0 -6
- package/src/managers/permissionManager.ts +154 -18
- package/src/managers/slashCommandManager.ts +7 -14
- package/src/managers/subagentManager.ts +15 -19
- package/src/managers/toolManager.ts +37 -4
- package/src/prompts/index.ts +0 -144
- package/src/services/configurationService.ts +8 -7
- package/src/services/hook.ts +5 -11
- package/src/services/initializationService.ts +3 -3
- package/src/services/jsonlHandler.ts +4 -0
- package/src/services/reversionService.ts +9 -4
- package/src/services/session.ts +19 -12
- package/src/tools/agentTool.ts +1 -1
- package/src/tools/bashTool.ts +6 -5
- package/src/tools/cronCreateTool.ts +73 -0
- package/src/tools/cronDeleteTool.ts +47 -0
- package/src/tools/cronListTool.ts +38 -0
- package/src/tools/skillTool.ts +6 -4
- package/src/tools/taskOutputTool.ts +14 -8
- package/src/tools/types.ts +2 -0
- package/src/types/agent.ts +10 -0
- package/src/types/configuration.ts +1 -1
- package/src/types/cron.ts +9 -0
- package/src/types/hooks.ts +5 -9
- package/src/types/index.ts +1 -0
- package/src/types/messaging.ts +1 -1
- package/src/utils/configPaths.ts +12 -10
- package/src/utils/containerSetup.ts +50 -16
- package/src/utils/fileSearch.ts +7 -1
- package/src/utils/mcpUtils.ts +2 -5
- package/src/utils/subagentParser.ts +16 -6
- package/dist/builtin-skills/settings/HOOKS.md +0 -95
- package/dist/utils/builtinSubagents.d.ts +0 -7
- package/dist/utils/builtinSubagents.d.ts.map +0 -1
- package/dist/utils/builtinSubagents.js +0 -94
- package/src/builtin-skills/settings/HOOKS.md +0 -95
- package/src/builtin-skills/settings/SKILL.md +0 -86
- package/src/utils/builtinSubagents.ts +0 -122
package/src/types/hooks.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type HookEvent =
|
|
|
19
19
|
| "UserPromptSubmit"
|
|
20
20
|
| "Stop"
|
|
21
21
|
| "SubagentStop"
|
|
22
|
-
| "
|
|
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
|
-
"
|
|
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" | "
|
|
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
|
|
package/src/types/index.ts
CHANGED
package/src/types/messaging.ts
CHANGED
|
@@ -11,7 +11,7 @@ export enum MessageSource {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface Message {
|
|
14
|
-
id
|
|
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)
|
package/src/utils/configPaths.ts
CHANGED
|
@@ -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
|
-
//
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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, {
|
|
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.
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
|
174
|
+
const canUseToolWithPermissionRequest = options.canUseTool
|
|
164
175
|
? async (context: ToolPermissionContext) => {
|
|
165
176
|
try {
|
|
166
|
-
const
|
|
167
|
-
|
|
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
|
-
|
|
175
|
-
|
|
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
|
|
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: !!
|
|
245
|
+
hasCallback: !!canUseToolWithPermissionRequest,
|
|
219
246
|
});
|
|
220
|
-
container.register("CanUseToolCallback",
|
|
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:
|
|
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
|
}
|
package/src/utils/fileSearch.ts
CHANGED
|
@@ -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) =>
|
|
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
|
});
|
package/src/utils/mcpUtils.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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`.
|