From f127498e53b01ea7d5d6d4ae9a6363da3e2b8f89 Mon Sep 17 00:00:00 2001 From: Tyagiquamar Date: Tue, 25 Aug 2026 16:39:09 +0530 Subject: [PATCH] fix: stop delegation cleanup from leaking unhandled rejections --- src/rlm.ts | 3 ++- test/rlm.test.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/rlm.ts b/src/rlm.ts index 9e49dc0..51867c6 100644 --- a/src/rlm.ts +++ b/src/rlm.ts @@ -705,7 +705,8 @@ export async function press(query: string, context: Record | un })(); pendingRlmCalls.add(promise); - promise.finally(() => pendingRlmCalls.delete(promise)); + const removeFromPending = () => pendingRlmCalls.delete(promise); + promise.then(removeFromPending, removeFromPending); return promise; }; diff --git a/test/rlm.test.ts b/test/rlm.test.ts index f241fcc..7d11cc4 100644 --- a/test/rlm.test.ts +++ b/test/rlm.test.ts @@ -547,6 +547,33 @@ describe("press", () => { expect(toolResult!.content).toContain("other-component"); }); + it("caught delegation failure does not surface as a phantom error", async () => { + const events: Array<{ type: string; invocationId?: string; error?: string | null }> = []; + const callLLM = mockToolCallLLM([ + tc(`try { await press("child task", undefined, { model: "failer" }) } catch (e) { console.log("caught:", e.message) }`, "t1"), + tc('return "ok"', "t2"), + ]); + + const result = await press("parent task", undefined, { + callLLM, + maxDepth: 3, + models: { + failer: { + callLLM: async () => { + throw new Error("child boom"); + }, + }, + }, + observer: { emit: (event) => events.push(event as { type: string; invocationId?: string; error?: string | null }) }, + }); + + expect(result.answer).toBe("ok"); + const rootIterationEnds = events.filter((e) => e.type === "iteration:end" && e.invocationId === "root"); + for (const event of rootIterationEnds) { + expect(event.error).toBeNull(); + } + }); + it("use + systemPrompt concatenated", async () => { const systemPrompts: string[] = []; const callLLM: CallLLM = async (messages, systemPrompt) => {