Merge pull request #2476 from code-yeongyu/fix/issue-2441-session-id-pending
fix: omit sessionId from metadata when not yet assigned
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
/// <reference types="bun-types" />
|
||||||
|
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -75,7 +75,7 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client:
|
|||||||
agent: task.agent,
|
agent: task.agent,
|
||||||
category: task.category,
|
category: task.category,
|
||||||
description: task.description,
|
description: task.description,
|
||||||
sessionId: task.sessionID ?? "pending",
|
...(task.sessionID ? { sessionId: task.sessionID } : {}),
|
||||||
} as Record<string, unknown>,
|
} as Record<string, unknown>,
|
||||||
}
|
}
|
||||||
ctx.metadata?.(meta)
|
ctx.metadata?.(meta)
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/// <reference types="bun-types" />
|
||||||
|
|
||||||
|
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<string, unknown> } | 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()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -94,9 +94,11 @@ export function createBackgroundTask(
|
|||||||
|
|
||||||
const bgMeta = {
|
const bgMeta = {
|
||||||
title: args.description,
|
title: args.description,
|
||||||
metadata: { sessionId: sessionId ?? "pending" },
|
metadata: {
|
||||||
|
...(sessionId ? { sessionId } : {}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
await ctx.metadata?.(bgMeta)
|
ctx.metadata?.(bgMeta)
|
||||||
|
|
||||||
if (ctx.callID) {
|
if (ctx.callID) {
|
||||||
storeToolMetadata(ctx.sessionID, ctx.callID, bgMeta)
|
storeToolMetadata(ctx.sessionID, ctx.callID, bgMeta)
|
||||||
@@ -105,7 +107,7 @@ export function createBackgroundTask(
|
|||||||
return `Background task launched successfully.
|
return `Background task launched successfully.
|
||||||
|
|
||||||
Task ID: ${task.id}
|
Task ID: ${task.id}
|
||||||
Session ID: ${sessionId ?? "pending"}
|
Session ID: ${sessionId ?? "(not yet assigned)"}
|
||||||
Description: ${task.description}
|
Description: ${task.description}
|
||||||
Agent: ${task.agent}
|
Agent: ${task.agent}
|
||||||
Status: ${task.status}
|
Status: ${task.status}
|
||||||
|
|||||||
Reference in New Issue
Block a user