From af8aff37889c059e38ccf2e18e10ee156bf0eea1 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 10 Apr 2026 22:57:47 -0400 Subject: [PATCH] refactor: make TaskPromptOps effectful (#21971) --- packages/opencode/src/session/prompt.ts | 4 +-- packages/opencode/src/tool/task.ts | 38 +++++++++++------------- packages/opencode/test/tool/task.test.ts | 11 +++---- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index fabcfdcf6f..a1bdcb1b98 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1665,8 +1665,8 @@ NOTE: At any point in time through this workflow you should feel free to ask the const promptOps: TaskPromptOps = { cancel: (sessionID) => run.fork(cancel(sessionID)), - resolvePromptParts: (template) => run.promise(resolvePromptParts(template)), - prompt: (input) => run.promise(prompt(input)), + resolvePromptParts: (template) => resolvePromptParts(template), + prompt: (input) => prompt(input), } return Service.of({ diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 3829aeae11..a8e7a8d69c 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -12,8 +12,8 @@ import { Log } from "@/util/log" export interface TaskPromptOps { cancel(sessionID: SessionID): void - resolvePromptParts(template: string): Promise - prompt(input: SessionPrompt.PromptInput): Promise + resolvePromptParts(template: string): Effect.Effect + prompt(input: SessionPrompt.PromptInput): Effect.Effect } const id = "task" @@ -132,24 +132,22 @@ export const TaskTool = Tool.define( }), () => Effect.gen(function* () { - const parts = yield* Effect.promise(() => ops.resolvePromptParts(params.prompt)) - const result = yield* Effect.promise(() => - ops.prompt({ - messageID, - sessionID: nextSession.id, - model: { - modelID: model.modelID, - providerID: model.providerID, - }, - agent: next.name, - tools: { - ...(canTodo ? {} : { todowrite: false }), - ...(canTask ? {} : { task: false }), - ...Object.fromEntries((cfg.experimental?.primary_tools ?? []).map((item) => [item, false])), - }, - parts, - }), - ) + const parts = yield* ops.resolvePromptParts(params.prompt) + const result = yield* ops.prompt({ + messageID, + sessionID: nextSession.id, + model: { + modelID: model.modelID, + providerID: model.providerID, + }, + agent: next.name, + tools: { + ...(canTodo ? {} : { todowrite: false }), + ...(canTask ? {} : { task: false }), + ...Object.fromEntries((cfg.experimental?.primary_tools ?? []).map((item) => [item, false])), + }, + parts, + }) return { title: params.description, diff --git a/packages/opencode/test/tool/task.test.ts b/packages/opencode/test/tool/task.test.ts index 478ff96628..943e68e78c 100644 --- a/packages/opencode/test/tool/task.test.ts +++ b/packages/opencode/test/tool/task.test.ts @@ -65,11 +65,12 @@ const seed = Effect.fn("TaskToolTest.seed")(function* (title = "Pinned") { function stubOps(opts?: { onPrompt?: (input: SessionPrompt.PromptInput) => void; text?: string }): TaskPromptOps { return { cancel() {}, - resolvePromptParts: async (template) => [{ type: "text", text: template }], - prompt: async (input) => { - opts?.onPrompt?.(input) - return reply(input, opts?.text ?? "done") - }, + resolvePromptParts: (template) => Effect.succeed([{ type: "text" as const, text: template }]), + prompt: (input) => + Effect.sync(() => { + opts?.onPrompt?.(input) + return reply(input, opts?.text ?? "done") + }), } }