wave-agent-sdk 1.1.5 → 1.2.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.
- package/dist/agent.d.ts +70 -24
- package/dist/agent.js +110 -30
- package/dist/builtin/plugins.js +11 -20
- package/dist/builtin/skills/settings.js +6 -8
- package/dist/core/plugin.d.ts +4 -0
- package/dist/core/plugin.js +7 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/managers/aiManager.d.ts +0 -24
- package/dist/managers/aiManager.js +14 -181
- package/dist/managers/bashModeManager.d.ts +33 -0
- package/dist/managers/bashModeManager.js +110 -0
- package/dist/managers/hookManager.d.ts +5 -0
- package/dist/managers/hookManager.js +7 -0
- package/dist/managers/liveConfigManager.js +3 -3
- package/dist/managers/mcpManager.d.ts +23 -0
- package/dist/managers/mcpManager.js +162 -14
- package/dist/managers/messageManager.d.ts +12 -13
- package/dist/managers/messageManager.js +63 -60
- package/dist/managers/permissionManager.d.ts +29 -0
- package/dist/managers/permissionManager.js +158 -70
- package/dist/managers/planManager.d.ts +9 -0
- package/dist/managers/planManager.js +19 -1
- package/dist/managers/skillManager.d.ts +31 -0
- package/dist/managers/skillManager.js +122 -12
- package/dist/managers/slashCommandManager.js +9 -28
- package/dist/managers/subagentManager.d.ts +7 -0
- package/dist/managers/subagentManager.js +61 -9
- package/dist/managers/workflowManager.js +6 -0
- package/dist/prompts/index.d.ts +0 -1
- package/dist/prompts/index.js +0 -4
- package/dist/services/MarketplaceService.js +36 -14
- package/dist/services/configurationService.d.ts +34 -2
- package/dist/services/configurationService.js +123 -16
- package/dist/services/initializationService.js +2 -2
- package/dist/services/jsonlHandler.d.ts +14 -0
- package/dist/services/jsonlHandler.js +44 -1
- package/dist/services/memory.d.ts +14 -0
- package/dist/services/memory.js +33 -0
- package/dist/services/officialMarketplaceMirror.d.ts +85 -0
- package/dist/services/officialMarketplaceMirror.js +289 -0
- package/dist/services/remoteSettingsService.js +4 -4
- package/dist/services/session.js +30 -13
- package/dist/services/worktreeHooks.js +6 -1
- package/dist/stdio/index.d.ts +10 -0
- package/dist/stdio/index.js +10 -0
- package/dist/stdio/notificationRouter.d.ts +38 -0
- package/dist/stdio/notificationRouter.js +96 -0
- package/dist/stdio/rpcClient.d.ts +18 -0
- package/dist/stdio/rpcClient.js +10 -0
- package/dist/stdio/stdioAgent.d.ts +222 -0
- package/dist/stdio/stdioAgent.js +341 -0
- package/dist/tools/bashTool.js +2 -0
- package/dist/tools/exitPlanMode.js +10 -2
- package/dist/types/agent.d.ts +8 -0
- package/dist/types/commands.d.ts +7 -0
- package/dist/types/configuration.d.ts +6 -1
- package/dist/types/hooks.d.ts +1 -0
- package/dist/types/hooks.js +19 -0
- package/dist/types/mcp.d.ts +3 -0
- package/dist/types/messaging.d.ts +1 -8
- package/dist/types/skills.d.ts +11 -0
- package/dist/utils/bashParser.d.ts +17 -0
- package/dist/utils/bashParser.js +72 -0
- package/dist/utils/bashStructure/bashLexer.d.ts +96 -0
- package/dist/utils/bashStructure/bashLexer.js +676 -0
- package/dist/utils/bashStructure/bashParser.d.ts +144 -0
- package/dist/utils/bashStructure/bashParser.js +606 -0
- package/dist/utils/bashStructure/bashSemantics.d.ts +70 -0
- package/dist/utils/bashStructure/bashSemantics.js +477 -0
- package/dist/utils/bashStructure/index.d.ts +26 -0
- package/dist/utils/bashStructure/index.js +27 -0
- package/dist/utils/bashStructure/types.d.ts +62 -0
- package/dist/utils/bashStructure/types.js +47 -0
- package/dist/utils/containerSetup.js +5 -6
- package/dist/utils/fileUtils.d.ts +11 -0
- package/dist/utils/fileUtils.js +37 -0
- package/dist/utils/messageOperations.d.ts +0 -18
- package/dist/utils/messageOperations.js +0 -62
- package/dist/utils/subagentParser.js +9 -2
- package/dist/utils/tokenCalculation.js +0 -8
- package/dist/utils/worktreeUtils.d.ts +2 -1
- package/dist/utils/worktreeUtils.js +64 -34
- package/package.json +6 -1
- package/dist/managers/bangManager.d.ts +0 -26
- package/dist/managers/bangManager.js +0 -78
package/dist/agent.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type QueuedMessage } from "./managers/messageQueue.js";
|
|
2
2
|
import { SlashCommand, CustomSlashCommand, AgentOptions } from "./types/index.js";
|
|
3
3
|
import type { Message, McpServerStatus, GatewayConfig, ModelConfig, Usage, PermissionMode, ForegroundTask, SkillMetadata } from "./types/index.js";
|
|
4
|
+
import type { HookEvent, HookEventConfig } from "./types/hooks.js";
|
|
4
5
|
import type { WorktreeSession } from "./utils/worktreeSession.js";
|
|
5
6
|
export declare class Agent {
|
|
6
7
|
private messageManager;
|
|
7
8
|
private aiManager;
|
|
8
|
-
private
|
|
9
|
+
private bashModeManager;
|
|
9
10
|
private backgroundTaskManager;
|
|
10
11
|
private logger?;
|
|
11
12
|
private toolManager;
|
|
@@ -65,6 +66,10 @@ export declare class Agent {
|
|
|
65
66
|
private constructor();
|
|
66
67
|
get sessionId(): string;
|
|
67
68
|
get messages(): Message[];
|
|
69
|
+
/** Full UI display message stream (includes pre-compaction history).
|
|
70
|
+
* Consumed by hosts for the full-list message view (getMessages RPC,
|
|
71
|
+
* CLI structural refresh); the API context stays on `messages`. */
|
|
72
|
+
get displayMessages(): Message[];
|
|
68
73
|
get usages(): Usage[];
|
|
69
74
|
get sessionFilePath(): string;
|
|
70
75
|
get latestTotalTokens(): number;
|
|
@@ -87,6 +92,21 @@ export declare class Agent {
|
|
|
87
92
|
get userMemory(): string;
|
|
88
93
|
/** Get combined memory content (project + user + modular rules) */
|
|
89
94
|
getCombinedMemory(): Promise<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Read the user-level memory file (~/.wave/AGENTS.md). Unlike the cached
|
|
97
|
+
* `userMemory` getter this always reads fresh content (the settings UI edits
|
|
98
|
+
* the file while the agent may already hold a cache).
|
|
99
|
+
*/
|
|
100
|
+
readUserMemoryContent(): Promise<string>;
|
|
101
|
+
/**
|
|
102
|
+
* Read the project-level memory file (<workdir>/AGENTS.md, CLAUDE.md
|
|
103
|
+
* fallback). Always reads fresh content for the settings UI.
|
|
104
|
+
*/
|
|
105
|
+
readProjectMemoryContent(workdir: string): Promise<string>;
|
|
106
|
+
/** Persist the user-level memory file (~/.wave/AGENTS.md). */
|
|
107
|
+
writeUserMemoryContent(content: string): Promise<void>;
|
|
108
|
+
/** Persist the project-level memory file (<workdir>/AGENTS.md). */
|
|
109
|
+
writeProjectMemoryContent(workdir: string, content: string): Promise<void>;
|
|
90
110
|
/** Get AI loading status */
|
|
91
111
|
get isLoading(): boolean;
|
|
92
112
|
/** Get message compaction status */
|
|
@@ -229,7 +249,7 @@ export declare class Agent {
|
|
|
229
249
|
*/
|
|
230
250
|
restoreSession(sessionId: string): Promise<void>;
|
|
231
251
|
abortAIMessage(): void;
|
|
232
|
-
/** Execute bash command (
|
|
252
|
+
/** Execute a bash-mode command (`!command`) */
|
|
233
253
|
bang(command: string): Promise<void>;
|
|
234
254
|
clearMessages(): Promise<void>;
|
|
235
255
|
/**
|
|
@@ -274,28 +294,6 @@ export declare class Agent {
|
|
|
274
294
|
* @returns Promise that resolves to the AI's answer
|
|
275
295
|
*/
|
|
276
296
|
askBtw(question: string, abortSignal?: AbortSignal, onContent?: (content: string) => void, onReasoning?: (content: string) => void): Promise<string>;
|
|
277
|
-
/**
|
|
278
|
-
* Start a fork subagent in the background (the "/subtask" command path).
|
|
279
|
-
*
|
|
280
|
-
* The fork inherits the parent's full conversation context — same system
|
|
281
|
-
* prompt, tools, model, and message prefix — so the prompt cache is reused,
|
|
282
|
-
* then works independently in the background. On completion its final
|
|
283
|
-
* response is delivered back to the main conversation as a task notification
|
|
284
|
-
* carrying the `<result>` tag. Recursion is prevented inside the fork (the
|
|
285
|
-
* Agent tool and Task tools are denied).
|
|
286
|
-
*
|
|
287
|
-
* @param prompt - The task description for the fork subagent
|
|
288
|
-
* @param options - Background task label and optional loose turn bound
|
|
289
|
-
* @param options.description - Display label for the background task
|
|
290
|
-
* @param options.maxTurns - Loose turn bound (defaults to 200, aligned with
|
|
291
|
-
* Claude Code's fork subagent)
|
|
292
|
-
* @param abortSignal - Optional signal to abort the fork
|
|
293
|
-
* @returns Promise that resolves to the background task ID
|
|
294
|
-
*/
|
|
295
|
-
forkSubagent(prompt: string, options: {
|
|
296
|
-
description: string;
|
|
297
|
-
maxTurns?: number;
|
|
298
|
-
}, abortSignal?: AbortSignal): Promise<string>;
|
|
299
297
|
/**
|
|
300
298
|
* Send a message to the AI agent with optional images
|
|
301
299
|
*
|
|
@@ -351,6 +349,15 @@ export declare class Agent {
|
|
|
351
349
|
connectMcpServer(serverName: string): Promise<boolean>;
|
|
352
350
|
/** Disconnect MCP server */
|
|
353
351
|
disconnectMcpServer(serverName: string): Promise<boolean>;
|
|
352
|
+
/**
|
|
353
|
+
* Remove an MCP server from a persisted config file (user ~/.wave/mcp.json
|
|
354
|
+
* or project <workdir>/.mcp.json), then disconnect and drop it from memory.
|
|
355
|
+
*/
|
|
356
|
+
removeMcpServer(scope: "user" | "project", serverName: string): Promise<boolean>;
|
|
357
|
+
/** The user-level MCP config path (~/.wave/mcp.json) */
|
|
358
|
+
getUserMcpConfigPath(): string;
|
|
359
|
+
/** The project-level MCP config path (<workdir>/.mcp.json) */
|
|
360
|
+
getProjectMcpConfigPath(): string;
|
|
354
361
|
/** Get all available slash commands */
|
|
355
362
|
getSlashCommands(): SlashCommand[];
|
|
356
363
|
/** Check if slash command exists */
|
|
@@ -395,6 +402,14 @@ export declare class Agent {
|
|
|
395
402
|
* Get the current plan file path (for testing and UI)
|
|
396
403
|
*/
|
|
397
404
|
getPlanFilePath(): string | undefined;
|
|
405
|
+
/**
|
|
406
|
+
* Resolve once the plan file path has been generated and set after entering
|
|
407
|
+
* plan mode. Resolves `undefined` when no generation is in flight.
|
|
408
|
+
* Used by the CLI /plan command and the stdio getPlanFile RPC to avoid
|
|
409
|
+
* querying the model before the path is known (the plan mode reminder needs
|
|
410
|
+
* the path to be set).
|
|
411
|
+
*/
|
|
412
|
+
awaitPlanFilePath(): Promise<string | undefined>;
|
|
398
413
|
/**
|
|
399
414
|
* Get all currently allowed rules (user-defined and default)
|
|
400
415
|
*/
|
|
@@ -430,6 +445,37 @@ export declare class Agent {
|
|
|
430
445
|
* @returns The list of skill metadata
|
|
431
446
|
*/
|
|
432
447
|
getSkillMetadata(): SkillMetadata[];
|
|
448
|
+
/**
|
|
449
|
+
* Delete a user/personal or project skill by removing its directory.
|
|
450
|
+
* Builtin and plugin skills are read-only and cannot be deleted.
|
|
451
|
+
* @param name - The skill name as shown in skill metadata
|
|
452
|
+
* @returns true if the skill was deleted
|
|
453
|
+
*/
|
|
454
|
+
deleteSkill(name: string): Promise<boolean>;
|
|
455
|
+
/**
|
|
456
|
+
* Delete a user-level or project-level subagent by removing its markdown
|
|
457
|
+
* file. Builtin and plugin agents are read-only and cannot be deleted.
|
|
458
|
+
* @param name - The subagent name as shown in configurations
|
|
459
|
+
* @returns true if the subagent was deleted
|
|
460
|
+
*/
|
|
461
|
+
deleteSubagent(name: string): Promise<boolean>;
|
|
462
|
+
/**
|
|
463
|
+
* Get hook configurations at a specific scope (user or project settings.json;
|
|
464
|
+
* plugin hooks come from the hook manager's plugin-registered set).
|
|
465
|
+
*/
|
|
466
|
+
getHooksByScope(scope: "user" | "project" | "plugin"): Promise<Partial<Record<HookEvent, HookEventConfig[]>>>;
|
|
467
|
+
/**
|
|
468
|
+
* Absolute path of the settings.json holding hooks at `scope` — user
|
|
469
|
+
* `~/.wave/settings.json` or project `<workdir>/.wave/settings.json`. Hosts
|
|
470
|
+
* pass it to the GUI so editors / file panels can open the file (they cannot
|
|
471
|
+
* expand `~`).
|
|
472
|
+
*/
|
|
473
|
+
getHookConfigPath(scope: "user" | "project"): string;
|
|
474
|
+
/**
|
|
475
|
+
* Delete a hook at a specific scope, identified by hookName of the form
|
|
476
|
+
* `Event:Matcher`.
|
|
477
|
+
*/
|
|
478
|
+
deleteHook(scope: "user" | "project", hookName: string): Promise<void>;
|
|
433
479
|
/**
|
|
434
480
|
* Get currently active subagent instances (status active/initializing).
|
|
435
481
|
* @returns The list of active subagent instances
|
package/dist/agent.js
CHANGED
|
@@ -51,7 +51,7 @@ export class Agent {
|
|
|
51
51
|
* @param options - Configuration options for the Agent instance
|
|
52
52
|
*/
|
|
53
53
|
constructor(options) {
|
|
54
|
-
this.
|
|
54
|
+
this.bashModeManager = null;
|
|
55
55
|
this.dispatchPromise = null; // Track current dispatch for teardown
|
|
56
56
|
this.isAborting = false; // Transient guard: prevents tryDispatch from firing during abortMessage (reset when the abort completes)
|
|
57
57
|
this.isDestroyed = false; // Terminal guard: set in destroy(), never reset — no dispatch may ever start after destroy
|
|
@@ -115,7 +115,7 @@ export class Agent {
|
|
|
115
115
|
this.aiManager = this.container.get("AIManager");
|
|
116
116
|
this.slashCommandManager = this.container.get("SlashCommandManager");
|
|
117
117
|
this.pluginManager = this.container.get("PluginManager");
|
|
118
|
-
this.
|
|
118
|
+
this.bashModeManager = this.container.get("BashModeManager");
|
|
119
119
|
this.cronManager = this.container.get("CronManager");
|
|
120
120
|
this.messageQueue = this.container.get("MessageQueue");
|
|
121
121
|
this.asyncWorkRegistry = this.container.get("AsyncWorkRegistry");
|
|
@@ -135,7 +135,7 @@ export class Agent {
|
|
|
135
135
|
this.tryDispatch();
|
|
136
136
|
};
|
|
137
137
|
// Wire up bang manager callback for command running changes
|
|
138
|
-
this.
|
|
138
|
+
this.bashModeManager.onCommandRunningChange = (running) => {
|
|
139
139
|
this.options.callbacks?.onCommandRunningChange?.(running);
|
|
140
140
|
if (!running)
|
|
141
141
|
this.tryDispatch();
|
|
@@ -152,6 +152,12 @@ export class Agent {
|
|
|
152
152
|
get messages() {
|
|
153
153
|
return this.messageManager.getMessages();
|
|
154
154
|
}
|
|
155
|
+
/** Full UI display message stream (includes pre-compaction history).
|
|
156
|
+
* Consumed by hosts for the full-list message view (getMessages RPC,
|
|
157
|
+
* CLI structural refresh); the API context stays on `messages`. */
|
|
158
|
+
get displayMessages() {
|
|
159
|
+
return this.messageManager.getDisplayMessages();
|
|
160
|
+
}
|
|
155
161
|
get usages() {
|
|
156
162
|
return this.messageManager.getUsages();
|
|
157
163
|
}
|
|
@@ -196,6 +202,33 @@ export class Agent {
|
|
|
196
202
|
async getCombinedMemory() {
|
|
197
203
|
return this.messageManager.getCombinedMemory();
|
|
198
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Read the user-level memory file (~/.wave/AGENTS.md). Unlike the cached
|
|
207
|
+
* `userMemory` getter this always reads fresh content (the settings UI edits
|
|
208
|
+
* the file while the agent may already hold a cache).
|
|
209
|
+
*/
|
|
210
|
+
async readUserMemoryContent() {
|
|
211
|
+
const memoryService = this.container.get("MemoryService");
|
|
212
|
+
return (await memoryService?.getUserMemoryContent()) ?? "";
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Read the project-level memory file (<workdir>/AGENTS.md, CLAUDE.md
|
|
216
|
+
* fallback). Always reads fresh content for the settings UI.
|
|
217
|
+
*/
|
|
218
|
+
async readProjectMemoryContent(workdir) {
|
|
219
|
+
const memoryService = this.container.get("MemoryService");
|
|
220
|
+
return (await memoryService?.readMemoryFile(workdir)) ?? "";
|
|
221
|
+
}
|
|
222
|
+
/** Persist the user-level memory file (~/.wave/AGENTS.md). */
|
|
223
|
+
async writeUserMemoryContent(content) {
|
|
224
|
+
const memoryService = this.container.get("MemoryService");
|
|
225
|
+
await memoryService?.writeUserMemoryContent(content);
|
|
226
|
+
}
|
|
227
|
+
/** Persist the project-level memory file (<workdir>/AGENTS.md). */
|
|
228
|
+
async writeProjectMemoryContent(workdir, content) {
|
|
229
|
+
const memoryService = this.container.get("MemoryService");
|
|
230
|
+
await memoryService?.writeProjectMemoryContent(workdir, content);
|
|
231
|
+
}
|
|
199
232
|
/** Get AI loading status */
|
|
200
233
|
get isLoading() {
|
|
201
234
|
return this.aiManager.isLoading;
|
|
@@ -206,7 +239,7 @@ export class Agent {
|
|
|
206
239
|
}
|
|
207
240
|
/** Get bash command execution status */
|
|
208
241
|
get isCommandRunning() {
|
|
209
|
-
return this.
|
|
242
|
+
return this.bashModeManager?.isCommandRunning ?? false;
|
|
210
243
|
}
|
|
211
244
|
/** Get queued user-facing messages (excludes background notifications) */
|
|
212
245
|
get queuedMessages() {
|
|
@@ -317,7 +350,7 @@ export class Agent {
|
|
|
317
350
|
this.messageQueue.transitionTo("running");
|
|
318
351
|
this.options.callbacks?.onQueuedMessagesChange?.(this.queuedMessages);
|
|
319
352
|
if (next.type === "bang") {
|
|
320
|
-
await this.
|
|
353
|
+
await this.bashModeManager?.executeCommand(next.content);
|
|
321
354
|
await this.messageManager.saveSession();
|
|
322
355
|
}
|
|
323
356
|
else if (next.type === "notification") {
|
|
@@ -516,7 +549,7 @@ export class Agent {
|
|
|
516
549
|
abortAIMessage() {
|
|
517
550
|
this.aiManager.abortAIMessage();
|
|
518
551
|
}
|
|
519
|
-
/** Execute bash command (
|
|
552
|
+
/** Execute a bash-mode command (`!command`) */
|
|
520
553
|
async bang(command) {
|
|
521
554
|
this.assertNotDestroyed();
|
|
522
555
|
// If the agent is busy, enqueue the bang command
|
|
@@ -525,7 +558,7 @@ export class Agent {
|
|
|
525
558
|
this.options.callbacks?.onQueuedMessagesChange?.(this.queuedMessages);
|
|
526
559
|
return;
|
|
527
560
|
}
|
|
528
|
-
await this.
|
|
561
|
+
await this.bashModeManager?.executeCommand(command);
|
|
529
562
|
await this.messageManager.saveSession();
|
|
530
563
|
}
|
|
531
564
|
async clearMessages() {
|
|
@@ -620,7 +653,7 @@ export class Agent {
|
|
|
620
653
|
}
|
|
621
654
|
/** Interrupt bash command execution */
|
|
622
655
|
abortBashCommand() {
|
|
623
|
-
this.
|
|
656
|
+
this.bashModeManager?.abortCommand();
|
|
624
657
|
}
|
|
625
658
|
/** Interrupt slash command execution */
|
|
626
659
|
abortSlashCommand() {
|
|
@@ -753,28 +786,6 @@ export class Agent {
|
|
|
753
786
|
const result = await this.aiManager.runBtwFork(question, abortSignal, onContent, onReasoning);
|
|
754
787
|
return result.content ?? result.error ?? "No response received";
|
|
755
788
|
}
|
|
756
|
-
/**
|
|
757
|
-
* Start a fork subagent in the background (the "/subtask" command path).
|
|
758
|
-
*
|
|
759
|
-
* The fork inherits the parent's full conversation context — same system
|
|
760
|
-
* prompt, tools, model, and message prefix — so the prompt cache is reused,
|
|
761
|
-
* then works independently in the background. On completion its final
|
|
762
|
-
* response is delivered back to the main conversation as a task notification
|
|
763
|
-
* carrying the `<result>` tag. Recursion is prevented inside the fork (the
|
|
764
|
-
* Agent tool and Task tools are denied).
|
|
765
|
-
*
|
|
766
|
-
* @param prompt - The task description for the fork subagent
|
|
767
|
-
* @param options - Background task label and optional loose turn bound
|
|
768
|
-
* @param options.description - Display label for the background task
|
|
769
|
-
* @param options.maxTurns - Loose turn bound (defaults to 200, aligned with
|
|
770
|
-
* Claude Code's fork subagent)
|
|
771
|
-
* @param abortSignal - Optional signal to abort the fork
|
|
772
|
-
* @returns Promise that resolves to the background task ID
|
|
773
|
-
*/
|
|
774
|
-
async forkSubagent(prompt, options, abortSignal) {
|
|
775
|
-
this.assertNotDestroyed();
|
|
776
|
-
return this.aiManager.runForkSubagent(prompt, options, abortSignal);
|
|
777
|
-
}
|
|
778
789
|
/**
|
|
779
790
|
* Send a message to the AI agent with optional images
|
|
780
791
|
*
|
|
@@ -876,6 +887,21 @@ export class Agent {
|
|
|
876
887
|
async disconnectMcpServer(serverName) {
|
|
877
888
|
return await this.mcpManager.disconnectServer(serverName);
|
|
878
889
|
}
|
|
890
|
+
/**
|
|
891
|
+
* Remove an MCP server from a persisted config file (user ~/.wave/mcp.json
|
|
892
|
+
* or project <workdir>/.mcp.json), then disconnect and drop it from memory.
|
|
893
|
+
*/
|
|
894
|
+
async removeMcpServer(scope, serverName) {
|
|
895
|
+
return await this.mcpManager.removeServerFromConfig(scope, serverName);
|
|
896
|
+
}
|
|
897
|
+
/** The user-level MCP config path (~/.wave/mcp.json) */
|
|
898
|
+
getUserMcpConfigPath() {
|
|
899
|
+
return this.mcpManager.getUserConfigPath();
|
|
900
|
+
}
|
|
901
|
+
/** The project-level MCP config path (<workdir>/.mcp.json) */
|
|
902
|
+
getProjectMcpConfigPath() {
|
|
903
|
+
return this.mcpManager.getProjectConfigPath();
|
|
904
|
+
}
|
|
879
905
|
// ========== Slash Command Management Methods ==========
|
|
880
906
|
/** Get all available slash commands */
|
|
881
907
|
getSlashCommands() {
|
|
@@ -951,6 +977,16 @@ export class Agent {
|
|
|
951
977
|
getPlanFilePath() {
|
|
952
978
|
return this.permissionManager.getPlanFilePath();
|
|
953
979
|
}
|
|
980
|
+
/**
|
|
981
|
+
* Resolve once the plan file path has been generated and set after entering
|
|
982
|
+
* plan mode. Resolves `undefined` when no generation is in flight.
|
|
983
|
+
* Used by the CLI /plan command and the stdio getPlanFile RPC to avoid
|
|
984
|
+
* querying the model before the path is known (the plan mode reminder needs
|
|
985
|
+
* the path to be set).
|
|
986
|
+
*/
|
|
987
|
+
awaitPlanFilePath() {
|
|
988
|
+
return this.planManager.awaitPlanFilePath();
|
|
989
|
+
}
|
|
954
990
|
/**
|
|
955
991
|
* Get all currently allowed rules (user-defined and default)
|
|
956
992
|
*/
|
|
@@ -1003,6 +1039,50 @@ export class Agent {
|
|
|
1003
1039
|
getSkillMetadata() {
|
|
1004
1040
|
return this.skillManager.getAvailableSkills();
|
|
1005
1041
|
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Delete a user/personal or project skill by removing its directory.
|
|
1044
|
+
* Builtin and plugin skills are read-only and cannot be deleted.
|
|
1045
|
+
* @param name - The skill name as shown in skill metadata
|
|
1046
|
+
* @returns true if the skill was deleted
|
|
1047
|
+
*/
|
|
1048
|
+
async deleteSkill(name) {
|
|
1049
|
+
return await this.skillManager.deleteSkill(name);
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Delete a user-level or project-level subagent by removing its markdown
|
|
1053
|
+
* file. Builtin and plugin agents are read-only and cannot be deleted.
|
|
1054
|
+
* @param name - The subagent name as shown in configurations
|
|
1055
|
+
* @returns true if the subagent was deleted
|
|
1056
|
+
*/
|
|
1057
|
+
async deleteSubagent(name) {
|
|
1058
|
+
return await this.subagentManager.deleteSubagent(name);
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Get hook configurations at a specific scope (user or project settings.json;
|
|
1062
|
+
* plugin hooks come from the hook manager's plugin-registered set).
|
|
1063
|
+
*/
|
|
1064
|
+
async getHooksByScope(scope) {
|
|
1065
|
+
if (scope === "plugin") {
|
|
1066
|
+
return this.hookManager.getPluginHooks();
|
|
1067
|
+
}
|
|
1068
|
+
return await this.configurationService.getHooksByScope(this.workdir, scope);
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* Absolute path of the settings.json holding hooks at `scope` — user
|
|
1072
|
+
* `~/.wave/settings.json` or project `<workdir>/.wave/settings.json`. Hosts
|
|
1073
|
+
* pass it to the GUI so editors / file panels can open the file (they cannot
|
|
1074
|
+
* expand `~`).
|
|
1075
|
+
*/
|
|
1076
|
+
getHookConfigPath(scope) {
|
|
1077
|
+
return this.configurationService.getHookConfigPath(this.workdir, scope);
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Delete a hook at a specific scope, identified by hookName of the form
|
|
1081
|
+
* `Event:Matcher`.
|
|
1082
|
+
*/
|
|
1083
|
+
async deleteHook(scope, hookName) {
|
|
1084
|
+
await this.configurationService.deleteHook(this.workdir, scope, hookName);
|
|
1085
|
+
}
|
|
1006
1086
|
/**
|
|
1007
1087
|
* Get currently active subagent instances (status active/initializing).
|
|
1008
1088
|
* @returns The list of active subagent instances
|
package/dist/builtin/plugins.js
CHANGED
|
@@ -41,9 +41,9 @@ const guidance = [
|
|
|
41
41
|
"- 边界模糊时也先写 spec 草稿请用户确认,不要直接改代码。",
|
|
42
42
|
"- 规格编写技能(specify)由 AI 自动触发:对话中涉及新需求或需求变更时主动创建或更新规格文件,不需要用户手动调用(不出现在斜杠命令列表中)。",
|
|
43
43
|
\`- 新增或修改 spec 后运行校验:\${specCount}(自动检测 docs/specs/,否则 specs/,否则退出)。\`,
|
|
44
|
-
"-
|
|
45
|
-
"-
|
|
46
|
-
"- 用 task
|
|
44
|
+
"- 规格确认与阶段衔接一次完成:通过 AskUserQuestion 单选让用户点击决策(选项只传「直接实现 / 制定技术方案」,并在问题文案中说明如需调整规格可选「其他」输入修改意见;「其他」由 AskUserQuestion 自动附加,勿手动添加;选「其他」=规格需调整,按反馈修改后再次询问)。",
|
|
45
|
+
"- 可选技术方案阶段:制定技术方案并批准后再编码;也可跳过——最短流程=规格+编码,最长=规格+技术方案+编码。",
|
|
46
|
+
"- 用 task 工具追踪进度:规格、技术方案、编码各阶段开始前用 TaskCreate 创建任务并标记进行中(TaskUpdate),完成/批准/确认后标记完成,让用户在任务列表中看到当前所处阶段。",
|
|
47
47
|
].join("\\n");
|
|
48
48
|
|
|
49
49
|
// JSON form → parsed as hookSpecificOutput.additionalContext by the hook manager.
|
|
@@ -131,7 +131,7 @@ if (warnings.length) {
|
|
|
131
131
|
`,
|
|
132
132
|
"plugins/sdd/skills/specify/SKILL.md": `---
|
|
133
133
|
name: specify
|
|
134
|
-
description:
|
|
134
|
+
description: 根据自然语言描述创建或更新功能规格说明,并通过单选衔接可选技术方案与编码阶段。
|
|
135
135
|
user-invocable: false
|
|
136
136
|
---
|
|
137
137
|
|
|
@@ -147,7 +147,7 @@ $ARGUMENTS
|
|
|
147
147
|
|
|
148
148
|
根据对话中的功能描述,执行以下步骤:
|
|
149
149
|
|
|
150
|
-
0. **创建进度任务**:用 TaskCreate 创建「编写功能规格」任务,并用 TaskUpdate
|
|
150
|
+
0. **创建进度任务**:用 TaskCreate 创建「编写功能规格」任务,并用 TaskUpdate 标记进行中。后续每个阶段(技术方案、编码)同样在开始前创建任务、结束后更新状态,让用户在任务列表中看到当前进度。
|
|
151
151
|
|
|
152
152
|
1. **确定规格文件路径**:
|
|
153
153
|
- **确定规格根目录**:优先复用项目中已有的规格目录——若 \`docs/specs/\` 存在则用之,否则若 \`specs/\` 存在则用之,否则默认 \`specs/\`(并在完成报告中说明所选目录,便于用户纠正)。
|
|
@@ -172,23 +172,14 @@ $ARGUMENTS
|
|
|
172
172
|
|
|
173
173
|
5. **校验并确认规格**:
|
|
174
174
|
- 运行会话引导中给出的 spec-count 校验命令(自动检测 docs/specs/,否则 specs/,否则跳过)
|
|
175
|
-
- 输出规格文件路径,并通过 AskUserQuestion
|
|
176
|
-
-
|
|
175
|
+
- 输出规格文件路径,并通过 AskUserQuestion 单选请求决策(选项只传:直接实现 / 制定技术方案;AskUserQuestion 会自动附加「其他」选项,勿手动添加「其他」;在问题文案中说明如需调整规格可选「其他」并输入修改意见)
|
|
176
|
+
- 用户选「其他」并输入意见 → 视为规格需要调整:按用户反馈更新规格后重新校验,并再次单选
|
|
177
|
+
- 选「直接实现」→ 将「编写功能规格」任务标记完成,进入编码阶段
|
|
178
|
+
- 选「制定技术方案」→ 将「编写功能规格」任务标记完成;用 TaskCreate 创建「制定技术方案」任务并标记进行中;调用 EnterPlanMode 进入技术方案模式,制定技术方案(技术选型、架构设计、实现步骤)并写入计划文件;用 ExitPlanMode 请求批准——被拒绝则按反馈更新方案后重新请求,批准后标记任务完成
|
|
177
179
|
|
|
178
|
-
6.
|
|
179
|
-
- 仅当需求涉及前端界面时弹出询问;需求不涉及前端界面(如后端服务、CLI 工具、算法库)时,跳过本阶段直接进入下一步,不弹出原型选择
|
|
180
|
-
- 通过 AskUserQuestion 单选询问(选项:制作原型 / 跳过)
|
|
181
|
-
- 选「制作原型」→ 用 TaskCreate 创建「制作原型」任务并标记进行中;仅实现前端界面,数据全部使用 mock(不接后端、不接真实数据);完成后展示可交互原型供用户查看,并将任务标记完成
|
|
182
|
-
- 选「跳过」→ 直接进入下一步
|
|
183
|
-
|
|
184
|
-
7. **询问是否制定技术方案(可选 plan 阶段)**:
|
|
185
|
-
- 通过 AskUserQuestion 单选询问(选项:进入 plan 模式 / 跳过)
|
|
186
|
-
- 选「进入 plan 模式」→ 用 TaskCreate 创建「制定技术方案」任务并标记进行中;调用 EnterPlanMode 进入 plan 模式,制定技术方案(技术选型、架构设计、实现步骤)并写入计划文件;用 ExitPlanMode 请求批准——被拒绝则按反馈更新方案后重新请求,批准后标记任务完成
|
|
187
|
-
- 选「跳过」→ 直接进入下一步
|
|
188
|
-
|
|
189
|
-
8. **编码阶段**:
|
|
180
|
+
6. **编码阶段**:
|
|
190
181
|
- 用 TaskCreate 创建「实现功能」任务并标记进行中
|
|
191
|
-
-
|
|
182
|
+
- 按已确认的规格实现;若批准了技术方案则遵循其架构
|
|
192
183
|
- 实现完成后将任务标记完成
|
|
193
184
|
|
|
194
185
|
## 指南
|
|
@@ -702,7 +702,7 @@ You can extend the Safe Zone by adding \`additionalDirectories\` to your \`permi
|
|
|
702
702
|
|
|
703
703
|
## Permission Modes
|
|
704
704
|
|
|
705
|
-
The \`
|
|
705
|
+
The \`defaultMode\` setting (under \`permissions\`, aligning with Claude Code's settings key) determines how Wave handles requests to use restricted tools (e.g., \`Bash\`, \`Edit\`, \`Write\`, \`AskUserQuestion\`).
|
|
706
706
|
|
|
707
707
|
| Mode | Description |
|
|
708
708
|
| :--- | :--- |
|
|
@@ -717,7 +717,7 @@ The \`permissionMode\` setting determines how Wave handles requests to use restr
|
|
|
717
717
|
\`\`\`json
|
|
718
718
|
{
|
|
719
719
|
"permissions": {
|
|
720
|
-
"
|
|
720
|
+
"defaultMode": "default",
|
|
721
721
|
"additionalDirectories": ["/home/user/my-exports"],
|
|
722
722
|
"allow": ["ls -R", "git status"],
|
|
723
723
|
"deny": ["rm -rf"]
|
|
@@ -735,7 +735,7 @@ You can pre-approve or explicitly forbid specific operations using \`allow\` and
|
|
|
735
735
|
When a tool is called, Wave checks:
|
|
736
736
|
1. If the operation matches a \`deny\` rule, it is rejected.
|
|
737
737
|
2. If the operation matches an \`allow\` rule, it is permitted.
|
|
738
|
-
3. If no rules match, the behavior depends on the \`
|
|
738
|
+
3. If no rules match, the behavior depends on the \`defaultMode\`.
|
|
739
739
|
|
|
740
740
|
### Rule Syntax
|
|
741
741
|
|
|
@@ -998,7 +998,7 @@ For detailed permission configuration and available permission modes, see [PERMI
|
|
|
998
998
|
"permissions": {
|
|
999
999
|
"allow": ["Bash", "Read"],
|
|
1000
1000
|
"deny": ["Write"],
|
|
1001
|
-
"
|
|
1001
|
+
"defaultMode": "default",
|
|
1002
1002
|
"additionalDirectories": ["/tmp/wave-exports"]
|
|
1003
1003
|
}
|
|
1004
1004
|
}
|
|
@@ -1104,10 +1104,6 @@ The \`SKILL.md\` file uses YAML frontmatter for configuration and Markdown for i
|
|
|
1104
1104
|
---
|
|
1105
1105
|
name: my-skill
|
|
1106
1106
|
description: A brief description of what the skill does.
|
|
1107
|
-
context: fork
|
|
1108
|
-
allowed-tools:
|
|
1109
|
-
- Bash
|
|
1110
|
-
- Read
|
|
1111
1107
|
---
|
|
1112
1108
|
|
|
1113
1109
|
# My Skill Instructions
|
|
@@ -1117,6 +1113,8 @@ When this skill is invoked, follow these steps:
|
|
|
1117
1113
|
2. Use the \`Bash\` tool to run \`npm test\`.
|
|
1118
1114
|
\`\`\`
|
|
1119
1115
|
|
|
1116
|
+
By default, new skills only include \`name\` and \`description\`. Only add \`context: fork\` or \`allowed-tools\` when the user explicitly asks for them.
|
|
1117
|
+
|
|
1120
1118
|
### YAML Frontmatter Fields
|
|
1121
1119
|
|
|
1122
1120
|
- \`name\`: (Required) Unique identifier (lowercase, numbers, hyphens).
|
package/dist/core/plugin.d.ts
CHANGED
|
@@ -56,6 +56,10 @@ export declare class PluginCore {
|
|
|
56
56
|
removeMarketplace(name: string, scope?: Scope): Promise<void>;
|
|
57
57
|
/**
|
|
58
58
|
* Updates a specific marketplace or all marketplaces
|
|
59
|
+
*
|
|
60
|
+
* Pulls the latest marketplace source and reinstalls any plugins that are
|
|
61
|
+
* already installed from it, so a manual "update marketplace" also brings
|
|
62
|
+
* installed plugins up to date (mirrors Claude Code's refresh-and-bump).
|
|
59
63
|
*/
|
|
60
64
|
updateMarketplace(name?: string): Promise<void>;
|
|
61
65
|
/**
|
package/dist/core/plugin.js
CHANGED
|
@@ -121,9 +121,15 @@ export class PluginCore {
|
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
123
123
|
* Updates a specific marketplace or all marketplaces
|
|
124
|
+
*
|
|
125
|
+
* Pulls the latest marketplace source and reinstalls any plugins that are
|
|
126
|
+
* already installed from it, so a manual "update marketplace" also brings
|
|
127
|
+
* installed plugins up to date (mirrors Claude Code's refresh-and-bump).
|
|
124
128
|
*/
|
|
125
129
|
async updateMarketplace(name) {
|
|
126
|
-
await this.marketplaceService.updateMarketplace(name
|
|
130
|
+
await this.marketplaceService.updateMarketplace(name, {
|
|
131
|
+
updatePlugins: true,
|
|
132
|
+
});
|
|
127
133
|
}
|
|
128
134
|
/**
|
|
129
135
|
* Lists all registered marketplaces
|
package/dist/index.d.ts
CHANGED
|
@@ -25,7 +25,8 @@ export * from "./utils/nameGenerator.js";
|
|
|
25
25
|
export * from "./utils/pathEncoder.js";
|
|
26
26
|
export * from "./utils/worktreeSession.js";
|
|
27
27
|
export * from "./utils/worktreeUtils.js";
|
|
28
|
-
export { loadMergedWaveConfig, loadUserConfigEnv, } from "./services/configurationService.js";
|
|
28
|
+
export { loadMergedWaveConfig, loadUserConfigEnv, loadWaveConfigFromFile, } from "./services/configurationService.js";
|
|
29
|
+
export { getUserConfigPaths, getProjectConfigPaths, } from "./utils/configPaths.js";
|
|
29
30
|
export * from "./types/index.js";
|
|
30
31
|
export type { SubagentConfiguration } from "./utils/subagentParser.js";
|
|
31
32
|
export type { SubagentInstance } from "./managers/subagentManager.js";
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,8 @@ export * from "./utils/nameGenerator.js";
|
|
|
29
29
|
export * from "./utils/pathEncoder.js";
|
|
30
30
|
export * from "./utils/worktreeSession.js";
|
|
31
31
|
export * from "./utils/worktreeUtils.js";
|
|
32
|
-
export { loadMergedWaveConfig, loadUserConfigEnv, } from "./services/configurationService.js";
|
|
32
|
+
export { loadMergedWaveConfig, loadUserConfigEnv, loadWaveConfigFromFile, } from "./services/configurationService.js";
|
|
33
|
+
export { getUserConfigPaths, getProjectConfigPaths, } from "./utils/configPaths.js";
|
|
33
34
|
export * from "./types/index.js";
|
|
34
35
|
// Export tool building utilities
|
|
35
36
|
export * from "./tools/buildTool.js";
|
|
@@ -189,30 +189,6 @@ export declare class AIManager {
|
|
|
189
189
|
deniedToolMessage?: string;
|
|
190
190
|
maxTurns?: number;
|
|
191
191
|
}, abortSignal?: AbortSignal): Promise<ForkLoopResult>;
|
|
192
|
-
/**
|
|
193
|
-
* Fork subagent ("/subtask"): spawn a background agent that inherits the
|
|
194
|
-
* parent's full conversation context — the same system prompt, tools, model,
|
|
195
|
-
* and message prefix as the main loop — so the forked request prefix matches
|
|
196
|
-
* exactly and the prompt cache is reused. The fork runs to completion in the
|
|
197
|
-
* background via the shared BackgroundTaskManager (visible in /tasks, log at
|
|
198
|
-
* `os.tmpdir()/wave-subagent-<taskId>.log`); its final response is enqueued
|
|
199
|
-
* as a task notification carrying the `<result>` tag, so the main agent
|
|
200
|
-
* picks it up on the next turn and can act on it.
|
|
201
|
-
*
|
|
202
|
-
* Recursion is prevented by denying the Agent tool and the Task management
|
|
203
|
-
* tools (the fork cannot spawn further subagents or mutate the shared task
|
|
204
|
-
* list), and by honoring the parent's denied rules for everything else.
|
|
205
|
-
* Gate-approved tools execute locally in the stripped fork context (no
|
|
206
|
-
* permission prompts), mirroring the other fork paths.
|
|
207
|
-
*
|
|
208
|
-
* Returns the background task ID (empty string when no BackgroundTaskManager
|
|
209
|
-
* is registered, in which case the fork still runs but without task
|
|
210
|
-
* bookkeeping or notification).
|
|
211
|
-
*/
|
|
212
|
-
runForkSubagent(prompt: string, options: {
|
|
213
|
-
description: string;
|
|
214
|
-
maxTurns?: number;
|
|
215
|
-
}, abortSignal?: AbortSignal): Promise<string>;
|
|
216
192
|
/**
|
|
217
193
|
* Parse a fork tool call's JSON arguments, recovering truncated JSON the
|
|
218
194
|
* same way the main loop does. Unparseable arguments fall back to `{}` and
|