@@ -110,8 +110,8 @@ describe("EvaluatorService", () => {
110110 expect ( params . responseSchema . properties ) . toHaveProperty ( "first" ) ;
111111 expect ( params . responseSchema . properties ) . toHaveProperty ( "second" ) ;
112112 expect ( params . responseFormat ) . toEqual ( { type : "json_object" } ) ;
113- expect ( params . prompt ) . toContain ( "### first" ) ;
114- expect ( params . prompt ) . toContain ( "### second" ) ;
113+ expect ( params . messages ?. [ 0 ] ?. content ) . toContain ( "### first" ) ;
114+ expect ( params . messages ?. [ 0 ] ?. content ) . toContain ( "### second" ) ;
115115 return {
116116 first : { ok : true } ,
117117 second : { ok : true } ,
@@ -221,4 +221,129 @@ describe("EvaluatorService", () => {
221221 ] ) ,
222222 ) ;
223223 } ) ;
224+
225+ it ( "retries without responseSchema when the provider rejects structured schemas" , async ( ) => {
226+ const runtime = makeRuntime ( ) ;
227+ const processed : string [ ] = [ ] ;
228+
229+ runtime . registerEvaluator ( {
230+ name : "ok" ,
231+ description : "ok section" ,
232+ schema : schema ( ) ,
233+ shouldRun : async ( ) => true ,
234+ prompt : ( ) => "Extract ok." ,
235+ parse : ( output ) => output as never ,
236+ processors : [
237+ {
238+ name : "storeOk" ,
239+ process : async ( ) => {
240+ processed . push ( "ok" ) ;
241+ return { success : true } ;
242+ } ,
243+ } ,
244+ ] ,
245+ } ) ;
246+
247+ const useModel = vi
248+ . fn ( )
249+ . mockRejectedValueOnce ( new Error ( "Bad Request" ) )
250+ . mockResolvedValueOnce ( { ok : { ok : true } } ) ;
251+ runtime . useModel = useModel as AgentRuntime [ "useModel" ] ;
252+
253+ const result = await new EvaluatorService ( runtime ) . run ( makeMessage ( ) ) ;
254+
255+ expect ( useModel ) . toHaveBeenCalledTimes ( 2 ) ;
256+ expect ( useModel . mock . calls [ 0 ] ?. [ 1 ] ) . toHaveProperty ( "responseSchema" ) ;
257+ expect ( useModel . mock . calls [ 1 ] ?. [ 1 ] ) . not . toHaveProperty ( "responseSchema" ) ;
258+ expect ( useModel . mock . calls [ 1 ] ?. [ 1 ] ?. responseFormat ) . toEqual ( {
259+ type : "json_object" ,
260+ } ) ;
261+ expect ( processed ) . toEqual ( [ "ok" ] ) ;
262+ expect ( result . errors ) . toEqual ( [ ] ) ;
263+ } ) ;
264+
265+ it ( "falls back to a plain JSON prompt when JSON-object mode is also rejected" , async ( ) => {
266+ const runtime = makeRuntime ( ) ;
267+ const processed : string [ ] = [ ] ;
268+
269+ runtime . registerEvaluator ( {
270+ name : "ok" ,
271+ description : "ok section" ,
272+ schema : schema ( ) ,
273+ shouldRun : async ( ) => true ,
274+ prompt : ( ) => "Extract ok." ,
275+ parse : ( output ) => output as never ,
276+ processors : [
277+ {
278+ name : "storeOk" ,
279+ process : async ( ) => {
280+ processed . push ( "ok" ) ;
281+ return { success : true } ;
282+ } ,
283+ } ,
284+ ] ,
285+ } ) ;
286+
287+ const useModel = vi
288+ . fn ( )
289+ . mockRejectedValueOnce ( new Error ( "Bad Request" ) )
290+ . mockRejectedValueOnce ( new Error ( "Bad Request" ) )
291+ . mockResolvedValueOnce ( '{"ok":{"ok":true}}' ) ;
292+ runtime . useModel = useModel as AgentRuntime [ "useModel" ] ;
293+
294+ const result = await new EvaluatorService ( runtime ) . run ( makeMessage ( ) ) ;
295+
296+ expect ( useModel ) . toHaveBeenCalledTimes ( 3 ) ;
297+ expect ( useModel . mock . calls [ 0 ] ?. [ 1 ] ) . toHaveProperty ( "responseSchema" ) ;
298+ expect ( useModel . mock . calls [ 1 ] ?. [ 1 ] ) . toHaveProperty ( "responseFormat" ) ;
299+ expect ( useModel . mock . calls [ 2 ] ?. [ 1 ] ) . not . toHaveProperty ( "responseSchema" ) ;
300+ expect ( useModel . mock . calls [ 2 ] ?. [ 1 ] ) . not . toHaveProperty ( "responseFormat" ) ;
301+ expect ( processed ) . toEqual ( [ "ok" ] ) ;
302+ expect ( result . errors ) . toEqual ( [ ] ) ;
303+ } ) ;
304+
305+ it ( "contains provider generation failures as post-turn evaluator errors" , async ( ) => {
306+ const runtime = makeRuntime ( ) ;
307+
308+ runtime . registerEvaluator ( {
309+ name : "ok" ,
310+ description : "ok section" ,
311+ schema : schema ( ) ,
312+ shouldRun : async ( ) => true ,
313+ prompt : ( ) => "Extract ok." ,
314+ parse : ( output ) => output as never ,
315+ processors : [
316+ {
317+ name : "storeOk" ,
318+ process : async ( ) => ( { success : true } ) ,
319+ } ,
320+ ] ,
321+ } ) ;
322+
323+ const useModel = vi
324+ . fn ( )
325+ . mockRejectedValueOnce ( new Error ( "Bad Request" ) )
326+ . mockRejectedValueOnce ( new Error ( "Bad Request" ) )
327+ . mockRejectedValueOnce ( new Error ( "Bad Request" ) ) ;
328+ runtime . useModel = useModel as AgentRuntime [ "useModel" ] ;
329+
330+ const result = await new EvaluatorService ( runtime ) . run ( makeMessage ( ) ) ;
331+
332+ expect ( useModel ) . toHaveBeenCalledTimes ( 3 ) ;
333+ expect ( result . processedEvaluators ) . toEqual ( [ ] ) ;
334+ expect ( result . results ) . toEqual ( [ ] ) ;
335+ expect ( result . errors ) . toEqual ( [
336+ {
337+ evaluatorName : "post_turn" ,
338+ error : "Bad Request" ,
339+ } ,
340+ ] ) ;
341+ expect ( runtime . emitEvent ) . toHaveBeenCalledWith (
342+ expect . anything ( ) ,
343+ expect . objectContaining ( {
344+ evaluatorName : "post_turn" ,
345+ completed : false ,
346+ } ) ,
347+ ) ;
348+ } ) ;
224349} ) ;
0 commit comments