wave-agent-sdk 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +54 -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 +3 -3
  8. package/dist/managers/aiManager.d.ts.map +1 -1
  9. package/dist/managers/aiManager.js +3 -4
  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 +137 -39
  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 +44 -172
  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 +73 -45
  77. package/src/constants/tools.ts +2 -2
  78. package/src/managers/MemoryRuleManager.ts +1 -1
  79. package/src/managers/aiManager.ts +6 -9
  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 +167 -35
  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 +59 -196
  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
@@ -46,6 +46,11 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
46
46
  type: "string",
47
47
  description: `The type or name of subagent to use. Available options: ${availableSubagents.map((c) => c.name).join(", ") || "none"}`,
48
48
  },
49
+ run_in_background: {
50
+ type: "boolean",
51
+ description:
52
+ "Set to true to run this command in the background. Use TaskOutput to read the output later.",
53
+ },
49
54
  },
50
55
  required: ["description", "prompt", "subagent_type"],
51
56
  },
@@ -57,80 +62,131 @@ export function createTaskTool(subagentManager: SubagentManager): ToolPlugin {
57
62
  args: Record<string, unknown>,
58
63
  context: ToolContext,
59
64
  ): Promise<ToolResult> => {
60
- // Input validation
61
- const description = args.description as string;
62
- const prompt = args.prompt as string;
63
- const subagent_type = args.subagent_type as string;
64
-
65
- if (!description || typeof description !== "string") {
66
- return {
67
- success: false,
68
- content: "",
69
- error: "description parameter is required and must be a string",
70
- shortResult: "Task delegation failed",
71
- };
72
- }
73
-
74
- if (!prompt || typeof prompt !== "string") {
75
- return {
76
- success: false,
77
- content: "",
78
- error: "prompt parameter is required and must be a string",
79
- shortResult: "Task delegation failed",
80
- };
81
- }
82
-
83
- if (!subagent_type || typeof subagent_type !== "string") {
84
- return {
85
- success: false,
86
- content: "",
87
- error: "subagent_type parameter is required and must be a string",
88
- shortResult: "Task delegation failed",
89
- };
90
- }
91
-
92
- try {
93
- // Subagent selection logic with explicit name matching only
94
- const configuration = await subagentManager.findSubagent(subagent_type);
95
-
96
- if (!configuration) {
97
- // Error handling for nonexistent subagents with available subagents listing
98
- const allConfigs = subagentManager.getConfigurations();
99
- const availableNames = allConfigs.map((c) => c.name).join(", ");
100
-
101
- return {
102
- success: false,
103
- content: "",
104
- error: `No subagent found matching "${subagent_type}". Available subagents: ${availableNames || "none"}`,
105
- shortResult: "Subagent not found",
106
- };
107
- }
108
-
109
- // Create subagent instance and execute task
110
- const instance = await subagentManager.createInstance(configuration, {
111
- description,
112
- prompt,
113
- subagent_type,
114
- });
115
- const response = await subagentManager.executeTask(
116
- instance,
117
- prompt,
118
- context.abortSignal,
119
- );
120
-
121
- return {
122
- success: true,
123
- content: response,
124
- shortResult: `Task completed by ${configuration.name}`,
125
- };
126
- } catch (error) {
127
- return {
128
- success: false,
129
- content: "",
130
- error: `Task delegation failed: ${error instanceof Error ? error.message : String(error)}`,
131
- shortResult: "Delegation error",
132
- };
133
- }
65
+ return new Promise((resolve) => {
66
+ (async () => {
67
+ // Input validation
68
+ const description = args.description as string;
69
+ const prompt = args.prompt as string;
70
+ const subagent_type = args.subagent_type as string;
71
+ const run_in_background = args.run_in_background as boolean;
72
+
73
+ if (!description || typeof description !== "string") {
74
+ return resolve({
75
+ success: false,
76
+ content: "",
77
+ error: "description parameter is required and must be a string",
78
+ shortResult: "Task delegation failed",
79
+ });
80
+ }
81
+
82
+ if (!prompt || typeof prompt !== "string") {
83
+ return resolve({
84
+ success: false,
85
+ content: "",
86
+ error: "prompt parameter is required and must be a string",
87
+ shortResult: "Task delegation failed",
88
+ });
89
+ }
90
+
91
+ if (!subagent_type || typeof subagent_type !== "string") {
92
+ return resolve({
93
+ success: false,
94
+ content: "",
95
+ error: "subagent_type parameter is required and must be a string",
96
+ shortResult: "Task delegation failed",
97
+ });
98
+ }
99
+
100
+ try {
101
+ // Subagent selection logic with explicit name matching only
102
+ const configuration =
103
+ await subagentManager.findSubagent(subagent_type);
104
+
105
+ if (!configuration) {
106
+ // Error handling for nonexistent subagents with available subagents listing
107
+ const allConfigs = subagentManager.getConfigurations();
108
+ const availableNames = allConfigs.map((c) => c.name).join(", ");
109
+
110
+ return resolve({
111
+ success: false,
112
+ content: "",
113
+ error: `No subagent found matching "${subagent_type}". Available subagents: ${availableNames || "none"}`,
114
+ shortResult: "Subagent not found",
115
+ });
116
+ }
117
+
118
+ // Create subagent instance and execute task
119
+ const instance = await subagentManager.createInstance(
120
+ configuration,
121
+ {
122
+ description,
123
+ prompt,
124
+ subagent_type,
125
+ },
126
+ run_in_background,
127
+ );
128
+
129
+ let isBackgrounded = false;
130
+
131
+ // Register for backgrounding if not already in background
132
+ if (!run_in_background && context.foregroundTaskManager) {
133
+ context.foregroundTaskManager.registerForegroundTask({
134
+ id: instance.subagentId,
135
+ backgroundHandler: async () => {
136
+ isBackgrounded = true;
137
+ const taskId = await subagentManager.backgroundInstance(
138
+ instance.subagentId,
139
+ );
140
+ // Resolve the tool execution early so the main agent can continue
141
+ resolve({
142
+ success: true,
143
+ content: `Task moved to background with ID: ${taskId}. Use TaskOutput to monitor progress.`,
144
+ shortResult: "Task backgrounded",
145
+ });
146
+ },
147
+ });
148
+ }
149
+
150
+ try {
151
+ const result = await subagentManager.executeTask(
152
+ instance,
153
+ prompt,
154
+ context.abortSignal,
155
+ run_in_background,
156
+ );
157
+
158
+ if (isBackgrounded) return;
159
+
160
+ if (run_in_background) {
161
+ return resolve({
162
+ success: true,
163
+ content: `Task started in background with ID: ${result}`,
164
+ shortResult: `Task started in background: ${result}`,
165
+ });
166
+ }
167
+
168
+ return resolve({
169
+ success: true,
170
+ content: result,
171
+ shortResult: `Task completed by ${configuration.name}`,
172
+ });
173
+ } finally {
174
+ if (!run_in_background && context.foregroundTaskManager) {
175
+ context.foregroundTaskManager.unregisterForegroundTask(
176
+ instance.subagentId,
177
+ );
178
+ }
179
+ }
180
+ } catch (error) {
181
+ return resolve({
182
+ success: false,
183
+ content: "",
184
+ error: `Task delegation failed: ${error instanceof Error ? error.message : String(error)}`,
185
+ shortResult: "Delegation error",
186
+ });
187
+ }
188
+ })();
189
+ });
134
190
  },
135
191
 
136
192
  formatCompactParams: (params: Record<string, unknown>) => {
@@ -39,6 +39,7 @@ export interface ToolResult {
39
39
  export interface ToolContext {
40
40
  abortSignal?: AbortSignal;
41
41
  backgroundBashManager?: import("../managers/backgroundBashManager.js").BackgroundBashManager;
42
+ backgroundTaskManager?: import("../managers/backgroundTaskManager.js").BackgroundTaskManager;
42
43
  workdir: string;
43
44
  /** Permission mode for this tool execution */
44
45
  permissionMode?: PermissionMode;
@@ -54,4 +55,6 @@ export interface ToolContext {
54
55
  reversionManager?: import("../managers/reversionManager.js").ReversionManager;
55
56
  /** Current message ID for associating snapshots */
56
57
  messageId?: string;
58
+ /** Foreground task manager for backgrounding tasks */
59
+ foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
57
60
  }
@@ -49,6 +49,7 @@ export interface InstalledPlugin {
49
49
  version: string;
50
50
  cachePath: string;
51
51
  scope?: Scope;
52
+ projectPath?: string;
52
53
  }
53
54
 
54
55
  export interface InstalledPluginsRegistry {
@@ -103,6 +103,7 @@ export interface SubagentBlock {
103
103
  status: "active" | "completed" | "error" | "aborted";
104
104
  sessionId: string;
105
105
  configuration: SubagentConfiguration;
106
+ runInBackground?: boolean;
106
107
  }
107
108
 
108
109
  export interface ReasoningBlock {
@@ -5,14 +5,43 @@
5
5
 
6
6
  import type { ChildProcess } from "child_process";
7
7
 
8
- export interface BackgroundShell {
8
+ export type BackgroundTaskStatus =
9
+ | "running"
10
+ | "completed"
11
+ | "failed"
12
+ | "killed";
13
+ export type BackgroundTaskType = "shell" | "subagent";
14
+
15
+ export interface BackgroundTask {
9
16
  id: string;
10
- process: ChildProcess;
11
- command: string;
17
+ type: BackgroundTaskType;
18
+ status: BackgroundTaskStatus;
12
19
  startTime: number;
13
- status: "running" | "completed" | "killed";
20
+ endTime?: number;
21
+ command?: string; // for shell
22
+ description?: string; // for subagent
14
23
  stdout: string;
15
24
  stderr: string;
16
25
  exitCode?: number;
17
26
  runtime?: number;
18
27
  }
28
+
29
+ export interface BackgroundShell extends BackgroundTask {
30
+ type: "shell";
31
+ process: ChildProcess;
32
+ }
33
+
34
+ export interface ForegroundTask {
35
+ id: string;
36
+ backgroundHandler: () => Promise<void>;
37
+ }
38
+
39
+ export interface IForegroundTaskManager {
40
+ registerForegroundTask(task: ForegroundTask): void;
41
+ unregisterForegroundTask(id: string): void;
42
+ }
43
+
44
+ export interface IForegroundTaskManager {
45
+ registerForegroundTask(task: ForegroundTask): void;
46
+ unregisterForegroundTask(id: string): void;
47
+ }
@@ -1,128 +1,90 @@
1
- import { mkdir, writeFile } from "fs/promises";
2
- import path from "path";
3
- import os from "os";
4
- import { logger } from "./globalLogger.js";
5
-
6
1
  /**
7
2
  * Utility functions for file editing tools
8
3
  */
9
4
 
10
5
  /**
11
- * Find a match in content that is identical to searchString except for a consistent indentation offset.
12
- *
13
- * Priority:
14
- * 1. If exact matches exist, returns searchString (letting the tool handle uniqueness/replaceAll).
15
- * 2. If no exact match, but exactly one unique indentation-insensitive match exists, returns that match.
16
- * 3. Otherwise returns null.
6
+ * Escape regular expression special characters
7
+ */
8
+ export function escapeRegExp(string: string): string {
9
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10
+ }
11
+
12
+ /**
13
+ * Analyze why an edit failed by finding the best partial match and highlighting mismatches.
17
14
  */
18
- export function findIndentationInsensitiveMatch(
15
+ export function analyzeEditMismatch(
19
16
  content: string,
20
17
  searchString: string,
21
- ): string | null {
22
- // 1. If exact match exists, return it
23
- if (content.includes(searchString)) {
24
- return searchString;
25
- }
26
-
18
+ ): string {
19
+ const contentLines = content.split("\n");
27
20
  const searchLines = searchString.split("\n");
28
- if (searchLines.length === 0) return null;
29
21
 
30
- const contentLines = content.split("\n");
31
- let foundMatch: string | null = null;
22
+ if (searchLines.length === 0 || contentLines.length === 0) {
23
+ return "old_string not found in file (empty search or content)";
24
+ }
32
25
 
33
- for (let i = 0; i <= contentLines.length - searchLines.length; i++) {
34
- let offset: number | null = null;
35
- let isMatch = true;
26
+ let bestMatchIndex = -1;
27
+ let bestMatchScore = -1;
36
28
 
29
+ // Sliding window to find the best partial match
30
+ for (let i = 0; i <= contentLines.length - searchLines.length; i++) {
31
+ let currentScore = 0;
37
32
  for (let j = 0; j < searchLines.length; j++) {
38
- const sLine = searchLines[j];
39
- const cLine = contentLines[i + j];
40
-
41
- const sTrimmed = sLine.trimStart();
42
- const cTrimmed = cLine.trimStart();
43
-
44
- // If trimmed content doesn't match, it's not a match
45
- if (sTrimmed !== cTrimmed) {
46
- isMatch = false;
47
- break;
33
+ if (contentLines[i + j] === searchLines[j]) {
34
+ currentScore++;
48
35
  }
36
+ }
49
37
 
50
- // For non-empty lines, check for consistent indentation offset
51
- if (sTrimmed !== "") {
52
- const sIndent = sLine.length - sTrimmed.length;
53
- const cIndent = cLine.length - cTrimmed.length;
54
- const currentOffset = cIndent - sIndent;
38
+ // Heuristic: prioritize matches where first or last lines match
39
+ if (contentLines[i] === searchLines[0]) currentScore += 0.5;
40
+ if (
41
+ contentLines[i + searchLines.length - 1] ===
42
+ searchLines[searchLines.length - 1]
43
+ )
44
+ currentScore += 0.5;
55
45
 
56
- if (offset === null) {
57
- offset = currentOffset;
58
- } else if (offset !== currentOffset) {
59
- isMatch = false;
60
- break;
61
- }
46
+ // Also consider trimmed matches to catch indentation issues
47
+ for (let j = 0; j < searchLines.length; j++) {
48
+ if (
49
+ contentLines[i + j].trim() === searchLines[j].trim() &&
50
+ contentLines[i + j] !== searchLines[j]
51
+ ) {
52
+ currentScore += 0.1;
62
53
  }
63
54
  }
64
55
 
65
- if (isMatch) {
66
- const matchCandidate = contentLines
67
- .slice(i, i + searchLines.length)
68
- .join("\n");
69
- if (foundMatch !== null && foundMatch !== matchCandidate) {
70
- // Multiple different smart matches found
71
- return null;
72
- }
73
- foundMatch = matchCandidate;
56
+ if (currentScore > bestMatchScore) {
57
+ bestMatchScore = currentScore;
58
+ bestMatchIndex = i;
74
59
  }
75
60
  }
76
61
 
77
- // If we found exactly one unique smart match (or multiple instances of the same smart match)
78
- // return it. The tool will then check for uniqueness if replaceAll is false.
79
- return foundMatch;
80
- }
81
-
82
- /**
83
- * Escape regular expression special characters
84
- */
85
- export function escapeRegExp(string: string): string {
86
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
87
- }
88
-
89
- /**
90
- * Save a snapshot of the old string and current file content for debugging
91
- */
92
- export async function saveEditErrorSnapshot(
93
- filePath: string,
94
- oldString: string,
95
- currentContent: string,
96
- toolName: string,
97
- ): Promise<string | null> {
98
- try {
99
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
100
- const fileName = path.basename(filePath);
101
- const snapshotDirName = `${timestamp}_${toolName}_${fileName}`;
102
- const snapshotDir = path.join(
103
- os.tmpdir(),
104
- "wave-agent-edit-errors",
105
- snapshotDirName,
106
- );
107
-
108
- await mkdir(snapshotDir, { recursive: true });
109
-
110
- await Promise.all([
111
- writeFile(path.join(snapshotDir, "old_string.txt"), oldString, "utf-8"),
112
- writeFile(
113
- path.join(snapshotDir, "file_content.txt"),
114
- currentContent,
115
- "utf-8",
116
- ),
117
- ]);
118
-
119
- logger.error(
120
- `Edit error snapshot saved to: ${snapshotDir}\nFile: ${filePath}\nTool: ${toolName}`,
121
- );
62
+ // If no decent match found (score <= 0), return generic message
63
+ if (bestMatchScore <= 0) {
64
+ return "old_string not found in file (no similar block found)";
65
+ }
122
66
 
123
- return snapshotDir;
124
- } catch (error) {
125
- logger.error(`Failed to save edit error snapshot: ${error}`);
126
- return null;
67
+ // Generate detailed report
68
+ const reportLines: string[] = [
69
+ `old_string not found in file. Best partial match found at line ${bestMatchIndex + 1}:`,
70
+ ];
71
+
72
+ for (let j = 0; j < searchLines.length; j++) {
73
+ const lineNum = bestMatchIndex + j + 1;
74
+ const actualLine = contentLines[bestMatchIndex + j];
75
+ const expectedLine = searchLines[j];
76
+
77
+ if (actualLine === expectedLine) {
78
+ reportLines.push(`${lineNum.toString().padStart(4)} | ${actualLine}`);
79
+ } else {
80
+ reportLines.push(
81
+ `${lineNum.toString().padStart(4)} | - ${expectedLine} (expected)`,
82
+ );
83
+ reportLines.push(
84
+ `${lineNum.toString().padStart(4)} | + ${actualLine} (actual)`,
85
+ );
86
+ }
127
87
  }
88
+
89
+ return reportLines.join("\n");
128
90
  }
@@ -504,6 +504,7 @@ export interface AddSubagentBlockParams {
504
504
  status: "active" | "completed" | "error" | "aborted";
505
505
  sessionId: string;
506
506
  configuration: SubagentConfiguration;
507
+ runInBackground?: boolean;
507
508
  }
508
509
 
509
510
  export interface UpdateSubagentBlockParams {
@@ -520,6 +521,7 @@ export const addSubagentBlockToMessage = ({
520
521
  status,
521
522
  sessionId,
522
523
  configuration,
524
+ runInBackground,
523
525
  }: AddSubagentBlockParams): Message[] => {
524
526
  const newMessages = [...messages];
525
527
 
@@ -544,6 +546,7 @@ export const addSubagentBlockToMessage = ({
544
546
  status,
545
547
  sessionId,
546
548
  configuration,
549
+ runInBackground,
547
550
  });
548
551
 
549
552
  return newMessages;
@@ -555,6 +558,7 @@ export const updateSubagentBlockInMessage = (
555
558
  updates: Partial<{
556
559
  status: "active" | "completed" | "error" | "aborted";
557
560
  sessionId: string;
561
+ runInBackground: boolean;
558
562
  }>,
559
563
  ): Message[] => {
560
564
  const newMessages = [...messages];
@@ -571,6 +575,9 @@ export const updateSubagentBlockInMessage = (
571
575
  if (updates.sessionId !== undefined) {
572
576
  block.sessionId = updates.sessionId;
573
577
  }
578
+ if (updates.runInBackground !== undefined) {
579
+ block.runInBackground = updates.runInBackground;
580
+ }
574
581
  return newMessages;
575
582
  }
576
583
  }