@nick3/copilot-api 1.10.29 → 1.10.34

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 (28) hide show
  1. package/README.md +41 -9
  2. package/README.zh-CN.md +39 -7
  3. package/dist/admin/assets/index-Cl_ViIW_.js +110 -0
  4. package/dist/admin/index.html +1 -1
  5. package/dist/{auth-nO-eHeO_.js → auth-Cc11G9V9.js} +2 -2
  6. package/dist/{auth-nO-eHeO_.js.map → auth-Cc11G9V9.js.map} +1 -1
  7. package/dist/{check-usage-ZifYvA3w.js → check-usage-C2QE6R93.js} +2 -2
  8. package/dist/{check-usage-ZifYvA3w.js.map → check-usage-C2QE6R93.js.map} +1 -1
  9. package/dist/{config-CmhIPHn_.js → config-BaU_aWgi.js} +35 -4
  10. package/dist/config-BaU_aWgi.js.map +1 -0
  11. package/dist/{debug-DvpksqEL.js → debug-BKqoXB_p.js} +2 -2
  12. package/dist/{debug-DvpksqEL.js.map → debug-BKqoXB_p.js.map} +1 -1
  13. package/dist/main.js +4 -4
  14. package/dist/{responses-bridge-registry-BJ5Sbh6-.js → responses-bridge-registry-DqCoY6Ex.js} +14 -7
  15. package/dist/responses-bridge-registry-DqCoY6Ex.js.map +1 -0
  16. package/dist/{server-DJ3_UGc4.js → server-C7pCkArb.js} +636 -187
  17. package/dist/server-C7pCkArb.js.map +1 -0
  18. package/dist/{start-DaB0AcjZ.js → start-CdLbBkRA.js} +4 -4
  19. package/dist/{start-DaB0AcjZ.js.map → start-CdLbBkRA.js.map} +1 -1
  20. package/dist/token-671YFxgv.js +947 -0
  21. package/dist/token-671YFxgv.js.map +1 -0
  22. package/package.json +2 -2
  23. package/dist/admin/assets/index-BAh4eOwM.js +0 -110
  24. package/dist/config-CmhIPHn_.js.map +0 -1
  25. package/dist/responses-bridge-registry-BJ5Sbh6-.js.map +0 -1
  26. package/dist/server-DJ3_UGc4.js.map +0 -1
  27. package/dist/token-DrFDLVxa.js +0 -365
  28. package/dist/token-DrFDLVxa.js.map +0 -1
@@ -1,12 +1,13 @@
1
1
  import { A as accountFromState, B as compactSystemPromptStarts, C as copilotHeaders, D as prepareForCompact, E as normalizeDomain, F as resolveTraceId, L as compactAutoContinuePromptStarts, M as captureOutboundHeadersSnapshot, O as prepareInteractionHeaders, P as requestContext, R as compactMessageSections, S as copilotBaseUrl, T as copilotWebSocketHeaders, b as HTTPError, c as getUUID, d as parseUserIdMetadata, f as resolveAffinityKey, g as getCopilotUsage, h as getDeviceCode, j as state, k as prepareMessageProxyHeaders, l as isNullish, m as getGitHubUser, o as generateRequestIdFromPayload, p as sleep, s as getRootSessionId, t as pollAccessToken, u as normalizeStableSessionId, v as getProxyEnvDispatcher, x as forwardError } from "./poll-access-token-GzVkiTH8.js";
2
2
  import { a as getAccountClientIdentityByLoginAndApp, b as getCurrentIdentityEnvironment, d as loadRegistry, g as saveRegistry, h as saveAccountToken, l as listAccountsFromRegistry, m as removeAccountToken, p as removeAccountFromRegistry, r as addAccountToRegistry, t as isAccountType } from "./account-DpW8RaT6.js";
3
3
  import { r as ensurePaths, t as PATHS } from "./paths-Bpsb62LK.js";
4
- import { C as isResponsesApiWebSocketEnabled, E as resolveModelAlias, O as shouldCompactUseSmallModel, S as isResponsesApiWebSearchEnabled, T as mergeConfigWithDefaults, _ as isAccountAffinityEnabled, a as getConfig, b as isMessagesApiEnabled, c as getModelAliases, d as getProviderConfig, g as getSmallModel, i as getClaudeTokenMultiplier, l as getModelAliasesInfo, m as getReasoningEffortForModel, n as getAliasTargetSet, o as getExtraPromptForModel, r as getAnthropicApiKey, s as getLogLevel, t as PROVIDER_TYPE_ANTHROPIC, u as getModelRefreshIntervalMs, v as isForceAgentEnabled, x as isResponsesApiContextManagementEnabled, y as isMessageStartInputTokensFallbackEnabled } from "./config-CmhIPHn_.js";
4
+ import { A as shouldCompactUseSmallModel, C as isResponsesApiWebSearchEnabled, D as resolveMappedModel, E as mergeConfigWithDefaults, O as resolveModelAlias, S as isResponsesApiContextManagementEnabled, _ as getSmallModel, a as getConfig, b as isMessageStartInputTokensFallbackEnabled, c as getModelAliases, d as getModelResponsesApiCompactThreshold$1, f as getProviderConfig, h as getReasoningEffortForModel, i as getClaudeTokenMultiplier, l as getModelAliasesInfo, m as getRawProviderConfig, n as getAliasTargetSet, o as getExtraPromptForModel, r as getAnthropicApiKey, s as getLogLevel, t as PROVIDER_TYPE_ANTHROPIC, u as getModelRefreshIntervalMs, v as isAccountAffinityEnabled, w as isResponsesApiWebSocketEnabled, x as isMessagesApiEnabled, y as isForceAgentEnabled } from "./config-BaU_aWgi.js";
5
+ import { a as forwardCodexResponses, n as setupCodexToken } from "./token-671YFxgv.js";
5
6
  import { i as getRequestOutboundStore, r as getRedactedHeaderKeys } from "./request-outbound-DZTxxtcx.js";
6
7
  import { i as isMcpHttpEnabledFromEnv, n as DEFAULT_MCP_HTTP_PATH } from "./mcp-http-config-DMdUDz1D.js";
7
8
  import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, i as isBridgeToolSearchName, l as selectDeferredToolsByNames, n as BRIDGE_TOOL_SEARCH_NAME, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, u as shouldEnableResponsesToolSearch } from "./mcp-server-DEqHrXFq.js";
8
9
  import { n as handleStreamableHttpMcpRequest, r as mcpHttpCorsOptions } from "./mcp-http-DI4Vz01p.js";
9
- import { S as createAuthMiddleware, _ as normalizeMessagesUsage, b as flushPendingCapture, c as accountsManager, d as extractResponsesUsageFromStreamEvent, f as getClientIpInfo, g as normalizeEmbeddingsUsage, h as normalizeChatCompletionsUsage, l as applySharedSessionAffinityRetention, m as getStatsStore, p as getRequestHistoryStore, s as updateQuotaRefreshSchedulerFromConfig, t as closeResponsesBridge, u as extractResponsesUsageFromResult, v as toLocalDateString, x as isDevModeEnabled, y as copilotFetch } from "./responses-bridge-registry-BJ5Sbh6-.js";
10
+ import { C as createAuthMiddleware, S as isDevModeEnabled, _ as normalizeMessagesUsage, b as copilotFetch, c as accountsManager, d as extractResponsesUsageFromStreamEvent, f as getClientIpInfo, g as normalizeEmbeddingsUsage, h as normalizeChatCompletionsUsage, l as applySharedSessionAffinityRetention, m as getStatsStore, p as getRequestHistoryStore, s as updateQuotaRefreshSchedulerFromConfig, t as closeResponsesBridge, u as extractResponsesUsageFromResult, v as normalizeResponsesUsage, x as flushPendingCapture, y as toLocalDateString } from "./responses-bridge-registry-DqCoY6Ex.js";
10
11
  import consola from "consola";
11
12
  import fs, { readFile } from "node:fs/promises";
12
13
  import { createHash, randomUUID } from "node:crypto";
@@ -953,6 +954,44 @@ const stripCacheControl = (payload) => {
953
954
  }
954
955
  }
955
956
  };
957
+ const normalizeCacheControl = (cacheControl) => {
958
+ if (!cacheControl || typeof cacheControl !== "object" || Array.isArray(cacheControl)) return;
959
+ const type = cacheControl.type;
960
+ return type === "ephemeral" ? { type } : void 0;
961
+ };
962
+ const applyTopLevelCacheControl = (payload) => {
963
+ const topLevel = normalizeCacheControl(payload.cache_control);
964
+ if (!topLevel) {
965
+ if (payload.cache_control !== void 0) delete payload.cache_control;
966
+ return;
967
+ }
968
+ delete payload.cache_control;
969
+ for (let m = payload.messages.length - 1; m >= 0; m--) {
970
+ const message = payload.messages[m];
971
+ if (typeof message.content === "string") {
972
+ message.content = [{
973
+ type: "text",
974
+ text: message.content,
975
+ cache_control: { ...topLevel }
976
+ }];
977
+ return;
978
+ }
979
+ if (!Array.isArray(message.content)) continue;
980
+ for (let b = message.content.length - 1; b >= 0; b--) {
981
+ const block = message.content[b];
982
+ if (block.type !== "text" && block.type !== "image" && block.type !== "tool_use" && block.type !== "tool_result") continue;
983
+ block.cache_control ??= { ...topLevel };
984
+ return;
985
+ }
986
+ }
987
+ };
988
+ const stripToolEagerInputStreaming = (payload) => {
989
+ if (!payload.tools || payload.tools.length === 0) return;
990
+ for (const tool of payload.tools) {
991
+ const extended = tool;
992
+ if ("eager_input_streaming" in extended) delete extended.eager_input_streaming;
993
+ }
994
+ };
956
995
  const filterAssistantThinkingBlocks = (payload) => {
957
996
  for (const msg of payload.messages) if (msg.role === "assistant" && Array.isArray(msg.content)) msg.content = msg.content.filter((block) => {
958
997
  if (block.type !== "thinking") return true;
@@ -961,6 +1000,8 @@ const filterAssistantThinkingBlocks = (payload) => {
961
1000
  };
962
1001
  const prepareMessagesApiPayload = (payload, selectedModel) => {
963
1002
  stripCacheControl(payload);
1003
+ applyTopLevelCacheControl(payload);
1004
+ stripToolEagerInputStreaming(payload);
964
1005
  filterAssistantThinkingBlocks(payload);
965
1006
  const hasThinking = Boolean(payload.thinking);
966
1007
  const toolChoice = payload.tool_choice;
@@ -2499,13 +2540,22 @@ adminApiRoutes.get("/accounts", async (c) => {
2499
2540
  unlimited: s.unlimited,
2500
2541
  failed: s.failed,
2501
2542
  failureReason: s.failureReason,
2502
- enabled: s.enabled
2543
+ enabled: s.enabled,
2544
+ lastModelsFetch: s.lastModelsFetch,
2545
+ isRefreshingModels: s.isRefreshingModels
2503
2546
  },
2504
2547
  stats
2505
2548
  };
2506
2549
  });
2507
2550
  return c.json({ items });
2508
2551
  });
2552
+ adminApiRoutes.post("/accounts/models/refresh", async (c) => {
2553
+ const { failedCount } = await accountsManager.refreshAllModelsNow();
2554
+ return c.json({
2555
+ ok: true,
2556
+ failedCount
2557
+ });
2558
+ });
2509
2559
  adminApiRoutes.get("/requests", (c) => {
2510
2560
  const p = new URL(c.req.url, "http://local").searchParams;
2511
2561
  const limit = parseFiniteNumber(p.get("limit")) ?? 50;
@@ -3736,6 +3786,41 @@ const createHandlerLogger = (name) => {
3736
3786
  return instance;
3737
3787
  };
3738
3788
  //#endregion
3789
+ //#region src/lib/provider-model.ts
3790
+ const parseProviderModelAlias = (model) => {
3791
+ const separatorIndex = model.indexOf("/");
3792
+ if (separatorIndex <= 0 || separatorIndex === model.length - 1) return null;
3793
+ const provider = model.slice(0, separatorIndex).trim();
3794
+ const providerModel = model.slice(separatorIndex + 1).trim();
3795
+ if (!provider || !providerModel) return null;
3796
+ return {
3797
+ model: providerModel,
3798
+ provider
3799
+ };
3800
+ };
3801
+ const resolveExistingProviderModelAlias = (model, resolveProvider) => {
3802
+ const alias = parseProviderModelAlias(model);
3803
+ if (!alias) return null;
3804
+ return resolveProvider(alias.provider) ? alias : null;
3805
+ };
3806
+ const createFallbackModel = (modelId) => ({
3807
+ capabilities: {
3808
+ family: "provider",
3809
+ limits: {},
3810
+ object: "model_capabilities",
3811
+ supports: {},
3812
+ tokenizer: "o200k_base",
3813
+ type: "chat"
3814
+ },
3815
+ id: modelId,
3816
+ model_picker_enabled: false,
3817
+ name: modelId,
3818
+ object: "model",
3819
+ preview: false,
3820
+ vendor: "provider",
3821
+ version: "unknown"
3822
+ });
3823
+ //#endregion
3739
3824
  //#region src/lib/rate-limit.ts
3740
3825
  async function checkRateLimit(state) {
3741
3826
  if (state.rateLimitSeconds === void 0) return;
@@ -3761,6 +3846,210 @@ async function checkRateLimit(state) {
3761
3846
  consola.info("Rate limit wait completed, proceeding with request");
3762
3847
  }
3763
3848
  //#endregion
3849
+ //#region src/lib/provider-resolver.ts
3850
+ function isMissingCodexCredentialsError(error) {
3851
+ return error instanceof Error && error.message === "Codex credentials not found. Run `copilot-api auth login --provider codex` first.";
3852
+ }
3853
+ async function resolveProviderConfig$3(providerName) {
3854
+ const normalizedProviderName = providerName.trim();
3855
+ if (!normalizedProviderName) return null;
3856
+ if (normalizedProviderName === "codex") {
3857
+ if (getRawProviderConfig(normalizedProviderName)?.enabled === false) return null;
3858
+ try {
3859
+ await setupCodexToken();
3860
+ } catch (error) {
3861
+ if (isMissingCodexCredentialsError(error)) return null;
3862
+ throw error;
3863
+ }
3864
+ const providerConfig = getProviderConfig(normalizedProviderName);
3865
+ if (!providerConfig) return null;
3866
+ return {
3867
+ ...providerConfig,
3868
+ apiKey: state.codexAccessToken ?? providerConfig.apiKey
3869
+ };
3870
+ }
3871
+ return getProviderConfig(normalizedProviderName);
3872
+ }
3873
+ //#endregion
3874
+ //#region src/lib/token-usage.ts
3875
+ function normalizeOpenAIUsage$1(usage) {
3876
+ const cacheCreationInputTokens = usage?.prompt_tokens_details?.cache_creation_input_tokens;
3877
+ const cacheReadInputTokens = usage?.prompt_tokens_details?.cached_tokens;
3878
+ return {
3879
+ inputTokens: usage?.prompt_tokens === void 0 ? void 0 : Math.max(0, usage.prompt_tokens - (cacheCreationInputTokens ?? 0) - (cacheReadInputTokens ?? 0)),
3880
+ outputTokens: usage?.completion_tokens,
3881
+ cacheCreationInputTokens,
3882
+ cacheReadInputTokens
3883
+ };
3884
+ }
3885
+ function createProviderTokenUsageRecorder(options) {
3886
+ const logger = createHandlerLogger(`provider-${options.providerName}`);
3887
+ return (usage) => {
3888
+ logger.debug(`${options.endpoint} usage`, {
3889
+ model: options.model,
3890
+ provider: options.providerName,
3891
+ ...usage
3892
+ });
3893
+ };
3894
+ }
3895
+ //#endregion
3896
+ //#region src/services/providers/provider-proxy.ts
3897
+ const SHARED_FORWARDABLE_HEADERS = ["accept", "user-agent"];
3898
+ const ANTHROPIC_FORWARDABLE_HEADERS = ["anthropic-version", "anthropic-beta"];
3899
+ const STRIPPED_RESPONSE_HEADERS = [
3900
+ "connection",
3901
+ "content-encoding",
3902
+ "content-length",
3903
+ "keep-alive",
3904
+ "proxy-authenticate",
3905
+ "proxy-authorization",
3906
+ "te",
3907
+ "trailer",
3908
+ "transfer-encoding",
3909
+ "upgrade"
3910
+ ];
3911
+ function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
3912
+ const authHeaders = {};
3913
+ if (providerConfig.authType === "x-api-key") authHeaders["x-api-key"] = providerConfig.apiKey;
3914
+ else authHeaders.authorization = `Bearer ${providerConfig.apiKey}`;
3915
+ const headers = {
3916
+ "content-type": "application/json",
3917
+ accept: "application/json",
3918
+ ...authHeaders
3919
+ };
3920
+ for (const headerName of SHARED_FORWARDABLE_HEADERS) {
3921
+ const headerValue = requestHeaders.get(headerName);
3922
+ if (headerValue) headers[headerName] = headerValue;
3923
+ }
3924
+ if (providerConfig.type !== "anthropic") return headers;
3925
+ for (const headerName of ANTHROPIC_FORWARDABLE_HEADERS) {
3926
+ const headerValue = requestHeaders.get(headerName);
3927
+ if (headerValue) headers[headerName] = headerValue;
3928
+ }
3929
+ return headers;
3930
+ }
3931
+ function createProviderProxyResponse(upstreamResponse, body) {
3932
+ const headers = new Headers(upstreamResponse.headers);
3933
+ for (const headerName of STRIPPED_RESPONSE_HEADERS) headers.delete(headerName);
3934
+ return new Response(body ?? upstreamResponse.body, {
3935
+ headers,
3936
+ status: upstreamResponse.status,
3937
+ statusText: upstreamResponse.statusText
3938
+ });
3939
+ }
3940
+ async function forwardProviderMessages(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
3941
+ return await fetchImpl(`${providerConfig.baseUrl}/v1/messages`, {
3942
+ method: "POST",
3943
+ headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
3944
+ body: JSON.stringify(payload)
3945
+ });
3946
+ }
3947
+ async function forwardProviderChatCompletions(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
3948
+ return await fetchImpl(`${providerConfig.baseUrl}/v1/chat/completions`, {
3949
+ method: "POST",
3950
+ headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
3951
+ body: JSON.stringify(payload)
3952
+ });
3953
+ }
3954
+ async function forwardProviderResponses(providerConfig, payload, requestHeaders) {
3955
+ return await fetch(`${providerConfig.baseUrl}/v1/responses`, {
3956
+ method: "POST",
3957
+ headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
3958
+ body: JSON.stringify(payload)
3959
+ });
3960
+ }
3961
+ async function forwardProviderModels(providerConfig, requestHeaders, fetchImpl = fetch) {
3962
+ return await fetchImpl(`${providerConfig.baseUrl}/v1/models`, {
3963
+ method: "GET",
3964
+ headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders)
3965
+ });
3966
+ }
3967
+ //#endregion
3968
+ //#region src/routes/provider/chat-completions/handler.ts
3969
+ const logger$8 = createHandlerLogger("provider-chat-completions-handler");
3970
+ async function handleProviderChatCompletionsForProvider(c, options) {
3971
+ const { payload, provider } = options;
3972
+ const providerConfig = await (c.get("providerConfigResolver") ?? resolveProviderConfig$3)(provider);
3973
+ if (providerConfig?.type !== "openai-compatible") return c.json({ error: {
3974
+ message: `Provider '${provider}' does not support the /v1/chat/completions endpoint`,
3975
+ type: "invalid_request_error"
3976
+ } }, 400);
3977
+ const modelConfig = providerConfig.models?.[payload.model];
3978
+ applyProviderModelDefaults(payload, modelConfig);
3979
+ applyMissingExtraBody$1(payload, { extraBody: modelConfig?.extraBody });
3980
+ applyProviderStreamOptions(payload);
3981
+ debugJson(logger$8, "provider.chat_completions.request", {
3982
+ payload,
3983
+ provider
3984
+ });
3985
+ const upstreamResponse = await forwardProviderChatCompletions(providerConfig, payload, c.req.raw.headers);
3986
+ if (!upstreamResponse.ok) {
3987
+ logger$8.error("Failed to create provider chat completions", {
3988
+ provider,
3989
+ statusCode: upstreamResponse.status
3990
+ });
3991
+ throw new HTTPError(`Failed to create ${provider} chat completions`, upstreamResponse);
3992
+ }
3993
+ const recordUsage = createProviderChatCompletionsUsageRecorder(payload, provider);
3994
+ const contentType = upstreamResponse.headers.get("content-type") ?? "";
3995
+ if (Boolean(payload.stream) && contentType.includes("text/event-stream")) return streamProviderChatCompletions(c, upstreamResponse, {
3996
+ provider,
3997
+ recordUsage
3998
+ });
3999
+ const responseBody = await upstreamResponse.clone().json();
4000
+ recordUsage(normalizeOpenAIUsage$1(responseBody.usage));
4001
+ debugJson(logger$8, "provider.chat_completions.response", responseBody);
4002
+ return createProviderProxyResponse(upstreamResponse);
4003
+ }
4004
+ const applyProviderModelDefaults = (payload, modelConfig) => {
4005
+ payload.temperature ??= modelConfig?.temperature;
4006
+ payload.top_p ??= modelConfig?.topP;
4007
+ payload.top_k ??= modelConfig?.topK;
4008
+ };
4009
+ const applyMissingExtraBody$1 = (payload, options) => {
4010
+ for (const [key, value] of Object.entries(options.extraBody ?? {})) if (!Object.hasOwn(payload, key)) payload[key] = value;
4011
+ };
4012
+ const applyProviderStreamOptions = (payload) => {
4013
+ if (!payload.stream) return;
4014
+ payload.stream_options = {
4015
+ ...payload.stream_options ?? {},
4016
+ include_usage: true
4017
+ };
4018
+ };
4019
+ const createProviderChatCompletionsUsageRecorder = (payload, provider) => createProviderTokenUsageRecorder({
4020
+ endpoint: "chat_completions",
4021
+ model: payload.model,
4022
+ providerName: provider
4023
+ });
4024
+ const streamProviderChatCompletions = (c, upstreamResponse, options) => {
4025
+ logger$8.debug("provider.chat_completions.streaming", { provider: options.provider });
4026
+ return streamSSE(c, async (stream) => {
4027
+ let usage = {};
4028
+ try {
4029
+ for await (const chunk of events(upstreamResponse)) {
4030
+ debugJson(logger$8, "provider.chat_completions.stream_chunk", chunk);
4031
+ if (chunk.data && chunk.data !== "[DONE]") {
4032
+ const parsedChunk = parseChatCompletionChunkData(chunk.data);
4033
+ if (parsedChunk?.usage) usage = normalizeOpenAIUsage$1(parsedChunk.usage);
4034
+ }
4035
+ await stream.writeSSE({
4036
+ event: chunk.event,
4037
+ data: chunk.data ?? ""
4038
+ });
4039
+ }
4040
+ } finally {
4041
+ options.recordUsage(usage);
4042
+ }
4043
+ });
4044
+ };
4045
+ const parseChatCompletionChunkData = (data) => {
4046
+ try {
4047
+ return JSON.parse(data);
4048
+ } catch {
4049
+ return null;
4050
+ }
4051
+ };
4052
+ //#endregion
3764
4053
  //#region src/routes/chat-completions/support.ts
3765
4054
  const CHAT_COMPLETIONS_ENDPOINT$1 = "/chat/completions";
3766
4055
  const GPT_5_4_MODEL_ID = "gpt-5.4";
@@ -3870,7 +4159,7 @@ function selectionFailureResponse$2(c, params) {
3870
4159
  }
3871
4160
  //#endregion
3872
4161
  //#region src/routes/chat-completions/handler.ts
3873
- const logger$6 = createHandlerLogger("chat-completions-handler");
4162
+ const logger$7 = createHandlerLogger("chat-completions-handler");
3874
4163
  function buildChatCompletionCandidates(clientModel) {
3875
4164
  return [{
3876
4165
  modelId: clientModel,
@@ -3905,10 +4194,21 @@ function maybeRejectChatCompletionsClientModel(c, store, params) {
3905
4194
  return null;
3906
4195
  }
3907
4196
  async function handleCompletion$1(c) {
4197
+ const payload = await c.req.json();
4198
+ const mappedModelResolver = c.get("resolveMappedModel") ?? resolveMappedModel;
4199
+ const providerConfigResolver = c.get("providerConfigResolver") ?? getProviderConfig;
4200
+ payload.model = mappedModelResolver(payload.model);
4201
+ const providerModelAlias = resolveExistingProviderModelAlias(payload.model, providerConfigResolver);
4202
+ if (providerModelAlias) {
4203
+ payload.model = providerModelAlias.model;
4204
+ return await handleProviderChatCompletionsForProvider(c, {
4205
+ payload,
4206
+ provider: providerModelAlias.provider
4207
+ });
4208
+ }
3908
4209
  await checkRateLimit(state);
3909
4210
  const store = getRequestHistoryStore();
3910
4211
  const request = buildRequestContext$1(c);
3911
- const payload = await c.req.json();
3912
4212
  const clientModel = payload.model;
3913
4213
  const streamRequested = Boolean(payload.stream);
3914
4214
  const normalizedPromptCacheKey = applyChatRequestMetadata(request, payload, getChatInitiator(payload.messages));
@@ -4007,12 +4307,12 @@ async function writeChatCompletionsStreamError(stream, message) {
4007
4307
  } }) });
4008
4308
  await stream.writeSSE({ data: "[DONE]" });
4009
4309
  } catch (streamError) {
4010
- logger$6.warn("Failed to write chat completions stream error event:", streamError);
4310
+ logger$7.warn("Failed to write chat completions stream error event:", streamError);
4011
4311
  }
4012
4312
  }
4013
4313
  async function selectChatCompletionAccount(params) {
4014
4314
  const { c, store, request, payload, clientModel, streamRequested, normalizedPromptCacheKey } = params;
4015
- debugJsonTail(logger$6, "Request payload:", {
4315
+ debugJsonTail(logger$7, "Request payload:", {
4016
4316
  value: payload,
4017
4317
  tailLength: 400
4018
4318
  });
@@ -4047,9 +4347,9 @@ async function selectChatCompletionAccount(params) {
4047
4347
  async function logTokenCountForRequest(params) {
4048
4348
  try {
4049
4349
  const tokenCount = await getTokenCount(params.payload, params.selectedModel);
4050
- logger$6.info("Current token count:", tokenCount);
4350
+ logger$7.info("Current token count:", tokenCount);
4051
4351
  } catch (error) {
4052
- logger$6.warn("Failed to calculate token count:", error);
4352
+ logger$7.warn("Failed to calculate token count:", error);
4053
4353
  }
4054
4354
  }
4055
4355
  function applyDefaultMaxTokens(payload, selectedModel) {
@@ -4058,7 +4358,7 @@ function applyDefaultMaxTokens(payload, selectedModel) {
4058
4358
  ...payload,
4059
4359
  max_tokens: selectedModel.capabilities.limits.max_output_tokens
4060
4360
  };
4061
- debugJson(logger$6, "Set max_tokens to:", updated.max_tokens);
4361
+ debugJson(logger$7, "Set max_tokens to:", updated.max_tokens);
4062
4362
  return updated;
4063
4363
  }
4064
4364
  async function handleStreamingRequest(params) {
@@ -4092,7 +4392,7 @@ async function handleStreamingRequest(params) {
4092
4392
  premiumUnlimitedBefore,
4093
4393
  response
4094
4394
  });
4095
- logger$6.debug("Streaming response");
4395
+ logger$7.debug("Streaming response");
4096
4396
  return streamSSE(c, (stream) => streamChatCompletionsAndLog$1({
4097
4397
  stream,
4098
4398
  response,
@@ -4147,7 +4447,7 @@ async function handleNonStreamingUpstreamResponse(params) {
4147
4447
  let upstreamErrorMessageRaw;
4148
4448
  const finishedAtMs = Date.now();
4149
4449
  try {
4150
- debugJson(logger$6, "Non-streaming response:", response);
4450
+ debugJson(logger$7, "Non-streaming response:", response);
4151
4451
  return c.json(response);
4152
4452
  } catch (error) {
4153
4453
  const details = await extractErrorObservability(error);
@@ -4200,7 +4500,7 @@ async function streamChatCompletionsAndLog$1(params) {
4200
4500
  if (ttfbMs === void 0) ttfbMs = Date.now() - request.startedAtMs;
4201
4501
  const usage = await extractUsageFromChunk(chunk);
4202
4502
  if (usage) lastUsage = usage;
4203
- debugJson(logger$6, "Streaming chunk:", chunk);
4503
+ debugJson(logger$7, "Streaming chunk:", chunk);
4204
4504
  await stream.writeSSE(chunk);
4205
4505
  }
4206
4506
  } catch (error) {
@@ -4209,7 +4509,7 @@ async function streamChatCompletionsAndLog$1(params) {
4209
4509
  errorStatus = details.errorStatus;
4210
4510
  errorMessage = details.errorMessage;
4211
4511
  upstreamErrorMessageRaw = details.upstreamErrorMessageRaw;
4212
- logger$6.warn("Streaming error:", error);
4512
+ logger$7.warn("Streaming error:", error);
4213
4513
  if (shouldMarkAccountFailed(details)) accountsManager.markAccountFailed(account.id, "Unauthorized (401)");
4214
4514
  await writeChatCompletionsStreamError(stream, getUserVisibleErrorMessage(details));
4215
4515
  } finally {
@@ -4247,7 +4547,7 @@ async function extractUsageFromChunk(chunk) {
4247
4547
  try {
4248
4548
  data = typeof chunk.data === "string" ? chunk.data : await chunk.data;
4249
4549
  } catch (error) {
4250
- logger$6.warn("Failed to read chat completions usage chunk:", error);
4550
+ logger$7.warn("Failed to read chat completions usage chunk:", error);
4251
4551
  return;
4252
4552
  }
4253
4553
  if (!data || data === "[DONE]") return;
@@ -4256,7 +4556,7 @@ async function extractUsageFromChunk(chunk) {
4256
4556
  if (!parsed.usage) return void 0;
4257
4557
  return normalizeChatCompletionsUsage(parsed.usage);
4258
4558
  } catch (error) {
4259
- logger$6.warn("Failed to parse chat completions usage chunk:", {
4559
+ logger$7.warn("Failed to parse chat completions usage chunk:", {
4260
4560
  error,
4261
4561
  data
4262
4562
  });
@@ -4283,7 +4583,7 @@ async function handleNonStreamingRequest(params) {
4283
4583
  selection.confirmAffinity?.();
4284
4584
  finishedAtMs = Date.now();
4285
4585
  usage = normalizeChatCompletionsUsage(response.usage);
4286
- debugJson(logger$6, "Non-streaming response:", response);
4586
+ debugJson(logger$7, "Non-streaming response:", response);
4287
4587
  return c.json(response);
4288
4588
  } catch (error) {
4289
4589
  finishedAtMs = Date.now();
@@ -4505,43 +4805,8 @@ async function runEmbeddingsWithAccount({ c, store, ctx, payload, clientModel, s
4505
4805
  }
4506
4806
  }
4507
4807
  //#endregion
4508
- //#region src/lib/provider-model.ts
4509
- const parseProviderModelAlias = (model) => {
4510
- const separatorIndex = model.indexOf("/");
4511
- if (separatorIndex <= 0 || separatorIndex === model.length - 1) return null;
4512
- const provider = model.slice(0, separatorIndex).trim();
4513
- const providerModel = model.slice(separatorIndex + 1).trim();
4514
- if (!provider || !providerModel) return null;
4515
- return {
4516
- model: providerModel,
4517
- provider
4518
- };
4519
- };
4520
- const resolveExistingProviderModelAlias = (model, resolveProvider) => {
4521
- const alias = parseProviderModelAlias(model);
4522
- if (!alias) return null;
4523
- return resolveProvider(alias.provider) ? alias : null;
4524
- };
4525
- const createFallbackModel = (modelId) => ({
4526
- capabilities: {
4527
- family: "provider",
4528
- limits: {},
4529
- object: "model_capabilities",
4530
- supports: {},
4531
- tokenizer: "o200k_base",
4532
- type: "chat"
4533
- },
4534
- id: modelId,
4535
- model_picker_enabled: false,
4536
- name: modelId,
4537
- object: "model",
4538
- preview: false,
4539
- vendor: "provider",
4540
- version: "unknown"
4541
- });
4542
- //#endregion
4543
4808
  //#region src/routes/provider/messages/count-tokens-handler.ts
4544
- const logger$5 = createHandlerLogger("provider-count-tokens-handler");
4809
+ const logger$6 = createHandlerLogger("provider-count-tokens-handler");
4545
4810
  const resolveProviderConfig$2 = (c, provider) => {
4546
4811
  return (c.get("providerConfigResolver") ?? getProviderConfig)(provider);
4547
4812
  };
@@ -4573,14 +4838,14 @@ async function handleProviderCountTokensForProvider(c, options) {
4573
4838
  try {
4574
4839
  const tokenCount = await getTokenCount(translateToOpenAI(anthropicPayload, translationOptions), findEndpointModel(modelId) ?? createFallbackModel(modelId));
4575
4840
  const finalTokenCount = tokenCount.input + tokenCount.output;
4576
- logger$5.debug("provider.count_tokens.success", {
4841
+ logger$6.debug("provider.count_tokens.success", {
4577
4842
  provider,
4578
4843
  model: anthropicPayload.model,
4579
4844
  input_tokens: finalTokenCount
4580
4845
  });
4581
4846
  return c.json({ input_tokens: finalTokenCount });
4582
4847
  } catch (error) {
4583
- logger$5.error("provider.count_tokens.error", {
4848
+ logger$6.error("provider.count_tokens.error", {
4584
4849
  provider,
4585
4850
  error
4586
4851
  });
@@ -5035,7 +5300,11 @@ const consumeResponsesWebSocketStream = async (stream) => {
5035
5300
  for await (const chunk of stream) {
5036
5301
  if (!chunk.data || chunk.data === "[DONE]") continue;
5037
5302
  const event = JSON.parse(chunk.data);
5038
- if (event.type === "error") throw new Error(event.message);
5303
+ if (event.type === "error") {
5304
+ const status = typeof event.code === "string" ? parseInt(event.code, 10) : NaN;
5305
+ const httpStatus = Number.isFinite(status) && status >= 100 && status < 600 ? status : 500;
5306
+ throw new HTTPError(event.message, new Response(JSON.stringify({ error: { message: event.message } }), { status: httpStatus }));
5307
+ }
5039
5308
  if (event.type === "response.completed" || event.type === "response.failed" || event.type === "response.incomplete") return event.response;
5040
5309
  }
5041
5310
  throw new Error("Responses websocket ended without a terminal response");
@@ -6015,73 +6284,8 @@ function closeThinkingBlockIfOpen(state, events) {
6015
6284
  }
6016
6285
  }
6017
6286
  //#endregion
6018
- //#region src/services/providers/provider-proxy.ts
6019
- const SHARED_FORWARDABLE_HEADERS = ["accept", "user-agent"];
6020
- const ANTHROPIC_FORWARDABLE_HEADERS = ["anthropic-version", "anthropic-beta"];
6021
- const STRIPPED_RESPONSE_HEADERS = [
6022
- "connection",
6023
- "content-encoding",
6024
- "content-length",
6025
- "keep-alive",
6026
- "proxy-authenticate",
6027
- "proxy-authorization",
6028
- "te",
6029
- "trailer",
6030
- "transfer-encoding",
6031
- "upgrade"
6032
- ];
6033
- function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
6034
- const authHeaders = {};
6035
- if (providerConfig.authType === "x-api-key") authHeaders["x-api-key"] = providerConfig.apiKey;
6036
- else authHeaders.authorization = `Bearer ${providerConfig.apiKey}`;
6037
- const headers = {
6038
- "content-type": "application/json",
6039
- accept: "application/json",
6040
- ...authHeaders
6041
- };
6042
- for (const headerName of SHARED_FORWARDABLE_HEADERS) {
6043
- const headerValue = requestHeaders.get(headerName);
6044
- if (headerValue) headers[headerName] = headerValue;
6045
- }
6046
- if (providerConfig.type !== "anthropic") return headers;
6047
- for (const headerName of ANTHROPIC_FORWARDABLE_HEADERS) {
6048
- const headerValue = requestHeaders.get(headerName);
6049
- if (headerValue) headers[headerName] = headerValue;
6050
- }
6051
- return headers;
6052
- }
6053
- function createProviderProxyResponse(upstreamResponse, body) {
6054
- const headers = new Headers(upstreamResponse.headers);
6055
- for (const headerName of STRIPPED_RESPONSE_HEADERS) headers.delete(headerName);
6056
- return new Response(body ?? upstreamResponse.body, {
6057
- headers,
6058
- status: upstreamResponse.status,
6059
- statusText: upstreamResponse.statusText
6060
- });
6061
- }
6062
- async function forwardProviderMessages(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
6063
- return await fetchImpl(`${providerConfig.baseUrl}/v1/messages`, {
6064
- method: "POST",
6065
- headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
6066
- body: JSON.stringify(payload)
6067
- });
6068
- }
6069
- async function forwardProviderChatCompletions(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
6070
- return await fetchImpl(`${providerConfig.baseUrl}/v1/chat/completions`, {
6071
- method: "POST",
6072
- headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
6073
- body: JSON.stringify(payload)
6074
- });
6075
- }
6076
- async function forwardProviderModels(providerConfig, requestHeaders, fetchImpl = fetch) {
6077
- return await fetchImpl(`${providerConfig.baseUrl}/v1/models`, {
6078
- method: "GET",
6079
- headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders)
6080
- });
6081
- }
6082
- //#endregion
6083
6287
  //#region src/routes/provider/messages/handler.ts
6084
- const logger$4 = createHandlerLogger("provider-messages-handler");
6288
+ const logger$5 = createHandlerLogger("provider-messages-handler");
6085
6289
  const getProviderFetch$1 = (c) => c.get("providerFetch") ?? fetch;
6086
6290
  const resolveProviderConfig$1 = (c, provider) => {
6087
6291
  return (c.get("providerConfigResolver") ?? getProviderConfig)(provider);
@@ -6107,7 +6311,7 @@ const writeProviderStreamError = async (stream, message) => {
6107
6311
  })
6108
6312
  });
6109
6313
  } catch (error) {
6110
- logger$4.warn("Failed to write provider stream error event", error);
6314
+ logger$5.warn("Failed to write provider stream error event", error);
6111
6315
  }
6112
6316
  };
6113
6317
  async function handleProviderMessages(c) {
@@ -6136,7 +6340,7 @@ async function handleProviderMessagesForProvider(c, options) {
6136
6340
  try {
6137
6341
  const modelConfig = providerConfig.models?.[payload.model];
6138
6342
  applyModelDefaults(payload, modelConfig);
6139
- debugJson(logger$4, "provider.messages.request", {
6343
+ debugJson(logger$5, "provider.messages.request", {
6140
6344
  payload,
6141
6345
  provider
6142
6346
  });
@@ -6150,7 +6354,7 @@ async function handleProviderMessagesForProvider(c, options) {
6150
6354
  applyMissingExtraBody(payload, { extraBody: modelConfig?.extraBody });
6151
6355
  const upstreamResponse = await forwardProviderMessages(providerConfig, payload, c.req.raw.headers, getProviderFetch$1(c));
6152
6356
  if (!upstreamResponse.ok) {
6153
- logger$4.error("Failed to create responses", upstreamResponse);
6357
+ logger$5.error("Failed to create responses", upstreamResponse);
6154
6358
  throw new HTTPError("Failed to create responses", upstreamResponse);
6155
6359
  }
6156
6360
  const contentType = upstreamResponse.headers.get("content-type") ?? "";
@@ -6170,7 +6374,7 @@ async function handleProviderMessagesForProvider(c, options) {
6170
6374
  providerConfig
6171
6375
  });
6172
6376
  } catch (error) {
6173
- logger$4.error("provider.messages.error", {
6377
+ logger$5.error("provider.messages.error", {
6174
6378
  provider,
6175
6379
  error
6176
6380
  });
@@ -6207,13 +6411,13 @@ const applyOpenAICompatibleExtraBodyThinkingBudget = (payload, options) => {
6207
6411
  const handleOpenAICompatibleProviderMessages = async (c, options) => {
6208
6412
  const { instrumentation, modelConfig, payload, provider, providerConfig } = options;
6209
6413
  const openAIPayload = createOpenAICompatiblePayload(payload, modelConfig);
6210
- debugJson(logger$4, "provider.messages.openai_compatible.request", {
6414
+ debugJson(logger$5, "provider.messages.openai_compatible.request", {
6211
6415
  payload: openAIPayload,
6212
6416
  provider
6213
6417
  });
6214
6418
  const upstreamResponse = await forwardProviderChatCompletions(providerConfig, openAIPayload, c.req.raw.headers, getProviderFetch$1(c));
6215
6419
  if (!upstreamResponse.ok) {
6216
- logger$4.error("Failed to create openai-compatible responses", upstreamResponse);
6420
+ logger$5.error("Failed to create openai-compatible responses", upstreamResponse);
6217
6421
  throw new HTTPError("Failed to create openai-compatible responses", upstreamResponse);
6218
6422
  }
6219
6423
  const contentType = upstreamResponse.headers.get("content-type") ?? "";
@@ -6297,13 +6501,13 @@ const setContextCacheControl = (part) => {
6297
6501
  part.cache_control = { ...OPENAI_COMPATIBLE_CONTEXT_CACHE_CONTROL };
6298
6502
  };
6299
6503
  const streamProviderMessages = ({ c, instrumentation, providerConfig, upstreamResponse }) => {
6300
- logger$4.debug("provider.messages.streaming");
6504
+ logger$5.debug("provider.messages.streaming");
6301
6505
  return streamSSE(c, async (stream) => {
6302
6506
  let usage = {};
6303
6507
  try {
6304
6508
  let completed = false;
6305
6509
  for await (const chunk of events(upstreamResponse)) {
6306
- logger$4.debug("provider.messages.raw_stream_event:", chunk.data);
6510
+ logger$5.debug("provider.messages.raw_stream_event:", chunk.data);
6307
6511
  const eventName = chunk.event;
6308
6512
  if (eventName === "ping") {
6309
6513
  await stream.writeSSE({
@@ -6339,14 +6543,14 @@ const streamProviderMessages = ({ c, instrumentation, providerConfig, upstreamRe
6339
6543
  instrumentation?.onComplete?.(usage);
6340
6544
  } catch (error) {
6341
6545
  const details = await extractErrorObservability(error);
6342
- logger$4.warn("provider.messages.streaming.error", error);
6546
+ logger$5.warn("provider.messages.streaming.error", error);
6343
6547
  instrumentation?.onError?.(details);
6344
6548
  await writeProviderStreamError(stream, getUserVisibleErrorMessage(details));
6345
6549
  }
6346
6550
  });
6347
6551
  };
6348
6552
  const streamOpenAICompatibleProviderMessages = ({ c, instrumentation, upstreamResponse }) => {
6349
- logger$4.debug("provider.messages.openai_compatible.streaming");
6553
+ logger$5.debug("provider.messages.openai_compatible.streaming");
6350
6554
  return streamSSE(c, async (stream) => {
6351
6555
  let usage = {};
6352
6556
  const streamState = {
@@ -6359,7 +6563,7 @@ const streamOpenAICompatibleProviderMessages = ({ c, instrumentation, upstreamRe
6359
6563
  try {
6360
6564
  let completed = false;
6361
6565
  for await (const chunk of events(upstreamResponse)) {
6362
- logger$4.debug("provider.messages.openai_compatible.raw_stream_event:", chunk.data);
6566
+ logger$5.debug("provider.messages.openai_compatible.raw_stream_event:", chunk.data);
6363
6567
  if (chunk.event === "ping") {
6364
6568
  await stream.writeSSE({
6365
6569
  event: "ping",
@@ -6377,7 +6581,7 @@ const streamOpenAICompatibleProviderMessages = ({ c, instrumentation, upstreamRe
6377
6581
  const events = translateChunkToAnthropicEvents(parsed, streamState);
6378
6582
  for (const event of events) {
6379
6583
  const eventData = JSON.stringify(event);
6380
- debugLazy(logger$4, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6584
+ debugLazy(logger$5, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6381
6585
  await stream.writeSSE({
6382
6586
  event: event.type,
6383
6587
  data: eventData
@@ -6387,7 +6591,7 @@ const streamOpenAICompatibleProviderMessages = ({ c, instrumentation, upstreamRe
6387
6591
  }
6388
6592
  for (const event of flushPendingAnthropicStreamEvents(streamState)) {
6389
6593
  const eventData = JSON.stringify(event);
6390
- debugLazy(logger$4, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6594
+ debugLazy(logger$5, () => ["provider.messages.openai_compatible.translated_event:", eventData]);
6391
6595
  await stream.writeSSE({
6392
6596
  event: event.type,
6393
6597
  data: eventData
@@ -6398,7 +6602,7 @@ const streamOpenAICompatibleProviderMessages = ({ c, instrumentation, upstreamRe
6398
6602
  instrumentation?.onComplete?.(usage);
6399
6603
  } catch (error) {
6400
6604
  const details = await extractErrorObservability(error);
6401
- logger$4.warn("provider.messages.openai_compatible.streaming.error", error);
6605
+ logger$5.warn("provider.messages.openai_compatible.streaming.error", error);
6402
6606
  instrumentation?.onError?.(details);
6403
6607
  await writeProviderStreamError(stream, getUserVisibleErrorMessage(details));
6404
6608
  }
@@ -6409,7 +6613,7 @@ const parseOpenAICompatibleStreamChunk = (data) => {
6409
6613
  try {
6410
6614
  parsed = JSON.parse(data);
6411
6615
  } catch (error) {
6412
- logger$4.error("provider.messages.openai_compatible.parse_chunk_error", {
6616
+ logger$5.error("provider.messages.openai_compatible.parse_chunk_error", {
6413
6617
  data,
6414
6618
  error
6415
6619
  });
@@ -6466,7 +6670,7 @@ const parseProviderStreamEvent = (data, providerConfig) => {
6466
6670
  usage: {}
6467
6671
  };
6468
6672
  } catch (error) {
6469
- logger$4.error("provider.messages.streaming.adjust_tokens_error", {
6673
+ logger$5.error("provider.messages.streaming.adjust_tokens_error", {
6470
6674
  error,
6471
6675
  originalData: data
6472
6676
  });
@@ -6476,7 +6680,7 @@ const parseProviderStreamEvent = (data, providerConfig) => {
6476
6680
  const respondProviderMessagesJson = (c, options) => {
6477
6681
  const { body, instrumentation, providerConfig } = options;
6478
6682
  adjustInputTokens(providerConfig, body.usage);
6479
- debugJson(logger$4, "provider.messages.no_stream result:", body);
6683
+ debugJson(logger$5, "provider.messages.no_stream result:", body);
6480
6684
  const response = c.json(body);
6481
6685
  instrumentation?.onComplete?.(normalizeAnthropicUsage(body.usage));
6482
6686
  return response;
@@ -6484,7 +6688,7 @@ const respondProviderMessagesJson = (c, options) => {
6484
6688
  const respondOpenAICompatibleProviderMessagesJson = (c, options) => {
6485
6689
  const { body, instrumentation } = options;
6486
6690
  const anthropicResponse = translateToAnthropic(body);
6487
- debugJson(logger$4, "provider.messages.openai_compatible.no_stream result:", anthropicResponse);
6691
+ debugJson(logger$5, "provider.messages.openai_compatible.no_stream result:", anthropicResponse);
6488
6692
  const response = c.json(anthropicResponse);
6489
6693
  instrumentation?.onComplete?.(normalizeOpenAIUsage(body.usage));
6490
6694
  return response;
@@ -6514,7 +6718,7 @@ const mergeAnthropicUsage = (current, next) => ({
6514
6718
  const adjustInputTokens = (providerConfig, usage) => {
6515
6719
  if (!providerConfig.adjustInputTokens || !usage) return;
6516
6720
  usage.input_tokens = Math.max(0, (usage.input_tokens ?? 0) - (usage.cache_read_input_tokens ?? 0) - (usage.cache_creation_input_tokens ?? 0));
6517
- debugJson(logger$4, "provider.messages.adjusted_usage:", usage);
6721
+ debugJson(logger$5, "provider.messages.adjusted_usage:", usage);
6518
6722
  };
6519
6723
  //#endregion
6520
6724
  //#region src/routes/messages/responses-stream-translation.ts
@@ -6991,6 +7195,7 @@ const stringifyToolSearchArguments = (argumentsValue) => {
6991
7195
  };
6992
7196
  const DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO = .9;
6993
7197
  const responsesUtilsDependencies = {
7198
+ getModelResponsesApiCompactThreshold: getModelResponsesApiCompactThreshold$1,
6994
7199
  isResponsesApiContextManagementEnabled,
6995
7200
  isResponsesApiWebSocketEnabled
6996
7201
  };
@@ -7021,7 +7226,8 @@ const isAgentRole = (item) => {
7021
7226
  const hasVisionInput$1 = (payload) => {
7022
7227
  return getPayloadItems(payload).some((item) => containsVisionContent(item));
7023
7228
  };
7024
- "" + [
7229
+ const DATA_URL_PREFIX = "data:";
7230
+ const REDACTED_IMAGE_PLACEHOLDER_DATA_URL = "data:image/png;base64," + [
7025
7231
  "iVBORw0KGgoAAAANSUhEUgAAAGAAAAAgCAMAAADaHo1mAAADAFBMVEX///8fKTfR1dsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7026
7232
  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7027
7233
  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
@@ -7038,10 +7244,71 @@ const hasVisionInput$1 = (payload) => {
7038
7244
  "ucSQ4s8JkKDDIYr3IuR8vEWgqroKP9b1bYKk2wfgeVmqATQLXdXamsXdEKkz3QXEEeTTuWWImMhW6qci94/+hwSVf99HqVoD",
7039
7245
  "OAuj2SEAAAAASUVORK5CYII="
7040
7246
  ].join("");
7247
+ const sanitizeOversizedInputImages = (payload, maxPromptImageSize) => {
7248
+ const limit = typeof maxPromptImageSize === "number" && maxPromptImageSize > 0 ? maxPromptImageSize : void 0;
7249
+ if (limit === void 0 || !Array.isArray(payload.input)) return 0;
7250
+ return sanitizeInputImages(payload.input, (image) => image.decodedBytes > limit);
7251
+ };
7252
+ const sanitizeInputImages = (input, shouldReplace) => {
7253
+ let count = 0;
7254
+ for (const image of collectInputImageDataUrls(input)) {
7255
+ if (!shouldReplace(image)) continue;
7256
+ replaceInputImageWithPlaceholder(image);
7257
+ count += 1;
7258
+ }
7259
+ return count;
7260
+ };
7261
+ const collectInputImageDataUrls = (input, images = []) => {
7262
+ for (const item of input) collectInputItemImageDataUrls(item, images);
7263
+ return images;
7264
+ };
7265
+ const collectInputItemImageDataUrls = (item, images) => {
7266
+ if (isResponseInputMessage(item)) collectContentImageDataUrls(item.content, images);
7267
+ else if (isResponseFunctionCallOutputItem(item)) collectContentImageDataUrls(item.output, images);
7268
+ };
7269
+ const collectContentImageDataUrls = (content, images) => {
7270
+ if (!Array.isArray(content)) return;
7271
+ for (const block of content) {
7272
+ const image = getInputImageDataUrl(block);
7273
+ if (image) images.push(image);
7274
+ }
7275
+ };
7276
+ const getInputImageDataUrl = (content) => {
7277
+ if (!isResponseInputImage(content) || typeof content.image_url !== "string") return null;
7278
+ const imageUrl = content.image_url;
7279
+ if (!imageUrl.startsWith(DATA_URL_PREFIX)) return null;
7280
+ return {
7281
+ decodedBytes: estimateDataUrlByteLength(imageUrl),
7282
+ record: content
7283
+ };
7284
+ };
7285
+ const estimateDataUrlByteLength = (value) => {
7286
+ return Math.max(0, Math.floor(value.length * 3 / 4));
7287
+ };
7288
+ const replaceInputImageWithPlaceholder = (image) => {
7289
+ image.record.type = "input_image";
7290
+ image.record.image_url = REDACTED_IMAGE_PLACEHOLDER_DATA_URL;
7291
+ image.record.detail = "low";
7292
+ delete image.record.file_id;
7293
+ };
7294
+ const isResponseInputMessage = (item) => {
7295
+ return typeof item === "object" && item !== null && "role" in item && typeof item.role === "string";
7296
+ };
7297
+ const isResponseFunctionCallOutputItem = (item) => {
7298
+ return typeof item === "object" && item !== null && "type" in item && item.type === "function_call_output";
7299
+ };
7300
+ const isResponseInputImage = (content) => {
7301
+ return typeof content === "object" && content !== null && "type" in content && content.type === "input_image";
7302
+ };
7041
7303
  const resolveResponsesCompactThreshold = (maxPromptTokens, compactThresholdRatio = DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO) => {
7042
7304
  if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * compactThresholdRatio);
7043
7305
  return 2e5 * compactThresholdRatio;
7044
7306
  };
7307
+ const getModelResponsesApiCompactThreshold = (model) => {
7308
+ const threshold = responsesUtilsDependencies.getModelResponsesApiCompactThreshold(model);
7309
+ if (typeof threshold !== "number" || !Number.isFinite(threshold) || threshold <= 0) return;
7310
+ return threshold;
7311
+ };
7045
7312
  const createCompactionContextManagement = (compactThreshold) => [{
7046
7313
  type: "compaction",
7047
7314
  compact_threshold: compactThreshold
@@ -7049,7 +7316,7 @@ const createCompactionContextManagement = (compactThreshold) => [{
7049
7316
  const applyResponsesApiContextManagement = (payload, maxPromptTokens, compactThresholdRatio = DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO) => {
7050
7317
  if (payload.context_management !== void 0) return;
7051
7318
  if (!responsesUtilsDependencies.isResponsesApiContextManagementEnabled()) return;
7052
- payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens, compactThresholdRatio));
7319
+ payload.context_management = createCompactionContextManagement(getModelResponsesApiCompactThreshold(payload.model) ?? resolveResponsesCompactThreshold(maxPromptTokens, compactThresholdRatio));
7053
7320
  };
7054
7321
  const compactInputByLatestCompaction = (payload) => {
7055
7322
  if (!Array.isArray(payload.input) || payload.input.length === 0) return;
@@ -7291,7 +7558,7 @@ const extractBalancedJson = (text) => {
7291
7558
  };
7292
7559
  //#endregion
7293
7560
  //#region src/routes/messages/handler.ts
7294
- const logger$3 = createHandlerLogger("messages-handler");
7561
+ const logger$4 = createHandlerLogger("messages-handler");
7295
7562
  const CHAT_COMPLETIONS_ENDPOINT = "/chat/completions";
7296
7563
  const RESPONSES_ENDPOINT$1 = "/responses";
7297
7564
  const MESSAGES_ENDPOINT = "/v1/messages";
@@ -7337,7 +7604,7 @@ async function handleProviderAliasCompletion(c, options) {
7337
7604
  let requestRecorded = false;
7338
7605
  const insertProviderAliasLog = (record) => {
7339
7606
  if (requestRecorded) {
7340
- logger$3.warn("provider alias request already recorded", { requestId });
7607
+ logger$4.warn("provider alias request already recorded", { requestId });
7341
7608
  return;
7342
7609
  }
7343
7610
  requestRecorded = true;
@@ -7412,14 +7679,14 @@ async function handleCompletion(c) {
7412
7679
  const userAgent = c.req.header("user-agent") ?? void 0;
7413
7680
  normalizeSystemMessages(anthropicPayload);
7414
7681
  sanitizeIdeTools(anthropicPayload);
7415
- debugJson(logger$3, "Anthropic request payload:", anthropicPayload);
7682
+ debugJson(logger$4, "Anthropic request payload:", anthropicPayload);
7416
7683
  const markerInspection = inspectSubagentMarkerFromFirstUser(anthropicPayload);
7417
7684
  const subagentMarker = markerInspection.kind === "valid" ? markerInspection.marker : null;
7418
7685
  const isSubagentRequest = subagentMarker !== null;
7419
7686
  const invalidSubagentMarkerSelectionReason = markerInspection.kind === "invalid" ? "subagent_marker_invalid_fallback" : void 0;
7420
- if (subagentMarker) debugJson(logger$3, "Detected Subagent marker:", subagentMarker);
7687
+ if (subagentMarker) debugJson(logger$4, "Detected Subagent marker:", subagentMarker);
7421
7688
  const sessionId = getRootSessionId(anthropicPayload, c);
7422
- logger$3.debug("Extracted session ID:", sessionId);
7689
+ logger$4.debug("Extracted session ID:", sessionId);
7423
7690
  const ownershipLookupSessionId = markerInspection.kind === "valid" ? normalizeStableSessionId(markerInspection.marker.session_id) : void 0;
7424
7691
  const ownershipWriteSessionId = markerInspection.kind === "none" ? sessionId : void 0;
7425
7692
  const anthropicBeta = c.req.header("anthropic-beta");
@@ -7427,7 +7694,7 @@ async function handleCompletion(c) {
7427
7694
  const isCompact = compactType !== 0;
7428
7695
  const originalRequestModel = anthropicPayload.model;
7429
7696
  if (anthropicBeta && isWarmupProbeRequest(anthropicPayload)) anthropicPayload.model = getSmallModel();
7430
- if (compactType !== 0) logger$3.debug("Compact request type:", compactType);
7697
+ if (compactType !== 0) logger$4.debug("Compact request type:", compactType);
7431
7698
  const lastMessageCacheControl = getLastMessageContentCacheControl(anthropicPayload.messages.at(-1));
7432
7699
  if (compactType === 1 && shouldCompactUseSmallModel()) anthropicPayload.model = getSmallModel();
7433
7700
  if (compactType === 0) {
@@ -7436,7 +7703,7 @@ async function handleCompletion(c) {
7436
7703
  }
7437
7704
  applyLastMessageCacheControl(anthropicPayload, lastMessageCacheControl);
7438
7705
  const upstreamRequestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
7439
- logger$3.debug("Generated request ID:", upstreamRequestId);
7706
+ logger$4.debug("Generated request ID:", upstreamRequestId);
7440
7707
  const clientModel = anthropicPayload.model;
7441
7708
  anthropicPayload.model = resolveModelAlias(anthropicPayload.model);
7442
7709
  const routingModel = anthropicPayload.model;
@@ -7593,7 +7860,7 @@ async function handleCompletion(c) {
7593
7860
  }
7594
7861
  const handleWithChatCompletions = async (params) => {
7595
7862
  const { c, openAIPayload, subagentMarker, sessionId, selectedModel, instr, compactType } = params;
7596
- debugJson(logger$3, "Translated OpenAI request payload:", openAIPayload);
7863
+ debugJson(logger$4, "Translated OpenAI request payload:", openAIPayload);
7597
7864
  const ctx = toAccountContext(instr.account);
7598
7865
  const effectiveInitiator = resolveEffectiveInitiator(getChatInitiator(openAIPayload.messages), {
7599
7866
  isCompact: compactType !== 0,
@@ -7624,9 +7891,9 @@ const handleWithChatCompletions = async (params) => {
7624
7891
  response,
7625
7892
  instr
7626
7893
  });
7627
- logger$3.debug("Streaming response from Copilot");
7894
+ logger$4.debug("Streaming response from Copilot");
7628
7895
  const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
7629
- const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$3) : void 0;
7896
+ const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$4) : void 0;
7630
7897
  const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
7631
7898
  promptCacheKey: instr.promptCacheKey,
7632
7899
  safetyIdentifier: instr.safetyIdentifier,
@@ -7648,7 +7915,7 @@ const handleWithResponsesApi = async (params) => {
7648
7915
  });
7649
7916
  applyResponsesApiContextManagement(responsesPayload, selectedModel.capabilities.limits.max_prompt_tokens);
7650
7917
  compactInputByLatestCompaction(responsesPayload);
7651
- debugJson(logger$3, "Translated Responses payload:", responsesPayload);
7918
+ debugJson(logger$4, "Translated Responses payload:", responsesPayload);
7652
7919
  const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
7653
7920
  const transport = getResponsesTransportForModel(selectedModel, { compactType }) ?? "http";
7654
7921
  const effectiveInitiator = resolveEffectiveInitiator(initiator, {
@@ -7679,9 +7946,9 @@ const handleWithResponsesApi = async (params) => {
7679
7946
  });
7680
7947
  }
7681
7948
  if (responsesPayload.stream && isAsyncIterable(response)) {
7682
- logger$3.debug("Streaming response from Copilot (Responses API)");
7949
+ logger$4.debug("Streaming response from Copilot (Responses API)");
7683
7950
  const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
7684
- const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$3) : void 0;
7951
+ const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$4) : void 0;
7685
7952
  const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
7686
7953
  promptCacheKey: instr.promptCacheKey,
7687
7954
  safetyIdentifier: instr.safetyIdentifier,
@@ -7779,9 +8046,9 @@ async function handleChatCompletionsNonStreaming(params) {
7779
8046
  let upstreamErrorMessageRaw;
7780
8047
  const finishedAtMs = Date.now();
7781
8048
  try {
7782
- logger$3.debug("Non-streaming response from Copilot:", JSON.stringify(response));
8049
+ logger$4.debug("Non-streaming response from Copilot:", JSON.stringify(response));
7783
8050
  const anthropicResponse = translateToAnthropic(response);
7784
- debugJson(logger$3, "Translated Anthropic response:", anthropicResponse);
8051
+ debugJson(logger$4, "Translated Anthropic response:", anthropicResponse);
7785
8052
  return c.json(anthropicResponse);
7786
8053
  } catch (error) {
7787
8054
  const details = await extractErrorObservability(error);
@@ -7832,7 +8099,7 @@ async function streamChatCompletionsAndLog(params) {
7832
8099
  try {
7833
8100
  for await (const rawEvent of response) {
7834
8101
  if (ttfbMs === void 0) ttfbMs = Date.now() - instr.startedAtMs;
7835
- logger$3.debug("Copilot raw stream event:", JSON.stringify(rawEvent));
8102
+ logger$4.debug("Copilot raw stream event:", JSON.stringify(rawEvent));
7836
8103
  const { data: rawData } = rawEvent;
7837
8104
  const data = typeof rawData === "string" ? rawData : await rawData;
7838
8105
  if (data === "[DONE]") break;
@@ -7841,7 +8108,7 @@ async function streamChatCompletionsAndLog(params) {
7841
8108
  if (chunk.usage) lastUsage = normalizeChatCompletionsUsage(chunk.usage);
7842
8109
  const events = translateChunkToAnthropicEvents(chunk, streamState);
7843
8110
  for (const event of events) {
7844
- logger$3.debug("Translated Anthropic event:", JSON.stringify(event));
8111
+ logger$4.debug("Translated Anthropic event:", JSON.stringify(event));
7845
8112
  await stream.writeSSE({
7846
8113
  event: event.type,
7847
8114
  data: JSON.stringify(event)
@@ -7854,7 +8121,7 @@ async function streamChatCompletionsAndLog(params) {
7854
8121
  errorStatus = details.errorStatus;
7855
8122
  errorMessage = details.errorMessage;
7856
8123
  upstreamErrorMessageRaw = details.upstreamErrorMessageRaw;
7857
- logger$3.warn("Streaming error:", error);
8124
+ logger$4.warn("Streaming error:", error);
7858
8125
  if (shouldMarkAccountFailed(details)) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
7859
8126
  await writeAnthropicStreamError(stream, getUserVisibleErrorMessage(details));
7860
8127
  } finally {
@@ -7915,9 +8182,9 @@ async function handleResponsesNonStreaming(params) {
7915
8182
  usage = extractResponsesUsageFromResult(result);
7916
8183
  const responseOwnerKeys = extractResponsesResultOwnerKeys(result);
7917
8184
  instr.responsesItemOwnerRecordedKeys = responseOwnerKeys;
7918
- logger$3.debug("Non-streaming Responses result:", JSON.stringify(result).slice(-400));
8185
+ logger$4.debug("Non-streaming Responses result:", JSON.stringify(result).slice(-400));
7919
8186
  const anthropicResponse = translateResponsesResultToAnthropic(result);
7920
- debugJson(logger$3, "Translated Anthropic response:", anthropicResponse);
8187
+ debugJson(logger$4, "Translated Anthropic response:", anthropicResponse);
7921
8188
  const response = c.json(anthropicResponse);
7922
8189
  if (result.status === "completed") accountsManager.recordResponsesItemOwnership(responseOwnerKeys, instr.account.id);
7923
8190
  return response;
@@ -7951,7 +8218,7 @@ async function handleResponsesNonStreaming(params) {
7951
8218
  async function ensureResponsesStreamCompleted(params) {
7952
8219
  const { stream, streamState, setStreamError } = params;
7953
8220
  if (streamState.messageCompleted) return;
7954
- logger$3.warn("Responses stream ended without completion; sending error event");
8221
+ logger$4.warn("Responses stream ended without completion; sending error event");
7955
8222
  const msg = "Responses stream ended without completion";
7956
8223
  const errorEvent = buildErrorEvent(msg);
7957
8224
  setStreamError("StreamIncomplete", msg);
@@ -7968,7 +8235,7 @@ async function writeAnthropicStreamError(stream, message) {
7968
8235
  data: JSON.stringify(errorEvent)
7969
8236
  });
7970
8237
  } catch (streamError) {
7971
- logger$3.warn("Failed to write Anthropic stream error event:", streamError);
8238
+ logger$4.warn("Failed to write Anthropic stream error event:", streamError);
7972
8239
  }
7973
8240
  }
7974
8241
  function collectResponsesStreamOwnerKeys(event, responseOwnerKeys) {
@@ -8011,7 +8278,7 @@ function getResponsesStreamEventError(event) {
8011
8278
  async function writeTranslatedAnthropicStreamEvents(stream, events) {
8012
8279
  for (const event of events) {
8013
8280
  const eventData = JSON.stringify(event);
8014
- logger$3.debug("Translated Anthropic event:", eventData);
8281
+ logger$4.debug("Translated Anthropic event:", eventData);
8015
8282
  await stream.writeSSE({
8016
8283
  event: event.type,
8017
8284
  data: eventData
@@ -8040,7 +8307,7 @@ async function streamResponsesAndLog$1(params) {
8040
8307
  }
8041
8308
  const data = chunk.data;
8042
8309
  if (!data) continue;
8043
- logger$3.debug("Responses raw stream event:", data);
8310
+ logger$4.debug("Responses raw stream event:", data);
8044
8311
  const parsed = JSON.parse(data);
8045
8312
  const streamEventError = getResponsesStreamEventError(parsed);
8046
8313
  if (streamEventError) {
@@ -8054,7 +8321,7 @@ async function streamResponsesAndLog$1(params) {
8054
8321
  if (u.usageJson) lastUsage = u;
8055
8322
  await writeTranslatedAnthropicStreamEvents(stream, translateResponsesStreamEvent(parsed, streamState));
8056
8323
  if (streamState.messageCompleted) {
8057
- logger$3.debug("Message completed, ending stream");
8324
+ logger$4.debug("Message completed, ending stream");
8058
8325
  break;
8059
8326
  }
8060
8327
  }
@@ -8073,7 +8340,7 @@ async function streamResponsesAndLog$1(params) {
8073
8340
  errorStatus = details.errorStatus;
8074
8341
  errorMessage = details.errorMessage;
8075
8342
  upstreamErrorMessageRaw = details.upstreamErrorMessageRaw;
8076
- logger$3.warn("Streaming error:", error);
8343
+ logger$4.warn("Streaming error:", error);
8077
8344
  invalidateAffinityOnOwnershipMismatch(details.ownershipMismatch, instr);
8078
8345
  if (shouldMarkAccountFailed(details)) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
8079
8346
  await writeAnthropicStreamError(stream, getUserVisibleErrorMessage(details));
@@ -8128,7 +8395,7 @@ async function handleMessagesNonStreaming(params) {
8128
8395
  let upstreamErrorMessageRaw;
8129
8396
  const finishedAtMs = Date.now();
8130
8397
  try {
8131
- logger$3.debug("Non-streaming Messages result:", JSON.stringify(response).slice(-400));
8398
+ logger$4.debug("Non-streaming Messages result:", JSON.stringify(response).slice(-400));
8132
8399
  return c.json(response);
8133
8400
  } catch (error) {
8134
8401
  const details = await extractErrorObservability(error);
@@ -8165,7 +8432,7 @@ const parseMessagesStreamUsage = (data) => {
8165
8432
  if (parsed.type !== "message_delta" || !parsed.usage) return null;
8166
8433
  return normalizeMessagesUsage(parsed.usage);
8167
8434
  } catch (error) {
8168
- logger$3.warn("Failed to parse messages stream event", error);
8435
+ logger$4.warn("Failed to parse messages stream event", error);
8169
8436
  throw new Error("Failed to parse messages stream event", { cause: error });
8170
8437
  }
8171
8438
  };
@@ -8183,7 +8450,7 @@ async function streamMessagesAndLog(params) {
8183
8450
  const eventNameRaw = rawEvent.event;
8184
8451
  const eventName = typeof eventNameRaw === "string" && eventNameRaw.length > 0 ? eventNameRaw : "message";
8185
8452
  const data = rawEvent.data ?? "";
8186
- logger$3.debug("Messages raw stream event:", data);
8453
+ logger$4.debug("Messages raw stream event:", data);
8187
8454
  const usage = parseMessagesStreamUsage(data);
8188
8455
  if (usage) lastUsage = usage;
8189
8456
  await stream.writeSSE({
@@ -8197,7 +8464,7 @@ async function streamMessagesAndLog(params) {
8197
8464
  errorStatus = details.errorStatus;
8198
8465
  errorMessage = details.errorMessage;
8199
8466
  upstreamErrorMessageRaw = details.upstreamErrorMessageRaw;
8200
- logger$3.warn("Streaming error:", error);
8467
+ logger$4.warn("Streaming error:", error);
8201
8468
  if (shouldMarkAccountFailed(details)) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
8202
8469
  await writeAnthropicStreamError(stream, getUserVisibleErrorMessage(details));
8203
8470
  } finally {
@@ -8223,7 +8490,7 @@ async function streamMessagesAndLog(params) {
8223
8490
  const handleWithMessagesApi = async (params) => {
8224
8491
  const { c, anthropicPayload, anthropicBetaHeader, subagentMarker, sessionId, instr, selectedModel, compactType } = params;
8225
8492
  prepareMessagesApiPayload(anthropicPayload, selectedModel);
8226
- debugJson(logger$3, "Translated Messages payload:", anthropicPayload);
8493
+ debugJson(logger$4, "Translated Messages payload:", anthropicPayload);
8227
8494
  const ctx = toAccountContext(instr.account);
8228
8495
  const effectiveInitiator = resolveEffectiveInitiator(getMessagesInitiator(anthropicPayload), {
8229
8496
  isCompact: compactType !== 0,
@@ -8251,7 +8518,7 @@ const handleWithMessagesApi = async (params) => {
8251
8518
  });
8252
8519
  }
8253
8520
  if (isAsyncIterable(response)) {
8254
- logger$3.debug("Streaming response from Copilot (Messages API)");
8521
+ logger$4.debug("Streaming response from Copilot (Messages API)");
8255
8522
  return streamSSE(c, (stream) => streamMessagesAndLog({
8256
8523
  stream,
8257
8524
  response,
@@ -8416,7 +8683,7 @@ function getModels() {
8416
8683
  }
8417
8684
  //#endregion
8418
8685
  //#region src/routes/provider/models/route.ts
8419
- const logger$2 = createHandlerLogger("provider-models-handler");
8686
+ const logger$3 = createHandlerLogger("provider-models-handler");
8420
8687
  const getProviderFetch = (c) => c.get("providerFetch") ?? fetch;
8421
8688
  const resolveProviderConfig = (c, provider) => {
8422
8689
  return (c.get("providerConfigResolver") ?? getProviderConfig)(provider);
@@ -8439,13 +8706,13 @@ providerModelRoutes.get("/", async (c) => {
8439
8706
  });
8440
8707
  }
8441
8708
  const upstreamResponse = await forwardProviderModels(providerConfig, c.req.raw.headers, getProviderFetch(c));
8442
- logger$2.debug("provider.models.response", {
8709
+ logger$3.debug("provider.models.response", {
8443
8710
  provider,
8444
8711
  statusCode: upstreamResponse.status
8445
8712
  });
8446
8713
  return createProviderProxyResponse(upstreamResponse);
8447
8714
  } catch (error) {
8448
- logger$2.error("provider.models.error", {
8715
+ logger$3.error("provider.models.error", {
8449
8716
  provider,
8450
8717
  error
8451
8718
  });
@@ -8453,6 +8720,141 @@ providerModelRoutes.get("/", async (c) => {
8453
8720
  }
8454
8721
  });
8455
8722
  //#endregion
8723
+ //#region src/lib/codex-rate-limit.ts
8724
+ const codexRateLimitScopes = ["primary", "secondary"];
8725
+ const formatCodexRateLimitResetAt = (resetAt) => {
8726
+ const date = /* @__PURE__ */ new Date(resetAt * 1e3);
8727
+ return Number.isNaN(date.getTime()) ? String(resetAt) : date.toLocaleString();
8728
+ };
8729
+ const logCodexRateLimitsEvent = (event) => {
8730
+ if (!event || typeof event !== "object") return;
8731
+ const eventRecord = event;
8732
+ if (eventRecord.type !== "codex.rate_limits") return;
8733
+ const rateLimits = eventRecord.rate_limits;
8734
+ if (!rateLimits || typeof rateLimits !== "object") return;
8735
+ const planType = typeof eventRecord.plan_type === "string" ? eventRecord.plan_type : null;
8736
+ const rateLimitRecord = rateLimits;
8737
+ const allowed = typeof rateLimitRecord.allowed === "boolean" ? rateLimitRecord.allowed : null;
8738
+ const limitReached = typeof rateLimitRecord.limit_reached === "boolean" ? rateLimitRecord.limit_reached : null;
8739
+ for (const scope of codexRateLimitScopes) {
8740
+ const window = rateLimitRecord[scope];
8741
+ if (!isCodexRateLimitWindow(window)) continue;
8742
+ const summary = [];
8743
+ if (allowed !== null) summary.push(`allowed=${allowed}`);
8744
+ if (limitReached !== null) summary.push(`limit_reached=${limitReached}`);
8745
+ summary.push(`used=${window.used_percent}%`, `reset_at=${formatCodexRateLimitResetAt(window.reset_at)}`);
8746
+ const label = planType ? `Codex ${scope} rate limit (${planType})` : `Codex ${scope} rate limit`;
8747
+ consola.log(`${label}: ${summary.join(", ")}`);
8748
+ }
8749
+ };
8750
+ const isCodexRateLimitWindow = (value) => {
8751
+ if (!value || typeof value !== "object") return false;
8752
+ const record = value;
8753
+ return typeof record.reset_after_seconds === "number" && typeof record.reset_at === "number" && typeof record.used_percent === "number" && typeof record.window_minutes === "number";
8754
+ };
8755
+ //#endregion
8756
+ //#region src/routes/provider/responses/handler.ts
8757
+ const logger$2 = createHandlerLogger("provider-responses-handler");
8758
+ async function handleProviderResponsesForProvider(c, options) {
8759
+ const { payload, provider } = options;
8760
+ debugJson(logger$2, "Responses request payload:", {
8761
+ payload,
8762
+ provider
8763
+ });
8764
+ const providerConfig = await resolveProviderConfig$3(provider);
8765
+ if (providerConfig?.type !== "openai-responses") return c.json({ error: {
8766
+ message: `Provider '${provider}' does not support the /v1/responses endpoint`,
8767
+ type: "invalid_request_error"
8768
+ } }, 400);
8769
+ applyResponsesApiContextManagement(payload, (providerConfig.name === "codex" ? getModels().data.find((model) => model.id === payload.model) : void 0)?.capabilities.limits.max_prompt_tokens ?? 0, .8);
8770
+ const contextManagement = payload.context_management;
8771
+ debugJson(logger$2, "Translated Responses request payload:", {
8772
+ contextManagement,
8773
+ provider
8774
+ });
8775
+ compactInputByLatestCompaction(payload);
8776
+ if (providerConfig.name === "codex") {
8777
+ const upstreamResponse = await forwardCodexResponses(payload, c.req.raw.headers, providerConfig.baseUrl);
8778
+ const recordUsage = createProviderResponsesUsageRecorder(payload, provider);
8779
+ if (payload.stream && isResponsesStream(upstreamResponse)) return streamProviderResponses(c, upstreamResponse, {
8780
+ normalizeCodex: true,
8781
+ provider,
8782
+ recordUsage
8783
+ });
8784
+ const responseBody = upstreamResponse;
8785
+ recordUsage(normalizeResponsesUsage(responseBody.usage));
8786
+ return c.json(responseBody);
8787
+ }
8788
+ const upstreamResponse = await forwardProviderResponses(providerConfig, payload, c.req.raw.headers);
8789
+ if (!upstreamResponse.ok) throw new HTTPError(`Failed to create ${provider} responses`, upstreamResponse);
8790
+ const recordUsage = createProviderResponsesUsageRecorder(payload, provider);
8791
+ if (payload.stream) return streamProviderResponses(c, getResponsesEvents(upstreamResponse), {
8792
+ normalizeCodex: false,
8793
+ provider,
8794
+ recordUsage
8795
+ });
8796
+ recordUsage(normalizeResponsesUsage((await upstreamResponse.clone().json()).usage));
8797
+ return createProviderProxyResponse(upstreamResponse);
8798
+ }
8799
+ const createProviderResponsesUsageRecorder = (_payload, _provider) => {
8800
+ return (_usage) => {};
8801
+ };
8802
+ const streamProviderResponses = (c, upstreamResponse, options) => {
8803
+ return streamSSE(c, async (stream) => {
8804
+ let usage = {};
8805
+ try {
8806
+ for await (const chunk of upstreamResponse) {
8807
+ debugJson(logger$2, "Responses stream chunk:", chunk);
8808
+ let responseChunk = chunk;
8809
+ let event = null;
8810
+ if (chunk.data && chunk.data !== "[DONE]") {
8811
+ event = parseProviderResponsesStreamEvent(chunk.data, {
8812
+ normalizeCodex: options.normalizeCodex,
8813
+ provider: options.provider
8814
+ });
8815
+ if (event && options.normalizeCodex) responseChunk = {
8816
+ ...chunk,
8817
+ data: JSON.stringify(event),
8818
+ event: event.type
8819
+ };
8820
+ }
8821
+ if (event) {
8822
+ const nextUsage = getResponsesStreamEventUsage(event);
8823
+ if (nextUsage) usage = nextUsage;
8824
+ }
8825
+ await stream.writeSSE({
8826
+ data: responseChunk.data ?? "",
8827
+ event: responseChunk.event
8828
+ });
8829
+ }
8830
+ } finally {
8831
+ options.recordUsage(usage);
8832
+ }
8833
+ });
8834
+ };
8835
+ const parseProviderResponsesStreamEvent = (data, options) => {
8836
+ try {
8837
+ const parsed = JSON.parse(data);
8838
+ if (options.normalizeCodex) logCodexRateLimitsEvent(parsed);
8839
+ return parsed;
8840
+ } catch (error) {
8841
+ logger$2.error("provider.responses.parse_chunk_error", {
8842
+ provider: options.provider,
8843
+ data,
8844
+ error
8845
+ });
8846
+ return null;
8847
+ }
8848
+ };
8849
+ const getResponsesStreamEventUsage = (event) => {
8850
+ if (event.type === "response.completed" || event.type === "response.failed" || event.type === "response.incomplete") return normalizeResponsesUsage(event.response.usage);
8851
+ return null;
8852
+ };
8853
+ const getResponsesEvents = (response) => events(response);
8854
+ const isResponsesStream = (value) => {
8855
+ return Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
8856
+ };
8857
+ //#endregion
8456
8858
  //#region src/routes/responses/stream-id-sync.ts
8457
8859
  const createStreamIdTracker = () => ({ outputItems: /* @__PURE__ */ new Map() });
8458
8860
  const fixStreamIds = (data, event, tracker) => {
@@ -8493,16 +8895,31 @@ const handleItemId = (parsed, tracker) => {
8493
8895
  const logger$1 = createHandlerLogger("responses-handler");
8494
8896
  const RESPONSES_ENDPOINT = "/responses";
8495
8897
  const handleResponses = async (c) => {
8898
+ const payload = await c.req.json();
8899
+ debugJson(logger$1, "Responses request payload:", payload);
8900
+ const requestedModel = payload.model;
8901
+ payload.model = resolveMappedModel(payload.model);
8902
+ if (payload.model !== requestedModel) consola.debug(`Resolved model mapping: ${requestedModel} -> ${payload.model}`);
8903
+ const providerModelAlias = parseProviderModelAlias(payload.model);
8904
+ if (providerModelAlias) {
8905
+ payload.model = providerModelAlias.model;
8906
+ return await handleProviderResponsesForProvider(c, {
8907
+ payload,
8908
+ provider: providerModelAlias.provider
8909
+ });
8910
+ }
8911
+ const subagentMarker = getCodexResponsesSubagentMarker(c);
8912
+ if (subagentMarker) debugJson(logger$1, "Detected Codex subagent headers:", subagentMarker);
8913
+ const incomingSessionId = subagentMarker ? getIncomingResponsesSessionId(c) : void 0;
8496
8914
  await checkRateLimit(state);
8497
8915
  const store = getRequestHistoryStore();
8498
8916
  const request = buildRequestContext(c);
8499
- const payload = await c.req.json();
8500
8917
  const clientModel = payload.model;
8501
- debugJson(logger$1, "Responses request payload:", payload);
8502
8918
  if (!isResponsesApiWebSearchEnabled()) removeWebSearchTool(payload);
8503
8919
  compactInputByLatestCompaction(payload);
8504
8920
  const streamRequested = Boolean(payload.stream);
8505
- const { initiator: initialInitiator } = getResponsesRequestOptions(payload);
8921
+ const { initiator: inferredInitiator } = getResponsesRequestOptions(payload);
8922
+ const initialInitiator = subagentMarker ? "agent" : inferredInitiator;
8506
8923
  const userId = payload.metadata?.user_id;
8507
8924
  const requestBodyPromptCacheKey = typeof payload.prompt_cache_key === "string" ? payload.prompt_cache_key : null;
8508
8925
  const { safetyIdentifier, sessionId: metadataSessionId } = parseUserIdMetadata(userId);
@@ -8524,8 +8941,8 @@ const handleResponses = async (c) => {
8524
8941
  message: "This model is only available via an alias. Please use the alias model name."
8525
8942
  });
8526
8943
  }
8527
- const upstreamRequestId = generateRequestIdFromPayload({ messages: payload.input }, normalizedPromptCacheKey);
8528
8944
  const headerSessionId = c.req.header("x-session-id") ?? null;
8945
+ const upstreamRequestId = generateRequestIdFromPayload({ messages: payload.input }, incomingSessionId ?? normalizedPromptCacheKey);
8529
8946
  const affinityKey = resolveAffinityKey({
8530
8947
  promptCacheKey: requestBodyPromptCacheKey,
8531
8948
  metadataSessionId,
@@ -8556,16 +8973,19 @@ const handleResponses = async (c) => {
8556
8973
  model: selectedModel.id
8557
8974
  };
8558
8975
  removeUnsupportedTools(upstreamPayload);
8976
+ const sanitizedImageCount = sanitizeOversizedInputImages(upstreamPayload, selectedModel.capabilities.limits.vision?.max_prompt_image_size);
8977
+ if (sanitizedImageCount > 0) logger$1.warn(`Omitted ${sanitizedImageCount} oversized input image(s) before forwarding to Copilot Responses`);
8559
8978
  applyResponsesApiContextManagement(upstreamPayload, selectedModel.capabilities.limits.max_prompt_tokens);
8560
8979
  compactInputByLatestCompaction(upstreamPayload);
8561
8980
  const premiumRemainingBefore = account.premiumRemaining;
8562
8981
  const premiumUnlimitedBefore = account.unlimited;
8563
8982
  const transport = getResponsesTransportForModel(selectedModel) ?? "http";
8564
- const { vision, initiator } = getResponsesRequestOptions(upstreamPayload);
8983
+ const { vision, initiator: inferredUpstreamInitiator } = getResponsesRequestOptions(upstreamPayload);
8984
+ const initiator = subagentMarker ? "agent" : inferredUpstreamInitiator;
8565
8985
  request.initiator = initiator;
8566
8986
  if (state.manualApprove) await awaitApproval();
8567
8987
  const accountCtx = toAccountContext(account);
8568
- const upstreamSessionId = getUUID(normalizedPromptCacheKey ?? headerSessionId ?? upstreamRequestId);
8988
+ const upstreamSessionId = getUUID(incomingSessionId ?? normalizedPromptCacheKey ?? headerSessionId ?? upstreamRequestId);
8569
8989
  request.upstreamRequestId = upstreamRequestId;
8570
8990
  request.upstreamSessionId = upstreamSessionId;
8571
8991
  const bridgeId = c.req.header("x-responses-bridge-id") ?? void 0;
@@ -8579,6 +8999,7 @@ const handleResponses = async (c) => {
8579
8999
  accountCtx,
8580
9000
  vision,
8581
9001
  initiator,
9002
+ subagentMarker,
8582
9003
  premiumRemainingBefore,
8583
9004
  premiumUnlimitedBefore,
8584
9005
  transport,
@@ -8594,6 +9015,7 @@ const handleResponses = async (c) => {
8594
9015
  accountCtx,
8595
9016
  vision,
8596
9017
  initiator,
9018
+ subagentMarker,
8597
9019
  premiumRemainingBefore,
8598
9020
  premiumUnlimitedBefore,
8599
9021
  transport,
@@ -8705,12 +9127,13 @@ function extractUsageFromChunkData(data) {
8705
9127
  }
8706
9128
  }
8707
9129
  async function handleStreamingResponses(params) {
8708
- const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, premiumRemainingBefore, premiumUnlimitedBefore, transport, bridgeId } = params;
9130
+ const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, subagentMarker, premiumRemainingBefore, premiumUnlimitedBefore, transport, bridgeId } = params;
8709
9131
  let response;
8710
9132
  try {
8711
9133
  response = await createResponses(payload, {
8712
9134
  vision,
8713
9135
  initiator,
9136
+ subagentMarker,
8714
9137
  upstreamRequestId: request.upstreamRequestId,
8715
9138
  sessionId: request.upstreamSessionId,
8716
9139
  requestId: request.requestId,
@@ -8903,7 +9326,7 @@ async function streamResponsesAndLog(params) {
8903
9326
  }
8904
9327
  }
8905
9328
  async function handleNonStreamingResponses(params) {
8906
- const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, premiumRemainingBefore, premiumUnlimitedBefore, transport, bridgeId } = params;
9329
+ const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, subagentMarker, premiumRemainingBefore, premiumUnlimitedBefore, transport, bridgeId } = params;
8907
9330
  const { account, reservation, selectedModel, endpoint, costUnits } = selection;
8908
9331
  let usage = {};
8909
9332
  let errorState = { httpStatus: 200 };
@@ -8912,6 +9335,7 @@ async function handleNonStreamingResponses(params) {
8912
9335
  const response = await createResponses(payload, {
8913
9336
  vision,
8914
9337
  initiator,
9338
+ subagentMarker,
8915
9339
  upstreamRequestId: request.upstreamRequestId,
8916
9340
  sessionId: request.upstreamSessionId,
8917
9341
  requestId: request.requestId,
@@ -8978,6 +9402,31 @@ const removeUnsupportedTools = (payload) => {
8978
9402
  });
8979
9403
  if (dropped.length > 0) logger$1.debug("Removed unsupported tools:", dropped);
8980
9404
  };
9405
+ const getTrimmedHeader = (c, name) => {
9406
+ const value = c.req.header(name)?.trim();
9407
+ return value ? value : void 0;
9408
+ };
9409
+ const getIncomingResponsesSessionId = (c) => getTrimmedHeader(c, "session-id") ?? getTrimmedHeader(c, "x-session-id");
9410
+ const codexSubagentHeaderValues = new Set([
9411
+ "collab_spawn",
9412
+ "compact",
9413
+ "memory_consolidation",
9414
+ "review"
9415
+ ]);
9416
+ const getCodexResponsesSubagentMarker = (c) => {
9417
+ const agentType = getTrimmedHeader(c, "x-openai-subagent");
9418
+ if (!agentType || !codexSubagentHeaderValues.has(agentType)) return null;
9419
+ const threadId = getTrimmedHeader(c, "thread-id");
9420
+ const rootSessionId = getIncomingResponsesSessionId(c);
9421
+ const parentThreadId = getTrimmedHeader(c, "x-codex-parent-thread-id");
9422
+ if (!threadId && !rootSessionId && !parentThreadId) return null;
9423
+ const agentId = threadId ?? parentThreadId ?? rootSessionId;
9424
+ return {
9425
+ agent_id: agentId,
9426
+ agent_type: agentType,
9427
+ session_id: threadId ?? rootSessionId ?? agentId
9428
+ };
9429
+ };
8981
9430
  //#endregion
8982
9431
  //#region src/routes/responses/route.ts
8983
9432
  const responsesRoutes = new Hono();
@@ -9079,4 +9528,4 @@ createServer();
9079
9528
  //#endregion
9080
9529
  export { createServer };
9081
9530
 
9082
- //# sourceMappingURL=server-DJ3_UGc4.js.map
9531
+ //# sourceMappingURL=server-C7pCkArb.js.map