UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

377 lines (375 loc) 13.3 kB
import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js"; import { Gt as DEFAULT_PROVIDER, J as resolveEnvApiKey, W as getCustomProviderApiKey, Wt as DEFAULT_MODEL, kt as ensureAuthProfileStore, l as normalizeProviderId, p as resolveConfiguredModelRef, r as buildModelAliasIndex, s as modelKey, t as buildAllowedModelSet, wt as listProfilesForProvider } from "./model-selection-CqaTAlhy.js"; import { n as loadModelCatalog } from "./model-catalog-CIixTnGt.js"; import { i as formatTokenK } from "./shared-B-zggieW.js"; import { n as OPENAI_CODEX_DEFAULT_MODEL, t as promptAndConfigureVllm } from "./vllm-setup-G6R-Hqd8.js"; //#region src/commands/model-picker.ts var model_picker_exports = /* @__PURE__ */ __exportAll({ applyModelAllowlist: () => applyModelAllowlist, applyModelFallbacksFromSelection: () => applyModelFallbacksFromSelection, applyPrimaryModel: () => applyPrimaryModel, promptDefaultModel: () => promptDefaultModel, promptModelAllowlist: () => promptModelAllowlist }); const KEEP_VALUE = "__keep__"; const MANUAL_VALUE = "__manual__"; const VLLM_VALUE = "__vllm__"; const PROVIDER_FILTER_THRESHOLD = 30; const HIDDEN_ROUTER_MODELS = new Set(["openrouter/auto"]); function hasAuthForProvider(provider, cfg, store) { if (listProfilesForProvider(store, provider).length > 0) return true; if (resolveEnvApiKey(provider)) return true; if (getCustomProviderApiKey(cfg, provider)) return true; return false; } function createProviderAuthChecker(params) { const authStore = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }); const authCache = /* @__PURE__ */ new Map(); return (provider) => { const cached = authCache.get(provider); if (cached !== void 0) return cached; const value = hasAuthForProvider(provider, params.cfg, authStore); authCache.set(provider, value); return value; }; } function resolveConfiguredModelRaw(cfg) { const raw = cfg.agents?.defaults?.model; if (typeof raw === "string") return raw.trim(); return raw?.primary?.trim() ?? ""; } function resolveConfiguredModelKeys(cfg) { const models = cfg.agents?.defaults?.models ?? {}; return Object.keys(models).map((key) => String(key ?? "").trim()).filter((key) => key.length > 0); } function normalizeModelKeys(values) { const seen = /* @__PURE__ */ new Set(); const next = []; for (const raw of values) { const value = String(raw ?? "").trim(); if (!value || seen.has(value)) continue; seen.add(value); next.push(value); } return next; } function addModelSelectOption(params) { const key = modelKey(params.entry.provider, params.entry.id); if (params.seen.has(key)) return; if (HIDDEN_ROUTER_MODELS.has(key)) return; const hints = []; if (params.entry.name && params.entry.name !== params.entry.id) hints.push(params.entry.name); if (params.entry.contextWindow) hints.push(`ctx ${formatTokenK(params.entry.contextWindow)}`); if (params.entry.reasoning) hints.push("reasoning"); const aliases = params.aliasIndex.byKey.get(key); if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`); if (!params.hasAuth(params.entry.provider)) hints.push("auth missing"); params.options.push({ value: key, label: key, hint: hints.length > 0 ? hints.join(" · ") : void 0 }); params.seen.add(key); } function isAnthropicLegacyModel(entry) { return entry.provider === "anthropic" && typeof entry.id === "string" && entry.id.toLowerCase().startsWith("claude-3"); } async function promptManualModel(params) { const modelInput = await params.prompter.text({ message: params.allowBlank ? "Default model (blank to keep)" : "Default model", initialValue: params.initialValue, placeholder: "provider/model", validate: params.allowBlank ? void 0 : (value) => value?.trim() ? void 0 : "Required" }); const model = String(modelInput ?? "").trim(); if (!model) return {}; return { model }; } async function promptDefaultModel(params) { const cfg = params.config; const allowKeep = params.allowKeep ?? true; const includeManual = params.includeManual ?? true; const includeVllm = params.includeVllm ?? false; const ignoreAllowlist = params.ignoreAllowlist ?? false; const preferredProviderRaw = params.preferredProvider?.trim(); const preferredProvider = preferredProviderRaw ? normalizeProviderId(preferredProviderRaw) : void 0; const configuredRaw = resolveConfiguredModelRaw(cfg); const resolved = resolveConfiguredModelRef({ cfg, defaultProvider: DEFAULT_PROVIDER, defaultModel: DEFAULT_MODEL }); const resolvedKey = modelKey(resolved.provider, resolved.model); const configuredKey = configuredRaw ? resolvedKey : ""; const catalog = await loadModelCatalog({ config: cfg, useCache: false }); if (catalog.length === 0) return promptManualModel({ prompter: params.prompter, allowBlank: allowKeep, initialValue: configuredRaw || resolvedKey || void 0 }); const aliasIndex = buildModelAliasIndex({ cfg, defaultProvider: DEFAULT_PROVIDER }); let models = catalog; if (!ignoreAllowlist) { const { allowedCatalog } = buildAllowedModelSet({ cfg, catalog, defaultProvider: DEFAULT_PROVIDER }); models = allowedCatalog.length > 0 ? allowedCatalog : catalog; } if (models.length === 0) return promptManualModel({ prompter: params.prompter, allowBlank: allowKeep, initialValue: configuredRaw || resolvedKey || void 0 }); const providers = Array.from(new Set(models.map((entry) => entry.provider))).toSorted((a, b) => a.localeCompare(b)); const hasPreferredProvider = preferredProvider ? providers.includes(preferredProvider) : false; if (!hasPreferredProvider && providers.length > 1 && models.length > PROVIDER_FILTER_THRESHOLD) { const selection = await params.prompter.select({ message: "Filter models by provider", options: [{ value: "*", label: "All providers" }, ...providers.map((provider) => { const count = models.filter((entry) => entry.provider === provider).length; return { value: provider, label: provider, hint: `${count} model${count === 1 ? "" : "s"}` }; })] }); if (selection !== "*") models = models.filter((entry) => entry.provider === selection); } if (hasPreferredProvider && preferredProvider) { models = models.filter((entry) => entry.provider === preferredProvider); if (preferredProvider === "anthropic") models = models.filter((entry) => !isAnthropicLegacyModel(entry)); } const agentDir = params.agentDir; const hasAuth = createProviderAuthChecker({ cfg, agentDir }); const options = []; if (allowKeep) options.push({ value: KEEP_VALUE, label: configuredRaw ? `Keep current (${configuredRaw})` : `Keep current (default: ${resolvedKey})`, hint: configuredRaw && configuredRaw !== resolvedKey ? `resolves to ${resolvedKey}` : void 0 }); if (includeManual) options.push({ value: MANUAL_VALUE, label: "Enter model manually" }); if (includeVllm && agentDir) options.push({ value: VLLM_VALUE, label: "vLLM (custom)", hint: "Enter vLLM URL + API key + model" }); const seen = /* @__PURE__ */ new Set(); for (const entry of models) addModelSelectOption({ entry, options, seen, aliasIndex, hasAuth }); if (configuredKey && !seen.has(configuredKey)) options.push({ value: configuredKey, label: configuredKey, hint: "current (not in catalog)" }); let initialValue = allowKeep ? KEEP_VALUE : configuredKey || void 0; if (allowKeep && hasPreferredProvider && preferredProvider && resolved.provider !== preferredProvider) { const firstModel = models[0]; if (firstModel) initialValue = modelKey(firstModel.provider, firstModel.id); } const selection = await params.prompter.select({ message: params.message ?? "Default model", options, initialValue }); if (selection === KEEP_VALUE) return {}; if (selection === MANUAL_VALUE) return promptManualModel({ prompter: params.prompter, allowBlank: false, initialValue: configuredRaw || resolvedKey || void 0 }); if (selection === VLLM_VALUE) { if (!agentDir) { await params.prompter.note("vLLM setup requires an agent directory context.", "vLLM not available"); return {}; } const { config: nextConfig, modelRef } = await promptAndConfigureVllm({ cfg, prompter: params.prompter, agentDir }); return { model: modelRef, config: nextConfig }; } return { model: String(selection) }; } async function promptModelAllowlist(params) { const cfg = params.config; const existingKeys = resolveConfiguredModelKeys(cfg); const allowedKeys = normalizeModelKeys(params.allowedKeys ?? []); const allowedKeySet = allowedKeys.length > 0 ? new Set(allowedKeys) : null; const resolved = resolveConfiguredModelRef({ cfg, defaultProvider: DEFAULT_PROVIDER, defaultModel: DEFAULT_MODEL }); const resolvedKey = modelKey(resolved.provider, resolved.model); const initialSeeds = normalizeModelKeys([ ...existingKeys, resolvedKey, ...params.initialSelections ?? [] ]); const initialKeys = allowedKeySet ? initialSeeds.filter((key) => allowedKeySet.has(key)) : initialSeeds; const catalog = await loadModelCatalog({ config: cfg, useCache: false }); if (catalog.length === 0 && allowedKeys.length === 0) { const raw = await params.prompter.text({ message: params.message ?? "Allowlist models (comma-separated provider/model; blank to keep current)", initialValue: existingKeys.join(", "), placeholder: `${OPENAI_CODEX_DEFAULT_MODEL}, anthropic/claude-opus-4-6` }); const parsed = String(raw ?? "").split(",").map((value) => value.trim()).filter((value) => value.length > 0); if (parsed.length === 0) return {}; return { models: normalizeModelKeys(parsed) }; } const aliasIndex = buildModelAliasIndex({ cfg, defaultProvider: DEFAULT_PROVIDER }); const hasAuth = createProviderAuthChecker({ cfg, agentDir: params.agentDir }); const options = []; const seen = /* @__PURE__ */ new Set(); const filteredCatalog = allowedKeySet ? catalog.filter((entry) => allowedKeySet.has(modelKey(entry.provider, entry.id))) : catalog; for (const entry of filteredCatalog) addModelSelectOption({ entry, options, seen, aliasIndex, hasAuth }); const supplementalKeys = allowedKeySet ? allowedKeys : existingKeys; for (const key of supplementalKeys) { if (seen.has(key)) continue; options.push({ value: key, label: key, hint: allowedKeySet ? "allowed (not in catalog)" : "configured (not in catalog)" }); seen.add(key); } if (options.length === 0) return {}; const selected = normalizeModelKeys((await params.prompter.multiselect({ message: params.message ?? "Models in /model picker (multi-select)", options, initialValues: initialKeys.length > 0 ? initialKeys : void 0, searchable: true })).map((value) => String(value))); if (selected.length > 0) return { models: selected }; if (existingKeys.length === 0) return { models: [] }; if (!await params.prompter.confirm({ message: "Clear the model allowlist? (shows all models)", initialValue: false })) return {}; return { models: [] }; } function applyPrimaryModel(cfg, model) { const defaults = cfg.agents?.defaults; const existingModel = defaults?.model; const existingModels = defaults?.models; const fallbacks = typeof existingModel === "object" && existingModel !== null && "fallbacks" in existingModel ? existingModel.fallbacks : void 0; return { ...cfg, agents: { ...cfg.agents, defaults: { ...defaults, model: { ...fallbacks ? { fallbacks } : void 0, primary: model }, models: { ...existingModels, [model]: existingModels?.[model] ?? {} } } } }; } function applyModelAllowlist(cfg, models) { const defaults = cfg.agents?.defaults; const normalized = normalizeModelKeys(models); if (normalized.length === 0) { if (!defaults?.models) return cfg; const { models: _ignored, ...restDefaults } = defaults; return { ...cfg, agents: { ...cfg.agents, defaults: restDefaults } }; } const existingModels = defaults?.models ?? {}; const nextModels = {}; for (const key of normalized) nextModels[key] = existingModels[key] ?? {}; return { ...cfg, agents: { ...cfg.agents, defaults: { ...defaults, models: nextModels } } }; } function applyModelFallbacksFromSelection(cfg, selection) { const normalized = normalizeModelKeys(selection); if (normalized.length <= 1) return cfg; const resolved = resolveConfiguredModelRef({ cfg, defaultProvider: DEFAULT_PROVIDER, defaultModel: DEFAULT_MODEL }); const resolvedKey = modelKey(resolved.provider, resolved.model); if (!normalized.includes(resolvedKey)) return cfg; const defaults = cfg.agents?.defaults; const existingModel = defaults?.model; const existingPrimary = typeof existingModel === "string" ? existingModel : existingModel && typeof existingModel === "object" ? existingModel.primary : void 0; const fallbacks = normalized.filter((key) => key !== resolvedKey); return { ...cfg, agents: { ...cfg.agents, defaults: { ...defaults, model: { ...typeof existingModel === "object" ? existingModel : void 0, primary: existingPrimary ?? resolvedKey, fallbacks } } } }; } //#endregion export { promptDefaultModel as a, model_picker_exports as i, applyModelFallbacksFromSelection as n, promptModelAllowlist as o, applyPrimaryModel as r, applyModelAllowlist as t };