@jeffreycao/copilot-api 2.7.16 → 2.7.18

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.
Files changed (31) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/{auth-sKq0qru1.js → auth-BI9j5Vof.js} +10 -5
  4. package/dist/auth-BI9j5Vof.js.map +1 -0
  5. package/dist/auth-Dv6K056n.js +2 -0
  6. package/dist/{config-BKA4Y1t8.js → config-0pYepRvK.js} +15 -8
  7. package/dist/config-0pYepRvK.js.map +1 -0
  8. package/dist/{config-store-CC5TNG7V.js → config-store-DeipVulH.js} +3 -2
  9. package/dist/config-store-DeipVulH.js.map +1 -0
  10. package/dist/{copilot-runtime-XKDhY-sV.js → copilot-runtime-D7uXIiMk.js} +3 -3
  11. package/dist/{copilot-runtime-XKDhY-sV.js.map → copilot-runtime-D7uXIiMk.js.map} +1 -1
  12. package/dist/{debug-BPNjSHgl.js → debug-C26JAmhE.js} +3 -3
  13. package/dist/{debug-BPNjSHgl.js.map → debug-C26JAmhE.js.map} +1 -1
  14. package/dist/main.js +4 -4
  15. package/dist/{provider-Dg-3-rrN.js → provider-BkN9E04x.js} +2 -2
  16. package/dist/{provider-Dg-3-rrN.js.map → provider-BkN9E04x.js.map} +1 -1
  17. package/dist/{provider-management-CBrc2nDg.js → provider-management-CLV6-gBT.js} +2 -2
  18. package/dist/{provider-management-CBrc2nDg.js.map → provider-management-CLV6-gBT.js.map} +1 -1
  19. package/dist/{server-04fZfBz1.js → server-D8LzQcmu.js} +644 -73
  20. package/dist/server-D8LzQcmu.js.map +1 -0
  21. package/dist/{start-qcGeG0TU.js → start-Xf1MJrNI.js} +7 -7
  22. package/dist/{start-qcGeG0TU.js.map → start-Xf1MJrNI.js.map} +1 -1
  23. package/dist/{token-CWFRUUIv.js → token-OftpnSxC.js} +3 -3
  24. package/dist/{token-CWFRUUIv.js.map → token-OftpnSxC.js.map} +1 -1
  25. package/package.json +1 -1
  26. package/pages/index.html +4 -4
  27. package/dist/auth-DuGyJdjW.js +0 -2
  28. package/dist/auth-sKq0qru1.js.map +0 -1
  29. package/dist/config-BKA4Y1t8.js.map +0 -1
  30. package/dist/config-store-CC5TNG7V.js.map +0 -1
  31. package/dist/server-04fZfBz1.js.map +0 -1
@@ -1,9 +1,9 @@
1
- import { D as state, E as isGitHubCopilotEnabled, O as HTTPError, S as PATHS, a as getAnthropicApiKey, c as getConfig, d as getUpstreamTransportConfig, g as isResponsesApiWebSocketEnabled, h as isResponsesApiWebSearchEnabled, i as getAlphaSearchModel, j as forwardError, l as getMessageApiWebSearchModel, m as isMessagesApiEnabled, o as getClaudeAutoModel, p as isAlphaSearchCodexPriorityEnabled, s as getClaudeTokenMultiplier, u as getOpencodeModelContextWindow, w as GITHUB_COPILOT_PROVIDER, y as reloadConfig } from "./config-store-CC5TNG7V.js";
2
- import { A as resolveMappedModel, C as getModelResponsesApiCompactThreshold$1, D as isContextManagementEnabledForMessages, E as getSmallModelForProvider, O as isContextManagementEnabledForResponses, S as getModelMappings, T as getSmallModel, _ as getModelsDevModelMaxOutputTokens, d as isProviderModelVisible, f as resolveProviderModelsDevId, g as getModelsDevModel, h as getBuiltinProviderModelRecords, i as listEnabledProviders, j as setModelMappings, k as isGpt56OrAbove, l as getLocalProviderModelRecords, m as builtinProviderModelRegistry, n as getRawProviderConfig, o as resolveEffectiveProviderType, p as usesModelsDevModelCatalog, s as resolveProviderConfigForModel, t as getProviderConfig, u as getProviderModelConfig, v as getModelsDevModelPricing, w as getReasoningEffortForModel, x as getExtraPromptForModel } from "./config-BKA4Y1t8.js";
3
- import { $ as resolveTraceId$1, C as isOpencodeOauthApp, E as prepareMessageProxyHeaders, G as XAI_API_BASE_URL, J as CODEX_API_BASE_URL, L as getXaiAccessToken, M as compactTextOnlyGuard, N as createAuthMiddleware, O as compactAutoContinuePromptStarts, P as getConfiguredAdminApiKeys, Q as requestContext, S as copilotWebSocketHeaders, T as prepareInteractionHeaders, U as readGitHubToken, W as readGitHubTokenFromEnv, X as forwardCodexResponses, Y as buildCodexRequestHeaders, Z as generateTraceId, _ as parseUserIdMetadata, at as createPooledWebSocketStream, b as copilotHeaders, ct as stripInternalRequestHeaders, d as generateRequestIdFromPayload, et as fetchUpstreamWithLifecycle, f as getRootSessionId, g as isResponsesStream, h as isNullish, it as getResponsesStreamTerminalDisposition, j as compactSystemPromptStarts, k as compactMessageSections, m as isAsyncIterable, n as invalidateCodexRuntime, nt as createResponsesSafeStream, ot as createWebSocketUrl, p as getUUID, rt as encodePoolKeyPart, s as setupCodexToken, tt as createResponsesHttpEventStream, u as stopCopilotRefreshLoop, v as getCopilotUsage, w as prepareForCompact, y as copilotBaseUrl } from "./token-CWFRUUIv.js";
1
+ import { D as state, E as isGitHubCopilotEnabled, O as HTTPError, S as PATHS, a as getAnthropicApiKey, c as getConfig, d as getUpstreamTransportConfig, g as isResponsesApiWebSocketEnabled, h as isResponsesApiWebSearchEnabled, i as getAlphaSearchModel, j as forwardError, l as getMessageApiWebSearchModel, m as isMessagesApiEnabled, o as getClaudeAutoModel, p as isAlphaSearchCodexPriorityEnabled, s as getClaudeTokenMultiplier, u as getOpencodeModelContextWindow, w as GITHUB_COPILOT_PROVIDER, y as reloadConfig } from "./config-store-DeipVulH.js";
2
+ import { A as resolveMappedModel, C as getModelResponsesApiCompactThreshold$1, D as isContextManagementEnabledForMessages, E as getSmallModelForProvider, O as isContextManagementEnabledForResponses, S as getModelMappings, T as getSmallModel, _ as getModelsDevModelMaxOutputTokens, a as normalizeProviderBaseUrl, d as isProviderModelVisible, f as resolveProviderModelsDevId, g as getModelsDevModel, h as getBuiltinProviderModelRecords, i as listEnabledProviders, j as setModelMappings, k as isGpt56OrAbove, l as getLocalProviderModelRecords, m as builtinProviderModelRegistry, n as getRawProviderConfig, o as resolveEffectiveProviderType, p as usesModelsDevModelCatalog, s as resolveProviderConfigForModel, t as getProviderConfig, u as getProviderModelConfig, v as getModelsDevModelPricing, w as getReasoningEffortForModel, x as getExtraPromptForModel } from "./config-0pYepRvK.js";
3
+ import { $ as resolveTraceId$1, C as isOpencodeOauthApp, E as prepareMessageProxyHeaders, G as XAI_API_BASE_URL, J as CODEX_API_BASE_URL, L as getXaiAccessToken, M as compactTextOnlyGuard, N as createAuthMiddleware, O as compactAutoContinuePromptStarts, P as getConfiguredAdminApiKeys, Q as requestContext, S as copilotWebSocketHeaders, T as prepareInteractionHeaders, U as readGitHubToken, W as readGitHubTokenFromEnv, X as forwardCodexResponses, Y as buildCodexRequestHeaders, Z as generateTraceId, _ as parseUserIdMetadata, at as createPooledWebSocketStream, b as copilotHeaders, ct as stripInternalRequestHeaders, d as generateRequestIdFromPayload, et as fetchUpstreamWithLifecycle, f as getRootSessionId, g as isResponsesStream, h as isNullish, it as getResponsesStreamTerminalDisposition, j as compactSystemPromptStarts, k as compactMessageSections, m as isAsyncIterable, n as invalidateCodexRuntime, nt as createResponsesSafeStream, ot as createWebSocketUrl, p as getUUID, rt as encodePoolKeyPart, s as setupCodexToken, tt as createResponsesHttpEventStream, u as stopCopilotRefreshLoop, v as getCopilotUsage, w as prepareForCompact, y as copilotBaseUrl } from "./token-OftpnSxC.js";
4
4
  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-CcvaqM03.js";
5
- import { n as isProviderAgentModelVisible, t as getProviderAgentModels } from "./provider-management-CBrc2nDg.js";
6
- import { n as stopModelsRefreshLoop, t as setupCopilotRuntime } from "./copilot-runtime-XKDhY-sV.js";
5
+ import { n as isProviderAgentModelVisible, t as getProviderAgentModels } from "./provider-management-CLV6-gBT.js";
6
+ import { n as stopModelsRefreshLoop, t as setupCopilotRuntime } from "./copilot-runtime-D7uXIiMk.js";
7
7
  import consola from "consola";
8
8
  import { createHash, randomUUID } from "node:crypto";
9
9
  import fs, { createWriteStream, readFileSync, rmSync } from "node:fs";
@@ -1966,6 +1966,8 @@ const createTimeoutDispatcher = (timeoutMs) => ({ dispatch(options, handler) {
1966
1966
  } });
1967
1967
  //#endregion
1968
1968
  //#region src/services/providers/provider-proxy.ts
1969
+ const OPENCODE_GO_PROVIDER_NAME = "opencode-go";
1970
+ const OPENCODE_SESSION_HEADER = "x-opencode-session";
1969
1971
  const SHARED_FORWARDABLE_HEADERS = ["accept", "user-agent"];
1970
1972
  const ANTHROPIC_FORWARDABLE_HEADERS = ["anthropic-version", "anthropic-beta"];
1971
1973
  const STRIPPED_RESPONSE_HEADERS = [
@@ -1981,11 +1983,19 @@ const STRIPPED_RESPONSE_HEADERS = [
1981
1983
  "upgrade"
1982
1984
  ];
1983
1985
  function resolveProviderEndpointUrl(providerConfig, endpoint) {
1986
+ if (providerConfig.name === OPENCODE_GO_PROVIDER_NAME) {
1987
+ const base = normalizeProviderBaseUrl(providerConfig.baseUrl);
1988
+ return `${/\/v\d+(?:alpha|beta)?$/u.test(base) ? base : `${base}/v1`}/${endpoint}`;
1989
+ }
1990
+ if (providerConfig.type === "google") {
1991
+ const base = providerConfig.baseUrl.replace(/\/+$/u, "");
1992
+ return `${/\/v\d+(?:alpha|beta)?$/u.test(base) ? base : `${base}/v1beta`}/${endpoint}`;
1993
+ }
1984
1994
  return `${providerConfig.modelsDevProviderId ? providerConfig.baseUrl.replace(/\/(?:chat\/completions|responses)$/u, "") : `${providerConfig.baseUrl}/v1`}/${endpoint}`;
1985
1995
  }
1986
1996
  function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
1987
1997
  const authHeaders = {};
1988
- if (providerConfig.authType === "x-api-key") authHeaders["x-api-key"] = providerConfig.apiKey;
1998
+ if (providerConfig.authType === "x-api-key" || providerConfig.authType === "x-goog-api-key") authHeaders[providerConfig.authType] = providerConfig.apiKey;
1989
1999
  else authHeaders.authorization = `Bearer ${providerConfig.apiKey}`;
1990
2000
  const headers = {
1991
2001
  "content-type": "application/json",
@@ -2004,8 +2014,6 @@ function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
2004
2014
  }
2005
2015
  return headers;
2006
2016
  }
2007
- const OPENCODE_GO_PROVIDER_NAME = "opencode-go";
2008
- const OPENCODE_SESSION_HEADER = "x-opencode-session";
2009
2017
  const resolveOpencodeMessagesSession = (payload) => {
2010
2018
  const sessionAffinity = requestContext.getStore()?.sessionAffinity?.trim();
2011
2019
  if (sessionAffinity) return sessionAffinity;
@@ -2093,12 +2101,51 @@ async function forwardProviderResponses(providerConfig, payload, requestHeaders,
2093
2101
  }
2094
2102
  const PROVIDER_MODELS_TIMEOUT_MS = 15e3;
2095
2103
  async function forwardProviderModels(providerConfig, requestHeaders) {
2104
+ if (providerConfig.type === "google") return await forwardGoogleModels(providerConfig, requestHeaders);
2096
2105
  return await fetch(resolveProviderEndpointUrl(providerConfig, "models"), {
2097
2106
  method: "GET",
2098
2107
  headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
2099
2108
  signal: AbortSignal.timeout(PROVIDER_MODELS_TIMEOUT_MS)
2100
2109
  });
2101
2110
  }
2111
+ async function forwardGoogleModels(provider, requestHeaders) {
2112
+ const data = [];
2113
+ const pageTokens = /* @__PURE__ */ new Set();
2114
+ let pageToken;
2115
+ const signal = AbortSignal.timeout(PROVIDER_MODELS_TIMEOUT_MS);
2116
+ do {
2117
+ const url = new URL(resolveProviderEndpointUrl(provider, "models"));
2118
+ url.searchParams.set("pageSize", "1000");
2119
+ if (pageToken) url.searchParams.set("pageToken", pageToken);
2120
+ const upstream = await fetch(url, {
2121
+ headers: buildProviderUpstreamHeaders(provider, requestHeaders),
2122
+ signal
2123
+ });
2124
+ if (!upstream.ok) return upstream;
2125
+ const body = await upstream.json();
2126
+ for (const model of body.models ?? []) {
2127
+ if (!model.supportedGenerationMethods?.includes("generateContent")) continue;
2128
+ data.push({
2129
+ id: model.name.replace(/^models\//u, ""),
2130
+ object: "model",
2131
+ owned_by: provider.name,
2132
+ name: model.displayName,
2133
+ display_name: model.displayName,
2134
+ description: model.description,
2135
+ context_window: model.inputTokenLimit,
2136
+ max_output_tokens: model.outputTokenLimit
2137
+ });
2138
+ }
2139
+ pageToken = body.nextPageToken;
2140
+ if (pageToken && pageTokens.has(pageToken)) throw new Error("Google models returned a repeated page token");
2141
+ if (pageToken) pageTokens.add(pageToken);
2142
+ } while (pageToken);
2143
+ return Response.json({
2144
+ object: "list",
2145
+ data,
2146
+ has_more: false
2147
+ });
2148
+ }
2102
2149
  /** Align with Codex images: long-running generation/edits need a generous cap. */
2103
2150
  const PROVIDER_IMAGES_TIMEOUT_MS = 9e5;
2104
2151
  const providerImagesDispatcher = createTimeoutDispatcher(PROVIDER_IMAGES_TIMEOUT_MS);
@@ -2142,7 +2189,7 @@ async function forwardProviderImages(providerConfig, request, operation) {
2142
2189
  }
2143
2190
  //#endregion
2144
2191
  //#region src/routes/alpha-search/alpha-search-responses.ts
2145
- const logger$18 = createHandlerLogger("alpha-search-responses-handler");
2192
+ const logger$19 = createHandlerLogger("alpha-search-responses-handler");
2146
2193
  const SESSION_TTL_MS = 36e5;
2147
2194
  const MAX_SESSIONS = 128;
2148
2195
  const MAX_URL_REFERENCES = 256;
@@ -2329,7 +2376,7 @@ function buildInstruction(operations, responseLength) {
2329
2376
  function unavailableReference(refId) {
2330
2377
  return `Reference ${JSON.stringify(refId)} is unavailable or expired. Search or open the URL again.`;
2331
2378
  }
2332
- function invalidRequest$1(c, message) {
2379
+ function invalidRequest$2(c, message) {
2333
2380
  return c.json({ error: {
2334
2381
  message,
2335
2382
  type: "invalid_request_error"
@@ -2472,13 +2519,13 @@ async function resolveRemoteModel(c, request, provider) {
2472
2519
  message: `Provider '${provider}' not found or disabled`,
2473
2520
  type: "invalid_request_error"
2474
2521
  } }, 404);
2475
- if (alphaSearchResponsesDependencies.resolveEffectiveProviderType(providerConfig, model) !== "openai-responses") return invalidRequest$1(c, `Provider '${provider}' does not support the /v1/responses endpoint required for alpha search`);
2522
+ if (alphaSearchResponsesDependencies.resolveEffectiveProviderType(providerConfig, model) !== "openai-responses") return invalidRequest$2(c, `Provider '${provider}' does not support the /v1/responses endpoint required for alpha search`);
2476
2523
  return {
2477
2524
  model,
2478
2525
  providerConfig: resolveProviderConfigForModel(providerConfig, model)
2479
2526
  };
2480
2527
  }
2481
- if (!alphaSearchResponsesDependencies.findEndpointModel(model)?.supported_endpoints?.includes("/responses")) return invalidRequest$1(c, `Model '${model}' does not support the Copilot Responses endpoint required for alpha search`);
2528
+ if (!alphaSearchResponsesDependencies.findEndpointModel(model)?.supported_endpoints?.includes("/responses")) return invalidRequest$2(c, `Model '${model}' does not support the Copilot Responses endpoint required for alpha search`);
2482
2529
  return { model };
2483
2530
  }
2484
2531
  function createRemoteResponsesPayload(request, model, instruction) {
@@ -2500,14 +2547,14 @@ function createRemoteResponsesPayload(request, model, instruction) {
2500
2547
  };
2501
2548
  }
2502
2549
  async function requestProviderSearch(c, providerConfig, payload, model, sessionId) {
2503
- debugJson(logger$18, "Alpha search provider Responses request:", {
2550
+ debugJson(logger$19, "Alpha search provider Responses request:", {
2504
2551
  payload,
2505
2552
  provider: providerConfig.name
2506
2553
  });
2507
2554
  const upstreamResponse = await forwardProviderResponses(providerConfig, payload, c.req.raw.headers, { clientSignal: c.req.raw.signal });
2508
2555
  if (!upstreamResponse.ok) throw new HTTPError(`Failed to create ${providerConfig.name} responses for alpha search`, upstreamResponse);
2509
2556
  const result = await upstreamResponse.json();
2510
- debugJson(logger$18, "Alpha search provider Responses result:", {
2557
+ debugJson(logger$19, "Alpha search provider Responses result:", {
2511
2558
  provider: providerConfig.name,
2512
2559
  result
2513
2560
  });
@@ -2523,7 +2570,7 @@ async function requestProviderSearch(c, providerConfig, payload, model, sessionI
2523
2570
  return result;
2524
2571
  }
2525
2572
  async function requestCopilotSearch(payload, model, requestId, sessionId, clientSignal) {
2526
- debugJson(logger$18, "Alpha search Copilot Responses request:", payload);
2573
+ debugJson(logger$19, "Alpha search Copilot Responses request:", payload);
2527
2574
  const result = await alphaSearchResponsesDependencies.createResponses(payload, {
2528
2575
  vision: false,
2529
2576
  initiator: "agent",
@@ -2532,7 +2579,7 @@ async function requestCopilotSearch(payload, model, requestId, sessionId, client
2532
2579
  sessionId,
2533
2580
  clientSignal
2534
2581
  });
2535
- debugJson(logger$18, "Alpha search Copilot Responses result:", result);
2582
+ debugJson(logger$19, "Alpha search Copilot Responses result:", result);
2536
2583
  alphaSearchResponsesDependencies.createUsageRecorder(model, sessionId)({
2537
2584
  ...normalizeResponsesUsage(result.usage),
2538
2585
  total_nano_aiu: normalizeOptionalToken(result.copilot_usage?.total_nano_aiu)
@@ -2608,7 +2655,7 @@ async function handleAlphaSearchResponses(c, options) {
2608
2655
  const parsed = alphaSearchRequestSchema.safeParse(options.request);
2609
2656
  if (!parsed.success) {
2610
2657
  const issue = parsed.error.issues[0];
2611
- return invalidRequest$1(c, `Invalid alpha search request at ${issue?.path.join(".") || "body"}: ${issue?.message ?? "invalid value"}`);
2658
+ return invalidRequest$2(c, `Invalid alpha search request at ${issue?.path.join(".") || "body"}: ${issue?.message ?? "invalid value"}`);
2612
2659
  }
2613
2660
  const request = parsed.data;
2614
2661
  const now = alphaSearchResponsesDependencies.now();
@@ -2647,7 +2694,7 @@ async function forwardCodexAlphaSearch(request) {
2647
2694
  }
2648
2695
  //#endregion
2649
2696
  //#region src/routes/alpha-search/route.ts
2650
- const logger$17 = createHandlerLogger("alpha-search-handler");
2697
+ const logger$18 = createHandlerLogger("alpha-search-handler");
2651
2698
  const alphaSearchRoutes = new Hono();
2652
2699
  const alphaSearchRouteDependencies = {
2653
2700
  findEndpointModel,
@@ -2667,9 +2714,9 @@ function parseDebugBody(body) {
2667
2714
  }
2668
2715
  }
2669
2716
  async function forwardCodexAlphaSearchRequest(request) {
2670
- await debugJsonAsync(logger$17, "alpha_search.codex.request", async () => ({ body: parseDebugBody(await request.clone().text()) }));
2717
+ await debugJsonAsync(logger$18, "alpha_search.codex.request", async () => ({ body: parseDebugBody(await request.clone().text()) }));
2671
2718
  const upstreamResponse = await alphaSearchRouteDependencies.forwardCodexAlphaSearch(request);
2672
- await debugJsonAsync(logger$17, "alpha_search.codex.response", async () => ({
2719
+ await debugJsonAsync(logger$18, "alpha_search.codex.response", async () => ({
2673
2720
  body: parseDebugBody(await upstreamResponse.clone().text()),
2674
2721
  statusCode: upstreamResponse.status
2675
2722
  }));
@@ -2690,7 +2737,7 @@ async function handleCodexRequest(c, request, resolvedProviderConfig) {
2690
2737
  } }, 404);
2691
2738
  return await forwardCodexAlphaSearchRequest(request);
2692
2739
  }
2693
- function invalidRequest(c, message) {
2740
+ function invalidRequest$1(c, message) {
2694
2741
  return c.json({ error: {
2695
2742
  message,
2696
2743
  type: "invalid_request_error"
@@ -2701,9 +2748,9 @@ async function parseAlphaSearchBody(c) {
2701
2748
  try {
2702
2749
  body = await c.req.raw.clone().json();
2703
2750
  } catch {
2704
- return invalidRequest(c, "Invalid alpha search request: expected JSON body");
2751
+ return invalidRequest$1(c, "Invalid alpha search request: expected JSON body");
2705
2752
  }
2706
- if (typeof body?.model !== "string") return invalidRequest(c, "Invalid alpha search request: model must be a string");
2753
+ if (typeof body?.model !== "string") return invalidRequest$1(c, "Invalid alpha search request: model must be a string");
2707
2754
  return body;
2708
2755
  }
2709
2756
  /**
@@ -2733,9 +2780,9 @@ async function handleAlphaSearchRequest(c, resolvedProviderConfig) {
2733
2780
  const messagesBackedModel = await isMessagesBackedModel(resolvedRequestedModel);
2734
2781
  if (messagesBackedModel) {
2735
2782
  const searchModel = alphaSearchRouteDependencies.getAlphaSearchModel();
2736
- if (!searchModel) return invalidRequest(c, "alphaSearchModel is disabled; Messages-backed Codex models require a native Responses search model");
2783
+ if (!searchModel) return invalidRequest$1(c, "alphaSearchModel is disabled; Messages-backed Codex models require a native Responses search model");
2737
2784
  const resolvedSearchModel = alphaSearchRouteDependencies.resolveMappedModel(searchModel);
2738
- if (!await isNativeResponsesModel(resolvedSearchModel)) return invalidRequest(c, `Configured alphaSearchModel '${searchModel}' does not support the Responses endpoint required for alpha search`);
2785
+ if (!await isNativeResponsesModel(resolvedSearchModel)) return invalidRequest$1(c, `Configured alphaSearchModel '${searchModel}' does not support the Responses endpoint required for alpha search`);
2739
2786
  consola.debug(`Redirected alpha search model: ${resolvedRequestedModel} -> ${resolvedSearchModel}`);
2740
2787
  payload.model = resolvedSearchModel;
2741
2788
  providerModelAlias = parseProviderModelAlias(payload.model);
@@ -2780,7 +2827,7 @@ alphaSearchRoutes.post("/", async (c) => {
2780
2827
  try {
2781
2828
  return await handleAlphaSearchRequest(c);
2782
2829
  } catch (error) {
2783
- logger$17.error("alpha_search.error", { error });
2830
+ logger$18.error("alpha_search.error", { error });
2784
2831
  return await forwardError(c, error);
2785
2832
  }
2786
2833
  });
@@ -2935,7 +2982,7 @@ const normalizeProviderResponsesReasoningEffort = (payload, providerConfig) => {
2935
2982
  };
2936
2983
  //#endregion
2937
2984
  //#region src/routes/provider/chat-completions/handler.ts
2938
- const logger$16 = createHandlerLogger("provider-chat-completions-handler");
2985
+ const logger$17 = createHandlerLogger("provider-chat-completions-handler");
2939
2986
  async function handleProviderChatCompletionsForProvider(c, options) {
2940
2987
  const { payload, provider } = options;
2941
2988
  const configuredProvider = await resolveProviderConfig(provider);
@@ -2950,13 +2997,13 @@ async function handleProviderChatCompletionsForProvider(c, options) {
2950
2997
  applyProviderStreamOptions(payload);
2951
2998
  applyDashScopePreserveThinkingDefault(payload, providerConfig);
2952
2999
  applyProviderContextCache(payload, modelConfig, providerConfig);
2953
- debugJson(logger$16, "provider.chat_completions.request", {
3000
+ debugJson(logger$17, "provider.chat_completions.request", {
2954
3001
  payload,
2955
3002
  provider
2956
3003
  });
2957
3004
  const upstreamResponse = await forwardProviderChatCompletions(providerConfig, payload, c.req.raw.headers, { clientSignal: c.req.raw.signal });
2958
3005
  if (!upstreamResponse.ok) {
2959
- logger$16.error("Failed to create provider chat completions", {
3006
+ logger$17.error("Failed to create provider chat completions", {
2960
3007
  provider,
2961
3008
  statusCode: upstreamResponse.status
2962
3009
  });
@@ -2970,7 +3017,7 @@ async function handleProviderChatCompletionsForProvider(c, options) {
2970
3017
  });
2971
3018
  const responseBody = await upstreamResponse.clone().json();
2972
3019
  recordUsage(normalizeOpenAIUsage(responseBody.usage));
2973
- debugJson(logger$16, "provider.chat_completions.response", responseBody);
3020
+ debugJson(logger$17, "provider.chat_completions.response", responseBody);
2974
3021
  return createProviderProxyResponse(upstreamResponse);
2975
3022
  }
2976
3023
  const applyProviderStreamOptions = (payload) => {
@@ -2992,12 +3039,12 @@ const createProviderChatCompletionsUsageRecorder = (payload, provider, modelConf
2992
3039
  providerName: provider
2993
3040
  });
2994
3041
  const streamProviderChatCompletions = (c, upstreamResponse, options) => {
2995
- logger$16.debug("provider.chat_completions.streaming", { provider: options.provider });
3042
+ logger$17.debug("provider.chat_completions.streaming", { provider: options.provider });
2996
3043
  return streamSSE(c, async (stream) => {
2997
3044
  let usage = {};
2998
3045
  try {
2999
3046
  for await (const chunk of events(upstreamResponse)) {
3000
- debugJson(logger$16, "provider.chat_completions.stream_chunk", chunk);
3047
+ debugJson(logger$17, "provider.chat_completions.stream_chunk", chunk);
3001
3048
  if (chunk.data && chunk.data !== "[DONE]") {
3002
3049
  const parsedChunk = parseChatCompletionChunkData(chunk.data);
3003
3050
  if (parsedChunk?.usage) usage = normalizeOpenAIUsage(parsedChunk.usage);
@@ -3056,7 +3103,7 @@ const createChatCompletions = async (payload, options) => {
3056
3103
  };
3057
3104
  //#endregion
3058
3105
  //#region src/routes/chat-completions/handler.ts
3059
- const logger$15 = createHandlerLogger("chat-completions-handler");
3106
+ const logger$16 = createHandlerLogger("chat-completions-handler");
3060
3107
  async function handleCompletion$1(c) {
3061
3108
  let payload = await c.req.json();
3062
3109
  const requestedModel = payload.model;
@@ -3070,7 +3117,7 @@ async function handleCompletion$1(c) {
3070
3117
  provider: providerModelAlias.provider
3071
3118
  });
3072
3119
  }
3073
- debugJson(logger$15, "Request payload:", payload);
3120
+ debugJson(logger$16, "Request payload:", payload);
3074
3121
  const selectedModel = findEndpointModel(payload.model);
3075
3122
  payload.model = selectedModel?.id ?? payload.model;
3076
3123
  if (isNullish(payload.max_tokens) && isNullish(payload.max_completion_tokens)) {
@@ -3078,16 +3125,16 @@ async function handleCompletion$1(c) {
3078
3125
  ...payload,
3079
3126
  max_tokens: selectedModel?.capabilities.limits.max_output_tokens
3080
3127
  };
3081
- debugJson(logger$15, "Set max_tokens to:", payload.max_tokens);
3128
+ debugJson(logger$16, "Set max_tokens to:", payload.max_tokens);
3082
3129
  }
3083
3130
  if (payload.model.includes("gpt")) {
3084
3131
  if (isNullish(payload.max_completion_tokens)) payload.max_completion_tokens = payload.max_tokens;
3085
3132
  delete payload.max_tokens;
3086
3133
  }
3087
3134
  const requestId = generateRequestIdFromPayload(payload);
3088
- logger$15.debug("Generated request ID:", requestId);
3135
+ logger$16.debug("Generated request ID:", requestId);
3089
3136
  const sessionId = getUUID(requestId);
3090
- logger$15.debug("Extracted session ID:", sessionId);
3137
+ logger$16.debug("Extracted session ID:", sessionId);
3091
3138
  const recordUsage = createCopilotTokenUsageRecorder({
3092
3139
  endpoint: "chat_completions",
3093
3140
  fallbackSessionId: sessionId,
@@ -3099,18 +3146,18 @@ async function handleCompletion$1(c) {
3099
3146
  sessionId
3100
3147
  });
3101
3148
  if (isNonStreaming$1(response)) {
3102
- debugJson(logger$15, "Non-streaming response:", response);
3149
+ debugJson(logger$16, "Non-streaming response:", response);
3103
3150
  recordUsage({
3104
3151
  ...normalizeOpenAIUsage(response.usage),
3105
3152
  total_nano_aiu: normalizeOptionalToken(response.copilot_usage?.total_nano_aiu)
3106
3153
  });
3107
3154
  return c.json(response);
3108
3155
  }
3109
- logger$15.debug("Streaming response");
3156
+ logger$16.debug("Streaming response");
3110
3157
  return streamSSE(c, async (stream) => {
3111
3158
  let usage = {};
3112
3159
  for await (const chunk of response) {
3113
- debugJson(logger$15, "Streaming chunk:", chunk);
3160
+ debugJson(logger$16, "Streaming chunk:", chunk);
3114
3161
  const parsedChunk = parseChatCompletionChunk(chunk);
3115
3162
  if (parsedChunk?.usage || parsedChunk?.copilot_usage) usage = {
3116
3163
  ...normalizeOpenAIUsage(parsedChunk.usage),
@@ -3340,7 +3387,7 @@ async function forwardCodexImages(request, operation) {
3340
3387
  }
3341
3388
  //#endregion
3342
3389
  //#region src/routes/images/shared.ts
3343
- const logger$14 = createHandlerLogger("images-handler");
3390
+ const logger$15 = createHandlerLogger("images-handler");
3344
3391
  const imageRouteDependencies = {
3345
3392
  debugJsonAsync,
3346
3393
  getImageEditModel,
@@ -3388,16 +3435,16 @@ async function handleCodexImages(c, operation, resolvedProviderConfig, request =
3388
3435
  message: "Provider 'codex' not found or disabled",
3389
3436
  type: "invalid_request_error"
3390
3437
  } }, 404);
3391
- if (operation === "generations") await imageRouteDependencies.debugJsonAsync(logger$14, "images.generations.codex.request", async () => ({ body: await request.clone().text() }));
3392
- else debugJson(logger$14, "images.edits.codex.request", getContentMetadata(request.headers));
3438
+ if (operation === "generations") await imageRouteDependencies.debugJsonAsync(logger$15, "images.generations.codex.request", async () => ({ body: await request.clone().text() }));
3439
+ else debugJson(logger$15, "images.edits.codex.request", getContentMetadata(request.headers));
3393
3440
  const upstreamResponse = await forwardCodexImages(request, operation);
3394
- debugJson(logger$14, `images.${operation}.codex.response`, {
3441
+ debugJson(logger$15, `images.${operation}.codex.response`, {
3395
3442
  ...getContentMetadata(upstreamResponse.headers),
3396
3443
  statusCode: upstreamResponse.status
3397
3444
  });
3398
3445
  return createProviderProxyResponse(upstreamResponse);
3399
3446
  } catch (error) {
3400
- logger$14.error(`images.${operation}.codex.error`, { error });
3447
+ logger$15.error(`images.${operation}.codex.error`, { error });
3401
3448
  return await forwardError(c, error);
3402
3449
  }
3403
3450
  }
@@ -3416,7 +3463,7 @@ async function routeImagesRequest(c, operation, parsed) {
3416
3463
  const request = parsed.createRequest(providerModelAlias.model);
3417
3464
  if (providerConfig.name === "codex") return await handleCodexImages(c, operation, providerConfig, request);
3418
3465
  return await forwardProviderImagesWithLogging(providerConfig, request, operation, {
3419
- logger: logger$14,
3466
+ logger: logger$15,
3420
3467
  provider: providerModelAlias.provider
3421
3468
  });
3422
3469
  }
@@ -3910,12 +3957,12 @@ async function forwardXaiImages(providerConfig, request, operation, payload) {
3910
3957
  method: "POST",
3911
3958
  signal: request.signal
3912
3959
  }), operation, {
3913
- logger: logger$14,
3960
+ logger: logger$15,
3914
3961
  provider: "xai"
3915
3962
  }), void 0, {
3916
3963
  clientSignal: request.signal,
3917
3964
  onImageUrl: (url) => {
3918
- logger$14.info("images.xai.output.url", JSON.stringify({
3965
+ logger$15.info("images.xai.output.url", JSON.stringify({
3919
3966
  operation,
3920
3967
  url
3921
3968
  }));
@@ -3939,7 +3986,7 @@ async function handleXaiImageEdit(c, model, parsed) {
3939
3986
  }
3940
3987
  //#endregion
3941
3988
  //#region src/routes/images/temp-form-data.ts
3942
- const logger$13 = createHandlerLogger("images-temp-form-data");
3989
+ const logger$14 = createHandlerLogger("images-temp-form-data");
3943
3990
  const multipartStagingDependencies = { createWriteStream };
3944
3991
  /**
3945
3992
  * Matches the images forwarding timeouts: an upstream upload may take that
@@ -4131,7 +4178,7 @@ async function stageMultipartBodyToDisk(body, contentType, limitOverrides = {})
4131
4178
  recursive: true
4132
4179
  });
4133
4180
  } catch (error) {
4134
- logger$13.warn("Failed to remove staged images temp directory", {
4181
+ logger$14.warn("Failed to remove staged images temp directory", {
4135
4182
  directory,
4136
4183
  error
4137
4184
  });
@@ -4153,7 +4200,7 @@ async function stageMultipartBodyToDisk(body, contentType, limitOverrides = {})
4153
4200
  recursive: true
4154
4201
  });
4155
4202
  } catch (error) {
4156
- logger$13.warn("Failed to remove staged images temp directory on exit", {
4203
+ logger$14.warn("Failed to remove staged images temp directory on exit", {
4157
4204
  directory,
4158
4205
  error
4159
4206
  });
@@ -4234,7 +4281,7 @@ async function handleImagesEdits(c) {
4234
4281
  } }, error instanceof MultipartBodyTooLargeError ? 413 : 400);
4235
4282
  const invalidRequest = xaiImagesRequestErrorResponse(c, error);
4236
4283
  if (invalidRequest) return invalidRequest;
4237
- logger$14.error("images.edits.error", { error });
4284
+ logger$15.error("images.edits.error", { error });
4238
4285
  return await forwardError(c, error);
4239
4286
  }
4240
4287
  }
@@ -4286,7 +4333,7 @@ async function handleImagesGenerations(c) {
4286
4333
  } catch (error) {
4287
4334
  const invalidRequest = xaiImagesRequestErrorResponse(c, error);
4288
4335
  if (invalidRequest) return invalidRequest;
4289
- logger$14.error("images.generations.error", { error });
4336
+ logger$15.error("images.generations.error", { error });
4290
4337
  return await forwardError(c, error);
4291
4338
  }
4292
4339
  }
@@ -5380,7 +5427,7 @@ const prepareMessagesApiPayload = (payload, selectedModel) => {
5380
5427
  };
5381
5428
  //#endregion
5382
5429
  //#region src/routes/provider/messages/count-tokens-handler.ts
5383
- const logger$12 = createHandlerLogger("provider-count-tokens-handler");
5430
+ const logger$13 = createHandlerLogger("provider-count-tokens-handler");
5384
5431
  async function handleProviderCountTokens(c) {
5385
5432
  const provider = c.req.param("provider");
5386
5433
  const payload = await c.req.json();
@@ -5408,7 +5455,7 @@ async function handleProviderCountTokensForProvider(c, options) {
5408
5455
  const selectedModel = createFallbackModel(modelId);
5409
5456
  const tokenCount = await getTokenCount(openAIPayload, selectedModel);
5410
5457
  const finalTokenCount = tokenCount.input + tokenCount.output;
5411
- logger$12.debug("provider.count_tokens.success", {
5458
+ logger$13.debug("provider.count_tokens.success", {
5412
5459
  provider,
5413
5460
  model: anthropicPayload.model,
5414
5461
  input_tokens: finalTokenCount
@@ -8461,6 +8508,539 @@ function getModels() {
8461
8508
  };
8462
8509
  }
8463
8510
  //#endregion
8511
+ //#region src/routes/messages/google-thinking.ts
8512
+ function supportsThinkingControls(modelId) {
8513
+ const model = modelId.replace(/^models\//u, "").toLowerCase();
8514
+ if (/(?:^|-)(?:tts|live|image)(?:-|$)/u.test(model)) return false;
8515
+ if (/^gemini-3\.8-flash(?:-|$)/u.test(model)) return true;
8516
+ const major = /^gemini-(\d+)(?:\.\d+)?(?:-|$)/u.exec(model)?.[1];
8517
+ return major !== void 0 && Number(major) >= 4;
8518
+ }
8519
+ function translateGoogleThinking(payload) {
8520
+ const thinking = payload.thinking;
8521
+ const effort = payload.output_config?.effort;
8522
+ if (!thinking && !effort || !supportsThinkingControls(payload.model)) return void 0;
8523
+ const config = { includeThoughts: thinking?.type !== "disabled" };
8524
+ if (thinking?.type === "disabled") return {
8525
+ ...config,
8526
+ thinkingLevel: "LOW"
8527
+ };
8528
+ const requestedBudget = thinking?.budget_tokens;
8529
+ if (requestedBudget !== void 0) {
8530
+ if (requestedBudget !== -1) config.thinkingLevel = requestedBudget <= 2048 ? "LOW" : requestedBudget <= 8192 ? "MEDIUM" : "HIGH";
8531
+ return config;
8532
+ }
8533
+ if (effort) config.thinkingLevel = effort === "low" ? "LOW" : effort === "medium" ? "MEDIUM" : "HIGH";
8534
+ return config;
8535
+ }
8536
+ //#endregion
8537
+ //#region src/routes/messages/google-translation.ts
8538
+ const GOOGLE_SIGNATURE_PREFIX = "google:";
8539
+ function encodeGoogleSignature(signature, target) {
8540
+ return GOOGLE_SIGNATURE_PREFIX + Buffer.from(JSON.stringify({
8541
+ signature,
8542
+ target
8543
+ })).toString("base64url");
8544
+ }
8545
+ function decodeGoogleSignature(value) {
8546
+ if (!value.startsWith(GOOGLE_SIGNATURE_PREFIX)) return void 0;
8547
+ try {
8548
+ const decoded = JSON.parse(Buffer.from(value.slice(7), "base64url").toString());
8549
+ if (typeof decoded !== "object" || decoded === null) return void 0;
8550
+ const { signature, target } = decoded;
8551
+ if (typeof signature !== "string") return void 0;
8552
+ if (target === "thinking" || target === "previous") return {
8553
+ signature,
8554
+ target
8555
+ };
8556
+ if (typeof target === "object" && target !== null && "toolUseId" in target && typeof target.toolUseId === "string" && target.toolUseId.length > 0) return {
8557
+ signature,
8558
+ target: { toolUseId: target.toolUseId }
8559
+ };
8560
+ } catch {}
8561
+ }
8562
+ function translateThinkingBlock(block, parts, toolSignatures) {
8563
+ const decoded = decodeGoogleSignature(block.signature);
8564
+ if (decoded?.target === "previous") {
8565
+ const previous = parts.at(-1);
8566
+ if (previous) previous.thoughtSignature = decoded.signature;
8567
+ } else if (decoded && typeof decoded.target === "object") toolSignatures.set(decoded.target.toolUseId, decoded.signature);
8568
+ if (block.thinking || decoded?.target === "thinking") parts.push({
8569
+ text: block.thinking,
8570
+ thought: true,
8571
+ ...decoded?.target === "thinking" && { thoughtSignature: decoded.signature }
8572
+ });
8573
+ }
8574
+ function invalidRequest(message) {
8575
+ throw new HTTPError(message, Response.json({ error: {
8576
+ type: "invalid_request_error",
8577
+ message
8578
+ } }, { status: 400 }));
8579
+ }
8580
+ function translateToolResult(block, toolNames) {
8581
+ const name = toolNames.get(block.tool_use_id);
8582
+ if (!name) invalidRequest(`Google tool result has no matching tool_use: ${block.tool_use_id}`);
8583
+ const text = [];
8584
+ const media = [];
8585
+ const references = [];
8586
+ const mediaPrefix = createHash("sha256").update(block.tool_use_id).digest("hex").slice(0, 16);
8587
+ if (typeof block.content === "string") text.push(block.content);
8588
+ else for (const item of block.content) if (item.type === "text") text.push(item.text);
8589
+ else if (item.type === "tool_reference") text.push(item.tool_name);
8590
+ else {
8591
+ const displayName = `tool-result-${mediaPrefix}-${media.length}`;
8592
+ media.push({ inlineData: {
8593
+ mimeType: item.source.media_type,
8594
+ data: item.source.data,
8595
+ displayName
8596
+ } });
8597
+ references.push({ $ref: displayName });
8598
+ }
8599
+ return { functionResponse: {
8600
+ id: block.tool_use_id,
8601
+ name,
8602
+ response: { [block.is_error ? "error" : "output"]: media.length > 0 ? {
8603
+ text: text.join("\n"),
8604
+ media: references
8605
+ } : text.join("\n") },
8606
+ ...media.length > 0 && { parts: media }
8607
+ } };
8608
+ }
8609
+ function translateAnthropicToGoogle(payload) {
8610
+ const result = {
8611
+ contents: [],
8612
+ generationConfig: {
8613
+ candidateCount: 1,
8614
+ maxOutputTokens: payload.max_tokens,
8615
+ temperature: payload.temperature,
8616
+ topP: payload.top_p,
8617
+ topK: payload.top_k,
8618
+ stopSequences: payload.stop_sequences
8619
+ }
8620
+ };
8621
+ const systemParts = typeof payload.system === "string" ? [{ text: payload.system }] : (payload.system ?? []).map((block) => ({ text: block.text }));
8622
+ const toolNames = /* @__PURE__ */ new Map();
8623
+ const toolSignatures = /* @__PURE__ */ new Map();
8624
+ for (const message of payload.messages) {
8625
+ if (message.role === "system") {
8626
+ systemParts.push(...typeof message.content === "string" ? [{ text: message.content }] : message.content.map((block) => ({ text: block.text })));
8627
+ continue;
8628
+ }
8629
+ const parts = [];
8630
+ if (typeof message.content === "string") {
8631
+ if (message.content) parts.push({ text: message.content });
8632
+ } else for (const block of message.content) switch (block.type) {
8633
+ case "text":
8634
+ if (block.text) parts.push({ text: block.text });
8635
+ break;
8636
+ case "image":
8637
+ case "document":
8638
+ parts.push({ inlineData: {
8639
+ mimeType: block.source.media_type,
8640
+ data: block.source.data
8641
+ } });
8642
+ break;
8643
+ case "tool_use":
8644
+ toolNames.set(block.id, block.name);
8645
+ parts.push({ functionCall: {
8646
+ id: block.id,
8647
+ name: block.name,
8648
+ args: block.input
8649
+ } });
8650
+ break;
8651
+ case "tool_result":
8652
+ parts.push(translateToolResult(block, toolNames));
8653
+ break;
8654
+ case "thinking": translateThinkingBlock(block, parts, toolSignatures);
8655
+ }
8656
+ if (!parts.length) continue;
8657
+ const role = message.role === "assistant" ? "model" : "user";
8658
+ const previous = result.contents.at(-1);
8659
+ if (previous?.role === role) previous.parts.push(...parts);
8660
+ else result.contents.push({
8661
+ role,
8662
+ parts
8663
+ });
8664
+ }
8665
+ for (const content of result.contents) for (const part of content.parts) {
8666
+ const id = part.functionCall?.id;
8667
+ const signature = id ? toolSignatures.get(id) : void 0;
8668
+ if (signature !== void 0) part.thoughtSignature = signature;
8669
+ }
8670
+ if (systemParts.length) result.systemInstruction = { parts: systemParts };
8671
+ if (payload.tools?.length) result.tools = [{ functionDeclarations: payload.tools.map((tool) => {
8672
+ if (tool.type && tool.type !== "custom") invalidRequest(`Google does not support Anthropic server tool '${tool.type}'`);
8673
+ return {
8674
+ name: tool.name,
8675
+ description: tool.description,
8676
+ parametersJsonSchema: tool.input_schema
8677
+ };
8678
+ }) }];
8679
+ if (payload.tool_choice) {
8680
+ const choice = payload.tool_choice;
8681
+ result.toolConfig = { functionCallingConfig: {
8682
+ mode: choice.type === "none" ? "NONE" : choice.type === "auto" ? "AUTO" : "ANY",
8683
+ ...choice.type === "tool" && choice.name && { allowedFunctionNames: [choice.name] }
8684
+ } };
8685
+ }
8686
+ if (payload.output_config?.format) {
8687
+ result.generationConfig.responseMimeType = "application/json";
8688
+ result.generationConfig.responseJsonSchema = payload.output_config.format.schema;
8689
+ }
8690
+ const thinkingConfig = translateGoogleThinking(payload);
8691
+ if (thinkingConfig) result.generationConfig.thinkingConfig = thinkingConfig;
8692
+ return result;
8693
+ }
8694
+ function translateGoogleUsage(usage = {}) {
8695
+ const cached = usage.cachedContentTokenCount ?? 0;
8696
+ return {
8697
+ input_tokens: Math.max(0, (usage.promptTokenCount ?? 0) - cached),
8698
+ output_tokens: (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0),
8699
+ cache_read_input_tokens: cached
8700
+ };
8701
+ }
8702
+ function getGoogleStopReason(finishReason, hasTools, blocked) {
8703
+ if (blocked || [
8704
+ "SAFETY",
8705
+ "RECITATION",
8706
+ "BLOCKLIST",
8707
+ "PROHIBITED_CONTENT",
8708
+ "SPII",
8709
+ "IMAGE_SAFETY"
8710
+ ].includes(finishReason ?? "")) return "refusal";
8711
+ if (finishReason === "MAX_TOKENS") return "max_tokens";
8712
+ if (finishReason === "STOP") return hasTools ? "tool_use" : "end_turn";
8713
+ throw new Error(`Google generation ended without a successful finish reason (${finishReason ?? "missing"})`);
8714
+ }
8715
+ function googleSignatureBlock(signature, toolUseId) {
8716
+ return {
8717
+ type: "thinking",
8718
+ thinking: "",
8719
+ signature: encodeGoogleSignature(signature, toolUseId ? { toolUseId } : "previous")
8720
+ };
8721
+ }
8722
+ function translateGoogleToAnthropic(response, model) {
8723
+ if (response.error) throw new Error(response.error.message ?? "Google generation failed");
8724
+ const candidate = response.candidates?.[0];
8725
+ const content = [];
8726
+ for (const part of candidate?.content?.parts ?? []) {
8727
+ if (part.functionCall) {
8728
+ const call = part.functionCall;
8729
+ const id = call.id || `toolu_${randomUUID()}`;
8730
+ if (part.thoughtSignature) {
8731
+ const previous = content.at(-1);
8732
+ const signature = googleSignatureBlock(part.thoughtSignature, id);
8733
+ if (previous?.type === "thinking" && !previous.signature) previous.signature = signature.signature;
8734
+ else content.push(signature);
8735
+ }
8736
+ content.push({
8737
+ type: "tool_use",
8738
+ id,
8739
+ name: call.name,
8740
+ input: call.args ?? {}
8741
+ });
8742
+ continue;
8743
+ } else if (part.thought) {
8744
+ content.push({
8745
+ type: "thinking",
8746
+ thinking: part.text ?? "",
8747
+ signature: part.thoughtSignature ? encodeGoogleSignature(part.thoughtSignature, "thinking") : ""
8748
+ });
8749
+ continue;
8750
+ } else if (part.text !== void 0) content.push({
8751
+ type: "text",
8752
+ text: part.text
8753
+ });
8754
+ if (part.thoughtSignature) content.push(googleSignatureBlock(part.thoughtSignature));
8755
+ }
8756
+ return {
8757
+ id: response.responseId || `msg_${randomUUID()}`,
8758
+ type: "message",
8759
+ role: "assistant",
8760
+ model,
8761
+ content,
8762
+ stop_reason: getGoogleStopReason(candidate?.finishReason, content.some((block) => block.type === "tool_use"), response.promptFeedback?.blockReason),
8763
+ stop_sequence: null,
8764
+ usage: translateGoogleUsage(response.usageMetadata)
8765
+ };
8766
+ }
8767
+ //#endregion
8768
+ //#region src/routes/messages/google-stream-translation.ts
8769
+ var GoogleMessagesStreamTranslator = class {
8770
+ started = false;
8771
+ nextIndex = 0;
8772
+ block;
8773
+ hasTools = false;
8774
+ finishReason;
8775
+ blocked;
8776
+ usageMetadata = {};
8777
+ model;
8778
+ constructor(model) {
8779
+ this.model = model;
8780
+ }
8781
+ get usage() {
8782
+ return translateGoogleUsage(this.usageMetadata);
8783
+ }
8784
+ push(response) {
8785
+ if (response.error) throw new Error(response.error.message ?? "Google stream failed");
8786
+ this.usageMetadata = {
8787
+ ...this.usageMetadata,
8788
+ ...response.usageMetadata
8789
+ };
8790
+ const events = [];
8791
+ if (!this.started) {
8792
+ this.started = true;
8793
+ events.push({
8794
+ type: "message_start",
8795
+ message: {
8796
+ id: response.responseId || `msg_${randomUUID()}`,
8797
+ type: "message",
8798
+ role: "assistant",
8799
+ model: this.model,
8800
+ content: [],
8801
+ stop_reason: null,
8802
+ stop_sequence: null,
8803
+ usage: {
8804
+ ...this.usage,
8805
+ output_tokens: 0
8806
+ }
8807
+ }
8808
+ });
8809
+ }
8810
+ const candidate = response.candidates?.[0];
8811
+ for (const part of candidate?.content?.parts ?? []) this.addPart(part, events);
8812
+ this.finishReason = candidate?.finishReason ?? this.finishReason;
8813
+ this.blocked = response.promptFeedback?.blockReason ?? this.blocked;
8814
+ return events;
8815
+ }
8816
+ finish() {
8817
+ const stopReason = getGoogleStopReason(this.finishReason, this.hasTools, this.blocked);
8818
+ const events = [];
8819
+ this.closeBlock(events);
8820
+ events.push({
8821
+ type: "message_delta",
8822
+ delta: {
8823
+ stop_reason: stopReason,
8824
+ stop_sequence: null
8825
+ },
8826
+ usage: this.usage
8827
+ }, { type: "message_stop" });
8828
+ return events;
8829
+ }
8830
+ addPart(part, events) {
8831
+ if (part.functionCall) {
8832
+ const call = part.functionCall;
8833
+ const id = call.id || `toolu_${randomUUID()}`;
8834
+ if (part.thoughtSignature) this.addSignature(part.thoughtSignature, events, id);
8835
+ this.closeBlock(events);
8836
+ const index = this.nextIndex++;
8837
+ this.hasTools = true;
8838
+ events.push({
8839
+ type: "content_block_start",
8840
+ index,
8841
+ content_block: {
8842
+ type: "tool_use",
8843
+ id,
8844
+ name: call.name,
8845
+ input: {}
8846
+ }
8847
+ }, {
8848
+ type: "content_block_delta",
8849
+ index,
8850
+ delta: {
8851
+ type: "input_json_delta",
8852
+ partial_json: JSON.stringify(call.args ?? {})
8853
+ }
8854
+ }, {
8855
+ type: "content_block_stop",
8856
+ index
8857
+ });
8858
+ return;
8859
+ }
8860
+ if (part.text || part.thought) {
8861
+ const type = part.thought ? "thinking" : "text";
8862
+ if (this.block?.type !== type) this.closeBlock(events);
8863
+ if (!this.block) {
8864
+ const index = this.nextIndex++;
8865
+ this.block = {
8866
+ index,
8867
+ type,
8868
+ signed: false
8869
+ };
8870
+ events.push({
8871
+ type: "content_block_start",
8872
+ index,
8873
+ content_block: type === "thinking" ? {
8874
+ type,
8875
+ thinking: ""
8876
+ } : {
8877
+ type,
8878
+ text: ""
8879
+ }
8880
+ });
8881
+ }
8882
+ events.push({
8883
+ type: "content_block_delta",
8884
+ index: this.block.index,
8885
+ delta: type === "thinking" ? {
8886
+ type: "thinking_delta",
8887
+ thinking: part.text ?? ""
8888
+ } : {
8889
+ type: "text_delta",
8890
+ text: part.text ?? ""
8891
+ }
8892
+ });
8893
+ }
8894
+ if (part.thoughtSignature) this.addSignature(part.thoughtSignature, events);
8895
+ }
8896
+ addSignature(signature, events, toolUseId) {
8897
+ if (this.block?.type === "thinking") {
8898
+ this.block.signed = true;
8899
+ events.push({
8900
+ type: "content_block_delta",
8901
+ index: this.block.index,
8902
+ delta: {
8903
+ type: "signature_delta",
8904
+ signature: encodeGoogleSignature(signature, toolUseId ? { toolUseId } : "thinking")
8905
+ }
8906
+ });
8907
+ this.closeBlock(events);
8908
+ return;
8909
+ }
8910
+ this.closeBlock(events);
8911
+ const index = this.nextIndex++;
8912
+ events.push({
8913
+ type: "content_block_start",
8914
+ index,
8915
+ content_block: {
8916
+ type: "thinking",
8917
+ thinking: ""
8918
+ }
8919
+ }, {
8920
+ type: "content_block_delta",
8921
+ index,
8922
+ delta: {
8923
+ type: "signature_delta",
8924
+ signature: encodeGoogleSignature(signature, toolUseId ? { toolUseId } : "previous")
8925
+ }
8926
+ }, {
8927
+ type: "content_block_stop",
8928
+ index
8929
+ });
8930
+ }
8931
+ closeBlock(events) {
8932
+ if (!this.block) return;
8933
+ if (this.block.type === "thinking" && !this.block.signed) events.push({
8934
+ type: "content_block_delta",
8935
+ index: this.block.index,
8936
+ delta: {
8937
+ type: "signature_delta",
8938
+ signature: ""
8939
+ }
8940
+ });
8941
+ events.push({
8942
+ type: "content_block_stop",
8943
+ index: this.block.index
8944
+ });
8945
+ this.block = void 0;
8946
+ }
8947
+ };
8948
+ //#endregion
8949
+ //#region src/services/providers/google.ts
8950
+ async function forwardGoogleGenerateContent(provider, model, payload, requestHeaders, options) {
8951
+ const modelId = encodeURIComponent(model.replace(/^models\//u, ""));
8952
+ const method = options.stream ? "streamGenerateContent" : "generateContent";
8953
+ const url = new URL(resolveProviderEndpointUrl(provider, `models/${modelId}:${method}`));
8954
+ if (options.stream) url.searchParams.set("alt", "sse");
8955
+ const headers = buildProviderUpstreamHeaders(provider, requestHeaders);
8956
+ applyOpencodeSessionHeader(provider, headers, options.sessionId);
8957
+ headers.accept = options.stream ? "text/event-stream" : "application/json";
8958
+ const transport = getUpstreamTransportConfig();
8959
+ return await fetchUpstreamWithLifecycle(url, {
8960
+ method: "POST",
8961
+ headers,
8962
+ body: JSON.stringify(payload)
8963
+ }, {
8964
+ clientSignal: options.clientSignal,
8965
+ headersTimeoutMs: transport.headersTimeoutMs,
8966
+ streamInactivityTimeoutMs: transport.streamInactivityTimeoutMs
8967
+ });
8968
+ }
8969
+ //#endregion
8970
+ //#region src/routes/provider/messages/google-handler.ts
8971
+ const logger$12 = createHandlerLogger("provider-google-messages");
8972
+ async function handleGoogleProviderMessages(c, payload, provider, usageEndpoint) {
8973
+ debugJson(logger$12, "provider.messages.google.original_request", payload);
8974
+ const translated = translateAnthropicToGoogle(payload);
8975
+ const modelConfig = provider.models?.[payload.model];
8976
+ const extraGenerationConfig = modelConfig?.extraBody?.generationConfig;
8977
+ if (extraGenerationConfig && typeof extraGenerationConfig === "object" && !Array.isArray(extraGenerationConfig)) {
8978
+ const generationConfig = translated.generationConfig;
8979
+ for (const [key, value] of Object.entries(extraGenerationConfig)) if (generationConfig[key] === void 0) generationConfig[key] = value;
8980
+ }
8981
+ applyMissingExtraBody(translated, { extraBody: modelConfig?.extraBody });
8982
+ debugJson(logger$12, "provider.messages.google.request", translated);
8983
+ const controller = new AbortController();
8984
+ const signal = AbortSignal.any([controller.signal, c.req.raw.signal]);
8985
+ const upstream = await forwardGoogleGenerateContent(provider, payload.model, translated, c.req.raw.headers, {
8986
+ stream: payload.stream === true,
8987
+ clientSignal: signal,
8988
+ sessionId: resolveOpencodeMessagesSession(payload)
8989
+ });
8990
+ if (!upstream.ok) throw new HTTPError("Failed to create Google response", upstream);
8991
+ const recordUsage = createProviderTokenUsageRecorder({
8992
+ endpoint: usageEndpoint ?? "provider_messages",
8993
+ model: payload.model,
8994
+ providerName: provider.name,
8995
+ pricing: modelConfig?.pricing,
8996
+ pricingCurrency: provider.pricingCurrency,
8997
+ sessionId: parseUserIdMetadata(payload.metadata?.user_id).sessionId
8998
+ });
8999
+ if (!payload.stream) {
9000
+ const response = translateGoogleToAnthropic(await upstream.json(), payload.model);
9001
+ recordUsage(normalizeAnthropicUsage(response.usage));
9002
+ return c.json(response);
9003
+ }
9004
+ return streamSSE(c, async (stream) => {
9005
+ const translator = new GoogleMessagesStreamTranslator(payload.model);
9006
+ stream.onAbort(() => controller.abort());
9007
+ const writeEvents = async (items) => {
9008
+ for (const item of items) {
9009
+ debugJson(logger$12, "provider.messages.google.translated_event:", item);
9010
+ await writeSSEIfConnected(stream, {
9011
+ event: item.type,
9012
+ data: JSON.stringify(item)
9013
+ });
9014
+ }
9015
+ };
9016
+ try {
9017
+ const response = new Response(upstream.body?.pipeThrough(new TransformStream(), { signal }), { headers: upstream.headers });
9018
+ if (response.headers.get("content-type")?.includes("text/event-stream")) for await (const event of events(response, signal)) {
9019
+ if (!event.data || event.data === "[DONE]") continue;
9020
+ const response = JSON.parse(event.data);
9021
+ debugJson(logger$12, "provider.messages.google.raw_stream_event:", response);
9022
+ await writeEvents(translator.push(response));
9023
+ }
9024
+ else await writeEvents(translator.push(await response.json()));
9025
+ if (!signal.aborted) await writeEvents(translator.finish());
9026
+ } catch (error) {
9027
+ if (!signal.aborted) {
9028
+ logger$12.warn("provider.messages.google.stream_interrupted", error);
9029
+ await writeEvents([{
9030
+ type: "error",
9031
+ error: {
9032
+ type: "api_error",
9033
+ message: error instanceof Error ? error.message : "Google stream interrupted"
9034
+ }
9035
+ }]);
9036
+ }
9037
+ } finally {
9038
+ controller.abort();
9039
+ recordUsage(normalizeAnthropicUsage(translator.usage));
9040
+ }
9041
+ });
9042
+ }
9043
+ //#endregion
8464
9044
  //#region src/routes/provider/messages/handler.ts
8465
9045
  const logger$11 = createHandlerLogger("provider-messages-handler");
8466
9046
  const providerMessagesHandlerDependencies = { resolveProviderConfig };
@@ -8497,6 +9077,10 @@ async function handleProviderMessagesForProvider(c, options) {
8497
9077
  normalizeSystemMessages(payload);
8498
9078
  applyModelDefaults(payload, modelConfig);
8499
9079
  appendClaudeContinuationMessage(payload);
9080
+ if (effectiveType === "google") {
9081
+ stripWebSearchServerTool(payload);
9082
+ return await handleGoogleProviderMessages(c, payload, providerConfig, usageEndpoint);
9083
+ }
8500
9084
  if (effectiveType === "openai-responses") {
8501
9085
  if (hasWebSearchServerTool(payload)) {
8502
9086
  if (isWebSearchOnlyRequest(payload)) return await handleOpenAIResponsesProviderWebSearchMessages(c, {
@@ -9984,20 +10568,13 @@ function getCopilotCodexCandidates() {
9984
10568
  function isCopilotCodexCandidate(model) {
9985
10569
  return (model.supported_endpoints ?? []).some((endpoint) => endpoint === MESSAGES_ENDPOINT || endpoint === CHAT_COMPLETIONS_ENDPOINT || RESPONSES_ENDPOINTS.has(endpoint)) && model.capabilities.supports.tool_calls !== false;
9986
10570
  }
9987
- function describeCopilotAdapter(model) {
9988
- const supportsResponses = model.supported_endpoints?.some((endpoint) => RESPONSES_ENDPOINTS.has(endpoint));
9989
- if (model.id.startsWith("gpt") && supportsResponses) return `${model.name} through the Copilot Responses API.`;
9990
- if (model.supported_endpoints?.includes(MESSAGES_ENDPOINT)) return `${model.name} through the Copilot Messages adapter.`;
9991
- if (supportsResponses) return `${model.name} through the Copilot Messages-to-Responses adapter.`;
9992
- return `${model.name} through the Copilot Messages-to-Chat adapter.`;
9993
- }
9994
10571
  function createCopilotCodexCandidate(model) {
9995
10572
  const reasoningEfforts = normalizeReasoningEfforts(model.capabilities.supports.reasoning_effort);
9996
10573
  return {
9997
10574
  slug: toClientModelId(model.id),
9998
10575
  catalogSlug: model.id,
9999
10576
  displayName: model.name,
10000
- description: describeCopilotAdapter(model),
10577
+ description: model.name,
10001
10578
  contextWindow: positiveNumber(model.capabilities.limits.max_prompt_tokens, 256e3),
10002
10579
  maxOutputTokens: positiveNumber(model.capabilities.limits.max_output_tokens, 32e3),
10003
10580
  inputModalities: model.capabilities.supports.vision ? ["text", "image"] : ["text"],
@@ -10029,18 +10606,12 @@ async function getProviderCodexCandidates(provider, requestHeaders) {
10029
10606
  }
10030
10607
  }
10031
10608
  function isMessagesFallbackProviderType(type) {
10032
- return type === "anthropic" || type === "openai-compatible";
10033
- }
10034
- function describeProviderAdapter(type) {
10035
- if (type === "anthropic") return "Messages";
10036
- if (type === "openai-responses") return "Messages-to-Responses";
10037
- return "Messages-to-Chat";
10609
+ return type === "anthropic" || type === "openai-compatible" || type === "google";
10038
10610
  }
10039
10611
  function createProviderCodexCandidate(providerConfig, modelId, remoteModel, effectiveType) {
10040
10612
  const metadata = getModelMetadata(providerConfig.name, modelId, remoteModel ?? {}, providerConfig);
10041
10613
  const reasoningEfforts = normalizeReasoningEfforts(metadata.reasoningEfforts);
10042
10614
  const displayName = getStringField(remoteModel ?? {}, "display_name") ?? getStringField(remoteModel ?? {}, "name") ?? modelId;
10043
- const adapterName = describeProviderAdapter(effectiveType);
10044
10615
  const requiresCatalogMatch = effectiveType === "openai-responses" && modelId.startsWith("gpt");
10045
10616
  return {
10046
10617
  slug: `${providerConfig.name}/${modelId}`,
@@ -10048,7 +10619,7 @@ function createProviderCodexCandidate(providerConfig, modelId, remoteModel, effe
10048
10619
  catalogMatchRequired: requiresCatalogMatch,
10049
10620
  providerName: providerConfig.name,
10050
10621
  displayName: `${displayName} (${providerConfig.name})`,
10051
- description: `${displayName} through the ${providerConfig.name} ${adapterName} adapter.`,
10622
+ description: displayName,
10052
10623
  contextWindow: metadata.contextWindow ?? 256e3,
10053
10624
  maxOutputTokens: metadata.maxOutputTokens ?? 32e3,
10054
10625
  inputModalities: normalizeInputModalities(metadata.inputModalities),
@@ -13149,7 +13720,7 @@ async function handleProviderResponsesForProvider(c, options) {
13149
13720
  return createProviderProxyResponse(upstreamResponse);
13150
13721
  }
13151
13722
  const shouldFallbackToMessages$1 = (c, modelId, effectiveType) => {
13152
- if (effectiveType === "anthropic" || effectiveType === "openai-compatible") return true;
13723
+ if (effectiveType === "anthropic" || effectiveType === "openai-compatible" || effectiveType === "google") return true;
13153
13724
  if (isCodexUserAgent(c.req.header("user-agent"))) return !(modelId.startsWith("gpt") || modelId.startsWith("codex"));
13154
13725
  return false;
13155
13726
  };
@@ -13633,4 +14204,4 @@ createServer();
13633
14204
  //#endregion
13634
14205
  export { createServer };
13635
14206
 
13636
- //# sourceMappingURL=server-04fZfBz1.js.map
14207
+ //# sourceMappingURL=server-D8LzQcmu.js.map