Spaces:
Paused
Paused
| import type { RuntimeEnv } from "../../runtime.js"; | |
| import { buildModelAliasIndex, resolveModelRefFromString } from "../../agents/model-selection.js"; | |
| import { loadConfig } from "../../config/config.js"; | |
| import { logConfigUpdated } from "../../config/logging.js"; | |
| import { | |
| DEFAULT_PROVIDER, | |
| ensureFlagCompatibility, | |
| modelKey, | |
| resolveModelTarget, | |
| updateConfig, | |
| } from "./shared.js"; | |
| export async function modelsFallbacksListCommand( | |
| opts: { json?: boolean; plain?: boolean }, | |
| runtime: RuntimeEnv, | |
| ) { | |
| ensureFlagCompatibility(opts); | |
| const cfg = loadConfig(); | |
| const fallbacks = cfg.agents?.defaults?.model?.fallbacks ?? []; | |
| if (opts.json) { | |
| runtime.log(JSON.stringify({ fallbacks }, null, 2)); | |
| return; | |
| } | |
| if (opts.plain) { | |
| for (const entry of fallbacks) { | |
| runtime.log(entry); | |
| } | |
| return; | |
| } | |
| runtime.log(`Fallbacks (${fallbacks.length}):`); | |
| if (fallbacks.length === 0) { | |
| runtime.log("- none"); | |
| return; | |
| } | |
| for (const entry of fallbacks) { | |
| runtime.log(`- ${entry}`); | |
| } | |
| } | |
| export async function modelsFallbacksAddCommand(modelRaw: string, runtime: RuntimeEnv) { | |
| const updated = await updateConfig((cfg) => { | |
| const resolved = resolveModelTarget({ raw: modelRaw, cfg }); | |
| const targetKey = modelKey(resolved.provider, resolved.model); | |
| const nextModels = { ...cfg.agents?.defaults?.models }; | |
| if (!nextModels[targetKey]) { | |
| nextModels[targetKey] = {}; | |
| } | |
| const aliasIndex = buildModelAliasIndex({ | |
| cfg, | |
| defaultProvider: DEFAULT_PROVIDER, | |
| }); | |
| const existing = cfg.agents?.defaults?.model?.fallbacks ?? []; | |
| const existingKeys = existing | |
| .map((entry) => | |
| resolveModelRefFromString({ | |
| raw: String(entry ?? ""), | |
| defaultProvider: DEFAULT_PROVIDER, | |
| aliasIndex, | |
| }), | |
| ) | |
| .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry)) | |
| .map((entry) => modelKey(entry.ref.provider, entry.ref.model)); | |
| if (existingKeys.includes(targetKey)) { | |
| return cfg; | |
| } | |
| const existingModel = cfg.agents?.defaults?.model as | |
| | { primary?: string; fallbacks?: string[] } | |
| | undefined; | |
| return { | |
| ...cfg, | |
| agents: { | |
| ...cfg.agents, | |
| defaults: { | |
| ...cfg.agents?.defaults, | |
| model: { | |
| ...(existingModel?.primary ? { primary: existingModel.primary } : undefined), | |
| fallbacks: [...existing, targetKey], | |
| }, | |
| models: nextModels, | |
| }, | |
| }, | |
| }; | |
| }); | |
| logConfigUpdated(runtime); | |
| runtime.log(`Fallbacks: ${(updated.agents?.defaults?.model?.fallbacks ?? []).join(", ")}`); | |
| } | |
| export async function modelsFallbacksRemoveCommand(modelRaw: string, runtime: RuntimeEnv) { | |
| const updated = await updateConfig((cfg) => { | |
| const resolved = resolveModelTarget({ raw: modelRaw, cfg }); | |
| const targetKey = modelKey(resolved.provider, resolved.model); | |
| const aliasIndex = buildModelAliasIndex({ | |
| cfg, | |
| defaultProvider: DEFAULT_PROVIDER, | |
| }); | |
| const existing = cfg.agents?.defaults?.model?.fallbacks ?? []; | |
| const filtered = existing.filter((entry) => { | |
| const resolvedEntry = resolveModelRefFromString({ | |
| raw: String(entry ?? ""), | |
| defaultProvider: DEFAULT_PROVIDER, | |
| aliasIndex, | |
| }); | |
| if (!resolvedEntry) { | |
| return true; | |
| } | |
| return modelKey(resolvedEntry.ref.provider, resolvedEntry.ref.model) !== targetKey; | |
| }); | |
| if (filtered.length === existing.length) { | |
| throw new Error(`Fallback not found: ${targetKey}`); | |
| } | |
| const existingModel = cfg.agents?.defaults?.model as | |
| | { primary?: string; fallbacks?: string[] } | |
| | undefined; | |
| return { | |
| ...cfg, | |
| agents: { | |
| ...cfg.agents, | |
| defaults: { | |
| ...cfg.agents?.defaults, | |
| model: { | |
| ...(existingModel?.primary ? { primary: existingModel.primary } : undefined), | |
| fallbacks: filtered, | |
| }, | |
| }, | |
| }, | |
| }; | |
| }); | |
| logConfigUpdated(runtime); | |
| runtime.log(`Fallbacks: ${(updated.agents?.defaults?.model?.fallbacks ?? []).join(", ")}`); | |
| } | |
| export async function modelsFallbacksClearCommand(runtime: RuntimeEnv) { | |
| await updateConfig((cfg) => { | |
| const existingModel = cfg.agents?.defaults?.model as | |
| | { primary?: string; fallbacks?: string[] } | |
| | undefined; | |
| return { | |
| ...cfg, | |
| agents: { | |
| ...cfg.agents, | |
| defaults: { | |
| ...cfg.agents?.defaults, | |
| model: { | |
| ...(existingModel?.primary ? { primary: existingModel.primary } : undefined), | |
| fallbacks: [], | |
| }, | |
| }, | |
| }, | |
| }; | |
| }); | |
| logConfigUpdated(runtime); | |
| runtime.log("Fallback list cleared."); | |
| } | |