From 7f4338b6ed913b223785ddaf254bec52388c94de Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sun, 8 Feb 2026 13:52:55 +0900 Subject: [PATCH] fix: preserve variant in sync continuation to maintain thinking budget --- src/tools/delegate-task/executor.ts | 34 +++++++------ src/tools/delegate-task/tools.test.ts | 71 ++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/src/tools/delegate-task/executor.ts b/src/tools/delegate-task/executor.ts index 1f43491b0..aa8ad8140 100644 --- a/src/tools/delegate-task/executor.ts +++ b/src/tools/delegate-task/executor.ts @@ -39,7 +39,7 @@ export interface ParentContext { } interface SessionMessage { - info?: { role?: string; time?: { created?: number }; agent?: string; model?: { providerID: string; modelID: string }; modelID?: string; providerID?: string } + info?: { role?: string; time?: { created?: number }; agent?: string; model?: { providerID: string; modelID: string }; modelID?: string; providerID?: string; variant?: string } parts?: Array<{ type?: string; text?: string }> } @@ -190,6 +190,7 @@ export async function executeSyncContinuation( try { let resumeAgent: string | undefined let resumeModel: { providerID: string; modelID: string } | undefined + let resumeVariant: string | undefined try { const messagesResp = await client.session.messages({ path: { id: args.session_id! } }) @@ -199,6 +200,7 @@ export async function executeSyncContinuation( if (info?.agent || info?.model || (info?.modelID && info?.providerID)) { resumeAgent = info.agent resumeModel = info.model ?? (info.providerID && info.modelID ? { providerID: info.providerID, modelID: info.modelID } : undefined) + resumeVariant = info.variant break } } @@ -209,22 +211,24 @@ export async function executeSyncContinuation( resumeModel = resumeMessage?.model?.providerID && resumeMessage?.model?.modelID ? { providerID: resumeMessage.model.providerID, modelID: resumeMessage.model.modelID } : undefined + resumeVariant = resumeMessage?.model?.variant } - await promptSyncWithModelSuggestionRetry(client, { - path: { id: args.session_id! }, - body: { - ...(resumeAgent !== undefined ? { agent: resumeAgent } : {}), - ...(resumeModel !== undefined ? { model: resumeModel } : {}), - tools: { - ...(resumeAgent ? getAgentToolRestrictions(resumeAgent) : {}), - task: false, - call_omo_agent: true, - question: false, - }, - parts: [{ type: "text", text: args.prompt }], - }, - }) + await promptSyncWithModelSuggestionRetry(client, { + path: { id: args.session_id! }, + body: { + ...(resumeAgent !== undefined ? { agent: resumeAgent } : {}), + ...(resumeModel !== undefined ? { model: resumeModel } : {}), + ...(resumeVariant !== undefined ? { variant: resumeVariant } : {}), + tools: { + ...(resumeAgent ? getAgentToolRestrictions(resumeAgent) : {}), + task: false, + call_omo_agent: true, + question: false, + }, + parts: [{ type: "text", text: args.prompt }], + }, + }) } catch (promptError) { if (toastManager) { toastManager.removeTask(taskId) diff --git a/src/tools/delegate-task/tools.test.ts b/src/tools/delegate-task/tools.test.ts index 773022439..68eca3e52 100644 --- a/src/tools/delegate-task/tools.test.ts +++ b/src/tools/delegate-task/tools.test.ts @@ -1,5 +1,5 @@ declare const require: (name: string) => any -const { describe, test, expect, beforeEach, afterEach, spyOn } = require("bun:test") +const { describe, test, expect, beforeEach, afterEach, spyOn, mock } = require("bun:test") import { DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS, CATEGORY_DESCRIPTIONS, isPlanAgent, PLAN_AGENT_NAMES } from "./constants" import { resolveCategoryConfig } from "./tools" import type { CategoryConfig } from "../../config/schema" @@ -1055,6 +1055,75 @@ describe("sisyphus-task", () => { expect(result).not.toContain("Background task continued") }, { timeout: 10000 }) + test("sync continuation preserves variant from previous session message", async () => { + //#given a session with a previous message that has variant "max" + const { createDelegateTask } = require("./tools") + + const promptMock = mock(async (input: any) => { + return { data: {} } + }) + + const mockClient = { + session: { + prompt: async () => ({ data: {} }), + promptAsync: promptMock, + messages: async () => ({ + data: [ + { + info: { + role: "user", + agent: "sisyphus-junior", + model: { providerID: "anthropic", modelID: "claude-opus-4-6" }, + variant: "max", + time: { created: Date.now() }, + }, + parts: [{ type: "text", text: "previous message" }], + }, + { + info: { role: "assistant", time: { created: Date.now() + 1 } }, + parts: [{ type: "text", text: "Completed." }], + }, + ], + }), + }, + config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) }, + app: { + agents: async () => ({ data: [] }), + }, + } + + const tool = createDelegateTask({ + manager: { resume: async () => ({ id: "task-var", sessionID: "ses_var_test", description: "Variant test", agent: "sisyphus-junior", status: "running" }) }, + client: mockClient, + }) + + const toolContext = { + sessionID: "parent-session", + messageID: "parent-message", + agent: "sisyphus", + abort: new AbortController().signal, + } + + //#when continuing the session + await tool.execute( + { + description: "Continue with variant", + prompt: "Continue the task", + session_id: "ses_var_test", + run_in_background: false, + load_skills: [], + }, + toolContext + ) + + //#then promptAsync should include variant from previous message + expect(promptMock).toHaveBeenCalled() + const callArgs = promptMock.mock.calls[0][0] + expect(callArgs.body.variant).toBe("max") + expect(callArgs.body.agent).toBe("sisyphus-junior") + expect(callArgs.body.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-6" }) + }, { timeout: 10000 }) + test("session_id with background=true should return immediately without waiting", async () => { // given const { createDelegateTask } = require("./tools")