diff --git a/src/cli/__snapshots__/model-fallback.test.ts.snap b/src/cli/__snapshots__/model-fallback.test.ts.snap index 6d3c7ef2..f0e8dc31 100644 --- a/src/cli/__snapshots__/model-fallback.test.ts.snap +++ b/src/cli/__snapshots__/model-fallback.test.ts.snap @@ -36,6 +36,9 @@ exports[`generateModelConfig no providers available returns ULTIMATE_FALLBACK fo "artistry": { "model": "opencode/glm-4.7-free", }, + "deep": { + "model": "opencode/glm-4.7-free", + }, "quick": { "model": "opencode/glm-4.7-free", }, @@ -77,6 +80,7 @@ exports[`generateModelConfig single native provider uses Claude models when only }, "momus": { "model": "anthropic/claude-opus-4-5", + "variant": "max", }, "multimodal-looker": { "model": "anthropic/claude-haiku-4-5", @@ -98,6 +102,10 @@ exports[`generateModelConfig single native provider uses Claude models when only "model": "anthropic/claude-opus-4-5", "variant": "max", }, + "deep": { + "model": "anthropic/claude-opus-4-5", + "variant": "max", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, @@ -141,6 +149,7 @@ exports[`generateModelConfig single native provider uses Claude models with isMa }, "momus": { "model": "anthropic/claude-opus-4-5", + "variant": "max", }, "multimodal-looker": { "model": "anthropic/claude-haiku-4-5", @@ -163,6 +172,10 @@ exports[`generateModelConfig single native provider uses Claude models with isMa "model": "anthropic/claude-opus-4-5", "variant": "max", }, + "deep": { + "model": "anthropic/claude-opus-4-5", + "variant": "max", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, @@ -229,6 +242,10 @@ exports[`generateModelConfig single native provider uses OpenAI models when only "artistry": { "model": "openai/gpt-5.2", }, + "deep": { + "model": "openai/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "opencode/glm-4.7-free", }, @@ -245,8 +262,7 @@ exports[`generateModelConfig single native provider uses OpenAI models when only "variant": "medium", }, "visual-engineering": { - "model": "openai/gpt-5.2", - "variant": "high", + "model": "opencode/glm-4.7-free", }, "writing": { "model": "openai/gpt-5.2", @@ -296,6 +312,10 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa "artistry": { "model": "openai/gpt-5.2", }, + "deep": { + "model": "openai/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "opencode/glm-4.7-free", }, @@ -312,8 +332,7 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa "variant": "medium", }, "visual-engineering": { - "model": "openai/gpt-5.2", - "variant": "high", + "model": "opencode/glm-4.7-free", }, "writing": { "model": "openai/gpt-5.2", @@ -348,6 +367,7 @@ exports[`generateModelConfig single native provider uses Gemini models when only }, "oracle": { "model": "google/gemini-3-pro", + "variant": "max", }, "prometheus": { "model": "google/gemini-3-pro", @@ -361,11 +381,16 @@ exports[`generateModelConfig single native provider uses Gemini models when only "model": "google/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "google/gemini-3-pro", + "variant": "max", + }, "quick": { "model": "google/gemini-3-flash", }, "ultrabrain": { "model": "google/gemini-3-pro", + "variant": "max", }, "unspecified-high": { "model": "google/gemini-3-flash", @@ -409,6 +434,7 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa }, "oracle": { "model": "google/gemini-3-pro", + "variant": "max", }, "prometheus": { "model": "google/gemini-3-pro", @@ -422,11 +448,16 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa "model": "google/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "google/gemini-3-pro", + "variant": "max", + }, "quick": { "model": "google/gemini-3-flash", }, "ultrabrain": { "model": "google/gemini-3-pro", + "variant": "max", }, "unspecified-high": { "model": "google/gemini-3-pro", @@ -485,6 +516,10 @@ exports[`generateModelConfig all native providers uses preferred models from fal "model": "google/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "openai/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, @@ -550,6 +585,10 @@ exports[`generateModelConfig all native providers uses preferred models with isM "model": "google/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "openai/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, @@ -615,6 +654,10 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on "model": "opencode/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "opencode/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "opencode/claude-haiku-4-5", }, @@ -680,6 +723,10 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is "model": "opencode/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "opencode/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "opencode/claude-haiku-4-5", }, @@ -745,6 +792,10 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when "model": "github-copilot/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "github-copilot/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, @@ -810,6 +861,10 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with "model": "github-copilot/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "github-copilot/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, @@ -870,6 +925,9 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian whe "artistry": { "model": "opencode/glm-4.7-free", }, + "deep": { + "model": "opencode/glm-4.7-free", + }, "quick": { "model": "opencode/glm-4.7-free", }, @@ -883,7 +941,7 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian whe "model": "opencode/glm-4.7-free", }, "visual-engineering": { - "model": "opencode/glm-4.7-free", + "model": "zai-coding-plan/glm-4.7", }, "writing": { "model": "zai-coding-plan/glm-4.7", @@ -928,6 +986,9 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian wit "artistry": { "model": "opencode/glm-4.7-free", }, + "deep": { + "model": "opencode/glm-4.7-free", + }, "quick": { "model": "opencode/glm-4.7-free", }, @@ -941,7 +1002,7 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian wit "model": "opencode/glm-4.7-free", }, "visual-engineering": { - "model": "opencode/glm-4.7-free", + "model": "zai-coding-plan/glm-4.7", }, "writing": { "model": "zai-coding-plan/glm-4.7", @@ -991,6 +1052,10 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen "model": "opencode/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "opencode/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, @@ -1055,6 +1120,10 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb "model": "github-copilot/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "openai/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, @@ -1097,6 +1166,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat }, "momus": { "model": "anthropic/claude-opus-4-5", + "variant": "max", }, "multimodal-looker": { "model": "zai-coding-plan/glm-4.6v", @@ -1118,6 +1188,10 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat "model": "anthropic/claude-opus-4-5", "variant": "max", }, + "deep": { + "model": "anthropic/claude-opus-4-5", + "variant": "max", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, @@ -1161,12 +1235,13 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi }, "momus": { "model": "anthropic/claude-opus-4-5", + "variant": "max", }, "multimodal-looker": { "model": "google/gemini-3-flash", }, "oracle": { - "model": "anthropic/claude-opus-4-5", + "model": "google/gemini-3-pro", "variant": "max", }, "prometheus": { @@ -1182,11 +1257,15 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi "model": "google/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "anthropic/claude-opus-4-5", + "variant": "max", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, "ultrabrain": { - "model": "anthropic/claude-opus-4-5", + "model": "google/gemini-3-pro", "variant": "max", }, "unspecified-high": { @@ -1246,6 +1325,10 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider "model": "github-copilot/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "github-copilot/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, @@ -1310,6 +1393,10 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe "model": "google/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "openai/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, @@ -1375,6 +1462,10 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is "model": "google/gemini-3-pro", "variant": "max", }, + "deep": { + "model": "openai/gpt-5.2-codex", + "variant": "medium", + }, "quick": { "model": "anthropic/claude-haiku-4-5", }, diff --git a/src/cli/config-manager.test.ts b/src/cli/config-manager.test.ts index 9bea707d..7ba3d465 100644 --- a/src/cli/config-manager.test.ts +++ b/src/cli/config-manager.test.ts @@ -250,6 +250,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, } // #when generating config @@ -271,6 +272,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, } // #when generating config @@ -290,6 +292,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: true, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, } // #when generating config @@ -309,6 +312,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, } // #when generating config @@ -329,6 +333,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: true, + hasKimiForCoding: false, } // #when generating config @@ -350,6 +355,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, } // #when generating config @@ -373,6 +379,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, } // #when generating config @@ -392,6 +399,7 @@ describe("generateOmoConfig - model fallback system", () => { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, } // #when generating config diff --git a/src/cli/config-manager.ts b/src/cli/config-manager.ts index ef7e6284..2807ba36 100644 --- a/src/cli/config-manager.ts +++ b/src/cli/config-manager.ts @@ -598,27 +598,28 @@ export function addProviderConfig(config: InstallConfig): ConfigMergeResult { } } -function detectProvidersFromOmoConfig(): { hasOpenAI: boolean; hasOpencodeZen: boolean; hasZaiCodingPlan: boolean } { +function detectProvidersFromOmoConfig(): { hasOpenAI: boolean; hasOpencodeZen: boolean; hasZaiCodingPlan: boolean; hasKimiForCoding: boolean } { const omoConfigPath = getOmoConfig() if (!existsSync(omoConfigPath)) { - return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false } + return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false, hasKimiForCoding: false } } try { const content = readFileSync(omoConfigPath, "utf-8") const omoConfig = parseJsonc>(content) if (!omoConfig || typeof omoConfig !== "object") { - return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false } + return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false, hasKimiForCoding: false } } const configStr = JSON.stringify(omoConfig) const hasOpenAI = configStr.includes('"openai/') const hasOpencodeZen = configStr.includes('"opencode/') const hasZaiCodingPlan = configStr.includes('"zai-coding-plan/') + const hasKimiForCoding = configStr.includes('"kimi-for-coding/') - return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan } + return { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding } } catch { - return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false } + return { hasOpenAI: true, hasOpencodeZen: true, hasZaiCodingPlan: false, hasKimiForCoding: false } } } @@ -632,6 +633,7 @@ export function detectCurrentConfig(): DetectedConfig { hasCopilot: false, hasOpencodeZen: true, hasZaiCodingPlan: false, + hasKimiForCoding: false, } const { format, path } = detectConfigFormat() @@ -655,10 +657,11 @@ export function detectCurrentConfig(): DetectedConfig { // Gemini auth plugin detection still works via plugin presence result.hasGemini = plugins.some((p) => p.startsWith("opencode-antigravity-auth")) - const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan } = detectProvidersFromOmoConfig() + const { hasOpenAI, hasOpencodeZen, hasZaiCodingPlan, hasKimiForCoding } = detectProvidersFromOmoConfig() result.hasOpenAI = hasOpenAI result.hasOpencodeZen = hasOpencodeZen result.hasZaiCodingPlan = hasZaiCodingPlan + result.hasKimiForCoding = hasKimiForCoding return result } diff --git a/src/cli/index.ts b/src/cli/index.ts index ddf0dfb5..7c4b1f30 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -30,6 +30,7 @@ program .option("--copilot ", "GitHub Copilot subscription: no, yes") .option("--opencode-zen ", "OpenCode Zen access: no, yes (default: no)") .option("--zai-coding-plan ", "Z.ai Coding Plan subscription: no, yes (default: no)") + .option("--kimi-for-coding ", "Kimi For Coding subscription: no, yes (default: no)") .option("--skip-auth", "Skip authentication setup hints") .addHelpText("after", ` Examples: @@ -37,13 +38,14 @@ Examples: $ bunx oh-my-opencode install --no-tui --claude=max20 --openai=yes --gemini=yes --copilot=no $ bunx oh-my-opencode install --no-tui --claude=no --gemini=no --copilot=yes --opencode-zen=yes -Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai): +Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi): Claude Native anthropic/ models (Opus, Sonnet, Haiku) OpenAI Native openai/ models (GPT-5.2 for Oracle) Gemini Native google/ models (Gemini 3 Pro, Flash) Copilot github-copilot/ models (fallback) OpenCode Zen opencode/ models (opencode/claude-opus-4-5, etc.) Z.ai zai-coding-plan/glm-4.7 (Librarian priority) + Kimi kimi-for-coding/k2p5 (Sisyphus/Prometheus fallback) `) .action(async (options) => { const args: InstallArgs = { @@ -54,6 +56,7 @@ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai): copilot: options.copilot, opencodeZen: options.opencodeZen, zaiCodingPlan: options.zaiCodingPlan, + kimiForCoding: options.kimiForCoding, skipAuth: options.skipAuth ?? false, } const exitCode = await install(args) diff --git a/src/cli/install.ts b/src/cli/install.ts index d8cb85b0..fd7bf985 100644 --- a/src/cli/install.ts +++ b/src/cli/install.ts @@ -45,6 +45,7 @@ function formatConfigSummary(config: InstallConfig): string { lines.push(formatProvider("GitHub Copilot", config.hasCopilot, "fallback")) lines.push(formatProvider("OpenCode Zen", config.hasOpencodeZen, "opencode/ models")) lines.push(formatProvider("Z.ai Coding Plan", config.hasZaiCodingPlan, "Librarian/Multimodal")) + lines.push(formatProvider("Kimi For Coding", config.hasKimiForCoding, "Sisyphus/Prometheus fallback")) lines.push("") lines.push(color.dim("─".repeat(40))) @@ -141,6 +142,10 @@ function validateNonTuiArgs(args: InstallArgs): { valid: boolean; errors: string errors.push(`Invalid --zai-coding-plan value: ${args.zaiCodingPlan} (expected: no, yes)`) } + if (args.kimiForCoding !== undefined && !["no", "yes"].includes(args.kimiForCoding)) { + errors.push(`Invalid --kimi-for-coding value: ${args.kimiForCoding} (expected: no, yes)`) + } + return { valid: errors.length === 0, errors } } @@ -153,10 +158,11 @@ function argsToConfig(args: InstallArgs): InstallConfig { hasCopilot: args.copilot === "yes", hasOpencodeZen: args.opencodeZen === "yes", hasZaiCodingPlan: args.zaiCodingPlan === "yes", + hasKimiForCoding: args.kimiForCoding === "yes", } } -function detectedToInitialValues(detected: DetectedConfig): { claude: ClaudeSubscription; openai: BooleanArg; gemini: BooleanArg; copilot: BooleanArg; opencodeZen: BooleanArg; zaiCodingPlan: BooleanArg } { +function detectedToInitialValues(detected: DetectedConfig): { claude: ClaudeSubscription; openai: BooleanArg; gemini: BooleanArg; copilot: BooleanArg; opencodeZen: BooleanArg; zaiCodingPlan: BooleanArg; kimiForCoding: BooleanArg } { let claude: ClaudeSubscription = "no" if (detected.hasClaude) { claude = detected.isMax20 ? "max20" : "yes" @@ -169,6 +175,7 @@ function detectedToInitialValues(detected: DetectedConfig): { claude: ClaudeSubs copilot: detected.hasCopilot ? "yes" : "no", opencodeZen: detected.hasOpencodeZen ? "yes" : "no", zaiCodingPlan: detected.hasZaiCodingPlan ? "yes" : "no", + kimiForCoding: detected.hasKimiForCoding ? "yes" : "no", } } @@ -260,6 +267,20 @@ async function runTuiMode(detected: DetectedConfig): Promise = {}): InstallConfig { hasCopilot: false, hasOpencodeZen: false, hasZaiCodingPlan: false, + hasKimiForCoding: false, ...overrides, } } diff --git a/src/cli/types.ts b/src/cli/types.ts index 6825075a..ca20bb94 100644 --- a/src/cli/types.ts +++ b/src/cli/types.ts @@ -9,6 +9,7 @@ export interface InstallArgs { copilot?: BooleanArg opencodeZen?: BooleanArg zaiCodingPlan?: BooleanArg + kimiForCoding?: BooleanArg skipAuth?: boolean } @@ -20,6 +21,7 @@ export interface InstallConfig { hasCopilot: boolean hasOpencodeZen: boolean hasZaiCodingPlan: boolean + hasKimiForCoding: boolean } export interface ConfigMergeResult { @@ -37,4 +39,5 @@ export interface DetectedConfig { hasCopilot: boolean hasOpencodeZen: boolean hasZaiCodingPlan: boolean + hasKimiForCoding: boolean } diff --git a/src/shared/model-requirements.ts b/src/shared/model-requirements.ts index 8051e58a..6b2cb2e7 100644 --- a/src/shared/model-requirements.ts +++ b/src/shared/model-requirements.ts @@ -13,7 +13,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { sisyphus: { fallbackChain: [ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, - { providers: ["kimi-for-coding", "opencode"], model: "kimi-k2.5" }, + { providers: ["kimi-for-coding", "opencode"], model: "k2p5" }, { providers: ["zai-coding-plan"], model: "glm-4.7" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, @@ -45,7 +45,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, { providers: ["zai-coding-plan"], model: "glm-4.6v" }, - { providers: ["kimi-for-coding", "opencode"], model: "kimi-k2.5" }, + { providers: ["kimi-for-coding", "opencode"], model: "k2p5" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" }, { providers: ["opencode"], model: "gpt-5-nano" }, ], @@ -53,7 +53,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { prometheus: { fallbackChain: [ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, - { providers: ["kimi-for-coding", "opencode"], model: "kimi-k2.5" }, + { providers: ["kimi-for-coding", "opencode"], model: "k2p5" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, ], @@ -61,7 +61,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { metis: { fallbackChain: [ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, - { providers: ["kimi-for-coding", "opencode"], model: "kimi-k2.5" }, + { providers: ["kimi-for-coding", "opencode"], model: "k2p5" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }, ], @@ -76,7 +76,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { atlas: { fallbackChain: [ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }, - { providers: ["kimi-for-coding"], model: "kimi-k2.5" }, + { providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, ],