From 7fe44024c0e646bd2135fceb24f86e867558d1bf Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 6 Mar 2026 17:35:31 +0900 Subject: [PATCH] feat(no-sisyphus-gpt): allow Sisyphus with GPT-5.4 model Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- src/hooks/no-sisyphus-gpt/hook.ts | 8 ++++---- src/hooks/no-sisyphus-gpt/index.test.ts | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/hooks/no-sisyphus-gpt/hook.ts b/src/hooks/no-sisyphus-gpt/hook.ts index 2042c7451..a4e6c77da 100644 --- a/src/hooks/no-sisyphus-gpt/hook.ts +++ b/src/hooks/no-sisyphus-gpt/hook.ts @@ -1,5 +1,5 @@ import type { PluginInput } from "@opencode-ai/plugin" -import { isGptModel } from "../../agents/types" +import { isGptModel, isGpt5_4Model } from "../../agents/types" import { getSessionAgent, updateSessionAgent } from "../../features/claude-code-session-state" import { log } from "../../shared" import { getAgentConfigKey, getAgentDisplayName } from "../../shared/agent-display-names" @@ -7,8 +7,8 @@ import { getAgentConfigKey, getAgentDisplayName } from "../../shared/agent-displ const TOAST_TITLE = "NEVER Use Sisyphus with GPT" const TOAST_MESSAGE = [ "Sisyphus works best with Claude Opus, and works fine with Kimi/GLM models.", - "Do NOT use Sisyphus with GPT.", - "For GPT models, always use Hephaestus.", + "Do NOT use Sisyphus with GPT (except GPT-5.4 which has specialized support).", + "For GPT models (other than 5.4), always use Hephaestus.", ].join("\n") const HEPHAESTUS_DISPLAY = getAgentDisplayName("hephaestus") @@ -41,7 +41,7 @@ export function createNoSisyphusGptHook(ctx: PluginInput) { const agentKey = getAgentConfigKey(rawAgent) const modelID = input.model?.modelID - if (agentKey === "sisyphus" && modelID && isGptModel(modelID)) { + if (agentKey === "sisyphus" && modelID && isGptModel(modelID) && !isGpt5_4Model(modelID)) { showToast(ctx, input.sessionID) input.agent = HEPHAESTUS_DISPLAY if (output?.message) { diff --git a/src/hooks/no-sisyphus-gpt/index.test.ts b/src/hooks/no-sisyphus-gpt/index.test.ts index 7ae31e88b..b18014bfe 100644 --- a/src/hooks/no-sisyphus-gpt/index.test.ts +++ b/src/hooks/no-sisyphus-gpt/index.test.ts @@ -43,12 +43,33 @@ describe("no-sisyphus-gpt hook", () => { expect(showToast.mock.calls[0]?.[0]).toMatchObject({ body: { title: "NEVER Use Sisyphus with GPT", - message: expect.stringContaining("For GPT models, always use Hephaestus."), + message: expect.stringContaining("For GPT models (other than 5.4), always use Hephaestus."), variant: "error", }, }) }) + test("does not show toast for gpt-5.4 model (Sisyphus has specialized support)", async () => { + // given - sisyphus with gpt-5.4 model (should be allowed) + const showToast = spyOn({ fn: async () => ({}) }, "fn") + const hook = createNoSisyphusGptHook({ + client: { tui: { showToast } }, + } as any) + + const output = createOutput() + + // when - chat.message runs with gpt-5.4 + await hook["chat.message"]?.({ + sessionID: "ses_gpt54", + agent: SISYPHUS_DISPLAY, + model: { providerID: "openai", modelID: "gpt-5.4" }, + }, output) + + // then - no toast, agent NOT switched to Hephaestus + expect(showToast).toHaveBeenCalledTimes(0) + expect(output.message.agent).toBeUndefined() + }) + test("does not show toast for non-gpt model", async () => { // given - sisyphus with claude model const showToast = spyOn({ fn: async () => ({}) }, "fn")