fix(session): cancel subtask child sessions (#25798)

This commit is contained in:
Kit Langton 2026-05-04 22:36:06 -04:00 committed by GitHub
commit 75d141b574
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 317 additions and 225 deletions

View file

@ -6,10 +6,11 @@ import { MessageV2 } from "../session/message-v2"
import { Agent } from "../agent/agent"
import type { SessionPrompt } from "../session/prompt"
import { Config } from "@/config/config"
import { Effect, Schema } from "effect"
import { Effect, Exit, Schema } from "effect"
import { EffectBridge } from "@/effect/bridge"
export interface TaskPromptOps {
cancel(sessionID: SessionID): void
cancel(sessionID: SessionID): Effect.Effect<void>
resolvePromptParts(template: string): Effect.Effect<SessionPrompt.PromptInput["parts"]>
prompt(input: SessionPrompt.PromptInput): Effect.Effect<MessageV2.WithParts>
}
@ -118,16 +119,18 @@ export const TaskTool = Tool.define(
const ops = ctx.extra?.promptOps as TaskPromptOps
if (!ops) return yield* Effect.fail(new Error("TaskTool requires promptOps in ctx.extra"))
const runCancel = yield* EffectBridge.make()
const messageID = MessageID.ascending()
const cancel = ops.cancel(nextSession.id)
function cancel() {
ops.cancel(nextSession.id)
function onAbort() {
runCancel.fork(cancel)
}
return yield* Effect.acquireUseRelease(
Effect.sync(() => {
ctx.abort.addEventListener("abort", cancel)
ctx.abort.addEventListener("abort", onAbort)
}),
() =>
Effect.gen(function* () {
@ -163,10 +166,16 @@ export const TaskTool = Tool.define(
].join("\n"),
}
}),
() =>
Effect.sync(() => {
ctx.abort.removeEventListener("abort", cancel)
}),
(_, exit) =>
Effect.gen(function* () {
if (Exit.hasInterrupts(exit)) yield* cancel
}).pipe(
Effect.ensuring(
Effect.sync(() => {
ctx.abort.removeEventListener("abort", onAbort)
}),
),
),
)
})