wave-agent-sdk 0.17.6 → 0.17.7

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.
@@ -1,7 +1,5 @@
1
1
  import type { MessageManager } from "./messageManager.js";
2
2
  import type { AIManager } from "./aiManager.js";
3
- import type { BackgroundTaskManager } from "./backgroundTaskManager.js";
4
- import type { TaskManager } from "../services/taskManager.js";
5
3
  import type { SlashCommand, CustomSlashCommand } from "../types/index.js";
6
4
  import { loadCustomSlashCommands } from "../utils/customCommands.js";
7
5
 
@@ -23,10 +21,6 @@ import {
23
21
  import type { SkillManager } from "./skillManager.js";
24
22
  import type { SkillMetadata } from "../types/skills.js";
25
23
  import type { SubagentManager } from "./subagentManager.js";
26
- import type { MemoryService } from "../services/memory.js";
27
- import type { HookManager } from "./hookManager.js";
28
- import type { GoalManager } from "./goalManager.js";
29
-
30
24
  import { logger } from "../utils/globalLogger.js";
31
25
 
32
26
  export interface SlashCommandManagerOptions {
@@ -48,7 +42,6 @@ export class SlashCommandManager {
48
42
  }
49
43
 
50
44
  public initialize(): void {
51
- this.initializeBuiltinCommands();
52
45
  this.loadCustomCommands();
53
46
 
54
47
  // Listen for skill refreshes and update skill commands
@@ -68,14 +61,6 @@ export class SlashCommandManager {
68
61
  return this.container.get<AIManager>("AIManager")!;
69
62
  }
70
63
 
71
- private get backgroundTaskManager(): BackgroundTaskManager {
72
- return this.container.get<BackgroundTaskManager>("BackgroundTaskManager")!;
73
- }
74
-
75
- private get taskManager(): TaskManager {
76
- return this.container.get<TaskManager>("TaskManager")!;
77
- }
78
-
79
64
  private get skillManager(): SkillManager {
80
65
  return this.container.get<SkillManager>("SkillManager")!;
81
66
  }
@@ -84,206 +69,6 @@ export class SlashCommandManager {
84
69
  return this.container.get<SubagentManager>("SubagentManager")!;
85
70
  }
86
71
 
87
- private get memoryService(): MemoryService {
88
- return this.container.get<MemoryService>("MemoryService")!;
89
- }
90
-
91
- private get hookManager(): HookManager | undefined {
92
- return this.container.get<HookManager>("HookManager");
93
- }
94
-
95
- private get goalManager(): GoalManager | undefined {
96
- return this.container.get<GoalManager>("GoalManager");
97
- }
98
-
99
- private initializeBuiltinCommands(): void {
100
- // Register built-in clear command
101
- this.registerCommand({
102
- id: "clear",
103
- name: "clear",
104
- description: "Clear conversation history and reset session",
105
- immediate: true,
106
- handler: async () => {
107
- this.aiManager.abortAIMessage();
108
-
109
- // Clear any active goal
110
- this.goalManager?.clearGoal();
111
-
112
- // Capture old session info before clearing
113
- const oldSessionId = this.messageManager.getSessionId();
114
- const transcriptPath = this.messageManager.getTranscriptPath();
115
-
116
- // Run SessionEnd hooks (cleanup before clear)
117
- if (this.hookManager) {
118
- try {
119
- await this.hookManager.executeSessionEndHooks(
120
- "clear",
121
- oldSessionId,
122
- transcriptPath,
123
- );
124
- } catch (error) {
125
- logger?.warn(
126
- `SessionEnd hooks on clear failed: ${(error as Error).message}`,
127
- );
128
- }
129
- }
130
-
131
- // Clear messages and generate new session
132
- this.messageManager.clearMessages();
133
- this.memoryService.clearCache();
134
- await this.taskManager.syncWithSession();
135
-
136
- // Run SessionStart hooks (restore context for new session)
137
- if (this.hookManager) {
138
- try {
139
- const newSessionId = this.messageManager.getSessionId();
140
- const sessionStartResult =
141
- await this.hookManager.executeSessionStartHooks(
142
- "clear",
143
- newSessionId,
144
- this.messageManager.getTranscriptPath(),
145
- );
146
-
147
- // Inject additionalContext as a meta user message
148
- if (sessionStartResult.additionalContext) {
149
- this.messageManager.addUserMessage({
150
- content: `<system-reminder>\nSessionStart hook additional context: ${sessionStartResult.additionalContext}\n</system-reminder>`,
151
- isMeta: true,
152
- });
153
- }
154
-
155
- // Inject initialUserMessage as a meta user message
156
- if (sessionStartResult.initialUserMessage) {
157
- this.messageManager.addUserMessage({
158
- content: sessionStartResult.initialUserMessage,
159
- isMeta: true,
160
- });
161
- }
162
- } catch (error) {
163
- logger?.warn(
164
- `SessionStart hooks on clear failed: ${(error as Error).message}`,
165
- );
166
- }
167
- }
168
- },
169
- });
170
-
171
- // Register built-in compact command
172
- this.registerCommand({
173
- id: "compact",
174
- name: "compact",
175
- description: "Compact conversation history to reduce context usage",
176
- immediate: true,
177
- handler: async (args?: string, signal?: AbortSignal) => {
178
- this.aiManager.abortAIMessage();
179
-
180
- const customInstructions = args?.trim() || undefined;
181
-
182
- await this.aiManager.compactConversation({
183
- customInstructions,
184
- abortSignal: signal,
185
- });
186
- },
187
- });
188
-
189
- // Register built-in goal command
190
- this.registerCommand({
191
- id: "goal",
192
- name: "goal",
193
- description: "Set, check, or clear an autonomous goal for the session",
194
- immediate: (args?: string) => {
195
- const trimmed = args?.trim() ?? "";
196
- return (
197
- !trimmed ||
198
- ["clear", "stop", "off", "reset", "none", "cancel"].includes(trimmed)
199
- );
200
- },
201
- handler: async (args?: string) => {
202
- const goalManager = this.goalManager;
203
- if (!goalManager) {
204
- this.messageManager.addUserMessage({
205
- content: "Goal manager is not available",
206
- isMeta: true,
207
- });
208
- return;
209
- }
210
-
211
- const trimmed = args?.trim() ?? "";
212
-
213
- // Clear aliases
214
- if (
215
- ["clear", "stop", "off", "reset", "none", "cancel"].includes(trimmed)
216
- ) {
217
- if (goalManager.isGoalActive()) {
218
- goalManager.clearGoal();
219
- this.messageManager.addUserMessage({
220
- content: "<system-reminder>Goal cleared.</system-reminder>",
221
- isMeta: true,
222
- });
223
- } else {
224
- this.messageManager.addUserMessage({
225
- content:
226
- "<system-reminder>No active goal to clear.</system-reminder>",
227
- isMeta: true,
228
- });
229
- }
230
- return;
231
- }
232
-
233
- // Show status
234
- if (!trimmed) {
235
- if (goalManager.isGoalActive()) {
236
- this.messageManager.addUserMessage({
237
- content: `<system-reminder>${goalManager.getStatusString()}</system-reminder>`,
238
- isMeta: true,
239
- });
240
- } else {
241
- this.messageManager.addUserMessage({
242
- content:
243
- "<system-reminder>No active goal. Use /goal <condition> to set one.</system-reminder>",
244
- isMeta: true,
245
- });
246
- }
247
- return;
248
- }
249
-
250
- // Check plan mode
251
- const permissionMode = this.container.has("PermissionMode")
252
- ? this.container.get<
253
- import("../types/permissions.js").PermissionMode
254
- >("PermissionMode")
255
- : undefined;
256
- if (permissionMode === "plan") {
257
- this.messageManager.addUserMessage({
258
- content:
259
- "<system-reminder>Cannot set a goal in plan mode. Exit plan mode first.</system-reminder>",
260
- isMeta: true,
261
- });
262
- return;
263
- }
264
-
265
- // Set goal
266
- try {
267
- goalManager.setGoal(trimmed);
268
- this.messageManager.addUserMessage({
269
- content: `<system-reminder>Goal set: ${trimmed}. The agent will work autonomously until this goal is achieved.</system-reminder>`,
270
- isMeta: true,
271
- });
272
- // Add the goal as a user directive to start working
273
- this.messageManager.addUserMessage({
274
- content: trimmed,
275
- });
276
- this.aiManager.sendAIMessage();
277
- } catch (error) {
278
- this.messageManager.addUserMessage({
279
- content: `<system-reminder>Failed to set goal: ${(error as Error).message}</system-reminder>`,
280
- isMeta: true,
281
- });
282
- }
283
- },
284
- });
285
- }
286
-
287
72
  /**
288
73
  * Load custom commands from filesystem
289
74
  */
@@ -364,11 +364,7 @@ class ToolManager {
364
364
  return false;
365
365
  }
366
366
  if (effectivePermissionMode === "bypassPermissions") {
367
- if (
368
- tool.name === "ExitPlanMode" ||
369
- tool.name === "AskUserQuestion" ||
370
- tool.name === "EnterPlanMode"
371
- ) {
367
+ if (tool.name === "ExitPlanMode") {
372
368
  return false;
373
369
  }
374
370
  }
@@ -376,10 +372,7 @@ class ToolManager {
376
372
  return effectivePermissionMode === "plan";
377
373
  }
378
374
  if (tool.name === "EnterPlanMode") {
379
- return (
380
- effectivePermissionMode !== "plan" &&
381
- effectivePermissionMode !== "bypassPermissions"
382
- );
375
+ return effectivePermissionMode !== "plan";
383
376
  }
384
377
  return true;
385
378
  })
@@ -106,26 +106,14 @@ This is critical - your turn should only end with either using the ${ASK_USER_QU
106
106
  NOTE: At any point in time through this workflow you should feel free to ask the user questions or clarifications using the ${ASK_USER_QUESTION_TOOL_NAME} tool. Don't make large assumptions about user intent. The goal is to present a well researched plan to the user, and tie any loose ends before implementation begins.`);
107
107
  }
108
108
 
109
- export function buildPlanModeSparseReminder(planFilePath: string): string {
110
- return wrapInSystemReminder(
111
- `Plan mode still active (see full instructions earlier in conversation). Read-only except plan file at ${planFilePath}. End turns with ${ASK_USER_QUESTION_TOOL_NAME} or ${EXIT_PLAN_MODE_TOOL_NAME}.`,
112
- );
113
- }
114
-
115
109
  export function buildPlanModeReEntryReminder(planFilePath: string): string {
116
110
  return wrapInSystemReminder(`## Re-entering Plan Mode
117
111
 
118
- You are returning to plan mode after having previously exited it. A plan file exists at ${planFilePath} from your previous planning session.
112
+ You are returning to plan mode. A plan file exists at ${planFilePath} from your previous session.
119
113
 
120
- **Before proceeding with any new planning, you should:**
121
114
  1. Read the existing plan file to understand what was previously planned
122
- 2. Evaluate the user's current request against that plan
123
- 3. Decide how to proceed:
124
- - **Different task**: If the user's request is for a different task—even if it's similar or related—start fresh by overwriting the existing plan
125
- - **Same task, continuing**: If this is explicitly a continuation or refinement of the exact same task, modify the existing plan while cleaning up outdated or irrelevant sections
126
- 4. Continue on with the plan process and most importantly you should always edit the plan file one way or the other before calling ${EXIT_PLAN_MODE_TOOL_NAME}
127
-
128
- Treat this as a fresh planning session. Do not assume the existing plan is relevant without evaluating it first.`);
115
+ 2. Decide: if the user's request is a different task, start fresh by overwriting the plan; if it's a continuation, modify the existing plan
116
+ 3. Edit the plan file as needed, then call ${EXIT_PLAN_MODE_TOOL_NAME}`);
129
117
  }
130
118
 
131
119
  export function buildExitedPlanModeReminder(