@@ -36,35 +36,6 @@ import {
3636} from "./provider-catalog.js" ;
3737import { resolveThinkingProfile } from "./provider-policy-api.js" ;
3838
39- function createOpenRouterDoneStream ( params : { responseId : string ; totalCost : number } ) {
40- const stream = createAssistantMessageEventStream ( ) ;
41- queueMicrotask ( ( ) => {
42- stream . push ( {
43- type : "done" ,
44- reason : "stop" ,
45- message : {
46- role : "assistant" ,
47- api : "openai-completions" ,
48- provider : "openrouter" ,
49- model : "openrouter/auto" ,
50- content : [ { type : "text" , text : "ok" } ] ,
51- responseId : params . responseId ,
52- stopReason : "stop" ,
53- timestamp : Date . now ( ) ,
54- usage : {
55- input : 1 ,
56- output : 1 ,
57- cacheRead : 0 ,
58- cacheWrite : 0 ,
59- totalTokens : 2 ,
60- cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 , total : params . totalCost } ,
61- } ,
62- } as never ,
63- } ) ;
64- } ) ;
65- return stream ;
66- }
67-
6839function createOpenRouterDoneStreamWithoutGeneration ( ) {
6940 const stream = createAssistantMessageEventStream ( ) ;
7041 queueMicrotask ( ( ) => {
@@ -85,35 +56,6 @@ function createOpenRouterDoneStreamWithoutGeneration() {
8556 return stream ;
8657}
8758
88- function createOpenRouterAbortedStream ( ) {
89- const stream = createAssistantMessageEventStream ( ) ;
90- queueMicrotask ( ( ) => {
91- stream . push ( {
92- type : "error" ,
93- reason : "aborted" ,
94- error : {
95- role : "assistant" ,
96- api : "openai-completions" ,
97- provider : "openrouter" ,
98- model : "openrouter/auto" ,
99- content : [ ] ,
100- responseId : "gen-aborted" ,
101- stopReason : "aborted" ,
102- timestamp : Date . now ( ) ,
103- usage : {
104- input : 1 ,
105- output : 1 ,
106- cacheRead : 0 ,
107- cacheWrite : 0 ,
108- totalTokens : 2 ,
109- cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 , total : 0.001 } ,
110- } ,
111- } as never ,
112- } ) ;
113- } ) ;
114- return stream ;
115- }
116-
11759type OpenRouterManifest = {
11860 providerAuthChoices ?: Array < {
11961 provider ?: string ;
@@ -808,172 +750,6 @@ describe("openrouter provider hooks", () => {
808750 expect ( headers . get ( "x-openrouter-title" ) ) . toBe ( "OpenClaw" ) ;
809751 } ) ;
810752
811- it ( "reconciles OpenRouter streamed usage with generation metadata cost" , async ( ) => {
812- const provider = await registerSingleProviderPlugin ( openrouterPlugin ) ;
813- const fetchMock = vi . fn ( async ( url : string ) => {
814- expect ( url ) . toBe ( "https://openrouter.ai/api/v1/generation?id=gen-cost-1" ) ;
815- return new Response ( JSON . stringify ( { data : { total_cost : 0.0042 } } ) , {
816- headers : { "Content-Type" : "application/json" } ,
817- status : 200 ,
818- } ) ;
819- } ) ;
820- vi . stubGlobal ( "fetch" , fetchMock ) ;
821- const baseStreamFn = vi . fn ( ( ) =>
822- createOpenRouterDoneStream ( { responseId : "gen-cost-1" , totalCost : 0.001 } ) ,
823- ) ;
824-
825- try {
826- const wrapped = provider . wrapStreamFn ?.( {
827- provider : "openrouter" ,
828- modelId : "openrouter/auto" ,
829- streamFn : baseStreamFn ,
830- } as never ) ;
831- if ( ! wrapped ) {
832- throw new Error ( "expected OpenRouter wrapper" ) ;
833- }
834- const stream = await wrapped (
835- {
836- provider : "openrouter" ,
837- api : "openai-completions" ,
838- id : "openrouter/auto" ,
839- baseUrl : "https://openrouter.ai/api/v1" ,
840- compat : { } ,
841- } as never ,
842- { messages : [ ] } as never ,
843- { apiKey : "or-test-key" } as never ,
844- ) ;
845- const message = await stream . result ( ) ;
846-
847- expect ( fetchMock ) . toHaveBeenCalledOnce ( ) ;
848- expect ( message . usage . cost . total ) . toBe ( 0.0042 ) ;
849- } finally {
850- vi . unstubAllGlobals ( ) ;
851- }
852- } ) ;
853-
854- it ( "falls back to streamed cost estimate when generation metadata response is oversized" , async ( ) => {
855- const provider = await registerSingleProviderPlugin ( openrouterPlugin ) ;
856- // Body exceeds the 16 MiB cap; readProviderJsonResponse must reject it and
857- // applyOpenRouterBilledCost must fall back to the streamed estimate.
858- const oversizedBody = new ReadableStream < Uint8Array > ( {
859- start ( controller ) {
860- controller . enqueue ( new Uint8Array ( 16 * 1024 * 1024 + 1 ) . fill ( 0x78 ) ) ;
861- controller . close ( ) ;
862- } ,
863- } ) ;
864- const fetchMock = vi . fn ( async ( url : string ) => {
865- expect ( url ) . toBe ( "https://openrouter.ai/api/v1/generation?id=gen-oversized-1" ) ;
866- return new Response ( oversizedBody , {
867- headers : { "Content-Type" : "application/json" } ,
868- status : 200 ,
869- } ) ;
870- } ) ;
871- vi . stubGlobal ( "fetch" , fetchMock ) ;
872- const baseStreamFn = vi . fn ( ( ) =>
873- createOpenRouterDoneStream ( { responseId : "gen-oversized-1" , totalCost : 0.001 } ) ,
874- ) ;
875-
876- try {
877- const wrapped = provider . wrapStreamFn ?.( {
878- provider : "openrouter" ,
879- modelId : "openrouter/auto" ,
880- streamFn : baseStreamFn ,
881- } as never ) ;
882- if ( ! wrapped ) {
883- throw new Error ( "expected OpenRouter wrapper" ) ;
884- }
885- const stream = await wrapped (
886- {
887- provider : "openrouter" ,
888- api : "openai-completions" ,
889- id : "openrouter/auto" ,
890- baseUrl : "https://openrouter.ai/api/v1" ,
891- compat : { } ,
892- } as never ,
893- { messages : [ ] } as never ,
894- { apiKey : "or-test-key" } as never ,
895- ) ;
896- const message = await stream . result ( ) ;
897-
898- expect ( fetchMock ) . toHaveBeenCalledOnce ( ) ;
899- expect ( message . usage . cost . total ) . toBe ( 0.001 ) ;
900- } finally {
901- vi . unstubAllGlobals ( ) ;
902- }
903- } ) ;
904-
905- it ( "does not fetch generation metadata for custom OpenRouter-compatible routes" , async ( ) => {
906- const provider = await registerSingleProviderPlugin ( openrouterPlugin ) ;
907- const fetchMock = vi . fn ( ) ;
908- vi . stubGlobal ( "fetch" , fetchMock ) ;
909- const baseStreamFn = vi . fn ( ( ) =>
910- createOpenRouterDoneStream ( { responseId : "gen-custom-route" , totalCost : 0.001 } ) ,
911- ) ;
912-
913- try {
914- const wrapped = provider . wrapStreamFn ?.( {
915- provider : "openrouter" ,
916- modelId : "openrouter/auto" ,
917- streamFn : baseStreamFn ,
918- } as never ) ;
919- if ( ! wrapped ) {
920- throw new Error ( "expected OpenRouter wrapper" ) ;
921- }
922- const stream = await wrapped (
923- {
924- provider : "openrouter" ,
925- api : "openai-completions" ,
926- id : "openrouter/auto" ,
927- baseUrl : "https://proxy.example.test/api/v1" ,
928- compat : { } ,
929- } as never ,
930- { messages : [ ] } as never ,
931- { apiKey : "or-test-key" } as never ,
932- ) ;
933- const message = await stream . result ( ) ;
934-
935- expect ( fetchMock ) . not . toHaveBeenCalled ( ) ;
936- expect ( message . usage . cost . total ) . toBe ( 0.001 ) ;
937- } finally {
938- vi . unstubAllGlobals ( ) ;
939- }
940- } ) ;
941-
942- it ( "does not fetch generation metadata for aborted stream errors" , async ( ) => {
943- const provider = await registerSingleProviderPlugin ( openrouterPlugin ) ;
944- const fetchMock = vi . fn ( ) ;
945- vi . stubGlobal ( "fetch" , fetchMock ) ;
946- const baseStreamFn = vi . fn ( ( ) => createOpenRouterAbortedStream ( ) ) ;
947-
948- try {
949- const wrapped = provider . wrapStreamFn ?.( {
950- provider : "openrouter" ,
951- modelId : "openrouter/auto" ,
952- streamFn : baseStreamFn ,
953- } as never ) ;
954- if ( ! wrapped ) {
955- throw new Error ( "expected OpenRouter wrapper" ) ;
956- }
957- const stream = await wrapped (
958- {
959- provider : "openrouter" ,
960- api : "openai-completions" ,
961- id : "openrouter/auto" ,
962- baseUrl : "https://openrouter.ai/api/v1" ,
963- compat : { } ,
964- } as never ,
965- { messages : [ ] } as never ,
966- { apiKey : "or-test-key" } as never ,
967- ) ;
968- const message = await stream . result ( ) ;
969-
970- expect ( fetchMock ) . not . toHaveBeenCalled ( ) ;
971- expect ( message . stopReason ) . toBe ( "aborted" ) ;
972- } finally {
973- vi . unstubAllGlobals ( ) ;
974- }
975- } ) ;
976-
977753 it ( "merges resolved OpenRouter model params into transport params" , async ( ) => {
978754 const provider = await registerSingleProviderPlugin ( openrouterPlugin ) ;
979755 const patch = provider . extraParamsForTransport ?.( {
0 commit comments