From 0274b726c964a158070858d3cf8f7eac451ebe0e Mon Sep 17 00:00:00 2001 From: maoxin1234 <875408344@qq.com> Date: Wed, 24 Jun 2026 17:18:35 +0800 Subject: [PATCH] fix(cli): dedupe subagent resume hint and await parent injection in test --- packages/opencode/src/tool/task.ts | 5 ++++- packages/opencode/test/tool/task.test.ts | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 65e065fbb1a..217f21c7042 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -85,7 +85,10 @@ function backgroundMessage(input: { ? `Background task completed: ${input.description}` : `Background task failed: ${input.description}` // kilocode_change start - surface the resumable task_id when a background subagent fails (#11620) - const body = input.state === "error" ? `${input.text}\n${resumeHint(input.sessionID)}` : input.text + const body = + input.state === "error" && !input.text.includes("can be resumed") + ? `${input.text}\n${resumeHint(input.sessionID)}` + : input.text // kilocode_change end return [ ``, diff --git a/packages/opencode/test/tool/task.test.ts b/packages/opencode/test/tool/task.test.ts index f25ed72a399..e376a9bb031 100644 --- a/packages/opencode/test/tool/task.test.ts +++ b/packages/opencode/test/tool/task.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect } from "bun:test" -import { Cause, Effect, Exit, Fiber, Layer } from "effect" // kilocode_change - Cause for squashing the failure exit +import { Cause, Deferred, Effect, Exit, Fiber, Layer } from "effect" // kilocode_change - Cause/Deferred for resume-hint coverage import { Agent } from "../../src/agent/agent" import { BackgroundJob } from "@/background/job" import { Bus } from "@/bus" @@ -574,6 +574,7 @@ describe("tool.task", () => { const tool = yield* TaskTool const def = yield* tool.init() const injected: SessionPrompt.PromptInput[] = [] + const parentInjected = yield* Deferred.make() const result = yield* def.execute( { @@ -594,7 +595,7 @@ describe("tool.task", () => { // The parent-session prompt is the injected background result; capture it. if (input.sessionID === chat.id) { injected.push(input) - return Effect.succeed(reply(input, "ack")) + return Effect.as(Deferred.succeed(parentInjected, undefined), reply(input, "ack")) } return Effect.die(new Error("child prompt failed")) }, @@ -608,6 +609,8 @@ describe("tool.task", () => { const childId = result.metadata.sessionId yield* jobs.wait({ id: childId, timeout: 1_000 }) + // The parent-session injection is forked asynchronously; wait for it before asserting. + yield* Deferred.await(parentInjected).pipe(Effect.timeout("1 second")) const text = injected .flatMap((input) => input.parts ?? [])