@@ -9,86 +9,6 @@ import type { StepText, ToolCall } from '../types/agent-definition'
99
1010type FilePickerMode = 'default' | 'max'
1111
12- /**
13- * Type guard to check if value is a non-null object.
14- * DUPLICATE: Keep in sync with copies inside handleStepsDefault and handleStepsMax (required for serialization).
15- */
16- function isObject ( value : unknown ) : value is Record < string , unknown > {
17- return value !== null && typeof value === 'object'
18- }
19-
20- /**
21- * Extracts spawn results from tool result array, returning agent values.
22- * DUPLICATE: Keep in sync with copies inside handleStepsDefault and handleStepsMax (required for serialization).
23- */
24- function extractSpawnResults ( results : unknown [ ] | undefined ) : unknown [ ] {
25- if ( ! results || results . length === 0 ) return [ ]
26- const jsonResult = results . find (
27- ( r ) : r is { type : 'json' ; value : unknown } =>
28- isObject ( r ) && r . type === 'json' ,
29- )
30- if ( ! jsonResult ?. value ) return [ ]
31- const spawnedResults = Array . isArray ( jsonResult . value )
32- ? jsonResult . value
33- : [ jsonResult . value ]
34- // Each spawned result may be an object with a .value property (spawn wrapper)
35- // or the agent output directly (type: 'lastMessage' or type: 'error')
36- return spawnedResults
37- . map ( ( result : unknown ) => {
38- if ( ! isObject ( result ) ) return undefined
39- // If it's a spawn wrapper with .value, extract the value
40- if ( 'value' in result && result . type !== 'lastMessage' && result . type !== 'error' ) {
41- return result . value
42- }
43- // Otherwise it's the agent output directly
44- return result
45- } )
46- . filter ( Boolean )
47- }
48-
49- /**
50- * Extracts the most recent assistant text from an agent's output.
51- * DUPLICATE: Keep in sync with copies inside handleStepsDefault and handleStepsMax (required for serialization).
52- */
53- function extractLastMessageText ( agentOutput : unknown ) : string | null {
54- if ( ! isObject ( agentOutput ) ) return null
55- if ( agentOutput . type !== 'lastMessage' || ! Array . isArray ( agentOutput . value ) ) {
56- return null
57- }
58- for ( let i = agentOutput . value . length - 1 ; i >= 0 ; i -- ) {
59- const message = agentOutput . value [ i ]
60- if (
61- isObject ( message ) &&
62- message . role === 'assistant' &&
63- Array . isArray ( message . content )
64- ) {
65- for ( const part of message . content ) {
66- if (
67- isObject ( part ) &&
68- part . type === 'text' &&
69- typeof part . text === 'string'
70- ) {
71- return part . text
72- }
73- }
74- }
75- }
76- return null
77- }
78-
79- /**
80- * Extracts error message from agent output if present.
81- * DUPLICATE: Keep in sync with copies inside handleStepsDefault and handleStepsMax (required for serialization).
82- */
83- function extractErrorMessage ( agentOutput : unknown ) : string | null {
84- if ( ! isObject ( agentOutput ) ) return null
85- if ( agentOutput . type === 'error' ) {
86- if ( typeof agentOutput . message === 'string' ) return agentOutput . message
87- if ( typeof agentOutput . value === 'string' ) return agentOutput . value
88- }
89- return null
90- }
91-
9212export const createFilePicker = (
9313 mode : FilePickerMode ,
9414) : Omit < SecretAgentDefinition , 'id' > => {
@@ -147,71 +67,6 @@ const handleStepsDefault: SecretAgentDefinition['handleSteps'] = function* ({
14767 prompt,
14868 params,
14969} ) {
150- // ============================================================================
151- // Helper functions duplicated inside generator for sandbox serialization.
152- // DUPLICATE: Keep in sync with module-level versions.
153- // ============================================================================
154- function isObject ( value : unknown ) : value is Record < string , unknown > {
155- return value !== null && typeof value === 'object'
156- }
157-
158- function extractSpawnResults ( results : unknown [ ] | undefined ) : unknown [ ] {
159- if ( ! results || results . length === 0 ) return [ ]
160- const jsonResult = results . find (
161- ( r ) : r is { type : 'json' ; value : unknown } =>
162- isObject ( r ) && r . type === 'json' ,
163- )
164- if ( ! jsonResult ?. value ) return [ ]
165- const spawnedResults = Array . isArray ( jsonResult . value )
166- ? jsonResult . value
167- : [ jsonResult . value ]
168- return spawnedResults
169- . map ( ( result : unknown ) => {
170- if ( ! isObject ( result ) ) return undefined
171- if ( 'value' in result && result . type !== 'lastMessage' && result . type !== 'error' ) {
172- return result . value
173- }
174- return result
175- } )
176- . filter ( Boolean )
177- }
178-
179- function extractLastMessageText ( agentOutput : unknown ) : string | null {
180- if ( ! isObject ( agentOutput ) ) return null
181- if ( agentOutput . type !== 'lastMessage' || ! Array . isArray ( agentOutput . value ) ) {
182- return null
183- }
184- for ( let i = agentOutput . value . length - 1 ; i >= 0 ; i -- ) {
185- const message = agentOutput . value [ i ]
186- if (
187- isObject ( message ) &&
188- message . role === 'assistant' &&
189- Array . isArray ( message . content )
190- ) {
191- for ( const part of message . content ) {
192- if (
193- isObject ( part ) &&
194- part . type === 'text' &&
195- typeof part . text === 'string'
196- ) {
197- return part . text
198- }
199- }
200- }
201- }
202- return null
203- }
204-
205- function extractErrorMessage ( agentOutput : unknown ) : string | null {
206- if ( ! isObject ( agentOutput ) ) return null
207- if ( agentOutput . type === 'error' ) {
208- if ( typeof agentOutput . message === 'string' ) return agentOutput . message
209- if ( typeof agentOutput . value === 'string' ) return agentOutput . value
210- }
211- return null
212- }
213- // ============================================================================
214-
21570 const { toolResult : fileListerResults } = yield {
21671 toolName : 'spawn_agents' ,
21772 input : {
@@ -265,78 +120,50 @@ const handleStepsDefault: SecretAgentDefinition['handleSteps'] = function* ({
265120
266121 yield 'STEP'
267122
268- }
269-
270- // handleSteps for max mode - spawns 2 file-listers in parallel
271- const handleStepsMax : SecretAgentDefinition [ 'handleSteps' ] = function * ( {
272- prompt,
273- params,
274- } ) {
275- // ============================================================================
276- // Helper functions duplicated inside generator for sandbox serialization.
277- // DUPLICATE: Keep in sync with module-level versions.
278- // ============================================================================
279- function isObject ( value : unknown ) : value is Record < string , unknown > {
280- return value !== null && typeof value === 'object'
281- }
282-
283- function extractSpawnResults ( results : unknown [ ] | undefined ) : unknown [ ] {
123+ function extractSpawnResults ( results : any [ ] | undefined ) : any [ ] {
284124 if ( ! results || results . length === 0 ) return [ ]
285- const jsonResult = results . find (
286- ( r ) : r is { type : 'json' ; value : unknown } =>
287- isObject ( r ) && r . type === 'json' ,
288- )
125+ const jsonResult = results . find ( ( r ) => r . type === 'json' )
289126 if ( ! jsonResult ?. value ) return [ ]
290127 const spawnedResults = Array . isArray ( jsonResult . value )
291128 ? jsonResult . value
292129 : [ jsonResult . value ]
293- return spawnedResults
294- . map ( ( result : unknown ) => {
295- if ( ! isObject ( result ) ) return undefined
296- if ( 'value' in result && result . type !== 'lastMessage' && result . type !== 'error' ) {
297- return result . value
298- }
299- return result
300- } )
301- . filter ( Boolean )
130+ return spawnedResults . map ( ( result : any ) => result ?. value ) . filter ( Boolean )
302131 }
303132
304- function extractLastMessageText ( agentOutput : unknown ) : string | null {
305- if ( ! isObject ( agentOutput ) ) return null
306- if ( agentOutput . type !== 'lastMessage' || ! Array . isArray ( agentOutput . value ) ) {
307- return null
308- }
309- for ( let i = agentOutput . value . length - 1 ; i >= 0 ; i -- ) {
310- const message = agentOutput . value [ i ]
311- if (
312- isObject ( message ) &&
313- message . role === 'assistant' &&
314- Array . isArray ( message . content )
315- ) {
316- for ( const part of message . content ) {
317- if (
318- isObject ( part ) &&
319- part . type === 'text' &&
320- typeof part . text === 'string'
321- ) {
322- return part . text
133+ function extractLastMessageText ( agentOutput : any ) : string | null {
134+ if ( ! agentOutput ) return null
135+ if (
136+ agentOutput . type === 'lastMessage' &&
137+ Array . isArray ( agentOutput . value )
138+ ) {
139+ for ( let i = agentOutput . value . length - 1 ; i >= 0 ; i -- ) {
140+ const message = agentOutput . value [ i ]
141+ if ( message . role === 'assistant' && Array . isArray ( message . content ) ) {
142+ for ( const part of message . content ) {
143+ if ( part . type === 'text' && typeof part . text === 'string' ) {
144+ return part . text
145+ }
323146 }
324147 }
325148 }
326149 }
327150 return null
328151 }
329152
330- function extractErrorMessage ( agentOutput : unknown ) : string | null {
331- if ( ! isObject ( agentOutput ) ) return null
153+ function extractErrorMessage ( agentOutput : any ) : string | null {
154+ if ( ! agentOutput ) return null
332155 if ( agentOutput . type === 'error' ) {
333- if ( typeof agentOutput . message === 'string' ) return agentOutput . message
334- if ( typeof agentOutput . value === 'string' ) return agentOutput . value
156+ return agentOutput . message ?? agentOutput . value ?? null
335157 }
336158 return null
337159 }
338- // ============================================================================
160+ }
339161
162+ // handleSteps for max mode - spawns 2 file-listers in parallel
163+ const handleStepsMax : SecretAgentDefinition [ 'handleSteps' ] = function * ( {
164+ prompt,
165+ params,
166+ } ) {
340167 const { toolResult : fileListerResults } = yield {
341168 toolName : 'spawn_agents' ,
342169 input : {
@@ -394,6 +221,44 @@ const handleStepsMax: SecretAgentDefinition['handleSteps'] = function* ({
394221 }
395222
396223 yield 'STEP'
224+
225+ function extractSpawnResults ( results : any [ ] | undefined ) : any [ ] {
226+ if ( ! results || results . length === 0 ) return [ ]
227+ const jsonResult = results . find ( ( r ) => r . type === 'json' )
228+ if ( ! jsonResult ?. value ) return [ ]
229+ const spawnedResults = Array . isArray ( jsonResult . value )
230+ ? jsonResult . value
231+ : [ jsonResult . value ]
232+ return spawnedResults . map ( ( result : any ) => result ?. value ) . filter ( Boolean )
233+ }
234+
235+ function extractLastMessageText ( agentOutput : any ) : string | null {
236+ if ( ! agentOutput ) return null
237+ if (
238+ agentOutput . type === 'lastMessage' &&
239+ Array . isArray ( agentOutput . value )
240+ ) {
241+ for ( let i = agentOutput . value . length - 1 ; i >= 0 ; i -- ) {
242+ const message = agentOutput . value [ i ]
243+ if ( message . role === 'assistant' && Array . isArray ( message . content ) ) {
244+ for ( const part of message . content ) {
245+ if ( part . type === 'text' && typeof part . text === 'string' ) {
246+ return part . text
247+ }
248+ }
249+ }
250+ }
251+ }
252+ return null
253+ }
254+
255+ function extractErrorMessage ( agentOutput : any ) : string | null {
256+ if ( ! agentOutput ) return null
257+ if ( agentOutput . type === 'error' ) {
258+ return agentOutput . message ?? agentOutput . value ?? null
259+ }
260+ return null
261+ }
397262}
398263
399264const definition : SecretAgentDefinition = {
0 commit comments