From 2622b1936b524eafd943f7076d08d4233b5c080e Mon Sep 17 00:00:00 2001 From: zerone0x Date: Mon, 19 Jan 2026 00:40:48 +0800 Subject: [PATCH 1/2] fix(configure): filter openrouter/auto from model selection list The openrouter/auto model is OpenRouter's internal routing feature, not a callable model. While it's valid as a default (set automatically during OpenRouter auth flow), showing it in the configure wizard's model selection causes "Unknown model: openrouter/auto" errors when users select it manually. Add a HIDDEN_ROUTER_MODELS set to filter out such internal models from the selection list while preserving existing functionality. Fixes #1115 Co-Authored-By: Claude --- src/commands/model-picker.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/commands/model-picker.ts b/src/commands/model-picker.ts index 3590bc596..c4ce5c4be 100644 --- a/src/commands/model-picker.ts +++ b/src/commands/model-picker.ts @@ -17,6 +17,11 @@ const KEEP_VALUE = "__keep__"; const MANUAL_VALUE = "__manual__"; const PROVIDER_FILTER_THRESHOLD = 30; +// Models that are internal routing features and should not be shown in selection lists. +// These may be valid as defaults (e.g., set automatically during auth flow) but are not +// directly callable via API and would cause "Unknown model" errors if selected manually. +const HIDDEN_ROUTER_MODELS = new Set(["openrouter/auto"]); + type PromptDefaultModelParams = { config: ClawdbotConfig; prompter: WizardPrompter; @@ -183,6 +188,8 @@ export async function promptDefaultModel( }) => { const key = modelKey(entry.provider, entry.id); if (seen.has(key)) return; + // Skip internal router models that can't be directly called via API. + if (HIDDEN_ROUTER_MODELS.has(key)) return; const hints: string[] = []; if (entry.name && entry.name !== entry.id) hints.push(entry.name); if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`); From a08a772ffcbd433a71dcaf0d7da41a23e35630e3 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 18 Jan 2026 18:30:49 +0000 Subject: [PATCH 2/2] fix: add model picker regression for openrouter auto (#1182) (thanks @zerone0x) --- CHANGELOG.md | 2 +- src/commands/model-picker.test.ts | 67 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/commands/model-picker.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 491b57792..cad0cf0fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ Docs: https://docs.clawd.bot - Dependencies: update core + plugin deps (grammy, vitest, openai, Microsoft agents hosting, etc.). ### Fixes -- macOS: load menu session previews asynchronously so items populate while the menu is open. +- Configure: hide OpenRouter auto routing model from the model picker. (#1182) — thanks @zerone0x. ## 2026.1.18-4 diff --git a/src/commands/model-picker.test.ts b/src/commands/model-picker.test.ts new file mode 100644 index 000000000..edd56994e --- /dev/null +++ b/src/commands/model-picker.test.ts @@ -0,0 +1,67 @@ +import { describe, expect, it, vi } from "vitest"; + +import type { ClawdbotConfig } from "../config/config.js"; +import { makePrompter } from "./onboarding/__tests__/test-utils.js"; +import { promptDefaultModel } from "./model-picker.js"; + +const loadModelCatalog = vi.hoisted(() => vi.fn()); +vi.mock("../agents/model-catalog.js", () => ({ + loadModelCatalog, +})); + +const ensureAuthProfileStore = vi.hoisted(() => + vi.fn(() => ({ + version: 1, + profiles: {}, + })), +); +const listProfilesForProvider = vi.hoisted(() => vi.fn(() => [])); +vi.mock("../agents/auth-profiles.js", () => ({ + ensureAuthProfileStore, + listProfilesForProvider, +})); + +const resolveEnvApiKey = vi.hoisted(() => vi.fn(() => undefined)); +const getCustomProviderApiKey = vi.hoisted(() => vi.fn(() => undefined)); +vi.mock("../agents/model-auth.js", () => ({ + resolveEnvApiKey, + getCustomProviderApiKey, +})); + +describe("promptDefaultModel", () => { + it("filters internal router models from the selection list", async () => { + loadModelCatalog.mockResolvedValue([ + { + provider: "openrouter", + id: "auto", + name: "OpenRouter Auto", + }, + { + provider: "openrouter", + id: "meta-llama/llama-3.3-70b:free", + name: "Llama 3.3 70B", + }, + ]); + + const select = vi.fn(async (params) => { + const first = params.options[0]; + return first?.value ?? ""; + }); + const prompter = makePrompter({ select }); + const config = { agents: { defaults: {} } } as ClawdbotConfig; + + await promptDefaultModel({ + config, + prompter, + allowKeep: false, + includeManual: false, + ignoreAllowlist: true, + }); + + const options = select.mock.calls[0]?.[0]?.options ?? []; + expect(options.some((opt) => opt.value === "openrouter/auto")).toBe(false); + expect( + options.some((opt) => opt.value === "openrouter/meta-llama/llama-3.3-70b:free"), + ).toBe(true); + }); +});