copilot-api-plus 1.0.11 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -681,6 +681,165 @@ const apiKeyAuthMiddleware = async (c, next) => {
681
681
  await next();
682
682
  };
683
683
 
684
+ //#endregion
685
+ //#region src/services/antigravity/stream-parser.ts
686
+ /**
687
+ * Create initial stream state
688
+ */
689
+ function createStreamState() {
690
+ return {
691
+ buffer: "",
692
+ inputTokens: 0,
693
+ outputTokens: 0,
694
+ contentBlockIndex: 0,
695
+ thinkingBlockStarted: false,
696
+ textBlockStarted: false
697
+ };
698
+ }
699
+ /**
700
+ * Parse a single SSE line and return the JSON data if valid
701
+ */
702
+ function parseSSELine(line) {
703
+ if (!line.startsWith("data: ")) return null;
704
+ const data = line.slice(6).trim();
705
+ if (data === "[DONE]" || data === "") return null;
706
+ try {
707
+ return JSON.parse(data);
708
+ } catch {
709
+ return null;
710
+ }
711
+ }
712
+ /**
713
+ * Extract candidates and usage from parsed data
714
+ */
715
+ function extractFromData(data) {
716
+ const candidates = data.response?.candidates || data.candidates || [];
717
+ const usage = data.response?.usageMetadata || data.usageMetadata;
718
+ return {
719
+ candidates,
720
+ usage
721
+ };
722
+ }
723
+ /**
724
+ * Process a single part and emit events
725
+ */
726
+ function processPart(part, state$1, emit) {
727
+ if (part.thought && part.text) {
728
+ processThinkingPart(part.text, state$1, emit);
729
+ return;
730
+ }
731
+ if (part.text && !part.thought) {
732
+ processTextPart(part.text, state$1, emit);
733
+ return;
734
+ }
735
+ if (part.functionCall) processToolPart(part.functionCall, state$1, emit);
736
+ }
737
+ /**
738
+ * Process thinking content
739
+ */
740
+ function processThinkingPart(text, state$1, emit) {
741
+ if (!state$1.thinkingBlockStarted) {
742
+ emit({
743
+ type: "thinking_start",
744
+ index: state$1.contentBlockIndex
745
+ });
746
+ state$1.thinkingBlockStarted = true;
747
+ }
748
+ emit({
749
+ type: "thinking_delta",
750
+ index: state$1.contentBlockIndex,
751
+ text
752
+ });
753
+ }
754
+ /**
755
+ * Process text content
756
+ */
757
+ function processTextPart(text, state$1, emit) {
758
+ if (state$1.thinkingBlockStarted && !state$1.textBlockStarted) {
759
+ emit({
760
+ type: "thinking_stop",
761
+ index: state$1.contentBlockIndex
762
+ });
763
+ state$1.contentBlockIndex++;
764
+ state$1.thinkingBlockStarted = false;
765
+ }
766
+ if (!state$1.textBlockStarted) {
767
+ emit({
768
+ type: "text_start",
769
+ index: state$1.contentBlockIndex
770
+ });
771
+ state$1.textBlockStarted = true;
772
+ }
773
+ emit({
774
+ type: "text_delta",
775
+ index: state$1.contentBlockIndex,
776
+ text
777
+ });
778
+ }
779
+ /**
780
+ * Process tool/function call
781
+ */
782
+ function processToolPart(functionCall, state$1, emit) {
783
+ if (state$1.textBlockStarted) {
784
+ emit({
785
+ type: "text_stop",
786
+ index: state$1.contentBlockIndex
787
+ });
788
+ state$1.contentBlockIndex++;
789
+ state$1.textBlockStarted = false;
790
+ } else if (state$1.thinkingBlockStarted) {
791
+ emit({
792
+ type: "thinking_stop",
793
+ index: state$1.contentBlockIndex
794
+ });
795
+ state$1.contentBlockIndex++;
796
+ state$1.thinkingBlockStarted = false;
797
+ }
798
+ emit({
799
+ type: "tool_use",
800
+ index: state$1.contentBlockIndex,
801
+ name: functionCall.name,
802
+ args: functionCall.args
803
+ });
804
+ state$1.contentBlockIndex++;
805
+ }
806
+ /**
807
+ * Handle finish reason and close open blocks
808
+ */
809
+ function handleFinish(state$1, emit) {
810
+ if (state$1.textBlockStarted) {
811
+ emit({
812
+ type: "text_stop",
813
+ index: state$1.contentBlockIndex
814
+ });
815
+ state$1.textBlockStarted = false;
816
+ } else if (state$1.thinkingBlockStarted) {
817
+ emit({
818
+ type: "thinking_stop",
819
+ index: state$1.contentBlockIndex
820
+ });
821
+ state$1.thinkingBlockStarted = false;
822
+ }
823
+ emit({
824
+ type: "usage",
825
+ inputTokens: state$1.inputTokens,
826
+ outputTokens: state$1.outputTokens
827
+ });
828
+ emit({
829
+ type: "finish",
830
+ stopReason: "end_turn"
831
+ });
832
+ }
833
+ /**
834
+ * Process chunk and update buffer, returning complete lines
835
+ */
836
+ function processChunk(chunk, state$1) {
837
+ state$1.buffer += chunk;
838
+ const lines = state$1.buffer.split("\n");
839
+ state$1.buffer = lines.pop() || "";
840
+ return lines;
841
+ }
842
+
684
843
  //#endregion
685
844
  //#region src/services/antigravity/create-chat-completions.ts
686
845
  const ANTIGRAVITY_API_HOST$1 = "daily-cloudcode-pa.sandbox.googleapis.com";
@@ -692,38 +851,18 @@ const ANTIGRAVITY_USER_AGENT$1 = "antigravity/1.11.3 windows/amd64";
692
851
  */
693
852
  function convertMessages$1(messages) {
694
853
  const contents = [];
695
- let systemInstruction = void 0;
854
+ let systemInstruction;
696
855
  for (const message of messages) {
697
856
  if (message.role === "system") {
698
- systemInstruction = {
699
- role: "user",
700
- parts: [{ text: typeof message.content === "string" ? message.content : message.content.map((c) => c.text || "").join("") }]
701
- };
857
+ systemInstruction = buildSystemInstruction(message.content);
702
858
  continue;
703
859
  }
704
860
  const role = message.role === "assistant" ? "model" : "user";
705
- if (typeof message.content === "string") contents.push({
861
+ const parts = buildMessageParts(message.content);
862
+ contents.push({
706
863
  role,
707
- parts: [{ text: message.content }]
864
+ parts
708
865
  });
709
- else {
710
- const parts = [];
711
- for (const part of message.content) if (part.type === "text") parts.push({ text: part.text });
712
- else if (part.type === "image_url" && part.image_url?.url) {
713
- const url = part.image_url.url;
714
- if (url.startsWith("data:")) {
715
- const match = url.match(/^data:([^;]+);base64,(.+)$/);
716
- if (match) parts.push({ inlineData: {
717
- mimeType: match[1],
718
- data: match[2]
719
- } });
720
- }
721
- }
722
- contents.push({
723
- role,
724
- parts
725
- });
726
- }
727
866
  }
728
867
  return {
729
868
  contents,
@@ -731,10 +870,44 @@ function convertMessages$1(messages) {
731
870
  };
732
871
  }
733
872
  /**
873
+ * Build system instruction from content
874
+ */
875
+ function buildSystemInstruction(content) {
876
+ return {
877
+ role: "user",
878
+ parts: [{ text: typeof content === "string" ? content : content.map((c) => c.text || "").join("") }]
879
+ };
880
+ }
881
+ /**
882
+ * Build message parts from content
883
+ */
884
+ function buildMessageParts(content) {
885
+ if (typeof content === "string") return [{ text: content }];
886
+ const parts = [];
887
+ for (const part of content) if (part.type === "text") parts.push({ text: part.text });
888
+ else if (part.type === "image_url" && part.image_url?.url) {
889
+ const imageData = parseBase64Image(part.image_url.url);
890
+ if (imageData) parts.push({ inlineData: imageData });
891
+ }
892
+ return parts;
893
+ }
894
+ /**
895
+ * Parse base64 image URL
896
+ */
897
+ function parseBase64Image(url) {
898
+ if (!url.startsWith("data:")) return null;
899
+ const match = url.match(/^data:([^;]+);base64,(.+)$/);
900
+ if (!match) return null;
901
+ return {
902
+ mimeType: match[1],
903
+ data: match[2]
904
+ };
905
+ }
906
+ /**
734
907
  * Convert tools to Antigravity format
735
908
  */
736
909
  function convertTools$1(tools) {
737
- if (!tools || tools.length === 0) return;
910
+ if (!tools || tools.length === 0) return void 0;
738
911
  return tools.map((tool) => {
739
912
  const t = tool;
740
913
  if (t.type === "function" && t.function) return { functionDeclarations: [{
@@ -746,20 +919,12 @@ function convertTools$1(tools) {
746
919
  });
747
920
  }
748
921
  /**
749
- * Create chat completion with Antigravity
922
+ * Build Antigravity request body
750
923
  */
751
- async function createAntigravityChatCompletion(request) {
752
- const accessToken = await getValidAccessToken();
753
- if (!accessToken) return new Response(JSON.stringify({ error: {
754
- message: "No valid Antigravity access token available. Please run login first.",
755
- type: "auth_error"
756
- } }), {
757
- status: 401,
758
- headers: { "Content-Type": "application/json" }
759
- });
924
+ function buildRequestBody(request) {
760
925
  const { contents, systemInstruction } = convertMessages$1(request.messages);
761
926
  const tools = convertTools$1(request.tools);
762
- const antigravityRequest = {
927
+ const body = {
763
928
  model: request.model,
764
929
  contents,
765
930
  generationConfig: {
@@ -769,13 +934,36 @@ async function createAntigravityChatCompletion(request) {
769
934
  maxOutputTokens: request.max_tokens ?? 8096
770
935
  }
771
936
  };
772
- if (systemInstruction) antigravityRequest.systemInstruction = systemInstruction;
773
- if (tools) antigravityRequest.tools = tools;
774
- if (isThinkingModel(request.model)) antigravityRequest.generationConfig = {
775
- ...antigravityRequest.generationConfig,
937
+ if (systemInstruction) body.systemInstruction = systemInstruction;
938
+ if (tools) body.tools = tools;
939
+ if (isThinkingModel(request.model)) body.generationConfig = {
940
+ ...body.generationConfig,
776
941
  thinkingConfig: { includeThoughts: true }
777
942
  };
943
+ return body;
944
+ }
945
+ /**
946
+ * Create error response
947
+ */
948
+ function createErrorResponse$1(message, type, status, details) {
949
+ const error = {
950
+ message,
951
+ type
952
+ };
953
+ if (details) error.details = details;
954
+ return new Response(JSON.stringify({ error }), {
955
+ status,
956
+ headers: { "Content-Type": "application/json" }
957
+ });
958
+ }
959
+ /**
960
+ * Create chat completion with Antigravity
961
+ */
962
+ async function createAntigravityChatCompletion(request) {
963
+ const accessToken = await getValidAccessToken();
964
+ if (!accessToken) return createErrorResponse$1("No valid Antigravity access token available. Please run login first.", "auth_error", 401);
778
965
  const endpoint = request.stream ? ANTIGRAVITY_STREAM_URL$1 : ANTIGRAVITY_NO_STREAM_URL$1;
966
+ const body = buildRequestBody(request);
779
967
  consola.debug(`Antigravity request to ${endpoint} with model ${request.model}`);
780
968
  try {
781
969
  const response = await fetch(endpoint, {
@@ -787,120 +975,46 @@ async function createAntigravityChatCompletion(request) {
787
975
  "Content-Type": "application/json",
788
976
  "Accept-Encoding": "gzip"
789
977
  },
790
- body: JSON.stringify(antigravityRequest)
978
+ body: JSON.stringify(body)
791
979
  });
792
- if (!response.ok) {
793
- const errorText = await response.text();
794
- consola.error(`Antigravity error: ${response.status} ${errorText}`);
795
- if (response.status === 403) await disableCurrentAccount();
796
- if (response.status === 429 || response.status === 503) await rotateAccount();
797
- return new Response(JSON.stringify({ error: {
798
- message: `Antigravity API error: ${response.status}`,
799
- type: "api_error",
800
- details: errorText
801
- } }), {
802
- status: response.status,
803
- headers: { "Content-Type": "application/json" }
804
- });
805
- }
806
- if (request.stream) return transformStreamResponse(response, request.model);
807
- else return transformNonStreamResponse(response, request.model);
980
+ if (!response.ok) return await handleApiError$1(response);
981
+ return request.stream ? transformStreamResponse$1(response, request.model) : await transformNonStreamResponse$1(response, request.model);
808
982
  } catch (error) {
809
983
  consola.error("Antigravity request error:", error);
810
- return new Response(JSON.stringify({ error: {
811
- message: `Request failed: ${error}`,
812
- type: "request_error"
813
- } }), {
814
- status: 500,
815
- headers: { "Content-Type": "application/json" }
816
- });
984
+ return createErrorResponse$1(`Request failed: ${String(error)}`, "request_error", 500);
817
985
  }
818
986
  }
819
987
  /**
988
+ * Handle API error response
989
+ */
990
+ async function handleApiError$1(response) {
991
+ const errorText = await response.text();
992
+ consola.error(`Antigravity error: ${response.status} ${errorText}`);
993
+ if (response.status === 403) await disableCurrentAccount();
994
+ if (response.status === 429 || response.status === 503) await rotateAccount();
995
+ return createErrorResponse$1(`Antigravity API error: ${response.status}`, "api_error", response.status, errorText);
996
+ }
997
+ /**
998
+ * Generate request ID
999
+ */
1000
+ function generateRequestId() {
1001
+ return `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
1002
+ }
1003
+ /**
820
1004
  * Transform Antigravity stream response to OpenAI format
821
1005
  */
822
- function transformStreamResponse(response, model) {
1006
+ function transformStreamResponse$1(response, model) {
823
1007
  const reader = response.body?.getReader();
824
1008
  if (!reader) return new Response("No response body", { status: 500 });
825
- const encoder = new TextEncoder();
1009
+ const encoder$1 = new TextEncoder();
826
1010
  const decoder = new TextDecoder();
1011
+ const requestId = generateRequestId();
827
1012
  const stream = new ReadableStream({ async start(controller) {
828
- let buffer = "";
829
- const requestId = `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
1013
+ const state$1 = createStreamState();
830
1014
  try {
831
- while (true) {
832
- const { done, value } = await reader.read();
833
- if (done) {
834
- controller.enqueue(encoder.encode("data: [DONE]\n\n"));
835
- controller.close();
836
- break;
837
- }
838
- buffer += decoder.decode(value, { stream: true });
839
- const lines = buffer.split("\n");
840
- buffer = lines.pop() || "";
841
- for (const line of lines) if (line.startsWith("data: ")) {
842
- const data = line.slice(6).trim();
843
- if (data === "[DONE]" || data === "") continue;
844
- try {
845
- const parsed = JSON.parse(data);
846
- const candidate = (parsed.response?.candidates || parsed.candidates)?.[0];
847
- const parts = candidate?.content?.parts || [];
848
- for (const part of parts) {
849
- if (part.thought && part.text) {
850
- const chunk = {
851
- id: requestId,
852
- object: "chat.completion.chunk",
853
- created: Math.floor(Date.now() / 1e3),
854
- model,
855
- choices: [{
856
- index: 0,
857
- delta: { reasoning_content: part.text },
858
- finish_reason: null
859
- }]
860
- };
861
- controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
862
- continue;
863
- }
864
- if (part.text) {
865
- const chunk = {
866
- id: requestId,
867
- object: "chat.completion.chunk",
868
- created: Math.floor(Date.now() / 1e3),
869
- model,
870
- choices: [{
871
- index: 0,
872
- delta: { content: part.text },
873
- finish_reason: candidate?.finishReason === "STOP" ? "stop" : null
874
- }]
875
- };
876
- controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
877
- }
878
- if (part.functionCall) {
879
- const chunk = {
880
- id: requestId,
881
- object: "chat.completion.chunk",
882
- created: Math.floor(Date.now() / 1e3),
883
- model,
884
- choices: [{
885
- index: 0,
886
- delta: { tool_calls: [{
887
- index: 0,
888
- id: `call_${Date.now()}`,
889
- type: "function",
890
- function: {
891
- name: part.functionCall.name,
892
- arguments: JSON.stringify(part.functionCall.args)
893
- }
894
- }] },
895
- finish_reason: null
896
- }]
897
- };
898
- controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
899
- }
900
- }
901
- } catch {}
902
- }
903
- }
1015
+ await processOpenAIStream(reader, decoder, state$1, controller, encoder$1, requestId, model);
1016
+ controller.enqueue(encoder$1.encode("data: [DONE]\n\n"));
1017
+ controller.close();
904
1018
  } catch (error) {
905
1019
  consola.error("Stream transform error:", error);
906
1020
  controller.error(error);
@@ -913,27 +1027,78 @@ function transformStreamResponse(response, model) {
913
1027
  } });
914
1028
  }
915
1029
  /**
916
- * Transform Antigravity non-stream response to OpenAI format
1030
+ * Process stream and emit OpenAI format chunks
917
1031
  */
918
- async function transformNonStreamResponse(response, model) {
919
- const data = await response.json();
920
- const candidate = data.candidates?.[0];
921
- const parts = candidate?.content?.parts || [];
922
- let content = "";
923
- let reasoningContent = "";
924
- const toolCalls = [];
925
- for (const part of parts) {
926
- if (part.thought && part.text) reasoningContent += part.text;
927
- else if (part.text) content += part.text;
928
- if (part.functionCall) toolCalls.push({
929
- id: `call_${Date.now()}`,
930
- type: "function",
931
- function: {
932
- name: part.functionCall.name,
933
- arguments: JSON.stringify(part.functionCall.args)
1032
+ async function processOpenAIStream(reader, decoder, state$1, controller, encoder$1, requestId, model) {
1033
+ while (true) {
1034
+ const { done, value } = await reader.read();
1035
+ if (done) break;
1036
+ const chunk = decoder.decode(value, { stream: true });
1037
+ const lines = processChunk(chunk, state$1);
1038
+ for (const line of lines) {
1039
+ const data = parseSSELine(line);
1040
+ if (!data) continue;
1041
+ const { candidates } = extractFromData(data);
1042
+ const candidate = candidates[0];
1043
+ const parts = candidate?.content?.parts ?? [];
1044
+ for (const part of parts) {
1045
+ const chunkData = buildOpenAIChunk(part, requestId, model, candidate?.finishReason);
1046
+ if (chunkData) controller.enqueue(encoder$1.encode(`data: ${JSON.stringify(chunkData)}\n\n`));
934
1047
  }
935
- });
1048
+ }
936
1049
  }
1050
+ }
1051
+ /**
1052
+ * Build OpenAI format chunk from part
1053
+ */
1054
+ function buildOpenAIChunk(part, requestId, model, finishReason) {
1055
+ const baseChunk = {
1056
+ id: requestId,
1057
+ object: "chat.completion.chunk",
1058
+ created: Math.floor(Date.now() / 1e3),
1059
+ model
1060
+ };
1061
+ if (part.thought && part.text) return {
1062
+ ...baseChunk,
1063
+ choices: [{
1064
+ index: 0,
1065
+ delta: { reasoning_content: part.text },
1066
+ finish_reason: null
1067
+ }]
1068
+ };
1069
+ if (part.text && !part.thought) return {
1070
+ ...baseChunk,
1071
+ choices: [{
1072
+ index: 0,
1073
+ delta: { content: part.text },
1074
+ finish_reason: finishReason === "STOP" ? "stop" : null
1075
+ }]
1076
+ };
1077
+ if (part.functionCall) return {
1078
+ ...baseChunk,
1079
+ choices: [{
1080
+ index: 0,
1081
+ delta: { tool_calls: [{
1082
+ index: 0,
1083
+ id: `call_${Date.now()}`,
1084
+ type: "function",
1085
+ function: {
1086
+ name: part.functionCall.name,
1087
+ arguments: JSON.stringify(part.functionCall.args)
1088
+ }
1089
+ }] },
1090
+ finish_reason: null
1091
+ }]
1092
+ };
1093
+ return null;
1094
+ }
1095
+ /**
1096
+ * Transform Antigravity non-stream response to OpenAI format
1097
+ */
1098
+ async function transformNonStreamResponse$1(response, model) {
1099
+ const data = await response.json();
1100
+ const parts = (data.candidates?.[0])?.content?.parts ?? [];
1101
+ const { content, reasoningContent, toolCalls } = extractNonStreamContent(parts);
937
1102
  const message = {
938
1103
  role: "assistant",
939
1104
  content: content || null
@@ -941,23 +1106,48 @@ async function transformNonStreamResponse(response, model) {
941
1106
  if (reasoningContent) message.reasoning_content = reasoningContent;
942
1107
  if (toolCalls.length > 0) message.tool_calls = toolCalls;
943
1108
  const openaiResponse = {
944
- id: `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
1109
+ id: generateRequestId(),
945
1110
  object: "chat.completion",
946
1111
  created: Math.floor(Date.now() / 1e3),
947
1112
  model,
948
1113
  choices: [{
949
1114
  index: 0,
950
1115
  message,
951
- finish_reason: candidate?.finishReason === "STOP" ? "stop" : "stop"
1116
+ finish_reason: "stop"
952
1117
  }],
953
1118
  usage: {
954
- prompt_tokens: data.usageMetadata?.promptTokenCount || 0,
955
- completion_tokens: data.usageMetadata?.candidatesTokenCount || 0,
956
- total_tokens: data.usageMetadata?.totalTokenCount || 0
1119
+ prompt_tokens: data.usageMetadata?.promptTokenCount ?? 0,
1120
+ completion_tokens: data.usageMetadata?.candidatesTokenCount ?? 0,
1121
+ total_tokens: data.usageMetadata?.totalTokenCount ?? 0
957
1122
  }
958
1123
  };
959
1124
  return new Response(JSON.stringify(openaiResponse), { headers: { "Content-Type": "application/json" } });
960
1125
  }
1126
+ /**
1127
+ * Extract content from non-stream response parts
1128
+ */
1129
+ function extractNonStreamContent(parts) {
1130
+ let content = "";
1131
+ let reasoningContent = "";
1132
+ const toolCalls = [];
1133
+ for (const part of parts) {
1134
+ if (part.thought && part.text) reasoningContent += part.text;
1135
+ else if (part.text) content += part.text;
1136
+ if (part.functionCall) toolCalls.push({
1137
+ id: `call_${Date.now()}`,
1138
+ type: "function",
1139
+ function: {
1140
+ name: part.functionCall.name,
1141
+ arguments: JSON.stringify(part.functionCall.args)
1142
+ }
1143
+ });
1144
+ }
1145
+ return {
1146
+ content,
1147
+ reasoningContent,
1148
+ toolCalls
1149
+ };
1150
+ }
961
1151
 
962
1152
  //#endregion
963
1153
  //#region src/routes/antigravity/chat-completions/route.ts
@@ -977,6 +1167,166 @@ app$1.post("/", async (c) => {
977
1167
  });
978
1168
  const antigravityChatCompletionsRoute = app$1;
979
1169
 
1170
+ //#endregion
1171
+ //#region src/services/antigravity/anthropic-events.ts
1172
+ /**
1173
+ * Anthropic SSE Event Builder
1174
+ *
1175
+ * Builds Anthropic-compatible SSE events for streaming responses.
1176
+ * Extracted for better code organization and reusability.
1177
+ */
1178
+ const encoder = new TextEncoder();
1179
+ /**
1180
+ * Create message_start event
1181
+ */
1182
+ function createMessageStart(messageId, model) {
1183
+ const event = {
1184
+ type: "message_start",
1185
+ message: {
1186
+ id: messageId,
1187
+ type: "message",
1188
+ role: "assistant",
1189
+ content: [],
1190
+ model,
1191
+ stop_reason: null,
1192
+ stop_sequence: null,
1193
+ usage: {
1194
+ input_tokens: 0,
1195
+ output_tokens: 0
1196
+ }
1197
+ }
1198
+ };
1199
+ return encoder.encode(`event: message_start\ndata: ${JSON.stringify(event)}\n\n`);
1200
+ }
1201
+ /**
1202
+ * Create message_stop event
1203
+ */
1204
+ function createMessageStop() {
1205
+ return encoder.encode(`event: message_stop\ndata: ${JSON.stringify({ type: "message_stop" })}\n\n`);
1206
+ }
1207
+ /**
1208
+ * Create content_block_start event for thinking
1209
+ */
1210
+ function createThinkingBlockStart(index) {
1211
+ const event = {
1212
+ type: "content_block_start",
1213
+ index,
1214
+ content_block: {
1215
+ type: "thinking",
1216
+ thinking: ""
1217
+ }
1218
+ };
1219
+ return encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(event)}\n\n`);
1220
+ }
1221
+ /**
1222
+ * Create content_block_delta event for thinking
1223
+ */
1224
+ function createThinkingDelta(index, text) {
1225
+ const event = {
1226
+ type: "content_block_delta",
1227
+ index,
1228
+ delta: {
1229
+ type: "thinking_delta",
1230
+ thinking: text
1231
+ }
1232
+ };
1233
+ return encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(event)}\n\n`);
1234
+ }
1235
+ /**
1236
+ * Create content_block_start event for text
1237
+ */
1238
+ function createTextBlockStart(index) {
1239
+ const event = {
1240
+ type: "content_block_start",
1241
+ index,
1242
+ content_block: {
1243
+ type: "text",
1244
+ text: ""
1245
+ }
1246
+ };
1247
+ return encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(event)}\n\n`);
1248
+ }
1249
+ /**
1250
+ * Create content_block_delta event for text
1251
+ */
1252
+ function createTextDelta(index, text) {
1253
+ const event = {
1254
+ type: "content_block_delta",
1255
+ index,
1256
+ delta: {
1257
+ type: "text_delta",
1258
+ text
1259
+ }
1260
+ };
1261
+ return encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(event)}\n\n`);
1262
+ }
1263
+ /**
1264
+ * Create content_block_stop event
1265
+ */
1266
+ function createBlockStop(index) {
1267
+ const event = {
1268
+ type: "content_block_stop",
1269
+ index
1270
+ };
1271
+ return encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(event)}\n\n`);
1272
+ }
1273
+ /**
1274
+ * Create content_block_start event for tool_use
1275
+ */
1276
+ function createToolBlockStart(index, toolId, name) {
1277
+ const event = {
1278
+ type: "content_block_start",
1279
+ index,
1280
+ content_block: {
1281
+ type: "tool_use",
1282
+ id: toolId,
1283
+ name,
1284
+ input: {}
1285
+ }
1286
+ };
1287
+ return encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(event)}\n\n`);
1288
+ }
1289
+ /**
1290
+ * Create content_block_delta event for tool input
1291
+ */
1292
+ function createToolDelta(index, args) {
1293
+ const event = {
1294
+ type: "content_block_delta",
1295
+ index,
1296
+ delta: {
1297
+ type: "input_json_delta",
1298
+ partial_json: JSON.stringify(args)
1299
+ }
1300
+ };
1301
+ return encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(event)}\n\n`);
1302
+ }
1303
+ /**
1304
+ * Create message_delta event with stop reason and usage
1305
+ */
1306
+ function createMessageDelta(stopReason, outputTokens) {
1307
+ const event = {
1308
+ type: "message_delta",
1309
+ delta: {
1310
+ stop_reason: stopReason,
1311
+ stop_sequence: null
1312
+ },
1313
+ usage: { output_tokens: outputTokens }
1314
+ };
1315
+ return encoder.encode(`event: message_delta\ndata: ${JSON.stringify(event)}\n\n`);
1316
+ }
1317
+ /**
1318
+ * Generate a unique message ID
1319
+ */
1320
+ function generateMessageId() {
1321
+ return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1322
+ }
1323
+ /**
1324
+ * Generate a unique tool ID
1325
+ */
1326
+ function generateToolId() {
1327
+ return `toolu_${Date.now()}`;
1328
+ }
1329
+
980
1330
  //#endregion
981
1331
  //#region src/services/antigravity/create-messages.ts
982
1332
  const ANTIGRAVITY_API_HOST = "daily-cloudcode-pa.sandbox.googleapis.com";
@@ -988,29 +1338,18 @@ const ANTIGRAVITY_USER_AGENT = "antigravity/1.11.3 windows/amd64";
988
1338
  */
989
1339
  function convertMessages(messages, system) {
990
1340
  const contents = [];
991
- let systemInstruction = void 0;
1341
+ let systemInstruction;
992
1342
  if (system) systemInstruction = {
993
1343
  role: "user",
994
1344
  parts: [{ text: system }]
995
1345
  };
996
1346
  for (const message of messages) {
997
1347
  const role = message.role === "assistant" ? "model" : "user";
998
- if (typeof message.content === "string") contents.push({
1348
+ const parts = buildParts(message.content);
1349
+ if (parts.length > 0) contents.push({
999
1350
  role,
1000
- parts: [{ text: message.content }]
1351
+ parts
1001
1352
  });
1002
- else {
1003
- const parts = [];
1004
- for (const block of message.content) if (block.type === "text" && block.text) parts.push({ text: block.text });
1005
- else if (block.type === "image" && block.source) parts.push({ inlineData: {
1006
- mimeType: block.source.media_type,
1007
- data: block.source.data
1008
- } });
1009
- if (parts.length > 0) contents.push({
1010
- role,
1011
- parts
1012
- });
1013
- }
1014
1353
  }
1015
1354
  return {
1016
1355
  contents,
@@ -1018,10 +1357,23 @@ function convertMessages(messages, system) {
1018
1357
  };
1019
1358
  }
1020
1359
  /**
1360
+ * Build parts array from message content
1361
+ */
1362
+ function buildParts(content) {
1363
+ if (typeof content === "string") return [{ text: content }];
1364
+ const parts = [];
1365
+ for (const block of content) if (block.type === "text" && block.text) parts.push({ text: block.text });
1366
+ else if (block.type === "image" && block.source) parts.push({ inlineData: {
1367
+ mimeType: block.source.media_type,
1368
+ data: block.source.data
1369
+ } });
1370
+ return parts;
1371
+ }
1372
+ /**
1021
1373
  * Convert tools to Antigravity format
1022
1374
  */
1023
1375
  function convertTools(tools) {
1024
- if (!tools || tools.length === 0) return;
1376
+ if (!tools || tools.length === 0) return void 0;
1025
1377
  return tools.map((tool) => {
1026
1378
  const t = tool;
1027
1379
  return { functionDeclarations: [{
@@ -1032,23 +1384,12 @@ function convertTools(tools) {
1032
1384
  });
1033
1385
  }
1034
1386
  /**
1035
- * Create Anthropic-compatible message response using Antigravity
1387
+ * Build Antigravity request body
1036
1388
  */
1037
- async function createAntigravityMessages(request) {
1038
- const accessToken = await getValidAccessToken();
1039
- if (!accessToken) return new Response(JSON.stringify({
1040
- type: "error",
1041
- error: {
1042
- type: "authentication_error",
1043
- message: "No valid Antigravity access token available. Please run login first."
1044
- }
1045
- }), {
1046
- status: 401,
1047
- headers: { "Content-Type": "application/json" }
1048
- });
1389
+ function buildAntigravityRequest(request) {
1049
1390
  const { contents, systemInstruction } = convertMessages(request.messages, request.system);
1050
1391
  const tools = convertTools(request.tools);
1051
- const antigravityRequest = {
1392
+ const body = {
1052
1393
  model: request.model,
1053
1394
  contents,
1054
1395
  generationConfig: {
@@ -1058,13 +1399,37 @@ async function createAntigravityMessages(request) {
1058
1399
  maxOutputTokens: request.max_tokens ?? 8096
1059
1400
  }
1060
1401
  };
1061
- if (systemInstruction) antigravityRequest.systemInstruction = systemInstruction;
1062
- if (tools) antigravityRequest.tools = tools;
1063
- if (isThinkingModel(request.model)) antigravityRequest.generationConfig = {
1064
- ...antigravityRequest.generationConfig,
1402
+ if (systemInstruction) body.systemInstruction = systemInstruction;
1403
+ if (tools) body.tools = tools;
1404
+ if (isThinkingModel(request.model)) body.generationConfig = {
1405
+ ...body.generationConfig,
1065
1406
  thinkingConfig: { includeThoughts: true }
1066
1407
  };
1408
+ return body;
1409
+ }
1410
+ /**
1411
+ * Create error response
1412
+ */
1413
+ function createErrorResponse(type, message, status) {
1414
+ return new Response(JSON.stringify({
1415
+ type: "error",
1416
+ error: {
1417
+ type,
1418
+ message
1419
+ }
1420
+ }), {
1421
+ status,
1422
+ headers: { "Content-Type": "application/json" }
1423
+ });
1424
+ }
1425
+ /**
1426
+ * Create Anthropic-compatible message response using Antigravity
1427
+ */
1428
+ async function createAntigravityMessages(request) {
1429
+ const accessToken = await getValidAccessToken();
1430
+ if (!accessToken) return createErrorResponse("authentication_error", "No valid Antigravity access token available. Please run login first.", 401);
1067
1431
  const endpoint = request.stream ? ANTIGRAVITY_STREAM_URL : ANTIGRAVITY_NO_STREAM_URL;
1432
+ const body = buildAntigravityRequest(request);
1068
1433
  consola.debug(`Antigravity messages request to ${endpoint} with model ${request.model}`);
1069
1434
  try {
1070
1435
  const response = await fetch(endpoint, {
@@ -1076,212 +1441,84 @@ async function createAntigravityMessages(request) {
1076
1441
  "Content-Type": "application/json",
1077
1442
  "Accept-Encoding": "gzip"
1078
1443
  },
1079
- body: JSON.stringify(antigravityRequest)
1444
+ body: JSON.stringify(body)
1080
1445
  });
1081
- if (!response.ok) {
1082
- const errorText = await response.text();
1083
- consola.error(`Antigravity error: ${response.status} ${errorText}`);
1084
- if (response.status === 403) await disableCurrentAccount();
1085
- if (response.status === 429 || response.status === 503) await rotateAccount();
1086
- return new Response(JSON.stringify({
1087
- type: "error",
1088
- error: {
1089
- type: "api_error",
1090
- message: `Antigravity API error: ${response.status}`
1091
- }
1092
- }), {
1093
- status: response.status,
1094
- headers: { "Content-Type": "application/json" }
1095
- });
1096
- }
1097
- if (request.stream) return transformStreamToAnthropic(response, request.model);
1098
- else return transformNonStreamToAnthropic(response, request.model);
1446
+ if (!response.ok) return await handleApiError(response);
1447
+ return request.stream ? transformStreamResponse(response, request.model) : await transformNonStreamResponse(response, request.model);
1099
1448
  } catch (error) {
1100
1449
  consola.error("Antigravity messages request error:", error);
1101
- return new Response(JSON.stringify({
1102
- type: "error",
1103
- error: {
1104
- type: "api_error",
1105
- message: `Request failed: ${error}`
1106
- }
1107
- }), {
1108
- status: 500,
1109
- headers: { "Content-Type": "application/json" }
1110
- });
1450
+ return createErrorResponse("api_error", `Request failed: ${String(error)}`, 500);
1451
+ }
1452
+ }
1453
+ /**
1454
+ * Handle API error response
1455
+ */
1456
+ async function handleApiError(response) {
1457
+ const errorText = await response.text();
1458
+ consola.error(`Antigravity error: ${response.status} ${errorText}`);
1459
+ if (response.status === 403) await disableCurrentAccount();
1460
+ if (response.status === 429 || response.status === 503) await rotateAccount();
1461
+ return createErrorResponse("api_error", `Antigravity API error: ${response.status}`, response.status);
1462
+ }
1463
+ /**
1464
+ * Emit SSE event to controller based on stream event type
1465
+ */
1466
+ function emitSSEEvent(event, controller, state$1) {
1467
+ switch (event.type) {
1468
+ case "thinking_start":
1469
+ controller.enqueue(createThinkingBlockStart(event.index));
1470
+ break;
1471
+ case "thinking_delta":
1472
+ controller.enqueue(createThinkingDelta(event.index, event.text));
1473
+ break;
1474
+ case "thinking_stop":
1475
+ controller.enqueue(createBlockStop(event.index));
1476
+ break;
1477
+ case "text_start":
1478
+ controller.enqueue(createTextBlockStart(event.index));
1479
+ break;
1480
+ case "text_delta":
1481
+ controller.enqueue(createTextDelta(event.index, event.text));
1482
+ break;
1483
+ case "text_stop":
1484
+ controller.enqueue(createBlockStop(event.index));
1485
+ break;
1486
+ case "tool_use":
1487
+ emitToolUseEvents(event, controller);
1488
+ break;
1489
+ case "usage":
1490
+ state$1.inputTokens = event.inputTokens;
1491
+ state$1.outputTokens = event.outputTokens;
1492
+ break;
1493
+ case "finish":
1494
+ controller.enqueue(createMessageDelta(event.stopReason, state$1.outputTokens));
1495
+ break;
1111
1496
  }
1112
1497
  }
1113
1498
  /**
1499
+ * Emit tool use events
1500
+ */
1501
+ function emitToolUseEvents(event, controller) {
1502
+ const toolId = generateToolId();
1503
+ controller.enqueue(createToolBlockStart(event.index, toolId, event.name));
1504
+ controller.enqueue(createToolDelta(event.index, event.args));
1505
+ controller.enqueue(createBlockStop(event.index));
1506
+ }
1507
+ /**
1114
1508
  * Transform Antigravity stream response to Anthropic format
1115
1509
  */
1116
- function transformStreamToAnthropic(response, model) {
1510
+ function transformStreamResponse(response, model) {
1117
1511
  const reader = response.body?.getReader();
1118
1512
  if (!reader) return new Response("No response body", { status: 500 });
1119
- const encoder = new TextEncoder();
1120
1513
  const decoder = new TextDecoder();
1514
+ const messageId = generateMessageId();
1121
1515
  const stream = new ReadableStream({ async start(controller) {
1122
- let buffer = "";
1123
- const messageId = `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1124
- let inputTokens = 0;
1125
- let outputTokens = 0;
1126
- let contentBlockIndex = 0;
1127
- let thinkingBlockStarted = false;
1128
- let textBlockStarted = false;
1129
- const messageStart = {
1130
- type: "message_start",
1131
- message: {
1132
- id: messageId,
1133
- type: "message",
1134
- role: "assistant",
1135
- content: [],
1136
- model,
1137
- stop_reason: null,
1138
- stop_sequence: null,
1139
- usage: {
1140
- input_tokens: 0,
1141
- output_tokens: 0
1142
- }
1143
- }
1144
- };
1145
- controller.enqueue(encoder.encode(`event: message_start\ndata: ${JSON.stringify(messageStart)}\n\n`));
1516
+ const state$1 = createStreamState();
1517
+ controller.enqueue(createMessageStart(messageId, model));
1146
1518
  try {
1147
- while (true) {
1148
- const { done, value } = await reader.read();
1149
- if (done) {
1150
- controller.enqueue(encoder.encode(`event: message_stop\ndata: ${JSON.stringify({ type: "message_stop" })}\n\n`));
1151
- controller.close();
1152
- break;
1153
- }
1154
- buffer += decoder.decode(value, { stream: true });
1155
- const lines = buffer.split("\n");
1156
- buffer = lines.pop() || "";
1157
- for (const line of lines) if (line.startsWith("data: ")) {
1158
- const data = line.slice(6).trim();
1159
- if (data === "[DONE]" || data === "") continue;
1160
- try {
1161
- const parsed = JSON.parse(data);
1162
- const candidate = (parsed.response?.candidates || parsed.candidates)?.[0];
1163
- const parts = candidate?.content?.parts || [];
1164
- const usage = parsed.response?.usageMetadata || parsed.usageMetadata;
1165
- if (usage) {
1166
- inputTokens = usage.promptTokenCount || inputTokens;
1167
- outputTokens = usage.candidatesTokenCount || outputTokens;
1168
- }
1169
- for (const part of parts) {
1170
- if (part.thought && part.text) {
1171
- if (!thinkingBlockStarted) {
1172
- const blockStart = {
1173
- type: "content_block_start",
1174
- index: contentBlockIndex,
1175
- content_block: {
1176
- type: "thinking",
1177
- thinking: ""
1178
- }
1179
- };
1180
- controller.enqueue(encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(blockStart)}\n\n`));
1181
- thinkingBlockStarted = true;
1182
- }
1183
- const thinkingDelta = {
1184
- type: "content_block_delta",
1185
- index: contentBlockIndex,
1186
- delta: {
1187
- type: "thinking_delta",
1188
- thinking: part.text
1189
- }
1190
- };
1191
- controller.enqueue(encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(thinkingDelta)}\n\n`));
1192
- continue;
1193
- }
1194
- if (part.text && !part.thought) {
1195
- if (thinkingBlockStarted && !textBlockStarted) {
1196
- const blockStop = {
1197
- type: "content_block_stop",
1198
- index: contentBlockIndex
1199
- };
1200
- controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(blockStop)}\n\n`));
1201
- contentBlockIndex++;
1202
- }
1203
- if (!textBlockStarted) {
1204
- const blockStart = {
1205
- type: "content_block_start",
1206
- index: contentBlockIndex,
1207
- content_block: {
1208
- type: "text",
1209
- text: ""
1210
- }
1211
- };
1212
- controller.enqueue(encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(blockStart)}\n\n`));
1213
- textBlockStarted = true;
1214
- }
1215
- const textDelta = {
1216
- type: "content_block_delta",
1217
- index: contentBlockIndex,
1218
- delta: {
1219
- type: "text_delta",
1220
- text: part.text
1221
- }
1222
- };
1223
- controller.enqueue(encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(textDelta)}\n\n`));
1224
- }
1225
- if (part.functionCall) {
1226
- if (textBlockStarted || thinkingBlockStarted) {
1227
- const blockStop = {
1228
- type: "content_block_stop",
1229
- index: contentBlockIndex
1230
- };
1231
- controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(blockStop)}\n\n`));
1232
- contentBlockIndex++;
1233
- textBlockStarted = false;
1234
- thinkingBlockStarted = false;
1235
- }
1236
- const toolBlockStart = {
1237
- type: "content_block_start",
1238
- index: contentBlockIndex,
1239
- content_block: {
1240
- type: "tool_use",
1241
- id: `toolu_${Date.now()}`,
1242
- name: part.functionCall.name,
1243
- input: {}
1244
- }
1245
- };
1246
- controller.enqueue(encoder.encode(`event: content_block_start\ndata: ${JSON.stringify(toolBlockStart)}\n\n`));
1247
- const toolDelta = {
1248
- type: "content_block_delta",
1249
- index: contentBlockIndex,
1250
- delta: {
1251
- type: "input_json_delta",
1252
- partial_json: JSON.stringify(part.functionCall.args)
1253
- }
1254
- };
1255
- controller.enqueue(encoder.encode(`event: content_block_delta\ndata: ${JSON.stringify(toolDelta)}\n\n`));
1256
- const toolBlockStop = {
1257
- type: "content_block_stop",
1258
- index: contentBlockIndex
1259
- };
1260
- controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(toolBlockStop)}\n\n`));
1261
- contentBlockIndex++;
1262
- }
1263
- }
1264
- if (candidate?.finishReason === "STOP") {
1265
- if (textBlockStarted || thinkingBlockStarted) {
1266
- const blockStop = {
1267
- type: "content_block_stop",
1268
- index: contentBlockIndex
1269
- };
1270
- controller.enqueue(encoder.encode(`event: content_block_stop\ndata: ${JSON.stringify(blockStop)}\n\n`));
1271
- }
1272
- const messageDelta = {
1273
- type: "message_delta",
1274
- delta: {
1275
- stop_reason: "end_turn",
1276
- stop_sequence: null
1277
- },
1278
- usage: { output_tokens: outputTokens }
1279
- };
1280
- controller.enqueue(encoder.encode(`event: message_delta\ndata: ${JSON.stringify(messageDelta)}\n\n`));
1281
- }
1282
- } catch {}
1283
- }
1284
- }
1519
+ await processStream(reader, decoder, state$1, controller);
1520
+ controller.enqueue(createMessageStop());
1521
+ controller.close();
1285
1522
  } catch (error) {
1286
1523
  consola.error("Stream transform error:", error);
1287
1524
  controller.error(error);
@@ -1294,12 +1531,56 @@ function transformStreamToAnthropic(response, model) {
1294
1531
  } });
1295
1532
  }
1296
1533
  /**
1534
+ * Process the stream and emit events
1535
+ */
1536
+ async function processStream(reader, decoder, state$1, controller) {
1537
+ const emit = (event) => emitSSEEvent(event, controller, state$1);
1538
+ while (true) {
1539
+ const { done, value } = await reader.read();
1540
+ if (done) break;
1541
+ const chunk = decoder.decode(value, { stream: true });
1542
+ const lines = processChunk(chunk, state$1);
1543
+ for (const line of lines) {
1544
+ const data = parseSSELine(line);
1545
+ if (!data) continue;
1546
+ const { candidates, usage } = extractFromData(data);
1547
+ if (usage) {
1548
+ state$1.inputTokens = usage.promptTokenCount ?? state$1.inputTokens;
1549
+ state$1.outputTokens = usage.candidatesTokenCount ?? state$1.outputTokens;
1550
+ }
1551
+ const candidate = candidates[0];
1552
+ const parts = candidate?.content?.parts ?? [];
1553
+ for (const part of parts) processPart(part, state$1, emit);
1554
+ if (candidate?.finishReason === "STOP") handleFinish(state$1, emit);
1555
+ }
1556
+ }
1557
+ }
1558
+ /**
1297
1559
  * Transform Antigravity non-stream response to Anthropic format
1298
1560
  */
1299
- async function transformNonStreamToAnthropic(response, model) {
1561
+ async function transformNonStreamResponse(response, model) {
1300
1562
  const data = await response.json();
1301
- const candidate = data.candidates?.[0];
1302
- const parts = candidate?.content?.parts || [];
1563
+ const parts = (data.candidates?.[0])?.content?.parts ?? [];
1564
+ const content = buildNonStreamContent(parts);
1565
+ const anthropicResponse = {
1566
+ id: generateMessageId(),
1567
+ type: "message",
1568
+ role: "assistant",
1569
+ content,
1570
+ model,
1571
+ stop_reason: "end_turn",
1572
+ stop_sequence: null,
1573
+ usage: {
1574
+ input_tokens: data.usageMetadata?.promptTokenCount ?? 0,
1575
+ output_tokens: data.usageMetadata?.candidatesTokenCount ?? 0
1576
+ }
1577
+ };
1578
+ return new Response(JSON.stringify(anthropicResponse), { headers: { "Content-Type": "application/json" } });
1579
+ }
1580
+ /**
1581
+ * Build content array for non-stream response
1582
+ */
1583
+ function buildNonStreamContent(parts) {
1303
1584
  const content = [];
1304
1585
  for (const part of parts) {
1305
1586
  if (part.thought && part.text) content.push({
@@ -1312,25 +1593,12 @@ async function transformNonStreamToAnthropic(response, model) {
1312
1593
  });
1313
1594
  if (part.functionCall) content.push({
1314
1595
  type: "tool_use",
1315
- id: `toolu_${Date.now()}`,
1596
+ id: generateToolId(),
1316
1597
  name: part.functionCall.name,
1317
1598
  input: part.functionCall.args
1318
1599
  });
1319
1600
  }
1320
- const anthropicResponse = {
1321
- id: `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
1322
- type: "message",
1323
- role: "assistant",
1324
- content,
1325
- model,
1326
- stop_reason: candidate?.finishReason === "STOP" ? "end_turn" : "end_turn",
1327
- stop_sequence: null,
1328
- usage: {
1329
- input_tokens: data.usageMetadata?.promptTokenCount || 0,
1330
- output_tokens: data.usageMetadata?.candidatesTokenCount || 0
1331
- }
1332
- };
1333
- return new Response(JSON.stringify(anthropicResponse), { headers: { "Content-Type": "application/json" } });
1601
+ return content;
1334
1602
  }
1335
1603
 
1336
1604
  //#endregion
@@ -1420,11 +1688,11 @@ const encodingCache = /* @__PURE__ */ new Map();
1420
1688
  /**
1421
1689
  * Calculate tokens for tool calls
1422
1690
  */
1423
- const calculateToolCallsTokens = (toolCalls, encoder, constants) => {
1691
+ const calculateToolCallsTokens = (toolCalls, encoder$1, constants) => {
1424
1692
  let tokens = 0;
1425
1693
  for (const toolCall of toolCalls) {
1426
1694
  tokens += constants.funcInit;
1427
- tokens += encoder.encode(JSON.stringify(toolCall)).length;
1695
+ tokens += encoder$1.encode(JSON.stringify(toolCall)).length;
1428
1696
  }
1429
1697
  tokens += constants.funcEnd;
1430
1698
  return tokens;
@@ -1432,34 +1700,34 @@ const calculateToolCallsTokens = (toolCalls, encoder, constants) => {
1432
1700
  /**
1433
1701
  * Calculate tokens for content parts
1434
1702
  */
1435
- const calculateContentPartsTokens = (contentParts, encoder) => {
1703
+ const calculateContentPartsTokens = (contentParts, encoder$1) => {
1436
1704
  let tokens = 0;
1437
- for (const part of contentParts) if (part.type === "image_url") tokens += encoder.encode(part.image_url.url).length + 85;
1438
- else if (part.text) tokens += encoder.encode(part.text).length;
1705
+ for (const part of contentParts) if (part.type === "image_url") tokens += encoder$1.encode(part.image_url.url).length + 85;
1706
+ else if (part.text) tokens += encoder$1.encode(part.text).length;
1439
1707
  return tokens;
1440
1708
  };
1441
1709
  /**
1442
1710
  * Calculate tokens for a single message
1443
1711
  */
1444
- const calculateMessageTokens = (message, encoder, constants) => {
1712
+ const calculateMessageTokens = (message, encoder$1, constants) => {
1445
1713
  const tokensPerMessage = 3;
1446
1714
  const tokensPerName = 1;
1447
1715
  let tokens = tokensPerMessage;
1448
1716
  for (const [key, value] of Object.entries(message)) {
1449
- if (typeof value === "string") tokens += encoder.encode(value).length;
1717
+ if (typeof value === "string") tokens += encoder$1.encode(value).length;
1450
1718
  if (key === "name") tokens += tokensPerName;
1451
- if (key === "tool_calls") tokens += calculateToolCallsTokens(value, encoder, constants);
1452
- if (key === "content" && Array.isArray(value)) tokens += calculateContentPartsTokens(value, encoder);
1719
+ if (key === "tool_calls") tokens += calculateToolCallsTokens(value, encoder$1, constants);
1720
+ if (key === "content" && Array.isArray(value)) tokens += calculateContentPartsTokens(value, encoder$1);
1453
1721
  }
1454
1722
  return tokens;
1455
1723
  };
1456
1724
  /**
1457
1725
  * Calculate tokens using custom algorithm
1458
1726
  */
1459
- const calculateTokens = (messages, encoder, constants) => {
1727
+ const calculateTokens = (messages, encoder$1, constants) => {
1460
1728
  if (messages.length === 0) return 0;
1461
1729
  let numTokens = 0;
1462
- for (const message of messages) numTokens += calculateMessageTokens(message, encoder, constants);
1730
+ for (const message of messages) numTokens += calculateMessageTokens(message, encoder$1, constants);
1463
1731
  numTokens += 3;
1464
1732
  return numTokens;
1465
1733
  };
@@ -1511,7 +1779,7 @@ const getModelConstants = (model) => {
1511
1779
  * Calculate tokens for a single parameter
1512
1780
  */
1513
1781
  const calculateParameterTokens = (key, prop, context) => {
1514
- const { encoder, constants } = context;
1782
+ const { encoder: encoder$1, constants } = context;
1515
1783
  let tokens = constants.propKey;
1516
1784
  if (typeof prop !== "object" || prop === null) return tokens;
1517
1785
  const param = prop;
@@ -1522,12 +1790,12 @@ const calculateParameterTokens = (key, prop, context) => {
1522
1790
  tokens += constants.enumInit;
1523
1791
  for (const item of param.enum) {
1524
1792
  tokens += constants.enumItem;
1525
- tokens += encoder.encode(String(item)).length;
1793
+ tokens += encoder$1.encode(String(item)).length;
1526
1794
  }
1527
1795
  }
1528
1796
  if (paramDesc.endsWith(".")) paramDesc = paramDesc.slice(0, -1);
1529
1797
  const line = `${paramName}:${paramType}:${paramDesc}`;
1530
- tokens += encoder.encode(line).length;
1798
+ tokens += encoder$1.encode(line).length;
1531
1799
  const excludedKeys = new Set([
1532
1800
  "type",
1533
1801
  "description",
@@ -1536,14 +1804,14 @@ const calculateParameterTokens = (key, prop, context) => {
1536
1804
  for (const propertyName of Object.keys(param)) if (!excludedKeys.has(propertyName)) {
1537
1805
  const propertyValue = param[propertyName];
1538
1806
  const propertyText = typeof propertyValue === "string" ? propertyValue : JSON.stringify(propertyValue);
1539
- tokens += encoder.encode(`${propertyName}:${propertyText}`).length;
1807
+ tokens += encoder$1.encode(`${propertyName}:${propertyText}`).length;
1540
1808
  }
1541
1809
  return tokens;
1542
1810
  };
1543
1811
  /**
1544
1812
  * Calculate tokens for function parameters
1545
1813
  */
1546
- const calculateParametersTokens = (parameters, encoder, constants) => {
1814
+ const calculateParametersTokens = (parameters, encoder$1, constants) => {
1547
1815
  if (!parameters || typeof parameters !== "object") return 0;
1548
1816
  const params = parameters;
1549
1817
  let tokens = 0;
@@ -1552,36 +1820,36 @@ const calculateParametersTokens = (parameters, encoder, constants) => {
1552
1820
  if (Object.keys(properties).length > 0) {
1553
1821
  tokens += constants.propInit;
1554
1822
  for (const propKey of Object.keys(properties)) tokens += calculateParameterTokens(propKey, properties[propKey], {
1555
- encoder,
1823
+ encoder: encoder$1,
1556
1824
  constants
1557
1825
  });
1558
1826
  }
1559
1827
  } else {
1560
1828
  const paramText = typeof value === "string" ? value : JSON.stringify(value);
1561
- tokens += encoder.encode(`${key}:${paramText}`).length;
1829
+ tokens += encoder$1.encode(`${key}:${paramText}`).length;
1562
1830
  }
1563
1831
  return tokens;
1564
1832
  };
1565
1833
  /**
1566
1834
  * Calculate tokens for a single tool
1567
1835
  */
1568
- const calculateToolTokens = (tool, encoder, constants) => {
1836
+ const calculateToolTokens = (tool, encoder$1, constants) => {
1569
1837
  let tokens = constants.funcInit;
1570
1838
  const func = tool.function;
1571
1839
  const fName = func.name;
1572
1840
  let fDesc = func.description || "";
1573
1841
  if (fDesc.endsWith(".")) fDesc = fDesc.slice(0, -1);
1574
1842
  const line = fName + ":" + fDesc;
1575
- tokens += encoder.encode(line).length;
1576
- if (typeof func.parameters === "object" && func.parameters !== null) tokens += calculateParametersTokens(func.parameters, encoder, constants);
1843
+ tokens += encoder$1.encode(line).length;
1844
+ if (typeof func.parameters === "object" && func.parameters !== null) tokens += calculateParametersTokens(func.parameters, encoder$1, constants);
1577
1845
  return tokens;
1578
1846
  };
1579
1847
  /**
1580
1848
  * Calculate token count for tools based on model
1581
1849
  */
1582
- const numTokensForTools = (tools, encoder, constants) => {
1850
+ const numTokensForTools = (tools, encoder$1, constants) => {
1583
1851
  let funcTokenCount = 0;
1584
- for (const tool of tools) funcTokenCount += calculateToolTokens(tool, encoder, constants);
1852
+ for (const tool of tools) funcTokenCount += calculateToolTokens(tool, encoder$1, constants);
1585
1853
  funcTokenCount += constants.funcEnd;
1586
1854
  return funcTokenCount;
1587
1855
  };
@@ -1590,14 +1858,14 @@ const numTokensForTools = (tools, encoder, constants) => {
1590
1858
  */
1591
1859
  const getTokenCount = async (payload, model) => {
1592
1860
  const tokenizer = getTokenizerFromModel(model);
1593
- const encoder = await getEncodeChatFunction(tokenizer);
1861
+ const encoder$1 = await getEncodeChatFunction(tokenizer);
1594
1862
  const simplifiedMessages = payload.messages;
1595
1863
  const inputMessages = simplifiedMessages.filter((msg) => msg.role !== "assistant");
1596
1864
  const outputMessages = simplifiedMessages.filter((msg) => msg.role === "assistant");
1597
1865
  const constants = getModelConstants(model);
1598
- let inputTokens = calculateTokens(inputMessages, encoder, constants);
1599
- if (payload.tools && payload.tools.length > 0) inputTokens += numTokensForTools(payload.tools, encoder, constants);
1600
- const outputTokens = calculateTokens(outputMessages, encoder, constants);
1866
+ let inputTokens = calculateTokens(inputMessages, encoder$1, constants);
1867
+ if (payload.tools && payload.tools.length > 0) inputTokens += numTokensForTools(payload.tools, encoder$1, constants);
1868
+ const outputTokens = calculateTokens(outputMessages, encoder$1, constants);
1601
1869
  return {
1602
1870
  input: inputTokens,
1603
1871
  output: outputTokens