github-router 0.3.315 → 0.3.317

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 (105) hide show
  1. package/dist/{aic-ledger-BS47yb_C.js → aic-ledger-DY03LbBM.js} +2 -2
  2. package/dist/{aic-ledger-BS47yb_C.js.map → aic-ledger-DY03LbBM.js.map} +1 -1
  3. package/dist/{attribution-settings-DXmmyuEE.js → attribution-settings-D6dAkP4e.js} +120 -21
  4. package/dist/attribution-settings-D6dAkP4e.js.map +1 -0
  5. package/dist/{auth-D8t41c5D.js → auth-Iun7ftd8.js} +4 -4
  6. package/dist/{auth-D8t41c5D.js.map → auth-Iun7ftd8.js.map} +1 -1
  7. package/dist/browser-ext/manifest.json +1 -1
  8. package/dist/{check-usage-BpBKOjGZ.js → check-usage-1c-0z3iy.js} +4 -4
  9. package/dist/{check-usage-BpBKOjGZ.js.map → check-usage-1c-0z3iy.js.map} +1 -1
  10. package/dist/{claude-Cmmu3-cL.js → claude-aZ6OaFP5.js} +178 -49
  11. package/dist/claude-aZ6OaFP5.js.map +1 -0
  12. package/dist/{codex-DqTKKoEx.js → codex-PTdWu7er.js} +6 -6
  13. package/dist/codex-PTdWu7er.js.map +1 -0
  14. package/dist/{copilot-discount-IbXR5A28.js → copilot-discount-C3jx9Q-o.js} +2 -2
  15. package/dist/{copilot-discount-IbXR5A28.js.map → copilot-discount-C3jx9Q-o.js.map} +1 -1
  16. package/dist/{debug-CA7pg8V9.js → debug-CDyXUPcC.js} +2 -2
  17. package/dist/{debug-CA7pg8V9.js.map → debug-CDyXUPcC.js.map} +1 -1
  18. package/dist/engine-D5GNXylB.js +2 -0
  19. package/dist/{gate-discovery-CPk6Z8yc.js → gate-discovery-B17pvgE0.js} +5 -5
  20. package/dist/{gate-discovery-CPk6Z8yc.js.map → gate-discovery-B17pvgE0.js.map} +1 -1
  21. package/dist/{get-copilot-usage-FSQE8szQ.js → get-copilot-usage-BWCAzmSc.js} +3 -3
  22. package/dist/{get-copilot-usage-FSQE8szQ.js.map → get-copilot-usage-BWCAzmSc.js.map} +1 -1
  23. package/dist/hooks.mjs +125 -117
  24. package/dist/hooks.sha256 +1 -1
  25. package/dist/{internal-aic-status-BN0xRLSF.js → internal-aic-status-BiblmImt.js} +13 -6
  26. package/dist/{internal-aic-status-BN0xRLSF.js.map → internal-aic-status-BiblmImt.js.map} +1 -1
  27. package/dist/{internal-artifact-open-B3stUu74.js → internal-artifact-open-CA1trJ15.js} +2 -2
  28. package/dist/{internal-artifact-open-B3stUu74.js.map → internal-artifact-open-CA1trJ15.js.map} +1 -1
  29. package/dist/{internal-fast-dispatch-guard-CAwYj_Yz.js → internal-fast-dispatch-guard-CZ4BZuAG.js} +2 -2
  30. package/dist/{internal-fast-dispatch-guard-CAwYj_Yz.js.map → internal-fast-dispatch-guard-CZ4BZuAG.js.map} +1 -1
  31. package/dist/{internal-fast-dispatch-guard-2QjUlhqO.js → internal-fast-dispatch-guard-D5kozMpo.js} +1 -1
  32. package/dist/{internal-first-mate-guard-VgnHBp0s.js → internal-first-mate-guard-B_or0eN3.js} +1 -1
  33. package/dist/{internal-first-mate-guard-B0rbLb0L.js → internal-first-mate-guard-CiFH6X1H.js} +3 -3
  34. package/dist/{internal-first-mate-guard-B0rbLb0L.js.map → internal-first-mate-guard-CiFH6X1H.js.map} +1 -1
  35. package/dist/{internal-max-dispatch-guard-BzKsY9ze.js → internal-max-dispatch-guard-BGOHRYRt.js} +1 -1
  36. package/dist/{internal-max-dispatch-guard-l1NGYHtF.js → internal-max-dispatch-guard-CnBZxo5l.js} +3 -3
  37. package/dist/{internal-max-dispatch-guard-l1NGYHtF.js.map → internal-max-dispatch-guard-CnBZxo5l.js.map} +1 -1
  38. package/dist/{internal-plan-review-QUvNZmMR.js → internal-plan-review-C73snnD8.js} +3 -3
  39. package/dist/{internal-plan-review-QUvNZmMR.js.map → internal-plan-review-C73snnD8.js.map} +1 -1
  40. package/dist/{internal-prompt-submit-fj5ccft_.js → internal-prompt-submit-dov4UvBo.js} +4 -4
  41. package/dist/{internal-prompt-submit-fj5ccft_.js.map → internal-prompt-submit-dov4UvBo.js.map} +1 -1
  42. package/dist/{internal-session-bind-0Hmak8PR.js → internal-session-bind-C3hrb9rP.js} +2 -2
  43. package/dist/{internal-session-bind-0Hmak8PR.js.map → internal-session-bind-C3hrb9rP.js.map} +1 -1
  44. package/dist/{internal-stop-hook-BKiKYeda.js → internal-stop-hook-DZ6CCP4C.js} +5 -5
  45. package/dist/{internal-stop-hook-BKiKYeda.js.map → internal-stop-hook-DZ6CCP4C.js.map} +1 -1
  46. package/dist/{internal-stop-review-8v2llYDB.js → internal-stop-review-MBVYtrYS.js} +2 -2
  47. package/dist/{internal-stop-review-8v2llYDB.js.map → internal-stop-review-MBVYtrYS.js.map} +1 -1
  48. package/dist/{internal-worker-guard-BI4Pl0Ew.js → internal-worker-guard-dxGawAY3.js} +2 -2
  49. package/dist/{internal-worker-guard-BI4Pl0Ew.js.map → internal-worker-guard-dxGawAY3.js.map} +1 -1
  50. package/dist/{internal-workspace-header-kg9FoNXK.js → internal-workspace-header-_aEXOz5q.js} +2 -2
  51. package/dist/{internal-workspace-header-kg9FoNXK.js.map → internal-workspace-header-_aEXOz5q.js.map} +1 -1
  52. package/dist/{lifecycle-IwotwedG.js → lifecycle-CJB2BwSJ.js} +2 -2
  53. package/dist/{lifecycle-IwotwedG.js.map → lifecycle-CJB2BwSJ.js.map} +1 -1
  54. package/dist/lifecycle-D0KsoSqz.js +2 -0
  55. package/dist/lifecycle-DimEguJO.js +2 -0
  56. package/dist/{lifecycle-Cx1wVrLb.js → lifecycle-_BE0SnNs.js} +2 -2
  57. package/dist/{lifecycle-Cx1wVrLb.js.map → lifecycle-_BE0SnNs.js.map} +1 -1
  58. package/dist/main.js +20 -20
  59. package/dist/{max-profile-contract-BcrMlrmo.js → max-profile-contract-Bl7I_EOC.js} +2 -2
  60. package/dist/{max-profile-contract-BcrMlrmo.js.map → max-profile-contract-Bl7I_EOC.js.map} +1 -1
  61. package/dist/{mcp-workspace-header-BYgWioLH.js → mcp-workspace-header-mXRLE8kg.js} +2 -2
  62. package/dist/{mcp-workspace-header-BYgWioLH.js.map → mcp-workspace-header-mXRLE8kg.js.map} +1 -1
  63. package/dist/{models-DgLeb-Dv.js → models-CSFIVxAH.js} +3 -3
  64. package/dist/{models-DgLeb-Dv.js.map → models-CSFIVxAH.js.map} +1 -1
  65. package/dist/{orchestration-Dc3mO0G3.js → orchestration-B8kypXcZ.js} +2 -2
  66. package/dist/{orchestration-Dc3mO0G3.js.map → orchestration-B8kypXcZ.js.map} +1 -1
  67. package/dist/{paths-CMxlQEfQ.js → paths-CHBAj_t9.js} +36 -4
  68. package/dist/{paths-CMxlQEfQ.js.map → paths-CHBAj_t9.js.map} +1 -1
  69. package/dist/paths-eHoOwFzZ.js +2 -0
  70. package/dist/{peer-mcp-personas-CYWJSxPK.js → peer-mcp-personas-CRMVuMVF.js} +201 -61
  71. package/dist/peer-mcp-personas-CRMVuMVF.js.map +1 -0
  72. package/dist/{plan-review-hook-BIMwWkh6.js → plan-review-hook-BMmw7wxR.js} +3 -3
  73. package/dist/{plan-review-hook-BIMwWkh6.js.map → plan-review-hook-BMmw7wxR.js.map} +1 -1
  74. package/dist/{prompt-submit-hook-BcFpjHXg.js → prompt-submit-hook-CGgT5m4Q.js} +3 -3
  75. package/dist/{prompt-submit-hook-BcFpjHXg.js.map → prompt-submit-hook-CGgT5m4Q.js.map} +1 -1
  76. package/dist/{provision-AwSjt-vR.js → provision-Bn8-NDp7.js} +4 -4
  77. package/dist/{provision-AwSjt-vR.js.map → provision-Bn8-NDp7.js.map} +1 -1
  78. package/dist/{self-invocation-cRl4RqfW.js → self-invocation-DahN1gw9.js} +2 -2
  79. package/dist/{self-invocation-cRl4RqfW.js.map → self-invocation-DahN1gw9.js.map} +1 -1
  80. package/dist/{serve-BG2O6Slz.js → serve-CX4Ifk5p.js} +13 -13
  81. package/dist/{serve-BG2O6Slz.js.map → serve-CX4Ifk5p.js.map} +1 -1
  82. package/dist/{server-setup-D7ABbEs1.js → server-setup-0PaS4m2B.js} +254 -66
  83. package/dist/server-setup-0PaS4m2B.js.map +1 -0
  84. package/dist/{start-Dpwpnq99.js → start-Bz_559ua.js} +3 -3
  85. package/dist/{start-Dpwpnq99.js.map → start-Bz_559ua.js.map} +1 -1
  86. package/dist/{state-B8adscCv.js → state-BlMpEFAt.js} +2 -1
  87. package/dist/{state-B8adscCv.js.map → state-BlMpEFAt.js.map} +1 -1
  88. package/dist/{stop-gate-hook-BUCxa5Kc.js → stop-gate-hook-D7N759TG.js} +72 -4
  89. package/dist/{stop-gate-hook-BUCxa5Kc.js.map → stop-gate-hook-D7N759TG.js.map} +1 -1
  90. package/dist/{stop-gate-policy--bpyxxXU.js → stop-gate-policy-C0gt04R0.js} +2 -2
  91. package/dist/{stop-gate-policy--bpyxxXU.js.map → stop-gate-policy-C0gt04R0.js.map} +1 -1
  92. package/dist/{token-ClzS23Y2.js → token-86uk6y4P.js} +3 -3
  93. package/dist/{token-ClzS23Y2.js.map → token-86uk6y4P.js.map} +1 -1
  94. package/dist/{worker-dispatch-DMIdrlsF.js → worker-dispatch-B-OA7tvU.js} +2 -2
  95. package/dist/{worker-dispatch-DMIdrlsF.js.map → worker-dispatch-B-OA7tvU.js.map} +1 -1
  96. package/package.json +1 -1
  97. package/dist/attribution-settings-DXmmyuEE.js.map +0 -1
  98. package/dist/claude-Cmmu3-cL.js.map +0 -1
  99. package/dist/codex-DqTKKoEx.js.map +0 -1
  100. package/dist/engine-b9XaKLp0.js +0 -2
  101. package/dist/lifecycle-BpqAyaAj.js +0 -2
  102. package/dist/lifecycle-CL2WiyeQ.js +0 -2
  103. package/dist/paths-BXXCVFvA.js +0 -2
  104. package/dist/peer-mcp-personas-CYWJSxPK.js.map +0 -1
  105. package/dist/server-setup-D7ABbEs1.js.map +0 -1
@@ -1,13 +1,13 @@
1
- import { $ as UNKNOWN_EFFORT_ANCHOR, An as CHEAP_PROFILE_MODELS, B as resolveAdvisorEffort, Cn as upstreamMaxConnections, D as toolbeltEnabled, Dn as withOneMSuffix, En as oneMContextDisabled, F as ADVISOR_TOOL_INSTRUCTIONS, Fn as withInstallLock, Ft as createMessages, G as repairRejectedThinkingHistory, Gt as createResponses, H as formatThinkingRepairDecline, Ht as assembleResponsesPayload, I as FAST_ADVISOR_TOOL_INSTRUCTIONS, It as getTextTokenCount, J as isControllerClosedError, Jt as readResponseBodyCapped, K as buildAnthropicErrorEvent, Kt as createChatCompletions, L as buildAdvisorStream, Lt as getTokenCount, N as searchWeb, Nt as shimDefaultsToXhigh, On as withOneMSuffixForLead, P as ADVISOR_INTERNAL_TOOL_NAME, Pn as CHEAP_PROFILE_SUBAGENT_CONTEXT_TOKENS, Pt as countTokens, Q as EFFORT_ORDER, R as injectAdvisorTool, Rt as getTokenizerFromModel, Sn as upstreamAllowH2, Tn as catalogAdvertises1M, U as rememberThinkingHistoryRepair, Ut as warnOnTokenPriceDrift, V as resolveAdvisorModel, W as repairKnownThinkingHistory, Wt as resolveMcpToolTimeoutMs, X as readIteratorWithTimeout, Xt as normalizeOpenAIUsage, Y as logStreamError, Yt as parseJsonOrDiagnose, Z as relayAnthropicStream, _n as UPSTREAM_INACTIVITY_TIMEOUT_MS, dn as BUDGET_SMALL_FAST_SLUG, et as bucketEffort, gn as UPSTREAM_FETCH_TIMEOUT_MS, i as assertMcpToolSurfaceConsistent, in as provisionTreeSitterAssets, it as agentToolsEnabled, jn as CHEAP_PROFILE_NATIVE_AGENT_NAMES, kn as CHEAP_PROFILE_ADVISOR_CLIENT_MODEL, ln as toolbeltPathOverride, nt as handleMcpDelete, q as buildOpenAIErrorEvent, qt as MAX_RESPONSE_BODY_BYTES, rt as handleMcpPost, tt as clampEffort, vn as generateRandomPort, wn as classifyMessagesRoute, yn as isBudgetClaudeLead, z as isAdvisorRequested, zt as findLaunchBySecret } from "./peer-mcp-personas-CYWJSxPK.js";
1
+ import { $ as EFFORT_ORDER, $t as parseJsonOrDiagnose, An as oneMContextDisabled, B as resolveAdvisorEffort, Bn as CHEAP_PROFILE_MODELS, Bt as getTextTokenCount, Cn as isBudgetClaudeLead, D as toolbeltEnabled, Dn as upstreamMaxConnections, En as upstreamAllowH2, F as ADVISOR_TOOL_INSTRUCTIONS, Fn as CHEAPEST_PROFILE_NATIVE_AGENT_NAMES, G as repairKnownThinkingHistory, Gn as withInstallLock, H as resolveCheapestAdvisorModel, Ht as getTokenizerFromModel, I as FAST_ADVISOR_TOOL_INSTRUCTIONS, J as buildOpenAIErrorEvent, Jt as resolveMcpToolTimeoutMs, K as repairRejectedThinkingHistory, Kt as assembleResponsesPayload, L as buildAdvisorStream, Lt as shimDefaultsToXhigh, Mn as withOneMSuffixForLead, N as searchWeb, Nn as CHEAPEST_PROFILE_ADVISOR_CLIENT_MODEL, On as classifyMessagesRoute, P as ADVISOR_INTERNAL_TOOL_NAME, Pn as CHEAPEST_PROFILE_MODELS, Q as relayAnthropicStream, Qt as readResponseBodyCapped, R as injectAdvisorTool, Rn as CHEAPEST_PROFILE_SUBAGENT_CONTEXT_TOKENS, Rt as countTokens, Sn as generateRandomPort, U as formatThinkingRepairDecline, Ut as findLaunchBySecret, V as resolveAdvisorModel, Vn as CHEAP_PROFILE_NATIVE_AGENT_NAMES, Vt as getTokenCount, W as rememberThinkingHistoryRepair, Wn as CHEAP_PROFILE_SUBAGENT_CONTEXT_TOKENS, X as logStreamError, Xt as createChatCompletions, Y as isControllerClosedError, Yt as createResponses, Z as readIteratorWithTimeout, Zt as MAX_RESPONSE_BODY_BYTES, at as agentToolsEnabled, bn as UPSTREAM_FETCH_TIMEOUT_MS, cn as provisionTreeSitterAssets, en as normalizeOpenAIUsage, et as UNKNOWN_EFFORT_ANCHOR, hn as BUDGET_SMALL_FAST_SLUG, i as assertMcpToolSurfaceConsistent, it as handleMcpPost, jn as withOneMSuffix, kn as catalogAdvertises1M, nt as clampEffort, pn as toolbeltPathOverride, q as buildAnthropicErrorEvent, qt as warnOnTokenPriceDrift, rt as handleMcpDelete, tt as bucketEffort, xn as UPSTREAM_INACTIVITY_TIMEOUT_MS, z as isAdvisorRequested, zn as CHEAP_PROFILE_ADVISOR_CLIENT_MODEL, zt as createMessages } from "./peer-mcp-personas-CRMVuMVF.js";
2
2
  import { t as getPackageVersion } from "./version-C8x2hQrZ.js";
3
- import { i as ensurePaths, t as PATHS } from "./paths-CMxlQEfQ.js";
4
- import { t as state } from "./state-B8adscCv.js";
5
- import { 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-ClzS23Y2.js";
6
- import { t as getCopilotUsage } from "./get-copilot-usage-FSQE8szQ.js";
3
+ import { i as ensurePaths, t as PATHS } from "./paths-CHBAj_t9.js";
4
+ import { t as state } from "./state-BlMpEFAt.js";
5
+ import { 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-86uk6y4P.js";
6
+ import { t as getCopilotUsage } from "./get-copilot-usage-BWCAzmSc.js";
7
7
  import { c as runCommandVoid, i as parseBoolEnv, o as resolveExecutable, r as killManagedTree, s as runCommandCapture } from "./exec-COUT4QsS.js";
8
8
  import { c as FAST_PROFILE_MODELS, l as FAST_PROFILE_NATIVE_AGENT_NAMES, r as FAST_PROFILE_ADVISOR_MODEL } from "./fast-profile-contract-_DhIWank.js";
9
- import { A as normalizeTrailingOneMSuffix, a as MAX_PROFILE_NATIVE_AGENT_NAMES, d as maxAdvisorPinIsValid, h as maxOpusModel, i as MAX_PROFILE_MODELS, j as stripTrailingOneMSuffix, k as fastEndpointForModel, l as maxAdvisorEffortForModel, n as MAX_PROFILE_ALLOWED_LEAD_MODEL_IDS, t as MAX_PROFILE_ADVISOR_INSTRUCTIONS, u as maxAdvisorModelFromPin, y as validateMaxProfilePrerequisites } from "./max-profile-contract-BcrMlrmo.js";
10
- import { c as recordAic, d as extractCopilotUsage, f as formatAic, i as extractAndRecordAic, p as nanoAiuToCredits } from "./aic-ledger-BS47yb_C.js";
9
+ import { A as normalizeTrailingOneMSuffix, a as MAX_PROFILE_NATIVE_AGENT_NAMES, d as maxAdvisorPinIsValid, h as maxOpusModel, i as MAX_PROFILE_MODELS, j as stripTrailingOneMSuffix, k as fastEndpointForModel, l as maxAdvisorEffortForModel, n as MAX_PROFILE_ALLOWED_LEAD_MODEL_IDS, t as MAX_PROFILE_ADVISOR_INSTRUCTIONS, u as maxAdvisorModelFromPin, y as validateMaxProfilePrerequisites } from "./max-profile-contract-Bl7I_EOC.js";
10
+ import { c as recordAic, d as extractCopilotUsage, f as formatAic, i as extractAndRecordAic, p as nanoAiuToCredits } from "./aic-ledger-DY03LbBM.js";
11
11
  import consola from "consola";
12
12
  import fs, { existsSync } from "node:fs";
13
13
  import path from "node:path";
@@ -421,6 +421,25 @@ const CHEAP_PROFILE = Object.freeze({
421
421
  hasCoordinator: false
422
422
  });
423
423
  /**
424
+ * The `-m cheapest` roster: the exact cheap surface and groups, but Luna-led
425
+ * (`gpt-5.6-luna`/max at the 200K default window), a Gemini/high Advisor, a
426
+ * Sol/high Oracle, and a Gemini/high reviewer. Oracle-only peer set, no
427
+ * `astra`. Hard-denies match fast's: core workers, `orchestrate`, `decide`,
428
+ * `fleet`, and `first-mate`.
429
+ */
430
+ const CHEAPEST_PROFILE = Object.freeze({
431
+ id: "cheapest",
432
+ nativeRoster: new Set(CHEAPEST_PROFILE_NATIVE_AGENT_NAMES),
433
+ personaAllowlist: /* @__PURE__ */ new Set(["oracle"]),
434
+ allowedGroups: /* @__PURE__ */ new Set([
435
+ "peers",
436
+ "search",
437
+ "workers",
438
+ "browser"
439
+ ]),
440
+ hasCoordinator: false
441
+ });
442
+ /**
424
443
  * The `-m max` profile: Sol/Luna-led, browse-only workers, and explicit
425
444
  * cross-lab peer names. The descriptor is a hard projection for bound launch
426
445
  * requests; unbound/BYO traffic remains standard because it has no registry
@@ -455,6 +474,7 @@ function profileDescriptor(id) {
455
474
  if (id === "max") return MAX_PROFILE;
456
475
  if (id === "cheap1m") return CHEAP1M_PROFILE;
457
476
  if (id === "cheap") return CHEAP_PROFILE;
477
+ if (id === "cheapest") return CHEAPEST_PROFILE;
458
478
  return STANDARD_PROFILE;
459
479
  }
460
480
  /**
@@ -474,6 +494,7 @@ function resolveLaunchProfile(modelArg) {
474
494
  if (arg === "max") return "max";
475
495
  if (arg === "cheap1m") return "cheap1m";
476
496
  if (arg === "cheap") return "cheap";
497
+ if (arg === "cheapest") return "cheapest";
477
498
  return "standard";
478
499
  }
479
500
  function validateMaxProfileLaunch(catalog) {
@@ -786,6 +807,53 @@ function formatCheap1mPrerequisiteFailure(missing) {
786
807
  function formatCheapPrerequisiteFailure(missing) {
787
808
  return "github-router claude -m cheap requires the following live-catalog capabilities, which this account's catalog does not fully provide:\n" + missing.map((m) => ` - ${m}`).join("\n") + "\n\nFalling back or silently dropping an agent is not supported for the cheap profile's exact roster. Run plain `github-router claude` instead.";
788
809
  }
810
+ /** The subagent window floor: every cheapest role runs at the 200K default. */
811
+ const CHEAPEST_SUBAGENT_MIN_CONTEXT_TOKENS = CHEAPEST_PROFILE_SUBAGENT_CONTEXT_TOKENS;
812
+ /**
813
+ * Validate the live Copilot catalog for `-m cheapest`: Luna lead at the 200K
814
+ * default window, Luna Explore/Plan/GP/implementer roles, Gemini reviewer and
815
+ * Advisor, and a Sol Oracle — all at the 200K default with their fixed
816
+ * efforts and supported endpoints.
817
+ */
818
+ function validateCheapestProfilePrerequisites(catalog) {
819
+ const missing = [];
820
+ const luna = findModel(catalog, CHEAPEST_PROFILE_MODELS.lead);
821
+ if (!luna) missing.push(`${CHEAPEST_PROFILE_MODELS.lead}: absent from the live catalog`);
822
+ else {
823
+ if (!hasToolCalls(luna)) missing.push(`${CHEAPEST_PROFILE_MODELS.lead}: does not advertise tool_calls`);
824
+ if (!hasContextAtLeast(luna, CHEAPEST_SUBAGENT_MIN_CONTEXT_TOKENS)) missing.push(`${CHEAPEST_PROFILE_MODELS.lead}: advertised context window is below the 200K subagent floor`);
825
+ if (!supportsEffort(luna, "high") || !supportsEffort(luna, "max") || !supportsEffort(luna, "xhigh")) missing.push(`${CHEAPEST_PROFILE_MODELS.lead}: does not advertise "high", "max", and "xhigh" reasoning effort`);
826
+ if (!supportsEndpoint(luna, "responses")) missing.push(`${CHEAPEST_PROFILE_MODELS.lead}: does not advertise a supported Responses endpoint`);
827
+ }
828
+ const sol = findModel(catalog, CHEAPEST_PROFILE_MODELS.plan);
829
+ if (!sol) missing.push(`${CHEAPEST_PROFILE_MODELS.plan}: absent from the live catalog`);
830
+ else {
831
+ if (!hasToolCalls(sol)) missing.push(`${CHEAPEST_PROFILE_MODELS.plan}: does not advertise tool_calls`);
832
+ if (!hasContextAtLeast(sol, CHEAPEST_SUBAGENT_MIN_CONTEXT_TOKENS)) missing.push(`${CHEAPEST_PROFILE_MODELS.plan}: advertised context window is below the 200K subagent floor`);
833
+ if (!supportsEffort(sol, "high")) missing.push(`${CHEAPEST_PROFILE_MODELS.plan}: does not advertise a "high" reasoning effort`);
834
+ if (!supportsEndpoint(sol, "responses")) missing.push(`${CHEAPEST_PROFILE_MODELS.plan}: does not advertise a supported Responses endpoint`);
835
+ if (!hasUsablePromptMetadata(sol)) missing.push(`${CHEAPEST_PROFILE_MODELS.plan}: no usable max_prompt_tokens metadata (Oracle brief)`);
836
+ }
837
+ const gemini = findModel(catalog, CHEAPEST_PROFILE_MODELS.reviewer);
838
+ if (!gemini) missing.push(`${CHEAPEST_PROFILE_MODELS.reviewer}: absent from the live catalog`);
839
+ else {
840
+ if (!hasToolCalls(gemini)) missing.push(`${CHEAPEST_PROFILE_MODELS.reviewer}: does not advertise tool_calls`);
841
+ if (!hasContextAtLeast(gemini, CHEAPEST_SUBAGENT_MIN_CONTEXT_TOKENS)) missing.push(`${CHEAPEST_PROFILE_MODELS.reviewer}: advertised context window is below the 200K subagent floor`);
842
+ if (!supportsEffort(gemini, "high")) missing.push(`${CHEAPEST_PROFILE_MODELS.reviewer}: does not advertise a "high" reasoning effort`);
843
+ if (!supportsEndpoint(gemini, "chat")) missing.push(`${CHEAPEST_PROFILE_MODELS.reviewer}: does not advertise a supported chat-completions endpoint`);
844
+ }
845
+ return {
846
+ ok: missing.length === 0,
847
+ missing
848
+ };
849
+ }
850
+ /**
851
+ * Format `validateCheapestProfilePrerequisites`'s failure list into the
852
+ * launch error message.
853
+ */
854
+ function formatCheapestPrerequisiteFailure(missing) {
855
+ return "github-router claude -m cheapest requires the following live-catalog capabilities, which this account's catalog does not fully provide:\n" + missing.map((m) => ` - ${m}`).join("\n") + "\n\nFalling back or silently dropping an agent is not supported for the cheapest profile's exact roster. Run plain `github-router claude` instead.";
856
+ }
789
857
  //#endregion
790
858
  //#region src/lib/file-log-reporter.ts
791
859
  const MAX_LOG_BYTES = 1048576;
@@ -1150,6 +1218,26 @@ const CHEAP_PICKER_MODELS = Object.freeze([
1150
1218
  neverOneM: true
1151
1219
  }
1152
1220
  ]);
1221
+ const CHEAPEST_PICKER_MODELS = Object.freeze([
1222
+ {
1223
+ id: "gpt-5.6-sol",
1224
+ label: "GPT-5.6 Sol",
1225
+ behavesAs: "claude-opus-5",
1226
+ neverOneM: true
1227
+ },
1228
+ {
1229
+ id: "gpt-5.6-luna",
1230
+ label: "GPT-5.6 Luna",
1231
+ behavesAs: "claude-opus-5",
1232
+ neverOneM: true
1233
+ },
1234
+ {
1235
+ id: "gemini-3.8-flash",
1236
+ label: "Gemini 3.8 Flash",
1237
+ behavesAs: "claude-sonnet-5",
1238
+ neverOneM: true
1239
+ }
1240
+ ]);
1153
1241
  /**
1154
1242
  * Return the ordered, profile-specific `/model` rows supported by the live
1155
1243
  * Copilot catalog. Fast intentionally shares Standard's four-row inventory;
@@ -1167,7 +1255,7 @@ function selectableModelsInCatalog(profile) {
1167
1255
  const catalog = state.models?.data;
1168
1256
  if (!catalog || catalog.length === 0) return [];
1169
1257
  const present = new Set(catalog.map((entry) => entry.id));
1170
- return (profile === "max" ? MAX_PICKER_MODELS : profile === "cheap" || profile === "cheap1m" ? CHEAP_PICKER_MODELS : STANDARD_PICKER_MODELS).filter((entry) => present.has(entry.id)).map((entry) => ({
1258
+ return (profile === "max" ? MAX_PICKER_MODELS : profile === "cheap" || profile === "cheap1m" ? CHEAP_PICKER_MODELS : profile === "cheapest" ? CHEAPEST_PICKER_MODELS : STANDARD_PICKER_MODELS).filter((entry) => present.has(entry.id)).map((entry) => ({
1171
1259
  model: entry.neverOneM ? entry.id : withOneMSuffix(entry.id),
1172
1260
  label: entry.label,
1173
1261
  behavesAs: entry.behavesAs
@@ -1196,6 +1284,17 @@ async function renameSettingsWithRetry(temp, target) {
1196
1284
  await fs$1.rm(temp, { force: true }).catch(() => {});
1197
1285
  throw lastError;
1198
1286
  }
1287
+ /**
1288
+ * Profiles whose sessions run router-provided surfaces only. On these
1289
+ * launches a user-curated `modelPicker` in the (per-launch, disposable)
1290
+ * mirror is overwritten with the router rows rather than preserved: the
1291
+ * mirror is a snapshot copy, so the operator's real settings are never
1292
+ * touched, but a stale standard `[1m]` picker must not survive into a
1293
+ * 200K session's `/model` UI.
1294
+ */
1295
+ function routerWinsPicker(profile) {
1296
+ return profile === "fast" || profile === "cheap" || profile === "cheap1m" || profile === "cheapest";
1297
+ }
1199
1298
  function modelIdsFromExistingPicker(value) {
1200
1299
  if (!value || typeof value !== "object" || Array.isArray(value)) return [];
1201
1300
  const options = value.options;
@@ -1220,11 +1319,16 @@ async function injectModelPickerSettingsFile(settingsPath, profile) {
1220
1319
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`settings.json at ${settingsPath} is not a JSON object; refusing to overwrite`);
1221
1320
  existing = parsed;
1222
1321
  }
1223
- if ("modelPicker" in existing) return {
1224
- written: false,
1225
- reason: "user-set",
1226
- models: modelIdsFromExistingPicker(existing.modelPicker)
1227
- };
1322
+ let overwroteUserPicker = false;
1323
+ if ("modelPicker" in existing) {
1324
+ if (!routerWinsPicker(profile)) return {
1325
+ written: false,
1326
+ reason: "user-set",
1327
+ models: modelIdsFromExistingPicker(existing.modelPicker)
1328
+ };
1329
+ overwroteUserPicker = true;
1330
+ delete existing.modelPicker;
1331
+ }
1228
1332
  if (options.length === 0) return {
1229
1333
  written: false,
1230
1334
  reason: "no-models",
@@ -1249,6 +1353,7 @@ async function injectModelPickerSettingsFile(settingsPath, profile) {
1249
1353
  }
1250
1354
  return {
1251
1355
  written: true,
1356
+ ...overwroteUserPicker ? { reason: "router-overwrite" } : {},
1252
1357
  models: options.map((option) => option.model)
1253
1358
  };
1254
1359
  }
@@ -2108,7 +2213,7 @@ function collectToolFieldKeys(body) {
2108
2213
  //#endregion
2109
2214
  //#region package.json
2110
2215
  var name = "github-router";
2111
- var version = "0.3.315";
2216
+ var version = "0.3.317";
2112
2217
  //#endregion
2113
2218
  //#region src/lib/approval.ts
2114
2219
  const awaitApproval = async () => {
@@ -4940,7 +5045,9 @@ async function handleNonClaudeResponses(c, opts) {
4940
5045
  return stream;
4941
5046
  }
4942
5047
  const payload = parsedToResponsesPayload(parsed);
4943
- const anthropic = responsesResponseToAnthropicMessage(await createResponses(payload, opts.model?.requestHeaders, void 0, true), opts.modelId);
5048
+ const result = await createResponses(payload, opts.model?.requestHeaders, void 0, true);
5049
+ extractAndRecordAic(opts.modelId, result);
5050
+ const anthropic = responsesResponseToAnthropicMessage(result, opts.modelId);
4944
5051
  const usage = anthropic.usage;
4945
5052
  logRequest({
4946
5053
  method: "POST",
@@ -4996,7 +5103,9 @@ async function handleNonClaudeChat(c, opts) {
4996
5103
  return stream;
4997
5104
  }
4998
5105
  const payload = parsedToChatPayload(parsed);
4999
- const anthropic = chatResponseToAnthropicMessage(await createChatCompletions(payload, opts.model?.requestHeaders, void 0, true), opts.modelId);
5106
+ const result = await createChatCompletions(payload, opts.model?.requestHeaders, void 0, true);
5107
+ extractAndRecordAic(opts.modelId, result);
5108
+ const anthropic = chatResponseToAnthropicMessage(result, opts.modelId);
5000
5109
  const usage = anthropic.usage;
5001
5110
  logRequest({
5002
5111
  method: "POST",
@@ -5159,16 +5268,38 @@ function preprocessMaxRequest(rawBody, launch, subagentRequest = false) {
5159
5268
  Object.freeze([MAX_LUNA_HIGH_ALIAS_ID, MAX_LUNA_MAX_ALIAS_ID]);
5160
5269
  //#endregion
5161
5270
  //#region src/lib/fast-request-preprocess.ts
5162
- const cheapFamily = (profileId) => profileId === "cheap" || profileId === "cheap1m";
5271
+ const cheapFamily = (profileId) => profileId === "cheap" || profileId === "cheap1m" || profileId === "cheapest";
5272
+ const pinnedProfile = (profileId) => profileId === "fast" || cheapFamily(profileId);
5273
+ /**
5274
+ * Profiles whose every selectable `/model` row must stay at Claude Code's
5275
+ * 200K DEFAULT context window (bare id, no `[1m]` accounting bracket).
5276
+ * `fast` keeps 1M on lead and subagents by design; `cheap1m` keeps 1M on
5277
+ * the lead only (its subagents are bare-by-construction).
5278
+ */
5279
+ const bareEnforcedProfile = (profileId) => profileId === "cheap" || profileId === "cheapest";
5280
+ function explicitEffortOf(value) {
5281
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
5282
+ }
5163
5283
  /**
5164
5284
  * Apply authenticated fast/cheap-profile model and effort policy before
5165
5285
  * ordinary model resolution. Synthetic aliases are refused outside an
5166
- * authenticated fast or cheap launch, so raw/BYO traffic cannot opt itself
5167
- * into private profile semantics. The cheap family shares fast's effort
5168
- * mapping (same model-to-effort rows, just bare subagent slugs at the
5169
- * wiring layer), so this preprocess is shared. Note the reviewer differs:
5170
- * fast reviews on Sonnet 5/xhigh while cheap reviews on Luna/max — both
5171
- * rows exist here, so each profile's reviewer resolves to its fixed effort.
5286
+ * authenticated pinned launch, so raw/BYO traffic cannot opt itself into
5287
+ * private profile semantics. The cheap family (including cheapest) shares
5288
+ * fast's effort mapping (same model-to-effort rows, just bare subagent
5289
+ * slugs at the wiring layer), so this preprocess is shared.
5290
+ * Note the reviewer differs: fast reviews on Sonnet 5/xhigh while cheap
5291
+ * reviews on Luna/max and cheapest reviews on Gemini/high all rows exist
5292
+ * here, so each profile's reviewer resolves to its fixed effort.
5293
+ *
5294
+ * Pinned-profile isolation (fast/cheap/cheap1m/cheapest): only
5295
+ * router-provided models are accepted (anything else is `rejectedModel`).
5296
+ * Context: cheap/cheapest traffic is stripped to the bare 200K id;
5297
+ * cheap1m subagent traffic is stripped while its lead keeps 1M; fast
5298
+ * keeps 1M on both. Effort: picker changes apply to the lead session
5299
+ * only — lead requests keep an explicit `output_config.effort` when
5300
+ * present and fall back to the fixed mapping otherwise, while subagent
5301
+ * traffic (`x-claude-code-agent-id`) always receives its fixed
5302
+ * per-model effort.
5172
5303
  */
5173
5304
  function preprocessFastRequest(rawBody, launch, subagentRequest = false) {
5174
5305
  if (launch?.profileId === "max") return preprocessMaxRequest(rawBody, launch, subagentRequest);
@@ -5205,23 +5336,30 @@ function preprocessFastRequest(rawBody, launch, subagentRequest = false) {
5205
5336
  modified: false
5206
5337
  };
5207
5338
  const { base: bare } = stripTrailingOneMSuffix(originalModel);
5208
- let effort;
5339
+ const profileId = launch?.profileId;
5340
+ const stripBracket = bareEnforcedProfile(profileId) || profileId === "cheap1m" && subagentRequest;
5341
+ const leadCallerControlled = pinnedProfile(profileId) && !subagentRequest;
5342
+ let fixedEffort;
5209
5343
  if (alias) {
5210
- effort = alias.absentEffortDefault;
5344
+ fixedEffort = alias.absentEffortDefault;
5211
5345
  parsed.model = canonicalizeAliasModel(originalModel);
5212
- } else if (bare === "gpt-5.6-luna") effort = "max";
5213
- else if (bare === "gpt-5.6-sol") effort = "high";
5214
- else if (bare === "grok-4.6") effort = "medium";
5215
- else if (bare === "gemini-3.8-flash") effort = "high";
5216
- else if (bare === "claude-sonnet-5") effort = "xhigh";
5217
- else if (bare === "claude-opus-5") effort = "high";
5218
- if (!effort && !alias) return {
5346
+ } else if (bare === "gpt-5.6-luna") fixedEffort = "max";
5347
+ else if (bare === "gpt-5.6-sol") fixedEffort = "high";
5348
+ else if (bare === "grok-4.6") fixedEffort = "medium";
5349
+ else if (bare === "gemini-3.8-flash") fixedEffort = "high";
5350
+ else if (bare === "claude-sonnet-5") fixedEffort = "xhigh";
5351
+ else if (bare === "claude-opus-5") fixedEffort = "high";
5352
+ if (!fixedEffort && !alias) return {
5219
5353
  body: rawBody,
5220
5354
  originalModel,
5221
5355
  modified: false,
5222
5356
  rejectedModel: originalModel
5223
5357
  };
5358
+ if (stripBracket && typeof parsed.model === "string") parsed.model = stripTrailingOneMSuffix(parsed.model).base;
5359
+ else if (stripBracket) parsed.model = bare;
5224
5360
  const outputConfig = parsed.output_config && typeof parsed.output_config === "object" ? parsed.output_config : {};
5361
+ const explicitEffort = explicitEffortOf(outputConfig.effort);
5362
+ const effort = leadCallerControlled && explicitEffort ? explicitEffort : fixedEffort;
5225
5363
  parsed.output_config = {
5226
5364
  ...outputConfig,
5227
5365
  effort
@@ -5539,6 +5677,23 @@ function fastAdvisorMetadataMismatch(rawBody) {
5539
5677
  if (stripTrailingOneMSuffix(model).base !== FAST_PROFILE_ADVISOR_MODEL) return `the native Advisor tool requested ${JSON.stringify(model)} instead of ${JSON.stringify(FAST_PROFILE_ADVISOR_MODEL)}`;
5540
5678
  }
5541
5679
  }
5680
+ function cheapestAdvisorMetadataMismatch(rawBody) {
5681
+ let body;
5682
+ try {
5683
+ body = JSON.parse(rawBody);
5684
+ } catch {
5685
+ return;
5686
+ }
5687
+ if (!Array.isArray(body.tools) || body.tools.length === 0) return void 0;
5688
+ for (const tool of body.tools) {
5689
+ if (!tool || typeof tool !== "object") continue;
5690
+ const type = tool.type;
5691
+ if (typeof type !== "string" || !type.startsWith("advisor_")) continue;
5692
+ const model = tool.model;
5693
+ if (typeof model !== "string") return "the native Advisor tool omitted its fixed model";
5694
+ if (stripTrailingOneMSuffix(model).base !== CHEAPEST_PROFILE_ADVISOR_CLIENT_MODEL) return `the native Advisor tool requested ${JSON.stringify(model)} instead of ${JSON.stringify(CHEAPEST_PROFILE_ADVISOR_CLIENT_MODEL)}`;
5695
+ }
5696
+ }
5542
5697
  function stripAdvisorTool(rawBody) {
5543
5698
  let body;
5544
5699
  try {
@@ -5674,18 +5829,22 @@ async function handleCompletion(c) {
5674
5829
  const fastProfileRequest = identity.launch?.profileId === "fast";
5675
5830
  const maxProfileRequest = identity.launch?.profileId === "max";
5676
5831
  const cheapProfileRequest = identity.launch?.profileId === "cheap" || identity.launch?.profileId === "cheap1m";
5832
+ const cheapestProfileRequest = identity.launch?.profileId === "cheapest";
5677
5833
  const subagentRequest = Boolean(c.req.header("x-claude-code-agent-id"));
5678
5834
  const fastSubagentRequest = fastProfileRequest && subagentRequest;
5679
5835
  const maxSubagentRequest = maxProfileRequest && subagentRequest;
5680
5836
  const cheapSubagentRequest = cheapProfileRequest && subagentRequest;
5837
+ const cheapestSubagentRequest = cheapestProfileRequest && subagentRequest;
5681
5838
  const fastLeadAdvisor = fastProfileRequest && !fastSubagentRequest;
5682
5839
  const maxLeadAdvisor = maxProfileRequest && !maxSubagentRequest;
5683
5840
  const cheapLeadAdvisor = cheapProfileRequest && !cheapSubagentRequest;
5684
- const advisorEnabled = advisorRequested && !fastSubagentRequest && !maxSubagentRequest && !cheapSubagentRequest;
5841
+ const cheapestLeadAdvisor = cheapestProfileRequest && !cheapestSubagentRequest;
5842
+ const advisorEnabled = advisorRequested && !fastSubagentRequest && !maxSubagentRequest && !cheapSubagentRequest && !cheapestSubagentRequest;
5685
5843
  const fastAdvisorEnabled = fastLeadAdvisor && advisorRequested && hasNonEmptyTools(rawBody);
5686
5844
  const maxAdvisorEnabled = maxLeadAdvisor && advisorRequested && hasNonEmptyTools(rawBody);
5687
5845
  const cheapAdvisorEnabled = cheapLeadAdvisor && advisorRequested && hasNonEmptyTools(rawBody);
5688
- const advisorBehaviorEnabled = fastLeadAdvisor ? fastAdvisorEnabled : cheapLeadAdvisor ? cheapAdvisorEnabled : maxLeadAdvisor ? maxAdvisorEnabled : advisorEnabled;
5846
+ const cheapestAdvisorEnabled = cheapestLeadAdvisor && advisorRequested && hasNonEmptyTools(rawBody);
5847
+ const advisorBehaviorEnabled = fastLeadAdvisor ? fastAdvisorEnabled : cheapLeadAdvisor ? cheapAdvisorEnabled : cheapestLeadAdvisor ? cheapestAdvisorEnabled : maxLeadAdvisor ? maxAdvisorEnabled : advisorEnabled;
5689
5848
  let fastAdvisorChoice;
5690
5849
  let maxAdvisorChoice;
5691
5850
  if (maxAdvisorEnabled) {
@@ -5746,10 +5905,31 @@ async function handleCompletion(c) {
5746
5905
  }, 503);
5747
5906
  }
5748
5907
  }
5908
+ if (cheapestAdvisorEnabled) {
5909
+ const mismatch = cheapestAdvisorMetadataMismatch(rawBody);
5910
+ if (mismatch) return c.json({
5911
+ type: "error",
5912
+ error: {
5913
+ type: "invalid_request_error",
5914
+ message: `Cheapest Advisor model mismatch: ${mismatch}. Run \`/advisor ${CHEAPEST_PROFILE_ADVISOR_CLIENT_MODEL}\` to restore the fixed cheapest profile, or relaunch with \`github-router claude -m cheapest\`.`
5915
+ }
5916
+ }, 400);
5917
+ try {
5918
+ fastAdvisorChoice = resolveCheapestAdvisorModel();
5919
+ } catch (error) {
5920
+ return c.json({
5921
+ type: "error",
5922
+ error: {
5923
+ type: "api_error",
5924
+ message: error instanceof Error ? error.message : String(error)
5925
+ }
5926
+ }, 503);
5927
+ }
5928
+ }
5749
5929
  const fastPreprocess = preprocessFastRequest(rawBody, identity.launch, subagentRequest);
5750
5930
  if (fastPreprocess.retiredAlias || fastPreprocess.rejectedAlias || fastPreprocess.rejectedModel) {
5751
5931
  const profileId = identity.launch?.profileId;
5752
- const profileLabel = profileId === "cheap" || profileId === "cheap1m" ? "cheap" : "fast";
5932
+ const profileLabel = profileId === "cheap" || profileId === "cheap1m" ? "cheap" : profileId === "cheapest" ? "cheapest" : "fast";
5753
5933
  const message = fastPreprocess.retiredAlias ? `Router-owned model alias ${JSON.stringify(fastPreprocess.retiredAlias)} belongs to a retired Fast role and is no longer valid. Relaunch or select a current Fast role.` : profileId === "max" ? maxRequestError(fastPreprocess) ?? "Invalid max request" : fastPreprocess.rejectedAlias ? `Router-owned model alias ${JSON.stringify(fastPreprocess.rejectedAlias)} is valid only for an authenticated -m ${profileLabel} launch.` : `Model ${JSON.stringify(fastPreprocess.rejectedModel)} is outside the fixed -m ${profileLabel} model set.`;
5754
5934
  return c.json({
5755
5935
  type: "error",
@@ -5796,7 +5976,7 @@ async function handleCompletion(c) {
5796
5976
  parsedBase = JSON.parse(promptWindowBody);
5797
5977
  } catch {}
5798
5978
  const wantsStream = parsedBase?.stream === true;
5799
- if ((fastAdvisorEnabled || cheapAdvisorEnabled || maxAdvisorEnabled) && wantsStream) {
5979
+ if ((fastAdvisorEnabled || cheapAdvisorEnabled || cheapestAdvisorEnabled || maxAdvisorEnabled) && wantsStream) {
5800
5980
  const initialConversation = Array.isArray(parsedBase.messages) ? parsedBase.messages : [];
5801
5981
  const parsedInitial = parseAnthropicRequest(parsedBase, modelId, selectedModel);
5802
5982
  const translatedAdvisorAborter = new AbortController();
@@ -5819,7 +5999,7 @@ async function handleCompletion(c) {
5819
5999
  effort: maxAdvisorChoice.effort,
5820
6000
  escalated: false,
5821
6001
  fastProfile: false
5822
- } : cheapAdvisorEnabled ? {
6002
+ } : cheapAdvisorEnabled || cheapestAdvisorEnabled ? {
5823
6003
  model: fastAdvisorChoice.model,
5824
6004
  effort: resolveAdvisorEffort(rawBody, fastAdvisorChoice.model, true),
5825
6005
  escalated: fastAdvisorChoice.escalated,
@@ -5839,7 +6019,7 @@ async function handleCompletion(c) {
5839
6019
  advisorEscalated: advisorChoice.escalated,
5840
6020
  advisorFastProfile: advisorChoice.fastProfile,
5841
6021
  advisorMaxProfile: maxAdvisorEnabled,
5842
- advisorCheapProfile: cheapAdvisorEnabled,
6022
+ advisorCheapProfile: cheapAdvisorEnabled || cheapestAdvisorEnabled,
5843
6023
  advisorEffort: advisorChoice.effort,
5844
6024
  externalAborter: translatedAdvisorAborter,
5845
6025
  continueTurn: makeShimContinueTurn(endpoint, {
@@ -5962,10 +6142,10 @@ async function handleCompletion(c) {
5962
6142
  requestHeaders,
5963
6143
  advisorModel: advisorChoice.model,
5964
6144
  advisorEscalated: advisorChoice.escalated,
5965
- advisorFastProfile: fastLeadAdvisor || cheapLeadAdvisor,
6145
+ advisorFastProfile: fastLeadAdvisor || cheapLeadAdvisor || cheapestLeadAdvisor,
5966
6146
  advisorMaxProfile: maxAdvisorEnabled,
5967
- advisorCheapProfile: cheapLeadAdvisor,
5968
- advisorEffort: maxAdvisorChoice ? maxAdvisorChoice.effort : resolveAdvisorEffort(rawBody, advisorChoice.model, fastLeadAdvisor || cheapLeadAdvisor),
6147
+ advisorCheapProfile: cheapLeadAdvisor || cheapestLeadAdvisor,
6148
+ advisorEffort: maxAdvisorChoice ? maxAdvisorChoice.effort : resolveAdvisorEffort(rawBody, advisorChoice.model, fastLeadAdvisor || cheapLeadAdvisor || cheapestLeadAdvisor),
5969
6149
  externalAborter: advisorAborter
5970
6150
  }), {
5971
6151
  status: response.status,
@@ -7113,6 +7293,7 @@ async function setupAndServe(options) {
7113
7293
  state.showToken = options.showToken;
7114
7294
  state.extendedBetas = options.extendedBetas;
7115
7295
  state.browseEnabled = options.browseEnabled || process.env.GH_ROUTER_ENABLE_BROWSE === "1";
7296
+ state.searchEnabled = options.searchEnabled || process.env.GH_ROUTER_ENABLE_SEMANTIC_SEARCH === "1";
7116
7297
  state.fleetEnabled = options.fleetEnabled || process.env.GH_ROUTER_ENABLE_FLEET === "1";
7117
7298
  state.agentsEnabled = options.agentsEnabled || process.env.GH_ROUTER_ENABLE_AGENTS === "1";
7118
7299
  state.powerBrowseEnabled = options.powerBrowseEnabled || process.env.GH_ROUTER_ENABLE_POWER_BROWSE === "1";
@@ -7261,6 +7442,11 @@ const sharedServerArgs = {
7261
7442
  type: "boolean",
7262
7443
  default: true,
7263
7444
  description: "Update github-router itself to the latest npm version on launch (throttled once/hour). Best-effort and non-blocking: the proxy serves immediately and a detached updater applies the new version after this process exits (it takes effect on the NEXT launch; the running process keeps its current build). Disable with --no-self-update or GH_ROUTER_NO_SELF_UPDATE=1. Skipped silently if npm/network unavailable."
7445
+ },
7446
+ search: {
7447
+ type: "boolean",
7448
+ default: false,
7449
+ description: "Enable ColBERT/colgrep semantic code search (meaning-ranked `code` tool results over a per-workspace index, with transparent lexical fallback). Off by default; the `code` tool is lexical-only unless this is set. Can also be enabled with GH_ROUTER_ENABLE_SEMANTIC_SEARCH=1. GH_ROUTER_DISABLE_SEMANTIC_SEARCH=1 hard-disables (wins over --search, for tests)."
7264
7450
  }
7265
7451
  };
7266
7452
  const allowedAccountTypes = /* @__PURE__ */ new Set([
@@ -7302,7 +7488,8 @@ function parseSharedArgs(args) {
7302
7488
  fleetEnabled: args.fleet,
7303
7489
  agentsEnabled: args.agents,
7304
7490
  powerBrowseEnabled: args["power-browse"],
7305
- humanlikeEnabled: args.humanlike
7491
+ humanlikeEnabled: args.humanlike,
7492
+ searchEnabled: args.search
7306
7493
  };
7307
7494
  }
7308
7495
  /**
@@ -7374,23 +7561,24 @@ function getClaudeCodeEnvVars(serverUrl, model, launchProfileId = "standard", pi
7374
7561
  if (process.env.MCP_TOOL_TIMEOUT === void 0) vars.MCP_TOOL_TIMEOUT = mcpToolTimeoutMs;
7375
7562
  const isFastProfile = launchProfileId === "fast";
7376
7563
  const isMaxProfile = launchProfileId === "max";
7377
- const isCheapProfile = launchProfileId === "cheap" || launchProfileId === "cheap1m";
7564
+ const isCheapProfile = launchProfileId === "cheap" || launchProfileId === "cheap1m" || launchProfileId === "cheapest";
7565
+ const routerWinsTiers = isFastProfile || isCheapProfile;
7378
7566
  const smallFastModel = isMaxProfile ? MAX_LUNA_HIGH_ALIAS_ID : isFastProfile ? LUNA_HAIKU_ALIAS_ID : isCheapProfile ? LUNA_HAIKU_ALIAS_ID : isBudgetClaudeLead(model) && (state.models?.data?.some((m) => m.id === "claude-haiku-4.5") ?? false) ? BUDGET_SMALL_FAST_SLUG : "claude-sonnet-5";
7379
- if (process.env.ANTHROPIC_SMALL_FAST_MODEL === void 0) vars.ANTHROPIC_SMALL_FAST_MODEL = (isFastProfile || isMaxProfile) && !isCheapProfile ? oneMSuffixForAlias(smallFastModel) : smallFastModel;
7567
+ if (process.env.ANTHROPIC_SMALL_FAST_MODEL === void 0 || routerWinsTiers) vars.ANTHROPIC_SMALL_FAST_MODEL = (isFastProfile || isMaxProfile) && !isCheapProfile ? oneMSuffixForAlias(smallFastModel) : smallFastModel;
7380
7568
  const seedTierRow = (modelKey, nameKey, bareSlug) => {
7381
7569
  if (process.env[modelKey] !== void 0) return;
7382
7570
  vars[modelKey] = withOneMSuffixForLead(bareSlug);
7383
7571
  if (process.env[nameKey] === void 0) vars[nameKey] = bareSlug;
7384
7572
  };
7385
- const seedFastAliasTierRow = (modelKey, nameKey, aliasId, displayName) => {
7386
- if (process.env[modelKey] !== void 0) return;
7573
+ const seedFastAliasTierRow = (modelKey, nameKey, aliasId, displayName, force = false) => {
7574
+ if (!force && process.env[modelKey] !== void 0) return;
7387
7575
  vars[modelKey] = oneMSuffixForAlias(aliasId);
7388
- if (process.env[nameKey] === void 0) vars[nameKey] = displayName;
7576
+ if (force || process.env[nameKey] === void 0) vars[nameKey] = displayName;
7389
7577
  };
7390
- const seedCheapAliasTierRow = (modelKey, nameKey, aliasId, displayName) => {
7391
- if (process.env[modelKey] !== void 0) return;
7578
+ const seedCheapAliasTierRow = (modelKey, nameKey, aliasId, displayName, force = false) => {
7579
+ if (!force && process.env[modelKey] !== void 0) return;
7392
7580
  vars[modelKey] = aliasId;
7393
- if (process.env[nameKey] === void 0) vars[nameKey] = displayName;
7581
+ if (force || process.env[nameKey] === void 0) vars[nameKey] = displayName;
7394
7582
  };
7395
7583
  if (isMaxProfile) {
7396
7584
  const seedMaxRow = (modelKey, nameKey, id) => {
@@ -7406,26 +7594,26 @@ function getClaudeCodeEnvVars(serverUrl, model, launchProfileId = "standard", pi
7406
7594
  if (process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = "GPT-5.6 Sol";
7407
7595
  }
7408
7596
  } else if (isCheapProfile) {
7409
- seedCheapAliasTierRow("ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME", LUNA_SONNET_ALIAS_ID, "GPT-5.6 Luna (xhigh)");
7410
- seedCheapAliasTierRow("ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME", LUNA_HAIKU_ALIAS_ID, "GPT-5.6 Luna (high)");
7597
+ seedCheapAliasTierRow("ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME", LUNA_SONNET_ALIAS_ID, "GPT-5.6 Luna (xhigh)", routerWinsTiers);
7598
+ seedCheapAliasTierRow("ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME", LUNA_HAIKU_ALIAS_ID, "GPT-5.6 Luna (high)", routerWinsTiers);
7411
7599
  const cheapAliasCapabilities = "effort,xhigh_effort,max_effort,thinking,adaptive_thinking,interleaved_thinking";
7412
- if (process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES = cheapAliasCapabilities;
7413
- if (process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES = cheapAliasCapabilities;
7414
- if (process.env.ANTHROPIC_CUSTOM_MODEL_OPTION === void 0) {
7600
+ if (routerWinsTiers || process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES = cheapAliasCapabilities;
7601
+ if (routerWinsTiers || process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES = cheapAliasCapabilities;
7602
+ if (routerWinsTiers || process.env.ANTHROPIC_CUSTOM_MODEL_OPTION === void 0) {
7415
7603
  vars.ANTHROPIC_CUSTOM_MODEL_OPTION = LUNA_DRIVER_ALIAS_ID;
7416
- if (process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = "GPT-5.6 Luna (max)";
7417
- if (process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES = cheapAliasCapabilities;
7604
+ if (routerWinsTiers || process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = "GPT-5.6 Luna (max)";
7605
+ if (routerWinsTiers || process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES = cheapAliasCapabilities;
7418
7606
  }
7419
7607
  } else if (isFastProfile) {
7420
- seedFastAliasTierRow("ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME", LUNA_SONNET_ALIAS_ID, "GPT-5.6 Luna (xhigh)");
7421
- seedFastAliasTierRow("ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME", LUNA_HAIKU_ALIAS_ID, "GPT-5.6 Luna (high)");
7608
+ seedFastAliasTierRow("ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME", LUNA_SONNET_ALIAS_ID, "GPT-5.6 Luna (xhigh)", routerWinsTiers);
7609
+ seedFastAliasTierRow("ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME", LUNA_HAIKU_ALIAS_ID, "GPT-5.6 Luna (high)", routerWinsTiers);
7422
7610
  const fastAliasCapabilities = "effort,xhigh_effort,max_effort,thinking,adaptive_thinking,interleaved_thinking";
7423
- if (process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES = fastAliasCapabilities;
7424
- if (process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES = fastAliasCapabilities;
7425
- if (process.env.ANTHROPIC_CUSTOM_MODEL_OPTION === void 0) {
7611
+ if (routerWinsTiers || process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES = fastAliasCapabilities;
7612
+ if (routerWinsTiers || process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES = fastAliasCapabilities;
7613
+ if (routerWinsTiers || process.env.ANTHROPIC_CUSTOM_MODEL_OPTION === void 0) {
7426
7614
  vars.ANTHROPIC_CUSTOM_MODEL_OPTION = oneMSuffixForAlias(LUNA_DRIVER_ALIAS_ID);
7427
- if (process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = "GPT-5.6 Luna (max)";
7428
- if (process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES = fastAliasCapabilities;
7615
+ if (routerWinsTiers || process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = "GPT-5.6 Luna (max)";
7616
+ if (routerWinsTiers || process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES === void 0) vars.ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES = fastAliasCapabilities;
7429
7617
  }
7430
7618
  } else {
7431
7619
  seedTierRow("ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME", "claude-sonnet-5");
@@ -7522,6 +7710,6 @@ function getCodexEnvVars(serverUrl) {
7522
7710
  return vars;
7523
7711
  }
7524
7712
  //#endregion
7525
- export { checkClaudeVersion as C, runSelfUpdate as S, resolveLaunchProfile as _, sharedServerArgs as a, validateFastProfilePrerequisites as b, stopKeepAwake as c, enableFileLogging as d, LUNA_SCOUT_ALIAS_ID as f, profileDescriptor as g, formatFastPrerequisiteFailure as h, setupAndServe as i, injectModelPickerSettingsFile as l, formatCheapPrerequisiteFailure as m, getCodexEnvVars as n, LAUNCH_SECRET_HEADER as o, formatCheap1mPrerequisiteFailure as p, parseSharedArgs as r, startKeepAwake as s, getClaudeCodeEnvVars as t, listModelsForEndpoint as u, validateCheap1mProfilePrerequisites as v, updateClaude as w, validateMaxProfileLaunch as x, validateCheapProfilePrerequisites as y };
7713
+ export { validateMaxProfileLaunch as C, updateClaude as E, validateFastProfilePrerequisites as S, checkClaudeVersion as T, profileDescriptor as _, sharedServerArgs as a, validateCheapProfilePrerequisites as b, stopKeepAwake as c, enableFileLogging as d, LUNA_SCOUT_ALIAS_ID as f, formatFastPrerequisiteFailure as g, formatCheapestPrerequisiteFailure as h, setupAndServe as i, injectModelPickerSettingsFile as l, formatCheapPrerequisiteFailure as m, getCodexEnvVars as n, LAUNCH_SECRET_HEADER as o, formatCheap1mPrerequisiteFailure as p, parseSharedArgs as r, startKeepAwake as s, getClaudeCodeEnvVars as t, listModelsForEndpoint as u, resolveLaunchProfile as v, runSelfUpdate as w, validateCheapestProfilePrerequisites as x, validateCheap1mProfilePrerequisites as y };
7526
7714
 
7527
- //# sourceMappingURL=server-setup-D7ABbEs1.js.map
7715
+ //# sourceMappingURL=server-setup-0PaS4m2B.js.map