Skip to content

Commit 94f5037

Browse files
committed
Fix infinite tool-call loop from over-aggressive trailing-message drop
The unconditional trailing-message drop introduced in 0.2.2 removed assistant messages with pending (non-completed) tool calls. The model then re-issued the tool call on the next turn, which produced another trailing assistant+tool message, which got dropped again — infinite loop. Fix: check each trailing message for pending tool parts before dropping. If a pending tool part is found, stop dropping (with a warning log) rather than removing the in-progress invocation. Completed tool parts are still safe to drop.
1 parent 1cb90cc commit 94f5037

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "opencode-lore",
3-
"version": "0.2.3",
3+
"version": "0.2.4",
44
"type": "module",
55
"license": "MIT",
66
"description": "Three-tier memory architecture for OpenCode — distillation, not summarization",

src/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,12 +395,25 @@ export const LorePlugin: Plugin = async (ctx) => {
395395
// so the append-only sequence stays intact for prompt caching.
396396
if (result.layer > 0) {
397397
// The API requires the conversation to end with a user message.
398-
// Always drop trailing non-user messages — even assistant messages with
399-
// tool parts. A hard API error is worse than the model re-invoking a tool.
398+
// Drop trailing non-user messages, but stop if we hit an assistant message
399+
// with an in-progress (non-completed) tool call — dropping it would cause
400+
// the model to lose its pending tool invocation and re-issue it in an
401+
// infinite loop. A completed tool part is safe to drop; a pending one is not.
400402
while (
401403
result.messages.length > 0 &&
402404
result.messages.at(-1)!.info.role !== "user"
403405
) {
406+
const last = result.messages.at(-1)!;
407+
const hasPendingTool = last.parts.some(
408+
(p) => p.type === "tool" && p.state.status !== "completed",
409+
);
410+
if (hasPendingTool) {
411+
console.error(
412+
"[lore] WARN: cannot drop trailing assistant message with pending tool call — may cause prefill error. id:",
413+
last.info.id,
414+
);
415+
break;
416+
}
404417
const dropped = result.messages.pop()!;
405418
console.error(
406419
"[lore] WARN: dropping trailing",

0 commit comments

Comments
 (0)