@jeffreycao/copilot-api 1.16.2 → 1.16.3

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,7 +1,7 @@
1
- import { A as PATHS, C as getConfig, D as isResponsesApiWebSearchEnabled, E as isMessagesApiEnabled, O as isResponsesApiWebSocketEnabled, S as getClaudeTokenMultiplier, T as isAlphaSearchCodexPriorityEnabled, _ as resolveMappedModel, b as getAnthropicApiKey, d as getModelResponsesApiCompactThreshold$1, f as getReasoningEffortForModel, g as isGpt56OrAbove, h as isContextManagementEnabledForResponses, i as listEnabledProviders, l as getExtraPromptForModel, m as isContextManagementEnabledForMessages, n as getRawProviderConfig, o as resolveEffectiveProviderType, p as getSmallModel, s as resolveProviderAuthType, t as getProviderConfig, u as getModelMappings, v as setModelMappings, w as getMessageApiWebSearchModel, x as getClaudeAutoModel } from "./config-BAC1UYyJ.js";
2
- import { A as buildCodexRequestHeaders, B as state, C as compactAutoContinuePromptStarts, E as compactSystemPromptStarts, F as createResponsesSafeStream, H as forwardError, I as encodePoolKeyPart, L as isTerminalResponsesStreamChunk, M as generateTraceId, N as requestContext, P as resolveTraceId$1, R as createPooledWebSocketStream, V as HTTPError, b as prepareInteractionHeaders, c as getUUID, d as isResponsesStream, f as parseUserIdMetadata, g as copilotHeaders, h as copilotBaseUrl, j as forwardCodexResponses, k as CODEX_API_BASE_URL, l as isAsyncIterable, o as generateRequestIdFromPayload, p as getCopilotUsage, r as setupCodexToken, s as getRootSessionId, u as isNullish, v as copilotWebSocketHeaders, w as compactMessageSections, x as prepareMessageProxyHeaders, y as prepareForCompact, z as createWebSocketUrl } from "./token-ByZO3ykJ.js";
1
+ import { C as getClaudeTokenMultiplier, D as isMessagesApiEnabled, E as isAlphaSearchCodexPriorityEnabled, O as isResponsesApiWebSearchEnabled, S as getClaudeAutoModel, T as getMessageApiWebSearchModel, _ as resolveMappedModel, b as getAlphaSearchModel, d as getModelResponsesApiCompactThreshold$1, f as getReasoningEffortForModel, g as isGpt56OrAbove, h as isContextManagementEnabledForResponses, i as listEnabledProviders, j as PATHS, k as isResponsesApiWebSocketEnabled, l as getExtraPromptForModel, m as isContextManagementEnabledForMessages, n as getRawProviderConfig, o as resolveEffectiveProviderType, p as getSmallModel, s as resolveProviderAuthType, t as getProviderConfig, u as getModelMappings, v as setModelMappings, w as getConfig, x as getAnthropicApiKey } from "./config-CoMdcHDW.js";
2
+ import { A as buildCodexRequestHeaders, B as state, C as compactAutoContinuePromptStarts, D as compactTextOnlyGuard, E as compactSystemPromptStarts, F as createResponsesSafeStream, H as forwardError, I as encodePoolKeyPart, L as isTerminalResponsesStreamChunk, M as generateTraceId, N as requestContext, P as resolveTraceId$1, R as createPooledWebSocketStream, V as HTTPError, b as prepareInteractionHeaders, c as getUUID, d as isResponsesStream, f as parseUserIdMetadata, g as copilotHeaders, h as copilotBaseUrl, j as forwardCodexResponses, k as CODEX_API_BASE_URL, l as isAsyncIterable, o as generateRequestIdFromPayload, p as getCopilotUsage, r as setupCodexToken, s as getRootSessionId, u as isNullish, v as copilotWebSocketHeaders, w as compactMessageSections, x as prepareMessageProxyHeaders, y as prepareForCompact, z as createWebSocketUrl } from "./token-_ZvkUtOA.js";
3
3
  import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, d as shouldEnableResponsesToolSearch, i as isBridgeToolSearchName, l as resolveBridgeToolSearchName, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, t as BRIDGE_TOOL_SEARCH_NAME, u as selectDeferredToolsByNames } from "./tool-search-Ds1vbmGG.js";
4
- import { i as toClientModelId, r as normalizeSdkModelId, t as findEndpointModel } from "./models-BY_m4eOW.js";
4
+ import { i as toClientModelId, r as normalizeSdkModelId, t as findEndpointModel } from "./models-DUdPhOBN.js";
5
5
  import consola from "consola";
6
6
  import { createHash } from "node:crypto";
7
7
  import fs, { readFileSync } from "node:fs";
@@ -1995,10 +1995,12 @@ async function forwardProviderResponses(providerConfig, payload, requestHeaders)
1995
1995
  body: JSON.stringify(payload)
1996
1996
  });
1997
1997
  }
1998
+ const PROVIDER_MODELS_TIMEOUT_MS = 15e3;
1998
1999
  async function forwardProviderModels(providerConfig, requestHeaders) {
1999
2000
  return await fetch(`${providerConfig.baseUrl}/v1/models`, {
2000
2001
  method: "GET",
2001
- headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders)
2002
+ headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
2003
+ signal: AbortSignal.timeout(PROVIDER_MODELS_TIMEOUT_MS)
2002
2004
  });
2003
2005
  }
2004
2006
  /** Align with Codex images: long-running generation/edits need a generous cap. */
@@ -2039,7 +2041,7 @@ async function forwardProviderImages(providerConfig, request, operation) {
2039
2041
  }
2040
2042
  //#endregion
2041
2043
  //#region src/routes/alpha-search/alpha-search-responses.ts
2042
- const logger$15 = createHandlerLogger("alpha-search-responses-handler");
2044
+ const logger$16 = createHandlerLogger("alpha-search-responses-handler");
2043
2045
  const SESSION_TTL_MS = 3600 * 1e3;
2044
2046
  const MAX_SESSIONS = 128;
2045
2047
  const MAX_URL_REFERENCES = 256;
@@ -2395,14 +2397,14 @@ function createRemoteResponsesPayload(request, model, instruction) {
2395
2397
  };
2396
2398
  }
2397
2399
  async function requestProviderSearch(c, providerConfig, payload, model, sessionId) {
2398
- debugJson(logger$15, "Alpha search provider Responses request:", {
2400
+ debugJson(logger$16, "Alpha search provider Responses request:", {
2399
2401
  payload,
2400
2402
  provider: providerConfig.name
2401
2403
  });
2402
2404
  const upstreamResponse = await forwardProviderResponses(providerConfig, payload, c.req.raw.headers);
2403
2405
  if (!upstreamResponse.ok) throw new HTTPError(`Failed to create ${providerConfig.name} responses for alpha search`, upstreamResponse);
2404
2406
  const result = await upstreamResponse.json();
2405
- debugJson(logger$15, "Alpha search provider Responses result:", {
2407
+ debugJson(logger$16, "Alpha search provider Responses result:", {
2406
2408
  provider: providerConfig.name,
2407
2409
  result
2408
2410
  });
@@ -2418,7 +2420,7 @@ async function requestProviderSearch(c, providerConfig, payload, model, sessionI
2418
2420
  return result;
2419
2421
  }
2420
2422
  async function requestCopilotSearch(payload, model, requestId, sessionId) {
2421
- debugJson(logger$15, "Alpha search Copilot Responses request:", payload);
2423
+ debugJson(logger$16, "Alpha search Copilot Responses request:", payload);
2422
2424
  const result = await alphaSearchResponsesDependencies.createResponses(payload, {
2423
2425
  vision: false,
2424
2426
  initiator: "agent",
@@ -2426,7 +2428,7 @@ async function requestCopilotSearch(payload, model, requestId, sessionId) {
2426
2428
  requestId,
2427
2429
  sessionId
2428
2430
  });
2429
- debugJson(logger$15, "Alpha search Copilot Responses result:", result);
2431
+ debugJson(logger$16, "Alpha search Copilot Responses result:", result);
2430
2432
  alphaSearchResponsesDependencies.createUsageRecorder(model, sessionId)({
2431
2433
  ...normalizeResponsesUsage(result.usage),
2432
2434
  total_nano_aiu: normalizeOptionalToken(result.copilot_usage?.total_nano_aiu)
@@ -2541,7 +2543,7 @@ async function forwardCodexAlphaSearch(request) {
2541
2543
  }
2542
2544
  //#endregion
2543
2545
  //#region src/routes/alpha-search/route.ts
2544
- const logger$14 = createHandlerLogger("alpha-search-handler");
2546
+ const logger$15 = createHandlerLogger("alpha-search-handler");
2545
2547
  const alphaSearchRoutes = new Hono();
2546
2548
  function parseDebugBody(body) {
2547
2549
  try {
@@ -2551,9 +2553,9 @@ function parseDebugBody(body) {
2551
2553
  }
2552
2554
  }
2553
2555
  async function forwardCodexAlphaSearchRequest(request) {
2554
- await debugJsonAsync(logger$14, "alpha_search.codex.request", async () => ({ body: parseDebugBody(await request.clone().text()) }));
2556
+ await debugJsonAsync(logger$15, "alpha_search.codex.request", async () => ({ body: parseDebugBody(await request.clone().text()) }));
2555
2557
  const upstreamResponse = await forwardCodexAlphaSearch(request);
2556
- await debugJsonAsync(logger$14, "alpha_search.codex.response", async () => ({
2558
+ await debugJsonAsync(logger$15, "alpha_search.codex.response", async () => ({
2557
2559
  body: parseDebugBody(await upstreamResponse.clone().text()),
2558
2560
  statusCode: upstreamResponse.status
2559
2561
  }));
@@ -2600,7 +2602,8 @@ async function handleAlphaSearchRequest(c, resolvedProviderConfig) {
2600
2602
  const requestedModel = payload.model;
2601
2603
  payload.model = resolveMappedModel(requestedModel);
2602
2604
  if (payload.model !== requestedModel) consola.debug(`Resolved model mapping: ${requestedModel} -> ${payload.model}`);
2603
- const providerModelAlias = parseProviderModelAlias(payload.model);
2605
+ const resolvedRequestedModel = payload.model;
2606
+ let providerModelAlias = parseProviderModelAlias(payload.model);
2604
2607
  if (providerModelAlias) {
2605
2608
  payload.model = providerModelAlias.model;
2606
2609
  if (providerModelAlias.provider === "codex") return await handleCodexRequest(c, createAlphaSearchRequest(c.req.raw, payload));
@@ -2608,20 +2611,55 @@ async function handleAlphaSearchRequest(c, resolvedProviderConfig) {
2608
2611
  if (isAlphaSearchCodexPriorityEnabled()) {
2609
2612
  if (await resolveProviderConfig("codex")) return await forwardCodexAlphaSearchRequest(createAlphaSearchRequest(c.req.raw, payload));
2610
2613
  }
2614
+ const messagesBackedModel = await isMessagesBackedModel(resolvedRequestedModel);
2615
+ if (messagesBackedModel) {
2616
+ const searchModel = getAlphaSearchModel();
2617
+ if (!searchModel) return invalidRequest(c, "alphaSearchModel is disabled; Messages-backed Codex models require a native Responses search model");
2618
+ const resolvedSearchModel = resolveMappedModel(searchModel);
2619
+ if (!await isNativeResponsesModel(resolvedSearchModel)) return invalidRequest(c, `Configured alphaSearchModel '${searchModel}' does not support the Responses endpoint required for alpha search`);
2620
+ consola.debug(`Redirected alpha search model: ${resolvedRequestedModel} -> ${resolvedSearchModel}`);
2621
+ payload.model = resolvedSearchModel;
2622
+ providerModelAlias = parseProviderModelAlias(payload.model);
2623
+ if (providerModelAlias) {
2624
+ payload.model = providerModelAlias.model;
2625
+ if (providerModelAlias.provider === "codex") return await handleCodexRequest(c, createAlphaSearchRequest(c.req.raw, payload));
2626
+ }
2627
+ }
2628
+ const fallbackRequestedModel = messagesBackedModel ? payload.model : requestedModel;
2611
2629
  if (providerModelAlias) return await handleAlphaSearchResponses(c, {
2612
2630
  provider: providerModelAlias.provider,
2613
2631
  request: payload
2614
2632
  });
2615
2633
  return await handleAlphaSearchResponses(c, { request: {
2616
2634
  ...payload,
2617
- model: requestedModel
2635
+ model: fallbackRequestedModel
2618
2636
  } });
2619
2637
  }
2638
+ async function isMessagesBackedModel(model) {
2639
+ const providerAlias = parseProviderModelAlias(model);
2640
+ if (providerAlias) {
2641
+ const providerConfig = await resolveProviderConfig(providerAlias.provider);
2642
+ if (!providerConfig) return false;
2643
+ const effectiveType = resolveEffectiveProviderType(providerConfig, providerAlias.model);
2644
+ return effectiveType === "anthropic" || effectiveType === "openai-compatible";
2645
+ }
2646
+ const endpoints = findEndpointModel(model)?.supported_endpoints ?? [];
2647
+ return (endpoints.includes("/v1/messages") || endpoints.includes("/chat/completions")) && !endpoints.includes("/responses") && !endpoints.includes("ws:/responses");
2648
+ }
2649
+ async function isNativeResponsesModel(model) {
2650
+ const providerAlias = parseProviderModelAlias(model);
2651
+ if (providerAlias) {
2652
+ const providerConfig = await resolveProviderConfig(providerAlias.provider);
2653
+ return providerConfig !== null && resolveEffectiveProviderType(providerConfig, providerAlias.model) === "openai-responses";
2654
+ }
2655
+ const endpoints = findEndpointModel(model)?.supported_endpoints ?? [];
2656
+ return endpoints.includes("/responses") || endpoints.includes("ws:/responses");
2657
+ }
2620
2658
  alphaSearchRoutes.post("/", async (c) => {
2621
2659
  try {
2622
2660
  return await handleAlphaSearchRequest(c);
2623
2661
  } catch (error) {
2624
- logger$14.error("alpha_search.error", { error });
2662
+ logger$15.error("alpha_search.error", { error });
2625
2663
  return await forwardError(c, error);
2626
2664
  }
2627
2665
  });
@@ -2686,7 +2724,7 @@ const applyMissingExtraBody = (payload, options) => {
2686
2724
  };
2687
2725
  //#endregion
2688
2726
  //#region src/routes/provider/chat-completions/handler.ts
2689
- const logger$13 = createHandlerLogger("provider-chat-completions-handler");
2727
+ const logger$14 = createHandlerLogger("provider-chat-completions-handler");
2690
2728
  async function handleProviderChatCompletionsForProvider(c, options) {
2691
2729
  const { payload, provider } = options;
2692
2730
  const providerConfig = await resolveProviderConfig(provider);
@@ -2700,13 +2738,13 @@ async function handleProviderChatCompletionsForProvider(c, options) {
2700
2738
  applyProviderStreamOptions(payload);
2701
2739
  applyDashScopePreserveThinkingDefault(payload, providerConfig);
2702
2740
  applyProviderContextCache(payload, modelConfig, providerConfig);
2703
- debugJson(logger$13, "provider.chat_completions.request", {
2741
+ debugJson(logger$14, "provider.chat_completions.request", {
2704
2742
  payload,
2705
2743
  provider
2706
2744
  });
2707
2745
  const upstreamResponse = await forwardProviderChatCompletions(providerConfig, payload, c.req.raw.headers);
2708
2746
  if (!upstreamResponse.ok) {
2709
- logger$13.error("Failed to create provider chat completions", {
2747
+ logger$14.error("Failed to create provider chat completions", {
2710
2748
  provider,
2711
2749
  statusCode: upstreamResponse.status
2712
2750
  });
@@ -2720,7 +2758,7 @@ async function handleProviderChatCompletionsForProvider(c, options) {
2720
2758
  });
2721
2759
  const responseBody = await upstreamResponse.clone().json();
2722
2760
  recordUsage(normalizeOpenAIUsage(responseBody.usage));
2723
- debugJson(logger$13, "provider.chat_completions.response", responseBody);
2761
+ debugJson(logger$14, "provider.chat_completions.response", responseBody);
2724
2762
  return createProviderProxyResponse(upstreamResponse);
2725
2763
  }
2726
2764
  const applyProviderStreamOptions = (payload) => {
@@ -2742,12 +2780,12 @@ const createProviderChatCompletionsUsageRecorder = (payload, provider, modelConf
2742
2780
  providerName: provider
2743
2781
  });
2744
2782
  const streamProviderChatCompletions = (c, upstreamResponse, options) => {
2745
- logger$13.debug("provider.chat_completions.streaming", { provider: options.provider });
2783
+ logger$14.debug("provider.chat_completions.streaming", { provider: options.provider });
2746
2784
  return streamSSE(c, async (stream) => {
2747
2785
  let usage = {};
2748
2786
  try {
2749
2787
  for await (const chunk of events(upstreamResponse)) {
2750
- debugJson(logger$13, "provider.chat_completions.stream_chunk", chunk);
2788
+ debugJson(logger$14, "provider.chat_completions.stream_chunk", chunk);
2751
2789
  if (chunk.data && chunk.data !== "[DONE]") {
2752
2790
  const parsedChunk = parseChatCompletionChunkData(chunk.data);
2753
2791
  if (parsedChunk?.usage) usage = normalizeOpenAIUsage(parsedChunk.usage);
@@ -2801,7 +2839,7 @@ const createChatCompletions = async (payload, options) => {
2801
2839
  };
2802
2840
  //#endregion
2803
2841
  //#region src/routes/chat-completions/handler.ts
2804
- const logger$12 = createHandlerLogger("chat-completions-handler");
2842
+ const logger$13 = createHandlerLogger("chat-completions-handler");
2805
2843
  async function handleCompletion$1(c) {
2806
2844
  let payload = await c.req.json();
2807
2845
  const requestedModel = payload.model;
@@ -2815,23 +2853,23 @@ async function handleCompletion$1(c) {
2815
2853
  provider: providerModelAlias.provider
2816
2854
  });
2817
2855
  }
2818
- debugJson(logger$12, "Request payload:", payload);
2856
+ debugJson(logger$13, "Request payload:", payload);
2819
2857
  const selectedModel = state.models?.data.find((model) => model.id === payload.model);
2820
2858
  if (isNullish(payload.max_tokens) && isNullish(payload.max_completion_tokens)) {
2821
2859
  payload = {
2822
2860
  ...payload,
2823
2861
  max_tokens: selectedModel?.capabilities.limits.max_output_tokens
2824
2862
  };
2825
- debugJson(logger$12, "Set max_tokens to:", payload.max_tokens);
2863
+ debugJson(logger$13, "Set max_tokens to:", payload.max_tokens);
2826
2864
  }
2827
2865
  if (payload.model.includes("gpt")) {
2828
2866
  if (isNullish(payload.max_completion_tokens)) payload.max_completion_tokens = payload.max_tokens;
2829
2867
  delete payload.max_tokens;
2830
2868
  }
2831
2869
  const requestId = generateRequestIdFromPayload(payload);
2832
- logger$12.debug("Generated request ID:", requestId);
2870
+ logger$13.debug("Generated request ID:", requestId);
2833
2871
  const sessionId = getUUID(requestId);
2834
- logger$12.debug("Extracted session ID:", sessionId);
2872
+ logger$13.debug("Extracted session ID:", sessionId);
2835
2873
  const recordUsage = createCopilotTokenUsageRecorder({
2836
2874
  endpoint: "chat_completions",
2837
2875
  fallbackSessionId: sessionId,
@@ -2842,18 +2880,18 @@ async function handleCompletion$1(c) {
2842
2880
  sessionId
2843
2881
  });
2844
2882
  if (isNonStreaming$1(response)) {
2845
- debugJson(logger$12, "Non-streaming response:", response);
2883
+ debugJson(logger$13, "Non-streaming response:", response);
2846
2884
  recordUsage({
2847
2885
  ...normalizeOpenAIUsage(response.usage),
2848
2886
  total_nano_aiu: normalizeOptionalToken(response.copilot_usage?.total_nano_aiu)
2849
2887
  });
2850
2888
  return c.json(response);
2851
2889
  }
2852
- logger$12.debug("Streaming response");
2890
+ logger$13.debug("Streaming response");
2853
2891
  return streamSSE(c, async (stream) => {
2854
2892
  let usage = {};
2855
2893
  for await (const chunk of response) {
2856
- debugJson(logger$12, "Streaming chunk:", chunk);
2894
+ debugJson(logger$13, "Streaming chunk:", chunk);
2857
2895
  const parsedChunk = parseChatCompletionChunk(chunk);
2858
2896
  if (parsedChunk?.usage || parsedChunk?.copilot_usage) usage = {
2859
2897
  ...normalizeOpenAIUsage(parsedChunk.usage),
@@ -2970,7 +3008,7 @@ async function forwardCodexImages(request, operation) {
2970
3008
  }
2971
3009
  //#endregion
2972
3010
  //#region src/routes/images/route.ts
2973
- const logger$11 = createHandlerLogger("images-handler");
3011
+ const logger$12 = createHandlerLogger("images-handler");
2974
3012
  const imageRoutes = new Hono();
2975
3013
  const imageRouteDependencies = { debugJsonAsync };
2976
3014
  function getContentMetadata$1(headers) {
@@ -2989,16 +3027,16 @@ async function handleCodexImages(c, operation, resolvedProviderConfig) {
2989
3027
  message: "Provider 'codex' not found or disabled",
2990
3028
  type: "invalid_request_error"
2991
3029
  } }, 404);
2992
- if (operation === "generations") await imageRouteDependencies.debugJsonAsync(logger$11, "images.generations.codex.request", async () => ({ body: await c.req.raw.clone().text() }));
2993
- else debugJson(logger$11, "images.edits.codex.request", getContentMetadata$1(c.req.raw.headers));
3030
+ if (operation === "generations") await imageRouteDependencies.debugJsonAsync(logger$12, "images.generations.codex.request", async () => ({ body: await c.req.raw.clone().text() }));
3031
+ else debugJson(logger$12, "images.edits.codex.request", getContentMetadata$1(c.req.raw.headers));
2994
3032
  const upstreamResponse = await forwardCodexImages(c.req.raw, operation);
2995
- debugJson(logger$11, `images.${operation}.codex.response`, {
3033
+ debugJson(logger$12, `images.${operation}.codex.response`, {
2996
3034
  ...getContentMetadata$1(upstreamResponse.headers),
2997
3035
  statusCode: upstreamResponse.status
2998
3036
  });
2999
3037
  return createProviderProxyResponse(upstreamResponse);
3000
3038
  } catch (error) {
3001
- logger$11.error(`images.${operation}.codex.error`, { error });
3039
+ logger$12.error(`images.${operation}.codex.error`, { error });
3002
3040
  return await forwardError(c, error);
3003
3041
  }
3004
3042
  }
@@ -3994,7 +4032,7 @@ const prepareMessagesApiPayload = (payload, selectedModel) => {
3994
4032
  };
3995
4033
  //#endregion
3996
4034
  //#region src/routes/provider/messages/count-tokens-handler.ts
3997
- const logger$10 = createHandlerLogger("provider-count-tokens-handler");
4035
+ const logger$11 = createHandlerLogger("provider-count-tokens-handler");
3998
4036
  async function handleProviderCountTokens(c) {
3999
4037
  const provider = c.req.param("provider");
4000
4038
  return await handleProviderCountTokensForProvider(c, {
@@ -4017,7 +4055,7 @@ async function handleProviderCountTokensForProvider(c, options) {
4017
4055
  toolContentSupportType: modelConfig?.toolContentSupportType ?? []
4018
4056
  } : void 0), createFallbackModel(modelId));
4019
4057
  const finalTokenCount = tokenCount.input + tokenCount.output;
4020
- logger$10.debug("provider.count_tokens.success", {
4058
+ logger$11.debug("provider.count_tokens.success", {
4021
4059
  provider,
4022
4060
  model: anthropicPayload.model,
4023
4061
  input_tokens: finalTokenCount
@@ -5030,9 +5068,9 @@ const mapResponsesUsage = (response) => {
5030
5068
  ...cacheWriteTokens !== void 0 && { cache_creation_input_tokens: cacheWriteTokens }
5031
5069
  };
5032
5070
  };
5033
- const isRecord$1 = (value) => typeof value === "object" && value !== null;
5034
- const isResponseOutputText = (block) => isRecord$1(block) && "type" in block && block.type === "output_text";
5035
- const isResponseOutputRefusal = (block) => isRecord$1(block) && "type" in block && block.type === "refusal";
5071
+ const isRecord$3 = (value) => typeof value === "object" && value !== null;
5072
+ const isResponseOutputText = (block) => isRecord$3(block) && "type" in block && block.type === "output_text";
5073
+ const isResponseOutputRefusal = (block) => isRecord$3(block) && "type" in block && block.type === "refusal";
5036
5074
  const convertToolResultContent = (content) => {
5037
5075
  if (typeof content === "string") return content;
5038
5076
  if (Array.isArray(content)) {
@@ -6116,6 +6154,7 @@ const CODEX_MODELS = [
6116
6154
  }
6117
6155
  ];
6118
6156
  const CODEX_MODELS_URL = `${CODEX_API_BASE_URL}/codex/models`;
6157
+ const CODEX_MODELS_TIMEOUT_MS = 15e3;
6119
6158
  function resolveCodexModelsUrl(requestUrl) {
6120
6159
  const upstreamUrl = new URL(CODEX_MODELS_URL);
6121
6160
  upstreamUrl.search = new URL(requestUrl, "http://localhost").search;
@@ -6126,7 +6165,8 @@ async function forwardCodexModels(requestUrl, requestHeaders) {
6126
6165
  if (!headers.has("accept")) headers.set("accept", "application/json");
6127
6166
  return await fetch(resolveCodexModelsUrl(requestUrl), {
6128
6167
  method: "GET",
6129
- headers
6168
+ headers,
6169
+ signal: AbortSignal.timeout(CODEX_MODELS_TIMEOUT_MS)
6130
6170
  });
6131
6171
  }
6132
6172
  function normalizeCodexModel(model) {
@@ -6175,7 +6215,7 @@ function getModels() {
6175
6215
  }
6176
6216
  //#endregion
6177
6217
  //#region src/routes/provider/messages/handler.ts
6178
- const logger$9 = createHandlerLogger("provider-messages-handler");
6218
+ const logger$10 = createHandlerLogger("provider-messages-handler");
6179
6219
  async function handleProviderMessages(c) {
6180
6220
  const provider = c.req.param("provider");
6181
6221
  const payload = await c.req.json();
@@ -6190,7 +6230,7 @@ async function handleProviderMessages(c) {
6190
6230
  });
6191
6231
  }
6192
6232
  async function handleProviderMessagesForProvider(c, options) {
6193
- const { payload, provider } = options;
6233
+ const { payload, provider, usageEndpoint } = options;
6194
6234
  const providerConfig = await resolveProviderConfig(provider);
6195
6235
  if (!providerConfig) return c.json({ error: {
6196
6236
  message: `Provider '${provider}' not found or disabled`,
@@ -6199,7 +6239,7 @@ async function handleProviderMessagesForProvider(c, options) {
6199
6239
  try {
6200
6240
  const modelConfig = providerConfig.models?.[payload.model];
6201
6241
  const effectiveType = resolveEffectiveProviderType(providerConfig, payload.model);
6202
- debugJson(logger$9, "provider.messages.request", {
6242
+ debugJson(logger$10, "provider.messages.request", {
6203
6243
  payload,
6204
6244
  provider
6205
6245
  });
@@ -6211,7 +6251,8 @@ async function handleProviderMessagesForProvider(c, options) {
6211
6251
  modelConfig,
6212
6252
  payload,
6213
6253
  provider,
6214
- providerConfig
6254
+ providerConfig,
6255
+ usageEndpoint
6215
6256
  });
6216
6257
  stripWebSearchServerTool(payload);
6217
6258
  }
@@ -6219,7 +6260,8 @@ async function handleProviderMessagesForProvider(c, options) {
6219
6260
  modelConfig,
6220
6261
  payload,
6221
6262
  provider,
6222
- providerConfig
6263
+ providerConfig,
6264
+ usageEndpoint
6223
6265
  });
6224
6266
  }
6225
6267
  if (effectiveType === "openai-compatible") {
@@ -6228,11 +6270,12 @@ async function handleProviderMessagesForProvider(c, options) {
6228
6270
  modelConfig,
6229
6271
  payload,
6230
6272
  provider,
6231
- providerConfig
6273
+ providerConfig,
6274
+ usageEndpoint
6232
6275
  });
6233
6276
  }
6234
6277
  applyMissingExtraBody(payload, { extraBody: modelConfig?.extraBody });
6235
- debugJson(logger$9, "Translated provider.messages.request", {
6278
+ debugJson(logger$10, "Translated provider.messages.request", {
6236
6279
  payload,
6237
6280
  provider
6238
6281
  });
@@ -6242,7 +6285,7 @@ async function handleProviderMessagesForProvider(c, options) {
6242
6285
  authType: resolveProviderAuthType(providerConfig.name, void 0, effectiveType)
6243
6286
  }, payload, c.req.raw.headers);
6244
6287
  if (!upstreamResponse.ok) {
6245
- logger$9.error("Failed to create responses", upstreamResponse);
6288
+ logger$10.error("Failed to create responses", upstreamResponse);
6246
6289
  throw new HTTPError("Failed to create responses", upstreamResponse);
6247
6290
  }
6248
6291
  const contentType = upstreamResponse.headers.get("content-type") ?? "";
@@ -6252,17 +6295,19 @@ async function handleProviderMessagesForProvider(c, options) {
6252
6295
  payload,
6253
6296
  pricingCurrency: providerConfig.pricingCurrency,
6254
6297
  provider,
6255
- upstreamResponse
6298
+ upstreamResponse,
6299
+ usageEndpoint
6256
6300
  });
6257
6301
  return respondProviderMessagesJson(c, {
6258
6302
  body: await upstreamResponse.json(),
6259
6303
  modelConfig,
6260
6304
  payload,
6261
6305
  pricingCurrency: providerConfig.pricingCurrency,
6262
- provider
6306
+ provider,
6307
+ usageEndpoint
6263
6308
  });
6264
6309
  } catch (error) {
6265
- logger$9.error("provider.messages.error", {
6310
+ logger$10.error("provider.messages.error", {
6266
6311
  provider,
6267
6312
  error
6268
6313
  });
@@ -6270,9 +6315,9 @@ async function handleProviderMessagesForProvider(c, options) {
6270
6315
  }
6271
6316
  }
6272
6317
  const handleOpenAIResponsesProviderWebSearchMessages = async (c, options) => {
6273
- const { modelConfig, payload, provider, providerConfig } = options;
6318
+ const { modelConfig, payload, provider, providerConfig, usageEndpoint } = options;
6274
6319
  const responsesPayload = prepareWebSearchResponsesPayload(payload);
6275
- debugJson(logger$9, "provider.messages.responses.web_search.request", {
6320
+ debugJson(logger$10, "provider.messages.responses.web_search.request", {
6276
6321
  payload: responsesPayload,
6277
6322
  provider
6278
6323
  });
@@ -6283,24 +6328,26 @@ const handleOpenAIResponsesProviderWebSearchMessages = async (c, options) => {
6283
6328
  errorMessagePrefix: `${provider} web search responses stream`,
6284
6329
  parseEvent: (data) => parseResponsesProviderStreamChunk(data, providerConfig),
6285
6330
  upstreamResponse,
6286
- logger: logger$9
6331
+ logger: logger$10
6287
6332
  }),
6288
6333
  modelConfig,
6289
6334
  payload,
6290
6335
  pricingCurrency: providerConfig.pricingCurrency,
6291
- provider
6336
+ provider,
6337
+ usageEndpoint
6292
6338
  });
6293
6339
  return respondWebSearchProviderMessagesJson(c, {
6294
6340
  body: upstreamResponse,
6295
6341
  modelConfig,
6296
6342
  payload,
6297
6343
  pricingCurrency: providerConfig.pricingCurrency,
6298
- provider
6344
+ provider,
6345
+ usageEndpoint
6299
6346
  });
6300
6347
  }
6301
6348
  const upstreamResponse = await forwardProviderResponses(providerConfig, responsesPayload, c.req.raw.headers);
6302
6349
  if (!upstreamResponse.ok) {
6303
- logger$9.error("Failed to create provider web search responses", {
6350
+ logger$10.error("Failed to create provider web search responses", {
6304
6351
  provider,
6305
6352
  upstreamResponse
6306
6353
  });
@@ -6311,29 +6358,31 @@ const handleOpenAIResponsesProviderWebSearchMessages = async (c, options) => {
6311
6358
  errorMessagePrefix: `${provider} web search responses stream`,
6312
6359
  parseEvent: (data) => parseResponsesProviderStreamChunk(data, providerConfig),
6313
6360
  upstreamResponse: events(upstreamResponse),
6314
- logger: logger$9
6361
+ logger: logger$10
6315
6362
  }),
6316
6363
  modelConfig,
6317
6364
  payload,
6318
6365
  pricingCurrency: providerConfig.pricingCurrency,
6319
- provider
6366
+ provider,
6367
+ usageEndpoint
6320
6368
  });
6321
6369
  return respondWebSearchProviderMessagesJson(c, {
6322
6370
  body: await upstreamResponse.json(),
6323
6371
  modelConfig,
6324
6372
  payload,
6325
6373
  pricingCurrency: providerConfig.pricingCurrency,
6326
- provider
6374
+ provider,
6375
+ usageEndpoint
6327
6376
  });
6328
6377
  };
6329
6378
  const handleOpenAIResponsesProviderMessages = async (c, options) => {
6330
- const { modelConfig, payload, provider, providerConfig } = options;
6379
+ const { modelConfig, payload, provider, providerConfig, usageEndpoint } = options;
6331
6380
  const selectedModel = providerConfig.name === "codex" ? getModels().data.find((model) => model.id === payload.model) : void 0;
6332
6381
  const wantsStream = payload.stream === true;
6333
6382
  const responsesPayload = translateAnthropicMessagesToResponsesPayload(payload);
6334
6383
  if (providerConfig.name === "codex" && !wantsStream) responsesPayload.stream = true;
6335
6384
  if (applyResponsesApiContextManagement(responsesPayload, selectedModel?.capabilities.limits.max_prompt_tokens, { source: "messages" })) compactInputByLatestCompaction(responsesPayload);
6336
- debugJson(logger$9, "provider.messages.responses.request", {
6385
+ debugJson(logger$10, "provider.messages.responses.request", {
6337
6386
  payload: responsesPayload,
6338
6387
  provider
6339
6388
  });
@@ -6347,20 +6396,22 @@ const handleOpenAIResponsesProviderMessages = async (c, options) => {
6347
6396
  pricingCurrency: providerConfig.pricingCurrency,
6348
6397
  provider,
6349
6398
  providerConfig,
6350
- upstreamResponse
6399
+ upstreamResponse,
6400
+ usageEndpoint
6351
6401
  });
6352
6402
  return respondResponsesProviderMessagesJson(c, {
6353
6403
  body: await collectResponsesStreamResult({
6354
6404
  errorMessagePrefix: `${provider} messages responses stream`,
6355
6405
  parseEvent: (data) => parseResponsesProviderStreamChunk(data, providerConfig),
6356
6406
  upstreamResponse,
6357
- logger: logger$9
6407
+ logger: logger$10
6358
6408
  }),
6359
6409
  modelConfig,
6360
6410
  payload,
6361
6411
  pricingCurrency: providerConfig.pricingCurrency,
6362
6412
  provider,
6363
- providerConfig
6413
+ providerConfig,
6414
+ usageEndpoint
6364
6415
  });
6365
6416
  }
6366
6417
  return respondResponsesProviderMessagesJson(c, {
@@ -6369,12 +6420,13 @@ const handleOpenAIResponsesProviderMessages = async (c, options) => {
6369
6420
  payload,
6370
6421
  pricingCurrency: providerConfig.pricingCurrency,
6371
6422
  provider,
6372
- providerConfig
6423
+ providerConfig,
6424
+ usageEndpoint
6373
6425
  });
6374
6426
  }
6375
6427
  const upstreamResponse = await forwardProviderResponses(providerConfig, responsesPayload, c.req.raw.headers);
6376
6428
  if (!upstreamResponse.ok) {
6377
- logger$9.error("Failed to create provider responses", upstreamResponse);
6429
+ logger$10.error("Failed to create provider responses", upstreamResponse);
6378
6430
  throw new HTTPError("Failed to create provider responses", upstreamResponse);
6379
6431
  }
6380
6432
  if (responsesPayload.stream) return streamResponsesProviderMessages({
@@ -6384,7 +6436,8 @@ const handleOpenAIResponsesProviderMessages = async (c, options) => {
6384
6436
  pricingCurrency: providerConfig.pricingCurrency,
6385
6437
  provider,
6386
6438
  providerConfig,
6387
- upstreamResponse: events(upstreamResponse)
6439
+ upstreamResponse: events(upstreamResponse),
6440
+ usageEndpoint
6388
6441
  });
6389
6442
  return respondResponsesProviderMessagesJson(c, {
6390
6443
  body: await upstreamResponse.json(),
@@ -6392,7 +6445,8 @@ const handleOpenAIResponsesProviderMessages = async (c, options) => {
6392
6445
  payload,
6393
6446
  pricingCurrency: providerConfig.pricingCurrency,
6394
6447
  provider,
6395
- providerConfig
6448
+ providerConfig,
6449
+ usageEndpoint
6396
6450
  });
6397
6451
  };
6398
6452
  const getRequestThinkingBudget = (payload) => {
@@ -6415,15 +6469,15 @@ const applyOpenAICompatibleExtraBodyThinkingBudget = (payload, options) => {
6415
6469
  rawPayload.thinking_budget = extraBody.thinking_budget;
6416
6470
  };
6417
6471
  const handleOpenAICompatibleProviderMessages = async (c, options) => {
6418
- const { modelConfig, payload, provider, providerConfig } = options;
6472
+ const { modelConfig, payload, provider, providerConfig, usageEndpoint } = options;
6419
6473
  const openAIPayload = createOpenAICompatiblePayload(payload, modelConfig, providerConfig);
6420
- debugJson(logger$9, "provider.messages.openai_compatible.request", {
6474
+ debugJson(logger$10, "provider.messages.openai_compatible.request", {
6421
6475
  payload: openAIPayload,
6422
6476
  provider
6423
6477
  });
6424
6478
  const upstreamResponse = await forwardProviderChatCompletions(providerConfig, openAIPayload, c.req.raw.headers);
6425
6479
  if (!upstreamResponse.ok) {
6426
- logger$9.error("Failed to create openai-compatible responses", upstreamResponse);
6480
+ logger$10.error("Failed to create openai-compatible responses", upstreamResponse);
6427
6481
  throw new HTTPError("Failed to create openai-compatible responses", upstreamResponse);
6428
6482
  }
6429
6483
  const contentType = upstreamResponse.headers.get("content-type") ?? "";
@@ -6433,14 +6487,16 @@ const handleOpenAICompatibleProviderMessages = async (c, options) => {
6433
6487
  payload,
6434
6488
  pricingCurrency: providerConfig.pricingCurrency,
6435
6489
  provider,
6436
- upstreamResponse
6490
+ upstreamResponse,
6491
+ usageEndpoint
6437
6492
  });
6438
6493
  return respondOpenAICompatibleProviderMessagesJson(c, {
6439
6494
  body: await upstreamResponse.json(),
6440
6495
  modelConfig,
6441
6496
  payload,
6442
6497
  pricingCurrency: providerConfig.pricingCurrency,
6443
- provider
6498
+ provider,
6499
+ usageEndpoint
6444
6500
  });
6445
6501
  };
6446
6502
  const createOpenAICompatiblePayload = (payload, modelConfig, providerConfig) => {
@@ -6477,9 +6533,9 @@ const applyOpenAICompatibleRequestOverrides = (payload, options) => {
6477
6533
  const allowedKeys = new Set(Object.keys(options.extraBody ?? {}));
6478
6534
  for (const key of allowedKeys) if (Object.hasOwn(options.source, key)) payload[key] = options.source[key];
6479
6535
  };
6480
- const streamProviderMessages = ({ c, modelConfig, payload, pricingCurrency, provider, upstreamResponse }) => {
6481
- logger$9.debug("provider.messages.streaming");
6482
- const recordUsage = createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency);
6536
+ const streamProviderMessages = ({ c, modelConfig, payload, pricingCurrency, provider, upstreamResponse, usageEndpoint }) => {
6537
+ logger$10.debug("provider.messages.streaming");
6538
+ const recordUsage = createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency, usageEndpoint);
6483
6539
  return streamSSE(c, async (stream) => {
6484
6540
  let usage = {};
6485
6541
  const openRouterThinkingState = {
@@ -6487,7 +6543,7 @@ const streamProviderMessages = ({ c, modelConfig, payload, pricingCurrency, prov
6487
6543
  thinkingBlockIndexes: /* @__PURE__ */ new Set()
6488
6544
  };
6489
6545
  for await (const chunk of events(upstreamResponse)) {
6490
- logger$9.debug("provider.messages.raw_stream_event:", chunk.data);
6546
+ logger$10.debug("provider.messages.raw_stream_event:", chunk.data);
6491
6547
  const eventName = chunk.event;
6492
6548
  if (eventName === "ping") {
6493
6549
  await stream.writeSSE({
@@ -6516,9 +6572,9 @@ const streamProviderMessages = ({ c, modelConfig, payload, pricingCurrency, prov
6516
6572
  recordUsage(usage);
6517
6573
  });
6518
6574
  };
6519
- const streamOpenAICompatibleProviderMessages = ({ c, modelConfig, payload, pricingCurrency, provider, upstreamResponse }) => {
6520
- logger$9.debug("provider.messages.openai_compatible.streaming");
6521
- const recordUsage = createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency);
6575
+ const streamOpenAICompatibleProviderMessages = ({ c, modelConfig, payload, pricingCurrency, provider, upstreamResponse, usageEndpoint }) => {
6576
+ logger$10.debug("provider.messages.openai_compatible.streaming");
6577
+ const recordUsage = createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency, usageEndpoint);
6522
6578
  return streamSSE(c, async (stream) => {
6523
6579
  let usage = {};
6524
6580
  const streamState = {
@@ -6529,7 +6585,7 @@ const streamOpenAICompatibleProviderMessages = ({ c, modelConfig, payload, prici
6529
6585
  thinkingBlockOpen: false
6530
6586
  };
6531
6587
  for await (const chunk of events(upstreamResponse)) {
6532
- logger$9.debug("provider.messages.openai_compatible.raw_stream_event:", chunk.data);
6588
+ logger$10.debug("provider.messages.openai_compatible.raw_stream_event:", chunk.data);
6533
6589
  if (chunk.event === "ping") {
6534
6590
  await stream.writeSSE({
6535
6591
  event: "ping",
@@ -6547,7 +6603,7 @@ const streamOpenAICompatibleProviderMessages = ({ c, modelConfig, payload, prici
6547
6603
  const events = translateChunkToAnthropicEvents(parsed, streamState);
6548
6604
  for (const event of events) {
6549
6605
  const eventData = JSON.stringify(event);
6550
- debugLazy(logger$9, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6606
+ debugLazy(logger$10, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6551
6607
  await stream.writeSSE({
6552
6608
  event: event.type,
6553
6609
  data: eventData
@@ -6556,7 +6612,7 @@ const streamOpenAICompatibleProviderMessages = ({ c, modelConfig, payload, prici
6556
6612
  }
6557
6613
  for (const event of flushPendingAnthropicStreamEvents(streamState)) {
6558
6614
  const eventData = JSON.stringify(event);
6559
- debugLazy(logger$9, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6615
+ debugLazy(logger$10, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6560
6616
  await stream.writeSSE({
6561
6617
  event: event.type,
6562
6618
  data: eventData
@@ -6565,14 +6621,14 @@ const streamOpenAICompatibleProviderMessages = ({ c, modelConfig, payload, prici
6565
6621
  recordUsage(usage);
6566
6622
  });
6567
6623
  };
6568
- const streamResponsesProviderMessages = ({ c, modelConfig, payload, pricingCurrency, provider, providerConfig, upstreamResponse }) => {
6569
- logger$9.debug("provider.messages.responses.streaming", { provider });
6570
- const recordUsage = createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency);
6624
+ const streamResponsesProviderMessages = ({ c, modelConfig, payload, pricingCurrency, provider, providerConfig, upstreamResponse, usageEndpoint }) => {
6625
+ logger$10.debug("provider.messages.responses.streaming", { provider });
6626
+ const recordUsage = createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency, usageEndpoint);
6571
6627
  return streamSSE(c, async (stream) => {
6572
6628
  let usage = {};
6573
6629
  const streamState = createResponsesStreamState({ toolSearchName: resolveBridgeToolSearchName(payload.tools) });
6574
6630
  for await (const chunk of upstreamResponse) {
6575
- logger$9.debug("provider.messages.responses.raw_stream_event:", chunk.data);
6631
+ logger$10.debug("provider.messages.responses.raw_stream_event:", chunk.data);
6576
6632
  if (chunk.event === "ping") {
6577
6633
  await stream.writeSSE({
6578
6634
  event: "ping",
@@ -6590,7 +6646,7 @@ const streamResponsesProviderMessages = ({ c, modelConfig, payload, pricingCurre
6590
6646
  const events = translateResponsesStreamEvent(parsed, streamState);
6591
6647
  for (const event of events) {
6592
6648
  const eventData = JSON.stringify(event);
6593
- debugLazy(logger$9, () => ["provider.messages.responses.translated_event:", eventData]);
6649
+ debugLazy(logger$10, () => ["provider.messages.responses.translated_event:", eventData]);
6594
6650
  await stream.writeSSE({
6595
6651
  event: event.type,
6596
6652
  data: eventData
@@ -6611,7 +6667,7 @@ const parseOpenAICompatibleStreamChunk = (data) => {
6611
6667
  try {
6612
6668
  return JSON.parse(data);
6613
6669
  } catch (error) {
6614
- logger$9.error("provider.messages.openai_compatible.parse_chunk_error", {
6670
+ logger$10.error("provider.messages.openai_compatible.parse_chunk_error", {
6615
6671
  data,
6616
6672
  error
6617
6673
  });
@@ -6624,7 +6680,7 @@ const parseResponsesProviderStreamChunk = (data, providerConfig) => {
6624
6680
  if (providerConfig.name === "codex") logCodexRateLimitsEvent(parsed);
6625
6681
  return parsed;
6626
6682
  } catch (error) {
6627
- logger$9.error("provider.messages.responses.parse_chunk_error", {
6683
+ logger$10.error("provider.messages.responses.parse_chunk_error", {
6628
6684
  provider: providerConfig.name,
6629
6685
  data,
6630
6686
  error
@@ -6649,7 +6705,7 @@ const parseProviderStreamEvent = (data) => {
6649
6705
  usage: {}
6650
6706
  };
6651
6707
  } catch (error) {
6652
- logger$9.error("provider.messages.streaming.adjust_tokens_error", {
6708
+ logger$10.error("provider.messages.streaming.adjust_tokens_error", {
6653
6709
  error,
6654
6710
  originalData: data
6655
6711
  });
@@ -6708,37 +6764,37 @@ const normalizeOpenRouterStreamEvents = (eventName, data, state) => {
6708
6764
  }];
6709
6765
  };
6710
6766
  const respondProviderMessagesJson = (c, options) => {
6711
- const { body, modelConfig, payload, pricingCurrency, provider } = options;
6712
- createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency)(normalizeAnthropicUsage(body.usage));
6767
+ const { body, modelConfig, payload, pricingCurrency, provider, usageEndpoint } = options;
6768
+ createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency, usageEndpoint)(normalizeAnthropicUsage(body.usage));
6713
6769
  if (provider === "openrouter") normalizeOpenRouterThinkingSignatures(body);
6714
- debugJson(logger$9, "provider.messages.no_stream result:", body);
6770
+ debugJson(logger$10, "provider.messages.no_stream result:", body);
6715
6771
  return c.json(body);
6716
6772
  };
6717
6773
  const respondOpenAICompatibleProviderMessagesJson = (c, options) => {
6718
- const { body, modelConfig, payload, pricingCurrency, provider } = options;
6719
- createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency)(normalizeOpenAIUsage(body.usage));
6774
+ const { body, modelConfig, payload, pricingCurrency, provider, usageEndpoint } = options;
6775
+ createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency, usageEndpoint)(normalizeOpenAIUsage(body.usage));
6720
6776
  const anthropicResponse = translateToAnthropic(body);
6721
- debugJson(logger$9, "provider.messages.openai_compatible.no_stream result:", anthropicResponse);
6777
+ debugJson(logger$10, "provider.messages.openai_compatible.no_stream result:", anthropicResponse);
6722
6778
  return c.json(anthropicResponse);
6723
6779
  };
6724
6780
  const respondResponsesProviderMessagesJson = (c, options) => {
6725
- const { body, modelConfig, payload, pricingCurrency, provider, providerConfig } = options;
6726
- createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency)(normalizeResponsesUsage(body.usage));
6781
+ const { body, modelConfig, payload, pricingCurrency, provider, providerConfig, usageEndpoint } = options;
6782
+ createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency, usageEndpoint)(normalizeResponsesUsage(body.usage));
6727
6783
  const anthropicResponse = translateResponsesResultToAnthropic(body, { toolSearchName: resolveBridgeToolSearchName(payload.tools) });
6728
- debugJson(logger$9, "provider.messages.responses.no_stream result:", anthropicResponse);
6729
- if (providerConfig.name === "codex") logger$9.debug("provider.messages.codex.no_stream.result");
6784
+ debugJson(logger$10, "provider.messages.responses.no_stream result:", anthropicResponse);
6785
+ if (providerConfig.name === "codex") logger$10.debug("provider.messages.codex.no_stream.result");
6730
6786
  return c.json(anthropicResponse);
6731
6787
  };
6732
6788
  const respondWebSearchProviderMessagesJson = (c, options) => {
6733
- const { body, modelConfig, payload, pricingCurrency, provider } = options;
6734
- createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency)(normalizeResponsesUsage(body.usage));
6789
+ const { body, modelConfig, payload, pricingCurrency, provider, usageEndpoint } = options;
6790
+ createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency, usageEndpoint)(normalizeResponsesUsage(body.usage));
6735
6791
  const { extract, response } = reconstructWebSearchResponse(payload, body, { requestId: body.id || `${provider}:${payload.model}` });
6736
- debugJson(logger$9, `Web search via responses: ${extract.queries.length} quer(y/ies), ${extract.sources.length} source(s)`, body);
6792
+ debugJson(logger$10, `Web search via responses: ${extract.queries.length} quer(y/ies), ${extract.sources.length} source(s)`, body);
6737
6793
  if (!payload.stream) return c.json(response);
6738
6794
  return streamSSE(c, async (stream) => {
6739
6795
  for (const event of buildSyntheticStreamEvents(response)) {
6740
6796
  const data = JSON.stringify(event);
6741
- logger$9.debug(`Web search stream event`, data);
6797
+ logger$10.debug(`Web search stream event`, data);
6742
6798
  await stream.writeSSE({
6743
6799
  event: event.type,
6744
6800
  data
@@ -6746,8 +6802,8 @@ const respondWebSearchProviderMessagesJson = (c, options) => {
6746
6802
  }
6747
6803
  });
6748
6804
  };
6749
- const createProviderMessagesUsageRecorder = (payload, provider, modelConfig, pricingCurrency) => createProviderTokenUsageRecorder({
6750
- endpoint: "provider_messages",
6805
+ const createProviderMessagesUsageRecorder = (payload, provider, modelConfig, pricingCurrency, endpoint = "provider_messages") => createProviderTokenUsageRecorder({
6806
+ endpoint,
6751
6807
  model: payload.model,
6752
6808
  pricing: modelConfig?.pricing,
6753
6809
  pricingCurrency,
@@ -6822,7 +6878,7 @@ const handleWithChatCompletions = async (c, anthropicPayload, options) => {
6822
6878
  });
6823
6879
  prepareCopilotChatCompletionsPayload(openAIPayload);
6824
6880
  const recordUsage = createCopilotUsageRecorder({
6825
- endpoint: "chat_completions",
6881
+ endpoint: options.usageEndpoint ?? "chat_completions",
6826
6882
  fallbackSessionId: sessionId,
6827
6883
  model: openAIPayload.model,
6828
6884
  payload: anthropicPayload
@@ -6888,7 +6944,7 @@ const handleWithResponsesApi = async (c, anthropicPayload, options) => {
6888
6944
  const { logger, selectedModel, ...requestOptions } = options;
6889
6945
  const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, requestOptions.subagentMarker?.agent_id);
6890
6946
  const recordUsage = createCopilotUsageRecorder({
6891
- endpoint: "responses",
6947
+ endpoint: options.usageEndpoint ?? "responses",
6892
6948
  fallbackSessionId: requestOptions.sessionId,
6893
6949
  model: responsesPayload.model,
6894
6950
  payload: anthropicPayload
@@ -6963,7 +7019,7 @@ const handleWithMessagesApi = async (c, anthropicPayload, options) => {
6963
7019
  const { logger, anthropicBetaHeader, subagentMarker, selectedModel, requestId, sessionId, compactType } = options;
6964
7020
  prepareMessagesApiPayload(anthropicPayload, selectedModel);
6965
7021
  const recordUsage = createCopilotUsageRecorder({
6966
- endpoint: "messages",
7022
+ endpoint: options.usageEndpoint ?? "messages",
6967
7023
  fallbackSessionId: sessionId,
6968
7024
  model: anthropicPayload.model,
6969
7025
  payload: anthropicPayload
@@ -7096,27 +7152,31 @@ const parseSubagentMarkerFromSystemReminder = (text) => {
7096
7152
  };
7097
7153
  //#endregion
7098
7154
  //#region src/routes/messages/handler.ts
7099
- const logger$8 = createHandlerLogger("messages-handler");
7155
+ const logger$9 = createHandlerLogger("messages-handler");
7100
7156
  const messagesFlowHandlers = {
7101
7157
  handleWithChatCompletions,
7102
7158
  handleWithMessagesApi,
7103
7159
  handleWithResponsesApi
7104
7160
  };
7105
7161
  async function handleCompletion(c) {
7106
- const anthropicPayload = await c.req.json();
7162
+ return await handleCompletionPayload(c, await c.req.json());
7163
+ }
7164
+ async function handleCompletionPayload(c, anthropicPayload, dispatchOptions = {}) {
7107
7165
  const requestedModel = anthropicPayload.model;
7108
- anthropicPayload.model = resolveMappedModel(anthropicPayload.model);
7166
+ if (!dispatchOptions.skipModelMapping) anthropicPayload.model = resolveMappedModel(anthropicPayload.model);
7109
7167
  if (anthropicPayload.model !== requestedModel) consola.debug(`Resolved model mapping: ${requestedModel} -> ${anthropicPayload.model}`);
7110
- const webSearchResult = await tryHandleWebSearch(c, anthropicPayload, {
7111
- logger: logger$8,
7112
- forwardToProvider: (ctx, payload, provider) => handleProviderMessagesForProvider(ctx, {
7113
- payload,
7114
- provider
7115
- })
7116
- });
7117
- if (webSearchResult) return webSearchResult;
7168
+ if (!dispatchOptions.skipWebSearch) {
7169
+ const webSearchResult = await tryHandleWebSearch(c, anthropicPayload, {
7170
+ logger: logger$9,
7171
+ forwardToProvider: (ctx, payload, provider) => handleProviderMessagesForProvider(ctx, {
7172
+ payload,
7173
+ provider
7174
+ })
7175
+ });
7176
+ if (webSearchResult) return webSearchResult;
7177
+ }
7118
7178
  const claudeAutoModel = getClaudeAutoModel();
7119
- const shouldUseClaudeAutoModel = Boolean(claudeAutoModel && isClaudeAutoModelRequest(anthropicPayload));
7179
+ const shouldUseClaudeAutoModel = Boolean(!dispatchOptions.skipClaudeAutoModel && claudeAutoModel && isClaudeAutoModelRequest(anthropicPayload));
7120
7180
  if (claudeAutoModel && shouldUseClaudeAutoModel) {
7121
7181
  consola.debug(`Claude auto model override: ${anthropicPayload.model} -> ${claudeAutoModel}`);
7122
7182
  anthropicPayload.model = claudeAutoModel;
@@ -7126,24 +7186,25 @@ async function handleCompletion(c) {
7126
7186
  anthropicPayload.model = providerModelAlias.model;
7127
7187
  return await handleProviderMessagesForProvider(c, {
7128
7188
  payload: anthropicPayload,
7129
- provider: providerModelAlias.provider
7189
+ provider: providerModelAlias.provider,
7190
+ usageEndpoint: dispatchOptions.usageEndpoint
7130
7191
  });
7131
7192
  }
7132
- debugJson(logger$8, "Anthropic request payload:", anthropicPayload);
7193
+ debugJson(logger$9, "Anthropic request payload:", anthropicPayload);
7133
7194
  normalizeSystemMessages(anthropicPayload);
7134
7195
  sanitizeIdeTools(anthropicPayload);
7135
7196
  const subagentMarker = parseSubagentMarkerFromFirstUser(anthropicPayload);
7136
- if (subagentMarker) debugJson(logger$8, "Detected Subagent marker:", subagentMarker);
7197
+ if (subagentMarker) debugJson(logger$9, "Detected Subagent marker:", subagentMarker);
7137
7198
  let sessionId = getRootSessionId(anthropicPayload, c);
7138
- const compactType = getCompactType(anthropicPayload);
7199
+ const compactType = dispatchOptions.compactType ?? getCompactType(anthropicPayload);
7139
7200
  const anthropicBeta = c.req.header("anthropic-beta");
7140
- logger$8.debug("Anthropic Beta header:", anthropicBeta);
7201
+ logger$9.debug("Anthropic Beta header:", anthropicBeta);
7141
7202
  if (!state.tokenBasedBilling && !shouldUseClaudeAutoModel) {
7142
7203
  const tools = anthropicPayload.tools;
7143
7204
  const noTools = !tools || tools.length === 0;
7144
7205
  if (anthropicBeta && noTools && compactType === 0) anthropicPayload.model = getSmallModel();
7145
7206
  }
7146
- if (compactType) logger$8.debug("Compact request type:", compactType);
7207
+ if (compactType) logger$9.debug("Compact request type:", compactType);
7147
7208
  if (!state.tokenBasedBilling) {
7148
7209
  const lastMessageCacheControl = getLastMessageContentCacheControl(anthropicPayload.messages.at(-1));
7149
7210
  stripToolReferenceTurnBoundary(anthropicPayload);
@@ -7151,9 +7212,9 @@ async function handleCompletion(c) {
7151
7212
  applyLastMessageCacheControl(anthropicPayload, lastMessageCacheControl);
7152
7213
  }
7153
7214
  const requestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
7154
- logger$8.debug("Generated request ID:", requestId);
7215
+ logger$9.debug("Generated request ID:", requestId);
7155
7216
  if (!sessionId) sessionId = getUUID(requestId);
7156
- logger$8.debug("Extracted session ID:", sessionId);
7217
+ logger$9.debug("Extracted session ID:", sessionId);
7157
7218
  const selectedModel = findEndpointModel(anthropicPayload.model);
7158
7219
  anthropicPayload.model = selectedModel?.id ?? anthropicPayload.model;
7159
7220
  if (shouldUseMessagesApi(selectedModel)) return await messagesFlowHandlers.handleWithMessagesApi(c, anthropicPayload, {
@@ -7163,7 +7224,8 @@ async function handleCompletion(c) {
7163
7224
  requestId,
7164
7225
  sessionId,
7165
7226
  compactType,
7166
- logger: logger$8
7227
+ logger: logger$9,
7228
+ usageEndpoint: dispatchOptions.usageEndpoint
7167
7229
  });
7168
7230
  if (shouldUseResponsesApi(selectedModel, compactType)) return await messagesFlowHandlers.handleWithResponsesApi(c, anthropicPayload, {
7169
7231
  subagentMarker,
@@ -7171,7 +7233,8 @@ async function handleCompletion(c) {
7171
7233
  requestId,
7172
7234
  sessionId,
7173
7235
  compactType,
7174
- logger: logger$8
7236
+ logger: logger$9,
7237
+ usageEndpoint: dispatchOptions.usageEndpoint
7175
7238
  });
7176
7239
  return await messagesFlowHandlers.handleWithChatCompletions(c, anthropicPayload, {
7177
7240
  subagentMarker,
@@ -7179,16 +7242,17 @@ async function handleCompletion(c) {
7179
7242
  requestId,
7180
7243
  sessionId,
7181
7244
  compactType,
7182
- logger: logger$8
7245
+ logger: logger$9,
7246
+ usageEndpoint: dispatchOptions.usageEndpoint
7183
7247
  });
7184
7248
  }
7185
- const MESSAGES_ENDPOINT = "/v1/messages";
7249
+ const MESSAGES_ENDPOINT$1 = "/v1/messages";
7186
7250
  const shouldUseResponsesApi = (selectedModel, compactType) => {
7187
7251
  return Boolean(getResponsesTransportForModel(selectedModel, { compactType }));
7188
7252
  };
7189
7253
  const shouldUseMessagesApi = (selectedModel) => {
7190
7254
  if (!isMessagesApiEnabled()) return false;
7191
- return selectedModel?.supported_endpoints?.includes(MESSAGES_ENDPOINT) ?? false;
7255
+ return selectedModel?.supported_endpoints?.includes(MESSAGES_ENDPOINT$1) ?? false;
7192
7256
  };
7193
7257
  //#endregion
7194
7258
  //#region src/routes/messages/route.ts
@@ -7209,20 +7273,49 @@ messageRoutes.post("/count_tokens", async (c) => {
7209
7273
  });
7210
7274
  //#endregion
7211
7275
  //#region src/routes/models/codex-models.ts
7212
- const logger$7 = createHandlerLogger("codex-models-handler");
7276
+ const logger$8 = createHandlerLogger("codex-models-handler");
7213
7277
  const CODEX_USER_AGENT_PATTERN = /^codex/iu;
7278
+ const FALLBACK_BASE_INSTRUCTIONS = "You are a coding agent. Follow the user's instructions, inspect the workspace as needed, use the available tools carefully, and continue until the task is complete.";
7279
+ const FALLBACK_AVAILABLE_IN_PLANS = [
7280
+ "business",
7281
+ "edu",
7282
+ "edu_plus",
7283
+ "edu_pro",
7284
+ "education",
7285
+ "enterprise",
7286
+ "enterprise_cbp_automation",
7287
+ "enterprise_cbp_usage_based",
7288
+ "finserv",
7289
+ "free",
7290
+ "free_workspace",
7291
+ "go",
7292
+ "hc",
7293
+ "k12",
7294
+ "plus",
7295
+ "pro",
7296
+ "prolite",
7297
+ "quorum",
7298
+ "sci",
7299
+ "self_serve_business_usage_based",
7300
+ "team"
7301
+ ];
7302
+ const DEFAULT_REASONING_EFFORTS = [
7303
+ "high",
7304
+ "xhigh",
7305
+ "max"
7306
+ ];
7214
7307
  function isCodexUserAgent(userAgent) {
7215
7308
  return CODEX_USER_AGENT_PATTERN.test(userAgent?.trim() ?? "");
7216
7309
  }
7217
7310
  async function logCodexModelsResponse(response) {
7218
7311
  try {
7219
7312
  const models = await response.clone().json();
7220
- debugJson(logger$7, "models.codex.response", {
7313
+ debugJson(logger$8, "models.codex.response", {
7221
7314
  statusCode: response.status,
7222
7315
  models
7223
7316
  });
7224
7317
  } catch (error) {
7225
- logger$7.warn("models.codex.response_log_error", { error });
7318
+ logger$8.warn("models.codex.response_log_error", { error });
7226
7319
  }
7227
7320
  }
7228
7321
  /**
@@ -7240,12 +7333,129 @@ async function handleCodexModelsProxy(c, resolvedProviderConfig) {
7240
7333
  await logCodexModelsResponse(upstreamResponse);
7241
7334
  return createProviderProxyResponse(upstreamResponse);
7242
7335
  }
7336
+ async function handleMergedCodexModels(c, candidatesRequest) {
7337
+ const [upstreamCatalog, candidates] = await Promise.all([tryGetCodexCatalog(c), Promise.resolve(candidatesRequest).catch((error) => {
7338
+ logger$8.warn("models.codex.candidates_error", { error });
7339
+ return [];
7340
+ })]);
7341
+ const upstreamModels = upstreamCatalog?.models ?? [];
7342
+ const template = selectTemplate(upstreamModels);
7343
+ const seenSlugs = new Set(upstreamModels.map((model) => model.slug));
7344
+ const syntheticModels = candidates.filter((candidate) => !seenSlugs.has(candidate.slug)).map((candidate, index) => createSyntheticCodexModel(candidate, template, upstreamModels.length + index));
7345
+ const response = {
7346
+ ...upstreamCatalog ?? {},
7347
+ models: [...upstreamModels, ...syntheticModels]
7348
+ };
7349
+ debugJson(logger$8, "models.codex.merged_response", {
7350
+ upstreamCount: upstreamModels.length,
7351
+ syntheticCount: syntheticModels.length,
7352
+ models: response
7353
+ });
7354
+ return c.json(response);
7355
+ }
7356
+ function createSyntheticCodexModel(candidate, template, priority) {
7357
+ const reasoningEfforts = candidate.reasoningEfforts.length > 0 ? candidate.reasoningEfforts : DEFAULT_REASONING_EFFORTS;
7358
+ const defaultReasoningEffort = reasoningEfforts.includes(candidate.defaultReasoningEffort) ? candidate.defaultReasoningEffort : reasoningEfforts[0];
7359
+ const supportsReasoning = reasoningEfforts.some((effort) => effort !== "none");
7360
+ const inputModalities = [...new Set(candidate.inputModalities)];
7361
+ return {
7362
+ ...template ?? {},
7363
+ slug: candidate.slug,
7364
+ display_name: candidate.displayName,
7365
+ description: candidate.description,
7366
+ priority,
7367
+ visibility: "list",
7368
+ supported_in_api: true,
7369
+ minimal_client_version: "0.0.0",
7370
+ prefer_websockets: false,
7371
+ support_verbosity: false,
7372
+ default_verbosity: "medium",
7373
+ apply_patch_tool_type: "freeform",
7374
+ web_search_tool_type: "text_and_image",
7375
+ supports_search_tool: false,
7376
+ use_responses_lite: true,
7377
+ tool_mode: "code_mode_only",
7378
+ multi_agent_version: "v1",
7379
+ shell_type: "shell_command",
7380
+ experimental_supported_tools: [],
7381
+ input_modalities: inputModalities,
7382
+ supports_image_detail_original: false,
7383
+ supports_parallel_tool_calls: candidate.supportsParallelToolCalls,
7384
+ context_window: candidate.contextWindow,
7385
+ max_context_window: candidate.contextWindow,
7386
+ max_output_tokens: candidate.maxOutputTokens,
7387
+ auto_compact_token_limit: null,
7388
+ comp_hash: null,
7389
+ effective_context_window_percent: 95,
7390
+ default_reasoning_level: defaultReasoningEffort,
7391
+ supported_reasoning_levels: reasoningEfforts.map((effort) => ({
7392
+ effort,
7393
+ description: `${effort} reasoning effort`
7394
+ })),
7395
+ supports_reasoning_summary_parameter: supportsReasoning,
7396
+ supports_reasoning_summaries: supportsReasoning,
7397
+ default_reasoning_summary: supportsReasoning ? "auto" : "none",
7398
+ reasoning_summary_format: "experimental",
7399
+ availability_nux: null,
7400
+ upgrade: null,
7401
+ available_in_plans: template?.available_in_plans ?? FALLBACK_AVAILABLE_IN_PLANS,
7402
+ model_messages: template?.model_messages ?? {
7403
+ instructions_template: FALLBACK_BASE_INSTRUCTIONS,
7404
+ instructions_variables: null,
7405
+ approvals: null,
7406
+ auto_review: null,
7407
+ permissions: null
7408
+ },
7409
+ auto_review_model_override: null,
7410
+ default_service_tier: null,
7411
+ service_tiers: [],
7412
+ additional_speed_tiers: [],
7413
+ include_skills_usage_instructions: false,
7414
+ truncation_policy: {
7415
+ mode: "tokens",
7416
+ limit: 1e4
7417
+ },
7418
+ base_instructions: template?.base_instructions?.trim() ? template.base_instructions : FALLBACK_BASE_INSTRUCTIONS
7419
+ };
7420
+ }
7421
+ async function tryGetCodexCatalog(c) {
7422
+ try {
7423
+ if (!await resolveProviderConfig("codex")) return null;
7424
+ const response = await forwardCodexModels(c.req.url, c.req.raw.headers);
7425
+ if (!response.ok) {
7426
+ logger$8.warn("models.codex.catalog_fallback", { statusCode: response.status });
7427
+ return null;
7428
+ }
7429
+ const body = await response.json();
7430
+ if (!isCodexModelsResponse(body)) {
7431
+ logger$8.warn("models.codex.catalog_invalid");
7432
+ return null;
7433
+ }
7434
+ return body;
7435
+ } catch (error) {
7436
+ logger$8.warn("models.codex.catalog_error", { error });
7437
+ return null;
7438
+ }
7439
+ }
7440
+ function selectTemplate(models) {
7441
+ return models.find((model) => model.visibility === "list" && model.supported_in_api !== false) ?? models[0];
7442
+ }
7443
+ function isCodexModelsResponse(value) {
7444
+ if (!isRecord$2(value) || !Array.isArray(value.models)) return false;
7445
+ return value.models.every((model) => isRecord$2(model) && typeof model.slug === "string");
7446
+ }
7447
+ function isRecord$2(value) {
7448
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7449
+ }
7243
7450
  //#endregion
7244
7451
  //#region src/routes/models/route.ts
7245
7452
  const modelRoutes = new Hono();
7246
- const logger$6 = createHandlerLogger("models-handler");
7453
+ const logger$7 = createHandlerLogger("models-handler");
7247
7454
  const EPOCH_ISO = (/* @__PURE__ */ new Date(0)).toISOString();
7248
- function isRecord(value) {
7455
+ const RESPONSES_ENDPOINTS = new Set(["/responses", "ws:/responses"]);
7456
+ const MESSAGES_ENDPOINT = "/v1/messages";
7457
+ const CHAT_COMPLETIONS_ENDPOINT = "/chat/completions";
7458
+ function isRecord$1(value) {
7249
7459
  return typeof value === "object" && value !== null && !Array.isArray(value);
7250
7460
  }
7251
7461
  function normalizeCopilotModel(model) {
@@ -7263,24 +7473,24 @@ function normalizeCopilotModel(model) {
7263
7473
  display_name: model.name
7264
7474
  };
7265
7475
  }
7266
- function getStringField(model, field) {
7476
+ function getStringField$1(model, field) {
7267
7477
  const value = model[field];
7268
7478
  return typeof value === "string" && value.trim() ? value : void 0;
7269
7479
  }
7270
7480
  function normalizeProviderModel(provider, model) {
7271
- if (!isRecord(model)) return null;
7272
- const rawId = getStringField(model, "id");
7481
+ if (!isRecord$1(model)) return null;
7482
+ const rawId = getStringField$1(model, "id");
7273
7483
  if (!rawId) return null;
7274
7484
  const id = `${provider}/${rawId}`;
7275
- const name = getStringField(model, "display_name") ?? getStringField(model, "name") ?? rawId;
7276
- const ownedBy = getStringField(model, "owned_by") ?? getStringField(model, "vendor") ?? provider;
7485
+ const name = getStringField$1(model, "display_name") ?? getStringField$1(model, "name") ?? rawId;
7486
+ const ownedBy = getStringField$1(model, "owned_by") ?? getStringField$1(model, "vendor") ?? provider;
7277
7487
  return {
7278
7488
  ...model,
7279
7489
  id,
7280
- object: getStringField(model, "object") ?? "model",
7281
- type: getStringField(model, "type") ?? "model",
7490
+ object: getStringField$1(model, "object") ?? "model",
7491
+ type: getStringField$1(model, "type") ?? "model",
7282
7492
  created: typeof model.created === "number" ? model.created : 0,
7283
- created_at: getStringField(model, "created_at") ?? EPOCH_ISO,
7493
+ created_at: getStringField$1(model, "created_at") ?? EPOCH_ISO,
7284
7494
  owned_by: ownedBy,
7285
7495
  display_name: name
7286
7496
  };
@@ -7292,20 +7502,20 @@ async function getProviderModels(provider, requestHeaders) {
7292
7502
  if (providerConfig.name === "codex") return getModels().data.map((model) => normalizeProviderModel(providerConfig.name, model)).filter((model) => model !== null);
7293
7503
  const response = await forwardProviderModels(providerConfig, requestHeaders);
7294
7504
  if (!response.ok) {
7295
- logger$6.warn("models.provider.skip_non_ok", {
7505
+ logger$7.warn("models.provider.skip_non_ok", {
7296
7506
  provider,
7297
7507
  statusCode: response.status
7298
7508
  });
7299
7509
  return [];
7300
7510
  }
7301
7511
  const body = await response.json();
7302
- if (!isRecord(body) || !Array.isArray(body.data)) {
7303
- logger$6.warn("models.provider.skip_invalid_body", { provider });
7512
+ if (!isRecord$1(body) || !Array.isArray(body.data)) {
7513
+ logger$7.warn("models.provider.skip_invalid_body", { provider });
7304
7514
  return [];
7305
7515
  }
7306
7516
  return body.data.map((model) => normalizeProviderModel(providerConfig.name, model)).filter((model) => model !== null);
7307
7517
  } catch (error) {
7308
- logger$6.warn("models.provider.skip_error", {
7518
+ logger$7.warn("models.provider.skip_error", {
7309
7519
  provider,
7310
7520
  error
7311
7521
  });
@@ -7323,9 +7533,178 @@ async function getAggregatedModels(requestHeaders) {
7323
7533
  return true;
7324
7534
  });
7325
7535
  }
7536
+ const CODEX_REASONING_EFFORTS = new Set([
7537
+ "none",
7538
+ "minimal",
7539
+ "low",
7540
+ "medium",
7541
+ "high",
7542
+ "xhigh",
7543
+ "max",
7544
+ "ultra"
7545
+ ]);
7546
+ async function getSyntheticCodexModels(requestHeaders) {
7547
+ const copilotModels = getCopilotCodexCandidates();
7548
+ const providerModels = (await Promise.allSettled(listEnabledProviders().map((provider) => getProviderCodexCandidates(provider, requestHeaders)))).flatMap((result) => result.status === "fulfilled" ? result.value : []);
7549
+ const seen = /* @__PURE__ */ new Set();
7550
+ return [...copilotModels, ...providerModels.flat()].filter((candidate) => {
7551
+ if (seen.has(candidate.slug)) return false;
7552
+ seen.add(candidate.slug);
7553
+ return true;
7554
+ });
7555
+ }
7556
+ function getCopilotCodexCandidates() {
7557
+ const candidates = [];
7558
+ for (const model of state.models?.data ?? []) try {
7559
+ if (isCopilotMessagesFallbackModel(model)) candidates.push(createCopilotCodexCandidate(model));
7560
+ } catch (error) {
7561
+ logger$7.warn("models.codex.copilot_skip_error", {
7562
+ modelId: model.id,
7563
+ error
7564
+ });
7565
+ }
7566
+ return candidates;
7567
+ }
7568
+ function isCopilotMessagesFallbackModel(model) {
7569
+ const endpoints = model.supported_endpoints ?? [];
7570
+ return endpoints.some((endpoint) => endpoint === MESSAGES_ENDPOINT || endpoint === CHAT_COMPLETIONS_ENDPOINT) && !endpoints.some((endpoint) => RESPONSES_ENDPOINTS.has(endpoint)) && model.capabilities.supports.tool_calls !== false;
7571
+ }
7572
+ function createCopilotCodexCandidate(model) {
7573
+ const reasoningEfforts = normalizeReasoningEfforts(model.capabilities.supports.reasoning_effort);
7574
+ const usesNativeMessages = model.supported_endpoints?.includes(MESSAGES_ENDPOINT);
7575
+ return {
7576
+ slug: toClientModelId(model.id),
7577
+ displayName: model.name,
7578
+ description: usesNativeMessages ? `${model.name} through the Copilot Messages adapter.` : `${model.name} through the Copilot Messages-to-Chat adapter.`,
7579
+ contextWindow: positiveNumber(model.capabilities.limits.max_context_window_tokens, 256e3),
7580
+ maxOutputTokens: positiveNumber(model.capabilities.limits.max_output_tokens, 32e3),
7581
+ inputModalities: model.capabilities.supports.vision ? ["text", "image"] : ["text"],
7582
+ reasoningEfforts,
7583
+ defaultReasoningEffort: selectDefaultReasoningEffort(reasoningEfforts),
7584
+ supportsParallelToolCalls: Boolean(model.capabilities.supports.parallel_tool_calls)
7585
+ };
7586
+ }
7587
+ async function getProviderCodexCandidates(provider, requestHeaders) {
7588
+ if (provider === "codex") return [];
7589
+ try {
7590
+ const providerConfig = await resolveProviderConfig(provider);
7591
+ if (!providerConfig || providerConfig.name === "codex") return [];
7592
+ const remoteModels = await getProviderModelRecords(providerConfig, requestHeaders);
7593
+ const remoteById = new Map(remoteModels.flatMap((model) => {
7594
+ const id = getStringField$1(model, "id");
7595
+ return id ? [[id, model]] : [];
7596
+ }));
7597
+ const modelIds = new Set([...remoteById.keys(), ...Object.keys(providerConfig.models ?? {})]);
7598
+ const candidates = [];
7599
+ for (const modelId of modelIds) {
7600
+ const effectiveType = resolveEffectiveProviderType(providerConfig, modelId);
7601
+ if (!isMessagesFallbackProviderType(effectiveType)) continue;
7602
+ const modelConfig = providerConfig.models?.[modelId];
7603
+ if (modelConfig?.codex?.enabled === false) continue;
7604
+ candidates.push(createProviderCodexCandidate(providerConfig, modelId, remoteById.get(modelId), modelConfig, effectiveType));
7605
+ }
7606
+ return candidates;
7607
+ } catch (error) {
7608
+ logger$7.warn("models.codex.provider_skip_error", {
7609
+ provider,
7610
+ error
7611
+ });
7612
+ return [];
7613
+ }
7614
+ }
7615
+ function isMessagesFallbackProviderType(type) {
7616
+ return type === "anthropic" || type === "openai-compatible";
7617
+ }
7618
+ async function getProviderModelRecords(providerConfig, requestHeaders) {
7619
+ try {
7620
+ const response = await forwardProviderModels(providerConfig, requestHeaders);
7621
+ if (!response.ok) {
7622
+ logger$7.warn("models.codex.provider_skip_non_ok", {
7623
+ provider: providerConfig.name,
7624
+ statusCode: response.status
7625
+ });
7626
+ return [];
7627
+ }
7628
+ const body = await response.json();
7629
+ if (!isRecord$1(body) || !Array.isArray(body.data)) return [];
7630
+ return body.data.filter(isRecord$1);
7631
+ } catch (error) {
7632
+ logger$7.warn("models.codex.provider_models_error", {
7633
+ provider: providerConfig.name,
7634
+ error
7635
+ });
7636
+ return [];
7637
+ }
7638
+ }
7639
+ function createProviderCodexCandidate(providerConfig, modelId, remoteModel, modelConfig, effectiveType) {
7640
+ const codexConfig = modelConfig?.codex;
7641
+ const configuredReasoningEfforts = normalizeReasoningEfforts(codexConfig?.reasoningEfforts);
7642
+ const reasoningEfforts = configuredReasoningEfforts.length > 0 ? configuredReasoningEfforts : normalizeRemoteReasoningEfforts(remoteModel);
7643
+ const configuredModalities = normalizeInputModalities(codexConfig?.inputModalities);
7644
+ const remoteModalities = normalizeInputModalities(remoteModel?.input_modalities ?? remoteModel?.modalities);
7645
+ const displayName = getStringField$1(remoteModel ?? {}, "display_name") ?? getStringField$1(remoteModel ?? {}, "name") ?? modelId;
7646
+ const adapterName = effectiveType === "anthropic" ? "Messages" : "Messages-to-Chat";
7647
+ return {
7648
+ slug: `${providerConfig.name}/${modelId}`,
7649
+ displayName: `${displayName} (${providerConfig.name})`,
7650
+ description: `${displayName} through the ${providerConfig.name} ${adapterName} adapter.`,
7651
+ contextWindow: positiveNumber(codexConfig?.contextWindow ?? getFirstPositiveNumber(remoteModel, [
7652
+ "context_window",
7653
+ "context_length",
7654
+ "max_context_length",
7655
+ "max_model_len"
7656
+ ]), 256e3),
7657
+ maxOutputTokens: positiveNumber(codexConfig?.maxOutputTokens ?? getFirstPositiveNumber(remoteModel, ["max_output_tokens"]), 32e3),
7658
+ inputModalities: resolveInputModalities(providerConfig.name, configuredModalities, remoteModalities),
7659
+ reasoningEfforts,
7660
+ defaultReasoningEffort: selectDefaultReasoningEffort(reasoningEfforts, codexConfig?.defaultReasoningEffort),
7661
+ supportsParallelToolCalls: codexConfig?.supportsParallelToolCalls ?? getBooleanField(remoteModel, "supports_parallel_tool_calls") ?? false
7662
+ };
7663
+ }
7664
+ function normalizeRemoteReasoningEfforts(model) {
7665
+ if (!model) return [];
7666
+ const value = model.reasoning_efforts ?? model.supported_reasoning_levels;
7667
+ if (!Array.isArray(value)) return [];
7668
+ return normalizeReasoningEfforts(value.map((entry) => isRecord$1(entry) && typeof entry.effort === "string" ? entry.effort : entry));
7669
+ }
7670
+ function normalizeReasoningEfforts(value) {
7671
+ if (!Array.isArray(value)) return [];
7672
+ return [...new Set(value.filter((effort) => typeof effort === "string" && CODEX_REASONING_EFFORTS.has(effort)))];
7673
+ }
7674
+ function normalizeInputModalities(value) {
7675
+ if (!Array.isArray(value)) return [];
7676
+ return [...new Set(value.filter((modality) => modality === "text" || modality === "image"))];
7677
+ }
7678
+ function resolveInputModalities(providerName, configuredModalities, remoteModalities) {
7679
+ if (configuredModalities.length > 0) return configuredModalities;
7680
+ if (providerName === "kimi") {
7681
+ const modalities = remoteModalities.length > 0 ? remoteModalities : ["text"];
7682
+ return [...new Set([...modalities, "image"])];
7683
+ }
7684
+ return remoteModalities.length > 0 ? remoteModalities : ["text"];
7685
+ }
7686
+ function selectDefaultReasoningEffort(efforts, configured) {
7687
+ if (configured && efforts.includes(configured)) return configured;
7688
+ if (efforts.includes("max")) return "max";
7689
+ return efforts[0] ?? "max";
7690
+ }
7691
+ function positiveNumber(value, fallback) {
7692
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
7693
+ }
7694
+ function getFirstPositiveNumber(model, fields) {
7695
+ if (!model) return void 0;
7696
+ for (const field of fields) {
7697
+ const value = model[field];
7698
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
7699
+ }
7700
+ }
7701
+ function getBooleanField(model, field) {
7702
+ const value = model?.[field];
7703
+ return typeof value === "boolean" ? value : void 0;
7704
+ }
7326
7705
  modelRoutes.get("/", async (c) => {
7327
7706
  try {
7328
- if (isCodexUserAgent(c.req.header("user-agent"))) return await handleCodexModelsProxy(c);
7707
+ if (isCodexUserAgent(c.req.header("user-agent"))) return await handleMergedCodexModels(c, getSyntheticCodexModels(c.req.raw.headers));
7329
7708
  const models = await getAggregatedModels(c.req.raw.headers);
7330
7709
  return c.json({
7331
7710
  object: "list",
@@ -7338,7 +7717,7 @@ modelRoutes.get("/", async (c) => {
7338
7717
  });
7339
7718
  //#endregion
7340
7719
  //#region src/routes/provider/alpha-search/route.ts
7341
- const logger$5 = createHandlerLogger("provider-alpha-search-handler");
7720
+ const logger$6 = createHandlerLogger("provider-alpha-search-handler");
7342
7721
  const providerAlphaSearchRoutes = new Hono();
7343
7722
  providerAlphaSearchRoutes.post("/", async (c) => {
7344
7723
  const provider = c.req.param("provider") ?? "";
@@ -7349,19 +7728,19 @@ providerAlphaSearchRoutes.post("/", async (c) => {
7349
7728
  type: "invalid_request_error"
7350
7729
  } }, 404);
7351
7730
  if (providerConfig.name === "codex") return await handleAlphaSearchRequest(c, providerConfig);
7352
- await debugJsonAsync(logger$5, "provider.alpha_search.request", async () => ({
7731
+ await debugJsonAsync(logger$6, "provider.alpha_search.request", async () => ({
7353
7732
  body: await c.req.raw.clone().text(),
7354
7733
  provider
7355
7734
  }));
7356
7735
  const upstreamResponse = await forwardProviderAlphaSearch(providerConfig, c.req.raw);
7357
- await debugJsonAsync(logger$5, "provider.alpha_search.response", async () => ({
7736
+ await debugJsonAsync(logger$6, "provider.alpha_search.response", async () => ({
7358
7737
  body: await upstreamResponse.clone().text(),
7359
7738
  provider,
7360
7739
  statusCode: upstreamResponse.status
7361
7740
  }));
7362
7741
  return createProviderProxyResponse(upstreamResponse);
7363
7742
  } catch (error) {
7364
- logger$5.error("provider.alpha_search.error", {
7743
+ logger$6.error("provider.alpha_search.error", {
7365
7744
  provider,
7366
7745
  error
7367
7746
  });
@@ -7370,7 +7749,7 @@ providerAlphaSearchRoutes.post("/", async (c) => {
7370
7749
  });
7371
7750
  //#endregion
7372
7751
  //#region src/routes/provider/images/route.ts
7373
- const logger$4 = createHandlerLogger("provider-images-handler");
7752
+ const logger$5 = createHandlerLogger("provider-images-handler");
7374
7753
  const providerImageRoutes = new Hono();
7375
7754
  function getContentMetadata(headers) {
7376
7755
  return {
@@ -7387,23 +7766,23 @@ async function handleProviderImages(c, operation) {
7387
7766
  type: "invalid_request_error"
7388
7767
  } }, 404);
7389
7768
  if (providerConfig.name === "codex") return await handleCodexImages(c, operation, providerConfig);
7390
- if (operation === "generations") await debugJsonAsync(logger$4, "provider.images.generations.request", async () => ({
7769
+ if (operation === "generations") await debugJsonAsync(logger$5, "provider.images.generations.request", async () => ({
7391
7770
  body: await c.req.raw.clone().text(),
7392
7771
  provider
7393
7772
  }));
7394
- else debugJson(logger$4, "provider.images.edits.request", {
7773
+ else debugJson(logger$5, "provider.images.edits.request", {
7395
7774
  ...getContentMetadata(c.req.raw.headers),
7396
7775
  provider
7397
7776
  });
7398
7777
  const upstreamResponse = await forwardProviderImages(providerConfig, c.req.raw, operation);
7399
- debugJson(logger$4, `provider.images.${operation}.response`, {
7778
+ debugJson(logger$5, `provider.images.${operation}.response`, {
7400
7779
  ...getContentMetadata(upstreamResponse.headers),
7401
7780
  provider,
7402
7781
  statusCode: upstreamResponse.status
7403
7782
  });
7404
7783
  return createProviderProxyResponse(upstreamResponse);
7405
7784
  } catch (error) {
7406
- logger$4.error(`provider.images.${operation}.error`, {
7785
+ logger$5.error(`provider.images.${operation}.error`, {
7407
7786
  provider,
7408
7787
  error
7409
7788
  });
@@ -7431,7 +7810,7 @@ providerMessageRoutes.post("/count_tokens", async (c) => {
7431
7810
  });
7432
7811
  //#endregion
7433
7812
  //#region src/routes/provider/models/route.ts
7434
- const logger$3 = createHandlerLogger("provider-models-handler");
7813
+ const logger$4 = createHandlerLogger("provider-models-handler");
7435
7814
  const providerModelRoutes = new Hono();
7436
7815
  providerModelRoutes.get("/", async (c) => {
7437
7816
  const provider = c.req.param("provider") ?? "";
@@ -7451,13 +7830,13 @@ providerModelRoutes.get("/", async (c) => {
7451
7830
  });
7452
7831
  }
7453
7832
  const upstreamResponse = await forwardProviderModels(providerConfig, c.req.raw.headers);
7454
- logger$3.debug("provider.models.response", {
7833
+ logger$4.debug("provider.models.response", {
7455
7834
  provider,
7456
7835
  statusCode: upstreamResponse.status
7457
7836
  });
7458
7837
  return createProviderProxyResponse(upstreamResponse);
7459
7838
  } catch (error) {
7460
- logger$3.error("provider.models.error", {
7839
+ logger$4.error("provider.models.error", {
7461
7840
  provider,
7462
7841
  error
7463
7842
  });
@@ -7465,6 +7844,1498 @@ providerModelRoutes.get("/", async (c) => {
7465
7844
  }
7466
7845
  });
7467
7846
  //#endregion
7847
+ //#region src/routes/responses/messages-translation.ts
7848
+ const MESSAGES_COMPACTION_PREFIX = "copilot-api:messages-compaction:v1:";
7849
+ const MESSAGES_COMPACTION_PROMPT = [
7850
+ "You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.",
7851
+ "Do NOT continue the task, make changes, or call any tools. Your only output must be the handoff summary.",
7852
+ "",
7853
+ "Include:",
7854
+ "- Current progress and key decisions made",
7855
+ "- Important context, constraints, or user preferences",
7856
+ "- What remains to be done (clear next steps)",
7857
+ "- Any critical data, examples, or references needed to continue",
7858
+ "",
7859
+ "Be concise, structured, and focused on helping the next LLM seamlessly continue the work.",
7860
+ "",
7861
+ compactTextOnlyGuard
7862
+ ].join("\n");
7863
+ const COMPACTION_REPLAY_PROMPT = "The previous conversation was compacted. Continue from this handoff summary:\n\n";
7864
+ const MAX_DEVELOPER_PROMPTS = 5;
7865
+ const TOOL_NAME_PATTERN = /^[A-Za-z0-9_-]{1,64}$/u;
7866
+ const CUSTOM_TOOL_INPUT_SCHEMA = {
7867
+ type: "object",
7868
+ properties: { input: { type: "string" } },
7869
+ required: ["input"],
7870
+ additionalProperties: false
7871
+ };
7872
+ var ResponsesMessagesTranslationError = class extends Error {
7873
+ status;
7874
+ constructor(message, status = 400) {
7875
+ super(message);
7876
+ this.name = "ResponsesMessagesTranslationError";
7877
+ this.status = status;
7878
+ }
7879
+ };
7880
+ function translateResponsesToMessages(payload, options) {
7881
+ const registry = createToolRegistry(payload);
7882
+ const normalized = normalizeResponsesInput(payload.input);
7883
+ const { messages, system } = translateInputToAnthropic(normalized.input, registry, payload.instructions, payload.input);
7884
+ if (normalized.compaction) messages.push({
7885
+ role: "user",
7886
+ content: MESSAGES_COMPACTION_PROMPT
7887
+ });
7888
+ if (messages.length === 0) throw new ResponsesMessagesTranslationError("Responses input must contain at least one translatable message");
7889
+ const reasoningEffort = translateReasoningEffort(payload.reasoning?.effort);
7890
+ const messagesPayload = {
7891
+ model: options.model,
7892
+ messages,
7893
+ max_tokens: Math.max(1, payload.max_output_tokens ?? 32e3),
7894
+ stream: payload.stream ?? false,
7895
+ temperature: payload.temperature ?? void 0,
7896
+ top_p: payload.top_p ?? void 0,
7897
+ system: system.length > 0 ? system : void 0,
7898
+ tools: normalized.compaction || registry.tools.length > 0 ? registry.tools : void 0,
7899
+ tool_choice: translateToolChoice(payload.tool_choice, registry),
7900
+ ...reasoningEffort ? { output_config: { effort: reasoningEffort } } : {},
7901
+ ...payload.service_tier === "auto" || payload.service_tier === "standard_only" ? { service_tier: payload.service_tier } : {},
7902
+ ...resolveMetadataUserId(payload) ? { metadata: { user_id: resolveMetadataUserId(payload) } } : {}
7903
+ };
7904
+ return {
7905
+ compaction: normalized.compaction,
7906
+ messagesPayload,
7907
+ originalPayload: payload,
7908
+ publicModel: options.publicModel ?? payload.model,
7909
+ registry
7910
+ };
7911
+ }
7912
+ function translateAnthropicToResponses(response, context) {
7913
+ const finish = translateStopReason(response.stop_reason);
7914
+ const output = context.compaction ? translateCompactionOutput(response) : translateAssistantOutput(response, context.registry);
7915
+ const outputText = context.compaction ? "" : extractAnthropicResponseText(response);
7916
+ return createMessagesBackedResponsesResult({
7917
+ context,
7918
+ id: toResponseId(response.id),
7919
+ output,
7920
+ outputText,
7921
+ status: finish.status,
7922
+ incompleteReason: finish.incompleteReason,
7923
+ usage: translateAnthropicUsage(response.usage),
7924
+ copilotUsage: response.copilot_usage
7925
+ });
7926
+ }
7927
+ function createMessagesBackedResponsesResult(options) {
7928
+ const { context } = options;
7929
+ return {
7930
+ id: options.id,
7931
+ object: "response",
7932
+ created_at: options.createdAt ?? Math.floor(Date.now() / 1e3),
7933
+ model: context.publicModel,
7934
+ output: options.output,
7935
+ output_text: options.outputText,
7936
+ status: options.status,
7937
+ copilot_usage: options.copilotUsage ?? null,
7938
+ usage: options.usage ?? null,
7939
+ error: options.error ?? null,
7940
+ incomplete_details: options.incompleteReason ? { reason: options.incompleteReason } : null,
7941
+ instructions: context.originalPayload.instructions ?? null,
7942
+ metadata: context.originalPayload.metadata ?? null,
7943
+ parallel_tool_calls: Boolean(context.originalPayload.parallel_tool_calls),
7944
+ temperature: context.originalPayload.temperature ?? null,
7945
+ tool_choice: context.originalPayload.tool_choice ?? "auto",
7946
+ tools: context.originalPayload.tools ?? [],
7947
+ top_p: context.originalPayload.top_p ?? null
7948
+ };
7949
+ }
7950
+ function translateAnthropicUsage(usage) {
7951
+ if (!usage) return null;
7952
+ const cachedTokens = usage.cache_read_input_tokens ?? 0;
7953
+ const cacheWriteTokens = usage.cache_creation_input_tokens ?? 0;
7954
+ const inputTokens = usage.input_tokens + cachedTokens + cacheWriteTokens;
7955
+ const outputTokens = usage.output_tokens;
7956
+ return {
7957
+ input_tokens: inputTokens,
7958
+ output_tokens: outputTokens,
7959
+ total_tokens: inputTokens + outputTokens,
7960
+ input_tokens_details: {
7961
+ cached_tokens: cachedTokens,
7962
+ ...cacheWriteTokens > 0 ? { cache_write_tokens: cacheWriteTokens } : {}
7963
+ },
7964
+ output_tokens_details: { reasoning_tokens: 0 }
7965
+ };
7966
+ }
7967
+ function encodeMessagesCompaction(summary) {
7968
+ const payload = `${MESSAGES_COMPACTION_PREFIX}${Buffer.from(summary, "utf8").toString("base64url")}`;
7969
+ return Buffer.from(payload, "utf8").toString("base64");
7970
+ }
7971
+ function decodeMessagesCompaction(value) {
7972
+ let payload = value;
7973
+ if (!payload.startsWith("copilot-api:messages-compaction:v1:")) {
7974
+ const decoded = Buffer.from(value, "base64");
7975
+ if (decoded.toString("base64") !== value) return null;
7976
+ payload = decoded.toString("utf8");
7977
+ }
7978
+ if (!payload.startsWith("copilot-api:messages-compaction:v1:")) return null;
7979
+ try {
7980
+ const encoded = payload.slice(35);
7981
+ if (!encoded) return null;
7982
+ return Buffer.from(encoded, "base64url").toString("utf8");
7983
+ } catch {
7984
+ return null;
7985
+ }
7986
+ }
7987
+ function resolveToolDescriptor(registry, alias) {
7988
+ return registry.byAlias.get(alias) ?? {
7989
+ alias,
7990
+ kind: "function",
7991
+ name: alias
7992
+ };
7993
+ }
7994
+ function decodeCustomToolInput(input) {
7995
+ if (isRecord(input) && typeof input.input === "string") return input.input;
7996
+ return typeof input === "string" ? input : JSON.stringify(input ?? {});
7997
+ }
7998
+ function toResponseId(messageId) {
7999
+ return `resp_${messageId.replace(/^msg[-_]?/u, "") || createStableHash(messageId)}`;
8000
+ }
8001
+ function normalizeResponsesInput(input) {
8002
+ if (!Array.isArray(input)) return {
8003
+ compaction: false,
8004
+ input
8005
+ };
8006
+ const triggerIndexes = input.flatMap((item, index) => getItemType(item) === "compaction_trigger" ? [index] : []);
8007
+ const compaction = triggerIndexes.length > 0;
8008
+ if (triggerIndexes.length > 1 || compaction && triggerIndexes[0] !== input.length - 1) throw new ResponsesMessagesTranslationError("compaction_trigger must be the final Responses input item");
8009
+ const withoutTrigger = compaction ? input.slice(0, -1) : [...input];
8010
+ let latestCompactionIndex = -1;
8011
+ for (let index = withoutTrigger.length - 1; index >= 0; index -= 1) if (getItemType(withoutTrigger[index]) === "compaction") {
8012
+ latestCompactionIndex = index;
8013
+ break;
8014
+ }
8015
+ if (latestCompactionIndex < 0) return {
8016
+ compaction,
8017
+ input: withoutTrigger
8018
+ };
8019
+ const carrier = withoutTrigger[latestCompactionIndex];
8020
+ const encryptedContent = getStringField(carrier, "encrypted_content");
8021
+ const summary = encryptedContent ? decodeMessagesCompaction(encryptedContent) : null;
8022
+ if (!summary) throw new ResponsesMessagesTranslationError("This Messages-backed model cannot replay a compaction created by another Responses backend; start a new conversation or switch back to the original model");
8023
+ return {
8024
+ compaction,
8025
+ input: [{
8026
+ type: "message",
8027
+ role: "user",
8028
+ content: `${COMPACTION_REPLAY_PROMPT}${summary}`
8029
+ }, ...withoutTrigger.slice(latestCompactionIndex + 1)]
8030
+ };
8031
+ }
8032
+ function createToolRegistry(payload) {
8033
+ const registry = {
8034
+ byAlias: /* @__PURE__ */ new Map(),
8035
+ byOriginal: /* @__PURE__ */ new Map(),
8036
+ tools: []
8037
+ };
8038
+ for (const tool of payload.tools ?? []) registerTool(tool, registry);
8039
+ if (Array.isArray(payload.input)) for (const item of payload.input) {
8040
+ if (getItemType(item) !== "additional_tools") continue;
8041
+ for (const tool of getArrayField(item, "tools")) registerTool(tool, registry);
8042
+ }
8043
+ return registry;
8044
+ }
8045
+ function registerTool(tool, registry, namespaces = []) {
8046
+ if (!isRecord(tool)) throw new ResponsesMessagesTranslationError("Invalid Responses tool definition");
8047
+ const type = getStringField(tool, "type");
8048
+ if (type === "namespace") {
8049
+ const namespaceTool = tool;
8050
+ const namespace = getStringField(namespaceTool, "name");
8051
+ if (!namespace || !Array.isArray(namespaceTool.tools)) throw new ResponsesMessagesTranslationError("Responses namespace tools require a name and tools array");
8052
+ for (const child of namespaceTool.tools) registerTool(child, registry, [...namespaces, namespace]);
8053
+ return;
8054
+ }
8055
+ if (type !== "function" && type !== "custom") throw new ResponsesMessagesTranslationError(`Responses Messages fallback does not support tool${type ? ` '${type}'` : " without a type"}`);
8056
+ const name = getStringField(tool, "name");
8057
+ if (!name) throw new ResponsesMessagesTranslationError(`Responses ${type} tools require a non-empty name`);
8058
+ registerMessagesTool({
8059
+ kind: type,
8060
+ name,
8061
+ namespace: namespaces.length > 0 ? namespaces.join(".") : void 0,
8062
+ description: getOptionalStringField(tool, "description"),
8063
+ parameters: type === "function" && isRecord(tool.parameters) ? tool.parameters : null
8064
+ }, registry);
8065
+ }
8066
+ function registerMessagesTool(registration, registry) {
8067
+ const originalKey = createOriginalToolKey(registration);
8068
+ const existing = registry.byOriginal.get(originalKey);
8069
+ if (existing) return existing;
8070
+ const alias = createToolAlias(registration.namespace ? `${registration.namespace.replaceAll(".", "_")}__${registration.name}` : registration.name, originalKey, registry);
8071
+ const descriptor = {
8072
+ alias,
8073
+ kind: registration.kind,
8074
+ name: registration.name,
8075
+ ...registration.namespace ? { namespace: registration.namespace } : {}
8076
+ };
8077
+ registry.byAlias.set(alias, descriptor);
8078
+ registry.byOriginal.set(originalKey, descriptor);
8079
+ registry.tools.push({
8080
+ name: alias,
8081
+ ...registration.description ? { description: registration.description } : {},
8082
+ input_schema: registration.kind === "custom" ? CUSTOM_TOOL_INPUT_SCHEMA : registration.parameters ?? {
8083
+ type: "object",
8084
+ properties: {}
8085
+ }
8086
+ });
8087
+ return descriptor;
8088
+ }
8089
+ function translateInputToAnthropic(input, registry, instructions, originalInput) {
8090
+ const messages = [];
8091
+ const system = [];
8092
+ if (instructions?.trim()) system.push({
8093
+ type: "text",
8094
+ text: instructions
8095
+ });
8096
+ appendDeveloperPrompts(system, originalInput);
8097
+ if (typeof input === "string") {
8098
+ messages.push({
8099
+ role: "user",
8100
+ content: input
8101
+ });
8102
+ return {
8103
+ messages,
8104
+ system
8105
+ };
8106
+ }
8107
+ if (!Array.isArray(input)) return {
8108
+ messages,
8109
+ system
8110
+ };
8111
+ let userMessageSeen = false;
8112
+ for (const item of input) {
8113
+ const type = getItemType(item);
8114
+ switch (type) {
8115
+ case void 0:
8116
+ case "message":
8117
+ translateInputMessage(item, messages, system, userMessageSeen);
8118
+ if (getStringField(item, "role") === "user") userMessageSeen = true;
8119
+ break;
8120
+ case "agent_message":
8121
+ translateInputAgentMessage(item, messages);
8122
+ userMessageSeen = true;
8123
+ break;
8124
+ case "reasoning":
8125
+ translateInputReasoning(item, messages);
8126
+ break;
8127
+ case "function_call":
8128
+ translateInputToolCall(item, "function", messages, registry);
8129
+ break;
8130
+ case "custom_tool_call":
8131
+ translateInputToolCall(item, "custom", messages, registry);
8132
+ break;
8133
+ case "function_call_output":
8134
+ case "custom_tool_call_output":
8135
+ appendUserBlock(messages, {
8136
+ type: "tool_result",
8137
+ tool_use_id: requireStringField(item, "call_id", type),
8138
+ content: translateToolResultContent(item.output, `${type}.output`),
8139
+ is_error: getStringField(item, "status") === "incomplete"
8140
+ });
8141
+ break;
8142
+ case "additional_tools": break;
8143
+ default: throw new ResponsesMessagesTranslationError(`Responses Messages fallback does not support input item type '${type}'`);
8144
+ }
8145
+ }
8146
+ return {
8147
+ messages,
8148
+ system
8149
+ };
8150
+ }
8151
+ function translateInputMessage(item, messages, system, userMessageSeen) {
8152
+ if (!isRecord(item)) throw new ResponsesMessagesTranslationError("Invalid Responses message item");
8153
+ const role = getStringField(item, "role");
8154
+ if (role !== "user" && role !== "assistant" && role !== "system" && role !== "developer") throw new ResponsesMessagesTranslationError("Responses message items require a supported role");
8155
+ if (role === "developer" && !userMessageSeen) return;
8156
+ if (role === "system") {
8157
+ const text = translateSystemContent(item.content, "message.content");
8158
+ if (text) system.push({
8159
+ type: "text",
8160
+ text
8161
+ });
8162
+ return;
8163
+ }
8164
+ if (role === "assistant") {
8165
+ const blocks = translateAssistantContent(item.content, "message.content");
8166
+ for (const block of blocks) appendAssistantBlock(messages, block);
8167
+ return;
8168
+ }
8169
+ const content = translateUserContent(item.content, "message.content");
8170
+ messages.push({
8171
+ role: "user",
8172
+ content
8173
+ });
8174
+ }
8175
+ function translateInputAgentMessage(item, messages) {
8176
+ const content = translateUserContent(item.content, "agent_message.content");
8177
+ messages.push({
8178
+ role: "user",
8179
+ content
8180
+ });
8181
+ }
8182
+ function appendDeveloperPrompts(system, input) {
8183
+ if (!Array.isArray(input)) return;
8184
+ const prompts = [];
8185
+ for (const item of input) {
8186
+ if (prompts.length >= MAX_DEVELOPER_PROMPTS) break;
8187
+ const type = getItemType(item);
8188
+ const role = getStringField(item, "role");
8189
+ if (type === "agent_message") break;
8190
+ if ((type === void 0 || type === "message") && role === "user") break;
8191
+ if (type !== void 0 && type !== "message" || role !== "developer") continue;
8192
+ prompts.push(translateSystemContent(isRecord(item) ? item.content : void 0, "message.content"));
8193
+ }
8194
+ const [firstPrompt, ...remainingPrompts] = prompts;
8195
+ if (firstPrompt) system.push({
8196
+ type: "text",
8197
+ text: firstPrompt
8198
+ });
8199
+ const mergedPrompts = remainingPrompts.filter(Boolean).join("\n\n");
8200
+ if (mergedPrompts) system.push({
8201
+ type: "text",
8202
+ text: mergedPrompts
8203
+ });
8204
+ }
8205
+ function translateInputReasoning(item, messages) {
8206
+ appendAssistantBlock(messages, {
8207
+ type: "thinking",
8208
+ thinking: (Array.isArray(item.summary) ? item.summary.map((part) => typeof part?.text === "string" ? part.text : "").filter(Boolean).join("\n\n") : "") || "Thinking...",
8209
+ signature: item.encrypted_content ?? ""
8210
+ });
8211
+ }
8212
+ function translateInputToolCall(item, kind, messages, registry) {
8213
+ if (!isRecord(item)) throw new ResponsesMessagesTranslationError("Invalid Responses tool call item");
8214
+ const descriptor = registerMessagesTool({
8215
+ kind,
8216
+ name: requireStringField(item, "name", `${kind}_tool_call`),
8217
+ namespace: getOptionalStringField(item, "namespace") ?? void 0
8218
+ }, registry);
8219
+ const input = kind === "custom" ? { input: getStringField(item, "input") ?? "" } : parseFunctionArguments(getStringField(item, "arguments") ?? "{}", `${kind}_tool_call.arguments`);
8220
+ appendAssistantBlock(messages, {
8221
+ type: "tool_use",
8222
+ id: requireStringField(item, "call_id", `${kind}_tool_call`),
8223
+ name: descriptor.alias,
8224
+ input
8225
+ });
8226
+ }
8227
+ function translateUserContent(value, path) {
8228
+ if (value === void 0 || value === null) return "";
8229
+ if (typeof value === "string") return value;
8230
+ if (!Array.isArray(value)) throw new ResponsesMessagesTranslationError(`${path} must be text or an array`);
8231
+ return value.map((part, index) => translateUserContentPart(part, `${path}[${index}]`));
8232
+ }
8233
+ function translateAssistantContent(value, path) {
8234
+ if (value === void 0 || value === null) return [];
8235
+ if (typeof value === "string") return value ? [{
8236
+ type: "text",
8237
+ text: value
8238
+ }] : [];
8239
+ if (!Array.isArray(value)) throw new ResponsesMessagesTranslationError(`${path} must be text or an array`);
8240
+ return value.map((part, index) => {
8241
+ if (!isRecord(part)) throw new ResponsesMessagesTranslationError(`${path}[${index}] must be an object`);
8242
+ const type = getStringField(part, "type");
8243
+ if (type !== "input_text" && type !== "output_text" && type !== "text") throw new ResponsesMessagesTranslationError(`${path}[${index}] has unsupported assistant content type '${type ?? "unknown"}'`);
8244
+ return {
8245
+ type: "text",
8246
+ text: requireStringField(part, "text", `${path}[${index}]`)
8247
+ };
8248
+ });
8249
+ }
8250
+ function translateSystemContent(value, path) {
8251
+ if (value === void 0 || value === null) return "";
8252
+ if (typeof value === "string") return value;
8253
+ if (!Array.isArray(value)) throw new ResponsesMessagesTranslationError(`${path} must be text or an array`);
8254
+ return value.map((part, index) => {
8255
+ if (!isRecord(part)) throw new ResponsesMessagesTranslationError(`${path}[${index}] must be an object`);
8256
+ const type = getStringField(part, "type");
8257
+ if (type !== "input_text" && type !== "output_text" && type !== "text") throw new ResponsesMessagesTranslationError(`${path}[${index}] has unsupported system content type '${type ?? "unknown"}'`);
8258
+ return requireStringField(part, "text", `${path}[${index}]`);
8259
+ }).join("\n\n");
8260
+ }
8261
+ function translateUserContentPart(part, path) {
8262
+ if (!isRecord(part)) throw new ResponsesMessagesTranslationError(`${path} must be an object`);
8263
+ const type = getStringField(part, "type");
8264
+ if (type === "input_text" || type === "output_text" || type === "text") return {
8265
+ type: "text",
8266
+ text: requireStringField(part, "text", path)
8267
+ };
8268
+ if (type === "input_image") return translateImagePart(part, path);
8269
+ if (type === "input_file") return translateFilePart(part, path);
8270
+ throw new ResponsesMessagesTranslationError(`${path} has unsupported content type '${type ?? "unknown"}'`);
8271
+ }
8272
+ function translateToolResultContent(value, path) {
8273
+ if (value === void 0 || value === null) return "";
8274
+ if (typeof value === "string") return value;
8275
+ if (!Array.isArray(value)) throw new ResponsesMessagesTranslationError(`${path} must be text or an array`);
8276
+ return value.map((part, index) => translateUserContentPart(part, `${path}[${index}]`));
8277
+ }
8278
+ function translateImagePart(part, path) {
8279
+ const imageUrl = getStringField(part, "image_url");
8280
+ if (!imageUrl) throw new ResponsesMessagesTranslationError(`${path} requires image_url; file_id-only images cannot be sent to Messages`);
8281
+ const parsed = parseDataUrl(imageUrl);
8282
+ if (!parsed || parsed.mediaType !== "image/jpeg" && parsed.mediaType !== "image/png" && parsed.mediaType !== "image/gif" && parsed.mediaType !== "image/webp") throw new ResponsesMessagesTranslationError(`${path} requires a base64 JPEG, PNG, GIF, or WebP data URL`);
8283
+ return {
8284
+ type: "image",
8285
+ source: {
8286
+ type: "base64",
8287
+ media_type: parsed.mediaType,
8288
+ data: parsed.data
8289
+ }
8290
+ };
8291
+ }
8292
+ function translateFilePart(part, path) {
8293
+ const fileData = getStringField(part, "file_data");
8294
+ if (!fileData) throw new ResponsesMessagesTranslationError(`${path} requires file_data; file_id-only files cannot be sent to Messages`);
8295
+ const parsed = parseDataUrl(fileData);
8296
+ if (parsed?.mediaType !== "application/pdf") throw new ResponsesMessagesTranslationError(`${path} requires a base64 PDF data URL`);
8297
+ return {
8298
+ type: "document",
8299
+ source: {
8300
+ type: "base64",
8301
+ media_type: "application/pdf",
8302
+ data: parsed.data
8303
+ },
8304
+ title: getOptionalStringField(part, "filename") ?? "document.pdf"
8305
+ };
8306
+ }
8307
+ function translateToolChoice(toolChoice, registry) {
8308
+ if (!toolChoice) return void 0;
8309
+ if (typeof toolChoice === "string") {
8310
+ if (toolChoice === "required") return { type: "any" };
8311
+ return { type: toolChoice };
8312
+ }
8313
+ const kind = toolChoice.type;
8314
+ if (kind !== "function" && kind !== "custom") throw new ResponsesMessagesTranslationError(`Responses Messages fallback does not support tool_choice type '${String(kind)}'`);
8315
+ const rawName = toolChoice.name;
8316
+ const descriptor = findOriginalDescriptor(registry, kind, rawName, getOptionalStringField(toolChoice, "namespace") ?? void 0);
8317
+ if (!descriptor) throw new ResponsesMessagesTranslationError(`tool_choice references unknown ${kind} tool '${rawName}'`);
8318
+ return {
8319
+ type: "tool",
8320
+ name: descriptor.alias
8321
+ };
8322
+ }
8323
+ function translateAssistantOutput(response, registry) {
8324
+ const output = [];
8325
+ for (const [index, block] of response.content.entries()) {
8326
+ if (block.type === "thinking") {
8327
+ output.push({
8328
+ id: `rs_${createStableHash(`${response.id}:${index}:reasoning`)}`,
8329
+ type: "reasoning",
8330
+ status: "completed",
8331
+ ...block.thinking && block.thinking !== "Thinking..." ? { summary: [{
8332
+ type: "summary_text",
8333
+ text: block.thinking
8334
+ }] } : {},
8335
+ ...block.signature ? { encrypted_content: block.signature } : {}
8336
+ });
8337
+ continue;
8338
+ }
8339
+ if (block.type === "text") {
8340
+ output.push({
8341
+ id: `msg_${createStableHash(`${response.id}:${index}:message`)}`,
8342
+ type: "message",
8343
+ role: "assistant",
8344
+ status: "completed",
8345
+ content: [{
8346
+ type: "output_text",
8347
+ text: block.text,
8348
+ annotations: []
8349
+ }]
8350
+ });
8351
+ continue;
8352
+ }
8353
+ if (block.type === "tool_use") output.push(translateToolUseOutput(block, registry, `${response.id}:${index}:tool`));
8354
+ }
8355
+ return output;
8356
+ }
8357
+ function translateToolUseOutput(block, registry, idSeed) {
8358
+ const descriptor = resolveToolDescriptor(registry, block.name);
8359
+ const common = {
8360
+ id: `fc_${createStableHash(idSeed)}`,
8361
+ call_id: block.id,
8362
+ name: descriptor.name,
8363
+ status: "completed",
8364
+ ...descriptor.namespace ? { namespace: descriptor.namespace } : {}
8365
+ };
8366
+ if (descriptor.kind === "custom") return {
8367
+ ...common,
8368
+ type: "custom_tool_call",
8369
+ input: decodeCustomToolInput(block.input)
8370
+ };
8371
+ return {
8372
+ ...common,
8373
+ type: "function_call",
8374
+ arguments: JSON.stringify(block.input)
8375
+ };
8376
+ }
8377
+ function translateCompactionOutput(response) {
8378
+ if (response.content.some((block) => block.type === "tool_use")) throw new ResponsesMessagesTranslationError("Messages API attempted a tool call during compaction", 502);
8379
+ const summary = extractAnthropicResponseText(response).trim();
8380
+ if (!summary) throw new ResponsesMessagesTranslationError("Messages API compaction response did not contain a text summary", 502);
8381
+ return [{
8382
+ id: `cmp_${createStableHash(summary)}`,
8383
+ type: "compaction",
8384
+ encrypted_content: encodeMessagesCompaction(summary)
8385
+ }];
8386
+ }
8387
+ function extractAnthropicResponseText(response) {
8388
+ return response.content.flatMap((block) => block.type === "text" ? [block.text] : []).join("");
8389
+ }
8390
+ function translateStopReason(stopReason) {
8391
+ if (stopReason === "max_tokens") return {
8392
+ status: "incomplete",
8393
+ incompleteReason: "max_output_tokens"
8394
+ };
8395
+ if (stopReason === "refusal") return {
8396
+ status: "incomplete",
8397
+ incompleteReason: "content_filter"
8398
+ };
8399
+ return { status: "completed" };
8400
+ }
8401
+ function translateReasoningEffort(effort) {
8402
+ if (effort === "minimal") return "low";
8403
+ if (effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max") return effort;
8404
+ }
8405
+ function resolveMetadataUserId(payload) {
8406
+ const metadataUserId = payload.metadata?.user_id;
8407
+ if (metadataUserId?.trim()) return metadataUserId;
8408
+ if (payload.safety_identifier?.trim()) return payload.safety_identifier;
8409
+ if (payload.prompt_cache_key?.trim()) return payload.prompt_cache_key;
8410
+ }
8411
+ function appendAssistantBlock(messages, block) {
8412
+ const last = messages.at(-1);
8413
+ if (last?.role === "assistant" && Array.isArray(last.content)) {
8414
+ last.content.push(block);
8415
+ return;
8416
+ }
8417
+ const message = {
8418
+ role: "assistant",
8419
+ content: [block]
8420
+ };
8421
+ messages.push(message);
8422
+ }
8423
+ function appendUserBlock(messages, block) {
8424
+ const last = messages.at(-1);
8425
+ if (last?.role === "user" && Array.isArray(last.content)) {
8426
+ last.content.push(block);
8427
+ return;
8428
+ }
8429
+ const message = {
8430
+ role: "user",
8431
+ content: [block]
8432
+ };
8433
+ messages.push(message);
8434
+ }
8435
+ function parseFunctionArguments(value, path) {
8436
+ try {
8437
+ const parsed = JSON.parse(value);
8438
+ if (isRecord(parsed)) return parsed;
8439
+ } catch {}
8440
+ throw new ResponsesMessagesTranslationError(`${path} must be a JSON object string`);
8441
+ }
8442
+ function parseDataUrl(value) {
8443
+ const match = /^data:([^;,]+);base64,(.*)$/su.exec(value);
8444
+ if (!match) return null;
8445
+ return {
8446
+ mediaType: match[1].toLowerCase(),
8447
+ data: match[2]
8448
+ };
8449
+ }
8450
+ function findOriginalDescriptor(registry, kind, name, namespace) {
8451
+ const matches = [];
8452
+ for (const descriptor of registry.byOriginal.values()) {
8453
+ if (descriptor.kind !== kind || descriptor.name !== name) continue;
8454
+ if (namespace !== void 0) {
8455
+ if (descriptor.namespace === namespace) return descriptor;
8456
+ continue;
8457
+ }
8458
+ matches.push(descriptor);
8459
+ }
8460
+ return matches.find((descriptor) => descriptor.namespace === void 0) ?? (matches.length === 1 ? matches[0] : void 0);
8461
+ }
8462
+ function createOriginalToolKey(tool) {
8463
+ return [
8464
+ tool.kind,
8465
+ tool.namespace ?? "",
8466
+ tool.name
8467
+ ].join("\0");
8468
+ }
8469
+ function createToolAlias(preferredName, originalKey, registry) {
8470
+ if (TOOL_NAME_PATTERN.test(preferredName) && !registry.byAlias.has(preferredName)) return preferredName;
8471
+ const sanitized = preferredName.replace(/[^A-Za-z0-9_-]+/gu, "_");
8472
+ const alias = `${`tool_${createStableHash(originalKey).slice(0, 12)}_`}${sanitized}`.slice(0, 64);
8473
+ if (!registry.byAlias.has(alias)) return alias;
8474
+ return `tool_${createStableHash(`${originalKey}:collision`)}`.slice(0, 64);
8475
+ }
8476
+ function createStableHash(value) {
8477
+ return createHash("sha256").update(value).digest("hex").slice(0, 24);
8478
+ }
8479
+ function getItemType(value) {
8480
+ return isRecord(value) && typeof value.type === "string" ? value.type : void 0;
8481
+ }
8482
+ function getStringField(value, field) {
8483
+ if (!isRecord(value)) return void 0;
8484
+ const fieldValue = value[field];
8485
+ return typeof fieldValue === "string" ? fieldValue : void 0;
8486
+ }
8487
+ function getOptionalStringField(value, field) {
8488
+ if (!isRecord(value)) return void 0;
8489
+ const fieldValue = value[field];
8490
+ return typeof fieldValue === "string" || fieldValue === null ? fieldValue : void 0;
8491
+ }
8492
+ function requireStringField(value, field, path) {
8493
+ const result = getStringField(value, field);
8494
+ if (!result) throw new ResponsesMessagesTranslationError(`${path}.${field} is required`);
8495
+ return result;
8496
+ }
8497
+ function getArrayField(value, field) {
8498
+ if (!isRecord(value)) return [];
8499
+ return Array.isArray(value[field]) ? value[field] : [];
8500
+ }
8501
+ function isRecord(value) {
8502
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8503
+ }
8504
+ //#endregion
8505
+ //#region src/routes/responses/custom-tool-input-stream-decoder.ts
8506
+ const CUSTOM_TOOL_INPUT_PREFIX_TOKENS = [
8507
+ "{",
8508
+ "\"input\"",
8509
+ ":",
8510
+ "\""
8511
+ ];
8512
+ var CustomToolInputStreamDecoder = class {
8513
+ inputParts = new Array();
8514
+ encodedInput = "";
8515
+ escapeState = "plain";
8516
+ failed = false;
8517
+ finished = false;
8518
+ offset = 0;
8519
+ prefixCharOffset = 0;
8520
+ prefixTokenOffset = 0;
8521
+ safeInputLength = 0;
8522
+ state = "prefix";
8523
+ unicodeDigitsRemaining = 0;
8524
+ append(partialJson) {
8525
+ if (this.failed) return this.fail("decoder is already in a failed state");
8526
+ if (this.finished) return this.fail("data arrived after the input was done");
8527
+ const deltaParts = new Array();
8528
+ for (const char of partialJson) {
8529
+ this.offset += char.length;
8530
+ this.consume(char, deltaParts);
8531
+ }
8532
+ this.flushSafeInput(deltaParts);
8533
+ const delta = deltaParts.join("");
8534
+ if (delta) this.inputParts.push(delta);
8535
+ return delta;
8536
+ }
8537
+ finish() {
8538
+ if (this.failed) return this.fail("decoder is already in a failed state");
8539
+ if (this.finished) return this.fail("input was already completed");
8540
+ if (this.state !== "done" || this.escapeState !== "plain" || this.encodedInput) return this.fail("input ended before the wrapper was complete");
8541
+ this.finished = true;
8542
+ return this.inputParts.join("");
8543
+ }
8544
+ consume(char, deltaParts) {
8545
+ if (this.state === "prefix") {
8546
+ const token = CUSTOM_TOOL_INPUT_PREFIX_TOKENS[this.prefixTokenOffset];
8547
+ if (this.prefixCharOffset === 0 && isJsonWhitespace(char)) return;
8548
+ if (!token || char !== token[this.prefixCharOffset]) return this.fail("unexpected custom tool input prefix");
8549
+ this.prefixCharOffset += 1;
8550
+ if (this.prefixCharOffset < token.length) return;
8551
+ this.prefixTokenOffset += 1;
8552
+ this.prefixCharOffset = 0;
8553
+ if (this.prefixTokenOffset === CUSTOM_TOOL_INPUT_PREFIX_TOKENS.length) this.state = "input";
8554
+ return;
8555
+ }
8556
+ if (this.state === "suffix") {
8557
+ if (isJsonWhitespace(char)) return;
8558
+ if (char !== "}") return this.fail("expected \"}\" after the input string");
8559
+ this.state = "done";
8560
+ return;
8561
+ }
8562
+ if (this.state === "done") {
8563
+ if (!isJsonWhitespace(char)) return this.fail("unexpected data after the input wrapper");
8564
+ return;
8565
+ }
8566
+ if (this.escapeState === "unicode") {
8567
+ if (!/^[0-9A-Fa-f]$/u.test(char)) return this.fail("invalid Unicode escape");
8568
+ this.encodedInput += char;
8569
+ this.unicodeDigitsRemaining -= 1;
8570
+ if (this.unicodeDigitsRemaining === 0) {
8571
+ this.escapeState = "plain";
8572
+ this.safeInputLength = this.encodedInput.length;
8573
+ }
8574
+ return;
8575
+ }
8576
+ if (this.escapeState === "escaped") {
8577
+ if (!"\"\\/bfnrtu".includes(char)) return this.fail("invalid JSON escape");
8578
+ this.encodedInput += char;
8579
+ if (char === "u") {
8580
+ this.escapeState = "unicode";
8581
+ this.unicodeDigitsRemaining = 4;
8582
+ } else {
8583
+ this.escapeState = "plain";
8584
+ this.safeInputLength = this.encodedInput.length;
8585
+ }
8586
+ return;
8587
+ }
8588
+ if (char === "\\") {
8589
+ this.encodedInput += char;
8590
+ this.escapeState = "escaped";
8591
+ return;
8592
+ }
8593
+ if (char === "\"") {
8594
+ this.flushSafeInput(deltaParts);
8595
+ this.state = "suffix";
8596
+ return;
8597
+ }
8598
+ if (char.charCodeAt(0) < 32) return this.fail("unescaped control character in custom tool input");
8599
+ this.encodedInput += char;
8600
+ this.safeInputLength = this.encodedInput.length;
8601
+ }
8602
+ flushSafeInput(deltaParts) {
8603
+ if (this.safeInputLength === 0) return;
8604
+ const encoded = this.encodedInput.slice(0, this.safeInputLength);
8605
+ const decoded = JSON.parse(`"${encoded}"`);
8606
+ if (decoded) deltaParts.push(decoded);
8607
+ this.encodedInput = this.encodedInput.slice(this.safeInputLength);
8608
+ this.safeInputLength = 0;
8609
+ }
8610
+ fail(reason) {
8611
+ this.failed = true;
8612
+ throw new ResponsesMessagesTranslationError(`Messages API returned invalid custom tool input JSON at offset ${this.offset}: ${reason}`, 502);
8613
+ }
8614
+ };
8615
+ function isJsonWhitespace(char) {
8616
+ return char === " " || char === " " || char === "\r" || char === "\n";
8617
+ }
8618
+ //#endregion
8619
+ //#region src/routes/responses/messages-stream-translation.ts
8620
+ const EMPTY_SIGNATURE_ENCRYPTED_CONTENT = "Y29waWxvdC1hcGk6bWVzc2FnZXMtZW1wdHktc2lnbmF0dXJlOnYx";
8621
+ async function* translateMessagesStream(chunks, context) {
8622
+ const state = createTranslationState(context);
8623
+ try {
8624
+ for await (const chunk of chunks) {
8625
+ if (!chunk.data || chunk.data === "[DONE]") continue;
8626
+ const event = parseAnthropicEvent(chunk.data);
8627
+ if (event.type === "ping") continue;
8628
+ if (event.type === "error") throw new ResponsesMessagesTranslationError(event.error.message, 502);
8629
+ if (!state.initialized) {
8630
+ initializeState(state, event);
8631
+ yield createLifecycleEvent(state, "response.created");
8632
+ yield createLifecycleEvent(state, "response.in_progress");
8633
+ }
8634
+ for (const translated of translateEvent(state, event)) yield translated;
8635
+ if (state.messageStopped) break;
8636
+ }
8637
+ if (!state.initialized) throw new ResponsesMessagesTranslationError("Messages API returned an empty stream", 502);
8638
+ if (!state.messageStopped) {
8639
+ for (const translated of closeAllBlocks(state)) yield translated;
8640
+ for (const translated of finishCompaction(state)) yield translated;
8641
+ state.messageStopped = true;
8642
+ yield createTerminalEvent(state);
8643
+ }
8644
+ } catch (error) {
8645
+ if (!state.initialized) throw error;
8646
+ yield createErrorEvent(state, error);
8647
+ yield createFailedEvent(state, error);
8648
+ }
8649
+ }
8650
+ function responsesResultToStreamEvents(result) {
8651
+ let sequence = 0;
8652
+ const next = (value) => ({
8653
+ ...value,
8654
+ sequence_number: sequence++
8655
+ });
8656
+ const inProgress = {
8657
+ ...result,
8658
+ output: [],
8659
+ output_text: "",
8660
+ status: "in_progress",
8661
+ usage: null
8662
+ };
8663
+ const events = [next({
8664
+ type: "response.created",
8665
+ response: inProgress
8666
+ }), next({
8667
+ type: "response.in_progress",
8668
+ response: inProgress
8669
+ })];
8670
+ for (const [outputIndex, item] of result.output.entries()) {
8671
+ events.push(next({
8672
+ type: "response.output_item.added",
8673
+ output_index: outputIndex,
8674
+ item: {
8675
+ ...structuredClone(item),
8676
+ status: "in_progress"
8677
+ }
8678
+ }));
8679
+ if (item.type === "message") {
8680
+ const textPart = item.content?.find((part) => part.type === "output_text");
8681
+ if (textPart?.type === "output_text") events.push(next({
8682
+ type: "response.content_part.added",
8683
+ item_id: item.id,
8684
+ output_index: outputIndex,
8685
+ content_index: 0,
8686
+ part: {
8687
+ type: "output_text",
8688
+ text: "",
8689
+ annotations: []
8690
+ }
8691
+ }), next({
8692
+ type: "response.output_text.delta",
8693
+ item_id: item.id,
8694
+ output_index: outputIndex,
8695
+ content_index: 0,
8696
+ delta: textPart.text
8697
+ }), next({
8698
+ type: "response.output_text.done",
8699
+ item_id: item.id,
8700
+ output_index: outputIndex,
8701
+ content_index: 0,
8702
+ text: textPart.text
8703
+ }), next({
8704
+ type: "response.content_part.done",
8705
+ item_id: item.id,
8706
+ output_index: outputIndex,
8707
+ content_index: 0,
8708
+ part: textPart
8709
+ }));
8710
+ } else if (item.type === "reasoning") {
8711
+ const text = item.summary?.[0]?.text;
8712
+ if (text) {
8713
+ const part = {
8714
+ type: "summary_text",
8715
+ text
8716
+ };
8717
+ events.push(next({
8718
+ type: "response.reasoning_summary_part.added",
8719
+ item_id: item.id,
8720
+ output_index: outputIndex,
8721
+ summary_index: 0,
8722
+ part: {
8723
+ type: "summary_text",
8724
+ text: ""
8725
+ }
8726
+ }), next({
8727
+ type: "response.reasoning_summary_text.delta",
8728
+ item_id: item.id,
8729
+ output_index: outputIndex,
8730
+ summary_index: 0,
8731
+ delta: text
8732
+ }), next({
8733
+ type: "response.reasoning_summary_text.done",
8734
+ item_id: item.id,
8735
+ output_index: outputIndex,
8736
+ summary_index: 0,
8737
+ text
8738
+ }), next({
8739
+ type: "response.reasoning_summary_part.done",
8740
+ item_id: item.id,
8741
+ output_index: outputIndex,
8742
+ summary_index: 0,
8743
+ part
8744
+ }));
8745
+ }
8746
+ } else if (item.type === "function_call") {
8747
+ if (item.arguments) events.push(next({
8748
+ type: "response.function_call_arguments.delta",
8749
+ item_id: item.id,
8750
+ output_index: outputIndex,
8751
+ delta: item.arguments
8752
+ }));
8753
+ events.push(next({
8754
+ type: "response.function_call_arguments.done",
8755
+ item_id: item.id,
8756
+ output_index: outputIndex,
8757
+ name: item.name,
8758
+ arguments: item.arguments
8759
+ }));
8760
+ } else if (item.type === "custom_tool_call") {
8761
+ if (item.input) events.push(next({
8762
+ type: "response.custom_tool_call_input.delta",
8763
+ item_id: item.id,
8764
+ output_index: outputIndex,
8765
+ delta: item.input
8766
+ }));
8767
+ events.push(next({
8768
+ type: "response.custom_tool_call_input.done",
8769
+ item_id: item.id,
8770
+ output_index: outputIndex,
8771
+ name: item.name,
8772
+ input: item.input
8773
+ }));
8774
+ }
8775
+ events.push(next({
8776
+ type: "response.output_item.done",
8777
+ output_index: outputIndex,
8778
+ item
8779
+ }));
8780
+ }
8781
+ events.push(next({
8782
+ type: result.status === "incomplete" ? "response.incomplete" : result.status === "failed" ? "response.failed" : "response.completed",
8783
+ response: {
8784
+ ...result,
8785
+ output: []
8786
+ },
8787
+ copilot_usage: result.copilot_usage
8788
+ }));
8789
+ return events;
8790
+ }
8791
+ function createTranslationState(context) {
8792
+ return {
8793
+ blocks: /* @__PURE__ */ new Map(),
8794
+ compactionText: "",
8795
+ compactionToolCall: false,
8796
+ context,
8797
+ copilotUsage: null,
8798
+ createdAt: Math.floor(Date.now() / 1e3),
8799
+ initialized: false,
8800
+ messageStopped: false,
8801
+ model: context.publicModel,
8802
+ nextOutputIndex: 0,
8803
+ outputText: "",
8804
+ responseId: `resp_${Date.now().toString(36)}`,
8805
+ sequence: 0,
8806
+ stopReason: null,
8807
+ usage: {
8808
+ input_tokens: 0,
8809
+ output_tokens: 0
8810
+ }
8811
+ };
8812
+ }
8813
+ function initializeState(state, event) {
8814
+ if (event.type === "message_start") {
8815
+ state.responseId = toResponseId(event.message.id);
8816
+ state.model = event.message.model;
8817
+ state.usage = { ...event.message.usage };
8818
+ state.copilotUsage = event.message.copilot_usage ?? null;
8819
+ }
8820
+ state.initialized = true;
8821
+ }
8822
+ function* translateEvent(state, event) {
8823
+ switch (event.type) {
8824
+ case "message_start":
8825
+ state.usage = mergeUsage(state.usage, event.message.usage);
8826
+ state.copilotUsage = event.message.copilot_usage ?? state.copilotUsage;
8827
+ break;
8828
+ case "content_block_start":
8829
+ for (const translated of startContentBlock(state, event)) yield translated;
8830
+ break;
8831
+ case "content_block_delta":
8832
+ for (const translated of translateContentDelta(state, event)) yield translated;
8833
+ break;
8834
+ case "content_block_stop":
8835
+ for (const translated of closeContentBlock(state, event.index)) yield translated;
8836
+ break;
8837
+ case "message_delta":
8838
+ if (event.delta.stop_reason !== void 0) state.stopReason = event.delta.stop_reason;
8839
+ if (event.usage) state.usage = mergeUsage(state.usage, event.usage);
8840
+ state.copilotUsage = event.copilot_usage ?? state.copilotUsage;
8841
+ break;
8842
+ case "message_stop":
8843
+ for (const translated of closeAllBlocks(state)) yield translated;
8844
+ for (const translated of finishCompaction(state)) yield translated;
8845
+ state.messageStopped = true;
8846
+ yield createTerminalEvent(state);
8847
+ break;
8848
+ }
8849
+ }
8850
+ function* startContentBlock(state, event) {
8851
+ const block = event.content_block;
8852
+ if (state.context.compaction) {
8853
+ if (block.type === "text") state.compactionText += block.text;
8854
+ if (block.type === "tool_use" || block.type === "server_tool_use") state.compactionToolCall = true;
8855
+ return;
8856
+ }
8857
+ if (block.type === "text") {
8858
+ const item = {
8859
+ id: `msg_${state.responseId.slice(-18)}_${event.index}`,
8860
+ type: "message",
8861
+ role: "assistant",
8862
+ status: "in_progress",
8863
+ content: [{
8864
+ type: "output_text",
8865
+ text: block.text,
8866
+ annotations: []
8867
+ }]
8868
+ };
8869
+ const output = addOutput(state, item);
8870
+ state.blocks.set(event.index, {
8871
+ ...output,
8872
+ type: "message",
8873
+ text: block.text,
8874
+ done: false
8875
+ });
8876
+ state.outputText += block.text;
8877
+ yield createEvent(state, {
8878
+ type: "response.output_item.added",
8879
+ output_index: output.outputIndex,
8880
+ item: structuredClone(item)
8881
+ });
8882
+ yield createEvent(state, {
8883
+ type: "response.content_part.added",
8884
+ item_id: item.id,
8885
+ output_index: output.outputIndex,
8886
+ content_index: 0,
8887
+ part: {
8888
+ type: "output_text",
8889
+ text: "",
8890
+ annotations: []
8891
+ }
8892
+ });
8893
+ if (block.text) yield createEvent(state, {
8894
+ type: "response.output_text.delta",
8895
+ item_id: item.id,
8896
+ output_index: output.outputIndex,
8897
+ content_index: 0,
8898
+ delta: block.text
8899
+ });
8900
+ return;
8901
+ }
8902
+ if (block.type === "thinking") {
8903
+ const item = {
8904
+ id: `rs_${state.responseId.slice(-18)}_${event.index}`,
8905
+ type: "reasoning",
8906
+ status: "in_progress",
8907
+ summary: [],
8908
+ encrypted_content: EMPTY_SIGNATURE_ENCRYPTED_CONTENT
8909
+ };
8910
+ const output = addOutput(state, item);
8911
+ const reasoning = {
8912
+ ...output,
8913
+ type: "reasoning",
8914
+ signature: "",
8915
+ summaryStarted: false,
8916
+ text: "",
8917
+ done: false
8918
+ };
8919
+ state.blocks.set(event.index, reasoning);
8920
+ yield createEvent(state, {
8921
+ type: "response.output_item.added",
8922
+ output_index: output.outputIndex,
8923
+ item: structuredClone(item)
8924
+ });
8925
+ if (block.thinking) for (const translated of appendReasoningText(state, reasoning, block.thinking)) yield translated;
8926
+ return;
8927
+ }
8928
+ if (block.type === "tool_use") {
8929
+ const descriptor = resolveToolDescriptor(state.context.registry, block.name);
8930
+ const common = {
8931
+ id: `fc_${state.responseId.slice(-18)}_${event.index}`,
8932
+ call_id: block.id,
8933
+ name: descriptor.name,
8934
+ status: "in_progress",
8935
+ ...descriptor.namespace ? { namespace: descriptor.namespace } : {}
8936
+ };
8937
+ if (descriptor.kind === "custom") {
8938
+ const item = {
8939
+ ...common,
8940
+ type: "custom_tool_call",
8941
+ input: ""
8942
+ };
8943
+ const output = addOutput(state, item);
8944
+ const decoder = new CustomToolInputStreamDecoder();
8945
+ state.blocks.set(event.index, {
8946
+ ...output,
8947
+ type: "custom_tool",
8948
+ decoder,
8949
+ done: false
8950
+ });
8951
+ yield createEvent(state, {
8952
+ type: "response.output_item.added",
8953
+ output_index: output.outputIndex,
8954
+ item: structuredClone(item)
8955
+ });
8956
+ if (Object.keys(block.input).length > 0) {
8957
+ const delta = decoder.append(JSON.stringify(block.input));
8958
+ if (delta) yield createEvent(state, {
8959
+ type: "response.custom_tool_call_input.delta",
8960
+ item_id: item.id,
8961
+ output_index: output.outputIndex,
8962
+ delta
8963
+ });
8964
+ }
8965
+ return;
8966
+ }
8967
+ const item = {
8968
+ ...common,
8969
+ type: "function_call",
8970
+ arguments: ""
8971
+ };
8972
+ const output = addOutput(state, item);
8973
+ const initialInput = Object.keys(block.input).length > 0 ? JSON.stringify(block.input) : "";
8974
+ state.blocks.set(event.index, {
8975
+ ...output,
8976
+ type: "function_tool",
8977
+ done: false
8978
+ });
8979
+ yield createEvent(state, {
8980
+ type: "response.output_item.added",
8981
+ output_index: output.outputIndex,
8982
+ item: structuredClone(item)
8983
+ });
8984
+ if (initialInput) {
8985
+ item.arguments = initialInput;
8986
+ yield createEvent(state, {
8987
+ type: "response.function_call_arguments.delta",
8988
+ item_id: item.id,
8989
+ output_index: output.outputIndex,
8990
+ delta: initialInput
8991
+ });
8992
+ }
8993
+ }
8994
+ }
8995
+ function* translateContentDelta(state, event) {
8996
+ if (state.context.compaction) {
8997
+ if (event.delta.type === "text_delta") state.compactionText += event.delta.text;
8998
+ return;
8999
+ }
9000
+ const block = state.blocks.get(event.index);
9001
+ if (!block) return;
9002
+ if (event.delta.type === "text_delta" && block.type === "message") {
9003
+ block.text += event.delta.text;
9004
+ const part = block.item.content?.[0];
9005
+ if (part?.type === "output_text") part.text = block.text;
9006
+ state.outputText += event.delta.text;
9007
+ yield createEvent(state, {
9008
+ type: "response.output_text.delta",
9009
+ item_id: block.item.id,
9010
+ output_index: block.outputIndex,
9011
+ content_index: 0,
9012
+ delta: event.delta.text
9013
+ });
9014
+ return;
9015
+ }
9016
+ if (event.delta.type === "thinking_delta" && block.type === "reasoning") {
9017
+ for (const translated of appendReasoningText(state, block, event.delta.thinking)) yield translated;
9018
+ return;
9019
+ }
9020
+ if (event.delta.type === "signature_delta" && block.type === "reasoning") {
9021
+ block.signature += event.delta.signature;
9022
+ block.item.encrypted_content = block.signature || EMPTY_SIGNATURE_ENCRYPTED_CONTENT;
9023
+ return;
9024
+ }
9025
+ if (event.delta.type === "input_json_delta" && block.type === "function_tool") {
9026
+ block.item.arguments += event.delta.partial_json;
9027
+ yield createEvent(state, {
9028
+ type: "response.function_call_arguments.delta",
9029
+ item_id: block.item.id,
9030
+ output_index: block.outputIndex,
9031
+ delta: event.delta.partial_json
9032
+ });
9033
+ return;
9034
+ }
9035
+ if (event.delta.type === "input_json_delta" && block.type === "custom_tool") {
9036
+ const delta = block.decoder.append(event.delta.partial_json);
9037
+ if (delta) yield createEvent(state, {
9038
+ type: "response.custom_tool_call_input.delta",
9039
+ item_id: block.item.id,
9040
+ output_index: block.outputIndex,
9041
+ delta
9042
+ });
9043
+ }
9044
+ }
9045
+ function* appendReasoningText(state, block, text) {
9046
+ if (!text) return;
9047
+ if (!block.summaryStarted) {
9048
+ block.summaryStarted = true;
9049
+ yield createEvent(state, {
9050
+ type: "response.reasoning_summary_part.added",
9051
+ item_id: block.item.id,
9052
+ output_index: block.outputIndex,
9053
+ summary_index: 0,
9054
+ part: {
9055
+ type: "summary_text",
9056
+ text: ""
9057
+ }
9058
+ });
9059
+ }
9060
+ block.text += text;
9061
+ block.item.summary = [{
9062
+ type: "summary_text",
9063
+ text: block.text
9064
+ }];
9065
+ yield createEvent(state, {
9066
+ type: "response.reasoning_summary_text.delta",
9067
+ item_id: block.item.id,
9068
+ output_index: block.outputIndex,
9069
+ summary_index: 0,
9070
+ delta: text
9071
+ });
9072
+ }
9073
+ function* closeContentBlock(state, index) {
9074
+ const block = state.blocks.get(index);
9075
+ if (!block || block.done) return;
9076
+ if (block.type === "message") {
9077
+ yield createEvent(state, {
9078
+ type: "response.output_text.done",
9079
+ item_id: block.item.id,
9080
+ output_index: block.outputIndex,
9081
+ content_index: 0,
9082
+ text: block.text
9083
+ });
9084
+ const part = block.item.content?.[0];
9085
+ if (part) yield createEvent(state, {
9086
+ type: "response.content_part.done",
9087
+ item_id: block.item.id,
9088
+ output_index: block.outputIndex,
9089
+ content_index: 0,
9090
+ part: structuredClone(part)
9091
+ });
9092
+ } else if (block.type === "reasoning") {
9093
+ if (block.text) {
9094
+ const part = {
9095
+ type: "summary_text",
9096
+ text: block.text
9097
+ };
9098
+ yield createEvent(state, {
9099
+ type: "response.reasoning_summary_text.done",
9100
+ item_id: block.item.id,
9101
+ output_index: block.outputIndex,
9102
+ summary_index: 0,
9103
+ text: block.text
9104
+ });
9105
+ yield createEvent(state, {
9106
+ type: "response.reasoning_summary_part.done",
9107
+ item_id: block.item.id,
9108
+ output_index: block.outputIndex,
9109
+ summary_index: 0,
9110
+ part
9111
+ });
9112
+ }
9113
+ block.item.encrypted_content = block.signature || EMPTY_SIGNATURE_ENCRYPTED_CONTENT;
9114
+ } else if (block.type === "custom_tool") {
9115
+ const input = block.decoder.finish();
9116
+ block.item.input = input;
9117
+ yield createEvent(state, {
9118
+ type: "response.custom_tool_call_input.done",
9119
+ item_id: block.item.id,
9120
+ output_index: block.outputIndex,
9121
+ name: block.item.name,
9122
+ input
9123
+ });
9124
+ } else yield createEvent(state, {
9125
+ type: "response.function_call_arguments.done",
9126
+ item_id: block.item.id,
9127
+ output_index: block.outputIndex,
9128
+ name: block.item.name,
9129
+ arguments: block.item.arguments
9130
+ });
9131
+ block.item.status = "completed";
9132
+ block.done = true;
9133
+ yield createEvent(state, {
9134
+ type: "response.output_item.done",
9135
+ output_index: block.outputIndex,
9136
+ item: structuredClone(block.item)
9137
+ });
9138
+ state.blocks.delete(index);
9139
+ }
9140
+ function* closeAllBlocks(state) {
9141
+ for (const index of [...state.blocks.keys()].sort((left, right) => left - right)) for (const translated of closeContentBlock(state, index)) yield translated;
9142
+ }
9143
+ function* finishCompaction(state) {
9144
+ if (!state.context.compaction) return;
9145
+ if (state.compactionToolCall) throw new ResponsesMessagesTranslationError("Messages API attempted a tool call during compaction", 502);
9146
+ const summary = state.compactionText.trim();
9147
+ if (!summary) throw new ResponsesMessagesTranslationError("Messages API compaction stream did not contain a text summary", 502);
9148
+ const item = {
9149
+ id: `cmp_${state.responseId.slice(-24)}`,
9150
+ type: "compaction",
9151
+ encrypted_content: encodeMessagesCompaction(summary)
9152
+ };
9153
+ const output = addOutput(state, item);
9154
+ yield createEvent(state, {
9155
+ type: "response.output_item.added",
9156
+ output_index: output.outputIndex,
9157
+ item
9158
+ });
9159
+ yield createEvent(state, {
9160
+ type: "response.output_item.done",
9161
+ output_index: output.outputIndex,
9162
+ item
9163
+ });
9164
+ }
9165
+ function addOutput(state, item) {
9166
+ const outputIndex = state.nextOutputIndex;
9167
+ state.nextOutputIndex += 1;
9168
+ return {
9169
+ item,
9170
+ outputIndex,
9171
+ done: false
9172
+ };
9173
+ }
9174
+ function createLifecycleEvent(state, type) {
9175
+ return createEvent(state, {
9176
+ type,
9177
+ response: createMessagesBackedResponsesResult({
9178
+ context: state.context,
9179
+ createdAt: state.createdAt,
9180
+ id: state.responseId,
9181
+ output: [],
9182
+ outputText: "",
9183
+ status: "in_progress",
9184
+ usage: null
9185
+ })
9186
+ });
9187
+ }
9188
+ function createTerminalEvent(state) {
9189
+ const finish = resolveFinish(state.stopReason);
9190
+ const response = createMessagesBackedResponsesResult({
9191
+ context: state.context,
9192
+ createdAt: state.createdAt,
9193
+ id: state.responseId,
9194
+ output: [],
9195
+ outputText: state.context.compaction ? "" : state.outputText,
9196
+ status: finish.status,
9197
+ incompleteReason: finish.incompleteReason,
9198
+ usage: translateAnthropicUsage(state.usage),
9199
+ copilotUsage: state.copilotUsage
9200
+ });
9201
+ return createEvent(state, {
9202
+ type: finish.status === "incomplete" ? "response.incomplete" : "response.completed",
9203
+ response,
9204
+ copilot_usage: state.copilotUsage
9205
+ });
9206
+ }
9207
+ function createErrorEvent(state, error) {
9208
+ const message = error instanceof Error ? error.message : String(error);
9209
+ return createEvent(state, {
9210
+ type: "error",
9211
+ code: "messages_translation_error",
9212
+ message,
9213
+ param: null,
9214
+ error: {
9215
+ type: "api_error",
9216
+ code: "messages_translation_error",
9217
+ message
9218
+ }
9219
+ });
9220
+ }
9221
+ function createFailedEvent(state, error) {
9222
+ const message = error instanceof Error ? error.message : String(error);
9223
+ return createEvent(state, {
9224
+ type: "response.failed",
9225
+ response: createMessagesBackedResponsesResult({
9226
+ context: state.context,
9227
+ createdAt: state.createdAt,
9228
+ id: state.responseId,
9229
+ output: [],
9230
+ outputText: state.outputText,
9231
+ status: "failed",
9232
+ usage: translateAnthropicUsage(state.usage),
9233
+ copilotUsage: state.copilotUsage,
9234
+ error: {
9235
+ code: "messages_translation_error",
9236
+ message
9237
+ }
9238
+ }),
9239
+ copilot_usage: state.copilotUsage
9240
+ });
9241
+ }
9242
+ function createEvent(state, value) {
9243
+ return {
9244
+ ...value,
9245
+ sequence_number: state.sequence++
9246
+ };
9247
+ }
9248
+ function resolveFinish(stopReason) {
9249
+ if (stopReason === "max_tokens") return {
9250
+ status: "incomplete",
9251
+ incompleteReason: "max_output_tokens"
9252
+ };
9253
+ if (stopReason === "refusal") return {
9254
+ status: "incomplete",
9255
+ incompleteReason: "content_filter"
9256
+ };
9257
+ return { status: "completed" };
9258
+ }
9259
+ function mergeUsage(current, incoming) {
9260
+ return {
9261
+ ...current,
9262
+ ...incoming,
9263
+ input_tokens: incoming.input_tokens ?? current.input_tokens,
9264
+ output_tokens: incoming.output_tokens ?? current.output_tokens
9265
+ };
9266
+ }
9267
+ function parseAnthropicEvent(data) {
9268
+ try {
9269
+ const parsed = JSON.parse(data);
9270
+ if (typeof parsed === "object" && parsed !== null && "type" in parsed && typeof parsed.type === "string") return parsed;
9271
+ } catch {}
9272
+ throw new ResponsesMessagesTranslationError("Messages API returned malformed streaming JSON", 502);
9273
+ }
9274
+ //#endregion
9275
+ //#region src/routes/responses/messages-handler.ts
9276
+ const logger$3 = createHandlerLogger("responses-messages-handler");
9277
+ const responsesMessagesDependencies = { handleCompletionPayload };
9278
+ async function handleResponsesViaMessages(c, options) {
9279
+ try {
9280
+ const translation = translateResponsesToMessages({
9281
+ ...options.payload,
9282
+ model: options.publicModel
9283
+ }, {
9284
+ model: options.targetModel,
9285
+ publicModel: options.publicModel
9286
+ });
9287
+ const context = translation;
9288
+ debugJson(logger$3, "Translated Messages request:", {
9289
+ payload: translation.messagesPayload,
9290
+ publicModel: options.publicModel,
9291
+ targetModel: options.targetModel
9292
+ });
9293
+ const messagesResponse = await responsesMessagesDependencies.handleCompletionPayload(c, translation.messagesPayload, {
9294
+ compactType: translation.compaction ? 1 : void 0,
9295
+ skipClaudeAutoModel: true,
9296
+ skipModelMapping: true,
9297
+ skipWebSearch: true,
9298
+ usageEndpoint: "responses"
9299
+ });
9300
+ if (!messagesResponse.ok) return messagesResponse;
9301
+ if ((messagesResponse.headers.get("content-type") ?? "").includes("text/event-stream")) {
9302
+ if (!translation.messagesPayload.stream) throw new ResponsesMessagesTranslationError("Messages API returned a stream for a non-streaming Responses request", 502);
9303
+ return streamTranslatedMessagesEvents(c, messagesResponse, context);
9304
+ }
9305
+ const body = await messagesResponse.json();
9306
+ if (!isAnthropicResponse(body)) throw new ResponsesMessagesTranslationError("Messages API returned an invalid response body", 502);
9307
+ const result = translateAnthropicToResponses(body, context);
9308
+ debugJson(logger$3, "Translated Responses result:", result);
9309
+ if (!translation.messagesPayload.stream) return c.json(result);
9310
+ return streamSSE(c, async (stream) => {
9311
+ for (const event of responsesResultToStreamEvents(result)) await stream.writeSSE({
9312
+ event: event.type,
9313
+ data: JSON.stringify(event)
9314
+ });
9315
+ });
9316
+ } catch (error) {
9317
+ if (error instanceof ResponsesMessagesTranslationError) return c.json({ error: {
9318
+ message: error.message,
9319
+ type: "invalid_request_error"
9320
+ } }, error.status);
9321
+ throw error;
9322
+ }
9323
+ }
9324
+ function streamTranslatedMessagesEvents(c, response, context) {
9325
+ return streamSSE(c, async (stream) => {
9326
+ for await (const event of translateMessagesStream(events(response), context)) {
9327
+ debugJson(logger$3, "Translated Responses stream event:", event);
9328
+ await stream.writeSSE({
9329
+ event: event.type,
9330
+ data: JSON.stringify(event)
9331
+ });
9332
+ }
9333
+ });
9334
+ }
9335
+ function isAnthropicResponse(value) {
9336
+ return typeof value === "object" && value !== null && "type" in value && value.type === "message" && "content" in value && Array.isArray(value.content);
9337
+ }
9338
+ //#endregion
7468
9339
  //#region src/routes/provider/responses/handler.ts
7469
9340
  const logger$2 = createHandlerLogger("provider-responses-handler");
7470
9341
  async function handleProviderResponsesForProvider(c, options) {
@@ -7474,7 +9345,17 @@ async function handleProviderResponsesForProvider(c, options) {
7474
9345
  provider
7475
9346
  });
7476
9347
  const providerConfig = await resolveProviderConfig(provider);
7477
- if (!providerConfig || resolveEffectiveProviderType(providerConfig, payload.model) !== "openai-responses") return c.json({ error: {
9348
+ if (!providerConfig) return c.json({ error: {
9349
+ message: `Provider '${provider}' does not support the /v1/responses endpoint`,
9350
+ type: "invalid_request_error"
9351
+ } }, 400);
9352
+ const effectiveType = resolveEffectiveProviderType(providerConfig, payload.model);
9353
+ if (effectiveType === "anthropic" || effectiveType === "openai-compatible") return await handleResponsesViaMessages(c, {
9354
+ payload,
9355
+ publicModel: options.publicModel ?? payload.model,
9356
+ targetModel: `${provider}/${payload.model}`
9357
+ });
9358
+ if (effectiveType !== "openai-responses") return c.json({ error: {
7478
9359
  message: `Provider '${provider}' does not support the /v1/responses endpoint`,
7479
9360
  type: "invalid_request_error"
7480
9361
  } }, 400);
@@ -7648,19 +9529,22 @@ const handleItemId = (parsed, tracker) => {
7648
9529
  const logger$1 = createHandlerLogger("responses-handler");
7649
9530
  const responsesHandlerDependencies = {
7650
9531
  createResponses,
7651
- isResponsesApiWebSearchEnabled
9532
+ findEndpointModel,
9533
+ isResponsesApiWebSearchEnabled,
9534
+ resolveMappedModel
7652
9535
  };
7653
9536
  const handleResponses = async (c) => {
7654
9537
  const payload = await c.req.json();
7655
9538
  const requestedModel = payload.model;
7656
- payload.model = resolveMappedModel(payload.model);
9539
+ payload.model = responsesHandlerDependencies.resolveMappedModel(payload.model);
7657
9540
  if (payload.model !== requestedModel) consola.debug(`Resolved model mapping: ${requestedModel} -> ${payload.model}`);
7658
9541
  const providerModelAlias = parseProviderModelAlias(payload.model);
7659
9542
  if (providerModelAlias) {
7660
9543
  payload.model = providerModelAlias.model;
7661
9544
  return await handleProviderResponsesForProvider(c, {
7662
9545
  payload,
7663
- provider: providerModelAlias.provider
9546
+ provider: providerModelAlias.provider,
9547
+ publicModel: requestedModel
7664
9548
  });
7665
9549
  }
7666
9550
  debugJson(logger$1, "Responses request payload:", payload);
@@ -7672,6 +9556,21 @@ const handleResponses = async (c) => {
7672
9556
  logger$1.debug("Generated request ID:", requestId);
7673
9557
  const fallbackSessionId = sessionId ?? getUUID(requestId);
7674
9558
  logger$1.debug("Extracted session ID:", fallbackSessionId);
9559
+ const selectedModel = responsesHandlerDependencies.findEndpointModel(payload.model);
9560
+ payload.model = selectedModel?.id ?? payload.model;
9561
+ const responsesTransport = getResponsesTransportForModel(selectedModel);
9562
+ if (!responsesTransport) {
9563
+ const supportedEndpoints = selectedModel?.supported_endpoints ?? [];
9564
+ if (supportedEndpoints.includes("/v1/messages") || supportedEndpoints.includes("/chat/completions")) return await handleResponsesViaMessages(c, {
9565
+ payload,
9566
+ publicModel: requestedModel,
9567
+ targetModel: payload.model
9568
+ });
9569
+ return c.json({ error: {
9570
+ message: "This model does not support the responses endpoint. Please choose a different model.",
9571
+ type: "invalid_request_error"
9572
+ } }, 400);
9573
+ }
7675
9574
  const recordUsage = createCopilotTokenUsageRecorder({
7676
9575
  endpoint: "responses",
7677
9576
  fallbackSessionId,
@@ -7679,12 +9578,6 @@ const handleResponses = async (c) => {
7679
9578
  });
7680
9579
  removeUnsupportedTools(payload);
7681
9580
  if (!responsesHandlerDependencies.isResponsesApiWebSearchEnabled()) removeWebSearchTool(payload);
7682
- const selectedModel = state.models?.data.find((model) => model.id === payload.model);
7683
- const responsesTransport = getResponsesTransportForModel(selectedModel);
7684
- if (!responsesTransport) return c.json({ error: {
7685
- message: "This model does not support the responses endpoint. Please choose a different model.",
7686
- type: "invalid_request_error"
7687
- } }, 400);
7688
9581
  const sanitizedImageCount = sanitizeOversizedInputImages(payload, selectedModel?.capabilities.limits.vision?.max_prompt_image_size);
7689
9582
  if (sanitizedImageCount > 0) logger$1.warn(`Omitted ${sanitizedImageCount} oversized input image(s) before forwarding to Copilot Responses`);
7690
9583
  const maxPromptTokens = selectedModel?.capabilities.limits.max_prompt_tokens;
@@ -7917,4 +9810,4 @@ server.route("/:provider/images", providerImageRoutes);
7917
9810
  //#endregion
7918
9811
  export { server };
7919
9812
 
7920
- //# sourceMappingURL=server-DhaNHHv3.js.map
9813
+ //# sourceMappingURL=server-39Y0II3a.js.map