@polderlabs/bizar 10.23.2 → 10.23.3
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.
package/cli/commands/models.mjs
CHANGED
|
@@ -923,16 +923,16 @@ export function partitionStalePicks({ liveIds, pickedIds, disabledProviders }) {
|
|
|
923
923
|
|
|
924
924
|
/**
|
|
925
925
|
* Sync `userSelected.models` into Claude Code's settings.json under
|
|
926
|
-
* `modelOverrides` using
|
|
926
|
+
* `modelOverrides` using recognized Claude IDs as keys and gateway IDs as
|
|
927
|
+
* values. This
|
|
927
928
|
* suppresses `[claude-code:unrecognized_model]` diagnostics on every turn
|
|
928
929
|
* for any picked ID the gateway serves. Stale IDs (not returned by the
|
|
929
930
|
* gateway) are excluded so the diagnostic still surfaces them.
|
|
930
931
|
*
|
|
931
932
|
* Behavior:
|
|
932
933
|
* - Reads `settings.json` if present; preserves every other field.
|
|
933
|
-
* - Writes `modelOverrides` as a sparse object
|
|
934
|
-
*
|
|
935
|
-
* identical (Claude Code dispatches the literal ID).
|
|
934
|
+
* - Writes `modelOverrides` as a sparse object for picked IDs that are
|
|
935
|
+
* also in `liveIds`; Claude Code still dispatches each literal value.
|
|
936
936
|
* - Atomic replace via temp-file + rename (matches `applyModels`).
|
|
937
937
|
* - When `settingsJsonPath` is provided (tests), uses that instead of
|
|
938
938
|
* `~/.claude/settings.json`.
|
|
@@ -962,13 +962,13 @@ export function applyModelOverrides({ settingsJsonPath, pickedIds, liveIds = [],
|
|
|
962
962
|
}
|
|
963
963
|
const live = new Set(Array.isArray(liveIds) ? liveIds : []);
|
|
964
964
|
const incoming = Array.isArray(pickedIds) ? pickedIds.filter((id) => typeof id === 'string' && id.trim()) : [];
|
|
965
|
-
// 10.22.0 / Phase 4: strip disabled-provider ids BEFORE the
|
|
966
|
-
// so Claude Code never sees an `anthropic/*`
|
|
965
|
+
// 10.22.0 / Phase 4: strip disabled-provider ids BEFORE the mapping
|
|
966
|
+
// so Claude Code never sees an `anthropic/*` override value. The
|
|
967
967
|
// skipped ids are reported back so the operator can see what was
|
|
968
968
|
// dropped (without crashing on the disabled list).
|
|
969
969
|
const disabled = Array.isArray(disabledProviders) ? disabledProviders : readDisabledProviders();
|
|
970
970
|
const { kept: picks, stripped: skippedDisabled } = filterCandidatesByDisabledProviders(incoming, disabled);
|
|
971
|
-
//
|
|
971
|
+
// Map only IDs the live gateway serves. Stale IDs intentionally stay
|
|
972
972
|
// out so the `[claude-code:unrecognized_model]` diagnostic still fires
|
|
973
973
|
// for them — the operator should re-run `bizar models` to drop them.
|
|
974
974
|
const synced = live.size === 0
|
|
@@ -987,9 +987,10 @@ export function applyModelOverrides({ settingsJsonPath, pickedIds, liveIds = [],
|
|
|
987
987
|
return { wrote: false, syncedIds: [], skippedStale: skipped, skippedDisabled, settingsPath: path };
|
|
988
988
|
}
|
|
989
989
|
}
|
|
990
|
-
//
|
|
991
|
-
//
|
|
992
|
-
|
|
990
|
+
// Claude Code ignores unknown override keys. Recognized Anthropic model IDs
|
|
991
|
+
// must be keys; configured gateway aliases are values. This also suppresses
|
|
992
|
+
// print-mode `[claude-code:unrecognized_model]` diagnostics for Agent SDK calls.
|
|
993
|
+
settings.modelOverrides = buildClaudeModelOverrides(synced);
|
|
993
994
|
const previousModel = typeof settings.model === 'string' ? settings.model : null;
|
|
994
995
|
const previousContext = profiles?.[previousModel]?.limits?.contextTokens;
|
|
995
996
|
const nextModel = synced[0] || null;
|
|
@@ -1028,6 +1029,33 @@ export function configuredEnabledModels(router) {
|
|
|
1028
1029
|
return selected.length > 0 ? selected : configuredFallbackModels(router);
|
|
1029
1030
|
}
|
|
1030
1031
|
|
|
1032
|
+
export const CLAUDE_MODEL_OVERRIDE_KEYS = Object.freeze([
|
|
1033
|
+
'claude-fable-5',
|
|
1034
|
+
'claude-opus-5',
|
|
1035
|
+
'claude-sonnet-5',
|
|
1036
|
+
'claude-haiku-4-5-20251001',
|
|
1037
|
+
'claude-opus-4-8',
|
|
1038
|
+
'claude-opus-4-7',
|
|
1039
|
+
'claude-opus-4-6',
|
|
1040
|
+
'claude-sonnet-4-6',
|
|
1041
|
+
'claude-opus-4-5-20251101',
|
|
1042
|
+
'claude-sonnet-4-5-20250929',
|
|
1043
|
+
'claude-opus-4-1-20250805',
|
|
1044
|
+
'claude-opus-4-20250514',
|
|
1045
|
+
'claude-sonnet-4-20250514',
|
|
1046
|
+
'claude-3-7-sonnet-20250219',
|
|
1047
|
+
'claude-3-5-haiku-20241022',
|
|
1048
|
+
'claude-3-5-sonnet-20241022',
|
|
1049
|
+
]);
|
|
1050
|
+
|
|
1051
|
+
export function buildClaudeModelOverrides(modelIds) {
|
|
1052
|
+
const unique = [...new Set((Array.isArray(modelIds) ? modelIds : [])
|
|
1053
|
+
.filter((id) => typeof id === 'string' && id.trim())
|
|
1054
|
+
.map((id) => id.trim()))];
|
|
1055
|
+
return Object.fromEntries(unique.slice(0, CLAUDE_MODEL_OVERRIDE_KEYS.length)
|
|
1056
|
+
.map((id, index) => [CLAUDE_MODEL_OVERRIDE_KEYS[index], id]));
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1031
1059
|
/**
|
|
1032
1060
|
* Derive a human-readable label for a model ID. Used to populate the
|
|
1033
1061
|
* `modelPicker` array in settings.json so Claude Code's `/model` picker
|
package/cli/provision.mjs
CHANGED
|
@@ -32,6 +32,7 @@ import { homedir } from 'node:os';
|
|
|
32
32
|
import { dirname, join, resolve, sep } from 'node:path';
|
|
33
33
|
import { fileURLToPath } from 'node:url';
|
|
34
34
|
import { resolveBizarHome } from './config-paths.mjs';
|
|
35
|
+
import { buildClaudeModelOverrides, configuredEnabledModels } from './commands/models.mjs';
|
|
35
36
|
|
|
36
37
|
const __filename = fileURLToPath(import.meta.url);
|
|
37
38
|
const __dirname = dirname(__filename);
|
|
@@ -944,11 +945,13 @@ export function writeClaudeSettings({ dryRun = false, force = false } = {}) {
|
|
|
944
945
|
const legacyRouterPath = join(CLAUDE_DIR, 'model-router.json');
|
|
945
946
|
let installModel;
|
|
946
947
|
let installContextTokens;
|
|
948
|
+
let installModels = [];
|
|
947
949
|
for (const p of [bizarRouterPath, legacyRouterPath]) {
|
|
948
950
|
if (!existsSync(p)) continue;
|
|
949
951
|
const parsed = readJsonSafe(p, null);
|
|
950
952
|
if (!parsed || typeof parsed !== 'object') continue;
|
|
951
953
|
installModel = configuredInstallModel(parsed);
|
|
954
|
+
installModels = configuredEnabledModels(parsed);
|
|
952
955
|
installContextTokens = installModel ? configuredModelContextTokens(parsed, installModel) : undefined;
|
|
953
956
|
if (installModel) break;
|
|
954
957
|
// The Bizar path is authoritative even when it has no enabled candidates.
|
|
@@ -956,7 +959,7 @@ export function writeClaudeSettings({ dryRun = false, force = false } = {}) {
|
|
|
956
959
|
}
|
|
957
960
|
if (installModel) {
|
|
958
961
|
bizarSettings.model = installModel;
|
|
959
|
-
bizarSettings.modelOverrides =
|
|
962
|
+
bizarSettings.modelOverrides = buildClaudeModelOverrides(installModels);
|
|
960
963
|
const configuredContext = pickEnv('CLAUDE_CODE_MAX_CONTEXT_TOKENS') || installContextTokens;
|
|
961
964
|
if (configuredContext) bizarSettings.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS = String(configuredContext);
|
|
962
965
|
} else {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Claude Code settings keys that the operator owns:
|
|
8
8
|
*
|
|
9
9
|
* - modelPicker → { options: [{ model, label }] } in user pick order
|
|
10
|
-
* - modelOverrides → { <id>: <id> }
|
|
10
|
+
* - modelOverrides → { <recognized Claude id>: <gateway id> }
|
|
11
11
|
* - model → reset to the first user pick if the current value
|
|
12
12
|
* starts with `claude-` (the dead gateway namespace —
|
|
13
13
|
* the live gateway rejects it with model_not_found)
|
|
@@ -223,8 +223,19 @@ function syncOnce() {
|
|
|
223
223
|
return option;
|
|
224
224
|
});
|
|
225
225
|
|
|
226
|
+
const overrideKeys = [
|
|
227
|
+
'claude-fable-5', 'claude-opus-5', 'claude-sonnet-5',
|
|
228
|
+
'claude-haiku-4-5-20251001', 'claude-opus-4-8', 'claude-opus-4-7',
|
|
229
|
+
'claude-opus-4-6', 'claude-sonnet-4-6', 'claude-opus-4-5-20251101',
|
|
230
|
+
'claude-sonnet-4-5-20250929', 'claude-opus-4-1-20250805',
|
|
231
|
+
'claude-opus-4-20250514', 'claude-sonnet-4-20250514',
|
|
232
|
+
'claude-3-7-sonnet-20250219', 'claude-3-5-haiku-20241022',
|
|
233
|
+
'claude-3-5-sonnet-20241022',
|
|
234
|
+
];
|
|
226
235
|
settings.modelPicker = { options };
|
|
227
|
-
settings.modelOverrides = Object.fromEntries(
|
|
236
|
+
settings.modelOverrides = Object.fromEntries(
|
|
237
|
+
liveIds.slice(0, overrideKeys.length).map((id, index) => [overrideKeys[index], id]),
|
|
238
|
+
);
|
|
228
239
|
|
|
229
240
|
let modelChanged = false;
|
|
230
241
|
if (typeof settings.model !== 'string' || !liveIds.includes(settings.model)) {
|
package/package.json
CHANGED