From 7ad5c27e7ce5b2eb1963bfdb945d23c200cc18f6 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Sat, 6 Jun 2026 23:01:43 -0400 Subject: [PATCH] refactor(core): simplify tool settlement outcomes --- packages/core/src/session/runner/run-turn.ts | 54 ++++++++++++-------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/packages/core/src/session/runner/run-turn.ts b/packages/core/src/session/runner/run-turn.ts index 1658bfd0fa7..196d5918613 100644 --- a/packages/core/src/session/runner/run-turn.ts +++ b/packages/core/src/session/runner/run-turn.ts @@ -240,31 +240,45 @@ export const make = Effect.gen(function* () { }), ) }) + const finishToolsSuccessfully = Effect.fnUntraced(function* (stream: Exit.Exit) { + if (Exit.hasInterrupts(stream) || publisher.hasProviderError()) yield* failUnsettled("Tool execution interrupted") + if (Exit.isSuccess(stream) && !publisher.hasProviderError()) + yield* failUnsettled("Provider did not return a tool result", true) + if (Exit.isFailure(stream)) return yield* Effect.failCause(stream.cause) + }) + const finishToolsAfterFailure = Effect.fnUntraced(function* ( + stream: Exit.Exit, + tools: FiberSet.FiberSet, + cause: Cause.Cause, + ) { + if (isQuestionRejected(cause)) { + yield* FiberSet.clear(tools) + yield* failUnsettled("Tool execution interrupted") + return yield* Effect.interrupt + } + const interrupted = Cause.hasInterrupts(cause) + if (interrupted) yield* FiberSet.clear(tools) + if (Exit.hasInterrupts(stream) || interrupted || publisher.hasProviderError()) + yield* failUnsettled("Tool execution interrupted") + if (!interrupted) { + const failure = Cause.squash(cause) + yield* failUnsettled(`Tool execution failed: ${failure instanceof Error ? failure.message : String(failure)}`) + } + if (Exit.isFailure(stream)) return yield* Effect.failCause(stream.cause) + return yield* Effect.failCause(cause) + }) const finishTools = Effect.fnUntraced(function* ( stream: Exit.Exit, tools: FiberSet.FiberSet, wait: Effect.Effect, ) { - const streamInterrupted = stream._tag === "Failure" && Cause.hasInterrupts(stream.cause) - if (streamInterrupted) yield* FiberSet.clear(tools) - const settled = yield* wait.pipe(Effect.exit) - if (settled._tag === "Failure" && isQuestionRejected(settled.cause)) { - yield* FiberSet.clear(tools) - yield* failUnsettled("Tool execution interrupted") - return yield* Effect.interrupt - } - const toolInterrupted = settled._tag === "Failure" && Cause.hasInterrupts(settled.cause) - if (toolInterrupted) yield* FiberSet.clear(tools) - if (streamInterrupted || toolInterrupted || publisher.hasProviderError()) - yield* failUnsettled("Tool execution interrupted") - if (settled._tag === "Failure" && !toolInterrupted) { - const failure = Cause.squash(settled.cause) - yield* failUnsettled(`Tool execution failed: ${failure instanceof Error ? failure.message : String(failure)}`) - } - if (stream._tag === "Success" && !publisher.hasProviderError()) - yield* failUnsettled("Provider did not return a tool result", true) - if (stream._tag === "Failure") return yield* Effect.failCause(stream.cause) - if (settled._tag === "Failure") return yield* Effect.failCause(settled.cause) + if (Exit.hasInterrupts(stream)) yield* FiberSet.clear(tools) + return yield* wait.pipe( + Effect.matchCauseEffect({ + onFailure: (cause) => finishToolsAfterFailure(stream, tools, cause), + onSuccess: () => finishToolsSuccessfully(stream), + }), + ) }) const settleProviderTurn = Effect.fnUntraced(function* () { const tools = yield* FiberSet.make()