fix(model): allow artistry category fallbacks

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-05-01 17:57:49 +09:00
parent 267745fa2f
commit ea5e3e034e
3 changed files with 14 additions and 16 deletions
+2 -2
View File
@@ -605,12 +605,12 @@ describe("requiresModel field in categories", () => {
expect(deep.requiresModel).toBeUndefined() expect(deep.requiresModel).toBeUndefined()
}) })
test("artistry category has requiresModel set to gemini-3.1-pro", () => { test("artistry category no longer hard-requires gemini-3.1-pro", () => {
// given // given
const artistry = CATEGORY_MODEL_REQUIREMENTS["artistry"] const artistry = CATEGORY_MODEL_REQUIREMENTS["artistry"]
// when / #then // when / #then
expect(artistry.requiresModel).toBe("gemini-3.1-pro") expect(artistry.requiresModel).toBeUndefined()
}) })
}) })
-1
View File
@@ -254,7 +254,6 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
}, },
{ providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.5" }, { providers: ["openai", "github-copilot", "opencode", "vercel"], model: "gpt-5.5" },
], ],
requiresModel: "gemini-3.1-pro",
}, },
quick: { quick: {
fallbackChain: [ fallbackChain: [
+12 -13
View File
@@ -381,7 +381,7 @@ describe("sisyphus-task", () => {
} }
//#when //#when
await tool.execute(args as DelegateTaskArgs, toolContext) await tool.execute(args, toolContext)
//#then //#then
expect(args.load_skills).toEqual(["playwright", "git-master"]) expect(args.load_skills).toEqual(["playwright", "git-master"])
@@ -444,7 +444,7 @@ describe("sisyphus-task", () => {
} }
//#when //#when
await tool.execute(args as DelegateTaskArgs, toolContext) await tool.execute(args, toolContext)
//#then //#then
expect(args.load_skills).toEqual([]) expect(args.load_skills).toEqual([])
@@ -755,8 +755,8 @@ describe("sisyphus-task", () => {
expect(result).toBeNull() expect(result).toBeNull()
}) })
test("blocks requiresModel when availability is known and missing the required model", () => { test("allows artistry to use its fallback chain when gemini is missing", () => {
// given - artistry has requiresModel: gemini-3.1-pro // given - artistry can fall back from gemini to another capable model
const categoryName = "artistry" const categoryName = "artistry"
const availableModels = new Set<string>(["anthropic/claude-opus-4-7"]) const availableModels = new Set<string>(["anthropic/claude-opus-4-7"])
@@ -767,11 +767,12 @@ describe("sisyphus-task", () => {
}) })
// then // then
expect(result).toBeNull() expect(result).not.toBeNull()
expect(result?.model).toBe("google/gemini-3.1-pro")
}) })
test("blocks requiresModel when availability is empty", () => { test("allows artistry when availability is empty", () => {
// given - artistry has requiresModel: gemini-3.1-pro // given - empty availability should not disable fallback-capable categories
const categoryName = "artistry" const categoryName = "artistry"
const availableModels = new Set<string>() const availableModels = new Set<string>()
@@ -782,7 +783,8 @@ describe("sisyphus-task", () => {
}) })
// then // then
expect(result).toBeNull() expect(result).not.toBeNull()
expect(result?.model).toBe("google/gemini-3.1-pro")
}) })
test("bypasses requiresModel when explicit user config provided", () => { test("bypasses requiresModel when explicit user config provided", () => {
@@ -1825,7 +1827,7 @@ describe("sisyphus-task", () => {
//#given a session with a previous message that has variant "max" //#given a session with a previous message that has variant "max"
const { createDelegateTask } = require("./tools") const { createDelegateTask } = require("./tools")
const promptMock = mock(async (input: any) => { const promptMock = mock(async () => {
return { data: {} } return { data: {} }
}) })
@@ -3144,8 +3146,6 @@ describe("sisyphus-task", () => {
test("should resolve agent-browser skill even when browserProvider is not set", async () => { test("should resolve agent-browser skill even when browserProvider is not set", async () => {
// given - delegate_task without browserProvider // given - delegate_task without browserProvider
const { createDelegateTask } = require("./tools") const { createDelegateTask } = require("./tools")
let promptBody: any
const mockManager = { launch: async () => ({}) } const mockManager = { launch: async () => ({}) }
const mockClient = { const mockClient = {
app: { agents: async () => ({ data: [] }) }, app: { agents: async () => ({ data: [] }) },
@@ -3153,8 +3153,7 @@ describe("sisyphus-task", () => {
session: { session: {
get: async () => ({ data: { directory: "/project" } }), get: async () => ({ data: { directory: "/project" } }),
create: async () => ({ data: { id: "ses_no_browser_provider" } }), create: async () => ({ data: { id: "ses_no_browser_provider" } }),
prompt: async (input: any) => { prompt: async () => {
promptBody = input.body
return { data: {} } return { data: {} }
}, },
messages: async () => ({ messages: async () => ({