From 38c925697bbbfcb17efa365273b8413bf324a654 Mon Sep 17 00:00:00 2001 From: Ravi Tharuma Date: Wed, 4 Mar 2026 20:25:25 +0100 Subject: [PATCH] Respect per-agent fallback chains in runtime fallback --- .../runtime-fallback/fallback-models.test.ts | 66 +++++++++++++++++++ src/hooks/runtime-fallback/fallback-models.ts | 16 +---- 2 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 src/hooks/runtime-fallback/fallback-models.test.ts diff --git a/src/hooks/runtime-fallback/fallback-models.test.ts b/src/hooks/runtime-fallback/fallback-models.test.ts new file mode 100644 index 000000000..7cf3f8e32 --- /dev/null +++ b/src/hooks/runtime-fallback/fallback-models.test.ts @@ -0,0 +1,66 @@ +import { afterEach, describe, expect, test } from "bun:test" + +import { getFallbackModelsForSession } from "./fallback-models" +import { SessionCategoryRegistry } from "../../shared/session-category-registry" + +describe("runtime-fallback fallback-models", () => { + afterEach(() => { + SessionCategoryRegistry.clear() + }) + + test("uses category fallback_models when session category is registered", () => { + //#given + const sessionID = "ses_runtime_fallback_category" + SessionCategoryRegistry.register(sessionID, "quick") + const pluginConfig = { + categories: { + quick: { + fallback_models: ["openai/gpt-5.2", "anthropic/claude-opus-4-6"], + }, + }, + } as any + + //#when + const result = getFallbackModelsForSession(sessionID, undefined, pluginConfig) + + //#then + expect(result).toEqual(["openai/gpt-5.2", "anthropic/claude-opus-4-6"]) + }) + + test("uses agent-specific fallback_models when agent is resolved", () => { + //#given + const pluginConfig = { + agents: { + oracle: { + fallback_models: ["openai/gpt-5.2", "anthropic/claude-opus-4-6"], + }, + }, + } as any + + //#when + const result = getFallbackModelsForSession("ses_runtime_fallback_agent", "oracle", pluginConfig) + + //#then + expect(result).toEqual(["openai/gpt-5.2", "anthropic/claude-opus-4-6"]) + }) + + test("does not fall back to another agent chain when agent cannot be resolved", () => { + //#given + const pluginConfig = { + agents: { + sisyphus: { + fallback_models: ["quotio/gpt-5.2", "quotio/glm-5", "quotio/kimi-k2.5"], + }, + oracle: { + fallback_models: ["openai/gpt-5.2", "anthropic/claude-opus-4-6"], + }, + }, + } as any + + //#when + const result = getFallbackModelsForSession("ses_runtime_fallback_unknown", undefined, pluginConfig) + + //#then + expect(result).toEqual([]) + }) +}) diff --git a/src/hooks/runtime-fallback/fallback-models.ts b/src/hooks/runtime-fallback/fallback-models.ts index e7af3b40e..fb984bbec 100644 --- a/src/hooks/runtime-fallback/fallback-models.ts +++ b/src/hooks/runtime-fallback/fallback-models.ts @@ -1,5 +1,5 @@ import type { OhMyOpenCodeConfig } from "../../config" -import { AGENT_NAMES, agentPattern } from "./agent-resolver" +import { agentPattern } from "./agent-resolver" import { HOOK_NAME } from "./constants" import { log } from "../../shared/logger" import { SessionCategoryRegistry } from "../../shared/session-category-registry" @@ -51,19 +51,7 @@ export function getFallbackModelsForSession( if (result) return result } - const sisyphusFallback = tryGetFallbackFromAgent("sisyphus") - if (sisyphusFallback) { - log(`[${HOOK_NAME}] Using sisyphus fallback models (no agent detected)`, { sessionID }) - return sisyphusFallback - } - - for (const agentName of AGENT_NAMES) { - const result = tryGetFallbackFromAgent(agentName) - if (result) { - log(`[${HOOK_NAME}] Using ${agentName} fallback models (no agent detected)`, { sessionID }) - return result - } - } + log(`[${HOOK_NAME}] No category/agent fallback models resolved for session`, { sessionID, agent }) return [] }