import { describe, expect, it } from "@effect/vitest"; import { recoverExecutionBody } from "./code-recovery"; const wrapCallableBody = (source: string): string => [ "const __fn = (", source, ");", 'if (typeof __fn !== "function") throw new Error("Code must evaluate to a function");', "return await __fn();", ].join("\n"); describe("recoverExecutionBody", () => { it("wraps an async arrow function body for invocation", () => { expect(recoverExecutionBody("async () => { return 1; }")).toBe( wrapCallableBody("async () => { return 1; }"), ); }); it("wraps an async arrow with params for invocation", () => { expect(recoverExecutionBody("async (x) => x + 1")).toBe(wrapCallableBody("async (x) => x + 1")); }); it("strips export default from an async arrow", () => { expect(recoverExecutionBody("export default async () => 42")).toBe( wrapCallableBody("async () => 42"), ); }); it("leaves a bare expression as a statement body", () => { expect(recoverExecutionBody("1 + 2")).toBe("1 + 2"); }); it("wraps a named function declaration and calls it", () => { expect(recoverExecutionBody("function hello() { return 42; }")).toBe( "function hello() { return 42; }\nreturn await hello();", ); }); it("wraps an async function declaration", () => { expect(recoverExecutionBody("async function run() { return 'ok'; }")).toBe( "async function run() { return 'ok'; }\nreturn await run();", ); }); it("wraps an exported default named async function declaration", () => { expect(recoverExecutionBody("export default async function run() { return 'ok'; }")).toBe( "async function run() { return 'ok'; }\nreturn await run();", ); }); it("wraps an exported default anonymous async function declaration", () => { expect(recoverExecutionBody("export default async function () { return 'ok'; }")).toBe( "return await (async function () { return 'ok'; })();", ); }); it("strips markdown code fences", () => { expect(recoverExecutionBody("```js\nasync () => 42\n```")).toBe( wrapCallableBody("async () => 42"), ); }); it("strips typescript fences", () => { expect(recoverExecutionBody("```typescript\nasync () => 42\n```")).toBe( wrapCallableBody("async () => 42"), ); }); it("returns an empty body for an empty string", () => { expect(recoverExecutionBody("")).toBe(""); }); it("returns an empty body for whitespace-only", () => { expect(recoverExecutionBody(" \n ")).toBe(""); }); it("handles multi-statement code", () => { const code = "const a = 1;\nconst b = 2;\na + b"; expect(recoverExecutionBody(code)).toBe(code); }); it("accepts a parenthesized async arrow from a fenced block", () => { expect(recoverExecutionBody("```ts\n(async () => 42)\n```")).toBe( wrapCallableBody("(async () => 42)"), ); }); it("passes through an async arrow with noisy spacing", () => { expect(recoverExecutionBody(" \n\tasync ( input ) => input?.value ?? 42 \n")).toBe( wrapCallableBody("async ( input ) => input?.value ?? 42"), ); }); it("strips export default from a parenthesized async arrow", () => { expect(recoverExecutionBody("export default (async () => 42)")).toBe( wrapCallableBody("async () => 42"), ); }); it("wraps a sync anonymous function declaration from a fence", () => { expect(recoverExecutionBody("```javascript\nfunction () { return 42; }\n```")).toBe( "return await (function () { return 42; })();", ); }); it("keeps a statement body that already contains return", () => { const code = 'const query = "github issues";\nreturn await tools.search({ query, limit: 5 });'; expect(recoverExecutionBody(code)).toBe(code); }); it("keeps a multiline async arrow with comments by wrapping the source", () => { const code = [ "async () => {", ' console.log("before");', " // Model added some narration inline", " return 42;", "}", ].join("\n"); expect(recoverExecutionBody(code)).toBe(wrapCallableBody(code)); }); it("extracts code from prose wrapped fences", () => { const code = ["Sure, here's the code:", "", "```ts", "async () => 42", "```"].join("\n"); expect(recoverExecutionBody(code)).toBe(wrapCallableBody("async () => 42")); }); it("ignores leading comments before an async arrow", () => { const code = [ "// calling tools.search with the narrowed namespace", 'async () => await tools.search({ query: "list contacts", namespace: "crm", limit: 5 })', ].join("\n"); expect(recoverExecutionBody(code)).toBe(wrapCallableBody(code)); }); it("handles block comments before export default", () => { const code = ["/* generated by the model */", "export default async () => 42"].join("\n"); expect(recoverExecutionBody(code)).toBe(wrapCallableBody("async () => 42")); }); it("handles uppercase fence labels", () => { expect(recoverExecutionBody("```TypeScript\nasync () => 42\n```")).toBe( wrapCallableBody("async () => 42"), ); }); it("treats a named function with leading comments as a declaration", () => { const code = [ "// top-level helper the model wanted to keep", "async function run() {", ' return "ok";', "}", ].join("\n"); expect(recoverExecutionBody(code)).toBe(`${code}\nreturn await run();`); }); it("extracts the body from prose before and after a fence", () => { const code = [ "Use this exact snippet.", "", "```javascript", 'return await tools.search({ query: "github issues", limit: 5 });', "```", "", "That should do it.", ].join("\n"); expect(recoverExecutionBody(code)).toBe( 'return await tools.search({ query: "github issues", limit: 5 });', ); }); it("keeps a complex multi-step function body intact", () => { const code = [ 'const query = "recent pull requests";', "const limit = 5;", "", "function pickTop(matches) {", " return matches.slice(0, 3).map((match) => match.path);", "}", "", "try {", " const matches = await tools.search({ query, limit });", " const top = pickTop(matches);", ' console.log("top results", top);', " return { count: matches.length, top };", "} catch (error) {", " return {", " error: error instanceof Error ? error.message : String(error),", " query,", " };", "}", ].join("\n"); expect(recoverExecutionBody(code)).toBe(code); }); it("extracts a complex fenced function body from surrounding prose", () => { const body = [ "const owner = 'openai';", "const repo = 'executor';", "", "const issues = await tools.github.listRepositoryIssues({ owner, repo });", "const titles = issues", " .slice(0, 5)", " .map((issue) => issue.title)", " .filter(Boolean);", "", "return {", " owner,", " repo,", " titles,", "};", ].join("\n"); const code = [ "Run this:", "", "```ts", body, "```", "", "It should return the top issue titles.", ].join("\n"); expect(recoverExecutionBody(code)).toBe(body); }); it("wraps a complex async arrow body for invocation", () => { const code = [ "async () => {", ' const query = "list contacts";', " const results = await tools.search({", " query,", ' namespace: "crm",', " limit: 5,", " });", "", " return results.map((result) => ({", " path: result.path,", " score: result.score ?? null,", " }));", "}", ].join("\n"); expect(recoverExecutionBody(code)).toBe(wrapCallableBody(code)); }); });