@nick3/copilot-api 1.2.4 → 1.3.1

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.
@@ -1,4 +1,4 @@
1
- import { HTTPError, PATHS, accountFromState, accountsManager, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getAliasTargetSet, getConfig, getCopilotUsage, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getReasoningEffortForModel, getRootSessionId, getSmallModel, getUUID, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isNullish, isResponsesApiContextManagementModel, listAccountsFromRegistry, mergeConfigWithDefaults, shouldCompactUseSmallModel, sleep, state } from "./accounts-manager-eec8Wj3_.js";
1
+ import { HTTPError, PATHS, accountFromState, accountsManager, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getAliasTargetSet, getConfig, getCopilotUsage, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getProviderConfig, getReasoningEffortForModel, getRootSessionId, getSmallModel, getUUID, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isNullish, isResponsesApiContextManagementModel, listAccountsFromRegistry, mergeConfigWithDefaults, prepareInteractionHeaders, shouldCompactUseSmallModel, sleep, state } from "./accounts-manager-BeKvbv0T.js";
2
2
  import consola from "consola";
3
3
  import fs, { readFile } from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -2234,11 +2234,7 @@ const createResponses = async (payload, { vision, initiator, upstreamRequestId,
2234
2234
  ...copilotHeaders(ctx, vision, upstreamRequestId),
2235
2235
  "x-initiator": initiator
2236
2236
  };
2237
- if (subagentMarker) {
2238
- headers["x-initiator"] = "agent";
2239
- headers["x-interaction-type"] = "conversation-subagent";
2240
- }
2241
- if (sessionId) headers["x-interaction-id"] = sessionId;
2237
+ prepareInteractionHeaders(sessionId, Boolean(subagentMarker), headers);
2242
2238
  payload.service_tier = null;
2243
2239
  const response = await fetch(`${copilotBaseUrl(ctx)}/responses`, {
2244
2240
  method: "POST",
@@ -2718,8 +2714,7 @@ const createChatCompletions = async (payload, account, options) => {
2718
2714
  ...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),
2719
2715
  "x-initiator": options?.subagentMarker ? "agent" : initiator
2720
2716
  };
2721
- if (options?.subagentMarker) headers["x-interaction-type"] = "conversation-subagent";
2722
- if (options?.sessionId) headers["x-interaction-id"] = options.sessionId;
2717
+ prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
2723
2718
  const upstreamPayload = applyDefaultReasoningEffort(payload);
2724
2719
  const response = await fetch(`${copilotBaseUrl(ctx)}/chat/completions`, {
2725
2720
  method: "POST",
@@ -2736,7 +2731,7 @@ const createChatCompletions = async (payload, account, options) => {
2736
2731
 
2737
2732
  //#endregion
2738
2733
  //#region src/routes/chat-completions/handler.ts
2739
- const logger$3 = createHandlerLogger("chat-completions-handler");
2734
+ const logger$6 = createHandlerLogger("chat-completions-handler");
2740
2735
  const CHAT_COMPLETIONS_ENDPOINT$1 = "/chat/completions";
2741
2736
  async function handleCompletion$1(c) {
2742
2737
  await checkRateLimit(state);
@@ -2766,7 +2761,7 @@ async function handleCompletion$1(c) {
2766
2761
  reason: "MODEL_NOT_SUPPORTED"
2767
2762
  });
2768
2763
  }
2769
- logger$3.debug("Request payload:", JSON.stringify(payload).slice(-400));
2764
+ logger$6.debug("Request payload:", JSON.stringify(payload).slice(-400));
2770
2765
  const selection = await accountsManager.selectAccountForRequest([{
2771
2766
  modelId: clientModel,
2772
2767
  endpoint: CHAT_COMPLETIONS_ENDPOINT$1
@@ -2885,9 +2880,9 @@ function selectionFailureResponse$2(c, params) {
2885
2880
  async function logTokenCountForRequest(params) {
2886
2881
  try {
2887
2882
  const tokenCount = await getTokenCount(params.payload, params.selectedModel);
2888
- logger$3.info("Current token count:", tokenCount);
2883
+ logger$6.info("Current token count:", tokenCount);
2889
2884
  } catch (error) {
2890
- logger$3.warn("Failed to calculate token count:", error);
2885
+ logger$6.warn("Failed to calculate token count:", error);
2891
2886
  }
2892
2887
  }
2893
2888
  function applyDefaultMaxTokens(payload, selectedModel) {
@@ -2896,7 +2891,7 @@ function applyDefaultMaxTokens(payload, selectedModel) {
2896
2891
  ...payload,
2897
2892
  max_tokens: selectedModel.capabilities.limits.max_output_tokens
2898
2893
  };
2899
- logger$3.debug("Set max_tokens to:", JSON.stringify(updated.max_tokens));
2894
+ logger$6.debug("Set max_tokens to:", JSON.stringify(updated.max_tokens));
2900
2895
  return updated;
2901
2896
  }
2902
2897
  async function handleStreamingRequest(params) {
@@ -2928,7 +2923,7 @@ async function handleStreamingRequest(params) {
2928
2923
  premiumUnlimitedBefore,
2929
2924
  response
2930
2925
  });
2931
- logger$3.debug("Streaming response");
2926
+ logger$6.debug("Streaming response");
2932
2927
  return streamSSE(c, (stream) => streamChatCompletionsAndLog$1({
2933
2928
  stream,
2934
2929
  response,
@@ -2981,7 +2976,7 @@ async function handleNonStreamingUpstreamResponse(params) {
2981
2976
  let errorMessage;
2982
2977
  const finishedAtMs = Date.now();
2983
2978
  try {
2984
- logger$3.debug("Non-streaming response:", JSON.stringify(response));
2979
+ logger$6.debug("Non-streaming response:", JSON.stringify(response));
2985
2980
  return c.json(response);
2986
2981
  } catch (error) {
2987
2982
  const details = extractErrorDetails(error);
@@ -3031,7 +3026,7 @@ async function streamChatCompletionsAndLog$1(params) {
3031
3026
  if (ttfbMs === void 0) ttfbMs = Date.now() - request.startedAtMs;
3032
3027
  const usage = await extractUsageFromChunk(chunk);
3033
3028
  if (usage) lastUsage = usage;
3034
- logger$3.debug("Streaming chunk:", JSON.stringify(chunk));
3029
+ logger$6.debug("Streaming chunk:", JSON.stringify(chunk));
3035
3030
  await stream.writeSSE(chunk);
3036
3031
  }
3037
3032
  } catch (error) {
@@ -3039,7 +3034,7 @@ async function streamChatCompletionsAndLog$1(params) {
3039
3034
  errorName = details.errorName;
3040
3035
  errorStatus = details.errorStatus;
3041
3036
  errorMessage = details.errorMessage;
3042
- logger$3.warn("Streaming error:", error);
3037
+ logger$6.warn("Streaming error:", error);
3043
3038
  } finally {
3044
3039
  const finishedAtMs = Date.now();
3045
3040
  await accountsManager.finalizeQuota(account, reservation);
@@ -3096,13 +3091,13 @@ async function handleNonStreamingRequest(params) {
3096
3091
  });
3097
3092
  finishedAtMs = Date.now();
3098
3093
  if (!isNonStreaming$1(response)) {
3099
- logger$3.debug("Unexpected streaming response");
3094
+ logger$6.debug("Unexpected streaming response");
3100
3095
  return streamSSE(c, async (stream) => {
3101
3096
  for await (const chunk of response) await stream.writeSSE(chunk);
3102
3097
  });
3103
3098
  }
3104
3099
  usage = normalizeChatCompletionsUsage(response.usage);
3105
- logger$3.debug("Non-streaming response:", JSON.stringify(response));
3100
+ logger$6.debug("Non-streaming response:", JSON.stringify(response));
3106
3101
  return c.json(response);
3107
3102
  } catch (error) {
3108
3103
  finishedAtMs = Date.now();
@@ -3319,6 +3314,57 @@ async function runEmbeddingsWithAccount({ c, store, ctx, payload, clientModel, s
3319
3314
  }
3320
3315
  }
3321
3316
 
3317
+ //#endregion
3318
+ //#region src/lib/models.ts
3319
+ const findEndpointModel = (sdkModelId) => {
3320
+ const models = state.models?.data ?? [];
3321
+ const exactMatch = models.find((m) => m.id === sdkModelId);
3322
+ if (exactMatch) return exactMatch;
3323
+ const normalized = _normalizeSdkModelId(sdkModelId);
3324
+ if (!normalized) return;
3325
+ const modelName = `claude-${normalized.family}-${normalized.version}`;
3326
+ const model = models.find((m) => m.id === modelName);
3327
+ if (model) return model;
3328
+ };
3329
+ /**
3330
+ * Normalizes an SDK model ID to extract the model family and version.
3331
+ * this method from github copilot extension
3332
+ * Examples:
3333
+ * - "claude-opus-4-5-20251101" -> { family: "opus", version: "4.5" }
3334
+ * - "claude-3-5-sonnet-20241022" -> { family: "sonnet", version: "3.5" }
3335
+ * - "claude-sonnet-4-20250514" -> { family: "sonnet", version: "4" }
3336
+ * - "claude-haiku-3-5-20250514" -> { family: "haiku", version: "3.5" }
3337
+ * - "claude-haiku-4.5" -> { family: "haiku", version: "4.5" }
3338
+ */
3339
+ const _normalizeSdkModelId = (sdkModelId) => {
3340
+ const withoutDate = sdkModelId.toLowerCase().replace(/-\d{8}$/, "");
3341
+ const pattern1 = withoutDate.match(/^claude-(\w+)-(\d+)-(\d+)$/);
3342
+ if (pattern1) return {
3343
+ family: pattern1[1],
3344
+ version: `${pattern1[2]}.${pattern1[3]}`
3345
+ };
3346
+ const pattern2 = withoutDate.match(/^claude-(\d+)-(\d+)-(\w+)$/);
3347
+ if (pattern2) return {
3348
+ family: pattern2[3],
3349
+ version: `${pattern2[1]}.${pattern2[2]}`
3350
+ };
3351
+ const pattern3 = withoutDate.match(/^claude-(\w+)-(\d+)\.(\d+)$/);
3352
+ if (pattern3) return {
3353
+ family: pattern3[1],
3354
+ version: `${pattern3[2]}.${pattern3[3]}`
3355
+ };
3356
+ const pattern4 = withoutDate.match(/^claude-(\w+)-(\d+)$/);
3357
+ if (pattern4) return {
3358
+ family: pattern4[1],
3359
+ version: pattern4[2]
3360
+ };
3361
+ const pattern5 = withoutDate.match(/^claude-(\d+)-(\w+)$/);
3362
+ if (pattern5) return {
3363
+ family: pattern5[2],
3364
+ version: pattern5[1]
3365
+ };
3366
+ };
3367
+
3322
3368
  //#endregion
3323
3369
  //#region src/routes/messages/utils.ts
3324
3370
  function mapOpenAIStopReasonToAnthropic(finishReason) {
@@ -3374,11 +3420,11 @@ const mergeToolResultForClaude = (anthropicPayload) => {
3374
3420
  msg.content = mergeToolResult(toolResults, textBlocks);
3375
3421
  }
3376
3422
  };
3377
- const estimateInputTokens = async (payload, selectedModel, logger$4) => {
3423
+ const estimateInputTokens = async (payload, selectedModel, logger$7) => {
3378
3424
  try {
3379
3425
  return (await getTokenCount(payload, selectedModel)).input;
3380
3426
  } catch (error) {
3381
- logger$4.warn("Failed to estimate input tokens for message_start", error);
3427
+ logger$7.warn("Failed to estimate input tokens for message_start", error);
3382
3428
  return;
3383
3429
  }
3384
3430
  };
@@ -3443,7 +3489,7 @@ const maybeBlockOriginalModelName = (context) => {
3443
3489
  //#region src/routes/messages/non-stream-translation.ts
3444
3490
  const THINKING_TEXT = "Thinking...";
3445
3491
  function translateToOpenAI(payload) {
3446
- const modelId = translateModelName(payload.model);
3492
+ const modelId = payload.model;
3447
3493
  const model = state.models?.data.find((m) => m.id === modelId);
3448
3494
  const thinkingBudget = getThinkingBudget(payload, model);
3449
3495
  return {
@@ -3464,56 +3510,27 @@ function getThinkingBudget(payload, model) {
3464
3510
  const thinking = payload.thinking;
3465
3511
  if (model && thinking) {
3466
3512
  const maxThinkingBudget = Math.min(model.capabilities.supports.max_thinking_budget ?? 0, (model.capabilities.limits.max_output_tokens ?? 0) - 1);
3467
- if (maxThinkingBudget > 0 && thinking.budget_tokens !== void 0) {
3513
+ thinking.budget_tokens ??= maxThinkingBudget;
3514
+ if (maxThinkingBudget > 0) {
3468
3515
  const budgetTokens = Math.min(thinking.budget_tokens, maxThinkingBudget);
3469
3516
  return Math.max(budgetTokens, model.capabilities.supports.min_thinking_budget ?? 1024);
3470
3517
  }
3471
3518
  }
3472
3519
  }
3473
- function translateModelName(model) {
3474
- if (model.startsWith("claude-sonnet-4-")) return model.replace(/^claude-sonnet-4-.*/, "claude-sonnet-4");
3475
- else if (model.startsWith("claude-opus-4-")) return model.replace(/^claude-opus-4-.*/, "claude-opus-4");
3476
- return model;
3477
- }
3478
- function translateAnthropicMessagesToOpenAI(payload, modelId, thinkingBudget) {
3479
- const systemMessages = handleSystemPrompt(payload.system, modelId, thinkingBudget);
3520
+ function translateAnthropicMessagesToOpenAI(payload, modelId, _thinkingBudget) {
3521
+ const systemMessages = handleSystemPrompt(payload.system);
3480
3522
  const otherMessages = payload.messages.flatMap((message) => message.role === "user" ? handleUserMessage(message) : handleAssistantMessage(message, modelId));
3481
- if (modelId.startsWith("claude") && thinkingBudget) {
3482
- const reminder = "<system-reminder>you MUST follow interleaved_thinking_protocol</system-reminder>";
3483
- const firstUserIndex = otherMessages.findIndex((m) => m.role === "user");
3484
- if (firstUserIndex !== -1) {
3485
- const userMessage = otherMessages[firstUserIndex];
3486
- if (typeof userMessage.content === "string") userMessage.content = reminder + "\n\n" + userMessage.content;
3487
- else if (Array.isArray(userMessage.content)) userMessage.content = [{
3488
- type: "text",
3489
- text: reminder
3490
- }, ...userMessage.content];
3491
- }
3492
- }
3493
3523
  return [...systemMessages, ...otherMessages];
3494
3524
  }
3495
- function handleSystemPrompt(system, modelId, thinkingBudget) {
3525
+ function handleSystemPrompt(system) {
3496
3526
  if (!system) return [];
3497
- let extraPrompt = "";
3498
- if (modelId.startsWith("claude") && thinkingBudget) extraPrompt = `
3499
- <interleaved_thinking_protocol>
3500
- ABSOLUTE REQUIREMENT - NON-NEGOTIABLE:
3501
- The current thinking_mode is interleaved, Whenever you have the result of a function call, think carefully , MUST output a thinking block
3502
- RULES:
3503
- Tool result → thinking block (ALWAYS, no exceptions)
3504
- This is NOT optional - it is a hard requirement
3505
- The thinking block must contain substantive reasoning (minimum 3-5 sentences)
3506
- Think about: what the results mean, what to do next, how to answer the user
3507
- NEVER skip this step, even if the result seems simple or obvious
3508
- </interleaved_thinking_protocol>`;
3509
3527
  if (typeof system === "string") return [{
3510
3528
  role: "system",
3511
- content: system + extraPrompt
3529
+ content: system
3512
3530
  }];
3513
3531
  else return [{
3514
3532
  role: "system",
3515
- content: system.map((block, index) => {
3516
- if (index === 0) return block.text + extraPrompt;
3533
+ content: system.map((block) => {
3517
3534
  return block.text;
3518
3535
  }).join("\n\n")
3519
3536
  }];
@@ -3685,7 +3702,8 @@ async function handleCountTokens(c) {
3685
3702
  const anthropicBeta = c.req.header("anthropic-beta");
3686
3703
  const anthropicPayload = await c.req.json();
3687
3704
  const openAIPayload = translateToOpenAI(anthropicPayload);
3688
- const selectedModel = state.models?.data.find((model) => model.id === anthropicPayload.model);
3705
+ const selectedModel = findEndpointModel(anthropicPayload.model);
3706
+ anthropicPayload.model = selectedModel?.id ?? anthropicPayload.model;
3689
3707
  if (!selectedModel) {
3690
3708
  consola.warn("Model not found, returning default token count");
3691
3709
  return c.json({ input_tokens: 1 });
@@ -4246,8 +4264,7 @@ const createMessages = async (payload, account, options) => {
4246
4264
  ...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),
4247
4265
  "x-initiator": options?.subagentMarker ? "agent" : initiator
4248
4266
  };
4249
- if (options?.subagentMarker) headers["x-interaction-type"] = "conversation-subagent";
4250
- if (options?.sessionId) headers["x-interaction-id"] = options.sessionId;
4267
+ prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
4251
4268
  const anthropicBeta = buildAnthropicBetaHeader(options?.anthropicBetaHeader, payload.thinking);
4252
4269
  if (anthropicBeta) headers["anthropic-beta"] = anthropicBeta;
4253
4270
  const response = await fetch(`${copilotBaseUrl(ctx)}/v1/messages`, {
@@ -4567,7 +4584,7 @@ const parseSubagentMarkerFromSystemReminder = (text) => {
4567
4584
 
4568
4585
  //#endregion
4569
4586
  //#region src/routes/messages/handler.ts
4570
- const logger$2 = createHandlerLogger("messages-handler");
4587
+ const logger$5 = createHandlerLogger("messages-handler");
4571
4588
  const CHAT_COMPLETIONS_ENDPOINT = "/chat/completions";
4572
4589
  const RESPONSES_ENDPOINT$1 = "/responses";
4573
4590
  const MESSAGES_ENDPOINT = "/v1/messages";
@@ -4582,21 +4599,21 @@ async function handleCompletion(c) {
4582
4599
  const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c);
4583
4600
  const userAgent = c.req.header("user-agent") ?? void 0;
4584
4601
  const anthropicPayload = await c.req.json();
4585
- logger$2.debug("Anthropic request payload:", JSON.stringify(anthropicPayload));
4602
+ logger$5.debug("Anthropic request payload:", JSON.stringify(anthropicPayload));
4586
4603
  const subagentMarker = parseSubagentMarkerFromFirstUser(anthropicPayload);
4587
4604
  const initiatorOverride = subagentMarker ? "agent" : void 0;
4588
- if (subagentMarker) logger$2.debug("Detected Subagent marker:", JSON.stringify(subagentMarker));
4605
+ if (subagentMarker) logger$5.debug("Detected Subagent marker:", JSON.stringify(subagentMarker));
4589
4606
  const sessionId = getRootSessionId(anthropicPayload, c);
4590
- logger$2.debug("Extracted session ID:", sessionId);
4607
+ logger$5.debug("Extracted session ID:", sessionId);
4591
4608
  const anthropicBeta = c.req.header("anthropic-beta");
4592
4609
  const isCompact = isCompactRequest(anthropicPayload);
4593
4610
  if (anthropicBeta && isWarmupProbeRequest(anthropicPayload)) anthropicPayload.model = getSmallModel();
4594
4611
  if (isCompact) {
4595
- logger$2.debug("Is compact request:", isCompact);
4612
+ logger$5.debug("Is compact request:", isCompact);
4596
4613
  if (shouldCompactUseSmallModel()) anthropicPayload.model = getSmallModel();
4597
4614
  } else mergeToolResultForClaude(anthropicPayload);
4598
4615
  const upstreamRequestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
4599
- logger$2.debug("Generated request ID:", upstreamRequestId);
4616
+ logger$5.debug("Generated request ID:", upstreamRequestId);
4600
4617
  const clientModel = anthropicPayload.model;
4601
4618
  const streamRequested = Boolean(anthropicPayload.stream);
4602
4619
  const rawUserId = anthropicPayload.metadata?.user_id;
@@ -4624,17 +4641,19 @@ async function handleCompletion(c) {
4624
4641
  if (blockedResponse) return blockedResponse;
4625
4642
  const openAIPayload = translateToOpenAI(anthropicPayload);
4626
4643
  const fallbackInitiator = initiatorOverride ?? getChatInitiator(openAIPayload.messages);
4644
+ const endpointModel = findEndpointModel(clientModel);
4645
+ const resolvedClientModel = endpointModel?.id ?? clientModel;
4627
4646
  const selection = await accountsManager.selectAccountForRequest([
4628
4647
  {
4629
- modelId: clientModel,
4648
+ modelId: resolvedClientModel,
4630
4649
  endpoint: MESSAGES_ENDPOINT
4631
4650
  },
4632
4651
  {
4633
- modelId: clientModel,
4652
+ modelId: resolvedClientModel,
4634
4653
  endpoint: RESPONSES_ENDPOINT$1
4635
4654
  },
4636
4655
  {
4637
- modelId: openAIPayload.model,
4656
+ modelId: endpointModel?.id ?? openAIPayload.model,
4638
4657
  endpoint: CHAT_COMPLETIONS_ENDPOINT
4639
4658
  }
4640
4659
  ]);
@@ -4716,7 +4735,7 @@ async function handleCompletion(c) {
4716
4735
  }
4717
4736
  const handleWithChatCompletions = async (params) => {
4718
4737
  const { c, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr } = params;
4719
- logger$2.debug("Translated OpenAI request payload:", JSON.stringify(openAIPayload));
4738
+ logger$5.debug("Translated OpenAI request payload:", JSON.stringify(openAIPayload));
4720
4739
  const ctx = toAccountContext(instr.account);
4721
4740
  const initiator = initiatorOverride ?? getChatInitiator(openAIPayload.messages);
4722
4741
  instr.initiator = initiator;
@@ -4740,9 +4759,9 @@ const handleWithChatCompletions = async (params) => {
4740
4759
  response,
4741
4760
  instr
4742
4761
  });
4743
- logger$2.debug("Streaming response from Copilot");
4762
+ logger$5.debug("Streaming response from Copilot");
4744
4763
  const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
4745
- const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$2) : void 0;
4764
+ const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$5) : void 0;
4746
4765
  const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
4747
4766
  promptCacheKey: instr.promptCacheKey,
4748
4767
  safetyIdentifier: instr.safetyIdentifier,
@@ -4761,7 +4780,7 @@ const handleWithResponsesApi = async (params) => {
4761
4780
  const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, selectedModel.id);
4762
4781
  applyResponsesApiContextManagement(responsesPayload, selectedModel.capabilities.limits.max_prompt_tokens);
4763
4782
  compactInputByLatestCompaction(responsesPayload);
4764
- logger$2.debug("Translated Responses payload:", JSON.stringify(responsesPayload));
4783
+ logger$5.debug("Translated Responses payload:", JSON.stringify(responsesPayload));
4765
4784
  const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
4766
4785
  const resolvedInitiator = initiatorOverride ?? initiator;
4767
4786
  const ctx = toAccountContext(instr.account);
@@ -4783,9 +4802,9 @@ const handleWithResponsesApi = async (params) => {
4783
4802
  });
4784
4803
  }
4785
4804
  if (responsesPayload.stream && isAsyncIterable$1(response)) {
4786
- logger$2.debug("Streaming response from Copilot (Responses API)");
4805
+ logger$5.debug("Streaming response from Copilot (Responses API)");
4787
4806
  const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
4788
- const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$2) : void 0;
4807
+ const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$5) : void 0;
4789
4808
  const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
4790
4809
  promptCacheKey: instr.promptCacheKey,
4791
4810
  safetyIdentifier: instr.safetyIdentifier,
@@ -4870,9 +4889,9 @@ async function handleChatCompletionsNonStreaming(params) {
4870
4889
  let errorMessage;
4871
4890
  const finishedAtMs = Date.now();
4872
4891
  try {
4873
- logger$2.debug("Non-streaming response from Copilot:", JSON.stringify(response));
4892
+ logger$5.debug("Non-streaming response from Copilot:", JSON.stringify(response));
4874
4893
  const anthropicResponse = translateToAnthropic(response);
4875
- logger$2.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
4894
+ logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
4876
4895
  return c.json(anthropicResponse);
4877
4896
  } catch (error) {
4878
4897
  const details = extractErrorDetails(error);
@@ -4920,7 +4939,7 @@ async function streamChatCompletionsAndLog(params) {
4920
4939
  try {
4921
4940
  for await (const rawEvent of response) {
4922
4941
  if (ttfbMs === void 0) ttfbMs = Date.now() - instr.startedAtMs;
4923
- logger$2.debug("Copilot raw stream event:", JSON.stringify(rawEvent));
4942
+ logger$5.debug("Copilot raw stream event:", JSON.stringify(rawEvent));
4924
4943
  const { data: rawData } = rawEvent;
4925
4944
  const data = typeof rawData === "string" ? rawData : await rawData;
4926
4945
  if (data === "[DONE]") break;
@@ -4929,7 +4948,7 @@ async function streamChatCompletionsAndLog(params) {
4929
4948
  if (chunk.usage) lastUsage = normalizeChatCompletionsUsage(chunk.usage);
4930
4949
  const events$1 = translateChunkToAnthropicEvents(chunk, streamState);
4931
4950
  for (const event of events$1) {
4932
- logger$2.debug("Translated Anthropic event:", JSON.stringify(event));
4951
+ logger$5.debug("Translated Anthropic event:", JSON.stringify(event));
4933
4952
  await stream.writeSSE({
4934
4953
  event: event.type,
4935
4954
  data: JSON.stringify(event)
@@ -4941,7 +4960,7 @@ async function streamChatCompletionsAndLog(params) {
4941
4960
  errorName = details.errorName;
4942
4961
  errorStatus = details.errorStatus;
4943
4962
  errorMessage = details.errorMessage;
4944
- logger$2.warn("Streaming error:", error);
4963
+ logger$5.warn("Streaming error:", error);
4945
4964
  if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
4946
4965
  } finally {
4947
4966
  const finishedAtMs = Date.now();
@@ -4992,9 +5011,9 @@ async function handleResponsesNonStreaming(params) {
4992
5011
  const finishedAtMs = Date.now();
4993
5012
  try {
4994
5013
  usage = extractResponsesUsageFromResult(result);
4995
- logger$2.debug("Non-streaming Responses result:", JSON.stringify(result).slice(-400));
5014
+ logger$5.debug("Non-streaming Responses result:", JSON.stringify(result).slice(-400));
4996
5015
  const anthropicResponse = translateResponsesResultToAnthropic(result);
4997
- logger$2.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
5016
+ logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
4998
5017
  return c.json(anthropicResponse);
4999
5018
  } catch (error) {
5000
5019
  const details = extractErrorDetails(error);
@@ -5024,7 +5043,7 @@ async function handleResponsesNonStreaming(params) {
5024
5043
  async function ensureResponsesStreamCompleted(params) {
5025
5044
  const { stream, streamState, setStreamError } = params;
5026
5045
  if (streamState.messageCompleted) return;
5027
- logger$2.warn("Responses stream ended without completion; sending error event");
5046
+ logger$5.warn("Responses stream ended without completion; sending error event");
5028
5047
  const msg = "Responses stream ended without completion";
5029
5048
  const errorEvent = buildErrorEvent(msg);
5030
5049
  setStreamError("StreamIncomplete", msg);
@@ -5057,21 +5076,21 @@ async function streamResponsesAndLog$1(params) {
5057
5076
  }
5058
5077
  const data = chunk.data;
5059
5078
  if (!data) continue;
5060
- logger$2.debug("Responses raw stream event:", data);
5079
+ logger$5.debug("Responses raw stream event:", data);
5061
5080
  const parsed = JSON.parse(data);
5062
5081
  const u = extractResponsesUsageFromStreamEvent(parsed);
5063
5082
  if (u.usageJson) lastUsage = u;
5064
5083
  const events$1 = translateResponsesStreamEvent(parsed, streamState);
5065
5084
  for (const event of events$1) {
5066
5085
  const eventData = JSON.stringify(event);
5067
- logger$2.debug("Translated Anthropic event:", eventData);
5086
+ logger$5.debug("Translated Anthropic event:", eventData);
5068
5087
  await stream.writeSSE({
5069
5088
  event: event.type,
5070
5089
  data: eventData
5071
5090
  });
5072
5091
  }
5073
5092
  if (streamState.messageCompleted) {
5074
- logger$2.debug("Message completed, ending stream");
5093
+ logger$5.debug("Message completed, ending stream");
5075
5094
  break;
5076
5095
  }
5077
5096
  }
@@ -5088,7 +5107,7 @@ async function streamResponsesAndLog$1(params) {
5088
5107
  errorName = details.errorName;
5089
5108
  errorStatus = details.errorStatus;
5090
5109
  errorMessage = details.errorMessage;
5091
- logger$2.warn("Streaming error:", error);
5110
+ logger$5.warn("Streaming error:", error);
5092
5111
  if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
5093
5112
  } finally {
5094
5113
  const finishedAtMs = Date.now();
@@ -5138,7 +5157,7 @@ async function handleMessagesNonStreaming(params) {
5138
5157
  let errorMessage;
5139
5158
  const finishedAtMs = Date.now();
5140
5159
  try {
5141
- logger$2.debug("Non-streaming Messages result:", JSON.stringify(response).slice(-400));
5160
+ logger$5.debug("Non-streaming Messages result:", JSON.stringify(response).slice(-400));
5142
5161
  return c.json(response);
5143
5162
  } catch (error) {
5144
5163
  const details = extractErrorDetails(error);
@@ -5172,7 +5191,7 @@ const parseMessagesStreamUsage = (data) => {
5172
5191
  if (parsed.type !== "message_delta" || !parsed.usage) return null;
5173
5192
  return normalizeMessagesUsage(parsed.usage);
5174
5193
  } catch (error) {
5175
- logger$2.warn("Failed to parse messages stream event", error);
5194
+ logger$5.warn("Failed to parse messages stream event", error);
5176
5195
  return null;
5177
5196
  }
5178
5197
  };
@@ -5189,7 +5208,7 @@ async function streamMessagesAndLog(params) {
5189
5208
  const eventNameRaw = rawEvent.event;
5190
5209
  const eventName = typeof eventNameRaw === "string" && eventNameRaw.length > 0 ? eventNameRaw : "message";
5191
5210
  const data = rawEvent.data ?? "";
5192
- logger$2.debug("Messages raw stream event:", data);
5211
+ logger$5.debug("Messages raw stream event:", data);
5193
5212
  const usage = parseMessagesStreamUsage(data);
5194
5213
  if (usage) lastUsage = usage;
5195
5214
  await stream.writeSSE({
@@ -5202,7 +5221,7 @@ async function streamMessagesAndLog(params) {
5202
5221
  errorName = details.errorName;
5203
5222
  errorStatus = details.errorStatus;
5204
5223
  errorMessage = details.errorMessage;
5205
- logger$2.warn("Streaming error:", error);
5224
+ logger$5.warn("Streaming error:", error);
5206
5225
  if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
5207
5226
  } finally {
5208
5227
  const finishedAtMs = Date.now();
@@ -5237,7 +5256,7 @@ const handleWithMessagesApi = async (params) => {
5237
5256
  anthropicPayload.thinking = { type: "adaptive" };
5238
5257
  anthropicPayload.output_config = { effort: getAnthropicEffortForModel(anthropicPayload.model) };
5239
5258
  }
5240
- logger$2.debug("Translated Messages payload:", JSON.stringify(anthropicPayload));
5259
+ logger$5.debug("Translated Messages payload:", JSON.stringify(anthropicPayload));
5241
5260
  const ctx = toAccountContext(instr.account);
5242
5261
  const initiator = initiatorOverride ?? getMessagesInitiator(anthropicPayload);
5243
5262
  instr.initiator = initiator;
@@ -5258,7 +5277,7 @@ const handleWithMessagesApi = async (params) => {
5258
5277
  });
5259
5278
  }
5260
5279
  if (isAsyncIterable$1(response)) {
5261
- logger$2.debug("Streaming response from Copilot (Messages API)");
5280
+ logger$5.debug("Streaming response from Copilot (Messages API)");
5262
5281
  return streamSSE(c, (stream) => streamMessagesAndLog({
5263
5282
  stream,
5264
5283
  response,
@@ -5342,6 +5361,204 @@ modelRoutes.get("/", async (c) => {
5342
5361
  }
5343
5362
  });
5344
5363
 
5364
+ //#endregion
5365
+ //#region src/routes/provider/messages/count-tokens-handler.ts
5366
+ const logger$4 = createHandlerLogger("provider-count-tokens-handler");
5367
+ const createFallbackModel = (modelId) => ({
5368
+ capabilities: {
5369
+ family: "provider",
5370
+ limits: {},
5371
+ object: "model_capabilities",
5372
+ supports: {},
5373
+ tokenizer: "o200k_base",
5374
+ type: "chat"
5375
+ },
5376
+ id: modelId,
5377
+ model_picker_enabled: false,
5378
+ name: modelId,
5379
+ object: "model",
5380
+ preview: false,
5381
+ vendor: "provider",
5382
+ version: "unknown"
5383
+ });
5384
+ async function handleProviderCountTokens(c) {
5385
+ const provider = c.req.param("provider");
5386
+ try {
5387
+ const anthropicPayload = await c.req.json();
5388
+ const openAIPayload = translateToOpenAI(anthropicPayload);
5389
+ const modelId = anthropicPayload.model.trim();
5390
+ let selectedModel = state.models?.data.find((model) => model.id === modelId);
5391
+ if (!selectedModel && modelId) selectedModel = createFallbackModel(modelId);
5392
+ if (!selectedModel) {
5393
+ logger$4.warn("provider.count_tokens.model_not_found", {
5394
+ provider,
5395
+ model: anthropicPayload.model
5396
+ });
5397
+ return c.json({ input_tokens: 1 });
5398
+ }
5399
+ const tokenCount = await getTokenCount(openAIPayload, selectedModel);
5400
+ const finalTokenCount = tokenCount.input + tokenCount.output;
5401
+ logger$4.debug("provider.count_tokens.success", {
5402
+ provider,
5403
+ model: anthropicPayload.model,
5404
+ input_tokens: finalTokenCount
5405
+ });
5406
+ return c.json({ input_tokens: finalTokenCount });
5407
+ } catch (error) {
5408
+ logger$4.error("provider.count_tokens.error", {
5409
+ provider,
5410
+ error
5411
+ });
5412
+ return c.json({ input_tokens: 1 });
5413
+ }
5414
+ }
5415
+
5416
+ //#endregion
5417
+ //#region src/services/providers/anthropic-proxy.ts
5418
+ const FORWARDABLE_HEADERS = [
5419
+ "anthropic-version",
5420
+ "anthropic-beta",
5421
+ "accept",
5422
+ "user-agent"
5423
+ ];
5424
+ const STRIPPED_RESPONSE_HEADERS = [
5425
+ "connection",
5426
+ "content-encoding",
5427
+ "content-length",
5428
+ "keep-alive",
5429
+ "proxy-authenticate",
5430
+ "proxy-authorization",
5431
+ "te",
5432
+ "trailer",
5433
+ "transfer-encoding",
5434
+ "upgrade"
5435
+ ];
5436
+ function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
5437
+ const headers = {
5438
+ "content-type": "application/json",
5439
+ accept: "application/json",
5440
+ "x-api-key": providerConfig.apiKey
5441
+ };
5442
+ for (const headerName of FORWARDABLE_HEADERS) {
5443
+ const headerValue = requestHeaders.get(headerName);
5444
+ if (headerValue) headers[headerName] = headerValue;
5445
+ }
5446
+ return headers;
5447
+ }
5448
+ function createProviderProxyResponse(upstreamResponse) {
5449
+ const headers = new Headers(upstreamResponse.headers);
5450
+ for (const headerName of STRIPPED_RESPONSE_HEADERS) headers.delete(headerName);
5451
+ return new Response(upstreamResponse.body, {
5452
+ headers,
5453
+ status: upstreamResponse.status,
5454
+ statusText: upstreamResponse.statusText
5455
+ });
5456
+ }
5457
+ async function forwardProviderMessages(providerConfig, payload, requestHeaders) {
5458
+ return await fetch(`${providerConfig.baseUrl}/v1/messages`, {
5459
+ method: "POST",
5460
+ headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
5461
+ body: JSON.stringify(payload)
5462
+ });
5463
+ }
5464
+ async function forwardProviderModels(providerConfig, requestHeaders) {
5465
+ return await fetch(`${providerConfig.baseUrl}/v1/models`, {
5466
+ method: "GET",
5467
+ headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders)
5468
+ });
5469
+ }
5470
+
5471
+ //#endregion
5472
+ //#region src/routes/provider/messages/handler.ts
5473
+ const logger$3 = createHandlerLogger("provider-messages-handler");
5474
+ async function handleProviderMessages(c) {
5475
+ const provider = c.req.param("provider");
5476
+ const providerConfig = getProviderConfig(provider);
5477
+ if (!providerConfig) return c.json({ error: {
5478
+ message: `Provider '${provider}' not found or disabled`,
5479
+ type: "invalid_request_error"
5480
+ } }, 404);
5481
+ try {
5482
+ const payload = await c.req.json();
5483
+ const modelConfig = providerConfig.models?.[payload.model];
5484
+ payload.temperature ??= modelConfig?.temperature;
5485
+ payload.top_p ??= modelConfig?.topP;
5486
+ payload.top_k ??= modelConfig?.topK;
5487
+ logger$3.debug("provider.messages.request", JSON.stringify({
5488
+ payload,
5489
+ provider
5490
+ }));
5491
+ const upstreamResponse = await forwardProviderMessages(providerConfig, payload, c.req.raw.headers);
5492
+ const contentType = upstreamResponse.headers.get("content-type") ?? "";
5493
+ if (Boolean(payload.stream) && contentType.includes("text/event-stream")) {
5494
+ logger$3.debug("provider.messages.streaming");
5495
+ return streamSSE(c, async (stream) => {
5496
+ for await (const event of events(upstreamResponse)) {
5497
+ const eventName = event.event;
5498
+ const data = event.data ?? "";
5499
+ logger$3.debug("provider.messages.raw_stream_event", data);
5500
+ await stream.writeSSE({
5501
+ event: eventName,
5502
+ data
5503
+ });
5504
+ }
5505
+ });
5506
+ }
5507
+ return createProviderProxyResponse(upstreamResponse);
5508
+ } catch (error) {
5509
+ logger$3.error("provider.messages.error", {
5510
+ provider,
5511
+ error
5512
+ });
5513
+ throw error;
5514
+ }
5515
+ }
5516
+
5517
+ //#endregion
5518
+ //#region src/routes/provider/messages/route.ts
5519
+ const providerMessageRoutes = new Hono();
5520
+ providerMessageRoutes.post("/", async (c) => {
5521
+ try {
5522
+ return await handleProviderMessages(c);
5523
+ } catch (error) {
5524
+ return await forwardError(c, error);
5525
+ }
5526
+ });
5527
+ providerMessageRoutes.post("/count_tokens", async (c) => {
5528
+ try {
5529
+ return await handleProviderCountTokens(c);
5530
+ } catch (error) {
5531
+ return await forwardError(c, error);
5532
+ }
5533
+ });
5534
+
5535
+ //#endregion
5536
+ //#region src/routes/provider/models/route.ts
5537
+ const logger$2 = createHandlerLogger("provider-models-handler");
5538
+ const providerModelRoutes = new Hono();
5539
+ providerModelRoutes.get("/", async (c) => {
5540
+ const provider = c.req.param("provider") ?? "";
5541
+ try {
5542
+ const providerConfig = getProviderConfig(provider);
5543
+ if (!providerConfig) return c.json({ error: {
5544
+ message: `Provider '${provider}' not found or disabled`,
5545
+ type: "invalid_request_error"
5546
+ } }, 404);
5547
+ const upstreamResponse = await forwardProviderModels(providerConfig, c.req.raw.headers);
5548
+ logger$2.debug("provider.models.response", {
5549
+ provider,
5550
+ statusCode: upstreamResponse.status
5551
+ });
5552
+ return createProviderProxyResponse(upstreamResponse);
5553
+ } catch (error) {
5554
+ logger$2.error("provider.models.error", {
5555
+ provider,
5556
+ error
5557
+ });
5558
+ return await forwardError(c, error);
5559
+ }
5560
+ });
5561
+
5345
5562
  //#endregion
5346
5563
  //#region src/routes/responses/stream-id-sync.ts
5347
5564
  const createStreamIdTracker = () => ({ outputItems: /* @__PURE__ */ new Map() });
@@ -5922,7 +6139,9 @@ server.route("/v1/models", modelRoutes);
5922
6139
  server.route("/v1/embeddings", embeddingRoutes);
5923
6140
  server.route("/v1/responses", responsesRoutes);
5924
6141
  server.route("/v1/messages", messageRoutes);
6142
+ server.route("/:provider/v1/messages", providerMessageRoutes);
6143
+ server.route("/:provider/v1/models", providerModelRoutes);
5925
6144
 
5926
6145
  //#endregion
5927
6146
  export { server };
5928
- //# sourceMappingURL=server-Cxlbm6kJ.js.map
6147
+ //# sourceMappingURL=server-D3A61KAx.js.map