@@ -11,6 +11,7 @@ import type {
1111} from '@ai-sdk/provider' ;
1212import type { ParseResult } from '@ai-sdk/provider-utils' ;
1313import type { FinishReason } from 'ai' ;
14+ import type { z } from 'zod/v4' ;
1415import type { ReasoningDetailUnion } from '@/src/schemas/reasoning-details' ;
1516import type { OpenRouterUsageAccounting } from '@/src/types/index' ;
1617import type {
@@ -27,18 +28,15 @@ import {
2728 isParsableJson ,
2829 postJsonToApi ,
2930} from '@ai-sdk/provider-utils' ;
30- import { z } from 'zod/v4' ;
31- import {
32- ReasoningDetailArraySchema ,
33- ReasoningDetailType ,
34- } from '@/src/schemas/reasoning-details' ;
35- import {
36- OpenRouterErrorResponseSchema ,
37- openrouterFailedResponseHandler ,
38- } from '../schemas/error-response' ;
31+ import { ReasoningDetailType } from '@/src/schemas/reasoning-details' ;
32+ import { openrouterFailedResponseHandler } from '../schemas/error-response' ;
3933import { mapOpenRouterFinishReason } from '../utils/map-finish-reason' ;
4034import { convertToOpenRouterChatMessages } from './convert-to-openrouter-chat-messages' ;
4135import { getChatCompletionToolChoice } from './get-tool-choice' ;
36+ import {
37+ OpenRouterNonStreamChatCompletionResponseSchema ,
38+ OpenRouterStreamChatCompletionChunkSchema ,
39+ } from './schemas' ;
4240
4341type OpenRouterChatConfig = {
4442 provider : string ;
@@ -562,7 +560,7 @@ export class OpenRouterChatLanguageModel implements LanguageModelV2 {
562560
563561 if ( delta . tool_calls != null ) {
564562 for ( const toolCallDelta of delta . tool_calls ) {
565- const index = toolCallDelta . index ;
563+ const index = toolCallDelta . index ?? toolCalls . length - 1 ;
566564
567565 // Tool call start. OpenRouter returns all information except the arguments in the first chunk.
568566 if ( toolCalls [ index ] == null ) {
@@ -725,129 +723,3 @@ export class OpenRouterChatLanguageModel implements LanguageModelV2 {
725723 } ;
726724 }
727725}
728-
729- const OpenRouterChatCompletionBaseResponseSchema = z . object ( {
730- id : z . string ( ) . optional ( ) ,
731- model : z . string ( ) . optional ( ) ,
732- usage : z
733- . object ( {
734- prompt_tokens : z . number ( ) ,
735- prompt_tokens_details : z
736- . object ( {
737- cached_tokens : z . number ( ) ,
738- } )
739- . nullish ( ) ,
740- completion_tokens : z . number ( ) ,
741- completion_tokens_details : z
742- . object ( {
743- reasoning_tokens : z . number ( ) ,
744- } )
745- . nullish ( ) ,
746- total_tokens : z . number ( ) ,
747- cost : z . number ( ) . optional ( ) ,
748- } )
749- . nullish ( ) ,
750- } ) ;
751-
752- // limited version of the schema, focussed on what is needed for the implementation
753- // this approach limits breakages when the API changes and increases efficiency
754- const OpenRouterNonStreamChatCompletionResponseSchema =
755- OpenRouterChatCompletionBaseResponseSchema . extend ( {
756- choices : z . array (
757- z . object ( {
758- message : z . object ( {
759- role : z . literal ( 'assistant' ) ,
760- content : z . string ( ) . nullable ( ) . optional ( ) ,
761- reasoning : z . string ( ) . nullable ( ) . optional ( ) ,
762- reasoning_details : ReasoningDetailArraySchema . nullish ( ) ,
763-
764- tool_calls : z
765- . array (
766- z . object ( {
767- id : z . string ( ) . optional ( ) . nullable ( ) ,
768- type : z . literal ( 'function' ) ,
769- function : z . object ( {
770- name : z . string ( ) ,
771- arguments : z . string ( ) ,
772- } ) ,
773- } ) ,
774- )
775- . optional ( ) ,
776- } ) ,
777- index : z . number ( ) ,
778- logprobs : z
779- . object ( {
780- content : z
781- . array (
782- z . object ( {
783- token : z . string ( ) ,
784- logprob : z . number ( ) ,
785- top_logprobs : z . array (
786- z . object ( {
787- token : z . string ( ) ,
788- logprob : z . number ( ) ,
789- } ) ,
790- ) ,
791- } ) ,
792- )
793- . nullable ( ) ,
794- } )
795- . nullable ( )
796- . optional ( ) ,
797- finish_reason : z . string ( ) . optional ( ) . nullable ( ) ,
798- } ) ,
799- ) ,
800- } ) ;
801-
802- // limited version of the schema, focussed on what is needed for the implementation
803- // this approach limits breakages when the API changes and increases efficiency
804- const OpenRouterStreamChatCompletionChunkSchema = z . union ( [
805- OpenRouterChatCompletionBaseResponseSchema . extend ( {
806- choices : z . array (
807- z . object ( {
808- delta : z
809- . object ( {
810- role : z . enum ( [ 'assistant' ] ) . optional ( ) ,
811- content : z . string ( ) . nullish ( ) ,
812- reasoning : z . string ( ) . nullish ( ) . optional ( ) ,
813- reasoning_details : ReasoningDetailArraySchema . nullish ( ) ,
814- tool_calls : z
815- . array (
816- z . object ( {
817- index : z . number ( ) ,
818- id : z . string ( ) . nullish ( ) ,
819- type : z . literal ( 'function' ) . optional ( ) ,
820- function : z . object ( {
821- name : z . string ( ) . nullish ( ) ,
822- arguments : z . string ( ) . nullish ( ) ,
823- } ) ,
824- } ) ,
825- )
826- . nullish ( ) ,
827- } )
828- . nullish ( ) ,
829- logprobs : z
830- . object ( {
831- content : z
832- . array (
833- z . object ( {
834- token : z . string ( ) ,
835- logprob : z . number ( ) ,
836- top_logprobs : z . array (
837- z . object ( {
838- token : z . string ( ) ,
839- logprob : z . number ( ) ,
840- } ) ,
841- ) ,
842- } ) ,
843- )
844- . nullable ( ) ,
845- } )
846- . nullish ( ) ,
847- finish_reason : z . string ( ) . nullable ( ) . optional ( ) ,
848- index : z . number ( ) ,
849- } ) ,
850- ) ,
851- } ) ,
852- OpenRouterErrorResponseSchema ,
853- ] ) ;
0 commit comments