github-router 0.3.304 → 0.3.305

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/{attribution-settings-C8iSwEAZ.js → attribution-settings-Chqw6VeK.js} +3 -3
  2. package/dist/{attribution-settings-C8iSwEAZ.js.map → attribution-settings-Chqw6VeK.js.map} +1 -1
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/{claude-Drv0roq1.js → claude-C3LWG_3H.js} +16 -7
  5. package/dist/claude-C3LWG_3H.js.map +1 -0
  6. package/dist/{codex-kgVL5OyN.js → codex-DdhBGec4.js} +4 -4
  7. package/dist/{codex-kgVL5OyN.js.map → codex-DdhBGec4.js.map} +1 -1
  8. package/dist/engine-C7DkYq2g.js +2 -0
  9. package/dist/{gate-discovery-D4-F99e_.js → gate-discovery-C6jB3bBG.js} +2 -2
  10. package/dist/{gate-discovery-D4-F99e_.js.map → gate-discovery-C6jB3bBG.js.map} +1 -1
  11. package/dist/{internal-stop-hook-D8LIWryj.js → internal-stop-hook-EPAu3tkg.js} +2 -2
  12. package/dist/{internal-stop-hook-D8LIWryj.js.map → internal-stop-hook-EPAu3tkg.js.map} +1 -1
  13. package/dist/main.js +5 -5
  14. package/dist/{peer-mcp-personas-D4bHdjOx.js → peer-mcp-personas-C9fDtu69.js} +3 -3
  15. package/dist/{peer-mcp-personas-D4bHdjOx.js.map → peer-mcp-personas-C9fDtu69.js.map} +1 -1
  16. package/dist/{provision-D3_GtXze.js → provision-Bn4FOzR4.js} +2 -2
  17. package/dist/{provision-D3_GtXze.js.map → provision-Bn4FOzR4.js.map} +1 -1
  18. package/dist/{serve-DPRZX-2j.js → serve-7q23O8hl.js} +22 -6
  19. package/dist/serve-7q23O8hl.js.map +1 -0
  20. package/dist/{server-setup-CSkdFAPP.js → server-setup-BP_JM0qb.js} +158 -192
  21. package/dist/server-setup-BP_JM0qb.js.map +1 -0
  22. package/dist/{start-C6G5tu81.js → start-wa7_DyyG.js} +3 -3
  23. package/dist/{start-C6G5tu81.js.map → start-wa7_DyyG.js.map} +1 -1
  24. package/package.json +1 -1
  25. package/dist/claude-Drv0roq1.js.map +0 -1
  26. package/dist/engine-xuIzQNV1.js +0 -2
  27. package/dist/serve-DPRZX-2j.js.map +0 -1
  28. package/dist/server-setup-CSkdFAPP.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { $ as UNKNOWN_EFFORT_ANCHOR, An as MAX_LUNA_HIGH_ALIAS_ID, At as countTokens, B as resolveAdvisorEffort, Bn as resolveModelAlias, Bt as resolveMcpToolTimeoutMs, Cn as withOneMSuffix, D as toolbeltEnabled, Dn as LUNA_REAL_MODEL_ID, En as LUNA_HAIKU_ALIAS_ID, F as ADVISOR_TOOL_INSTRUCTIONS, Fn as isRetiredFastModelAlias, Ft as findLaunchBySecret, G as repairRejectedThinkingHistory, Gt as parseJsonOrDiagnose, H as formatThinkingRepairDecline, Ht as createChatCompletions, I as FAST_ADVISOR_TOOL_INSTRUCTIONS, In as maxAliasEffort, J as isControllerClosedError, K as buildAnthropicErrorEvent, Kt as normalizeOpenAIUsage, L as buildAdvisorStream, Ln as maxAliasModel, Mn as canonicalizeAliasModel, Mt as getTextTokenCount, N as searchWeb, Nt as getTokenCount, P as ADVISOR_INTERNAL_TOOL_NAME, Pn as isMaxModelAlias, Pt as getTokenizerFromModel, Q as EFFORT_ORDER, R as injectAdvisorTool, Rt as assembleResponsesPayload, Sn as oneMContextDisabled, Tn as LUNA_DRIVER_ALIAS_ID, U as rememberThinkingHistoryRepair, Un as withInstallLock, Ut as MAX_RESPONSE_BODY_BYTES, V as resolveAdvisorModel, Vt as createResponses, W as repairKnownThinkingHistory, Wt as readResponseBodyCapped, X as readIteratorWithTimeout, Y as logStreamError, Z as relayAnthropicStream, an as toolbeltPathOverride, bn as classifyMessagesRoute, en as provisionTreeSitterAssets, et as bucketEffort, fn as UPSTREAM_FETCH_TIMEOUT_MS, hn as isBudgetClaudeLead, i as assertMcpToolSurfaceConsistent, it as agentToolsEnabled, jn as MAX_LUNA_MAX_ALIAS_ID, jt as createMessages, kn as LUNA_SONNET_ALIAS_ID, kt as shimDefaultsToXhigh, mn as generateRandomPort, nt as handleMcpDelete, pn as UPSTREAM_INACTIVITY_TIMEOUT_MS, q as buildOpenAIErrorEvent, rt as handleMcpPost, sn as BUDGET_SMALL_FAST_SLUG, tt as clampEffort, vn as upstreamAllowH2, wn as withOneMSuffixForLead, xn as catalogAdvertises1M, yn as upstreamMaxConnections, z as isAdvisorRequested, zt as warnOnTokenPriceDrift } from "./peer-mcp-personas-D4bHdjOx.js";
1
+ import { $ as UNKNOWN_EFFORT_ANCHOR, An as MAX_LUNA_HIGH_ALIAS_ID, At as countTokens, B as resolveAdvisorEffort, Bn as resolveModelAlias, Bt as resolveMcpToolTimeoutMs, Cn as withOneMSuffix, D as toolbeltEnabled, Dn as LUNA_REAL_MODEL_ID, En as LUNA_HAIKU_ALIAS_ID, F as ADVISOR_TOOL_INSTRUCTIONS, Fn as isRetiredFastModelAlias, Ft as findLaunchBySecret, G as repairRejectedThinkingHistory, Gt as parseJsonOrDiagnose, H as formatThinkingRepairDecline, Ht as createChatCompletions, I as FAST_ADVISOR_TOOL_INSTRUCTIONS, In as maxAliasEffort, J as isControllerClosedError, K as buildAnthropicErrorEvent, Kt as normalizeOpenAIUsage, L as buildAdvisorStream, Ln as maxAliasModel, Mn as canonicalizeAliasModel, Mt as getTextTokenCount, N as searchWeb, Nt as getTokenCount, P as ADVISOR_INTERNAL_TOOL_NAME, Pn as isMaxModelAlias, Pt as getTokenizerFromModel, Q as EFFORT_ORDER, R as injectAdvisorTool, Rt as assembleResponsesPayload, Sn as oneMContextDisabled, Tn as LUNA_DRIVER_ALIAS_ID, U as rememberThinkingHistoryRepair, Un as withInstallLock, Ut as MAX_RESPONSE_BODY_BYTES, V as resolveAdvisorModel, Vt as createResponses, W as repairKnownThinkingHistory, Wt as readResponseBodyCapped, X as readIteratorWithTimeout, Y as logStreamError, Z as relayAnthropicStream, an as toolbeltPathOverride, bn as classifyMessagesRoute, en as provisionTreeSitterAssets, et as bucketEffort, fn as UPSTREAM_FETCH_TIMEOUT_MS, hn as isBudgetClaudeLead, i as assertMcpToolSurfaceConsistent, it as agentToolsEnabled, jn as MAX_LUNA_MAX_ALIAS_ID, jt as createMessages, kn as LUNA_SONNET_ALIAS_ID, kt as shimDefaultsToXhigh, mn as generateRandomPort, nt as handleMcpDelete, pn as UPSTREAM_INACTIVITY_TIMEOUT_MS, q as buildOpenAIErrorEvent, rt as handleMcpPost, sn as BUDGET_SMALL_FAST_SLUG, tt as clampEffort, vn as upstreamAllowH2, wn as withOneMSuffixForLead, xn as catalogAdvertises1M, yn as upstreamMaxConnections, z as isAdvisorRequested, zt as warnOnTokenPriceDrift } from "./peer-mcp-personas-C9fDtu69.js";
2
2
  import { t as getPackageVersion } from "./version-C8x2hQrZ.js";
3
3
  import { i as ensurePaths, t as PATHS } from "./paths-IcZW8gZx.js";
4
4
  import { t as state } from "./state-B8adscCv.js";
@@ -8,9 +8,7 @@ import { a as resolveExecutable, n as killManagedTree, o as runCommandCapture, r
8
8
  import { r as FAST_PROFILE_ADVISOR_MODEL } from "./fast-profile-contract-OuZQaGif.js";
9
9
  import { d as maxAdvisorPinIsValid, i as MAX_PROFILE_MODELS, l as maxAdvisorEffortForModel, m as maxOpusModel, n as MAX_PROFILE_ALLOWED_LEAD_MODEL_IDS, t as MAX_PROFILE_ADVISOR_INSTRUCTIONS, u as maxAdvisorModelFromPin, x as stripTrailingOneMSuffix } from "./max-profile-contract-CiD5wyET.js";
10
10
  import consola from "consola";
11
- import * as fs$2 from "node:fs";
12
11
  import fs, { existsSync } from "node:fs";
13
- import * as nodePath from "node:path";
14
12
  import path from "node:path";
15
13
  import { createHash, randomUUID } from "node:crypto";
16
14
  import fs$1 from "node:fs/promises";
@@ -648,6 +646,155 @@ function listModelsForEndpoint(path) {
648
646
  }).map((m) => m.id);
649
647
  }
650
648
  //#endregion
649
+ //#region src/lib/model-picker-settings.ts
650
+ const STANDARD_PICKER_MODELS = Object.freeze([
651
+ {
652
+ id: "gpt-5.6-sol",
653
+ label: "GPT-5.6 Sol",
654
+ behavesAs: "claude-opus-5"
655
+ },
656
+ {
657
+ id: "gpt-5.6-luna",
658
+ label: "GPT-5.6 Luna",
659
+ behavesAs: "claude-opus-5"
660
+ },
661
+ {
662
+ id: "gemini-3.8-flash",
663
+ label: "Gemini 3.8 Flash",
664
+ behavesAs: "claude-sonnet-5"
665
+ },
666
+ {
667
+ id: "grok-4.6",
668
+ label: "Grok 4.6",
669
+ behavesAs: "claude-sonnet-5",
670
+ neverOneM: true
671
+ }
672
+ ]);
673
+ const MAX_PICKER_MODELS = Object.freeze([
674
+ {
675
+ id: MAX_PROFILE_MODELS.sol,
676
+ label: "GPT-5.6 Sol",
677
+ behavesAs: "claude-opus-5"
678
+ },
679
+ {
680
+ id: MAX_PROFILE_MODELS.luna,
681
+ label: "GPT-5.6 Luna",
682
+ behavesAs: "claude-opus-5"
683
+ },
684
+ {
685
+ id: MAX_PROFILE_MODELS.gemini,
686
+ label: "Gemini 3.8 Flash",
687
+ behavesAs: "claude-sonnet-5"
688
+ },
689
+ {
690
+ id: MAX_PROFILE_MODELS.opus,
691
+ label: "Claude Opus 5",
692
+ behavesAs: "claude-opus-5"
693
+ }
694
+ ]);
695
+ /**
696
+ * Return the ordered, profile-specific `/model` rows supported by the live
697
+ * Copilot catalog. Fast intentionally shares Standard's four-row inventory;
698
+ * Max replaces Grok with Opus because Grok is not an allowed Max lead.
699
+ *
700
+ * The `[1m]` suffix is Claude Code's local accounting marker and is never sent
701
+ * upstream. `withOneMSuffix` attaches it only when the exact live entry serves
702
+ * at least 1M and the user has not opted out. `behavesAs` is required by Claude
703
+ * Code 2.1.260 to OFFER an otherwise-unknown modelPicker row. It supplies the
704
+ * closest known client-side prompt/capability profile without changing the row
705
+ * label or selected model id; the proxy's request preprocessors still enforce
706
+ * each profile's actual model/effort contract.
707
+ */
708
+ function selectableModelsInCatalog(profile) {
709
+ const catalog = state.models?.data;
710
+ if (!catalog || catalog.length === 0) return [];
711
+ const present = new Set(catalog.map((entry) => entry.id));
712
+ return (profile === "max" ? MAX_PICKER_MODELS : STANDARD_PICKER_MODELS).filter((entry) => present.has(entry.id)).map((entry) => ({
713
+ model: entry.neverOneM ? entry.id : withOneMSuffix(entry.id),
714
+ label: entry.label,
715
+ behavesAs: entry.behavesAs
716
+ }));
717
+ }
718
+ const RENAME_RETRY_DELAYS_MS = [
719
+ 25,
720
+ 75,
721
+ 200
722
+ ];
723
+ const RETRYABLE_RENAME_CODES = /* @__PURE__ */ new Set([
724
+ "EACCES",
725
+ "EBUSY",
726
+ "EPERM"
727
+ ]);
728
+ async function renameSettingsWithRetry(temp, target) {
729
+ let lastError;
730
+ for (let attempt = 0; attempt <= RENAME_RETRY_DELAYS_MS.length; attempt += 1) try {
731
+ await fs$1.rename(temp, target);
732
+ return;
733
+ } catch (error) {
734
+ lastError = error;
735
+ if (!RETRYABLE_RENAME_CODES.has(error.code ?? "") || attempt === RENAME_RETRY_DELAYS_MS.length) break;
736
+ await new Promise((resolve) => setTimeout(resolve, RENAME_RETRY_DELAYS_MS[attempt]));
737
+ }
738
+ await fs$1.rm(temp, { force: true }).catch(() => {});
739
+ throw lastError;
740
+ }
741
+ function modelIdsFromExistingPicker(value) {
742
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
743
+ const options = value.options;
744
+ if (!Array.isArray(options)) return [];
745
+ return options.flatMap((option) => {
746
+ if (!option || typeof option !== "object" || Array.isArray(option)) return [];
747
+ const model = option.model;
748
+ return typeof model === "string" && model.trim() !== "" ? [model] : [];
749
+ });
750
+ }
751
+ async function injectModelPickerSettingsFile(settingsPath, profile) {
752
+ const options = selectableModelsInCatalog(profile);
753
+ let existing = {};
754
+ let raw;
755
+ try {
756
+ raw = await fs$1.readFile(settingsPath, "utf8");
757
+ } catch (error) {
758
+ if (error.code !== "ENOENT") throw error;
759
+ }
760
+ if (raw !== void 0) {
761
+ const parsed = JSON.parse(raw);
762
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`settings.json at ${settingsPath} is not a JSON object; refusing to overwrite`);
763
+ existing = parsed;
764
+ }
765
+ if ("modelPicker" in existing) return {
766
+ written: false,
767
+ reason: "user-set",
768
+ models: modelIdsFromExistingPicker(existing.modelPicker)
769
+ };
770
+ if (options.length === 0) return {
771
+ written: false,
772
+ reason: "no-models",
773
+ models: []
774
+ };
775
+ const merged = {
776
+ ...existing,
777
+ modelPicker: {
778
+ options,
779
+ replaceBuiltInOptions: false
780
+ }
781
+ };
782
+ const content = `${JSON.stringify(merged, null, 2)}\n`;
783
+ const temp = `${settingsPath}.${process.pid}.${Math.random().toString(36).slice(2)}.picker.tmp`;
784
+ await fs$1.mkdir(path.dirname(settingsPath), { recursive: true });
785
+ try {
786
+ await fs$1.writeFile(temp, content, { mode: 384 });
787
+ await renameSettingsWithRetry(temp, settingsPath);
788
+ } catch (error) {
789
+ await fs$1.rm(temp, { force: true }).catch(() => {});
790
+ throw error;
791
+ }
792
+ return {
793
+ written: true,
794
+ models: options.map((option) => option.model)
795
+ };
796
+ }
797
+ //#endregion
651
798
  //#region src/lib/keep-awake/flags.ts
652
799
  /**
653
800
  * Env-flag parsing for the Windows keep-awake feature. Pure +
@@ -1502,7 +1649,7 @@ function collectToolFieldKeys(body) {
1502
1649
  //#endregion
1503
1650
  //#region package.json
1504
1651
  var name = "github-router";
1505
- var version = "0.3.304";
1652
+ var version = "0.3.305";
1506
1653
  //#endregion
1507
1654
  //#region src/lib/approval.ts
1508
1655
  const awaitApproval = async () => {
@@ -6541,183 +6688,6 @@ function parseSharedArgs(args) {
6541
6688
  };
6542
6689
  }
6543
6690
  /**
6544
- * Non-Claude models we surface as first-class, selectable rows in Claude
6545
- * Code's model picker (Phase 3 of native-non-claude-models, later
6546
- * modernized to exactly these four live models by the fast-launch-profile
6547
- * change). The main agent loop runs on them through the `/v1/messages`
6548
- * translation shim (`src/lib/anthropic-translate/*`, branched in
6549
- * `routes/messages/handler.ts`) that forwards non-Claude targets to
6550
- * Copilot `/responses` (gpt) or `/chat/completions` (gemini/grok).
6551
- *
6552
- * This list is EXACT and STATIC — no dynamic Gemini-review append (the
6553
- * earlier `gemini-3.1-pro-preview`-preferred / `gemini-3.8-flash`-fallback
6554
- * row is retired: `gemini-3.8-flash` is now a first-class row on its own,
6555
- * always at this fixed id). A model missing from the catalog is simply
6556
- * omitted, never substituted — see `nativeSelectableModelsInCatalog`.
6557
- *
6558
- * Display labels only: the gateway-model cache schema Claude Code reads is
6559
- * `{id, display_name?}` per model — there is NO per-model context-window
6560
- * field. Context accounting is instead driven off the id itself, via the
6561
- * `[1m]` literal-bracket suffix `nativeSelectableModelsInCatalog` attaches to
6562
- * every row the catalog says serves >=1M. See `withOneMSuffix`.
6563
- */
6564
- const NATIVE_NON_CLAUDE_MODELS = [
6565
- {
6566
- id: "gpt-5.6-sol",
6567
- displayName: "GPT-5.6 Sol"
6568
- },
6569
- {
6570
- id: "gpt-5.6-luna",
6571
- displayName: "GPT-5.6 Luna"
6572
- },
6573
- {
6574
- id: "gemini-3.8-flash",
6575
- displayName: "Gemini 3.8 Flash"
6576
- },
6577
- {
6578
- id: "grok-4.6",
6579
- displayName: "Grok 4.6"
6580
- }
6581
- ];
6582
- /**
6583
- * `grok-4.6` never carries `[1m]` — its live-catalog window is 500K total
6584
- * (372K max prompt), genuinely below the 1M accounting threshold, and this
6585
- * project deliberately does NOT inject a global
6586
- * `CLAUDE_CODE_MAX_CONTEXT_TOKENS` override for it (see
6587
- * `docs/default-models.md` "fast launch profile" once landed): Claude Code
6588
- * permits arbitrary bare non-Claude ids and runtime `/model` switches, so a
6589
- * Grok-specific process-global window override would incorrectly follow the
6590
- * session onto every other model after a switch. Grok is simply left bare,
6591
- * which is also its true accounting rather than an over- or under-estimate
6592
- * disguised as one.
6593
- */
6594
- const NEVER_1M_MODEL_IDS = /* @__PURE__ */ new Set(["grok-4.6"]);
6595
- /**
6596
- * The subset of `NATIVE_NON_CLAUDE_MODELS` actually present in the live
6597
- * Copilot catalog. License tiers differ, so a model missing from the
6598
- * catalog is silently dropped — the caller then neither enables discovery
6599
- * nor writes a cache for it, and lesser tiers see the unchanged picker.
6600
- * Pure (reads `state.models`), so it is unit-testable without side effects.
6601
- *
6602
- * The projected id carries a `[1m]` suffix when the catalog advertises a
6603
- * >=1M window for it AND the id isn't in `NEVER_1M_MODEL_IDS`, because
6604
- * Claude Code budgets a gateway-discovered row at its 200K default
6605
- * otherwise. `withOneMSuffix` is catalog-gated on top of that, so a model
6606
- * whose advertised window shrinks below 1M stays bare regardless. The
6607
- * lookup below still keys off the BARE id — the decoration is applied only
6608
- * to the value handed to Claude Code.
6609
- */
6610
- function nativeSelectableModelsInCatalog() {
6611
- const catalog = state.models?.data;
6612
- if (!catalog || catalog.length === 0) return [];
6613
- const present = new Set(catalog.map((m) => m.id));
6614
- return NATIVE_NON_CLAUDE_MODELS.filter((m) => present.has(m.id)).map((m) => ({
6615
- id: NEVER_1M_MODEL_IDS.has(m.id) ? m.id : withOneMSuffix(m.id),
6616
- display_name: m.displayName
6617
- }));
6618
- }
6619
- const MAX_NATIVE_MODELS = [
6620
- {
6621
- id: MAX_PROFILE_MODELS.sol,
6622
- displayName: "GPT-5.6 Sol"
6623
- },
6624
- {
6625
- id: MAX_PROFILE_MODELS.luna,
6626
- displayName: "GPT-5.6 Luna"
6627
- },
6628
- {
6629
- id: MAX_PROFILE_MODELS.gemini,
6630
- displayName: "Gemini 3.8 Flash"
6631
- },
6632
- {
6633
- id: MAX_PROFILE_MODELS.opus,
6634
- displayName: "Claude Opus 5"
6635
- }
6636
- ];
6637
- function maxSelectableModelsInCatalog() {
6638
- return MAX_NATIVE_MODELS.filter((model) => state.models?.data.some((entry) => entry.id === model.id)).map((model) => ({
6639
- id: withOneMSuffix(model.id),
6640
- display_name: model.displayName
6641
- }));
6642
- }
6643
- /**
6644
- * Pre-seed Claude Code's gateway-model discovery cache so the non-Claude
6645
- * models appear as selectable picker rows WITHOUT the network fetch.
6646
- *
6647
- * Verified against the installed Claude Code build (2.1.201): the picker
6648
- * builder reads `<CLAUDE_CONFIG_DIR>/cache/gateway-models.json`
6649
- * (schema `{baseUrl: string, fetchedAt: number, models: [{id, display_name?}]}`)
6650
- * and — when gateway discovery is enabled (first-party auth mode +
6651
- * `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` set + a non-`api.anthropic.com`
6652
- * `ANTHROPIC_BASE_URL`, all true for the proxy) — maps each cached model to
6653
- * a picker row `{value: id, label: display_name}`. Critically, the
6654
- * cache-READ path applies NO id filter; the `/^(claude|anthropic)/i` filter
6655
- * lives ONLY in the network-FETCH path. So a pre-seeded cache can carry the
6656
- * real Copilot ids (`gpt-5.5`, `gemini-3.1-pro-preview`, …) — no `claude-*`
6657
- * alias needed — and selecting a row sends that real id, which
6658
- * `resolveModel()` exact-matches and the `/v1/messages` shim routes.
6659
- *
6660
- * The network fetch never overwrites this seed: it bails when nonessential
6661
- * traffic is disabled, and the proxy ALWAYS sets
6662
- * `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`, so the fetch returns before
6663
- * it can write. The seed is therefore authoritative for the session.
6664
- *
6665
- * `baseUrl` MUST equal the `ANTHROPIC_BASE_URL` Claude Code sees
6666
- * (`serverUrl`) or the cache is discarded. `configDir` defaults to
6667
- * `PATHS.CLAUDE_CONFIG_DIR` — the same dir the proxy points
6668
- * `CLAUDE_CONFIG_DIR` at — so the write target and Claude Code's read
6669
- * target are identical by construction.
6670
- *
6671
- * Best-effort: every failure is swallowed — a missing picker row must never
6672
- * break launch. This is coupled to Claude Code's internal cache path/schema;
6673
- * if a future build changes them the read simply ignores the seed and the
6674
- * rows don't appear (graceful degradation). Returns whether a file was
6675
- * written (for tests/observability).
6676
- *
6677
- * The write is atomic (temp file in the same dir + rename) so a Claude Code
6678
- * read can never observe a torn/partial JSON (which its safeParse would
6679
- * reject, dropping the rows). Rename-over-existing is atomic on POSIX and
6680
- * Windows (libuv MoveFileEx REPLACE_EXISTING).
6681
- */
6682
- function seedGatewayModelCache(serverUrl, models, configDir = PATHS.CLAUDE_CONFIG_DIR) {
6683
- if (models.length === 0) return false;
6684
- const cacheDir = nodePath.join(configDir, "cache");
6685
- const target = nodePath.join(cacheDir, "gateway-models.json");
6686
- const tmp = nodePath.join(cacheDir, `gateway-models.json.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`);
6687
- try {
6688
- fs$2.mkdirSync(cacheDir, { recursive: true });
6689
- const payload = {
6690
- baseUrl: serverUrl,
6691
- fetchedAt: Date.now(),
6692
- models: models.map((m) => ({
6693
- id: m.id,
6694
- display_name: m.display_name
6695
- }))
6696
- };
6697
- fs$2.writeFileSync(tmp, JSON.stringify(payload), "utf-8");
6698
- fs$2.renameSync(tmp, target);
6699
- return true;
6700
- } catch {
6701
- try {
6702
- fs$2.rmSync(tmp, { force: true });
6703
- } catch {}
6704
- return false;
6705
- }
6706
- }
6707
- /**
6708
- * Remove any seeded gateway-model cache. Called when the current catalog
6709
- * carries none of the target models, so a user who has pinned
6710
- * `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` on cannot surface rows for
6711
- * models that are no longer available. Best-effort (per-launch config dirs
6712
- * make a stale file rare, but this closes the pinned-port + catalog-change
6713
- * seam). Never throws.
6714
- */
6715
- function clearGatewayModelCache(configDir = PATHS.CLAUDE_CONFIG_DIR) {
6716
- try {
6717
- fs$2.rmSync(nodePath.join(configDir, "cache", "gateway-models.json"), { force: true });
6718
- } catch {}
6719
- }
6720
- /**
6721
6691
  * Build environment variables for Claude Code.
6722
6692
  *
6723
6693
  * The parent env is sanitized of every key in `STRIPPED_PARENT_ENV_KEYS`
@@ -6772,7 +6742,7 @@ function oneMSuffixForAlias(aliasId) {
6772
6742
  function oneMSuffixForMaxModel(id) {
6773
6743
  return withOneMSuffix(id);
6774
6744
  }
6775
- function getClaudeCodeEnvVars(serverUrl, model, launchProfileId = "standard") {
6745
+ function getClaudeCodeEnvVars(serverUrl, model, launchProfileId = "standard", pickerModels) {
6776
6746
  const vars = {
6777
6747
  ANTHROPIC_BASE_URL: serverUrl,
6778
6748
  CLAUDE_CONFIG_DIR: PATHS.CLAUDE_CONFIG_DIR,
@@ -6835,11 +6805,7 @@ function getClaudeCodeEnvVars(serverUrl, model, launchProfileId = "standard") {
6835
6805
  "CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING",
6836
6806
  "CLAUDE_CODE_ENABLE_TASKS"
6837
6807
  ]) if (process.env[key] === void 0) vars[key] = "1";
6838
- const nativeModels = isMaxProfile ? maxSelectableModelsInCatalog() : nativeSelectableModelsInCatalog();
6839
- if (nativeModels.length > 0) {
6840
- if (seedGatewayModelCache(serverUrl, nativeModels) && process.env.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY === void 0 && vars.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY === void 0) vars.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY = "1";
6841
- } else clearGatewayModelCache();
6842
- applyAutoCompactWindow(vars, launchProfileId);
6808
+ applyAutoCompactWindow(vars, launchProfileId, pickerModels);
6843
6809
  if (toolbeltEnabled()) Object.assign(vars, toolbeltPathOverride(process.env, PATHS.TOOLBELT_BIN_DIR));
6844
6810
  return vars;
6845
6811
  }
@@ -6884,7 +6850,7 @@ function catalogEntryForSeededModel(value) {
6884
6850
  *
6885
6851
  * Presence-guarded on the parent env, symmetric with every other guard here.
6886
6852
  */
6887
- function applyAutoCompactWindow(vars, launchProfileId) {
6853
+ function applyAutoCompactWindow(vars, launchProfileId, pickerModels) {
6888
6854
  if (process.env.CLAUDE_CODE_AUTO_COMPACT_WINDOW !== void 0) return;
6889
6855
  let tightestWindow;
6890
6856
  const consider = (value) => {
@@ -6894,8 +6860,8 @@ function applyAutoCompactWindow(vars, launchProfileId) {
6894
6860
  if (candidateWindow !== void 0 && (tightestWindow === void 0 || candidateWindow < tightestWindow)) tightestWindow = candidateWindow;
6895
6861
  };
6896
6862
  for (const key of LEAD_CAPABLE_MODEL_ENV_KEYS) consider(vars[key] ?? process.env[key]);
6897
- const gatewayModels = launchProfileId === "max" ? maxSelectableModelsInCatalog() : nativeSelectableModelsInCatalog();
6898
- for (const model of gatewayModels) consider(model.id);
6863
+ const effectivePickerModels = pickerModels ?? selectableModelsInCatalog(launchProfileId).map((model) => model.model);
6864
+ for (const model of effectivePickerModels) consider(model);
6899
6865
  if (tightestWindow === void 0) return;
6900
6866
  vars.CLAUDE_CODE_AUTO_COMPACT_WINDOW = String(tightestWindow);
6901
6867
  }
@@ -6921,6 +6887,6 @@ function getCodexEnvVars(serverUrl) {
6921
6887
  return vars;
6922
6888
  }
6923
6889
  //#endregion
6924
- export { sharedServerArgs as a, stopKeepAwake as c, runSelfUpdate as d, checkClaudeVersion as f, setupAndServe as i, listModelsForEndpoint as l, getCodexEnvVars as n, LAUNCH_SECRET_HEADER as o, updateClaude as p, parseSharedArgs as r, startKeepAwake as s, getClaudeCodeEnvVars as t, enableFileLogging as u };
6890
+ export { sharedServerArgs as a, stopKeepAwake as c, enableFileLogging as d, runSelfUpdate as f, setupAndServe as i, injectModelPickerSettingsFile as l, updateClaude as m, getCodexEnvVars as n, LAUNCH_SECRET_HEADER as o, checkClaudeVersion as p, parseSharedArgs as r, startKeepAwake as s, getClaudeCodeEnvVars as t, listModelsForEndpoint as u };
6925
6891
 
6926
- //# sourceMappingURL=server-setup-CSkdFAPP.js.map
6892
+ //# sourceMappingURL=server-setup-BP_JM0qb.js.map