@@ -29,6 +29,27 @@ describe('Vercel AI decide spans', () => {
2929 getMainCarrier ( ) . __SENTRY__ = undefined ;
3030 } ) ;
3131
32+ function recordedAnswers ( provider : string , result : Message [ 'result' ] ) : unknown {
33+ const message = {
34+ type : 'experimental_decide' ,
35+ event : {
36+ provider,
37+ modelId : 'typesafe/jev-1.13' ,
38+ state : 'I was charged twice and the app keeps crashing' ,
39+ questions : { } ,
40+ recordInputs : true ,
41+ recordOutputs : true ,
42+ } ,
43+ result,
44+ } satisfies Message ;
45+
46+ const span = createSpanFromMessage ( message , { } as Parameters < typeof createSpanFromMessage > [ 1 ] ) ! ;
47+ enrichSpanOnEnd ( span , message , { } as Parameters < typeof enrichSpanOnEnd > [ 2 ] ) ;
48+ span . end ( ) ;
49+
50+ return JSON . parse ( spanToStaticSpanJSON ( endedSpans [ 0 ] ! ) . data ?. [ GEN_AI_OUTPUT_MESSAGES ] as string ) [ 0 ] . answers ;
51+ }
52+
3253 // `ai` 7.0.128 renamed the channel event from `experimental_evaluate` to `experimental_decide`.
3354 it . each ( [ 'experimental_evaluate' , 'experimental_decide' ] as const ) ( 'creates a decide span for `%s`' , type => {
3455 const message = {
@@ -58,29 +79,80 @@ describe('Vercel AI decide spans', () => {
5879 } ) ;
5980
6081 it . each ( [ 'typesafe' , 'openai' ] ) ( 'restores answer confidence from `providerMetadata.%s`' , provider => {
61- const message = {
62- type : 'experimental_decide' ,
63- event : {
64- provider,
65- modelId : 'gpt-6-luna' ,
66- state : 'I was charged twice' ,
67- questions : { department : { type : 'choice' , criteria : { billing : 'Charges' , support : 'Other' } } } ,
68- recordInputs : true ,
69- recordOutputs : true ,
70- } ,
71- result : {
72- answers : { department : { type : 'choice' , choice : 'billing' } } ,
73- providerMetadata : { [ provider ] : { confidence : { department : 0.91 } } } ,
74- } ,
75- } satisfies Message ;
82+ const answers = recordedAnswers ( provider , {
83+ answers : { department : { type : 'choice' , choice : 'billing' } } ,
84+ providerMetadata : { [ provider ] : { confidence : { department : 0.91 } } } ,
85+ } ) ;
7686
77- const span = createSpanFromMessage ( message , { } as Parameters < typeof createSpanFromMessage > [ 1 ] ) ! ;
78- enrichSpanOnEnd ( span , message , { } as Parameters < typeof enrichSpanOnEnd > [ 2 ] ) ;
79- span . end ( ) ;
87+ expect ( answers ) . toEqual ( { department : { type : 'choice' , choice : 'billing' , confidence : 0.91 } } ) ;
88+ } ) ;
8089
81- const json = spanToStaticSpanJSON ( endedSpans [ 0 ] ! ) ;
82- expect ( JSON . parse ( json . data ?. [ GEN_AI_OUTPUT_MESSAGES ] as string ) ) . toEqual ( [
83- { type : 'evaluation' , answers : { department : { type : 'choice' , choice : 'billing' , confidence : 0.91 } } } ,
84- ] ) ;
90+ describe ( 'OpenRouter evaluation models' , ( ) => {
91+ it ( 'restores choice confidence from `providerMetadata.openrouter.answers`' , ( ) => {
92+ const answers = recordedAnswers ( 'openrouter' , {
93+ answers : {
94+ department : { type : 'choice' , choice : 'billing' , probabilities : { billing : 0.82 , technical : 0.18 } } ,
95+ wantsRefund : { type : 'boolean' , probability : 0.97 } ,
96+ } ,
97+ providerMetadata : {
98+ openrouter : { provider : 'TypeSafe' , answers : { department : { confidence : 0.64 } , wantsRefund : { } } } ,
99+ } ,
100+ } ) ;
101+
102+ expect ( answers ) . toEqual ( {
103+ department : {
104+ type : 'choice' ,
105+ choice : 'billing' ,
106+ probabilities : { billing : 0.82 , technical : 0.18 } ,
107+ confidence : 0.64 ,
108+ } ,
109+ wantsRefund : { type : 'boolean' , probability : 0.97 } ,
110+ } ) ;
111+ } ) ;
112+
113+ it ( 'restores score confidence and legend from `providerMetadata.openrouter.answers`' , ( ) => {
114+ const legend = { '0' : 'Not urgent' , '1' : 'Handle today' , '2' : 'Page on-call' } ;
115+
116+ const answers = recordedAnswers ( 'openrouter' , {
117+ answers : { urgency : { type : 'score' , score : 1.8 , probabilities : { '0' : 0 , '1' : 0.2 , '2' : 0.8 } } } ,
118+ providerMetadata : { openrouter : { answers : { urgency : { confidence : 0.31 , legend } } } } ,
119+ } ) ;
120+
121+ expect ( answers ) . toEqual ( {
122+ urgency : {
123+ type : 'score' ,
124+ score : 1.8 ,
125+ probabilities : { '0' : 0 , '1' : 0.2 , '2' : 0.8 } ,
126+ confidence : 0.31 ,
127+ legend,
128+ } ,
129+ } ) ;
130+ } ) ;
131+
132+ it . each ( [
133+ [ 'no provider metadata' , undefined ] ,
134+ [ 'no `answers` entry' , { openrouter : { provider : 'TypeSafe' , usage : { cost : 0.0004 } } } ] ,
135+ [ 'no entry for the question' , { openrouter : { answers : { department : { confidence : 0.64 } } } } ] ,
136+ ] ) ( 'leaves answers unchanged with %s' , ( _ , providerMetadata ) => {
137+ const answers = recordedAnswers ( 'openrouter' , {
138+ answers : { urgency : { type : 'score' , score : 1.8 } } ,
139+ providerMetadata,
140+ } ) ;
141+
142+ expect ( answers ) . toEqual ( { urgency : { type : 'score' , score : 1.8 } } ) ;
143+ } ) ;
144+
145+ it ( 'keeps confidence and legend already on the answer' , ( ) => {
146+ const answers = recordedAnswers ( 'openrouter' , {
147+ answers : { urgency : { type : 'score' , score : 1.8 , confidence : 0.9 , legend : { '2' : 'Page on-call' } } } ,
148+ providerMetadata : {
149+ openrouter : { answers : { urgency : { confidence : 0.31 , legend : { '2' : 'Escalate' } } } } ,
150+ } ,
151+ } ) ;
152+
153+ expect ( answers ) . toEqual ( {
154+ urgency : { type : 'score' , score : 1.8 , confidence : 0.9 , legend : { '2' : 'Page on-call' } } ,
155+ } ) ;
156+ } ) ;
85157 } ) ;
86158} ) ;
0 commit comments