diff --git a/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts b/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts index 56dd7cb4ea..100997c75f 100644 --- a/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts +++ b/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts @@ -40,7 +40,45 @@ describe("injectContinuation", () => { }) // then - expect(capturedAgent).toBe("Sisyphus - Ultraworker") + expect(capturedAgent).toBe("\u200BSisyphus - Ultraworker") + }) + + test("falls back to the runtime display name when only config-key agent info is available", async () => { + // given + let capturedAgent: string | undefined + const ctx = { + directory: "/tmp/test", + client: { + session: { + todo: async () => ({ data: [{ id: "1", content: "todo", status: "pending", priority: "high" }] }), + promptAsync: async (input: { + body: { + agent?: string + } + }) => { + capturedAgent = input.body.agent + return {} + }, + }, + }, + } + const sessionStateStore = { + getExistingState: () => ({ inFlight: false, lastInjectedAt: 0, consecutiveFailures: 0 }), + } + + // when + await injectContinuation({ + ctx: ctx as never, + sessionID: "ses_display_name_fallback", + resolvedInfo: { + agent: "sisyphus", + model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, + }, + sessionStateStore: sessionStateStore as never, + }) + + // then + expect(capturedAgent).toBe("\u200BSisyphus - Ultraworker") }) test("inherits tools from resolved message info when reinjecting", async () => { diff --git a/src/hooks/todo-continuation-enforcer/continuation-injection.ts b/src/hooks/todo-continuation-enforcer/continuation-injection.ts index 5844bebd20..29feddef02 100644 --- a/src/hooks/todo-continuation-enforcer/continuation-injection.ts +++ b/src/hooks/todo-continuation-enforcer/continuation-injection.ts @@ -19,6 +19,7 @@ import { log } from "../../shared/logger" import { isSqliteBackend } from "../../shared/opencode-storage-detection" import { getAgentConfigKey, + getAgentRuntimeName, normalizeAgentForPromptKey, } from "../../shared/agent-display-names" @@ -130,7 +131,13 @@ export async function injectContinuation(args: { } const promptAgent = normalizeAgentForPromptKey(agentName) - const launchAgent = resolveRegisteredAgentName(agentName) + const configKey = promptAgent ?? (agentName ? getAgentConfigKey(agentName) : undefined) + const fallbackLaunchAgent = configKey ? getAgentRuntimeName(configKey) : undefined + const resolvedLaunchAgent = resolveRegisteredAgentName(agentName) + const launchAgent = + resolvedLaunchAgent && resolvedLaunchAgent !== agentName + ? resolvedLaunchAgent + : fallbackLaunchAgent ?? agentName ?? promptAgent if (promptAgent && skipAgents.some(s => getAgentConfigKey(s) === getAgentConfigKey(promptAgent))) { log(`[${HOOK_NAME}] Skipped: agent in skipAgents list`, { sessionID, agent: agentName })