@@ -6,7 +6,7 @@ import { CleanupAggregateError, type AgentQuestion, type AgentSummary } from "./
66import { loadProfiles , type ProfilesConfig } from "./profiles.ts" ;
77import type { RunUsage } from "./run-state.ts" ;
88import { SpawnAdmissionController } from "./spawn-admission.ts" ;
9- import { activateForSubagentState , requiresExactResultRead } from "./tool-activation.ts" ;
9+ import { activateForSubagentState , activateSubagentTools , requiresExactResultRead } from "./tool-activation.ts" ;
1010import { bindRegistryUi , notifyCompletion , type RegistryUiBinding } from "./ui/widget.ts" ;
1111
1212export const BACKGROUND_COMPLETION_DEBOUNCE_MS = 50 ;
@@ -161,6 +161,7 @@ export function registerSubagentLifecycle(pi: ExtensionAPI, runtime: DefaultSuba
161161}
162162
163163function sendCompletions ( pi : ExtensionAPI , summaries : readonly AgentSummary [ ] ) : void {
164+ if ( backgroundCompletionsNeedExactRead ( summaries ) ) activateSubagentTools ( pi , [ "read_agent_result" ] ) ;
164165 pi . sendMessage (
165166 {
166167 customType : "subagent-completion" ,
@@ -177,7 +178,24 @@ const BACKGROUND_COMPLETION_NOTICE =
177178const BACKGROUND_RESULT_MAX_BYTES = 2 * 1024 ;
178179const BACKGROUND_BATCH_MAX_BYTES = 16 * 1024 ;
179180
181+ export function backgroundCompletionsNeedExactRead ( summaries : readonly AgentSummary [ ] ) : boolean {
182+ if ( summaries . some ( ( summary ) => requiresExactResultRead ( summary , BACKGROUND_RESULT_MAX_BYTES ) ) ) return true ;
183+ return (
184+ summaries . some ( ( summary ) => summary . result !== undefined ) &&
185+ Buffer . byteLength ( formatBackgroundCompletionContent ( summaries ) , "utf8" ) > BACKGROUND_BATCH_MAX_BYTES
186+ ) ;
187+ }
188+
180189export function formatBackgroundCompletions ( summaries : readonly AgentSummary [ ] ) : string {
190+ const content = formatBackgroundCompletionContent ( summaries ) ;
191+ const exactResultGuidance = backgroundCompletionsNeedExactRead ( summaries )
192+ ? "\nUse read_agent_result with agent_id and generation when exact reconstruction is needed.\n"
193+ : "" ;
194+ const boundedContent = truncateHead ( content , { maxBytes : BACKGROUND_BATCH_MAX_BYTES } ) . content ;
195+ return `${ BACKGROUND_COMPLETION_NOTICE } ${ exactResultGuidance } \n${ boundedContent } ` ;
196+ }
197+
198+ function formatBackgroundCompletionContent ( summaries : readonly AgentSummary [ ] ) : string {
181199 const results = summaries . map ( ( summary ) => {
182200 const output = escapeXml (
183201 truncateHead ( summary . final_text || summary . error || "(no output)" , {
@@ -191,13 +209,7 @@ export function formatBackgroundCompletions(summaries: readonly AgentSummary[]):
191209 : "" ;
192210 return `<subagent_result agent_id="${ escapeXmlAttribute ( summary . agent_id ) } " task_name="${ escapeXmlAttribute ( summary . task_name ) } " generation="${ summary . generation } " status="${ escapeXmlAttribute ( summary . status ) } " profile="${ escapeXmlAttribute ( summary . profile ) } " model="${ escapeXmlAttribute ( summary . model ) } "${ timing } >\n <output>${ output } </output>${ usage } ${ resultReference } \n</subagent_result>` ;
193211 } ) ;
194- const content =
195- results . length === 1 ? ( results [ 0 ] ?? "" ) : `<subagent_results>\n${ results . join ( "\n" ) } \n</subagent_results>` ;
196- const exactResultGuidance = summaries . some ( requiresExactResultRead )
197- ? "\nUse read_agent_result with agent_id and generation when exact reconstruction is needed.\n"
198- : "" ;
199- const boundedContent = truncateHead ( content , { maxBytes : BACKGROUND_BATCH_MAX_BYTES } ) . content ;
200- return `${ BACKGROUND_COMPLETION_NOTICE } ${ exactResultGuidance } \n${ boundedContent } ` ;
212+ return results . length === 1 ? ( results [ 0 ] ?? "" ) : `<subagent_results>\n${ results . join ( "\n" ) } \n</subagent_results>` ;
201213}
202214
203215export function formatSubagentQuestion ( summary : AgentSummary , question : AgentQuestion ) : string {
0 commit comments