wave-agent-sdk 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/agent.d.ts +28 -5
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +59 -37
  4. package/dist/constants/tools.d.ts +2 -2
  5. package/dist/constants/tools.js +2 -2
  6. package/dist/managers/MemoryRuleManager.js +1 -1
  7. package/dist/managers/aiManager.d.ts +8 -3
  8. package/dist/managers/aiManager.d.ts.map +1 -1
  9. package/dist/managers/aiManager.js +35 -9
  10. package/dist/managers/backgroundBashManager.d.ts.map +1 -1
  11. package/dist/managers/backgroundBashManager.js +1 -0
  12. package/dist/managers/backgroundTaskManager.d.ts +35 -0
  13. package/dist/managers/backgroundTaskManager.d.ts.map +1 -0
  14. package/dist/managers/backgroundTaskManager.js +249 -0
  15. package/dist/managers/foregroundTaskManager.d.ts +9 -0
  16. package/dist/managers/foregroundTaskManager.d.ts.map +1 -0
  17. package/dist/managers/foregroundTaskManager.js +20 -0
  18. package/dist/managers/liveConfigManager.d.ts +1 -1
  19. package/dist/managers/lspManager.d.ts.map +1 -1
  20. package/dist/managers/lspManager.js +3 -1
  21. package/dist/managers/messageManager.d.ts +12 -2
  22. package/dist/managers/messageManager.d.ts.map +1 -1
  23. package/dist/managers/messageManager.js +36 -2
  24. package/dist/managers/permissionManager.d.ts.map +1 -1
  25. package/dist/managers/permissionManager.js +1 -7
  26. package/dist/managers/pluginManager.d.ts.map +1 -1
  27. package/dist/managers/pluginManager.js +3 -2
  28. package/dist/managers/slashCommandManager.d.ts +3 -0
  29. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  30. package/dist/managers/slashCommandManager.js +1 -0
  31. package/dist/managers/subagentManager.d.ts +11 -2
  32. package/dist/managers/subagentManager.d.ts.map +1 -1
  33. package/dist/managers/subagentManager.js +141 -35
  34. package/dist/managers/toolManager.d.ts +7 -1
  35. package/dist/managers/toolManager.d.ts.map +1 -1
  36. package/dist/managers/toolManager.js +9 -3
  37. package/dist/services/GitService.d.ts.map +1 -1
  38. package/dist/services/GitService.js +6 -2
  39. package/dist/services/MarketplaceService.d.ts +2 -2
  40. package/dist/services/MarketplaceService.d.ts.map +1 -1
  41. package/dist/services/MarketplaceService.js +18 -11
  42. package/dist/services/MemoryRuleService.d.ts +1 -1
  43. package/dist/services/MemoryRuleService.d.ts.map +1 -1
  44. package/dist/services/MemoryRuleService.js +13 -2
  45. package/dist/services/memory.js +1 -1
  46. package/dist/tools/bashTool.d.ts +0 -8
  47. package/dist/tools/bashTool.d.ts.map +1 -1
  48. package/dist/tools/bashTool.js +52 -174
  49. package/dist/tools/editTool.d.ts.map +1 -1
  50. package/dist/tools/editTool.js +6 -5
  51. package/dist/tools/multiEditTool.d.ts.map +1 -1
  52. package/dist/tools/multiEditTool.js +7 -6
  53. package/dist/tools/taskOutputTool.d.ts +3 -0
  54. package/dist/tools/taskOutputTool.d.ts.map +1 -0
  55. package/dist/tools/taskOutputTool.js +149 -0
  56. package/dist/tools/taskStopTool.d.ts +3 -0
  57. package/dist/tools/taskStopTool.d.ts.map +1 -0
  58. package/dist/tools/taskStopTool.js +65 -0
  59. package/dist/tools/taskTool.d.ts.map +1 -1
  60. package/dist/tools/taskTool.js +105 -63
  61. package/dist/tools/types.d.ts +3 -0
  62. package/dist/tools/types.d.ts.map +1 -1
  63. package/dist/types/marketplace.d.ts +1 -0
  64. package/dist/types/marketplace.d.ts.map +1 -1
  65. package/dist/types/messaging.d.ts +1 -0
  66. package/dist/types/messaging.d.ts.map +1 -1
  67. package/dist/types/processes.d.ts +24 -4
  68. package/dist/types/processes.d.ts.map +1 -1
  69. package/dist/utils/editUtils.d.ts +2 -11
  70. package/dist/utils/editUtils.d.ts.map +1 -1
  71. package/dist/utils/editUtils.js +52 -79
  72. package/dist/utils/messageOperations.d.ts +3 -1
  73. package/dist/utils/messageOperations.d.ts.map +1 -1
  74. package/dist/utils/messageOperations.js +5 -1
  75. package/package.json +5 -5
  76. package/src/agent.ts +79 -45
  77. package/src/constants/tools.ts +2 -2
  78. package/src/managers/MemoryRuleManager.ts +1 -1
  79. package/src/managers/aiManager.ts +50 -17
  80. package/src/managers/backgroundBashManager.ts +1 -0
  81. package/src/managers/backgroundTaskManager.ts +306 -0
  82. package/src/managers/foregroundTaskManager.ts +26 -0
  83. package/src/managers/lspManager.ts +3 -1
  84. package/src/managers/messageManager.ts +48 -2
  85. package/src/managers/permissionManager.ts +1 -7
  86. package/src/managers/pluginManager.ts +4 -3
  87. package/src/managers/slashCommandManager.ts +4 -0
  88. package/src/managers/subagentManager.ts +171 -31
  89. package/src/managers/toolManager.ts +16 -4
  90. package/src/services/GitService.ts +6 -2
  91. package/src/services/MarketplaceService.ts +30 -12
  92. package/src/services/MemoryRuleService.ts +18 -6
  93. package/src/services/memory.ts +1 -1
  94. package/src/tools/bashTool.ts +73 -200
  95. package/src/tools/editTool.ts +6 -17
  96. package/src/tools/multiEditTool.ts +7 -18
  97. package/src/tools/taskOutputTool.ts +174 -0
  98. package/src/tools/taskStopTool.ts +72 -0
  99. package/src/tools/taskTool.ts +130 -74
  100. package/src/tools/types.ts +3 -0
  101. package/src/types/marketplace.ts +1 -0
  102. package/src/types/messaging.ts +1 -0
  103. package/src/types/processes.ts +33 -4
  104. package/src/utils/editUtils.ts +65 -103
  105. package/src/utils/messageOperations.ts +7 -0
package/src/agent.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ForegroundTaskManager } from "./managers/foregroundTaskManager.js";
1
2
  import {
2
3
  MessageManager,
3
4
  type MessageManagerCallbacks,
@@ -13,9 +14,9 @@ import { McpManager, type McpManagerCallbacks } from "./managers/mcpManager.js";
13
14
  import { LspManager } from "./managers/lspManager.js";
14
15
  import { BashManager } from "./managers/bashManager.js";
15
16
  import {
16
- BackgroundBashManager,
17
- type BackgroundBashManagerCallbacks,
18
- } from "./managers/backgroundBashManager.js";
17
+ BackgroundTaskManager,
18
+ type BackgroundTaskManagerCallbacks,
19
+ } from "./managers/backgroundTaskManager.js";
19
20
  import { SlashCommandManager } from "./managers/slashCommandManager.js";
20
21
  import { PluginManager } from "./managers/pluginManager.js";
21
22
  import { HookManager } from "./managers/hookManager.js";
@@ -38,6 +39,8 @@ import type {
38
39
  Usage,
39
40
  PermissionMode,
40
41
  PermissionCallback,
42
+ BackgroundTask,
43
+ ForegroundTask,
41
44
  } from "./types/index.js";
42
45
  import { MemoryRuleManager } from "./managers/MemoryRuleManager.js";
43
46
  import { LiveConfigManager } from "./managers/liveConfigManager.js";
@@ -100,10 +103,12 @@ export interface AgentOptions {
100
103
 
101
104
  export interface AgentCallbacks
102
105
  extends MessageManagerCallbacks,
103
- BackgroundBashManagerCallbacks,
106
+ BackgroundTaskManagerCallbacks,
104
107
  McpManagerCallbacks,
105
108
  SubagentManagerCallbacks {
109
+ onTasksChange?: (tasks: BackgroundTask[]) => void;
106
110
  onPermissionModeChange?: (mode: PermissionMode) => void;
111
+ onBackgroundCurrentTask?: () => void;
107
112
  }
108
113
 
109
114
  export class Agent {
@@ -111,7 +116,7 @@ export class Agent {
111
116
  private aiManager: AIManager;
112
117
 
113
118
  private bashManager: BashManager | null = null;
114
- private backgroundBashManager: BackgroundBashManager;
119
+ private backgroundTaskManager: BackgroundTaskManager;
115
120
  private logger?: Logger; // Add optional logger property
116
121
  private toolManager: ToolManager; // Add tool registry instance
117
122
  private mcpManager: McpManager; // Add MCP manager instance
@@ -126,6 +131,7 @@ export class Agent {
126
131
  private reversionManager: ReversionManager;
127
132
  private memoryRuleManager: MemoryRuleManager; // Add memory rule manager instance
128
133
  private liveConfigManager: LiveConfigManager; // Add live configuration manager
134
+ private foregroundTaskManager: ForegroundTaskManager;
129
135
  private configurationService: ConfigurationService; // Add configuration service
130
136
  private workdir: string; // Working directory
131
137
  private systemPrompt?: string; // Custom system prompt
@@ -200,8 +206,15 @@ export class Agent {
200
206
  // Store options for dynamic configuration resolution
201
207
  this.options = options;
202
208
 
203
- this.backgroundBashManager = new BackgroundBashManager({
204
- callbacks,
209
+ this.foregroundTaskManager = new ForegroundTaskManager();
210
+
211
+ this.backgroundTaskManager = new BackgroundTaskManager({
212
+ callbacks: {
213
+ ...callbacks,
214
+ onTasksChange: (tasks) => {
215
+ callbacks.onTasksChange?.(tasks);
216
+ },
217
+ },
205
218
  workdir: this.workdir,
206
219
  });
207
220
  this.mcpManager = new McpManager({ callbacks, logger: this.logger }); // Initialize MCP manager
@@ -230,11 +243,17 @@ export class Agent {
230
243
  workdir: this.workdir,
231
244
  });
232
245
 
246
+ // Initialize memory rule manager
247
+ this.memoryRuleManager = new MemoryRuleManager({
248
+ workdir: this.workdir,
249
+ });
250
+
233
251
  // Initialize MessageManager
234
252
  this.messageManager = new MessageManager({
235
253
  callbacks,
236
254
  workdir: this.workdir,
237
255
  logger: this.logger,
256
+ memoryRuleManager: this.memoryRuleManager,
238
257
  });
239
258
 
240
259
  // Initialize ReversionManager
@@ -242,11 +261,6 @@ export class Agent {
242
261
  new ReversionService(this.messageManager.getTranscriptPath()),
243
262
  );
244
263
 
245
- // Initialize memory rule manager
246
- this.memoryRuleManager = new MemoryRuleManager({
247
- workdir: this.workdir,
248
- });
249
-
250
264
  // Create a wrapper for canUseTool that triggers notification hooks
251
265
  const canUseToolWithNotification: PermissionCallback | undefined =
252
266
  options.canUseTool
@@ -298,6 +312,8 @@ export class Agent {
298
312
  reversionManager: this.reversionManager,
299
313
  permissionMode: options.permissionMode, // Let PermissionManager handle defaultMode resolution
300
314
  canUseToolCallback: canUseToolWithNotification,
315
+ backgroundTaskManager: this.backgroundTaskManager,
316
+ foregroundTaskManager: this.foregroundTaskManager,
301
317
  }); // Initialize tool registry with permission support
302
318
  this.liveConfigManager = new LiveConfigManager({
303
319
  workdir: this.workdir,
@@ -331,6 +347,8 @@ export class Agent {
331
347
  getLanguage: () => this.getLanguage(),
332
348
  hookManager: this.hookManager,
333
349
  onUsageAdded: (usage) => this.addUsage(usage),
350
+ backgroundTaskManager: this.backgroundTaskManager,
351
+ memoryRuleManager: this.memoryRuleManager,
334
352
  });
335
353
 
336
354
  // Initialize AI manager with resolved configuration
@@ -338,7 +356,7 @@ export class Agent {
338
356
  messageManager: this.messageManager,
339
357
  toolManager: this.toolManager,
340
358
  logger: this.logger,
341
- backgroundBashManager: this.backgroundBashManager,
359
+ backgroundTaskManager: this.backgroundTaskManager,
342
360
  hookManager: this.hookManager,
343
361
  permissionManager: this.permissionManager,
344
362
  callbacks: {
@@ -362,6 +380,7 @@ export class Agent {
362
380
  this.slashCommandManager = new SlashCommandManager({
363
381
  messageManager: this.messageManager,
364
382
  aiManager: this.aiManager,
383
+ backgroundTaskManager: this.backgroundTaskManager,
365
384
  workdir: this.workdir,
366
385
  logger: this.logger,
367
386
  });
@@ -456,34 +475,8 @@ export class Agent {
456
475
  }
457
476
 
458
477
  /** Get combined memory content (project + user + modular rules) */
459
- public get combinedMemory(): string {
460
- let combined = "";
461
- if (this._projectMemoryContent.trim()) {
462
- combined += this._projectMemoryContent;
463
- }
464
- if (this._userMemoryContent.trim()) {
465
- if (combined) {
466
- combined += "\n\n";
467
- }
468
- combined += this._userMemoryContent;
469
- }
470
-
471
- // Add modular memory rules
472
- const filesInContext = this.messageManager.getFilesInContext();
473
- const activeRules = this.memoryRuleManager.getActiveRules(filesInContext);
474
- if (activeRules.length > 0) {
475
- this.logger?.debug(
476
- `Active modular rules (${activeRules.length}): ${activeRules.map((r) => r.id).join(", ")}`,
477
- );
478
- if (combined) {
479
- combined += "\n\n";
480
- }
481
- combined += activeRules.map((r) => r.content).join("\n\n");
482
- } else {
483
- this.logger?.debug("No active modular rules for current context");
484
- }
485
-
486
- return combined;
478
+ public async getCombinedMemory(): Promise<string> {
479
+ return this.messageManager.getCombinedMemory();
487
480
  }
488
481
 
489
482
  /** Get AI loading status */
@@ -506,12 +499,25 @@ export class Agent {
506
499
  id: string,
507
500
  filter?: string,
508
501
  ): { stdout: string; stderr: string; status: string } | null {
509
- return this.backgroundBashManager.getOutput(id, filter);
502
+ return this.backgroundTaskManager.getOutput(id, filter);
510
503
  }
511
504
 
512
505
  /** Kill background bash shell */
513
506
  public killBackgroundShell(id: string): boolean {
514
- return this.backgroundBashManager.killShell(id);
507
+ return this.backgroundTaskManager.stopTask(id);
508
+ }
509
+
510
+ /** Get background task output */
511
+ public getBackgroundTaskOutput(
512
+ id: string,
513
+ filter?: string,
514
+ ): { stdout: string; stderr: string; status: string } | null {
515
+ return this.backgroundTaskManager.getOutput(id, filter);
516
+ }
517
+
518
+ /** Stop background task */
519
+ public stopBackgroundTask(id: string): boolean {
520
+ return this.backgroundTaskManager.stopTask(id);
515
521
  }
516
522
 
517
523
  /**
@@ -938,14 +944,42 @@ export class Agent {
938
944
  this.slashCommandManager.abortCurrentCommand();
939
945
  }
940
946
 
947
+ /**
948
+ * Register a foreground task that can be backgrounded
949
+ */
950
+ public registerForegroundTask(task: ForegroundTask): void {
951
+ this.foregroundTaskManager.registerForegroundTask(task);
952
+ }
953
+
954
+ /**
955
+ * Unregister a foreground task
956
+ */
957
+ public unregisterForegroundTask(id: string): void {
958
+ this.foregroundTaskManager.unregisterForegroundTask(id);
959
+ }
960
+
961
+ /**
962
+ * Background the current foreground task
963
+ */
964
+ public async backgroundCurrentTask(): Promise<void> {
965
+ await this.foregroundTaskManager.backgroundCurrentTask();
966
+ this.options.callbacks?.onBackgroundCurrentTask?.();
967
+
968
+ // If there was no foreground task (e.g. a tool that doesn't register one),
969
+ // or even if there was, we should stop the AI recursion loop.
970
+ if (!this.foregroundTaskManager.hasActiveTasks()) {
971
+ this.aiManager.abortRecursion();
972
+ }
973
+ }
974
+
941
975
  /** Destroy managers, clean up resources */
942
976
  public async destroy(): Promise<void> {
943
977
  await this.messageManager.saveSession();
944
978
  this.abortAIMessage(); // This will abort tools including Task tool (subagents)
945
979
  this.abortBashCommand();
946
980
  this.abortSlashCommand();
947
- // Cleanup background bash manager
948
- this.backgroundBashManager.cleanup();
981
+ // Cleanup background task manager
982
+ this.backgroundTaskManager.cleanup();
949
983
  // Cleanup MCP connections
950
984
  await this.mcpManager.cleanup();
951
985
  // Cleanup LSP connections
@@ -1,7 +1,7 @@
1
1
  export const ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion";
2
2
  export const BASH_TOOL_NAME = "Bash";
3
- export const BASH_OUTPUT_TOOL_NAME = "BashOutput";
4
- export const KILL_BASH_TOOL_NAME = "KillBash";
3
+ export const TASK_OUTPUT_TOOL_NAME = "TaskOutput";
4
+ export const TASK_STOP_TOOL_NAME = "TaskStop";
5
5
  export const DELETE_FILE_TOOL_NAME = "Delete";
6
6
  export const EDIT_TOOL_NAME = "Edit";
7
7
  export const EXIT_PLAN_MODE_TOOL_NAME = "ExitPlanMode";
@@ -148,7 +148,7 @@ export class MemoryRuleManager {
148
148
  getActiveRules(filesInContext: string[]): MemoryRule[] {
149
149
  const activeRules: MemoryRule[] = [];
150
150
  for (const rule of Object.values(this.state.rules)) {
151
- if (this.service.isRuleActive(rule, filesInContext)) {
151
+ if (this.service.isRuleActive(rule, filesInContext, this.workdir)) {
152
152
  activeRules.push(rule);
153
153
  }
154
154
  }
@@ -6,7 +6,6 @@ import {
6
6
  import { getMessagesToCompress } from "../utils/messageOperations.js";
7
7
  import { convertMessagesForAPI } from "../utils/convertMessagesForAPI.js";
8
8
  import { calculateComprehensiveTotalTokens } from "../utils/tokenCalculation.js";
9
- import * as memory from "../services/memory.js";
10
9
  import * as fs from "node:fs/promises";
11
10
  import type {
12
11
  Logger,
@@ -17,7 +16,7 @@ import type {
17
16
  import type { ToolManager } from "./toolManager.js";
18
17
  import type { ToolContext, ToolResult } from "../tools/types.js";
19
18
  import type { MessageManager } from "./messageManager.js";
20
- import type { BackgroundBashManager } from "./backgroundBashManager.js";
19
+ import type { BackgroundTaskManager } from "./backgroundTaskManager.js";
21
20
  import { ChatCompletionMessageFunctionToolCall } from "openai/resources.js";
22
21
  import type { HookManager } from "./hookManager.js";
23
22
  import type { ExtendedHookExecutionContext } from "../types/hooks.js";
@@ -36,7 +35,7 @@ export interface AIManagerOptions {
36
35
  messageManager: MessageManager;
37
36
  toolManager: ToolManager;
38
37
  logger?: Logger;
39
- backgroundBashManager?: BackgroundBashManager;
38
+ backgroundTaskManager?: BackgroundTaskManager;
40
39
  hookManager?: HookManager;
41
40
  permissionManager?: PermissionManager;
42
41
  callbacks?: AIManagerCallbacks;
@@ -61,7 +60,7 @@ export class AIManager {
61
60
  private logger?: Logger;
62
61
  private toolManager: ToolManager;
63
62
  private messageManager: MessageManager;
64
- private backgroundBashManager?: BackgroundBashManager;
63
+ private backgroundTaskManager?: BackgroundTaskManager;
65
64
  private hookManager?: HookManager;
66
65
  private reversionManager?: import("./reversionManager.js").ReversionManager;
67
66
  private permissionManager?: PermissionManager;
@@ -80,7 +79,7 @@ export class AIManager {
80
79
  constructor(options: AIManagerOptions) {
81
80
  this.messageManager = options.messageManager;
82
81
  this.toolManager = options.toolManager;
83
- this.backgroundBashManager = options.backgroundBashManager;
82
+ this.backgroundTaskManager = options.backgroundTaskManager;
84
83
  this.hookManager = options.hookManager;
85
84
  this.reversionManager = options.reversionManager;
86
85
  this.permissionManager = options.permissionManager;
@@ -160,6 +159,15 @@ export class AIManager {
160
159
  this.setIsLoading(false);
161
160
  }
162
161
 
162
+ /**
163
+ * Abort the AI recursion loop immediately.
164
+ * This is used when a tool is backgrounded via Ctrl-B, even if no foreground task was active.
165
+ */
166
+ public abortRecursion(): void {
167
+ this.logger?.info("Aborting AI recursion loop");
168
+ this.abortAIMessage();
169
+ }
170
+
163
171
  // Helper method to generate compactParams
164
172
  private generateCompactParams(
165
173
  toolName: string,
@@ -297,9 +305,6 @@ export class AIManager {
297
305
  return;
298
306
  }
299
307
 
300
- // Save session in each recursion to ensure message persistence
301
- await this.messageManager.saveSession();
302
-
303
308
  // Only create new AbortControllers for the initial call (recursionDepth === 0)
304
309
  // For recursive calls, reuse existing controllers to maintain abort signal
305
310
  let abortController: AbortController;
@@ -314,10 +319,14 @@ export class AIManager {
314
319
  this.toolAbortController = toolAbortController;
315
320
  } else {
316
321
  // Reuse existing controllers for recursive calls
317
- abortController = this.abortController!;
318
- toolAbortController = this.toolAbortController!;
322
+ // Fallback to new controllers if they were cleared (should not happen in normal flow but good for tests)
323
+ abortController = this.abortController || new AbortController();
324
+ toolAbortController = this.toolAbortController || new AbortController();
319
325
  }
320
326
 
327
+ // Save session in each recursion to ensure message persistence
328
+ await this.messageManager.saveSession();
329
+
321
330
  // Only set loading state for the initial call
322
331
  if (recursionDepth === 0) {
323
332
  this.setIsLoading(true);
@@ -333,9 +342,7 @@ export class AIManager {
333
342
 
334
343
  try {
335
344
  // Get combined memory content
336
- const combinedMemory = await memory.getCombinedMemoryContent(
337
- this.workdir,
338
- );
345
+ const combinedMemory = await this.messageManager.getCombinedMemory();
339
346
 
340
347
  // Track if assistant message has been created
341
348
  let assistantMessageCreated = false;
@@ -618,7 +625,7 @@ export class AIManager {
618
625
  // Create tool execution context
619
626
  const context: ToolContext = {
620
627
  abortSignal: toolAbortController.signal,
621
- backgroundBashManager: this.backgroundBashManager,
628
+ backgroundTaskManager: this.backgroundTaskManager,
622
629
  workdir: this.workdir,
623
630
  messageId: this.messageManager.getMessages().slice(-1)[0]?.id,
624
631
  };
@@ -630,6 +637,23 @@ export class AIManager {
630
637
  context,
631
638
  );
632
639
 
640
+ // Check if the tool was backgrounded via Ctrl-B
641
+ // If it was backgrounded, we should abort the AI recursion
642
+ if (
643
+ toolResult.success &&
644
+ toolResult.content.includes(
645
+ "Command was manually backgrounded by user",
646
+ )
647
+ ) {
648
+ this.logger?.info(
649
+ `Tool ${toolName} was backgrounded via Ctrl-B, aborting AI recursion`,
650
+ );
651
+ // Use abortAIMessage directly instead of abortRecursion to avoid double logging
652
+ // and ensure we don't trigger the "Request was aborted" error block
653
+ this.abortAIMessage();
654
+ return;
655
+ }
656
+
633
657
  // Update message state - tool execution completed
634
658
  this.messageManager.updateToolBlock({
635
659
  id: toolId,
@@ -709,9 +733,18 @@ export class AIManager {
709
733
  }
710
734
  }
711
735
  } catch (error) {
712
- this.messageManager.addErrorBlock(
713
- error instanceof Error ? error.message : "Unknown error occurred",
714
- );
736
+ // Check if the error is an abort error
737
+ // Use the local variables to avoid null reference if this.abortController was cleared
738
+ const isCurrentlyAborted =
739
+ abortController.signal.aborted || toolAbortController.signal.aborted;
740
+
741
+ if (isCurrentlyAborted) {
742
+ this.logger?.info("AI message processing was aborted");
743
+ } else {
744
+ this.messageManager.addErrorBlock(
745
+ error instanceof Error ? error.message : "Unknown error occurred",
746
+ );
747
+ }
715
748
  } finally {
716
749
  // Only execute cleanup and hooks for the initial call
717
750
  if (recursionDepth === 0) {
@@ -42,6 +42,7 @@ export class BackgroundBashManager {
42
42
 
43
43
  const shell: BackgroundShell = {
44
44
  id,
45
+ type: "shell",
45
46
  process: child,
46
47
  command,
47
48
  startTime,