diff --git a/AGENTS.md b/AGENTS.md index fd6313bd..2d741698 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -98,13 +98,13 @@ oh-my-opencode/ | Agent | Model | Purpose | |-------|-------|---------| -| Sisyphus | anthropic/claude-opus-4-5 | Primary orchestrator | -| Atlas | anthropic/claude-opus-4-5 | Master orchestrator | +| Sisyphus | anthropic/claude-opus-4-5 | Primary orchestrator (fallback: kimi-k2.5 → glm-4.7) | +| Atlas | anthropic/claude-sonnet-4-5 | Master orchestrator (fallback: kimi-k2.5 → gpt-5.2) | | oracle | openai/gpt-5.2 | Consultation, debugging | -| librarian | opencode/glm-4.7-free | Docs, GitHub search | -| explore | opencode/gpt-5-nano | Fast codebase grep | +| librarian | zai-coding-plan/glm-4.7 | Docs, GitHub search (fallback: glm-4.7-free) | +| explore | anthropic/claude-haiku-4-5 | Fast codebase grep (fallback: gpt-5-mini → gpt-5-nano) | | multimodal-looker | google/gemini-3-flash | PDF/image analysis | -| Prometheus | anthropic/claude-opus-4-5 | Strategic planning | +| Prometheus | anthropic/claude-opus-4-5 | Strategic planning (fallback: kimi-k2.5 → gpt-5.2) | ## COMMANDS diff --git a/docs/category-skill-guide.md b/docs/category-skill-guide.md index 04cb028a..8e3ced6d 100644 --- a/docs/category-skill-guide.md +++ b/docs/category-skill-guide.md @@ -23,6 +23,7 @@ A Category is an agent configuration preset optimized for specific domains. |----------|---------------|-----------| | `visual-engineering` | `google/gemini-3-pro` | Frontend, UI/UX, design, styling, animation | | `ultrabrain` | `openai/gpt-5.2-codex` (xhigh) | Deep logical reasoning, complex architecture decisions requiring extensive analysis | +| `deep` | `openai/gpt-5.2-codex` (medium) | Moderate complexity tasks requiring deeper reasoning | | `artistry` | `google/gemini-3-pro` (max) | Highly creative/artistic tasks, novel ideas | | `quick` | `anthropic/claude-haiku-4-5` | Trivial tasks - single file changes, typo fixes, simple modifications | | `unspecified-low` | `anthropic/claude-sonnet-4-5` | Tasks that don't fit other categories, low effort required | diff --git a/docs/configurations.md b/docs/configurations.md index 5e067f86..84eda6ce 100644 --- a/docs/configurations.md +++ b/docs/configurations.md @@ -894,15 +894,15 @@ Each agent has a defined provider priority chain. The system tries providers in | Agent | Model (no prefix) | Provider Priority Chain | |-------|-------------------|-------------------------| -| **Sisyphus** | `claude-opus-4-5` | anthropic → github-copilot → opencode → antigravity → google | -| **oracle** | `gpt-5.2` | openai → anthropic → google → github-copilot → opencode | -| **librarian** | `glm-4.7-free` | opencode → github-copilot → anthropic | -| **explore** | `gpt-5-nano` | anthropic → opencode | -| **multimodal-looker** | `gemini-3-flash` | google → openai → zai-coding-plan → anthropic → opencode | -| **Prometheus (Planner)** | `claude-opus-4-5` | anthropic → github-copilot → opencode → antigravity → google | -| **Metis (Plan Consultant)** | `claude-sonnet-4-5` | anthropic → github-copilot → opencode → antigravity → google | -| **Momus (Plan Reviewer)** | `claude-opus-4-5` | anthropic → github-copilot → opencode → antigravity → google | -| **Atlas** | `claude-sonnet-4-5` | anthropic → github-copilot → opencode → antigravity → google | +| **Sisyphus** | `claude-opus-4-5` | anthropic → kimi-for-coding → zai-coding-plan → openai → google | +| **oracle** | `gpt-5.2` | openai → google → anthropic | +| **librarian** | `glm-4.7` | zai-coding-plan → opencode → anthropic | +| **explore** | `claude-haiku-4-5` | anthropic → github-copilot → opencode | +| **multimodal-looker** | `gemini-3-flash` | google → openai → zai-coding-plan → kimi-for-coding → anthropic → opencode | +| **Prometheus (Planner)** | `claude-opus-4-5` | anthropic → kimi-for-coding → openai → google | +| **Metis (Plan Consultant)** | `claude-opus-4-5` | anthropic → kimi-for-coding → openai → google | +| **Momus (Plan Reviewer)** | `gpt-5.2` | openai → anthropic → google | +| **Atlas** | `claude-sonnet-4-5` | anthropic → kimi-for-coding → openai → google | ### Category Provider Chains @@ -910,13 +910,14 @@ Categories follow the same resolution logic: | Category | Model (no prefix) | Provider Priority Chain | |----------|-------------------|-------------------------| -| **visual-engineering** | `gemini-3-pro` | google → openai → anthropic → github-copilot → opencode | -| **ultrabrain** | `gpt-5.2-codex` | openai → anthropic → google → github-copilot → opencode | -| **artistry** | `gemini-3-pro` | google → openai → anthropic → github-copilot → opencode | -| **quick** | `claude-haiku-4-5` | anthropic → github-copilot → opencode → antigravity → google | -| **unspecified-low** | `claude-sonnet-4-5` | anthropic → github-copilot → opencode → antigravity → google | -| **unspecified-high** | `claude-opus-4-5` | anthropic → github-copilot → opencode → antigravity → google | -| **writing** | `gemini-3-flash` | google → openai → anthropic → github-copilot → opencode | +| **visual-engineering** | `gemini-3-pro` | google → anthropic → zai-coding-plan | +| **ultrabrain** | `gpt-5.2-codex` | openai → google → anthropic | +| **deep** | `gpt-5.2-codex` | openai → anthropic → google | +| **artistry** | `gemini-3-pro` | google → anthropic → openai | +| **quick** | `claude-haiku-4-5` | anthropic → google → opencode | +| **unspecified-low** | `claude-sonnet-4-5` | anthropic → openai → google | +| **unspecified-high** | `claude-opus-4-5` | anthropic → openai → google | +| **writing** | `gemini-3-flash` | google → anthropic → zai-coding-plan → openai | ### Checking Your Configuration diff --git a/docs/features.md b/docs/features.md index f47c5b02..63375cdb 100644 --- a/docs/features.md +++ b/docs/features.md @@ -10,19 +10,19 @@ Oh-My-OpenCode provides 10 specialized AI agents. Each has distinct expertise, o | Agent | Model | Purpose | |-------|-------|---------| -| **Sisyphus** | `anthropic/claude-opus-4-5` | **The default orchestrator.** Plans, delegates, and executes complex tasks using specialized subagents with aggressive parallel execution. Todo-driven workflow with extended thinking (32k budget). | +| **Sisyphus** | `anthropic/claude-opus-4-5` | **The default orchestrator.** Plans, delegates, and executes complex tasks using specialized subagents with aggressive parallel execution. Todo-driven workflow with extended thinking (32k budget). Fallback: kimi-k2.5 → glm-4.7 → gpt-5.2-codex → gemini-3-pro. | | **oracle** | `openai/gpt-5.2` | Architecture decisions, code review, debugging. Read-only consultation - stellar logical reasoning and deep analysis. Inspired by AmpCode. | -| **librarian** | `opencode/glm-4.7-free` | Multi-repo analysis, documentation lookup, OSS implementation examples. Deep codebase understanding with evidence-based answers. Inspired by AmpCode. | -| **explore** | `opencode/gpt-5-nano` | Fast codebase exploration and contextual grep. Uses Gemini 3 Flash when Antigravity auth is configured, Haiku when Claude max20 is available, otherwise Grok. Inspired by Claude Code. | -| **multimodal-looker** | `google/gemini-3-flash` | Visual content specialist. Analyzes PDFs, images, diagrams to extract information. Saves tokens by having another agent process media. | +| **librarian** | `zai-coding-plan/glm-4.7` | Multi-repo analysis, documentation lookup, OSS implementation examples. Deep codebase understanding with evidence-based answers. Fallback: glm-4.7-free → claude-sonnet-4-5. | +| **explore** | `anthropic/claude-haiku-4-5` | Fast codebase exploration and contextual grep. Fallback: gpt-5-mini → gpt-5-nano. Inspired by Claude Code. | +| **multimodal-looker** | `google/gemini-3-flash` | Visual content specialist. Analyzes PDFs, images, diagrams to extract information. Fallback: gpt-5.2 → glm-4.6v → kimi-k2.5 → claude-haiku-4-5 → gpt-5-nano. | ### Planning Agents | Agent | Model | Purpose | |-------|-------|---------| -| **Prometheus** | `anthropic/claude-opus-4-5` | Strategic planner with interview mode. Creates detailed work plans through iterative questioning. | -| **Metis** | `anthropic/claude-sonnet-4-5` | Plan consultant - pre-planning analysis. Identifies hidden intentions, ambiguities, and AI failure points. | -| **Momus** | `anthropic/claude-sonnet-4-5` | Plan reviewer - validates plans against clarity, verifiability, and completeness standards. | +| **Prometheus** | `anthropic/claude-opus-4-5` | Strategic planner with interview mode. Creates detailed work plans through iterative questioning. Fallback: kimi-k2.5 → gpt-5.2 → gemini-3-pro. | +| **Metis** | `anthropic/claude-opus-4-5` | Plan consultant - pre-planning analysis. Identifies hidden intentions, ambiguities, and AI failure points. Fallback: kimi-k2.5 → gpt-5.2 → gemini-3-pro. | +| **Momus** | `openai/gpt-5.2` | Plan reviewer - validates plans against clarity, verifiability, and completeness standards. Fallback: claude-opus-4-5 → gemini-3-pro. | ### Invoking Agents diff --git a/src/agents/AGENTS.md b/src/agents/AGENTS.md index 21366f68..717c5ff6 100644 --- a/src/agents/AGENTS.md +++ b/src/agents/AGENTS.md @@ -25,15 +25,15 @@ agents/ ## AGENT MODELS | Agent | Model | Temp | Purpose | |-------|-------|------|---------| -| Sisyphus | anthropic/claude-opus-4-5 | 0.1 | Primary orchestrator | -| Atlas | anthropic/claude-opus-4-5 | 0.1 | Master orchestrator | +| Sisyphus | anthropic/claude-opus-4-5 | 0.1 | Primary orchestrator (fallback: kimi-k2.5 → glm-4.7) | +| Atlas | anthropic/claude-sonnet-4-5 | 0.1 | Master orchestrator (fallback: kimi-k2.5 → gpt-5.2) | | oracle | openai/gpt-5.2 | 0.1 | Consultation, debugging | -| librarian | opencode/glm-4.7-free | 0.1 | Docs, GitHub search | -| explore | opencode/gpt-5-nano | 0.1 | Fast contextual grep | +| librarian | zai-coding-plan/glm-4.7 | 0.1 | Docs, GitHub search (fallback: glm-4.7-free) | +| explore | anthropic/claude-haiku-4-5 | 0.1 | Fast contextual grep (fallback: gpt-5-mini → gpt-5-nano) | | multimodal-looker | google/gemini-3-flash | 0.1 | PDF/image analysis | -| Prometheus | anthropic/claude-opus-4-5 | 0.1 | Strategic planning | -| Metis | anthropic/claude-sonnet-4-5 | 0.3 | Pre-planning analysis | -| Momus | anthropic/claude-sonnet-4-5 | 0.1 | Plan validation | +| Prometheus | anthropic/claude-opus-4-5 | 0.1 | Strategic planning (fallback: kimi-k2.5 → gpt-5.2) | +| Metis | anthropic/claude-opus-4-5 | 0.3 | Pre-planning analysis (fallback: kimi-k2.5 → gpt-5.2) | +| Momus | openai/gpt-5.2 | 0.1 | Plan validation (fallback: claude-opus-4-5) | | Sisyphus-Junior | anthropic/claude-sonnet-4-5 | 0.1 | Category-spawned executor | ## HOW TO ADD diff --git a/src/shared/model-requirements.ts b/src/shared/model-requirements.ts index 8fcf944e..8051e58a 100644 --- a/src/shared/model-requirements.ts +++ b/src/shared/model-requirements.ts @@ -13,6 +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: ["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" }, @@ -44,6 +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: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" }, { providers: ["opencode"], model: "gpt-5-nano" }, ], @@ -51,6 +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: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, ], @@ -58,6 +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: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }, ], @@ -72,6 +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: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, ], @@ -84,14 +89,13 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, { providers: ["zai-coding-plan"], model: "glm-4.7" }, - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, ], }, ultrabrain: { fallbackChain: [ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, ], }, deep: { diff --git a/src/shared/model-resolver.test.ts b/src/shared/model-resolver.test.ts index d4b7fbd7..372ccfe1 100644 --- a/src/shared/model-resolver.test.ts +++ b/src/shared/model-resolver.test.ts @@ -388,6 +388,85 @@ describe("resolveModelWithFallback", () => { expect(result!.model).toBe("anthropic/claude-opus-4-5") expect(result!.source).toBe("provider-fallback") }) + + test("cross-provider fuzzy match when preferred provider unavailable (librarian scenario)", () => { + // #given - glm-4.7 is defined for zai-coding-plan, but only opencode has it + const input: ExtendedModelResolutionInput = { + fallbackChain: [ + { providers: ["zai-coding-plan"], model: "glm-4.7" }, + { providers: ["anthropic"], model: "claude-sonnet-4-5" }, + ], + availableModels: new Set(["opencode/glm-4.7", "anthropic/claude-sonnet-4-5"]), + systemDefaultModel: "google/gemini-3-pro", + } + + // #when + const result = resolveModelWithFallback(input) + + // #then - should find glm-4.7 from opencode via cross-provider fuzzy match + expect(result!.model).toBe("opencode/glm-4.7") + expect(result!.source).toBe("provider-fallback") + expect(logSpy).toHaveBeenCalledWith("Model resolved via fallback chain (cross-provider fuzzy match)", { + model: "glm-4.7", + match: "opencode/glm-4.7", + variant: undefined, + }) + }) + + test("prefers specified provider over cross-provider match", () => { + // #given - both zai-coding-plan and opencode have glm-4.7 + const input: ExtendedModelResolutionInput = { + fallbackChain: [ + { providers: ["zai-coding-plan"], model: "glm-4.7" }, + ], + availableModels: new Set(["zai-coding-plan/glm-4.7", "opencode/glm-4.7"]), + systemDefaultModel: "google/gemini-3-pro", + } + + // #when + const result = resolveModelWithFallback(input) + + // #then - should prefer zai-coding-plan (specified provider) over opencode + expect(result!.model).toBe("zai-coding-plan/glm-4.7") + expect(result!.source).toBe("provider-fallback") + }) + + test("cross-provider match preserves variant from entry", () => { + // #given - entry has variant, model found via cross-provider + const input: ExtendedModelResolutionInput = { + fallbackChain: [ + { providers: ["zai-coding-plan"], model: "glm-4.7", variant: "high" }, + ], + availableModels: new Set(["opencode/glm-4.7"]), + systemDefaultModel: "google/gemini-3-pro", + } + + // #when + const result = resolveModelWithFallback(input) + + // #then - variant should be preserved + expect(result!.model).toBe("opencode/glm-4.7") + expect(result!.variant).toBe("high") + }) + + test("cross-provider match tries next entry if no match found anywhere", () => { + // #given - first entry model not available anywhere, second entry available + const input: ExtendedModelResolutionInput = { + fallbackChain: [ + { providers: ["zai-coding-plan"], model: "nonexistent-model" }, + { providers: ["anthropic"], model: "claude-sonnet-4-5" }, + ], + availableModels: new Set(["anthropic/claude-sonnet-4-5"]), + systemDefaultModel: "google/gemini-3-pro", + } + + // #when + const result = resolveModelWithFallback(input) + + // #then - should fall through to second entry + expect(result!.model).toBe("anthropic/claude-sonnet-4-5") + expect(result!.source).toBe("provider-fallback") + }) }) describe("Step 4: System default fallback (no availability match)", () => { diff --git a/src/shared/model-resolver.ts b/src/shared/model-resolver.ts index 792bf7fa..fbe1a807 100644 --- a/src/shared/model-resolver.ts +++ b/src/shared/model-resolver.ts @@ -117,6 +117,7 @@ export function resolveModelWithFallback( } } else { for (const entry of fallbackChain) { + // Step 1: Try with provider filter (preferred providers first) for (const provider of entry.providers) { const fullModel = `${provider}/${entry.model}` const match = fuzzyMatchModel(fullModel, availableModels, [provider]) @@ -125,6 +126,17 @@ export function resolveModelWithFallback( return { model: match, source: "provider-fallback", variant: entry.variant } } } + + // Step 2: Try without provider filter (cross-provider fuzzy match) + const crossProviderMatch = fuzzyMatchModel(entry.model, availableModels) + if (crossProviderMatch) { + log("Model resolved via fallback chain (cross-provider fuzzy match)", { + model: entry.model, + match: crossProviderMatch, + variant: entry.variant, + }) + return { model: crossProviderMatch, source: "provider-fallback", variant: entry.variant } + } } log("No available model found in fallback chain, falling through to system default") }