From 1b0ed01d3246b87d12b2ae2e8f0b0da9ce7fdc57 Mon Sep 17 00:00:00 2001 From: jiwangyihao Date: Tue, 12 May 2026 19:57:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(coding-agent):=20=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E6=89=80=E6=9C=89=E6=9C=80=E7=BB=88=20Promise=20=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/eval/js/shared/rewrite-imports.ts | 5 +---- packages/coding-agent/src/eval/js/shared/runtime.ts | 9 ++++++++- packages/coding-agent/test/core/js-executor.test.ts | 11 +++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts b/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts index f4b592370..9caca3c67 100644 --- a/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts +++ b/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts @@ -187,10 +187,7 @@ function returnFinalExpression(code: string): { source: string; returned: boolea const suffix = code.slice(expression.end); const semicolonMatch = statement.match(/;\s*$/); const trimmedStatement = semicolonMatch ? statement.slice(0, semicolonMatch.index) : statement; - const needsAwait = - expression.expression?.type === "AwaitExpression" || expression.expression?.type === "CallExpression"; - const displayExpression = needsAwait ? `await (${trimmedStatement})` : trimmedStatement; - return { source: `${prefix}__omp_display__(${displayExpression});${suffix}`, returned: true }; + return { source: `${prefix}globalThis.__omp_final_expr__ = (${trimmedStatement});${suffix}`, returned: true }; } /** diff --git a/packages/coding-agent/src/eval/js/shared/runtime.ts b/packages/coding-agent/src/eval/js/shared/runtime.ts index b1ba2278d..8f3a25d75 100644 --- a/packages/coding-agent/src/eval/js/shared/runtime.ts +++ b/packages/coding-agent/src/eval/js/shared/runtime.ts @@ -82,9 +82,16 @@ export class JsRuntime { } async run(code: string, filename?: string): Promise { + Reflect.deleteProperty(globalThis, "__omp_final_expr__"); const wrapped = wrapCode(code); const value = indirectEval(wrapped.source, filename); - return await awaitMaybePromise(value); + const awaited = await awaitMaybePromise(value); + if (Reflect.has(globalThis, "__omp_final_expr__")) { + const finalValue = (globalThis as { __omp_final_expr__?: unknown }).__omp_final_expr__; + Reflect.deleteProperty(globalThis, "__omp_final_expr__"); + return await awaitMaybePromise(finalValue); + } + return awaited; } displayValue(value: unknown): void { diff --git a/packages/coding-agent/test/core/js-executor.test.ts b/packages/coding-agent/test/core/js-executor.test.ts index f10aae61f..8333f432d 100644 --- a/packages/coding-agent/test/core/js-executor.test.ts +++ b/packages/coding-agent/test/core/js-executor.test.ts @@ -281,6 +281,17 @@ describe("executeJs", () => { expect(result.output.trim()).toBe('{\n "name": "demo",\n "enabled": true\n}'); }); + it("awaits identifier promise final expressions before displaying", async () => { + const result = await executeJs("const pending = read('config.json'); pending;", { + sessionId, + session, + sessionFile, + }); + + expect(result.exitCode).toBe(0); + expect(result.output.trim()).toBe('{\n "name": "demo",\n "enabled": true\n}'); + }); + it("auto-displays returned objects as structured output", async () => { const result = await executeJs("return { answer: 42, nested: { ok: true } };", { sessionId,