github-router 0.3.282 → 0.3.288

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 (88) hide show
  1. package/README.md +8 -5
  2. package/dist/{attribution-settings-srL3gBR9.js → attribution-settings-CofaqSzw.js} +54 -15
  3. package/dist/attribution-settings-CofaqSzw.js.map +1 -0
  4. package/dist/{auth-VUL2Zxvw.js → auth-DG4vh8-F.js} +3 -3
  5. package/dist/{auth-VUL2Zxvw.js.map → auth-DG4vh8-F.js.map} +1 -1
  6. package/dist/browser-ext/manifest.json +1 -1
  7. package/dist/{check-usage-CcLdFPGr.js → check-usage-BqN7mBYv.js} +4 -4
  8. package/dist/{check-usage-CcLdFPGr.js.map → check-usage-BqN7mBYv.js.map} +1 -1
  9. package/dist/{claude-DJQjA5oQ.js → claude-CoZKRNB8.js} +25 -20
  10. package/dist/claude-CoZKRNB8.js.map +1 -0
  11. package/dist/{codex-BAXemWpJ.js → codex-y2OyLIdv.js} +5 -5
  12. package/dist/{codex-BAXemWpJ.js.map → codex-y2OyLIdv.js.map} +1 -1
  13. package/dist/{debug-CtzYWxpJ.js → debug-B5TjPTTH.js} +2 -2
  14. package/dist/{debug-CtzYWxpJ.js.map → debug-B5TjPTTH.js.map} +1 -1
  15. package/dist/engine-B5nVGH4b.js +2 -0
  16. package/dist/{gate-discovery-BwtiYKvW.js → gate-discovery-LQZ-enJa.js} +5 -5
  17. package/dist/{gate-discovery-BwtiYKvW.js.map → gate-discovery-LQZ-enJa.js.map} +1 -1
  18. package/dist/{get-copilot-usage-B-EDAqQb.js → get-copilot-usage-BjA0nyGR.js} +2 -2
  19. package/dist/{get-copilot-usage-B-EDAqQb.js.map → get-copilot-usage-BjA0nyGR.js.map} +1 -1
  20. package/dist/{internal-artifact-open-Dj5Nlq0L.js → internal-artifact-open-BskmUpnb.js} +2 -2
  21. package/dist/{internal-artifact-open-Dj5Nlq0L.js.map → internal-artifact-open-BskmUpnb.js.map} +1 -1
  22. package/dist/{internal-first-mate-guard-DMgHg2s6.js → internal-first-mate-guard-5XEHMaqy.js} +3 -3
  23. package/dist/{internal-first-mate-guard-DMgHg2s6.js.map → internal-first-mate-guard-5XEHMaqy.js.map} +1 -1
  24. package/dist/{internal-first-mate-guard-CQdXWjNz.js → internal-first-mate-guard-DHDQ6hFz.js} +1 -1
  25. package/dist/{internal-plan-review-DRFHET_B.js → internal-plan-review-BUuMx4ku.js} +3 -3
  26. package/dist/{internal-plan-review-DRFHET_B.js.map → internal-plan-review-BUuMx4ku.js.map} +1 -1
  27. package/dist/{internal-prompt-submit-f1LR2P2G.js → internal-prompt-submit-CQQ15xdO.js} +4 -4
  28. package/dist/{internal-prompt-submit-f1LR2P2G.js.map → internal-prompt-submit-CQQ15xdO.js.map} +1 -1
  29. package/dist/{internal-session-bind-DhZhxJ3T.js → internal-session-bind-D04W2yWI.js} +2 -2
  30. package/dist/{internal-session-bind-DhZhxJ3T.js.map → internal-session-bind-D04W2yWI.js.map} +1 -1
  31. package/dist/{internal-stop-hook-514RJeHO.js → internal-stop-hook-DSbaDb_m.js} +5 -5
  32. package/dist/{internal-stop-hook-514RJeHO.js.map → internal-stop-hook-DSbaDb_m.js.map} +1 -1
  33. package/dist/{internal-stop-review-BBsLcbPG.js → internal-stop-review-CdByyJLc.js} +2 -2
  34. package/dist/{internal-stop-review-BBsLcbPG.js.map → internal-stop-review-CdByyJLc.js.map} +1 -1
  35. package/dist/{internal-worker-guard-VucpClSi.js → internal-worker-guard-BIPN6Rv9.js} +2 -2
  36. package/dist/{internal-worker-guard-VucpClSi.js.map → internal-worker-guard-BIPN6Rv9.js.map} +1 -1
  37. package/dist/{internal-workspace-header-OYgHEnFt.js → internal-workspace-header-BKqejstG.js} +2 -2
  38. package/dist/{internal-workspace-header-OYgHEnFt.js.map → internal-workspace-header-BKqejstG.js.map} +1 -1
  39. package/dist/lifecycle-BTodQvn4.js +2 -0
  40. package/dist/lifecycle-C7JYNz-F.js +2 -0
  41. package/dist/{lifecycle-B7CHqKlF.js → lifecycle-DbM29FLK.js} +2 -2
  42. package/dist/{lifecycle-B7CHqKlF.js.map → lifecycle-DbM29FLK.js.map} +1 -1
  43. package/dist/{lifecycle-D-rL81tT.js → lifecycle-SXaWssN9.js} +2 -2
  44. package/dist/{lifecycle-D-rL81tT.js.map → lifecycle-SXaWssN9.js.map} +1 -1
  45. package/dist/main.js +17 -17
  46. package/dist/{mcp-workspace-header-ucs2SDST.js → mcp-workspace-header-DRCCWlOi.js} +2 -2
  47. package/dist/{mcp-workspace-header-ucs2SDST.js.map → mcp-workspace-header-DRCCWlOi.js.map} +1 -1
  48. package/dist/{models-C16mBK2M.js → models-Dz8d_SnI.js} +3 -3
  49. package/dist/{models-C16mBK2M.js.map → models-Dz8d_SnI.js.map} +1 -1
  50. package/dist/{orchestration-CtM6FYNx.js → orchestration-BrJwZxMN.js} +2 -2
  51. package/dist/{orchestration-CtM6FYNx.js.map → orchestration-BrJwZxMN.js.map} +1 -1
  52. package/dist/paths-CTr59UC6.js +2 -0
  53. package/dist/{paths-wLC0InjX.js → paths-D7_SAaIQ.js} +4 -4
  54. package/dist/{paths-wLC0InjX.js.map → paths-D7_SAaIQ.js.map} +1 -1
  55. package/dist/{peer-mcp-personas-l4P4s1fK.js → peer-mcp-personas-B5Wp6wIn.js} +837 -147
  56. package/dist/peer-mcp-personas-B5Wp6wIn.js.map +1 -0
  57. package/dist/{plan-review-hook-Lf9ISdF6.js → plan-review-hook-CVZsG9MZ.js} +3 -3
  58. package/dist/{plan-review-hook-Lf9ISdF6.js.map → plan-review-hook-CVZsG9MZ.js.map} +1 -1
  59. package/dist/{prompt-submit-hook-BlijaOn7.js → prompt-submit-hook-BW92FX2D.js} +3 -3
  60. package/dist/{prompt-submit-hook-BlijaOn7.js.map → prompt-submit-hook-BW92FX2D.js.map} +1 -1
  61. package/dist/{provision-DlT34zcf.js → provision-CUqPki1z.js} +4 -4
  62. package/dist/{provision-DlT34zcf.js.map → provision-CUqPki1z.js.map} +1 -1
  63. package/dist/{self-invocation-CKMjcA5F.js → self-invocation-CP_SOkrr.js} +2 -2
  64. package/dist/{self-invocation-CKMjcA5F.js.map → self-invocation-CP_SOkrr.js.map} +1 -1
  65. package/dist/{serve-orGUartp.js → serve-BASqoXb3.js} +42 -29
  66. package/dist/serve-BASqoXb3.js.map +1 -0
  67. package/dist/{server-setup-BRBe8gW4.js → server-setup-D5hilphf.js} +33 -213
  68. package/dist/server-setup-D5hilphf.js.map +1 -0
  69. package/dist/{start-sutbbkwc.js → start-Rfim4TeF.js} +3 -3
  70. package/dist/{start-sutbbkwc.js.map → start-Rfim4TeF.js.map} +1 -1
  71. package/dist/{stop-gate-hook-DgJ6sW8N.js → stop-gate-hook-DriRc9xN.js} +3 -3
  72. package/dist/{stop-gate-hook-DgJ6sW8N.js.map → stop-gate-hook-DriRc9xN.js.map} +1 -1
  73. package/dist/{stop-gate-policy-DG5yYWGn.js → stop-gate-policy-DMPanpoR.js} +2 -2
  74. package/dist/{stop-gate-policy-DG5yYWGn.js.map → stop-gate-policy-DMPanpoR.js.map} +1 -1
  75. package/dist/{token-CnlB0884.js → token-BGCjZwtj.js} +2 -2
  76. package/dist/{token-CnlB0884.js.map → token-BGCjZwtj.js.map} +1 -1
  77. package/dist/{worker-dispatch-4O3IWtP0.js → worker-dispatch-BCTMyNE-.js} +9 -5
  78. package/dist/{worker-dispatch-4O3IWtP0.js.map → worker-dispatch-BCTMyNE-.js.map} +1 -1
  79. package/package.json +1 -1
  80. package/dist/attribution-settings-srL3gBR9.js.map +0 -1
  81. package/dist/claude-DJQjA5oQ.js.map +0 -1
  82. package/dist/engine-BvLgh1QI.js +0 -2
  83. package/dist/lifecycle-CbmHMMSD.js +0 -2
  84. package/dist/lifecycle-DTcZwa7U.js +0 -2
  85. package/dist/paths-CV9K7Xqm.js +0 -2
  86. package/dist/peer-mcp-personas-l4P4s1fK.js.map +0 -1
  87. package/dist/serve-orGUartp.js.map +0 -1
  88. package/dist/server-setup-BRBe8gW4.js.map +0 -1
@@ -1,8 +1,8 @@
1
- import { B as repairRejectedThinkingHistory, Ct as parseJsonOrDiagnose, F as injectAdvisorTool, G as readIteratorWithTimeout, Gt as upstreamAllowH2, H as buildOpenAIErrorEvent, Ht as UPSTREAM_INACTIVITY_TIMEOUT_MS, I as isAdvisorRequested, It as toolbeltPathOverride, J as handleMcpPost, Jt as withInstallLock, K as relayAnthropicStream, Kt as upstreamMaxConnections, L as formatThinkingRepairDecline, M as ADVISOR_INTERNAL_TOOL_NAME, N as ADVISOR_TOOL_INSTRUCTIONS, P as buildAdvisorStream, R as rememberThinkingHistoryRepair, St as readResponseBodyCapped, T as toolbeltEnabled, U as isControllerClosedError, Ut as generateRandomPort, V as buildAnthropicErrorEvent, Vt as UPSTREAM_FETCH_TIMEOUT_MS, W as logStreamError, Y as agentToolsEnabled, _t as resolveMcpToolTimeoutMs, bt as createChatCompletions, dt as shimDefaultsToXhigh, ft as countTokens, gt as warnOnTokenPriceDrift, ht as assembleResponsesPayload, j as searchWeb, jt as provisionTreeSitterAssets, mt as getTokenCount, pt as createMessages, q as handleMcpDelete, qt as withOneMSuffix, r as assertMcpToolSurfaceConsistent, vt as pickEndpoint, xt as MAX_RESPONSE_BODY_BYTES, yt as createResponses, z as repairKnownThinkingHistory } from "./peer-mcp-personas-l4P4s1fK.js";
1
+ import { $ as handleMcpDelete, $t as generateRandomPort, At as readResponseBodyCapped, B as rememberThinkingHistoryRepair, Ct as getTokenCount, Dt as createResponses, Et as resolveMcpToolTimeoutMs, F as injectAdvisorTool, G as isControllerClosedError, H as repairRejectedThinkingHistory, I as isAdvisorRequested, J as relayAnthropicStream, K as logStreamError, Kt as BUDGET_SMALL_FAST_SLUG, L as resolveAdvisorEffort, M as ADVISOR_INTERNAL_TOOL_NAME, N as ADVISOR_TOOL_INSTRUCTIONS, Ot as createChatCompletions, P as buildAdvisorStream, Q as clampEffort, Qt as UPSTREAM_INACTIVITY_TIMEOUT_MS, R as resolveAdvisorModel, St as createMessages, T as toolbeltEnabled, Tt as warnOnTokenPriceDrift, U as buildAnthropicErrorEvent, V as repairKnownThinkingHistory, W as buildOpenAIErrorEvent, Wt as toolbeltPathOverride, X as UNKNOWN_EFFORT_ANCHOR, Y as EFFORT_ORDER, Z as bucketEffort, Zt as UPSTREAM_FETCH_TIMEOUT_MS, an as classifyMessagesRoute, bt as shimDefaultsToXhigh, cn as withInstallLock, en as isBudgetClaudeLead, et as handleMcpPost, in as upstreamMaxConnections, j as searchWeb, jt as parseJsonOrDiagnose, kt as MAX_RESPONSE_BODY_BYTES, nt as agentToolsEnabled, on as withOneMSuffix, pt as resolveGeminiReviewModel, q as readIteratorWithTimeout, r as assertMcpToolSurfaceConsistent, rn as upstreamAllowH2, sn as withOneMSuffixForLead, wt as assembleResponsesPayload, xt as countTokens, z as formatThinkingRepairDecline, zt as provisionTreeSitterAssets } from "./peer-mcp-personas-B5Wp6wIn.js";
2
2
  import { t as getPackageVersion } from "./version-C8x2hQrZ.js";
3
- import { i as ensurePaths, t as PATHS } from "./paths-wLC0InjX.js";
4
- import { A as state, T as copilotHeaders, _ as forwardError, a as cacheCopilotVersion, c as filterBetaHeader, d as resolveModel, f as sleep, g as HTTPError, i as tryRefreshAndRetry, l as isNullish, n as setupGitHubAgentToken, o as cacheModels, r as setupGitHubToken, s as cacheVSCodeVersion, t as setupCopilotToken, w as copilotBaseUrl, y as fetchWithTransientRetry } from "./token-CnlB0884.js";
5
- import { t as getCopilotUsage } from "./get-copilot-usage-B-EDAqQb.js";
3
+ import { i as ensurePaths, t as PATHS } from "./paths-D7_SAaIQ.js";
4
+ import { A as state, T as copilotHeaders, _ as forwardError, a as cacheCopilotVersion, c as filterBetaHeader, d as resolveModel, f as sleep, g as HTTPError, i as tryRefreshAndRetry, l as isNullish, n as setupGitHubAgentToken, o as cacheModels, r as setupGitHubToken, s as cacheVSCodeVersion, t as setupCopilotToken, w as copilotBaseUrl, y as fetchWithTransientRetry } from "./token-BGCjZwtj.js";
5
+ import { t as getCopilotUsage } from "./get-copilot-usage-BjA0nyGR.js";
6
6
  import { a as resolveExecutable, n as killManagedTree, o as runCommandCapture, r as parseBoolEnv, s as runCommandVoid } from "./exec-y8C_MU8A.js";
7
7
  import consola from "consola";
8
8
  import * as fs$2 from "node:fs";
@@ -1429,7 +1429,7 @@ function collectToolFieldKeys(body) {
1429
1429
  //#endregion
1430
1430
  //#region package.json
1431
1431
  var name = "github-router";
1432
- var version = "0.3.282";
1432
+ var version = "0.3.288";
1433
1433
  //#endregion
1434
1434
  //#region src/lib/approval.ts
1435
1435
  const awaitApproval = async () => {
@@ -2775,98 +2775,6 @@ function anthropicSseStreamFromEvents(events, opts) {
2775
2775
  });
2776
2776
  }
2777
2777
  //#endregion
2778
- //#region src/lib/reasoning-effort.ts
2779
- /**
2780
- * Reasoning-effort bucketing + clamping shared by the `/v1/messages` handler
2781
- * (adaptive-thinking translation) and the Anthropic-translation shim
2782
- * (thinking-budget → Responses `reasoning.effort`).
2783
- *
2784
- * Extracted from `src/routes/messages/handler.ts` so a `~/lib/*` module can
2785
- * depend on it without importing route code (and without forming a
2786
- * handler → shim → handler import cycle). `handler.ts` re-exports these for
2787
- * backward compatibility with existing imports/tests.
2788
- */
2789
- /**
2790
- * Copilot's reasoning-effort tiers, lowest to highest.
2791
- *
2792
- * Both ends were added after the fact and both are load-bearing:
2793
- *
2794
- * `none` is advertised by every gpt-5.x entry in the live catalog. While it was
2795
- * missing here it was treated as an UNRECOGNIZED value, so a client asking for
2796
- * the MINIMUM on a model that does not offer it (gemini advertises only
2797
- * low/medium/high) was anchored at the unknown-value tier and clamped to
2798
- * `high` — the maximum. Listing it makes the clamp resolve to `low` instead,
2799
- * which is what "nearest supported tier" should always have meant.
2800
- *
2801
- * `max` is advertised by `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`,
2802
- * `claude-opus-5` and the 4.7/4.8 Opus lines, and Claude Code's effort picker
2803
- * offers it for any model whose entry allows it. Listing it lets an explicit
2804
- * selection pass through, and lets `clampEffort` land on it for a model that
2805
- * advertises nothing lower.
2806
- *
2807
- * `bucketEffort` deliberately reaches neither end — see below.
2808
- */
2809
- const EFFORT_ORDER = [
2810
- "none",
2811
- "low",
2812
- "medium",
2813
- "high",
2814
- "xhigh",
2815
- "max"
2816
- ];
2817
- /** Anchor for an effort value that is not a recognized tier at all.
2818
- *
2819
- * Deliberately NOT the top of `EFFORT_ORDER`. Callers reach this only when the
2820
- * incoming value is unrecognized, which is a guess — and resolving a guess to
2821
- * the most expensive tier a model advertises would silently spend more than the
2822
- * caller could have meant. Anchoring here and clamping DOWN keeps the behavior
2823
- * identical to before `max` joined the ladder, while `max` stays reachable by
2824
- * explicit, valid selection. */
2825
- const UNKNOWN_EFFORT_ANCHOR = "xhigh";
2826
- /**
2827
- * Bucket a thinking budget into a Copilot reasoning-effort string.
2828
- * `<2000`→low, `<8000`→medium, `<24000`→high, else→xhigh.
2829
- * Defaults missing/non-numeric budgets to 8000 ("high").
2830
- *
2831
- * The ceiling stays at `xhigh` even though `max` exists: Anthropic's
2832
- * `budget_tokens` is unbounded above, so any threshold chosen for a `max`
2833
- * bucket would silently re-tier existing callers whose budgets already map to
2834
- * `xhigh`. `max` is reachable only by explicit selection
2835
- * (`output_config.effort`), which is an unambiguous request rather than an
2836
- * inference from a token count.
2837
- */
2838
- function bucketEffort(budget) {
2839
- const n = typeof budget === "number" && Number.isFinite(budget) ? budget : 8e3;
2840
- if (n < 2e3) return "low";
2841
- if (n < 8e3) return "medium";
2842
- if (n < 24e3) return "high";
2843
- return "xhigh";
2844
- }
2845
- /**
2846
- * Clamp a bucketed effort to the closest value in `supported`. Ties resolve to
2847
- * the lower-tier option (per EFFORT_ORDER).
2848
- *
2849
- * Iterates EFFORT_ORDER (canonical low→xhigh) so the first match on a given
2850
- * distance is always the lower-tier value, regardless of input order in
2851
- * `supported`.
2852
- */
2853
- function clampEffort(bucketed, supported) {
2854
- if (supported.includes(bucketed)) return bucketed;
2855
- const targetIdx = EFFORT_ORDER.indexOf(bucketed);
2856
- let best;
2857
- let bestDist = Infinity;
2858
- for (let i = 0; i < EFFORT_ORDER.length; i++) {
2859
- const value = EFFORT_ORDER[i];
2860
- if (!supported.includes(value)) continue;
2861
- const dist = Math.abs(i - targetIdx);
2862
- if (dist < bestDist) {
2863
- bestDist = dist;
2864
- best = value;
2865
- }
2866
- }
2867
- return best ?? bucketed;
2868
- }
2869
- //#endregion
2870
2778
  //#region src/lib/anthropic-translate/anthropic-request.ts
2871
2779
  /**
2872
2780
  * Steering appended to `instructions` for shim-routed (non-Claude) models when
@@ -3151,7 +3059,8 @@ function parseDisableParallelToolUse(toolChoice) {
3151
3059
  function defaultReasoningEffort(model) {
3152
3060
  const supported = model?.capabilities?.supports?.reasoning_effort;
3153
3061
  if (!(Array.isArray(supported) && supported.length > 0)) return void 0;
3154
- return clampEffort(parseBoolEnv(process.env.GH_ROUTER_FRONTIER_XHIGH_DEFAULT) === true && model?.id != null && shimDefaultsToXhigh(model.id) && supported.includes("xhigh") ? "xhigh" : "high", supported);
3062
+ const wantXhigh = parseBoolEnv(process.env.GH_ROUTER_FRONTIER_XHIGH_DEFAULT) === true && model?.id != null && shimDefaultsToXhigh(model.id) && supported.includes("xhigh");
3063
+ return clampEffort(wantXhigh ? "xhigh" : "high", supported);
3155
3064
  }
3156
3065
  /**
3157
3066
  * Map Anthropic `thinking` to a Responses reasoning effort, clamped to the
@@ -3969,108 +3878,6 @@ async function* synthAnthropicFromResponses(upstream, opts) {
3969
3878
  q.length = 0;
3970
3879
  }
3971
3880
  //#endregion
3972
- //#region src/lib/anthropic-translate/classifier.ts
3973
- /**
3974
- * Routing classifier for `POST /v1/messages`.
3975
- *
3976
- * Claude Code speaks the Anthropic Messages wire format. Copilot only serves
3977
- * Claude models on its native `/v1/messages` endpoint; a gpt/gemini request
3978
- * sent there 400s. This classifier decides, from the RESOLVED model id and its
3979
- * catalog metadata, whether a request stays on the native passthrough
3980
- * (`createMessages`) or is diverted to the translation shim.
3981
- *
3982
- * Non-regression is the whole point — every Claude model (opus / sonnet / haiku /
3983
- * any `claude-*` or Anthropic-vendored id) MUST return "claude-passthrough" so
3984
- * its bytes reach `createMessages` unchanged — even if future catalog metadata
3985
- * were to (wrongly) advertise a `/responses` endpoint for it. The Claude check
3986
- * is therefore keyed off identity (id / vendor / family), NOT the endpoint.
3987
- *
3988
- * Non-Claude models are diverted to the translation shim by the endpoint the
3989
- * catalog says they serve: `/responses` models (gpt-5.5, gpt-5.3-codex, …) take
3990
- * the Responses path (`responses-shim`), `/chat/completions` models (gemini,
3991
- * and any chat-default model) take the chat path (`chat-shim`). The decision is
3992
- * derived from `pickEndpoint` (catalog `supported_endpoints`), never a
3993
- * hardcoded slug list, so it generalizes. Copilot only serves Claude models on
3994
- * its native `/v1/messages`, so diverting every non-Claude model to a shim is
3995
- * correct — a non-Claude request sent to `/v1/messages` would 400.
3996
- */
3997
- /**
3998
- * Match "claude"/"anthropic" as a delimiter-bounded segment anywhere in a model
3999
- * id: at the start, or after a `/ _ . : -` path/version delimiter, and followed
4000
- * by end-of-string, another such delimiter, or a digit. This catches catalog
4001
- * aliases like `github/claude-3-7-sonnet` or `anthropic/…` whose vendor is
4002
- * "github" and whose family is empty — where the token only surfaces mid-id —
4003
- * while NOT firing on incidental substrings like `notclaude`. Deliberately
4004
- * over-inclusive at the boundaries: we fail CLOSED toward Claude (→ passthrough)
4005
- * so a real Claude model can never be diverted to the non-Claude shim.
4006
- */
4007
- const CLAUDE_ID_RE = /(^|[/_.:-])(claude|anthropic)(?=$|[/_.:-]|\d)/i;
4008
- /**
4009
- * True when the target is a Claude / Anthropic model. Matches on any of:
4010
- * catalog vendor containing "anthropic", capability family containing "claude",
4011
- * or a Claude/anthropic path-segment (see `CLAUDE_ID_RE`) in ANY id we hold —
4012
- * the resolved id (`modelId`), the pre-resolution request id (`originalModelId`),
4013
- * or the catalog entry's own id (`model.id`). Conservative by design: when in
4014
- * doubt it returns true so a Claude request can never be diverted to the shim.
4015
- */
4016
- function isClaudeModel(modelId, model, originalModelId) {
4017
- if (model) {
4018
- if ((model.vendor?.toLowerCase() ?? "").includes("anthropic")) return true;
4019
- if ((model.capabilities?.family?.toLowerCase() ?? "").includes("claude")) return true;
4020
- }
4021
- return [
4022
- modelId,
4023
- originalModelId,
4024
- model?.id
4025
- ].some((id) => typeof id === "string" && CLAUDE_ID_RE.test(id));
4026
- }
4027
- /**
4028
- * Decide the route for a resolved model id + its catalog entry.
4029
- *
4030
- * - No model id, or a Claude model → "claude-passthrough" (existing behaviour).
4031
- * - A non-Claude model whose catalog endpoint is `/responses` → "responses-shim".
4032
- * - A non-Claude model whose catalog endpoint is `/chat/completions` (gemini and
4033
- * any chat-default model) → "chat-shim".
4034
- * - A non-Claude model absent from the catalog (so we can't confirm an endpoint)
4035
- * → "claude-passthrough" (unchanged; we don't divert what we can't classify).
4036
- * - A non-Claude model that IS in the catalog and serves NEITHER of the two shim
4037
- * endpoints (`pickEndpoint` → undefined) → "claude-passthrough" as well.
4038
- *
4039
- * Those last two land on the same route but are NOT the same answer, and the
4040
- * coincidence is deliberate rather than a collapsed default (contrast
4041
- * `resolveEndpointForModelId`, whose callers must tell them apart because
4042
- * guessing there produces an opaque upstream 400). Here neither shim is even a
4043
- * candidate: a shim can only speak `/responses` or `/chat/completions`, so
4044
- * diverting a model that serves neither would 400 just as surely. Passthrough
4045
- * is the better default because it is sometimes RIGHT — a non-Claude catalog
4046
- * model advertising `/v1/messages` is served by exactly the endpoint
4047
- * passthrough uses. It also preserves this module's fail-CLOSED-toward-Claude
4048
- * invariant: an unclassifiable model is never diverted.
4049
- *
4050
- * KNOWN GAP (audited, deliberately not fixed here): a non-Claude model serving
4051
- * only something we cannot speak at all (say `/embeddings`) also lands on
4052
- * passthrough and will still 400 upstream — `logEndpointMismatch(modelId,
4053
- * "/v1/messages")` logs it at the passthrough seam, but no local error is
4054
- * raised. Closing that needs a change in `src/routes/messages/handler.ts`,
4055
- * which this seam does not own. It is strictly narrower than the defect fixed
4056
- * in `resolveEndpointForModelId`: no such model is reachable as a Claude Code
4057
- * `/v1/messages` target today, whereas the plan worker's `claude-opus-5`
4058
- * default is.
4059
- *
4060
- * `originalModelId` is the optional pre-resolution request id; when supplied it
4061
- * is checked for Claude-likeness alongside the resolved id so an alias that
4062
- * resolves to a non-Claude-looking id can't slip past.
4063
- */
4064
- function classifyMessagesRoute(modelId, model, originalModelId) {
4065
- if (!modelId) return "claude-passthrough";
4066
- if (isClaudeModel(modelId, model, originalModelId)) return "claude-passthrough";
4067
- if (!model) return "claude-passthrough";
4068
- const endpoint = pickEndpoint(model);
4069
- if (endpoint === "responses") return "responses-shim";
4070
- if (endpoint === "chat") return "chat-shim";
4071
- return "claude-passthrough";
4072
- }
4073
- //#endregion
4074
3881
  //#region src/lib/anthropic-translate/index.ts
4075
3882
  const STREAM_HEADERS = {
4076
3883
  "content-type": "text/event-stream",
@@ -4536,11 +4343,15 @@ async function handleCompletion(c) {
4536
4343
  parsedBase = JSON.parse(nativeBody);
4537
4344
  } catch {}
4538
4345
  const initialConversation = Array.isArray(parsedBase.messages) ? parsedBase.messages : [];
4346
+ const advisorChoice = resolveAdvisorModel(originalModel);
4539
4347
  return new Response(buildAdvisorStream({
4540
4348
  firstResponse: response,
4541
4349
  initialConversation,
4542
4350
  baseBody: parsedBase,
4543
4351
  requestHeaders,
4352
+ advisorModel: advisorChoice.model,
4353
+ advisorEscalated: advisorChoice.escalated,
4354
+ advisorEffort: resolveAdvisorEffort(rawBody, advisorChoice.model),
4544
4355
  externalAborter: advisorAborter
4545
4356
  }), {
4546
4357
  status: response.status,
@@ -4649,7 +4460,8 @@ function clampOutputConfigEffortInPlace(body, model) {
4649
4460
  const current = oc.effort;
4650
4461
  if (typeof current !== "string") return false;
4651
4462
  if (supported.includes(current)) return false;
4652
- const clamped = clampEffort(EFFORT_ORDER.includes(current) ? current : UNKNOWN_EFFORT_ANCHOR, supported);
4463
+ const bucketed = EFFORT_ORDER.includes(current) ? current : UNKNOWN_EFFORT_ANCHOR;
4464
+ const clamped = clampEffort(bucketed, supported);
4653
4465
  if (clamped === current) return false;
4654
4466
  oc.effort = clamped;
4655
4467
  return true;
@@ -5833,8 +5645,8 @@ function parseSharedArgs(args) {
5833
5645
  * agent loop runs on them through the `/v1/messages` translation shim
5834
5646
  * (`src/lib/anthropic-translate/*`, branched in `routes/messages/handler.ts`)
5835
5647
  * that forwards non-Claude targets to Copilot `/responses` (gpt) or
5836
- * `/chat/completions` (gemini). The exact gemini id is
5837
- * `gemini-3.1-pro-preview` (preview slug NOT `gemini-3.1-pro`).
5648
+ * `/chat/completions` (gemini). The Gemini review row prefers
5649
+ * `gemini-3.1-pro-preview` and degrades to `gemini-3.7-flash`.
5838
5650
  *
5839
5651
  * Display labels only: the gateway-model cache schema Claude Code reads is
5840
5652
  * `{id, display_name?}` per model — there is NO per-model context-window
@@ -5858,10 +5670,6 @@ const NATIVE_NON_CLAUDE_MODELS = [
5858
5670
  {
5859
5671
  id: "gemini-3.5-flash",
5860
5672
  displayName: "Gemini 3.5 Flash"
5861
- },
5862
- {
5863
- id: "gemini-3.1-pro-preview",
5864
- displayName: "Gemini 3.1 Pro (preview)"
5865
5673
  }
5866
5674
  ];
5867
5675
  /**
@@ -5886,7 +5694,13 @@ function nativeSelectableModelsInCatalog() {
5886
5694
  const catalog = state.models?.data;
5887
5695
  if (!catalog || catalog.length === 0) return [];
5888
5696
  const present = new Set(catalog.map((m) => m.id));
5889
- return NATIVE_NON_CLAUDE_MODELS.filter((m) => present.has(m.id)).map((m) => ({
5697
+ const models = NATIVE_NON_CLAUDE_MODELS.filter((m) => present.has(m.id));
5698
+ const geminiReviewModel = resolveGeminiReviewModel();
5699
+ if (geminiReviewModel) models.push({
5700
+ id: geminiReviewModel,
5701
+ displayName: geminiReviewModel === "gemini-3.7-flash" ? "Gemini 3.7 Flash" : "Gemini 3.1 Pro (preview)"
5702
+ });
5703
+ return models.map((m) => ({
5890
5704
  id: withOneMSuffix(m.id),
5891
5705
  display_name: m.displayName
5892
5706
  }));
@@ -6020,10 +5834,16 @@ function getClaudeCodeEnvVars(serverUrl, model) {
6020
5834
  const mcpToolTimeoutMs = String(resolveMcpToolTimeoutMs());
6021
5835
  if (process.env.MCP_TIMEOUT === void 0) vars.MCP_TIMEOUT = mcpToolTimeoutMs;
6022
5836
  if (process.env.MCP_TOOL_TIMEOUT === void 0) vars.MCP_TOOL_TIMEOUT = mcpToolTimeoutMs;
6023
- if (process.env.ANTHROPIC_SMALL_FAST_MODEL === void 0) vars.ANTHROPIC_SMALL_FAST_MODEL = "claude-sonnet-5";
6024
- if (process.env.ANTHROPIC_DEFAULT_SONNET_MODEL === void 0) vars.ANTHROPIC_DEFAULT_SONNET_MODEL = "claude-sonnet-5";
6025
- if (process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL === void 0) vars.ANTHROPIC_DEFAULT_HAIKU_MODEL = "claude-sonnet-5";
6026
- if (process.env.ANTHROPIC_DEFAULT_OPUS_MODEL === void 0) vars.ANTHROPIC_DEFAULT_OPUS_MODEL = "claude-opus-5";
5837
+ const smallFastModel = isBudgetClaudeLead(model) && (state.models?.data?.some((m) => m.id === "claude-haiku-4.5") ?? false) ? BUDGET_SMALL_FAST_SLUG : "claude-sonnet-5";
5838
+ if (process.env.ANTHROPIC_SMALL_FAST_MODEL === void 0) vars.ANTHROPIC_SMALL_FAST_MODEL = smallFastModel;
5839
+ const seedTierRow = (modelKey, nameKey, bareSlug) => {
5840
+ if (process.env[modelKey] !== void 0) return;
5841
+ vars[modelKey] = withOneMSuffixForLead(bareSlug);
5842
+ if (process.env[nameKey] === void 0) vars[nameKey] = bareSlug;
5843
+ };
5844
+ seedTierRow("ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME", "claude-sonnet-5");
5845
+ seedTierRow("ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME", smallFastModel);
5846
+ seedTierRow("ANTHROPIC_DEFAULT_OPUS_MODEL", "ANTHROPIC_DEFAULT_OPUS_MODEL_NAME", "claude-opus-5");
6027
5847
  if (process.env.CLAUDE_CODE_PLAN_V2_AGENT_COUNT === void 0) vars.CLAUDE_CODE_PLAN_V2_AGENT_COUNT = "7";
6028
5848
  for (const key of [
6029
5849
  "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL",
@@ -6063,4 +5883,4 @@ function getCodexEnvVars(serverUrl) {
6063
5883
  //#endregion
6064
5884
  export { sharedServerArgs as a, listModelsForEndpoint as c, checkClaudeVersion as d, updateClaude as f, setupAndServe as i, enableFileLogging as l, getCodexEnvVars as n, startKeepAwake as o, parseSharedArgs as r, stopKeepAwake as s, getClaudeCodeEnvVars as t, runSelfUpdate as u };
6065
5885
 
6066
- //# sourceMappingURL=server-setup-BRBe8gW4.js.map
5886
+ //# sourceMappingURL=server-setup-D5hilphf.js.map