@@ -13,7 +13,10 @@ import {
1313} from "@/adapters" ;
1414import { getModelsWithProviderBySystemName } from "@/db" ;
1515import { apiKeyPlugin , type ApiKey } from "@/plugins/apiKeyPlugin" ;
16- import { apiKeyRateLimitPlugin , consumeTokens } from "@/plugins/apiKeyRateLimitPlugin" ;
16+ import {
17+ apiKeyRateLimitPlugin ,
18+ consumeTokens ,
19+ } from "@/plugins/apiKeyRateLimitPlugin" ;
1720import { rateLimitPlugin } from "@/plugins/rateLimitPlugin" ;
1821import {
1922 extractUpstreamHeaders ,
@@ -78,11 +81,18 @@ const tAnthropicToolResultBlock = t.Object({
7881 is_error : t . Optional ( t . Boolean ( ) ) ,
7982} ) ;
8083
84+ const tAnthropicThinkingBlock = t . Object ( {
85+ type : t . Literal ( "thinking" ) ,
86+ thinking : t . String ( ) ,
87+ signature : t . String ( ) ,
88+ } ) ;
89+
8190const tAnthropicContentBlock = t . Union ( [
8291 tAnthropicTextBlock ,
8392 tAnthropicImageBlock ,
8493 tAnthropicToolUseBlock ,
8594 tAnthropicToolResultBlock ,
95+ tAnthropicThinkingBlock ,
8696] ) ;
8797
8898// Anthropic tool definition
@@ -241,7 +251,11 @@ async function processNonStreamingResponse(
241251
242252 // Consume tokens for TPM rate limiting (post-flight)
243253 // Only consume if token counts are valid (not -1 which indicates parsing failure)
244- if ( apiKeyRecord && completion . promptTokens > 0 && completion . completionTokens > 0 ) {
254+ if (
255+ apiKeyRecord &&
256+ completion . promptTokens > 0 &&
257+ completion . completionTokens > 0
258+ ) {
245259 const totalTokens = completion . promptTokens + completion . completionTokens ;
246260 await consumeTokens ( apiKeyRecord . id , apiKeyRecord . tpmLimit , totalTokens ) ;
247261 }
@@ -305,7 +319,10 @@ async function* processStreamingResponse(
305319 id : `msg-cache-${ reqIdContext . preCreatedCompletionId } ` ,
306320 type : "message" ,
307321 role : "assistant" ,
308- content : contentBlocks . length > 0 ? contentBlocks : [ { type : "text" , text : "" } ] ,
322+ content :
323+ contentBlocks . length > 0
324+ ? contentBlocks
325+ : [ { type : "text" , text : "" } ] ,
309326 model : comp . model ,
310327 stop_reason : hasToolUse ? "tool_use" : "end_turn" ,
311328 usage : {
@@ -320,7 +337,14 @@ async function* processStreamingResponse(
320337 : undefined ;
321338
322339 // Create streaming context with abort handling
323- const ctx = new StreamingContext ( completion , bearer , apiKeyRecord , begin , signal , streamingReqIdContext ) ;
340+ const ctx = new StreamingContext (
341+ completion ,
342+ bearer ,
343+ apiKeyRecord ,
344+ begin ,
345+ signal ,
346+ streamingReqIdContext ,
347+ ) ;
324348
325349 // Track whether we've logged the client abort (to avoid duplicate logs)
326350 let loggedAbort = false ;
@@ -335,7 +359,9 @@ async function* processStreamingResponse(
335359 // Log client disconnect once when first detected
336360 if ( clientAborted && ! loggedAbort ) {
337361 loggedAbort = true ;
338- logger . info ( "Client disconnected during streaming, continuing to collect upstream data" ) ;
362+ logger . info (
363+ "Client disconnected during streaming, continuing to collect upstream data" ,
364+ ) ;
339365 }
340366
341367 ctx . recordTTFT ( ) ;
@@ -365,7 +391,10 @@ async function* processStreamingResponse(
365391 chunk . delta . thinking
366392 ) {
367393 ctx . thinkingParts . push ( chunk . delta . thinking ) ;
368- } else if ( chunk . delta ?. type === "input_json_delta" && chunk . delta . partialJson ) {
394+ } else if (
395+ chunk . delta ?. type === "input_json_delta" &&
396+ chunk . delta . partialJson
397+ ) {
369398 // Collect tool call arguments - lookup by index to get tool ID
370399 // Skip if index is missing to avoid data corruption
371400 if ( chunk . index !== undefined ) {
@@ -434,7 +463,10 @@ async function* processStreamingResponse(
434463 if ( ! ctx . isSaved ( ) ) {
435464 if ( ctx . isAborted ( ) ) {
436465 // If client aborted and we got an error, still save as aborted with the error info
437- await ctx . saveCompletion ( "aborted" , `Client disconnected, stream error: ${ String ( error ) } ` ) ;
466+ await ctx . saveCompletion (
467+ "aborted" ,
468+ `Client disconnected, stream error: ${ String ( error ) } ` ,
469+ ) ;
438470 } else {
439471 await ctx . saveCompletion ( "failed" , String ( error ) ) ;
440472 }
@@ -545,10 +577,15 @@ export const messagesApi = new Elysia({
545577 model : body . model ,
546578 modelId : candidates [ 0 ] ?. model . id ,
547579 prompt : {
548- messages : body . messages . map ( ( m : { role : string ; content : unknown } ) => ( {
549- role : m . role ,
550- content : typeof m . content === "string" ? m . content : JSON . stringify ( m . content ) ,
551- } ) ) ,
580+ messages : body . messages . map (
581+ ( m : { role : string ; content : unknown } ) => ( {
582+ role : m . role ,
583+ content :
584+ typeof m . content === "string"
585+ ? m . content
586+ : JSON . stringify ( m . content ) ,
587+ } ) ,
588+ ) ,
552589 extraHeaders,
553590 } ,
554591 apiFormat,
@@ -619,7 +656,12 @@ export const messagesApi = new Elysia({
619656 extraHeaders ,
620657 ) ;
621658
622- const errorResult = await processFailoverError ( result , completion , bearer , "streaming" ) ;
659+ const errorResult = await processFailoverError (
660+ result ,
661+ completion ,
662+ bearer ,
663+ "streaming" ,
664+ ) ;
623665
624666 // Finalize pre-created completion if ReqId was used
625667 await finalizeReqIdOnError ( reqIdContext , begin ) ;
@@ -718,7 +760,12 @@ export const messagesApi = new Elysia({
718760 extraHeaders ,
719761 ) ;
720762
721- const errorResult = await processFailoverError ( result , completion , bearer , "non-streaming" ) ;
763+ const errorResult = await processFailoverError (
764+ result ,
765+ completion ,
766+ bearer ,
767+ "non-streaming" ,
768+ ) ;
722769
723770 // Finalize pre-created completion if ReqId was used
724771 await finalizeReqIdOnError ( reqIdContext , begin ) ;
@@ -782,7 +829,8 @@ export const messagesApi = new Elysia({
782829 return JSON . parse ( response ) as Record < string , unknown > ;
783830 } catch ( error ) {
784831 // Handle error based on whether client aborted
785- const errorMsg = error instanceof Error ? error . message : String ( error ) ;
832+ const errorMsg =
833+ error instanceof Error ? error . message : String ( error ) ;
786834 // Only save if completion wasn't already saved in processNonStreamingResponse
787835 const alreadySaved = completion . status !== "pending" ;
788836 if ( request . signal . aborted ) {
@@ -799,7 +847,10 @@ export const messagesApi = new Elysia({
799847 } ,
800848 } ) ;
801849 } catch ( logError : unknown ) {
802- logger . error ( "Failed to log aborted completion after processing error" , logError ) ;
850+ logger . error (
851+ "Failed to log aborted completion after processing error" ,
852+ logError ,
853+ ) ;
803854 }
804855 }
805856 // Return nothing for aborted requests
@@ -818,13 +869,19 @@ export const messagesApi = new Elysia({
818869 } ,
819870 } ) ;
820871 } catch ( logError : unknown ) {
821- logger . error ( "Failed to log completion after processing error" , logError ) ;
872+ logger . error (
873+ "Failed to log completion after processing error" ,
874+ logError ,
875+ ) ;
822876 }
823877 }
824878 set . status = 500 ;
825879 return {
826880 type : "error" ,
827- error : { type : "api_error" , message : "Failed to process response" } ,
881+ error : {
882+ type : "api_error" ,
883+ message : "Failed to process response" ,
884+ } ,
828885 } ;
829886 }
830887 }
0 commit comments