feat: add silentCompletion + onComplete to spawnBackgroundSubagentTask (#1217)

This commit is contained in:
Devansh Jain
2026-02-27 19:14:05 -08:00
committed by GitHub
parent ba6df7a9ed
commit 0c1f2182a0
2 changed files with 106 additions and 45 deletions

View File

@@ -69,8 +69,15 @@ export interface SpawnBackgroundSubagentTaskArgs {
/**
* When true, skip injecting the completion notification into the primary
* agent's message queue and hide from SubagentGroupDisplay.
* Use `onComplete` to show a user-facing notification without leaking
* into the agent's context.
*/
silentCompletion?: boolean;
/**
* Called after the subagent finishes (success or failure).
* Runs regardless of `silentCompletion`.
*/
onComplete?: (result: { success: boolean; error?: string }) => void;
/**
* Optional dependency overrides for tests.
* Production callers should not provide this.
@@ -197,6 +204,7 @@ export function spawnBackgroundSubagentTask(
existingConversationId,
maxTurns,
silentCompletion,
onComplete,
deps,
} = args;
@@ -268,36 +276,43 @@ export function spawnBackgroundSubagentTask(
totalTokens: result.totalTokens,
});
const subagentSnapshot = getSubagentSnapshotFn();
const toolUses = subagentSnapshot.agents.find(
(agent) => agent.id === subagentId,
)?.toolCalls.length;
const durationMs = Math.max(0, Date.now() - bgTask.startTime.getTime());
onComplete?.({ success: result.success, error: result.error });
const fullResult = result.success
? `${header}\n\n${result.report || ""}`
: result.error || "Subagent execution failed";
const userCwd = process.env.USER_CWD || process.cwd();
const { content: truncatedResult } = truncateByChars(
fullResult,
LIMITS.TASK_OUTPUT_CHARS,
"Task",
{ workingDirectory: userCwd, toolName: "Task" },
);
if (!silentCompletion) {
const subagentSnapshot = getSubagentSnapshotFn();
const toolUses = subagentSnapshot.agents.find(
(agent) => agent.id === subagentId,
)?.toolCalls.length;
const durationMs = Math.max(0, Date.now() - bgTask.startTime.getTime());
const notificationXml = formatTaskNotificationFn({
taskId,
status: result.success ? "completed" : "failed",
summary: `Agent "${description}" ${result.success ? "completed" : "failed"}`,
result: truncatedResult,
outputFile,
usage: {
totalTokens: result.totalTokens,
toolUses,
durationMs,
},
});
addToMessageQueueFn({ kind: "task_notification", text: notificationXml });
const fullResult = result.success
? `${header}\n\n${result.report || ""}`
: result.error || "Subagent execution failed";
const userCwd = process.env.USER_CWD || process.cwd();
const { content: truncatedResult } = truncateByChars(
fullResult,
LIMITS.TASK_OUTPUT_CHARS,
"Task",
{ workingDirectory: userCwd, toolName: "Task" },
);
const notificationXml = formatTaskNotificationFn({
taskId,
status: result.success ? "completed" : "failed",
summary: `Agent "${description}" ${result.success ? "completed" : "failed"}`,
result: truncatedResult,
outputFile,
usage: {
totalTokens: result.totalTokens,
toolUses,
durationMs,
},
});
addToMessageQueueFn({
kind: "task_notification",
text: notificationXml,
});
}
runSubagentStopHooksFn(
subagentType,
@@ -318,23 +333,30 @@ export function spawnBackgroundSubagentTask(
appendToOutputFile(outputFile, `[error] ${errorMessage}\n`);
completeSubagentFn(subagentId, { success: false, error: errorMessage });
const subagentSnapshot = getSubagentSnapshotFn();
const toolUses = subagentSnapshot.agents.find(
(agent) => agent.id === subagentId,
)?.toolCalls.length;
const durationMs = Math.max(0, Date.now() - bgTask.startTime.getTime());
const notificationXml = formatTaskNotificationFn({
taskId,
status: "failed",
summary: `Agent "${description}" failed`,
result: errorMessage,
outputFile,
usage: {
toolUses,
durationMs,
},
});
addToMessageQueueFn({ kind: "task_notification", text: notificationXml });
onComplete?.({ success: false, error: errorMessage });
if (!silentCompletion) {
const subagentSnapshot = getSubagentSnapshotFn();
const toolUses = subagentSnapshot.agents.find(
(agent) => agent.id === subagentId,
)?.toolCalls.length;
const durationMs = Math.max(0, Date.now() - bgTask.startTime.getTime());
const notificationXml = formatTaskNotificationFn({
taskId,
status: "failed",
summary: `Agent "${description}" failed`,
result: errorMessage,
outputFile,
usage: {
toolUses,
durationMs,
},
});
addToMessageQueueFn({
kind: "task_notification",
text: notificationXml,
});
}
runSubagentStopHooksFn(
subagentType,