@nick3/copilot-api 1.10.8 → 1.10.29

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 (55) hide show
  1. package/README.md +141 -46
  2. package/README.zh-CN.md +141 -46
  3. package/dist/{account-COtMmvzU.js → account-DpW8RaT6.js} +3 -3
  4. package/dist/{account-COtMmvzU.js.map → account-DpW8RaT6.js.map} +1 -1
  5. package/dist/admin/AGENTS.md +19 -0
  6. package/dist/auth-nO-eHeO_.js +327 -0
  7. package/dist/auth-nO-eHeO_.js.map +1 -0
  8. package/dist/{check-usage-DdevqHE5.js → check-usage-ZifYvA3w.js} +4 -42
  9. package/dist/check-usage-ZifYvA3w.js.map +1 -0
  10. package/dist/config-CmhIPHn_.js +578 -0
  11. package/dist/config-CmhIPHn_.js.map +1 -0
  12. package/dist/{debug-BMo6ltbp.js → debug-DvpksqEL.js} +18 -7
  13. package/dist/debug-DvpksqEL.js.map +1 -0
  14. package/dist/main.js +5 -10
  15. package/dist/main.js.map +1 -1
  16. package/dist/mcp-http-BhELuvog.js +2 -0
  17. package/dist/mcp-http-DI4Vz01p.js +82 -0
  18. package/dist/mcp-http-DI4Vz01p.js.map +1 -0
  19. package/dist/mcp-http-config-DMdUDz1D.js +39 -0
  20. package/dist/mcp-http-config-DMdUDz1D.js.map +1 -0
  21. package/dist/mcp-pLTPS0tO.js +79 -0
  22. package/dist/mcp-pLTPS0tO.js.map +1 -0
  23. package/dist/{tool-search-BrN7M0Dd.js → mcp-server-DEqHrXFq.js} +25 -2
  24. package/dist/mcp-server-DEqHrXFq.js.map +1 -0
  25. package/dist/{paths-CclKwouX.js → paths-Bpsb62LK.js} +3 -1
  26. package/dist/paths-Bpsb62LK.js.map +1 -0
  27. package/dist/{poll-access-token-BAgM2-7k.js → poll-access-token-GzVkiTH8.js} +71 -4
  28. package/dist/poll-access-token-GzVkiTH8.js.map +1 -0
  29. package/dist/{request-outbound-BJjWS_jF.js → request-outbound-BkEA8Wgb.js} +1 -1
  30. package/dist/{request-outbound-Pu1kp2x8.js → request-outbound-DZTxxtcx.js} +3 -3
  31. package/dist/{request-outbound-Pu1kp2x8.js.map → request-outbound-DZTxxtcx.js.map} +1 -1
  32. package/dist/{proxy-_U-hgwIn.js → responses-bridge-registry-BJ5Sbh6-.js} +116 -577
  33. package/dist/responses-bridge-registry-BJ5Sbh6-.js.map +1 -0
  34. package/dist/{server-DulP9mYd.js → server-DJ3_UGc4.js} +339 -168
  35. package/dist/server-DJ3_UGc4.js.map +1 -0
  36. package/dist/start-DaB0AcjZ.js +526 -0
  37. package/dist/start-DaB0AcjZ.js.map +1 -0
  38. package/dist/token-DrFDLVxa.js +365 -0
  39. package/dist/token-DrFDLVxa.js.map +1 -0
  40. package/package.json +1 -1
  41. package/dist/auth-B0y-2njL.js +0 -226
  42. package/dist/auth-B0y-2njL.js.map +0 -1
  43. package/dist/check-usage-DdevqHE5.js.map +0 -1
  44. package/dist/debug-BMo6ltbp.js.map +0 -1
  45. package/dist/get-copilot-token-8Rm-rVsp.js +0 -17
  46. package/dist/get-copilot-token-8Rm-rVsp.js.map +0 -1
  47. package/dist/mcp-9Hgepkc5.js +0 -37
  48. package/dist/mcp-9Hgepkc5.js.map +0 -1
  49. package/dist/paths-CclKwouX.js.map +0 -1
  50. package/dist/poll-access-token-BAgM2-7k.js.map +0 -1
  51. package/dist/proxy-_U-hgwIn.js.map +0 -1
  52. package/dist/server-DulP9mYd.js.map +0 -1
  53. package/dist/start-CtEoE2gt.js +0 -274
  54. package/dist/start-CtEoE2gt.js.map +0 -1
  55. package/dist/tool-search-BrN7M0Dd.js.map +0 -1
@@ -1,109 +1,26 @@
1
- import { A as state, D as prepareInteractionHeaders, E as prepareForCompact, I as compactAutoContinuePromptStarts, L as compactMessageSections, N as requestContext, O as prepareMessageProxyHeaders, P as resolveTraceId, S as copilotWebSocketHeaders, T as normalizeDomain, _ as HTTPError, b as copilotHeaders, c as getUUID, d as parseUserIdMetadata, f as resolveAffinityKey, g as getCopilotUsage, h as getDeviceCode, j as captureOutboundHeadersSnapshot, k as accountFromState, l as isNullish, m as getGitHubUser, o as generateRequestIdFromPayload, p as sleep, s as getRootSessionId, t as pollAccessToken, u as normalizeStableSessionId, v as forwardError, y as copilotBaseUrl, z as compactSystemPromptStarts } from "./poll-access-token-BAgM2-7k.js";
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-COtMmvzU.js";
3
- import { r as ensurePaths, t as PATHS } from "./paths-CclKwouX.js";
4
- import { i as getRequestOutboundStore, r as getRedactedHeaderKeys } from "./request-outbound-Pu1kp2x8.js";
5
- import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, i as isBridgeToolSearchName, l as selectDeferredToolsByNames, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, t as BRIDGE_TOOL_SEARCH_NAME, u as shouldEnableResponsesToolSearch } from "./tool-search-BrN7M0Dd.js";
6
- import { A as getModelRefreshIntervalMs, B as isResponsesApiWebSocketEnabled, C as getAnthropicApiKey, D as getLogLevel, E as getExtraPromptForModel, F as isForceAgentEnabled, H as resolveModelAlias, I as isMessageStartInputTokensFallbackEnabled, L as isMessagesApiEnabled, M as getReasoningEffortForModel, N as getSmallModel, O as getModelAliases, P as isAccountAffinityEnabled, R as isResponsesApiContextManagementModel, S as getAliasTargetSet, T as getConfig, U as shouldCompactUseSmallModel, V as mergeConfigWithDefaults, _ as toLocalDateString, b as isDevModeEnabled, c as applySharedSessionAffinityRetention, d as getClientIpInfo, f as getRequestHistoryStore, g as normalizeMessagesUsage, h as normalizeEmbeddingsUsage, j as getProviderConfig, k as getModelAliasesInfo, l as extractResponsesUsageFromResult, m as normalizeChatCompletionsUsage, o as updateQuotaRefreshSchedulerFromConfig, p as getStatsStore, s as accountsManager, t as getProxyEnvDispatcher, u as extractResponsesUsageFromStreamEvent, v as copilotFetch, w as getClaudeTokenMultiplier, x as PROVIDER_TYPE_ANTHROPIC, y as flushPendingCapture, z as isResponsesApiWebSearchEnabled } from "./proxy-_U-hgwIn.js";
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
+ 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
+ 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";
5
+ import { i as getRequestOutboundStore, r as getRedactedHeaderKeys } from "./request-outbound-DZTxxtcx.js";
6
+ import { i as isMcpHttpEnabledFromEnv, n as DEFAULT_MCP_HTTP_PATH } from "./mcp-http-config-DMdUDz1D.js";
7
+ 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
+ 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";
7
10
  import consola from "consola";
8
11
  import fs, { readFile } from "node:fs/promises";
9
- import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
12
+ import { createHash, randomUUID } from "node:crypto";
10
13
  import * as path$1 from "node:path";
11
14
  import path from "node:path";
12
- import { fileURLToPath } from "node:url";
15
+ import { events } from "fetch-event-stream";
13
16
  import fs$1, { existsSync } from "node:fs";
17
+ import { WebSocket } from "undici";
18
+ import { fileURLToPath } from "node:url";
14
19
  import { Hono } from "hono";
15
20
  import { cors } from "hono/cors";
16
21
  import { logger } from "hono/logger";
17
22
  import { streamSSE } from "hono/streaming";
18
- import { events } from "fetch-event-stream";
19
23
  import util from "node:util";
20
- import { WebSocket } from "undici";
21
- //#region src/lib/request-auth.ts
22
- const LEGACY_API_KEY_ENV_VAR = "COPILOT_API_KEY";
23
- let warnedLegacyEnvFallback = false;
24
- let warnedLegacyConfigFallback = false;
25
- function normalizeApiKeys(apiKeys) {
26
- if (!Array.isArray(apiKeys)) {
27
- if (apiKeys !== void 0) consola.warn("Invalid auth.apiKeys config. Expected an array of strings.");
28
- return [];
29
- }
30
- const normalizedKeys = apiKeys.filter((key) => typeof key === "string").map((key) => key.trim()).filter((key) => key.length > 0);
31
- if (normalizedKeys.length !== apiKeys.length) consola.warn("Invalid auth.apiKeys entries found. Only non-empty strings are allowed.");
32
- return [...new Set(normalizedKeys)];
33
- }
34
- function getConfiguredApiKeys() {
35
- const config = getConfig();
36
- const configuredApiKeys = normalizeApiKeys(config.auth?.apiKeys);
37
- if (configuredApiKeys.length > 0) return configuredApiKeys;
38
- const envApiKey = process.env[LEGACY_API_KEY_ENV_VAR]?.trim();
39
- if (envApiKey) {
40
- if (!warnedLegacyEnvFallback) {
41
- warnedLegacyEnvFallback = true;
42
- consola.warn(`Using legacy ${LEGACY_API_KEY_ENV_VAR}. Please migrate to config.auth.apiKeys.`);
43
- }
44
- return [envApiKey];
45
- }
46
- const legacyConfigApiKey = config.apiKey?.trim();
47
- if (legacyConfigApiKey) {
48
- if (!warnedLegacyConfigFallback) {
49
- warnedLegacyConfigFallback = true;
50
- consola.warn("Using deprecated config.apiKey. Please migrate to config.auth.apiKeys.");
51
- }
52
- return [legacyConfigApiKey];
53
- }
54
- return configuredApiKeys;
55
- }
56
- function extractRequestApiKey(c) {
57
- const xApiKey = c.req.header("x-api-key")?.trim();
58
- if (xApiKey) return xApiKey;
59
- const authorization = c.req.header("authorization");
60
- if (!authorization) return null;
61
- const [scheme, ...rest] = authorization.trim().split(/\s+/);
62
- if (scheme.toLowerCase() !== "bearer") return null;
63
- return rest.join(" ").trim() || null;
64
- }
65
- function createUnauthorizedResponse(c) {
66
- c.header("WWW-Authenticate", "Bearer realm=\"copilot-api\"");
67
- return c.json({ error: {
68
- message: "Unauthorized. Provide Authorization: Bearer <key> or x-api-key.",
69
- type: "unauthorized"
70
- } }, 401);
71
- }
72
- function normalizePathname(pathname) {
73
- if (pathname.length > 1 && pathname.endsWith("/")) return pathname.slice(0, -1);
74
- return pathname;
75
- }
76
- function hasPrefixBoundary(pathname, prefix) {
77
- return pathname === prefix || pathname.startsWith(`${prefix}/`);
78
- }
79
- function timingSafeKeyCompare(a, b) {
80
- try {
81
- const aBuf = Buffer.from(a);
82
- const bBuf = Buffer.from(b);
83
- if (aBuf.length !== bBuf.length) return false;
84
- return timingSafeEqual(aBuf, bBuf);
85
- } catch {
86
- return false;
87
- }
88
- }
89
- function createAuthMiddleware(options = {}) {
90
- const getApiKeys = options.getApiKeys ?? getConfiguredApiKeys;
91
- const allowUnauthenticatedPaths = new Set((options.allowUnauthenticatedPaths ?? ["/"]).map((path) => normalizePathname(path)));
92
- const allowUnauthenticatedPathPrefixes = (options.allowUnauthenticatedPathPrefixes ?? []).map((path) => normalizePathname(path));
93
- const allowOptionsBypass = options.allowOptionsBypass ?? true;
94
- return async (c, next) => {
95
- if (allowOptionsBypass && c.req.method === "OPTIONS") return next();
96
- const pathname = normalizePathname(new URL(c.req.url, "http://local").pathname);
97
- if (allowUnauthenticatedPaths.has(pathname)) return next();
98
- if (allowUnauthenticatedPathPrefixes.some((prefix) => hasPrefixBoundary(pathname, prefix))) return next();
99
- const apiKeys = getApiKeys();
100
- if (apiKeys.length === 0) return next();
101
- const requestApiKey = extractRequestApiKey(c);
102
- if (!(requestApiKey ? apiKeys.some((apiKey) => timingSafeKeyCompare(requestApiKey, apiKey)) : false)) return createUnauthorizedResponse(c);
103
- return next();
104
- };
105
- }
106
- //#endregion
107
24
  //#region src/lib/trace.ts
108
25
  const traceIdMiddleware = async (c, next) => {
109
26
  const traceId = resolveTraceId(c.req.header("x-trace-id"));
@@ -112,7 +29,7 @@ const traceIdMiddleware = async (c, next) => {
112
29
  traceId,
113
30
  startTime: Date.now(),
114
31
  userAgent: c.req.header("user-agent") || "",
115
- sessionAffinity: c.req.header("x-session-affinity"),
32
+ sessionAffinity: c.req.header("x-session-affinity") ?? c.req.header("x-client-request-id"),
116
33
  parentSessionId: c.req.header("x-parent-session-id")
117
34
  };
118
35
  await requestContext.run(context, async () => {
@@ -302,7 +219,7 @@ const findEndpointModel = (sdkModelId) => {
302
219
  const models = getAvailableModels();
303
220
  const exactMatch = models.find((m) => m.id === sdkModelId);
304
221
  if (exactMatch) return exactMatch;
305
- const normalized = _normalizeSdkModelId(sdkModelId);
222
+ const normalized = normalizeSdkModelId(sdkModelId);
306
223
  if (!normalized) return;
307
224
  const modelName = `claude-${normalized.family}-${normalized.version}`;
308
225
  return models.find((m) => m.id === modelName);
@@ -317,22 +234,22 @@ const findEndpointModel = (sdkModelId) => {
317
234
  * - "claude-haiku-3-5-20250514" -> { family: "haiku", version: "3.5" }
318
235
  * - "claude-haiku-4.5" -> { family: "haiku", version: "4.5" }
319
236
  */
320
- const _normalizeSdkModelId = (sdkModelId) => {
237
+ const normalizeSdkModelId = (sdkModelId) => {
321
238
  const withoutDate = sdkModelId.toLowerCase().replace(/-\d{8}$/, "");
322
- const pattern1 = withoutDate.match(/^claude-(\w+)-(\d+)-(\d+)$/);
239
+ const pattern1 = withoutDate.match(/^claude-(\w+)-(\d+)\.(\d+)$/);
323
240
  if (pattern1) return {
324
241
  family: pattern1[1],
325
242
  version: `${pattern1[2]}.${pattern1[3]}`
326
243
  };
327
- const pattern2 = withoutDate.match(/^claude-(\d+)-(\d+)-(\w+)$/);
244
+ const pattern2 = withoutDate.match(/^claude-(\w+)-(\d+)-(\d+)$/);
328
245
  if (pattern2) return {
329
- family: pattern2[3],
330
- version: `${pattern2[1]}.${pattern2[2]}`
246
+ family: pattern2[1],
247
+ version: `${pattern2[2]}.${pattern2[3]}`
331
248
  };
332
- const pattern3 = withoutDate.match(/^claude-(\w+)-(\d+)\.(\d+)$/);
249
+ const pattern3 = withoutDate.match(/^claude-(\d+)-(\d+)-(\w+)$/);
333
250
  if (pattern3) return {
334
- family: pattern3[1],
335
- version: `${pattern3[2]}.${pattern3[3]}`
251
+ family: pattern3[3],
252
+ version: `${pattern3[1]}.${pattern3[2]}`
336
253
  };
337
254
  const pattern4 = withoutDate.match(/^claude-(\w+)-(\d+)$/);
338
255
  if (pattern4) return {
@@ -411,7 +328,7 @@ const logCopilotQuotaSnapshots = (snapshots) => {
411
328
  const logCopilotRateLimitUsage = (usage) => {
412
329
  const d = new Date(usage.resetAt);
413
330
  const dateStr = Number.isNaN(d.getTime()) ? usage.resetAt : d.toLocaleString();
414
- consola.info(`Copilot ${usage.type} quota remaining: ${usage.remaining}, resets at: ${dateStr}`);
331
+ consola.log(`Copilot ${usage.type} quota remaining: ${usage.remaining}, resets at: ${dateStr}`);
415
332
  };
416
333
  const isCopilotQuotaSnapshot = (value) => {
417
334
  if (!value || typeof value !== "object") return false;
@@ -693,10 +610,95 @@ const getTokenCount = async (payload, model) => {
693
610
  output: outputTokens
694
611
  };
695
612
  };
613
+ const SYSTEM_REMINDER_START = "<system-reminder>";
614
+ const SYSTEM_REMINDER_END = "</system-reminder>";
615
+ const SUBAGENT_START_HOOK_ADDITIONAL_PREFIX = "SubagentStart hook additional";
696
616
  const IDE_EXECUTE_CODE_TOOL = "mcp__ide__executeCode";
697
617
  const IDE_GET_DIAGNOSTICS_TOOL = "mcp__ide__getDiagnostics";
698
618
  const IDE_GET_DIAGNOSTICS_DESCRIPTION = "Get language diagnostics from VS Code. Returns errors, warnings, information, and hints for files in the workspace.";
699
619
  const PDF_FILE_READ_PREFIX = "PDF file read:";
620
+ const createTextBlock = (text) => ({
621
+ type: "text",
622
+ text
623
+ });
624
+ const appendTextSegment = (base, addition) => {
625
+ if (base.length === 0) return addition;
626
+ if (addition.length === 0) return base;
627
+ return `${base}\n\n${addition}`;
628
+ };
629
+ const ensureSystemReminderText = (text) => {
630
+ if (text.startsWith(SYSTEM_REMINDER_START)) return text;
631
+ return `${SYSTEM_REMINDER_START}\n${text.trim()}\n${SYSTEM_REMINDER_END}`;
632
+ };
633
+ const normalizeSystemStringForMerge = (text) => {
634
+ if (!text.startsWith(SUBAGENT_START_HOOK_ADDITIONAL_PREFIX)) return ensureSystemReminderText(text);
635
+ const lineBreakMatch = /\r?\n/.exec(text);
636
+ if (!lineBreakMatch) return [createTextBlock(ensureSystemReminderText(text))];
637
+ const firstLine = text.slice(0, lineBreakMatch.index);
638
+ const rest = text.slice(lineBreakMatch.index + lineBreakMatch[0].length);
639
+ return [createTextBlock(ensureSystemReminderText(firstLine)), ...rest.length > 0 ? [createTextBlock(ensureSystemReminderText(rest))] : []];
640
+ };
641
+ const normalizeSystemContentForMerge = (content) => {
642
+ if (typeof content === "string") return normalizeSystemStringForMerge(content);
643
+ return content.map((block) => block.text.startsWith(SYSTEM_REMINDER_START) ? block : {
644
+ ...block,
645
+ text: ensureSystemReminderText(block.text)
646
+ });
647
+ };
648
+ const toSystemTextBlocks = (content) => {
649
+ return typeof content === "string" ? [createTextBlock(content)] : [...content];
650
+ };
651
+ const mergeSystemPromptContent = (current, addition) => {
652
+ if (current === void 0) return typeof addition === "string" ? addition : [...addition];
653
+ if (typeof current === "string" && typeof addition === "string") return appendTextSegment(current, addition);
654
+ return [...toSystemTextBlocks(current), ...toSystemTextBlocks(addition)];
655
+ };
656
+ const prependSystemContentToUserMessage = (message, addition) => {
657
+ if (typeof message.content === "string" && typeof addition === "string") {
658
+ message.content = appendTextSegment(addition, message.content);
659
+ return;
660
+ }
661
+ if (Array.isArray(message.content)) {
662
+ const lastToolResultIndex = message.content.findLastIndex((block) => block.type === "tool_result");
663
+ if (lastToolResultIndex >= 0) {
664
+ message.content = [
665
+ ...message.content.slice(0, lastToolResultIndex + 1),
666
+ ...toSystemTextBlocks(addition),
667
+ ...message.content.slice(lastToolResultIndex + 1)
668
+ ];
669
+ return;
670
+ }
671
+ }
672
+ message.content = [...toSystemTextBlocks(addition), ...typeof message.content === "string" ? [createTextBlock(message.content)] : message.content];
673
+ };
674
+ const normalizeSystemMessages = (payload) => {
675
+ if (!Array.isArray(payload.messages) || !payload.messages.some((msg) => msg.role === "system")) return;
676
+ const normalizedMessages = [];
677
+ let system = payload.system;
678
+ for (const message of payload.messages) {
679
+ if (message.role === "system") {
680
+ const normalizedContent = normalizeSystemContentForMerge(message.content);
681
+ const previousMessage = normalizedMessages.at(-1);
682
+ if (previousMessage?.role === "user") prependSystemContentToUserMessage(previousMessage, normalizedContent);
683
+ else if (!previousMessage) system = mergeSystemPromptContent(system, normalizedContent);
684
+ continue;
685
+ }
686
+ normalizedMessages.push(message);
687
+ }
688
+ payload.messages = normalizedMessages;
689
+ payload.system = system;
690
+ };
691
+ const isVersionAtLeast = (version, minimumMajor, minimumMinor) => {
692
+ const [majorPart, minorPart = "0"] = version.split(".");
693
+ const major = Number.parseInt(majorPart, 10);
694
+ const minor = Number.parseInt(minorPart, 10);
695
+ if (!Number.isInteger(major) || !Number.isInteger(minor)) return false;
696
+ return major > minimumMajor || major === minimumMajor && minor >= minimumMinor;
697
+ };
698
+ const shouldSummarizeThinkingDisplayForModel = (model) => {
699
+ const normalized = normalizeSdkModelId(model);
700
+ return Boolean(normalized && isVersionAtLeast(normalized.version, 4, 7));
701
+ };
700
702
  const getBlockCacheControl = (block) => {
701
703
  if (!block || block.type === "thinking") return;
702
704
  const cacheControl = block.cache_control;
@@ -966,7 +968,7 @@ const prepareMessagesApiPayload = (payload, selectedModel) => {
966
968
  if (selectedModel?.capabilities.supports.adaptive_thinking && !disableThink) {
967
969
  payload.thinking = { type: "adaptive" };
968
970
  if (!hasThinking) payload.thinking.display = "summarized";
969
- if (payload.model === "claude-opus-4.7") payload.thinking.display = "summarized";
971
+ if (shouldSummarizeThinkingDisplayForModel(payload.model)) payload.thinking.display = "summarized";
970
972
  let effort = getReasoningEffortForModel(payload.model);
971
973
  if (effort === "none" || effort === "minimal") effort = "low";
972
974
  const reasoningEffort = selectedModel.capabilities.supports.reasoning_effort;
@@ -1884,7 +1886,11 @@ const PROVIDER_CONFIG_FIELDS = [
1884
1886
  "models",
1885
1887
  "adjustInputTokens"
1886
1888
  ];
1887
- const PROVIDER_AUTH_TYPES = ["authorization", "x-api-key"];
1889
+ const PROVIDER_AUTH_TYPES = [
1890
+ "authorization",
1891
+ "oauth2",
1892
+ "x-api-key"
1893
+ ];
1888
1894
  const PROVIDER_CONFIG_KEYS = new Set(PROVIDER_CONFIG_FIELDS);
1889
1895
  function isProviderAuthType(value) {
1890
1896
  return PROVIDER_AUTH_TYPES.includes(value);
@@ -4548,6 +4554,7 @@ async function handleProviderCountTokens(c) {
4548
4554
  }
4549
4555
  async function handleProviderCountTokensForProvider(c, options) {
4550
4556
  const { payload: anthropicPayload, provider } = options;
4557
+ normalizeSystemMessages(anthropicPayload);
4551
4558
  const providerConfig = resolveProviderConfig$2(c, provider);
4552
4559
  if (!providerConfig) return c.json({ error: {
4553
4560
  message: `Provider '${provider}' not found or disabled`,
@@ -4559,7 +4566,7 @@ async function handleProviderCountTokensForProvider(c, options) {
4559
4566
  } }, 400);
4560
4567
  const modelId = anthropicPayload.model.trim();
4561
4568
  const modelConfig = providerConfig.models?.[modelId];
4562
- const translationOptions = providerConfig.type === "openai-compatible" ? {
4569
+ const translationOptions = providerConfig.type === "openai-compatible" || providerConfig.type === "openai-responses" ? {
4563
4570
  supportPdf: modelConfig?.supportPdf,
4564
4571
  toolContentSupportType: modelConfig?.toolContentSupportType ?? []
4565
4572
  } : void 0;
@@ -4639,6 +4646,7 @@ async function countTokensViaAnthropic(c, payload) {
4639
4646
  async function handleCountTokens(c) {
4640
4647
  const anthropicPayload = await c.req.json();
4641
4648
  anthropicPayload.model = resolveModelAlias(anthropicPayload.model);
4649
+ normalizeSystemMessages(anthropicPayload);
4642
4650
  const providerModelAlias = resolveExistingProviderModelAlias(anthropicPayload.model, getProviderConfigResolver$1(c));
4643
4651
  if (providerModelAlias) {
4644
4652
  anthropicPayload.model = providerModelAlias.model;
@@ -4676,7 +4684,7 @@ async function handleCountTokens(c) {
4676
4684
  //#endregion
4677
4685
  //#region src/services/copilot/create-responses.ts
4678
4686
  const RESPONSES_WEBSOCKET_IDLE_TIMEOUT_MS = 6e4;
4679
- const createResponses = async (payload, { vision, initiator, upstreamRequestId, subagentMarker, sessionId, compactType, requestId, fetchImpl, transport = "http" }, account) => {
4687
+ const createResponses = async (payload, { vision, initiator, upstreamRequestId, subagentMarker, sessionId, compactType, requestId, fetchImpl, transport = "http", bridgeId }, account) => {
4680
4688
  const ctx = account ?? accountFromState();
4681
4689
  if (!ctx.copilotToken) throw new Error("Copilot token not found");
4682
4690
  const effectiveInitiator = resolveEffectiveInitiator(initiator, {
@@ -4696,7 +4704,9 @@ const createResponses = async (payload, { vision, initiator, upstreamRequestId,
4696
4704
  const stream = createPooledResponsesWebSocketStream(prepareResponsesWebSocketRequest(payload, headers, {
4697
4705
  copilotToken: ctx.copilotToken,
4698
4706
  requestId: requestId ?? upstreamRequestId ?? "missing-request-id",
4699
- subagentMarker
4707
+ sessionId,
4708
+ subagentMarker,
4709
+ bridgeId
4700
4710
  }), copilotBaseUrl(ctx));
4701
4711
  if (payload.stream) return stream;
4702
4712
  return await consumeResponsesWebSocketStream(stream);
@@ -4729,20 +4739,22 @@ const prepareResponsesWebSocketRequest = (payload, preparedHeaders, options) =>
4729
4739
  return {
4730
4740
  headers: copilotWebSocketHeaders(preparedHeaders),
4731
4741
  poolKey: buildResponsesWebSocketPoolKey(payload, options),
4732
- payload: buildResponsesWebSocketPayload(payload, initiator)
4742
+ payload: buildResponsesWebSocketPayload(payload, initiator),
4743
+ bridgeId: options.bridgeId
4733
4744
  };
4734
4745
  };
4735
- const buildResponsesWebSocketPoolKey = (payload, { copilotToken, requestId, subagentMarker }) => {
4746
+ const buildResponsesWebSocketPoolKey = (payload, { copilotToken, requestId, sessionId, subagentMarker }) => {
4736
4747
  const tokenFingerprint = copilotToken ? createHash("sha256").update(copilotToken).digest("hex").slice(0, 16) : "missing-token";
4737
4748
  const subagentKey = subagentMarker ? [
4738
4749
  subagentMarker.session_id,
4739
4750
  subagentMarker.agent_id,
4740
4751
  subagentMarker.agent_type
4741
4752
  ].join(":") : "main";
4753
+ const connectionAffinityKey = sessionId ?? requestId;
4742
4754
  return [
4743
4755
  tokenFingerprint,
4744
4756
  payload.model,
4745
- requestId,
4757
+ connectionAffinityKey,
4746
4758
  subagentKey
4747
4759
  ].map(encodePoolKeyPart).join("|");
4748
4760
  };
@@ -4797,6 +4809,7 @@ const getResponsesWebSocketRequestTarget = (request, baseUrl) => {
4797
4809
  const existing = responsesWebSocketPool.get(request.poolKey);
4798
4810
  if (existing && !existing.closed) {
4799
4811
  clearResponsesWebSocketIdleTimer(existing);
4812
+ existing.bridgeId = request.bridgeId;
4800
4813
  return {
4801
4814
  entry: existing,
4802
4815
  pooled: true
@@ -4817,13 +4830,16 @@ const createResponsesWebSocketEntry = (request, baseUrl) => {
4817
4830
  websocketPromise: openResponsesWebSocket({
4818
4831
  headers: request.headers,
4819
4832
  url: buildResponsesWebSocketUrl(baseUrl)
4820
- })
4833
+ }),
4834
+ bridgeId: request.bridgeId
4821
4835
  };
4822
4836
  entry.websocketPromise.then((websocket) => {
4823
4837
  websocket.addEventListener("close", () => {
4838
+ maybeCloseResponsesBridgeForReapedEntry(request.poolKey, entry);
4824
4839
  removeResponsesWebSocketPoolEntry(request.poolKey, entry);
4825
4840
  });
4826
4841
  websocket.addEventListener("error", () => {
4842
+ maybeCloseResponsesBridgeForReapedEntry(request.poolKey, entry);
4827
4843
  removeResponsesWebSocketPoolEntry(request.poolKey, entry);
4828
4844
  });
4829
4845
  }).catch(() => {
@@ -4831,6 +4847,10 @@ const createResponsesWebSocketEntry = (request, baseUrl) => {
4831
4847
  });
4832
4848
  return entry;
4833
4849
  };
4850
+ const maybeCloseResponsesBridgeForReapedEntry = (poolKey, entry) => {
4851
+ if (entry.bridgeId === void 0 || entry.requestCount > 0 || responsesWebSocketPool.get(poolKey) !== entry) return;
4852
+ closeResponsesBridge(entry.bridgeId);
4853
+ };
4834
4854
  const acquireResponsesWebSocketEntry = (poolKey, entry, pooled) => {
4835
4855
  clearResponsesWebSocketIdleTimer(entry);
4836
4856
  incrementResponsesWebSocketActiveRequestCount(poolKey);
@@ -4862,6 +4882,7 @@ const getReadyResponsesWebSocket = async (poolKey, entry, pooled) => {
4862
4882
  const scheduleResponsesWebSocketIdleClose = (poolKey, entry) => {
4863
4883
  clearResponsesWebSocketIdleTimer(entry);
4864
4884
  entry.idleTimer = setTimeout(() => {
4885
+ maybeCloseResponsesBridgeForReapedEntry(poolKey, entry);
4865
4886
  removeResponsesWebSocketPoolEntry(poolKey, entry);
4866
4887
  }, RESPONSES_WEBSOCKET_IDLE_TIMEOUT_MS);
4867
4888
  unrefTimer(entry.idleTimer);
@@ -5408,7 +5429,7 @@ const translateResponsesResultToAnthropic = (response, options) => {
5408
5429
  const usage = mapResponsesUsage(response);
5409
5430
  let anthropicContent = fallbackContentBlocks(response.output_text);
5410
5431
  if (contentBlocks.length > 0) anthropicContent = contentBlocks;
5411
- const stopReason = mapResponsesStopReason(response);
5432
+ const stopReason = mapResponsesStopReason(response, options);
5412
5433
  return {
5413
5434
  id: response.id,
5414
5435
  type: "message",
@@ -5422,6 +5443,7 @@ const translateResponsesResultToAnthropic = (response, options) => {
5422
5443
  };
5423
5444
  const mapOutputToAnthropicContent = (output, options) => {
5424
5445
  const contentBlocks = [];
5446
+ if (!output) output = [];
5425
5447
  for (const item of output) switch (item.type) {
5426
5448
  case "reasoning": {
5427
5449
  const thinkingText = extractReasoningText(item);
@@ -5562,9 +5584,10 @@ const fallbackContentBlocks = (outputText) => {
5562
5584
  text: outputText
5563
5585
  }];
5564
5586
  };
5565
- const mapResponsesStopReason = (response) => {
5587
+ const mapResponsesStopReason = (response, options) => {
5566
5588
  const { status, incomplete_details: incompleteDetails } = response;
5567
5589
  if (status === "completed") {
5590
+ if (!response.output || response.output.length === 0) return options?.hasToolCall ? "tool_use" : "end_turn";
5568
5591
  if (response.output.some((item) => item.type === "function_call" || item.type === "tool_search_call")) return "tool_use";
5569
5592
  return "end_turn";
5570
5593
  }
@@ -5992,7 +6015,7 @@ function closeThinkingBlockIfOpen(state, events) {
5992
6015
  }
5993
6016
  }
5994
6017
  //#endregion
5995
- //#region src/services/providers/anthropic-proxy.ts
6018
+ //#region src/services/providers/provider-proxy.ts
5996
6019
  const SHARED_FORWARDABLE_HEADERS = ["accept", "user-agent"];
5997
6020
  const ANTHROPIC_FORWARDABLE_HEADERS = ["anthropic-version", "anthropic-beta"];
5998
6021
  const STRIPPED_RESPONSE_HEADERS = [
@@ -6009,8 +6032,8 @@ const STRIPPED_RESPONSE_HEADERS = [
6009
6032
  ];
6010
6033
  function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
6011
6034
  const authHeaders = {};
6012
- if (providerConfig.authType === "authorization") authHeaders.authorization = `Bearer ${providerConfig.apiKey}`;
6013
- else authHeaders["x-api-key"] = providerConfig.apiKey;
6035
+ if (providerConfig.authType === "x-api-key") authHeaders["x-api-key"] = providerConfig.apiKey;
6036
+ else authHeaders.authorization = `Bearer ${providerConfig.apiKey}`;
6014
6037
  const headers = {
6015
6038
  "content-type": "application/json",
6016
6039
  accept: "application/json",
@@ -6027,10 +6050,10 @@ function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
6027
6050
  }
6028
6051
  return headers;
6029
6052
  }
6030
- function createProviderProxyResponse(upstreamResponse) {
6053
+ function createProviderProxyResponse(upstreamResponse, body) {
6031
6054
  const headers = new Headers(upstreamResponse.headers);
6032
6055
  for (const headerName of STRIPPED_RESPONSE_HEADERS) headers.delete(headerName);
6033
- return new Response(upstreamResponse.body, {
6056
+ return new Response(body ?? upstreamResponse.body, {
6034
6057
  headers,
6035
6058
  status: upstreamResponse.status,
6036
6059
  statusText: upstreamResponse.statusText
@@ -6162,6 +6185,25 @@ const applyModelDefaults = (payload, modelConfig) => {
6162
6185
  const applyMissingExtraBody = (payload, options) => {
6163
6186
  for (const [key, value] of Object.entries(options.extraBody ?? {})) if (!Object.hasOwn(payload, key)) payload[key] = value;
6164
6187
  };
6188
+ const getRequestThinkingBudget = (payload) => {
6189
+ const budget = payload.thinking?.budget_tokens;
6190
+ if (typeof budget !== "number" || !Number.isFinite(budget)) return;
6191
+ return budget;
6192
+ };
6193
+ const applyOpenAICompatibleThinkingBudget = (payload, source) => {
6194
+ const thinkingBudget = getRequestThinkingBudget(source);
6195
+ if (thinkingBudget !== void 0) {
6196
+ payload.thinking_budget = thinkingBudget;
6197
+ return;
6198
+ }
6199
+ if (payload.thinking_budget === void 0) delete payload.thinking_budget;
6200
+ };
6201
+ const applyOpenAICompatibleExtraBodyThinkingBudget = (payload, options) => {
6202
+ const { extraBody } = options;
6203
+ if (!extraBody || !Object.hasOwn(extraBody, "thinking_budget")) return;
6204
+ const rawPayload = payload;
6205
+ rawPayload.thinking_budget = extraBody.thinking_budget;
6206
+ };
6165
6207
  const handleOpenAICompatibleProviderMessages = async (c, options) => {
6166
6208
  const { instrumentation, modelConfig, payload, provider, providerConfig } = options;
6167
6209
  const openAIPayload = createOpenAICompatiblePayload(payload, modelConfig);
@@ -6194,6 +6236,7 @@ const createOpenAICompatiblePayload = (payload, modelConfig) => {
6194
6236
  supportPdf: modelConfig?.supportPdf,
6195
6237
  toolContentSupportType: modelConfig?.toolContentSupportType ?? []
6196
6238
  });
6239
+ applyOpenAICompatibleThinkingBudget(openAIPayload, payload);
6197
6240
  if (payload.top_k !== void 0) openAIPayload.top_k = payload.top_k;
6198
6241
  if (openAIPayload.stream) openAIPayload.stream_options = { include_usage: true };
6199
6242
  normalizeOpenAICompatibleReasoningContent(openAIPayload);
@@ -6202,6 +6245,7 @@ const createOpenAICompatiblePayload = (payload, modelConfig) => {
6202
6245
  source: payload
6203
6246
  });
6204
6247
  applyMissingExtraBody(openAIPayload, { extraBody: modelConfig?.extraBody });
6248
+ applyOpenAICompatibleExtraBodyThinkingBudget(openAIPayload, { extraBody: modelConfig?.extraBody });
6205
6249
  if (!Object.hasOwn(openAIPayload, "parallel_tool_calls")) openAIPayload.parallel_tool_calls = true;
6206
6250
  if (modelConfig?.contextCache !== false) applyOpenAICompatibleContextCache(openAIPayload);
6207
6251
  return openAIPayload;
@@ -6507,7 +6551,8 @@ const createResponsesStreamState = (options) => ({
6507
6551
  openBlocks: /* @__PURE__ */ new Set(),
6508
6552
  blockHasDelta: /* @__PURE__ */ new Set(),
6509
6553
  functionCallStateByOutputIndex: /* @__PURE__ */ new Map(),
6510
- toolSearchName: options?.toolSearchName ?? "mcp__tool_search__search"
6554
+ toolSearchName: options?.toolSearchName ?? "mcp__tool_search__search",
6555
+ hasToolCall: false
6511
6556
  });
6512
6557
  const translateResponsesStreamEvent = (rawEvent, state) => {
6513
6558
  switch (rawEvent.type) {
@@ -6755,7 +6800,10 @@ const handleResponseCompleted = (rawEvent, state) => {
6755
6800
  const events = new Array();
6756
6801
  closeAllOpenBlocks(state, events);
6757
6802
  state.responseStatus = response.status;
6758
- const anthropic = translateResponsesResultToAnthropic(response);
6803
+ const anthropic = translateResponsesResultToAnthropic(response, {
6804
+ hasToolCall: state.hasToolCall,
6805
+ toolSearchName: state.toolSearchName
6806
+ });
6759
6807
  events.push({
6760
6808
  type: "message_delta",
6761
6809
  delta: {
@@ -6887,6 +6935,7 @@ const buildErrorEvent = (message) => ({
6887
6935
  const getBlockKey = (outputIndex, contentIndex) => `${outputIndex}:${contentIndex}`;
6888
6936
  const openFunctionCallBlock = (state, params) => {
6889
6937
  const { outputIndex, toolCallId, name, events } = params;
6938
+ state.hasToolCall = true;
6890
6939
  let functionCallState = state.functionCallStateByOutputIndex.get(outputIndex);
6891
6940
  if (!functionCallState) {
6892
6941
  const blockIndex = state.nextContentBlockIndex;
@@ -6940,8 +6989,9 @@ const stringifyToolSearchArguments = (argumentsValue) => {
6940
6989
  return;
6941
6990
  }
6942
6991
  };
6992
+ const DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO = .9;
6943
6993
  const responsesUtilsDependencies = {
6944
- isResponsesApiContextManagementModel,
6994
+ isResponsesApiContextManagementEnabled,
6945
6995
  isResponsesApiWebSocketEnabled
6946
6996
  };
6947
6997
  const getResponsesRequestOptions = (payload) => {
@@ -6971,18 +7021,35 @@ const isAgentRole = (item) => {
6971
7021
  const hasVisionInput$1 = (payload) => {
6972
7022
  return getPayloadItems(payload).some((item) => containsVisionContent(item));
6973
7023
  };
6974
- const resolveResponsesCompactThreshold = (maxPromptTokens) => {
6975
- if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * .9);
6976
- return 5e4;
7024
+ "" + [
7025
+ "iVBORw0KGgoAAAANSUhEUgAAAGAAAAAgCAMAAADaHo1mAAADAFBMVEX///8fKTfR1dsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7026
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7027
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7028
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7029
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7030
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7031
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7032
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7033
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7034
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7035
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
7036
+ "AAAAAAAAAAAAAAAAAAAAAACae8QWAAAAvElEQVR42u1WixKAIAhj/f9Hdz2BXJiVed3pVSYtpgwsGSo3GaRq6wSd4F8EyIJx",
7037
+ "ydSUAMB8il51sHT2fiVQu8czguQwXWAyFvswIJhmoS9gmzYlcFiHj1aAgzcJVgCyguYhAhNZmMhYQZs1EJnnIAqKiuHjSrZT",
7038
+ "ucSQ4s8JkKDDIYr3IuR8vEWgqroKP9b1bYKk2wfgeVmqATQLXdXamsXdEKkz3QXEEeTTuWWImMhW6qci94/+hwSVf99HqVoD",
7039
+ "OAuj2SEAAAAASUVORK5CYII="
7040
+ ].join("");
7041
+ const resolveResponsesCompactThreshold = (maxPromptTokens, compactThresholdRatio = DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO) => {
7042
+ if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * compactThresholdRatio);
7043
+ return 2e5 * compactThresholdRatio;
6977
7044
  };
6978
7045
  const createCompactionContextManagement = (compactThreshold) => [{
6979
7046
  type: "compaction",
6980
7047
  compact_threshold: compactThreshold
6981
7048
  }];
6982
- const applyResponsesApiContextManagement = (payload, maxPromptTokens) => {
7049
+ const applyResponsesApiContextManagement = (payload, maxPromptTokens, compactThresholdRatio = DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO) => {
6983
7050
  if (payload.context_management !== void 0) return;
6984
- if (!responsesUtilsDependencies.isResponsesApiContextManagementModel(payload.model)) return;
6985
- payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens));
7051
+ if (!responsesUtilsDependencies.isResponsesApiContextManagementEnabled()) return;
7052
+ payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens, compactThresholdRatio));
6986
7053
  };
6987
7054
  const compactInputByLatestCompaction = (payload) => {
6988
7055
  if (!Array.isArray(payload.input) || payload.input.length === 0) return;
@@ -7085,7 +7152,7 @@ const buildMessagesHeaders = ({ ctx, enableVision, initiator, options, payload }
7085
7152
  };
7086
7153
  prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
7087
7154
  prepareForCompact(headers, options?.compactType);
7088
- if (shouldUseMessageProxyHeaders(payload)) prepareMessageProxyHeaders(headers);
7155
+ if (shouldUseMessageProxyHeaders(payload) && payload.model !== "claude-opus-4.8") prepareMessageProxyHeaders(headers);
7089
7156
  const anthropicBeta = buildAnthropicBetaHeader(options?.anthropicBetaHeader, payload.thinking, payload.model);
7090
7157
  if (anthropicBeta) headers["anthropic-beta"] = anthropicBeta;
7091
7158
  return headers;
@@ -7343,6 +7410,7 @@ async function handleCompletion(c) {
7343
7410
  const path = new URL(c.req.url, "http://local").pathname;
7344
7411
  const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c);
7345
7412
  const userAgent = c.req.header("user-agent") ?? void 0;
7413
+ normalizeSystemMessages(anthropicPayload);
7346
7414
  sanitizeIdeTools(anthropicPayload);
7347
7415
  debugJson(logger$3, "Anthropic request payload:", anthropicPayload);
7348
7416
  const markerInspection = inspectSubagentMarkerFromFirstUser(anthropicPayload);
@@ -7370,6 +7438,8 @@ async function handleCompletion(c) {
7370
7438
  const upstreamRequestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
7371
7439
  logger$3.debug("Generated request ID:", upstreamRequestId);
7372
7440
  const clientModel = anthropicPayload.model;
7441
+ anthropicPayload.model = resolveModelAlias(anthropicPayload.model);
7442
+ const routingModel = anthropicPayload.model;
7373
7443
  const streamRequested = Boolean(anthropicPayload.stream);
7374
7444
  const rawUserId = anthropicPayload.metadata?.user_id;
7375
7445
  const userId = typeof rawUserId === "string" ? rawUserId : void 0;
@@ -7401,9 +7471,9 @@ async function handleCompletion(c) {
7401
7471
  selectionReason: invalidSubagentMarkerSelectionReason
7402
7472
  });
7403
7473
  if (blockedResponse) return blockedResponse;
7404
- const endpointModel = findEndpointModel(clientModel);
7405
- const resolvedClientModel = endpointModel?.id ?? clientModel;
7406
- const affinityModelId = clientModel !== originalRequestModel ? findEndpointModel(originalRequestModel)?.id ?? originalRequestModel : void 0;
7474
+ const endpointModel = findEndpointModel(routingModel);
7475
+ const resolvedClientModel = endpointModel?.id ?? routingModel;
7476
+ const affinityModelId = routingModel !== originalRequestModel ? findEndpointModel(originalRequestModel)?.id ?? originalRequestModel : void 0;
7407
7477
  const useMessagesApi = isMessagesApiEnabled();
7408
7478
  const candidates = [];
7409
7479
  if (useMessagesApi) candidates.push({
@@ -8269,6 +8339,82 @@ providerMessageRoutes.post("/count_tokens", async (c) => {
8269
8339
  }
8270
8340
  });
8271
8341
  //#endregion
8342
+ //#region src/services/codex/get-models.ts
8343
+ const CODEX_MODELS = [
8344
+ {
8345
+ contextWindow: 1e5,
8346
+ id: "gpt-5.3-codex-spark",
8347
+ input: ["text"],
8348
+ maxTokens: 32e3,
8349
+ name: "GPT-5.3 Codex Spark"
8350
+ },
8351
+ {
8352
+ contextWindow: 4e5,
8353
+ id: "gpt-5.4",
8354
+ input: ["text", "image"],
8355
+ maxTokens: 128e3,
8356
+ name: "GPT-5.4"
8357
+ },
8358
+ {
8359
+ contextWindow: 4e5,
8360
+ id: "gpt-5.4-mini",
8361
+ input: ["text", "image"],
8362
+ maxTokens: 128e3,
8363
+ name: "GPT-5.4 mini"
8364
+ },
8365
+ {
8366
+ contextWindow: 272e3,
8367
+ id: "gpt-5.5",
8368
+ input: ["text", "image"],
8369
+ maxTokens: 128e3,
8370
+ name: "GPT-5.5"
8371
+ }
8372
+ ];
8373
+ function normalizeCodexModel(model) {
8374
+ const supportsVision = model.input.includes("image");
8375
+ return {
8376
+ capabilities: {
8377
+ family: "gpt",
8378
+ limits: {
8379
+ max_context_window_tokens: model.contextWindow,
8380
+ max_output_tokens: model.maxTokens,
8381
+ max_prompt_tokens: model.contextWindow
8382
+ },
8383
+ object: "model_capabilities",
8384
+ supports: {
8385
+ adaptive_thinking: true,
8386
+ parallel_tool_calls: true,
8387
+ reasoning_effort: [
8388
+ "minimal",
8389
+ "low",
8390
+ "medium",
8391
+ "high",
8392
+ "xhigh"
8393
+ ],
8394
+ streaming: true,
8395
+ tool_calls: true,
8396
+ vision: supportsVision
8397
+ },
8398
+ tokenizer: "o200k_base",
8399
+ type: "chat"
8400
+ },
8401
+ id: model.id,
8402
+ model_picker_enabled: true,
8403
+ name: model.name,
8404
+ object: "model",
8405
+ preview: false,
8406
+ supported_endpoints: ["/v1/messages", "/v1/responses"],
8407
+ vendor: "openai",
8408
+ version: "chatgpt-codex"
8409
+ };
8410
+ }
8411
+ function getModels() {
8412
+ return {
8413
+ object: "list",
8414
+ data: CODEX_MODELS.map((model) => normalizeCodexModel(model))
8415
+ };
8416
+ }
8417
+ //#endregion
8272
8418
  //#region src/routes/provider/models/route.ts
8273
8419
  const logger$2 = createHandlerLogger("provider-models-handler");
8274
8420
  const getProviderFetch = (c) => c.get("providerFetch") ?? fetch;
@@ -8284,6 +8430,14 @@ providerModelRoutes.get("/", async (c) => {
8284
8430
  message: `Provider '${provider}' not found or disabled`,
8285
8431
  type: "invalid_request_error"
8286
8432
  } }, 404);
8433
+ if (providerConfig.name === "codex") {
8434
+ const models = getModels();
8435
+ return c.json({
8436
+ object: "list",
8437
+ data: models.data,
8438
+ has_more: false
8439
+ });
8440
+ }
8287
8441
  const upstreamResponse = await forwardProviderModels(providerConfig, c.req.raw.headers, getProviderFetch(c));
8288
8442
  logger$2.debug("provider.models.response", {
8289
8443
  provider,
@@ -8414,6 +8568,7 @@ const handleResponses = async (c) => {
8414
8568
  const upstreamSessionId = getUUID(normalizedPromptCacheKey ?? headerSessionId ?? upstreamRequestId);
8415
8569
  request.upstreamRequestId = upstreamRequestId;
8416
8570
  request.upstreamSessionId = upstreamSessionId;
8571
+ const bridgeId = c.req.header("x-responses-bridge-id") ?? void 0;
8417
8572
  if (streamRequested) return handleStreamingResponses({
8418
8573
  c,
8419
8574
  store,
@@ -8426,7 +8581,8 @@ const handleResponses = async (c) => {
8426
8581
  initiator,
8427
8582
  premiumRemainingBefore,
8428
8583
  premiumUnlimitedBefore,
8429
- transport
8584
+ transport,
8585
+ bridgeId
8430
8586
  });
8431
8587
  return handleNonStreamingResponses({
8432
8588
  c,
@@ -8440,7 +8596,8 @@ const handleResponses = async (c) => {
8440
8596
  initiator,
8441
8597
  premiumRemainingBefore,
8442
8598
  premiumUnlimitedBefore,
8443
- transport
8599
+ transport,
8600
+ bridgeId
8444
8601
  });
8445
8602
  };
8446
8603
  async function observeRequestError(accountId, error, affinity) {
@@ -8548,7 +8705,7 @@ function extractUsageFromChunkData(data) {
8548
8705
  }
8549
8706
  }
8550
8707
  async function handleStreamingResponses(params) {
8551
- const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, premiumRemainingBefore, premiumUnlimitedBefore, transport } = params;
8708
+ const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, premiumRemainingBefore, premiumUnlimitedBefore, transport, bridgeId } = params;
8552
8709
  let response;
8553
8710
  try {
8554
8711
  response = await createResponses(payload, {
@@ -8557,7 +8714,8 @@ async function handleStreamingResponses(params) {
8557
8714
  upstreamRequestId: request.upstreamRequestId,
8558
8715
  sessionId: request.upstreamSessionId,
8559
8716
  requestId: request.requestId,
8560
- transport
8717
+ transport,
8718
+ bridgeId
8561
8719
  }, accountCtx);
8562
8720
  selection.confirmAffinity?.();
8563
8721
  } catch (error) {
@@ -8745,7 +8903,7 @@ async function streamResponsesAndLog(params) {
8745
8903
  }
8746
8904
  }
8747
8905
  async function handleNonStreamingResponses(params) {
8748
- const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, premiumRemainingBefore, premiumUnlimitedBefore, transport } = params;
8906
+ const { c, store, request, payload, selection, clientModel, accountCtx, vision, initiator, premiumRemainingBefore, premiumUnlimitedBefore, transport, bridgeId } = params;
8749
8907
  const { account, reservation, selectedModel, endpoint, costUnits } = selection;
8750
8908
  let usage = {};
8751
8909
  let errorState = { httpStatus: 200 };
@@ -8757,7 +8915,8 @@ async function handleNonStreamingResponses(params) {
8757
8915
  upstreamRequestId: request.upstreamRequestId,
8758
8916
  sessionId: request.upstreamSessionId,
8759
8917
  requestId: request.requestId,
8760
- transport
8918
+ transport,
8919
+ bridgeId
8761
8920
  }, accountCtx);
8762
8921
  if (isAsyncIterable$1(response)) throw new Error("Upstream returned a stream unexpectedly");
8763
8922
  selection.confirmAffinity?.();
@@ -8881,31 +9040,43 @@ usageRoute.get("/:accountIndex", async (c) => {
8881
9040
  });
8882
9041
  //#endregion
8883
9042
  //#region src/server.ts
8884
- const server = new Hono();
8885
- server.use(traceIdMiddleware);
8886
- server.use(logger());
8887
- server.use(cors());
8888
- server.use("*", createAuthMiddleware({
8889
- allowUnauthenticatedPaths: ["/"],
8890
- allowUnauthenticatedPathPrefixes: ["/admin", "/api/admin"]
8891
- }));
8892
- server.get("/", (c) => c.text("Server running"));
8893
- server.route("/chat/completions", completionRoutes);
8894
- server.route("/models", modelRoutes);
8895
- server.route("/embeddings", embeddingRoutes);
8896
- server.route("/usage", usageRoute);
8897
- server.route("/token", tokenRoute);
8898
- server.route("/responses", responsesRoutes);
8899
- server.route("/admin", adminRoutes);
8900
- server.route("/api/admin", adminApiRoutes);
8901
- server.route("/v1/chat/completions", completionRoutes);
8902
- server.route("/v1/models", modelRoutes);
8903
- server.route("/v1/embeddings", embeddingRoutes);
8904
- server.route("/v1/responses", responsesRoutes);
8905
- server.route("/v1/messages", messageRoutes);
8906
- server.route("/:provider/v1/messages", providerMessageRoutes);
8907
- server.route("/:provider/v1/models", providerModelRoutes);
9043
+ function createServer(options = {}) {
9044
+ const app = new Hono();
9045
+ const enableMcpHttp = options.enableMcpHttp ?? isMcpHttpEnabledFromEnv();
9046
+ app.use(traceIdMiddleware);
9047
+ app.use(logger());
9048
+ if (enableMcpHttp) {
9049
+ app.use(DEFAULT_MCP_HTTP_PATH, cors(mcpHttpCorsOptions));
9050
+ app.all(DEFAULT_MCP_HTTP_PATH, (c) => handleStreamableHttpMcpRequest(c.req.raw));
9051
+ } else app.all(DEFAULT_MCP_HTTP_PATH, (c) => c.json({ error: {
9052
+ type: "mcp_http_disabled",
9053
+ message: "MCP Streamable HTTP is disabled. Start with --enable-mcp-http to expose /mcp."
9054
+ } }, 404));
9055
+ app.use(cors());
9056
+ app.use("*", createAuthMiddleware({
9057
+ allowUnauthenticatedPaths: ["/", DEFAULT_MCP_HTTP_PATH],
9058
+ allowUnauthenticatedPathPrefixes: ["/admin", "/api/admin"]
9059
+ }));
9060
+ app.get("/", (c) => c.text("Server running"));
9061
+ app.route("/chat/completions", completionRoutes);
9062
+ app.route("/models", modelRoutes);
9063
+ app.route("/embeddings", embeddingRoutes);
9064
+ app.route("/usage", usageRoute);
9065
+ app.route("/token", tokenRoute);
9066
+ app.route("/responses", responsesRoutes);
9067
+ app.route("/admin", adminRoutes);
9068
+ app.route("/api/admin", adminApiRoutes);
9069
+ app.route("/v1/chat/completions", completionRoutes);
9070
+ app.route("/v1/models", modelRoutes);
9071
+ app.route("/v1/embeddings", embeddingRoutes);
9072
+ app.route("/v1/responses", responsesRoutes);
9073
+ app.route("/v1/messages", messageRoutes);
9074
+ app.route("/:provider/v1/messages", providerMessageRoutes);
9075
+ app.route("/:provider/v1/models", providerModelRoutes);
9076
+ return app;
9077
+ }
9078
+ createServer();
8908
9079
  //#endregion
8909
- export { server };
9080
+ export { createServer };
8910
9081
 
8911
- //# sourceMappingURL=server-DulP9mYd.js.map
9082
+ //# sourceMappingURL=server-DJ3_UGc4.js.map