@jeffreycao/copilot-api 2.4.1 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,25 @@
1
- import { A as isResponsesApiWebSocketEnabled, C as getClaudeTokenMultiplier, D as isAlphaSearchCodexPriorityEnabled, E as getResponsesTransportConfig, N as PATHS, O as isMessagesApiEnabled, S as getClaudeAutoModel, T as getMessageApiWebSearchModel, _ as resolveMappedModel, b as getAlphaSearchModel, d as getModelResponsesApiCompactThreshold$1, f as getReasoningEffortForModel, g as isGpt56OrAbove, h as isContextManagementEnabledForResponses, i as listEnabledProviders, k as isResponsesApiWebSearchEnabled, l as getExtraPromptForModel, m as isContextManagementEnabledForMessages, n as getRawProviderConfig, o as resolveEffectiveProviderType, p as getSmallModel, s as resolveProviderAuthType, t as getProviderConfig, u as getModelMappings, v as setModelMappings, x as getAnthropicApiKey } from "./config-DVWu2hKk.js";
2
- import { B as fetchResponsesWithLifecycle, C as compactAutoContinuePromptStarts, D as compactTextOnlyGuard, E as compactSystemPromptStarts, F as forwardCodexResponses, G as createWebSocketUrl, H as encodePoolKeyPart, I as generateTraceId, J as forwardError, K as state, L as requestContext, N as CODEX_API_BASE_URL, O as createAuthMiddleware, P as buildCodexRequestHeaders, R as resolveTraceId$1, U as isTerminalResponsesStreamChunk, V as createResponsesSafeStream, W as createPooledWebSocketStream, b as prepareInteractionHeaders, c as getUUID, d as isResponsesStream, f as parseUserIdMetadata, g as copilotHeaders, h as copilotBaseUrl, k as getConfiguredAdminApiKeys, l as isAsyncIterable, o as generateRequestIdFromPayload, p as getCopilotUsage, q as HTTPError, r as setupCodexToken, s as getRootSessionId, u as isNullish, v as copilotWebSocketHeaders, w as compactMessageSections, x as prepareMessageProxyHeaders, y as prepareForCompact, z as createResponsesHttpEventStream } from "./token-D0GGk3E8.js";
1
+ import { A as isResponsesApiWebSocketEnabled, C as getClaudeTokenMultiplier, D as isAlphaSearchCodexPriorityEnabled, E as getResponsesTransportConfig, N as PATHS, O as isMessagesApiEnabled, S as getClaudeAutoModel, T as getMessageApiWebSearchModel, _ as resolveMappedModel, b as getAlphaSearchModel, d as getModelResponsesApiCompactThreshold$1, f as getReasoningEffortForModel, g as isGpt56OrAbove, h as isContextManagementEnabledForResponses, i as listEnabledProviders, k as isResponsesApiWebSearchEnabled, l as getExtraPromptForModel, m as isContextManagementEnabledForMessages, n as getRawProviderConfig, o as resolveEffectiveProviderType, p as getSmallModel, s as resolveProviderAuthType, t as getProviderConfig, u as getModelMappings, v as setModelMappings, x as getAnthropicApiKey } from "./config-Cb0atQ6i.js";
2
+ import { B as fetchResponsesWithLifecycle, C as compactAutoContinuePromptStarts, D as compactTextOnlyGuard, E as compactSystemPromptStarts, F as forwardCodexResponses, G as createWebSocketUrl, H as encodePoolKeyPart, I as generateTraceId, J as forwardError, K as state, L as requestContext, N as CODEX_API_BASE_URL, O as createAuthMiddleware, P as buildCodexRequestHeaders, R as resolveTraceId$1, U as isTerminalResponsesStreamChunk, V as createResponsesSafeStream, W as createPooledWebSocketStream, b as prepareInteractionHeaders, c as getUUID, d as isResponsesStream, f as parseUserIdMetadata, g as copilotHeaders, h as copilotBaseUrl, k as getConfiguredAdminApiKeys, l as isAsyncIterable, o as generateRequestIdFromPayload, p as getCopilotUsage, q as HTTPError, r as setupCodexToken, s as getRootSessionId, u as isNullish, v as copilotWebSocketHeaders, w as compactMessageSections, x as prepareMessageProxyHeaders, y as prepareForCompact, z as createResponsesHttpEventStream } from "./token-DYqRXNhu.js";
3
3
  import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, d as shouldEnableResponsesToolSearch, i as isBridgeToolSearchName, l as resolveBridgeToolSearchName, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, t as BRIDGE_TOOL_SEARCH_NAME, u as selectDeferredToolsByNames } from "./tool-search-Ds1vbmGG.js";
4
- import { i as toClientModelId, r as normalizeSdkModelId, t as findEndpointModel } from "./models-DKNAPa_j.js";
4
+ import { i as toClientModelId, r as normalizeSdkModelId, t as findEndpointModel } from "./models-DvNveb2V.js";
5
5
  import consola from "consola";
6
6
  import { createHash } from "node:crypto";
7
- import fs, { readFileSync } from "node:fs";
8
- import path from "node:path";
9
- import fs$1 from "node:fs/promises";
7
+ import fs, { createWriteStream, readFileSync, rmSync } from "node:fs";
8
+ import path, { join } from "node:path";
9
+ import fs$1, { mkdtemp, rm } from "node:fs/promises";
10
+ import { tmpdir } from "node:os";
10
11
  import { fetch as fetch$1, getGlobalDispatcher } from "undici";
11
12
  import { events } from "fetch-event-stream";
12
13
  import { z } from "zod";
13
14
  import { Hono } from "hono";
14
15
  import { cors } from "hono/cors";
15
16
  import { logger } from "hono/logger";
16
- import { decompress } from "fzstd";
17
17
  import util from "node:util";
18
18
  import { streamSSE } from "hono/streaming";
19
+ import { Busboy } from "@fastify/busboy";
20
+ import { Readable, Transform } from "node:stream";
21
+ import { pipeline } from "node:stream/promises";
22
+ import { decompress } from "fzstd";
19
23
  //#region src/lib/trace.ts
20
24
  const traceIdMiddleware = async (c, next) => {
21
25
  const traceId = resolveTraceId$1(c.req.header("x-trace-id"));
@@ -32,58 +36,6 @@ const traceIdMiddleware = async (c, next) => {
32
36
  });
33
37
  };
34
38
  //#endregion
35
- //#region src/lib/zstd-request.ts
36
- const ZSTD_CONTENT_ENCODING = "zstd";
37
- const INVALID_BODY_STATUS = 400;
38
- let nodeZlibPromise = null;
39
- const zstdDecompressionMiddleware = async (c, next) => {
40
- if (c.req.header("content-encoding")?.trim().toLowerCase() !== ZSTD_CONTENT_ENCODING) return next();
41
- try {
42
- const decompressedBody = await decompressZstd(new Uint8Array(await c.req.raw.arrayBuffer()));
43
- const headers = new Headers(c.req.raw.headers);
44
- headers.delete("content-encoding");
45
- headers.delete("content-length");
46
- c.req.raw = new Request(c.req.raw.url, {
47
- body: decompressedBody,
48
- headers,
49
- method: c.req.raw.method,
50
- signal: c.req.raw.signal
51
- });
52
- c.req.bodyCache = {};
53
- } catch {
54
- return c.json({ error: {
55
- message: "Failed to decompress zstd request body.",
56
- type: "invalid_request_error"
57
- } }, INVALID_BODY_STATUS);
58
- }
59
- return next();
60
- };
61
- const decompressZstd = async (input) => {
62
- const bun = getBunRuntime();
63
- if (bun?.zstdDecompress) return toUint8Array(await bun.zstdDecompress(input));
64
- const nodeZlib = await getNodeZlib();
65
- if (nodeZlib?.zstdDecompress) return new Promise((resolve, reject) => {
66
- nodeZlib.zstdDecompress?.(input, (error, result) => {
67
- if (error) {
68
- reject(error);
69
- return;
70
- }
71
- resolve(toUint8Array(result));
72
- });
73
- });
74
- return decompress(input);
75
- };
76
- const getBunRuntime = () => globalThis.Bun;
77
- const getNodeZlib = async () => {
78
- nodeZlibPromise ??= import("node:zlib").then((module) => module).catch(() => null);
79
- return nodeZlibPromise;
80
- };
81
- const toUint8Array = (data) => {
82
- if (data instanceof Uint8Array) return data;
83
- if (data instanceof ArrayBuffer) return new Uint8Array(data);
84
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
85
- };
86
- //#endregion
87
39
  //#region src/lib/process-cleanup.ts
88
40
  const cleanupHandlers = /* @__PURE__ */ new Set();
89
41
  let cleanupPromise = null;
@@ -2474,7 +2426,7 @@ async function forwardProviderImages(providerConfig, request, operation) {
2474
2426
  }
2475
2427
  //#endregion
2476
2428
  //#region src/routes/alpha-search/alpha-search-responses.ts
2477
- const logger$16 = createHandlerLogger("alpha-search-responses-handler");
2429
+ const logger$17 = createHandlerLogger("alpha-search-responses-handler");
2478
2430
  const SESSION_TTL_MS = 3600 * 1e3;
2479
2431
  const MAX_SESSIONS = 128;
2480
2432
  const MAX_URL_REFERENCES = 256;
@@ -2832,14 +2784,14 @@ function createRemoteResponsesPayload(request, model, instruction) {
2832
2784
  };
2833
2785
  }
2834
2786
  async function requestProviderSearch(c, providerConfig, payload, model, sessionId) {
2835
- debugJson(logger$16, "Alpha search provider Responses request:", {
2787
+ debugJson(logger$17, "Alpha search provider Responses request:", {
2836
2788
  payload,
2837
2789
  provider: providerConfig.name
2838
2790
  });
2839
2791
  const upstreamResponse = await forwardProviderResponses(providerConfig, payload, c.req.raw.headers, { signal: c.req.raw.signal });
2840
2792
  if (!upstreamResponse.ok) throw new HTTPError(`Failed to create ${providerConfig.name} responses for alpha search`, upstreamResponse);
2841
2793
  const result = await upstreamResponse.json();
2842
- debugJson(logger$16, "Alpha search provider Responses result:", {
2794
+ debugJson(logger$17, "Alpha search provider Responses result:", {
2843
2795
  provider: providerConfig.name,
2844
2796
  result
2845
2797
  });
@@ -2855,7 +2807,7 @@ async function requestProviderSearch(c, providerConfig, payload, model, sessionI
2855
2807
  return result;
2856
2808
  }
2857
2809
  async function requestCopilotSearch(payload, model, requestId, sessionId, signal) {
2858
- debugJson(logger$16, "Alpha search Copilot Responses request:", payload);
2810
+ debugJson(logger$17, "Alpha search Copilot Responses request:", payload);
2859
2811
  const result = await alphaSearchResponsesDependencies.createResponses(payload, {
2860
2812
  vision: false,
2861
2813
  initiator: "agent",
@@ -2864,7 +2816,7 @@ async function requestCopilotSearch(payload, model, requestId, sessionId, signal
2864
2816
  sessionId,
2865
2817
  signal
2866
2818
  });
2867
- debugJson(logger$16, "Alpha search Copilot Responses result:", result);
2819
+ debugJson(logger$17, "Alpha search Copilot Responses result:", result);
2868
2820
  alphaSearchResponsesDependencies.createUsageRecorder(model, sessionId)({
2869
2821
  ...normalizeResponsesUsage(result.usage),
2870
2822
  total_nano_aiu: normalizeOptionalToken(result.copilot_usage?.total_nano_aiu)
@@ -2979,7 +2931,7 @@ async function forwardCodexAlphaSearch(request) {
2979
2931
  }
2980
2932
  //#endregion
2981
2933
  //#region src/routes/alpha-search/route.ts
2982
- const logger$15 = createHandlerLogger("alpha-search-handler");
2934
+ const logger$16 = createHandlerLogger("alpha-search-handler");
2983
2935
  const alphaSearchRoutes = new Hono();
2984
2936
  const alphaSearchRouteDependencies = {
2985
2937
  findEndpointModel,
@@ -2999,9 +2951,9 @@ function parseDebugBody(body) {
2999
2951
  }
3000
2952
  }
3001
2953
  async function forwardCodexAlphaSearchRequest(request) {
3002
- await debugJsonAsync(logger$15, "alpha_search.codex.request", async () => ({ body: parseDebugBody(await request.clone().text()) }));
2954
+ await debugJsonAsync(logger$16, "alpha_search.codex.request", async () => ({ body: parseDebugBody(await request.clone().text()) }));
3003
2955
  const upstreamResponse = await alphaSearchRouteDependencies.forwardCodexAlphaSearch(request);
3004
- await debugJsonAsync(logger$15, "alpha_search.codex.response", async () => ({
2956
+ await debugJsonAsync(logger$16, "alpha_search.codex.response", async () => ({
3005
2957
  body: parseDebugBody(await upstreamResponse.clone().text()),
3006
2958
  statusCode: upstreamResponse.status
3007
2959
  }));
@@ -3112,7 +3064,7 @@ alphaSearchRoutes.post("/", async (c) => {
3112
3064
  try {
3113
3065
  return await handleAlphaSearchRequest(c);
3114
3066
  } catch (error) {
3115
- logger$15.error("alpha_search.error", { error });
3067
+ logger$16.error("alpha_search.error", { error });
3116
3068
  return await forwardError(c, error);
3117
3069
  }
3118
3070
  });
@@ -3240,7 +3192,7 @@ const normalizeProviderResponsesReasoningEffort = (payload, providerConfig) => {
3240
3192
  };
3241
3193
  //#endregion
3242
3194
  //#region src/routes/provider/chat-completions/handler.ts
3243
- const logger$14 = createHandlerLogger("provider-chat-completions-handler");
3195
+ const logger$15 = createHandlerLogger("provider-chat-completions-handler");
3244
3196
  async function handleProviderChatCompletionsForProvider(c, options) {
3245
3197
  const { payload, provider } = options;
3246
3198
  const providerConfig = await resolveProviderConfig(provider);
@@ -3254,13 +3206,13 @@ async function handleProviderChatCompletionsForProvider(c, options) {
3254
3206
  applyProviderStreamOptions(payload);
3255
3207
  applyDashScopePreserveThinkingDefault(payload, providerConfig);
3256
3208
  applyProviderContextCache(payload, modelConfig, providerConfig);
3257
- debugJson(logger$14, "provider.chat_completions.request", {
3209
+ debugJson(logger$15, "provider.chat_completions.request", {
3258
3210
  payload,
3259
3211
  provider
3260
3212
  });
3261
3213
  const upstreamResponse = await forwardProviderChatCompletions(providerConfig, payload, c.req.raw.headers);
3262
3214
  if (!upstreamResponse.ok) {
3263
- logger$14.error("Failed to create provider chat completions", {
3215
+ logger$15.error("Failed to create provider chat completions", {
3264
3216
  provider,
3265
3217
  statusCode: upstreamResponse.status
3266
3218
  });
@@ -3274,7 +3226,7 @@ async function handleProviderChatCompletionsForProvider(c, options) {
3274
3226
  });
3275
3227
  const responseBody = await upstreamResponse.clone().json();
3276
3228
  recordUsage(normalizeOpenAIUsage(responseBody.usage));
3277
- debugJson(logger$14, "provider.chat_completions.response", responseBody);
3229
+ debugJson(logger$15, "provider.chat_completions.response", responseBody);
3278
3230
  return createProviderProxyResponse(upstreamResponse);
3279
3231
  }
3280
3232
  const applyProviderStreamOptions = (payload) => {
@@ -3296,12 +3248,12 @@ const createProviderChatCompletionsUsageRecorder = (payload, provider, modelConf
3296
3248
  providerName: provider
3297
3249
  });
3298
3250
  const streamProviderChatCompletions = (c, upstreamResponse, options) => {
3299
- logger$14.debug("provider.chat_completions.streaming", { provider: options.provider });
3251
+ logger$15.debug("provider.chat_completions.streaming", { provider: options.provider });
3300
3252
  return streamSSE(c, async (stream) => {
3301
3253
  let usage = {};
3302
3254
  try {
3303
3255
  for await (const chunk of events(upstreamResponse)) {
3304
- debugJson(logger$14, "provider.chat_completions.stream_chunk", chunk);
3256
+ debugJson(logger$15, "provider.chat_completions.stream_chunk", chunk);
3305
3257
  if (chunk.data && chunk.data !== "[DONE]") {
3306
3258
  const parsedChunk = parseChatCompletionChunkData(chunk.data);
3307
3259
  if (parsedChunk?.usage) usage = normalizeOpenAIUsage(parsedChunk.usage);
@@ -3355,7 +3307,7 @@ const createChatCompletions = async (payload, options) => {
3355
3307
  };
3356
3308
  //#endregion
3357
3309
  //#region src/routes/chat-completions/handler.ts
3358
- const logger$13 = createHandlerLogger("chat-completions-handler");
3310
+ const logger$14 = createHandlerLogger("chat-completions-handler");
3359
3311
  async function handleCompletion$1(c) {
3360
3312
  let payload = await c.req.json();
3361
3313
  const requestedModel = payload.model;
@@ -3369,7 +3321,7 @@ async function handleCompletion$1(c) {
3369
3321
  provider: providerModelAlias.provider
3370
3322
  });
3371
3323
  }
3372
- debugJson(logger$13, "Request payload:", payload);
3324
+ debugJson(logger$14, "Request payload:", payload);
3373
3325
  const selectedModel = findEndpointModel(payload.model);
3374
3326
  payload.model = selectedModel?.id ?? payload.model;
3375
3327
  if (isNullish(payload.max_tokens) && isNullish(payload.max_completion_tokens)) {
@@ -3377,16 +3329,16 @@ async function handleCompletion$1(c) {
3377
3329
  ...payload,
3378
3330
  max_tokens: selectedModel?.capabilities.limits.max_output_tokens
3379
3331
  };
3380
- debugJson(logger$13, "Set max_tokens to:", payload.max_tokens);
3332
+ debugJson(logger$14, "Set max_tokens to:", payload.max_tokens);
3381
3333
  }
3382
3334
  if (payload.model.includes("gpt")) {
3383
3335
  if (isNullish(payload.max_completion_tokens)) payload.max_completion_tokens = payload.max_tokens;
3384
3336
  delete payload.max_tokens;
3385
3337
  }
3386
3338
  const requestId = generateRequestIdFromPayload(payload);
3387
- logger$13.debug("Generated request ID:", requestId);
3339
+ logger$14.debug("Generated request ID:", requestId);
3388
3340
  const sessionId = getUUID(requestId);
3389
- logger$13.debug("Extracted session ID:", sessionId);
3341
+ logger$14.debug("Extracted session ID:", sessionId);
3390
3342
  const recordUsage = createCopilotTokenUsageRecorder({
3391
3343
  endpoint: "chat_completions",
3392
3344
  fallbackSessionId: sessionId,
@@ -3397,18 +3349,18 @@ async function handleCompletion$1(c) {
3397
3349
  sessionId
3398
3350
  });
3399
3351
  if (isNonStreaming$1(response)) {
3400
- debugJson(logger$13, "Non-streaming response:", response);
3352
+ debugJson(logger$14, "Non-streaming response:", response);
3401
3353
  recordUsage({
3402
3354
  ...normalizeOpenAIUsage(response.usage),
3403
3355
  total_nano_aiu: normalizeOptionalToken(response.copilot_usage?.total_nano_aiu)
3404
3356
  });
3405
3357
  return c.json(response);
3406
3358
  }
3407
- logger$13.debug("Streaming response");
3359
+ logger$14.debug("Streaming response");
3408
3360
  return streamSSE(c, async (stream) => {
3409
3361
  let usage = {};
3410
3362
  for await (const chunk of response) {
3411
- debugJson(logger$13, "Streaming chunk:", chunk);
3363
+ debugJson(logger$14, "Streaming chunk:", chunk);
3412
3364
  const parsedChunk = parseChatCompletionChunk(chunk);
3413
3365
  if (parsedChunk?.usage || parsedChunk?.copilot_usage) usage = {
3414
3366
  ...normalizeOpenAIUsage(parsedChunk.usage),
@@ -3497,6 +3449,32 @@ embeddingRoutes.post("/", async (c) => {
3497
3449
  }
3498
3450
  });
3499
3451
  //#endregion
3452
+ //#region src/routes/images/forward-provider-images.ts
3453
+ /**
3454
+ * Forwards an images request to a configured provider with debug logging.
3455
+ * Shared by the top-level images routes (model mapping) and the
3456
+ * provider-scoped images routes so both log and proxy identically.
3457
+ */
3458
+ async function forwardProviderImagesWithLogging(providerConfig, request, operation, { logger, provider }) {
3459
+ if (operation === "generations") await debugJsonAsync(logger, `provider.images.${operation}.request`, async () => ({
3460
+ body: await request.clone().text(),
3461
+ provider
3462
+ }));
3463
+ else debugJson(logger, `provider.images.${operation}.request`, {
3464
+ contentType: request.headers.get("content-type"),
3465
+ contentLength: request.headers.get("content-length"),
3466
+ provider
3467
+ });
3468
+ const upstreamResponse = await forwardProviderImages(providerConfig, request, operation);
3469
+ debugJson(logger, `provider.images.${operation}.response`, {
3470
+ contentType: upstreamResponse.headers.get("content-type"),
3471
+ contentLength: upstreamResponse.headers.get("content-length"),
3472
+ provider,
3473
+ statusCode: upstreamResponse.status
3474
+ });
3475
+ return createProviderProxyResponse(upstreamResponse);
3476
+ }
3477
+ //#endregion
3500
3478
  //#region src/services/codex/images.ts
3501
3479
  const CODEX_IMAGES_TIMEOUT_MS = 900 * 1e3;
3502
3480
  const codexImagesDispatcher = createTimeoutDispatcher(CODEX_IMAGES_TIMEOUT_MS);
@@ -3524,41 +3502,433 @@ async function forwardCodexImages(request, operation) {
3524
3502
  });
3525
3503
  }
3526
3504
  //#endregion
3527
- //#region src/routes/images/route.ts
3528
- const logger$12 = createHandlerLogger("images-handler");
3529
- const imageRoutes = new Hono();
3530
- const imageRouteDependencies = { debugJsonAsync };
3531
- function getContentMetadata$1(headers) {
3505
+ //#region src/routes/images/shared.ts
3506
+ const logger$13 = createHandlerLogger("images-handler");
3507
+ const imageRouteDependencies = {
3508
+ debugJsonAsync,
3509
+ resolveMappedModel,
3510
+ resolveProviderConfig
3511
+ };
3512
+ function getContentMetadata(headers) {
3532
3513
  return {
3533
3514
  contentType: headers.get("content-type"),
3534
3515
  contentLength: headers.get("content-length")
3535
3516
  };
3536
3517
  }
3537
3518
  /**
3538
- * Handles Codex images proxying. Pass `resolvedProviderConfig` when the
3539
- * caller already resolved the codex provider to avoid a second resolve.
3519
+ * Snapshots request headers before the body is consumed: Bun drops
3520
+ * auto-generated body headers (like the multipart boundary) afterwards.
3540
3521
  */
3541
- async function handleCodexImages(c, operation, resolvedProviderConfig) {
3522
+ function snapshotRequestHeaders(request) {
3523
+ return new Headers(request.headers);
3524
+ }
3525
+ /**
3526
+ * Rebuilds a request from primitives instead of cloning: under Node runtimes
3527
+ * srvx wraps incoming requests in a proxy class whose prototype chain
3528
+ * satisfies `instanceof Request` without the native internals, so
3529
+ * `new Request(request)` throws.
3530
+ */
3531
+ function createForwardRequest(request, requestHeaders, body) {
3532
+ const init = {
3533
+ body,
3534
+ duplex: "half",
3535
+ headers: requestHeaders,
3536
+ method: request.method,
3537
+ signal: request.signal
3538
+ };
3539
+ return new Request(request.url, init);
3540
+ }
3541
+ /**
3542
+ * Handles Codex images proxying. Pass a resolvedProviderConfig when the
3543
+ * caller already resolved the codex provider to avoid a second resolve, and
3544
+ * pass a request when model mapping rebuilt the request body.
3545
+ */
3546
+ async function handleCodexImages(c, operation, resolvedProviderConfig, request = c.req.raw) {
3542
3547
  try {
3543
- if (!(resolvedProviderConfig ?? await resolveProviderConfig("codex"))) return c.json({ error: {
3548
+ if (!(resolvedProviderConfig ?? await imageRouteDependencies.resolveProviderConfig("codex"))) return c.json({ error: {
3544
3549
  message: "Provider 'codex' not found or disabled",
3545
3550
  type: "invalid_request_error"
3546
3551
  } }, 404);
3547
- if (operation === "generations") await imageRouteDependencies.debugJsonAsync(logger$12, "images.generations.codex.request", async () => ({ body: await c.req.raw.clone().text() }));
3548
- else debugJson(logger$12, "images.edits.codex.request", getContentMetadata$1(c.req.raw.headers));
3549
- const upstreamResponse = await forwardCodexImages(c.req.raw, operation);
3550
- debugJson(logger$12, `images.${operation}.codex.response`, {
3551
- ...getContentMetadata$1(upstreamResponse.headers),
3552
+ if (operation === "generations") await imageRouteDependencies.debugJsonAsync(logger$13, "images.generations.codex.request", async () => ({ body: await request.clone().text() }));
3553
+ else debugJson(logger$13, "images.edits.codex.request", getContentMetadata(request.headers));
3554
+ const upstreamResponse = await forwardCodexImages(request, operation);
3555
+ debugJson(logger$13, `images.${operation}.codex.response`, {
3556
+ ...getContentMetadata(upstreamResponse.headers),
3552
3557
  statusCode: upstreamResponse.status
3553
3558
  });
3554
3559
  return createProviderProxyResponse(upstreamResponse);
3555
3560
  } catch (error) {
3556
- logger$12.error(`images.${operation}.codex.error`, { error });
3561
+ logger$13.error(`images.${operation}.codex.error`, { error });
3557
3562
  return await forwardError(c, error);
3558
3563
  }
3559
3564
  }
3560
- imageRoutes.post("/generations", (c) => handleCodexImages(c, "generations"));
3561
- imageRoutes.post("/edits", (c) => handleCodexImages(c, "edits"));
3565
+ /**
3566
+ * Routes a parsed images request: applies the model mapping, forwards to a
3567
+ * mapped provider when configured, and otherwise falls back to Codex.
3568
+ */
3569
+ async function routeImagesRequest(c, operation, parsed) {
3570
+ const requestedModel = parsed.model;
3571
+ const mappedModel = imageRouteDependencies.resolveMappedModel(requestedModel);
3572
+ if (mappedModel !== requestedModel) consola.debug(`Resolved model mapping: ${requestedModel} -> ${mappedModel}`);
3573
+ const providerModelAlias = parseProviderModelAlias(mappedModel);
3574
+ if (providerModelAlias) {
3575
+ const providerConfig = await imageRouteDependencies.resolveProviderConfig(providerModelAlias.provider);
3576
+ if (providerConfig) {
3577
+ const request = parsed.createRequest(providerModelAlias.model);
3578
+ if (providerConfig.name === "codex") return await handleCodexImages(c, operation, providerConfig, request);
3579
+ return await forwardProviderImagesWithLogging(providerConfig, request, operation, {
3580
+ logger: logger$13,
3581
+ provider: providerModelAlias.provider
3582
+ });
3583
+ }
3584
+ consola.debug(`Provider '${providerModelAlias.provider}' not found or disabled; forwarding the original model to Codex`);
3585
+ return await handleCodexImages(c, operation, void 0, parsed.originalRequest ?? parsed.createRequest(requestedModel));
3586
+ }
3587
+ if (parsed.originalRequest && mappedModel === requestedModel) return await handleCodexImages(c, operation, void 0, parsed.originalRequest);
3588
+ return await handleCodexImages(c, operation, void 0, parsed.createRequest(mappedModel));
3589
+ }
3590
+ //#endregion
3591
+ //#region src/routes/images/temp-form-data.ts
3592
+ const logger$12 = createHandlerLogger("images-temp-form-data");
3593
+ const multipartStagingDependencies = { createWriteStream };
3594
+ /**
3595
+ * Matches the images forwarding timeouts: an upstream upload may take that
3596
+ * long, so staged files must survive at least the whole forwarding window.
3597
+ */
3598
+ const STAGED_FILES_TTL_MS = 900 * 1e3;
3599
+ const DEFAULT_MULTIPART_STAGING_LIMITS = {
3600
+ maxBodySizeBytes: 128 * 1024 * 1024,
3601
+ maxFieldSizeBytes: 10 * 1024 * 1024,
3602
+ maxFields: 64,
3603
+ maxFileSizeBytes: 64 * 1024 * 1024,
3604
+ maxFiles: 16,
3605
+ maxParts: 80
3606
+ };
3607
+ var InvalidMultipartBodyError = class extends Error {
3608
+ constructor(options) {
3609
+ super("Invalid multipart form data body", options);
3610
+ this.name = "InvalidMultipartBodyError";
3611
+ }
3612
+ };
3613
+ var MultipartBodyTooLargeError = class extends Error {
3614
+ constructor() {
3615
+ super("Multipart form data body exceeds the configured upload limits");
3616
+ this.name = "MultipartBodyTooLargeError";
3617
+ }
3618
+ };
3619
+ function sanitizeFileName(name) {
3620
+ return name.split(/[\\/]/).pop()?.replaceAll("\0", "") || "file";
3621
+ }
3622
+ async function createDiskBackedBlob(filePath, type) {
3623
+ if (typeof Bun !== "undefined") return Bun.file(filePath, { type });
3624
+ const { openAsBlob } = await import("node:fs");
3625
+ return await openAsBlob(filePath, { type });
3626
+ }
3627
+ function toError(error) {
3628
+ return error instanceof Error ? error : new Error(String(error));
3629
+ }
3630
+ function parseMultipartBody(body, contentType, directory, entries, limits) {
3631
+ return new Promise((resolve, reject) => {
3632
+ let busboy;
3633
+ try {
3634
+ busboy = new Busboy({
3635
+ headers: { "content-type": contentType },
3636
+ limits: {
3637
+ fieldSize: limits.maxFieldSizeBytes,
3638
+ fields: limits.maxFields,
3639
+ fileSize: limits.maxFileSizeBytes,
3640
+ files: limits.maxFiles,
3641
+ parts: limits.maxParts
3642
+ }
3643
+ });
3644
+ } catch (error) {
3645
+ reject(new InvalidMultipartBodyError({ cause: toError(error) }));
3646
+ return;
3647
+ }
3648
+ const pendingWrites = [];
3649
+ const activeFileStreams = /* @__PURE__ */ new Set();
3650
+ const source = body === null ? Readable.from([]) : Readable.fromWeb(body);
3651
+ let bodySizeBytes = 0;
3652
+ const bodyLimiter = new Transform({ transform(chunk, _encoding, callback) {
3653
+ bodySizeBytes += chunk.byteLength;
3654
+ if (bodySizeBytes > limits.maxBodySizeBytes) {
3655
+ callback(new MultipartBodyTooLargeError());
3656
+ return;
3657
+ }
3658
+ callback(null, chunk);
3659
+ } });
3660
+ let fileIndex = 0;
3661
+ let failure = null;
3662
+ let inputPipeline = null;
3663
+ let settled = false;
3664
+ const settleStreams = () => Promise.allSettled([...inputPipeline ? [inputPipeline] : [], ...pendingWrites]);
3665
+ const fail = (error) => {
3666
+ if (failure || settled) return;
3667
+ const failureError = toError(error);
3668
+ failure = failureError;
3669
+ source.destroy(failureError);
3670
+ bodyLimiter.destroy(failureError);
3671
+ busboy.destroy(failureError);
3672
+ for (const stream of activeFileStreams) stream.destroy(failureError);
3673
+ settleStreams().then(() => {
3674
+ if (settled) return;
3675
+ settled = true;
3676
+ reject(failureError);
3677
+ });
3678
+ };
3679
+ const failLimit = () => fail(new MultipartBodyTooLargeError());
3680
+ busboy.on("field", (name, value, nameTruncated, valueTruncated) => {
3681
+ if (nameTruncated || valueTruncated) {
3682
+ failLimit();
3683
+ return;
3684
+ }
3685
+ entries.push({
3686
+ kind: "field",
3687
+ name,
3688
+ value
3689
+ });
3690
+ });
3691
+ busboy.on("file", (name, stream, fileName, _transferEncoding, mimeType) => {
3692
+ if (failure) {
3693
+ stream.resume();
3694
+ return;
3695
+ }
3696
+ const filePath = join(directory, `${fileIndex}.upload`);
3697
+ fileIndex += 1;
3698
+ entries.push({
3699
+ fileName: sanitizeFileName(fileName),
3700
+ filePath,
3701
+ kind: "file",
3702
+ mimeType,
3703
+ name
3704
+ });
3705
+ activeFileStreams.add(stream);
3706
+ stream.once("close", () => activeFileStreams.delete(stream));
3707
+ stream.once("limit", failLimit);
3708
+ const write = pipeline(stream, multipartStagingDependencies.createWriteStream(filePath));
3709
+ pendingWrites.push(write);
3710
+ write.catch(fail);
3711
+ });
3712
+ busboy.on("fieldsLimit", failLimit);
3713
+ busboy.on("filesLimit", failLimit);
3714
+ busboy.on("partsLimit", failLimit);
3715
+ inputPipeline = pipeline(source, bodyLimiter, busboy);
3716
+ inputPipeline.then(() => {
3717
+ Promise.allSettled(pendingWrites).then((results) => {
3718
+ if (failure || settled) return;
3719
+ const failed = results.find((result) => result.status === "rejected");
3720
+ if (failed) fail(failed.reason);
3721
+ else {
3722
+ settled = true;
3723
+ resolve();
3724
+ }
3725
+ });
3726
+ }, (error) => {
3727
+ fail(error instanceof MultipartBodyTooLargeError ? error : new InvalidMultipartBodyError({ cause: toError(error) }));
3728
+ });
3729
+ });
3730
+ }
3731
+ function resolveStagingLimits(overrides) {
3732
+ const limits = {
3733
+ ...DEFAULT_MULTIPART_STAGING_LIMITS,
3734
+ ...overrides
3735
+ };
3736
+ for (const [name, value] of Object.entries(limits)) if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError(`${name} must be a positive safe integer`);
3737
+ return limits;
3738
+ }
3739
+ /**
3740
+ * Streams a multipart request body through the parser, writing every file
3741
+ * part to a temporary directory as it arrives and rebuilding the form data
3742
+ * with disk-backed blobs, so forwarding streams payloads from disk instead
3743
+ * of pinning the whole upload in memory.
3744
+ */
3745
+ async function stageMultipartBodyToDisk(body, contentType, limitOverrides = {}) {
3746
+ const limits = resolveStagingLimits(limitOverrides);
3747
+ const directory = await mkdtemp(join(tmpdir(), "copilot-api-images-"));
3748
+ const entries = [];
3749
+ try {
3750
+ await parseMultipartBody(body, contentType, directory, entries, limits);
3751
+ } catch (error) {
3752
+ await rm(directory, {
3753
+ force: true,
3754
+ recursive: true
3755
+ });
3756
+ throw error;
3757
+ }
3758
+ const stagedFormData = new FormData();
3759
+ try {
3760
+ for (const entry of entries) if (entry.kind === "field") stagedFormData.append(entry.name, entry.value);
3761
+ else stagedFormData.append(entry.name, await createDiskBackedBlob(entry.filePath, entry.mimeType), entry.fileName);
3762
+ } catch (error) {
3763
+ await rm(directory, {
3764
+ force: true,
3765
+ recursive: true
3766
+ });
3767
+ throw error;
3768
+ }
3769
+ let cleanupPromise = null;
3770
+ let cleanupTimer = null;
3771
+ let unregisterProcessCleanup = null;
3772
+ const cleanup = () => {
3773
+ cleanupPromise ??= (async () => {
3774
+ if (cleanupTimer) {
3775
+ clearTimeout(cleanupTimer);
3776
+ cleanupTimer = null;
3777
+ }
3778
+ try {
3779
+ await rm(directory, {
3780
+ force: true,
3781
+ recursive: true
3782
+ });
3783
+ } catch (error) {
3784
+ logger$12.warn("Failed to remove staged images temp directory", {
3785
+ directory,
3786
+ error
3787
+ });
3788
+ } finally {
3789
+ unregisterProcessCleanup?.();
3790
+ unregisterProcessCleanup = null;
3791
+ }
3792
+ })();
3793
+ return cleanupPromise;
3794
+ };
3795
+ unregisterProcessCleanup = registerProcessCleanup(() => {
3796
+ if (cleanupTimer) {
3797
+ clearTimeout(cleanupTimer);
3798
+ cleanupTimer = null;
3799
+ }
3800
+ try {
3801
+ rmSync(directory, {
3802
+ force: true,
3803
+ recursive: true
3804
+ });
3805
+ } catch (error) {
3806
+ logger$12.warn("Failed to remove staged images temp directory on exit", {
3807
+ directory,
3808
+ error
3809
+ });
3810
+ } finally {
3811
+ unregisterProcessCleanup?.();
3812
+ unregisterProcessCleanup = null;
3813
+ }
3814
+ });
3815
+ return {
3816
+ directory,
3817
+ formData: stagedFormData,
3818
+ cleanup,
3819
+ scheduleCleanup: () => {
3820
+ if (cleanupPromise || cleanupTimer) return;
3821
+ cleanupTimer = setTimeout(() => void cleanup(), STAGED_FILES_TTL_MS);
3822
+ cleanupTimer.unref();
3823
+ }
3824
+ };
3825
+ }
3826
+ //#endregion
3827
+ //#region src/routes/images/edits-handler.ts
3828
+ const imageEditsRouteDependencies = { stageMultipartBodyToDisk };
3829
+ function createStagedFormDataRequest(request, requestHeaders, formData) {
3830
+ const headers = new Headers(requestHeaders);
3831
+ headers.delete("content-length");
3832
+ headers.delete("content-type");
3833
+ return createForwardRequest(request, headers, formData);
3834
+ }
3835
+ function createMultipartImagesRequest(request, requestHeaders, formData, model) {
3836
+ formData.set("model", model);
3837
+ return createStagedFormDataRequest(request, requestHeaders, formData);
3838
+ }
3839
+ /**
3840
+ * Streams an edits multipart body to disk, staging uploaded files so
3841
+ * forwarding streams them from the filesystem instead of pinning them in
3842
+ * memory. Non-multipart bodies come back as an untouched request stream;
3843
+ * malformed multipart bodies throw a typed error because the consumed stream
3844
+ * can no longer be forwarded.
3845
+ */
3846
+ async function parseEditsRequest(request) {
3847
+ const requestHeaders = snapshotRequestHeaders(request);
3848
+ const contentType = requestHeaders.get("content-type");
3849
+ if (contentType?.split(";", 1)[0]?.trim().toLowerCase() !== "multipart/form-data" || !contentType) return createForwardRequest(request, requestHeaders, request.body);
3850
+ const staged = await imageEditsRouteDependencies.stageMultipartBodyToDisk(request.body, contentType);
3851
+ const model = staged.formData.get("model");
3852
+ return {
3853
+ model: typeof model === "string" ? model : void 0,
3854
+ requestHeaders,
3855
+ staged
3856
+ };
3857
+ }
3858
+ async function handleImagesEdits(c) {
3859
+ try {
3860
+ const parsed = await parseEditsRequest(c.req.raw);
3861
+ if (parsed instanceof Request) return await handleCodexImages(c, "edits", void 0, parsed);
3862
+ const { model, requestHeaders, staged } = parsed;
3863
+ try {
3864
+ const response = model === void 0 ? await handleCodexImages(c, "edits", void 0, createStagedFormDataRequest(c.req.raw, requestHeaders, staged.formData)) : await routeImagesRequest(c, "edits", {
3865
+ createRequest: (mappedModel) => createMultipartImagesRequest(c.req.raw, requestHeaders, staged.formData, mappedModel),
3866
+ model
3867
+ });
3868
+ staged.scheduleCleanup();
3869
+ return response;
3870
+ } catch (error) {
3871
+ await staged.cleanup();
3872
+ throw error;
3873
+ }
3874
+ } catch (error) {
3875
+ if (error instanceof InvalidMultipartBodyError || error instanceof MultipartBodyTooLargeError) return c.json({ error: {
3876
+ message: error.message,
3877
+ type: "invalid_request_error"
3878
+ } }, error instanceof MultipartBodyTooLargeError ? 413 : 400);
3879
+ logger$13.error("images.edits.error", { error });
3880
+ return await forwardError(c, error);
3881
+ }
3882
+ }
3883
+ //#endregion
3884
+ //#region src/routes/images/generations-handler.ts
3885
+ function createJsonImagesRequest(request, requestHeaders, payload, model) {
3886
+ const headers = new Headers(requestHeaders);
3887
+ headers.delete("content-length");
3888
+ return createForwardRequest(request, headers, new TextEncoder().encode(JSON.stringify({
3889
+ ...payload,
3890
+ model
3891
+ })));
3892
+ }
3893
+ /**
3894
+ * Parses a generations request body as JSON. Generation payloads are small
3895
+ * JSON documents, so one byte copy covers both routing on the model field
3896
+ * and forwarding an unchanged body to Codex. Rebuilt bodies stay binary so
3897
+ * Node does not synthesize a text/plain content type.
3898
+ */
3899
+ async function parseGenerationsRequest(request) {
3900
+ const requestHeaders = snapshotRequestHeaders(request);
3901
+ const body = new Uint8Array(await request.arrayBuffer());
3902
+ const originalRequest = createForwardRequest(request, requestHeaders, body);
3903
+ let payload;
3904
+ try {
3905
+ const bodyText = new TextDecoder("utf-8", { fatal: true }).decode(body);
3906
+ payload = JSON.parse(bodyText);
3907
+ } catch {
3908
+ return originalRequest;
3909
+ }
3910
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload) || typeof payload.model !== "string") return originalRequest;
3911
+ return {
3912
+ createRequest: (mappedModel) => createJsonImagesRequest(request, requestHeaders, payload, mappedModel),
3913
+ model: payload.model,
3914
+ originalRequest
3915
+ };
3916
+ }
3917
+ async function handleImagesGenerations(c) {
3918
+ try {
3919
+ const parsed = await parseGenerationsRequest(c.req.raw);
3920
+ if (parsed instanceof Request) return await handleCodexImages(c, "generations", void 0, parsed);
3921
+ return await routeImagesRequest(c, "generations", parsed);
3922
+ } catch (error) {
3923
+ logger$13.error("images.generations.error", { error });
3924
+ return await forwardError(c, error);
3925
+ }
3926
+ }
3927
+ //#endregion
3928
+ //#region src/routes/images/route.ts
3929
+ const imageRoutes = new Hono();
3930
+ imageRoutes.post("/generations", handleImagesGenerations);
3931
+ imageRoutes.post("/edits", handleImagesEdits);
3562
3932
  //#endregion
3563
3933
  //#region src/lib/tokenizer.ts
3564
3934
  const ENCODING_MAP = {
@@ -10032,17 +10402,6 @@ function isDeepSeekModelId(modelId) {
10032
10402
  function shouldInjectMessagesToolCallTips(userAgent, targetModel) {
10033
10403
  return isCodexUserAgent(userAgent) && !isDeepSeekModelId(targetModel);
10034
10404
  }
10035
- async function logCodexModelsResponse(response) {
10036
- try {
10037
- const models = await response.clone().json();
10038
- debugJson(logger$8, "models.codex.response", {
10039
- statusCode: response.status,
10040
- models
10041
- });
10042
- } catch (error) {
10043
- logger$8.warn("models.codex.response_log_error", { error });
10044
- }
10045
- }
10046
10405
  /**
10047
10406
  * Proxies a models request to the fixed Codex upstream models endpoint.
10048
10407
  * Returns a 404 JSON response when the codex provider is unavailable.
@@ -10054,9 +10413,7 @@ async function handleCodexModelsProxy(c, resolvedProviderConfig) {
10054
10413
  message: "Provider 'codex' not found or disabled",
10055
10414
  type: "invalid_request_error"
10056
10415
  } }, 404);
10057
- const upstreamResponse = await forwardCodexModels(c.req.url, c.req.raw.headers);
10058
- await logCodexModelsResponse(upstreamResponse);
10059
- return createProviderProxyResponse(upstreamResponse);
10416
+ return createProviderProxyResponse(await forwardCodexModels(c.req.url, c.req.raw.headers));
10060
10417
  }
10061
10418
  async function handleMergedCodexModels(c, candidatesRequest, options = {}) {
10062
10419
  const [upstreamCatalog, candidates] = await Promise.all([tryGetCodexCatalog(c), Promise.resolve(candidatesRequest).catch((error) => {
@@ -10095,12 +10452,6 @@ async function handleMergedCodexModels(c, candidatesRequest, options = {}) {
10095
10452
  ...upstreamCatalog ?? {},
10096
10453
  models
10097
10454
  };
10098
- debugJson(logger$8, "models.codex.merged_response", {
10099
- upstreamCount: upstreamModels.length,
10100
- codexProviderAliasCount: codexProviderAliases.length,
10101
- syntheticCount: syntheticModels.length,
10102
- models: response
10103
- });
10104
10455
  return c.json(response);
10105
10456
  }
10106
10457
  function createCatalogAlias(model, slug, providerName) {
@@ -10543,12 +10894,6 @@ providerAlphaSearchRoutes.post("/", async (c) => {
10543
10894
  //#region src/routes/provider/images/route.ts
10544
10895
  const logger$5 = createHandlerLogger("provider-images-handler");
10545
10896
  const providerImageRoutes = new Hono();
10546
- function getContentMetadata(headers) {
10547
- return {
10548
- contentType: headers.get("content-type"),
10549
- contentLength: headers.get("content-length")
10550
- };
10551
- }
10552
10897
  async function handleProviderImages(c, operation) {
10553
10898
  const provider = c.req.param("provider") ?? "";
10554
10899
  try {
@@ -10558,21 +10903,10 @@ async function handleProviderImages(c, operation) {
10558
10903
  type: "invalid_request_error"
10559
10904
  } }, 404);
10560
10905
  if (providerConfig.name === "codex") return await handleCodexImages(c, operation, providerConfig);
10561
- if (operation === "generations") await debugJsonAsync(logger$5, "provider.images.generations.request", async () => ({
10562
- body: await c.req.raw.clone().text(),
10563
- provider
10564
- }));
10565
- else debugJson(logger$5, "provider.images.edits.request", {
10566
- ...getContentMetadata(c.req.raw.headers),
10906
+ return await forwardProviderImagesWithLogging(providerConfig, c.req.raw, operation, {
10907
+ logger: logger$5,
10567
10908
  provider
10568
10909
  });
10569
- const upstreamResponse = await forwardProviderImages(providerConfig, c.req.raw, operation);
10570
- debugJson(logger$5, `provider.images.${operation}.response`, {
10571
- ...getContentMetadata(upstreamResponse.headers),
10572
- provider,
10573
- statusCode: upstreamResponse.status
10574
- });
10575
- return createProviderProxyResponse(upstreamResponse);
10576
10910
  } catch (error) {
10577
10911
  logger$5.error(`provider.images.${operation}.error`, {
10578
10912
  provider,
@@ -10636,6 +10970,58 @@ providerModelRoutes.get("/", async (c) => {
10636
10970
  }
10637
10971
  });
10638
10972
  //#endregion
10973
+ //#region src/lib/zstd-request.ts
10974
+ const ZSTD_CONTENT_ENCODING = "zstd";
10975
+ const INVALID_BODY_STATUS = 400;
10976
+ let nodeZlibPromise = null;
10977
+ const zstdDecompressionMiddleware = async (c, next) => {
10978
+ if (c.req.header("content-encoding")?.trim().toLowerCase() !== ZSTD_CONTENT_ENCODING) return next();
10979
+ try {
10980
+ const decompressedBody = await decompressZstd(new Uint8Array(await c.req.raw.arrayBuffer()));
10981
+ const headers = new Headers(c.req.raw.headers);
10982
+ headers.delete("content-encoding");
10983
+ headers.delete("content-length");
10984
+ c.req.raw = new Request(c.req.raw.url, {
10985
+ body: decompressedBody,
10986
+ headers,
10987
+ method: c.req.raw.method,
10988
+ signal: c.req.raw.signal
10989
+ });
10990
+ c.req.bodyCache = {};
10991
+ } catch {
10992
+ return c.json({ error: {
10993
+ message: "Failed to decompress zstd request body.",
10994
+ type: "invalid_request_error"
10995
+ } }, INVALID_BODY_STATUS);
10996
+ }
10997
+ return next();
10998
+ };
10999
+ const decompressZstd = async (input) => {
11000
+ const bun = getBunRuntime();
11001
+ if (bun?.zstdDecompress) return toUint8Array(await bun.zstdDecompress(input));
11002
+ const nodeZlib = await getNodeZlib();
11003
+ if (nodeZlib?.zstdDecompress) return new Promise((resolve, reject) => {
11004
+ nodeZlib.zstdDecompress?.(input, (error, result) => {
11005
+ if (error) {
11006
+ reject(error);
11007
+ return;
11008
+ }
11009
+ resolve(toUint8Array(result));
11010
+ });
11011
+ });
11012
+ return decompress(input);
11013
+ };
11014
+ const getBunRuntime = () => globalThis.Bun;
11015
+ const getNodeZlib = async () => {
11016
+ nodeZlibPromise ??= import("node:zlib").then((module) => module).catch(() => null);
11017
+ return nodeZlibPromise;
11018
+ };
11019
+ const toUint8Array = (data) => {
11020
+ if (data instanceof Uint8Array) return data;
11021
+ if (data instanceof ArrayBuffer) return new Uint8Array(data);
11022
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
11023
+ };
11024
+ //#endregion
10639
11025
  //#region src/routes/responses/custom-tool-input-stream-decoder.ts
10640
11026
  const CUSTOM_TOOL_INPUT_PREFIX_TOKENS = [
10641
11027
  "{",
@@ -11675,6 +12061,7 @@ const getResponsesEvents = (response, signal) => createResponsesSafeStream(creat
11675
12061
  //#endregion
11676
12062
  //#region src/routes/provider/responses/route.ts
11677
12063
  const providerResponsesRoutes = new Hono();
12064
+ providerResponsesRoutes.use(zstdDecompressionMiddleware);
11678
12065
  providerResponsesRoutes.post("/", async (c) => {
11679
12066
  try {
11680
12067
  const provider = c.req.param("provider") ?? "";
@@ -11926,6 +12313,7 @@ const getTrimmedHeader = (c, name) => {
11926
12313
  //#endregion
11927
12314
  //#region src/routes/responses/route.ts
11928
12315
  const responsesRoutes = new Hono();
12316
+ responsesRoutes.use(zstdDecompressionMiddleware);
11929
12317
  responsesRoutes.post("/", async (c) => {
11930
12318
  try {
11931
12319
  return await handleResponses(c);
@@ -11989,56 +12377,70 @@ usageRoute.get("/", async (c) => {
11989
12377
  });
11990
12378
  //#endregion
11991
12379
  //#region src/server.ts
11992
- const server = new Hono();
11993
- server.use(traceIdMiddleware);
11994
- server.use(logger());
11995
- server.use(cors());
11996
- server.use("*", createAuthMiddleware({
11997
- allowUnauthenticatedPaths: [
11998
- "/",
11999
- "/usage-viewer",
12000
- "/usage-viewer/"
12001
- ],
12002
- shouldSkipPath: (path) => path.startsWith("/admin/")
12003
- }));
12004
- server.use("/admin/*", createAuthMiddleware({
12005
- getApiKeys: getConfiguredAdminApiKeys,
12006
- allowUnauthenticatedPaths: [],
12007
- allowWhenNoApiKeys: false
12008
- }));
12009
- server.use(zstdDecompressionMiddleware);
12010
- server.get("/", (c) => c.text("Server running"));
12011
- server.get("/usage-viewer", (c) => {
12012
- const usageViewerFileUrl = new URL("../pages/index.html", import.meta.url);
12013
- return c.html(readFileSync(usageViewerFileUrl, "utf8"));
12014
- });
12015
- server.get("/usage-viewer/", (c) => c.redirect("/usage-viewer", 301));
12016
- server.route("/chat/completions", completionRoutes);
12017
- server.route("/admin/config", configRoutes);
12018
- server.route("/models", modelRoutes);
12019
- server.route("/embeddings", embeddingRoutes);
12020
- server.route("/usage", usageRoute);
12021
- server.route("/token-usage", tokenUsageRoute);
12022
- server.route("/responses", responsesRoutes);
12023
- server.route("/alpha/search", alphaSearchRoutes);
12024
- server.route("/images", imageRoutes);
12025
- server.route("/v1/chat/completions", completionRoutes);
12026
- server.route("/v1/models", modelRoutes);
12027
- server.route("/v1/embeddings", embeddingRoutes);
12028
- server.route("/v1/responses", responsesRoutes);
12029
- server.route("/v1/alpha/search", alphaSearchRoutes);
12030
- server.route("/v1/images", imageRoutes);
12031
- server.route("/v1/messages", messageRoutes);
12032
- server.route("/:provider/v1/messages", providerMessageRoutes);
12033
- server.route("/:provider/v1/models", providerModelRoutes);
12034
- server.route("/:provider/v1/responses", providerResponsesRoutes);
12035
- server.route("/:provider/v1/alpha/search", providerAlphaSearchRoutes);
12036
- server.route("/:provider/v1/images", providerImageRoutes);
12037
- server.route("/:provider/models", providerModelRoutes);
12038
- server.route("/:provider/responses", providerResponsesRoutes);
12039
- server.route("/:provider/alpha/search", providerAlphaSearchRoutes);
12040
- server.route("/:provider/images", providerImageRoutes);
12380
+ function resolveSameOriginCorsOrigin(origin, context) {
12381
+ if (!origin) return null;
12382
+ try {
12383
+ return origin === new URL(context.req.url).origin ? origin : null;
12384
+ } catch {
12385
+ return null;
12386
+ }
12387
+ }
12388
+ function createServer(options = {}) {
12389
+ const server = new Hono();
12390
+ const networkExposed = options.networkExposed ?? false;
12391
+ server.use(traceIdMiddleware);
12392
+ server.use(logger());
12393
+ server.use(networkExposed ? cors({ origin: resolveSameOriginCorsOrigin }) : cors());
12394
+ server.use("*", createAuthMiddleware({
12395
+ getApiKeys: options.getApiKeys,
12396
+ allowUnauthenticatedPaths: [
12397
+ "/",
12398
+ "/usage-viewer",
12399
+ "/usage-viewer/"
12400
+ ],
12401
+ shouldSkipPath: (path) => path.startsWith("/admin/"),
12402
+ allowWhenNoApiKeys: !networkExposed
12403
+ }));
12404
+ server.use("/admin/*", createAuthMiddleware({
12405
+ getApiKeys: getConfiguredAdminApiKeys,
12406
+ allowUnauthenticatedPaths: [],
12407
+ allowWhenNoApiKeys: false
12408
+ }));
12409
+ server.get("/", (c) => c.text("Server running"));
12410
+ server.get("/usage-viewer", (c) => {
12411
+ const usageViewerFileUrl = new URL("../pages/index.html", import.meta.url);
12412
+ return c.html(readFileSync(usageViewerFileUrl, "utf8"));
12413
+ });
12414
+ server.get("/usage-viewer/", (c) => c.redirect("/usage-viewer", 301));
12415
+ server.route("/chat/completions", completionRoutes);
12416
+ server.route("/admin/config", configRoutes);
12417
+ server.route("/models", modelRoutes);
12418
+ server.route("/embeddings", embeddingRoutes);
12419
+ server.route("/usage", usageRoute);
12420
+ server.route("/token-usage", tokenUsageRoute);
12421
+ server.route("/responses", responsesRoutes);
12422
+ server.route("/alpha/search", alphaSearchRoutes);
12423
+ server.route("/images", imageRoutes);
12424
+ server.route("/v1/chat/completions", completionRoutes);
12425
+ server.route("/v1/models", modelRoutes);
12426
+ server.route("/v1/embeddings", embeddingRoutes);
12427
+ server.route("/v1/responses", responsesRoutes);
12428
+ server.route("/v1/alpha/search", alphaSearchRoutes);
12429
+ server.route("/v1/images", imageRoutes);
12430
+ server.route("/v1/messages", messageRoutes);
12431
+ server.route("/:provider/v1/messages", providerMessageRoutes);
12432
+ server.route("/:provider/v1/models", providerModelRoutes);
12433
+ server.route("/:provider/v1/responses", providerResponsesRoutes);
12434
+ server.route("/:provider/v1/alpha/search", providerAlphaSearchRoutes);
12435
+ server.route("/:provider/v1/images", providerImageRoutes);
12436
+ server.route("/:provider/models", providerModelRoutes);
12437
+ server.route("/:provider/responses", providerResponsesRoutes);
12438
+ server.route("/:provider/alpha/search", providerAlphaSearchRoutes);
12439
+ server.route("/:provider/images", providerImageRoutes);
12440
+ return server;
12441
+ }
12442
+ createServer();
12041
12443
  //#endregion
12042
- export { server };
12444
+ export { createServer };
12043
12445
 
12044
- //# sourceMappingURL=server-HBeQNO83.js.map
12446
+ //# sourceMappingURL=server-D5XuGc4z.js.map