fix(models): update model names to match OpenCode Zen catalog (#1048)

* fix(models): update model names to match OpenCode Zen catalog

OpenCode Zen recently updated their official model catalog, deprecating
several preview and free model variants:

DEPRECATED → NEW (Official Zen Names):
- gemini-3-pro-preview → gemini-3-pro
- gemini-3-flash-preview → gemini-3-flash
- grok-code → gpt-5-nano (FREE tier maintained)
- glm-4.7-free → big-pickle (FREE tier maintained)
- glm-4.6v → glm-4.6

Changes:
- Updated 6 source files (model-requirements, delegate-task, think-mode, etc.)
- Updated 9 documentation files (installation, configurations, features, etc.)
- Updated 14 test files with new model references
- Regenerated snapshots to reflect catalog changes
- Removed duplicate think-mode entries for preview variants

Impact:
- FREE tier access preserved via gpt-5-nano and big-pickle
- All 55 model-related tests passing
- Zero breaking changes - pure string replacement
- Aligns codebase with official OpenCode Zen model catalog

Verified:
- Zero deprecated model names in codebase
- All model-related tests pass (55/55)
- Snapshots regenerated and validated

Affects: 30 files (6 source, 9 docs, 14 tests, 1 snapshot)

* fix(multimodal-looker): update fallback chain with glm-4.6v and gpt-5-nano

- Change glm-4.6 to glm-4.6v for zai-coding-plan provider
- Add opencode/gpt-5-nano as 4th fallback (FREE tier)
- Push gpt-5.2 to 5th position

Fallback chain now:
1. gemini-3-flash (google, github-copilot, opencode)
2. claude-haiku-4-5 (anthropic, github-copilot, opencode)
3. glm-4.6v (zai-coding-plan)
4. gpt-5-nano (opencode) - FREE
5. gpt-5.2 (openai, github-copilot, opencode)

* chore: update bun.lock

---------

Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
This commit is contained in:
YeonGyu-Kim
2026-01-24 15:30:35 +09:00
committed by GitHub
parent 58459e692b
commit 04633ba208
31 changed files with 292 additions and 293 deletions
+3 -3
View File
@@ -156,13 +156,13 @@ Approach:
export const DEFAULT_CATEGORIES: Record<string, CategoryConfig> = {
"visual-engineering": { model: "google/gemini-3-pro-preview" },
"visual-engineering": { model: "google/gemini-3-pro" },
ultrabrain: { model: "openai/gpt-5.2-codex", variant: "xhigh" },
artistry: { model: "google/gemini-3-pro-preview", variant: "max" },
artistry: { model: "google/gemini-3-pro", variant: "max" },
quick: { model: "anthropic/claude-haiku-4-5" },
"unspecified-low": { model: "anthropic/claude-sonnet-4-5" },
"unspecified-high": { model: "anthropic/claude-opus-4-5", variant: "max" },
writing: { model: "google/gemini-3-flash-preview" },
writing: { model: "google/gemini-3-flash" },
}
export const CATEGORY_PROMPT_APPENDS: Record<string, string> = {
+14 -14
View File
@@ -20,7 +20,7 @@ describe("sisyphus-task", () => {
// #when / #then
expect(category).toBeDefined()
expect(category.model).toBe("google/gemini-3-pro-preview")
expect(category.model).toBe("google/gemini-3-pro")
})
test("ultrabrain category has model and variant config", () => {
@@ -142,7 +142,7 @@ describe("sisyphus-task", () => {
// #then
expect(result).not.toBeNull()
expect(result!.config.model).toBe("google/gemini-3-pro-preview")
expect(result!.config.model).toBe("google/gemini-3-pro")
expect(result!.promptAppend).toContain("VISUAL/UI")
})
@@ -166,7 +166,7 @@ describe("sisyphus-task", () => {
const categoryName = "visual-engineering"
const userCategories = {
"visual-engineering": {
model: "google/gemini-3-pro-preview",
model: "google/gemini-3-pro",
prompt_append: "Custom instructions here",
},
}
@@ -206,7 +206,7 @@ describe("sisyphus-task", () => {
const categoryName = "visual-engineering"
const userCategories = {
"visual-engineering": {
model: "google/gemini-3-pro-preview",
model: "google/gemini-3-pro",
temperature: 0.3,
},
}
@@ -229,7 +229,7 @@ describe("sisyphus-task", () => {
// #then - category's built-in model wins over inheritedModel
expect(result).not.toBeNull()
expect(result!.config.model).toBe("google/gemini-3-pro-preview")
expect(result!.config.model).toBe("google/gemini-3-pro")
})
test("systemDefaultModel is used as fallback when custom category has no model", () => {
@@ -271,7 +271,7 @@ describe("sisyphus-task", () => {
// #then
expect(result).not.toBeNull()
expect(result!.config.model).toBe("google/gemini-3-pro-preview")
expect(result!.config.model).toBe("google/gemini-3-pro")
})
})
@@ -960,7 +960,7 @@ describe("sisyphus-task", () => {
const mockClient = {
app: { agents: async () => ({ data: [] }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
model: { list: async () => [{ id: "google/gemini-3-pro-preview" }] },
model: { list: async () => [{ id: "google/gemini-3-pro" }] },
session: {
get: async () => ({ data: { directory: "/project" } }),
create: async () => ({ data: { id: "ses_unstable_gemini" } }),
@@ -1144,7 +1144,7 @@ describe("sisyphus-task", () => {
const mockClient = {
app: { agents: async () => ({ data: [] }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
model: { list: async () => [{ id: "google/gemini-3-pro-preview" }] },
model: { list: async () => [{ id: "google/gemini-3-pro" }] },
session: {
get: async () => ({ data: { directory: "/project" } }),
create: async () => ({ data: { id: "ses_artistry_gemini" } }),
@@ -1170,7 +1170,7 @@ describe("sisyphus-task", () => {
abort: new AbortController().signal,
}
// #when - artistry category (gemini-3-pro-preview with max variant)
// #when - artistry category (gemini-3-pro with max variant)
const result = await tool.execute(
{
description: "Test artistry forced background",
@@ -1189,7 +1189,7 @@ describe("sisyphus-task", () => {
}, { timeout: 20000 })
test("writing category (gemini-flash) with run_in_background=false should force background but wait for result", async () => {
// #given - writing uses gemini-3-flash-preview
// #given - writing uses gemini-3-flash
const { createDelegateTask } = require("./tools")
let launchCalled = false
@@ -1209,7 +1209,7 @@ describe("sisyphus-task", () => {
const mockClient = {
app: { agents: async () => ({ data: [] }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
model: { list: async () => [{ id: "google/gemini-3-flash-preview" }] },
model: { list: async () => [{ id: "google/gemini-3-flash" }] },
session: {
get: async () => ({ data: { directory: "/project" } }),
create: async () => ({ data: { id: "ses_writing_gemini" } }),
@@ -1235,7 +1235,7 @@ describe("sisyphus-task", () => {
abort: new AbortController().signal,
}
// #when - writing category (gemini-3-flash-preview)
// #when - writing category (gemini-3-flash)
const result = await tool.execute(
{
description: "Test writing forced background",
@@ -1535,9 +1535,9 @@ describe("sisyphus-task", () => {
// #when resolveCategoryConfig is called
const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL })
// #then should use category's built-in model (gemini-3-pro-preview for visual-engineering)
// #then should use category's built-in model (gemini-3-pro for visual-engineering)
expect(resolved).not.toBeNull()
expect(resolved!.model).toBe("google/gemini-3-pro-preview")
expect(resolved!.model).toBe("google/gemini-3-pro")
})
test("systemDefaultModel is used when no other model is available", () => {