@@ -601,4 +601,81 @@ describe('Vercel AI integration (V6)', () => {
601601 } ,
602602 } ,
603603 ) ;
604+
605+ createEsmAndCjsTests (
606+ __dirname ,
607+ 'scenario-tool-loop-agent.mjs' ,
608+ 'instrument.mjs' ,
609+ ( createRunner , test ) => {
610+ test ( 'creates spans for ToolLoopAgent with tool calls' , async ( ) => {
611+ const expectedTransaction = {
612+ transaction : 'main' ,
613+ spans : expect . arrayContaining ( [
614+ // ToolLoopAgent outer span
615+ expect . objectContaining ( {
616+ data : expect . objectContaining ( {
617+ [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] : 'invoke_agent' ,
618+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'gen_ai.invoke_agent' ,
619+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.vercelai.otel' ,
620+ [ GEN_AI_REQUEST_MODEL_ATTRIBUTE ] : 'mock-model-id' ,
621+ } ) ,
622+ op : 'gen_ai.invoke_agent' ,
623+ origin : 'auto.vercelai.otel' ,
624+ status : 'ok' ,
625+ } ) ,
626+ // First doGenerate span (returns tool-calls)
627+ expect . objectContaining ( {
628+ data : expect . objectContaining ( {
629+ [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] : 'generate_content' ,
630+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'gen_ai.generate_content' ,
631+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.vercelai.otel' ,
632+ [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] : 10 ,
633+ [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] : 20 ,
634+ [ GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE ] : [ 'tool-calls' ] ,
635+ } ) ,
636+ op : 'gen_ai.generate_content' ,
637+ origin : 'auto.vercelai.otel' ,
638+ status : 'ok' ,
639+ } ) ,
640+ // Tool execution span
641+ expect . objectContaining ( {
642+ data : expect . objectContaining ( {
643+ [ GEN_AI_TOOL_CALL_ID_ATTRIBUTE ] : 'call-1' ,
644+ [ GEN_AI_TOOL_NAME_ATTRIBUTE ] : 'getWeather' ,
645+ [ GEN_AI_TOOL_TYPE_ATTRIBUTE ] : 'function' ,
646+ [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] : 'execute_tool' ,
647+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'gen_ai.execute_tool' ,
648+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.vercelai.otel' ,
649+ } ) ,
650+ description : 'execute_tool getWeather' ,
651+ op : 'gen_ai.execute_tool' ,
652+ origin : 'auto.vercelai.otel' ,
653+ status : 'ok' ,
654+ } ) ,
655+ // Second doGenerate span (returns final text)
656+ expect . objectContaining ( {
657+ data : expect . objectContaining ( {
658+ [ GEN_AI_OPERATION_NAME_ATTRIBUTE ] : 'generate_content' ,
659+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'gen_ai.generate_content' ,
660+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.vercelai.otel' ,
661+ [ GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE ] : 15 ,
662+ [ GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE ] : 25 ,
663+ [ GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE ] : [ 'stop' ] ,
664+ } ) ,
665+ op : 'gen_ai.generate_content' ,
666+ origin : 'auto.vercelai.otel' ,
667+ status : 'ok' ,
668+ } ) ,
669+ ] ) ,
670+ } ;
671+
672+ await createRunner ( ) . expect ( { transaction : expectedTransaction } ) . start ( ) . completed ( ) ;
673+ } ) ;
674+ } ,
675+ {
676+ additionalDependencies : {
677+ ai : '^6.0.0' ,
678+ } ,
679+ } ,
680+ ) ;
604681} ) ;
0 commit comments