From 553817c1a0c563b8aa6b079248727e86ad0c8638 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sun, 15 Feb 2026 14:57:15 +0900 Subject: [PATCH] feat: migrate call-omo-agent tool callers to SDK message finders --- .../background-agent-executor.ts | 23 ++++++++++-- .../background-executor.test.ts | 36 ++++++++++++------- .../call-omo-agent/background-executor.ts | 25 ++++++++++--- src/tools/call-omo-agent/tools.ts | 2 +- 4 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/tools/call-omo-agent/background-agent-executor.ts b/src/tools/call-omo-agent/background-agent-executor.ts index 7babb43c..9041831f 100644 --- a/src/tools/call-omo-agent/background-agent-executor.ts +++ b/src/tools/call-omo-agent/background-agent-executor.ts @@ -1,21 +1,38 @@ import type { BackgroundManager } from "../../features/background-agent" -import { findFirstMessageWithAgent, findNearestMessageWithFields } from "../../features/hook-message-injector" +import type { PluginInput } from "@opencode-ai/plugin" +import { + findFirstMessageWithAgent, + findFirstMessageWithAgentFromSDK, + findNearestMessageWithFields, + findNearestMessageWithFieldsFromSDK, +} from "../../features/hook-message-injector" import { getSessionAgent } from "../../features/claude-code-session-state" import { log } from "../../shared" import type { CallOmoAgentArgs } from "./types" import type { ToolContextWithMetadata } from "./tool-context-with-metadata" import { getMessageDir } from "./message-storage-directory" import { getSessionTools } from "../../shared/session-tools-store" +import { isSqliteBackend } from "../../shared/opencode-storage-detection" export async function executeBackgroundAgent( args: CallOmoAgentArgs, toolContext: ToolContextWithMetadata, manager: BackgroundManager, + client: PluginInput["client"], ): Promise { try { const messageDir = getMessageDir(toolContext.sessionID) - const prevMessage = messageDir ? findNearestMessageWithFields(messageDir) : null - const firstMessageAgent = messageDir ? findFirstMessageWithAgent(messageDir) : null + + const [prevMessage, firstMessageAgent] = isSqliteBackend() + ? await Promise.all([ + findNearestMessageWithFieldsFromSDK(client, toolContext.sessionID), + findFirstMessageWithAgentFromSDK(client, toolContext.sessionID), + ]) + : [ + messageDir ? findNearestMessageWithFields(messageDir) : null, + messageDir ? findFirstMessageWithAgent(messageDir) : null, + ] + const sessionAgent = getSessionAgent(toolContext.sessionID) const parentAgent = toolContext.agent ?? sessionAgent ?? firstMessageAgent ?? prevMessage?.agent diff --git a/src/tools/call-omo-agent/background-executor.test.ts b/src/tools/call-omo-agent/background-executor.test.ts index 8323c651..970b9c13 100644 --- a/src/tools/call-omo-agent/background-executor.test.ts +++ b/src/tools/call-omo-agent/background-executor.test.ts @@ -1,17 +1,22 @@ +/// import { describe, test, expect, mock } from "bun:test" import type { BackgroundManager } from "../../features/background-agent" +import type { PluginInput } from "@opencode-ai/plugin" import { executeBackground } from "./background-executor" describe("executeBackground", () => { + const launchMock = mock(() => Promise.resolve({ + id: "test-task-id", + sessionID: null, + description: "Test task", + agent: "test-agent", + status: "pending", + })) + const getTaskMock = mock() + const mockManager = { - launch: mock(() => Promise.resolve({ - id: "test-task-id", - sessionID: null, - description: "Test task", - agent: "test-agent", - status: "pending", - })), - getTask: mock(), + launch: launchMock, + getTask: getTaskMock, } as unknown as BackgroundManager const testContext = { @@ -25,18 +30,25 @@ describe("executeBackground", () => { description: "Test background task", prompt: "Test prompt", subagent_type: "test-agent", + run_in_background: true, } + const mockClient = { + session: { + messages: mock(() => Promise.resolve({ data: [] })), + }, + } as unknown as PluginInput["client"] + test("detects interrupted task as failure", async () => { //#given - mockManager.launch.mockResolvedValueOnce({ + launchMock.mockResolvedValueOnce({ id: "test-task-id", sessionID: null, description: "Test task", agent: "test-agent", status: "pending", }) - mockManager.getTask.mockReturnValueOnce({ + getTaskMock.mockReturnValueOnce({ id: "test-task-id", sessionID: null, description: "Test task", @@ -45,11 +57,11 @@ describe("executeBackground", () => { }) //#when - const result = await executeBackground(testArgs, testContext, mockManager) + const result = await executeBackground(testArgs, testContext, mockManager, mockClient) //#then expect(result).toContain("Task failed to start") expect(result).toContain("interrupt") expect(result).toContain("test-task-id") }) -}) \ No newline at end of file +}) diff --git a/src/tools/call-omo-agent/background-executor.ts b/src/tools/call-omo-agent/background-executor.ts index 5751664a..e302bab7 100644 --- a/src/tools/call-omo-agent/background-executor.ts +++ b/src/tools/call-omo-agent/background-executor.ts @@ -1,11 +1,18 @@ import type { CallOmoAgentArgs } from "./types" import type { BackgroundManager } from "../../features/background-agent" +import type { PluginInput } from "@opencode-ai/plugin" import { log } from "../../shared" import { consumeNewMessages } from "../../shared/session-cursor" -import { findFirstMessageWithAgent, findNearestMessageWithFields } from "../../features/hook-message-injector" +import { + findFirstMessageWithAgent, + findFirstMessageWithAgentFromSDK, + findNearestMessageWithFields, + findNearestMessageWithFieldsFromSDK, +} from "../../features/hook-message-injector" import { getSessionAgent } from "../../features/claude-code-session-state" import { getMessageDir } from "./message-dir" import { getSessionTools } from "../../shared/session-tools-store" +import { isSqliteBackend } from "../../shared/opencode-storage-detection" export async function executeBackground( args: CallOmoAgentArgs, @@ -16,12 +23,22 @@ export async function executeBackground( abort: AbortSignal metadata?: (input: { title?: string; metadata?: Record }) => void }, - manager: BackgroundManager + manager: BackgroundManager, + client: PluginInput["client"] ): Promise { try { const messageDir = getMessageDir(toolContext.sessionID) - const prevMessage = messageDir ? findNearestMessageWithFields(messageDir) : null - const firstMessageAgent = messageDir ? findFirstMessageWithAgent(messageDir) : null + + const [prevMessage, firstMessageAgent] = isSqliteBackend() + ? await Promise.all([ + findNearestMessageWithFieldsFromSDK(client, toolContext.sessionID), + findFirstMessageWithAgentFromSDK(client, toolContext.sessionID), + ]) + : [ + messageDir ? findNearestMessageWithFields(messageDir) : null, + messageDir ? findFirstMessageWithAgent(messageDir) : null, + ] + const sessionAgent = getSessionAgent(toolContext.sessionID) const parentAgent = toolContext.agent ?? sessionAgent ?? firstMessageAgent ?? prevMessage?.agent diff --git a/src/tools/call-omo-agent/tools.ts b/src/tools/call-omo-agent/tools.ts index dbcfcf97..b773d21a 100644 --- a/src/tools/call-omo-agent/tools.ts +++ b/src/tools/call-omo-agent/tools.ts @@ -48,7 +48,7 @@ export function createCallOmoAgent( if (args.session_id) { return `Error: session_id is not supported in background mode. Use run_in_background=false to continue an existing session.` } - return await executeBackground(args, toolCtx, backgroundManager) + return await executeBackground(args, toolCtx, backgroundManager, ctx.client) } return await executeSync(args, toolCtx, ctx)