From f2a7d227cbca2a8f04be52c91723a24d2ec639ce Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 12 Mar 2026 01:02:12 +0900 Subject: [PATCH] fix: omit sessionId from metadata when not yet assigned (#2441) --- .../create-background-output.metadata.test.ts | 68 +++++++++++++++ .../create-background-output.ts | 2 +- .../create-background-task.metadata.test.ts | 84 +++++++++++++++++++ .../background-task/create-background-task.ts | 8 +- 4 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/tools/background-task/create-background-output.metadata.test.ts create mode 100644 src/tools/background-task/create-background-task.metadata.test.ts diff --git a/src/tools/background-task/create-background-output.metadata.test.ts b/src/tools/background-task/create-background-output.metadata.test.ts new file mode 100644 index 000000000..5111667bb --- /dev/null +++ b/src/tools/background-task/create-background-output.metadata.test.ts @@ -0,0 +1,68 @@ +/// + +import type { ToolContext } from "@opencode-ai/plugin/tool" +import { describe, expect, test } from "bun:test" +import type { BackgroundTask } from "../../features/background-agent" +import { clearPendingStore, consumeToolMetadata } from "../../features/tool-metadata-store" +import type { BackgroundOutputClient, BackgroundOutputManager } from "./clients" +import { createBackgroundOutput } from "./create-background-output" + +const projectDir = "/Users/yeongyu/local-workspaces/oh-my-opencode" + +type ToolContextWithCallID = ToolContext & { + callID: string +} + +describe("createBackgroundOutput metadata", () => { + test("omits sessionId metadata when task session is not yet assigned", async () => { + // #given + clearPendingStore() + + const task: BackgroundTask = { + id: "task-1", + sessionID: undefined, + parentSessionID: "main-1", + parentMessageID: "msg-1", + description: "background task", + prompt: "do work", + agent: "test-agent", + status: "running", + } + const manager: BackgroundOutputManager = { + getTask: id => (id === task.id ? task : undefined), + } + const client: BackgroundOutputClient = { + session: { + messages: async () => ({ data: [] }), + }, + } + const tool = createBackgroundOutput(manager, client) + const context = { + sessionID: "test-session", + messageID: "test-message", + agent: "test-agent", + directory: projectDir, + worktree: projectDir, + abort: new AbortController().signal, + metadata: () => {}, + ask: async () => {}, + callID: "call-1", + } as ToolContextWithCallID + + // #when + await tool.execute({ task_id: task.id }, context) + + // #then + expect(consumeToolMetadata("test-session", "call-1")).toEqual({ + title: "test-agent - background task", + metadata: { + agent: "test-agent", + category: undefined, + description: "background task", + task_id: "task-1", + }, + }) + + clearPendingStore() + }) +}) diff --git a/src/tools/background-task/create-background-output.ts b/src/tools/background-task/create-background-output.ts index 446c0888e..3508052cf 100644 --- a/src/tools/background-task/create-background-output.ts +++ b/src/tools/background-task/create-background-output.ts @@ -75,7 +75,7 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client: agent: task.agent, category: task.category, description: task.description, - sessionId: task.sessionID ?? "pending", + ...(task.sessionID ? { sessionId: task.sessionID } : {}), } as Record, } ctx.metadata?.(meta) diff --git a/src/tools/background-task/create-background-task.metadata.test.ts b/src/tools/background-task/create-background-task.metadata.test.ts new file mode 100644 index 000000000..d21e69c09 --- /dev/null +++ b/src/tools/background-task/create-background-task.metadata.test.ts @@ -0,0 +1,84 @@ +/// + +import type { PluginInput } from "@opencode-ai/plugin" +import type { ToolContext } from "@opencode-ai/plugin/tool" +import { describe, expect, mock, test } from "bun:test" +import type { BackgroundManager } from "../../features/background-agent" +import { clearPendingStore, consumeToolMetadata } from "../../features/tool-metadata-store" +import { createBackgroundTask } from "./create-background-task" + +const projectDir = "/Users/yeongyu/local-workspaces/oh-my-opencode" + +type ToolContextWithCallID = ToolContext & { + callID: string +} + +describe("createBackgroundTask metadata", () => { + test("omits sessionId metadata when session is not yet assigned", async () => { + // #given + clearPendingStore() + + const manager = { + launch: mock(() => Promise.resolve({ + id: "task-1", + sessionID: null, + description: "Test task", + agent: "test-agent", + status: "pending", + })), + getTask: mock(() => undefined), + } as unknown as BackgroundManager + const client = { + session: { + messages: mock(() => Promise.resolve({ data: [] })), + }, + } as unknown as PluginInput["client"] + + let capturedMetadata: { title?: string; metadata?: Record } | undefined + const tool = createBackgroundTask(manager, client) + const originalDateNow = Date.now + let dateNowCallCount = 0 + Date.now = () => { + dateNowCallCount += 1 + return dateNowCallCount === 1 ? 0 : 30001 + } + + try { + // #when + const context: ToolContextWithCallID = { + sessionID: "test-session", + messageID: "test-message", + agent: "test-agent", + directory: projectDir, + worktree: projectDir, + abort: new AbortController().signal, + ask: async () => {}, + callID: "call-1", + metadata: input => { + capturedMetadata = input + }, + } + + const output = await tool.execute( + { + description: "Test background task", + prompt: "Test prompt", + agent: "test-agent", + }, + context + ) + + // #then + expect(output).toContain("Session ID: (not yet assigned)") + expect(output).not.toContain('Session ID: pending') + expect(capturedMetadata?.metadata).toEqual({}) + expect(consumeToolMetadata("test-session", "call-1")).toEqual({ + title: "Test background task", + metadata: {}, + }) + } finally { + Date.now = originalDateNow + clearPendingStore() + } + }) +}) diff --git a/src/tools/background-task/create-background-task.ts b/src/tools/background-task/create-background-task.ts index 9da0d5c50..8f57ed763 100644 --- a/src/tools/background-task/create-background-task.ts +++ b/src/tools/background-task/create-background-task.ts @@ -94,9 +94,11 @@ export function createBackgroundTask( const bgMeta = { title: args.description, - metadata: { sessionId: sessionId ?? "pending" }, + metadata: { + ...(sessionId ? { sessionId } : {}), + }, } - await ctx.metadata?.(bgMeta) + ctx.metadata?.(bgMeta) if (ctx.callID) { storeToolMetadata(ctx.sessionID, ctx.callID, bgMeta) @@ -105,7 +107,7 @@ export function createBackgroundTask( return `Background task launched successfully. Task ID: ${task.id} -Session ID: ${sessionId ?? "pending"} +Session ID: ${sessionId ?? "(not yet assigned)"} Description: ${task.description} Agent: ${task.agent} Status: ${task.status}