From 5ea7af24e16613e5871b424d3f4b20ecec4355f4 Mon Sep 17 00:00:00 2001 From: qinzhen06 Date: Fri, 1 May 2026 13:07:14 +0800 Subject: [PATCH] fix(processor): fix doom loop detection scope and filter order --- packages/opencode/src/session/processor.ts | 35 +++++++++++++--------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index b475ec1c5997..1d341a42c8f0 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -152,6 +152,25 @@ export const layer: Layer.Layer< return { call, part } }) + const recentMatchingToolParts = Effect.fn("SessionProcessor.recentMatchingToolParts")(function* (input: { + tool: string + args: Record + }) { + const messages = yield* MessageV2.filterCompactedEffect(ctx.sessionID) + const lastUserIndex = messages.findLastIndex((msg) => msg.info.role === "user") + return messages + .slice(lastUserIndex + 1) + .flatMap((msg) => msg.parts) + .filter( + (part): part is MessageV2.ToolPart => + part.type === "tool" && + part.tool === input.tool && + part.state.status !== "pending" && + JSON.stringify(part.state.input) === JSON.stringify(input.args), + ) + .slice(-DOOM_LOOP_THRESHOLD) + }) + const updateToolCall = Effect.fn("SessionProcessor.updateToolCall")(function* ( toolCallID: string, update: (part: MessageV2.ToolPart) => MessageV2.ToolPart, @@ -302,21 +321,9 @@ export const layer: Layer.Layer< : value.providerMetadata, })) - const parts = MessageV2.parts(ctx.assistantMessage.id) - const recentParts = parts.slice(-DOOM_LOOP_THRESHOLD) + const recentParts = yield* recentMatchingToolParts({ tool: value.toolName, args: value.input ?? {} }) - if ( - recentParts.length !== DOOM_LOOP_THRESHOLD || - !recentParts.every( - (part) => - part.type === "tool" && - part.tool === value.toolName && - part.state.status !== "pending" && - JSON.stringify(part.state.input) === JSON.stringify(value.input), - ) - ) { - return - } + if (recentParts.length !== DOOM_LOOP_THRESHOLD) return const agent = yield* agents.get(ctx.assistantMessage.agent) yield* permission.ask({