1- import type { FormatDescriptor , ToolOutput } from "../types"
2- import { PRUNED_CONTENT_MESSAGE } from "../types"
1+ import type { FormatDescriptor , ToolOutput , ToolTracker } from "../types"
32import type { PluginState } from "../../state"
43import type { Logger } from "../../logger"
5- import type { ToolTracker } from "../../api-formats/synth-instruction"
64import { cacheToolParametersFromInput } from "../../state/tool-cache"
7- import { injectSynthResponses , trackNewToolResultsResponses } from "../../api-formats/synth-instruction"
8- import { injectPrunableListResponses } from "../../api-formats/prunable-list"
5+
6+ // ============================================================================
7+ // Format-specific injection helpers
8+ // ============================================================================
9+
10+ function isNudgeItem ( item : any , nudgeText : string ) : boolean {
11+ if ( typeof item . content === 'string' ) {
12+ return item . content === nudgeText
13+ }
14+ return false
15+ }
16+
17+ function injectSynth ( input : any [ ] , instruction : string , nudgeText : string ) : boolean {
18+ for ( let i = input . length - 1 ; i >= 0 ; i -- ) {
19+ const item = input [ i ]
20+ if ( item . type === 'message' && item . role === 'user' ) {
21+ // Skip nudge messages - find real user message
22+ if ( isNudgeItem ( item , nudgeText ) ) continue
23+
24+ if ( typeof item . content === 'string' ) {
25+ if ( item . content . includes ( instruction ) ) return false
26+ item . content = item . content + '\n\n' + instruction
27+ } else if ( Array . isArray ( item . content ) ) {
28+ const alreadyInjected = item . content . some (
29+ ( part : any ) => part ?. type === 'input_text' && typeof part . text === 'string' && part . text . includes ( instruction )
30+ )
31+ if ( alreadyInjected ) return false
32+ item . content . push ( { type : 'input_text' , text : instruction } )
33+ }
34+ return true
35+ }
36+ }
37+ return false
38+ }
39+
40+ function trackNewToolResults ( input : any [ ] , tracker : ToolTracker , protectedTools : Set < string > ) : number {
41+ let newCount = 0
42+ for ( const item of input ) {
43+ if ( item . type === 'function_call_output' && item . call_id ) {
44+ if ( ! tracker . seenToolResultIds . has ( item . call_id ) ) {
45+ tracker . seenToolResultIds . add ( item . call_id )
46+ const toolName = tracker . getToolName ?.( item . call_id )
47+ if ( ! toolName || ! protectedTools . has ( toolName ) ) {
48+ tracker . toolResultCount ++
49+ newCount ++
50+ }
51+ }
52+ }
53+ }
54+ return newCount
55+ }
56+
57+ function injectPrunableList ( input : any [ ] , injection : string ) : boolean {
58+ if ( ! injection ) return false
59+ input . push ( { type : 'message' , role : 'user' , content : injection } )
60+ return true
61+ }
62+
63+ // ============================================================================
64+ // Format Descriptor
65+ // ============================================================================
966
1067/**
1168 * Format descriptor for OpenAI Responses API (GPT-5 models via sdk.responses()).
@@ -31,15 +88,15 @@ export const openaiResponsesFormat: FormatDescriptor = {
3188 } ,
3289
3390 injectSynth ( data : any [ ] , instruction : string , nudgeText : string ) : boolean {
34- return injectSynthResponses ( data , instruction , nudgeText )
91+ return injectSynth ( data , instruction , nudgeText )
3592 } ,
3693
3794 trackNewToolResults ( data : any [ ] , tracker : ToolTracker , protectedTools : Set < string > ) : number {
38- return trackNewToolResultsResponses ( data , tracker , protectedTools )
95+ return trackNewToolResults ( data , tracker , protectedTools )
3996 } ,
4097
4198 injectPrunableList ( data : any [ ] , injection : string ) : boolean {
42- return injectPrunableListResponses ( data , injection )
99+ return injectPrunableList ( data , injection )
43100 } ,
44101
45102 extractToolOutputs ( data : any [ ] , state : PluginState ) : ToolOutput [ ] {
0 commit comments