From 9a8d60a187443807a273df28745ed645e210b5c9 Mon Sep 17 00:00:00 2001 From: aobazk <123452733+fpdy@users.noreply.github.com> Date: Sun, 14 Jun 2026 11:28:54 +0900 Subject: [PATCH] fix: await async generator return value in warpgrep_codebase_search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The morphsdk WarpGrepClient.execute() async generator returns a Promise from processAgentResult() via `return promise`. Node.js auto-awaits it per ECMAScript spec, but Bun does not — the unresolved Promise becomes the .next() value. Without the explicit await, result was a Promise whose .success was undefined, and formatWarpGrepResult returned the generic failure message: "Search failed: search returned no error details." The fix is a single line: `result = await value`. This is harmless on Node.js (await on a non-Promise is a no-op) and resolves the Promise on Bun. Closes #24 --- index.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ index.ts | 6 +++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/index.test.ts b/index.test.ts index 14e5a6c..7c5b2d0 100644 --- a/index.test.ts +++ b/index.test.ts @@ -1156,3 +1156,43 @@ describe("formatWarpGrepResult edge cases", () => { expect(result).toBe("Search failed: timeout after 60s"); }); }); + +describe("warpgrep_codebase_search result handling", () => { + test("awaits the async generator return value (Bun compatibility)", async () => { + const fakeResult = { + success: true, + contexts: [ + { file: "src/auth.ts", content: "code", lines: [[1, 5]] as Array<[number, number]> }, + ], + summary: "found auth", + }; + + const original = WarpGrepClient.prototype.execute; + // Async generator that returns a result via `return` (not yield). + // In Bun, `return value` in an async generator may not auto-await, + // so the plugin must explicitly await the final .next() value. + WarpGrepClient.prototype.execute = async function* (): AsyncGenerator { + return fakeResult; + } as any; + + try { + const { default: MorphPlugin } = await importPluginWithEnv({ + MORPH_API_KEY: "sk-test-key", + }); + const hooks = await MorphPlugin( + makePluginInput("/tmp/morph-warpgrep-async-test"), + ); + const output = (await hooks.tool.warpgrep_codebase_search.execute( + { search_term: "auth flow" }, + makeToolContext("/tmp/morph-warpgrep-async-test"), + )) as string; + + // Without the `await` fix, `value` is a Promise, `result.success` is + // undefined, and formatWarpGrepResult returns the generic failure message. + expect(output).toContain("Relevant context found:"); + expect(output).toContain("src/auth.ts"); + } finally { + WarpGrepClient.prototype.execute = original; + } + }); +}); diff --git a/index.ts b/index.ts index d3a166d..72c71b3 100644 --- a/index.ts +++ b/index.ts @@ -1046,7 +1046,11 @@ Get your API key at: https://morphllm.com/dashboard/api-keys`; for (;;) { const { value, done } = await generator.next(); if (done) { - result = value; + // Bun: morphsdk's async generator returns an unawaited Promise + // from processAgentResult() via `return promise`. Node.js + // auto-awaits it per spec, but Bun does not. Explicitly await + // so the resolved WarpGrepResult is used instead of a Promise. + result = await value as WarpGrepResult; break; } turnCount = value.turn;