// agentSSEInferer.test.ts — Regressione per sseActionInferer.ts // Protegge i 6 bug corretti in inferActionType e la copertura label italiane. // Runner: vitest run (configurato in package.json) import { describe, it, expect } from "vitest"; import { inferActionType, inferActionLabel, inferActionDetail } from "../sseActionInferer"; import type { SSEEvent } from "../agentSSETypes"; function ev(tool?: string, extra: Record = {}): SSEEvent { return { event: "step_start", taskId: "test", ...(tool ? { tool } : {}), ...extra } as SSEEvent; } // ─── inferActionType ────────────────────────────────────────────────────────── describe("inferActionType — bug fix regressions", () => { // FIX-1/2: browser_* era catturato da n.includes("open") → file_open // browser_navigate/act/screenshot non avevano match → tool_call it("browser_open → search_web (era file_open)", () => { expect(inferActionType("browser_open", ev("browser_open"))).toBe("search_web"); }); it("browser_navigate → search_web (era tool_call)", () => { expect(inferActionType("browser_navigate", ev("browser_navigate"))).toBe("search_web"); }); it("browser_act → search_web (era tool_call)", () => { expect(inferActionType("browser_act", ev("browser_act"))).toBe("search_web"); }); it("browser_screenshot → search_web (era tool_call)", () => { expect(inferActionType("browser_screenshot", ev("browser_screenshot"))).toBe("search_web"); }); it("browser_close → search_web", () => { expect(inferActionType("browser_close", ev("browser_close"))).toBe("search_web"); }); // FIX-3: git_list_files catturato da n.includes("file") → file_open it("git_list_files → api_call (era file_open)", () => { expect(inferActionType("git_list_files", ev("git_list_files"))).toBe("api_call"); }); it("git_push → api_call (era tool_call)", () => { expect(inferActionType("git_push", ev("git_push"))).toBe("api_call"); }); it("git_sync_vfs → api_call (era tool_call)", () => { expect(inferActionType("git_sync_vfs", ev("git_sync_vfs"))).toBe("api_call"); }); it("diff_commits → api_call (era tool_call)", () => { expect(inferActionType("diff_commits", ev("diff_commits"))).toBe("api_call"); }); // FIX-4: deploy → tool_call it("deploy_trigger → api_call (era tool_call)", () => { expect(inferActionType("deploy_trigger", ev("deploy_trigger"))).toBe("api_call"); }); it("check_deploy → api_call (era tool_call)", () => { expect(inferActionType("check_deploy", ev("check_deploy"))).toBe("api_call"); }); // FIX-5: generate_* → tool_call it("generate_image → file_write (era tool_call)", () => { expect(inferActionType("generate_image", ev("generate_image"))).toBe("file_write"); }); it("generate_readme → file_write (era tool_call)", () => { expect(inferActionType("generate_readme", ev("generate_readme"))).toBe("file_write"); }); it("create_chart → file_write (era tool_call)", () => { expect(inferActionType("create_chart", ev("create_chart"))).toBe("file_write"); }); // FIX-6: analyze_image → plan (n.includes("analyz")) it("analyze_image → file_read (era plan)", () => { expect(inferActionType("analyze_image", ev("analyze_image"))).toBe("file_read"); }); // send_email it("send_email → api_call (era tool_call)", () => { expect(inferActionType("send_email", ev("send_email"))).toBe("api_call"); }); }); describe("inferActionType — pattern generici invariati", () => { it("web_search → search_web", () => expect(inferActionType("web_search", ev("web_search"))).toBe("search_web")); it("write_file → file_write", () => expect(inferActionType("write_file", ev("write_file"))).toBe("file_write")); it("read_file → file_read", () => expect(inferActionType("read_file", ev("read_file"))).toBe("file_read")); it("delete_file → file_delete", () => expect(inferActionType("delete_file", ev("delete_file"))).toBe("file_delete")); it("run_python → code_run", () => expect(inferActionType("run_python", ev("run_python"))).toBe("code_run")); it("execute_shell → code_run", () => expect(inferActionType("execute_shell", ev("execute_shell"))).toBe("code_run")); it("run_tests → code_run", () => expect(inferActionType("run_tests", ev("run_tests"))).toBe("code_run")); it("planning → plan", () => expect(inferActionType("planning", ev("planning"))).toBe("plan")); it("goal_verifier → plan", () => expect(inferActionType("goal_verifier", ev("goal_verifier"))).toBe("plan")); it("execution_validator_fix → plan", () => expect(inferActionType("execution_validator_fix", ev("execution_validator_fix"))).toBe("plan")); it("validate_project → plan", () => expect(inferActionType("validate_project", ev("validate_project"))).toBe("plan")); it("__thinking__ → thinking", () => expect(inferActionType("__thinking__", ev("__thinking__"))).toBe("thinking")); it("remember → memory", () => expect(inferActionType("remember", ev("remember"))).toBe("memory")); it("calculate → tool_call", () => expect(inferActionType("calculate", ev("calculate"))).toBe("tool_call")); it("unknown_tool → tool_call", () => expect(inferActionType("unknown_tool", ev())).toBe("tool_call")); }); // ─── inferActionLabel ───────────────────────────────────────────────────────── describe("inferActionLabel — etichette italiane", () => { const EXPECTED: Array<[string, string]> = [ ["web_search", "Ricerca web"], ["run_python", "Script Python"], ["git_push", "Pubblica su Git"], ["send_email", "Email"], ["browser_navigate", "Naviga"], ["generate_image", "Genera immagine"], ["analyze_image", "Analisi immagine"], ["deploy_trigger", "Avvio deploy"], ["tool_governor_skip", "Cache hit"], ["__plan__", "Pianificazione"], ["__thinking__", "Analisi"], ["execution_validator_fix", "Fix automatico"], ["translate", "Traduzione"], ["text_to_speech", "Audio"], ["zip_project", "Comprimi progetto"], ]; EXPECTED.forEach(([tool, label]) => { it(`${tool} → "${label}"`, () => { expect(inferActionLabel(tool, ev(tool))).toBe(label); }); }); it("preferisce path sul label del tool", () => { expect(inferActionLabel("write_file", ev("write_file", { path: "/src/App.tsx" }))).toBe("App.tsx"); }); it("preferisce url/query sul label del tool", () => { expect(inferActionLabel("web_search", ev("web_search", { query: "react hooks" }))).toBe("react hooks"); }); it("humanizza tool sconosciuto (raw → Title case)", () => { expect(inferActionLabel("my_custom_tool", ev())).toBe("My custom tool"); }); it("rimuove underscore iniziali dai tool interni", () => { expect(inferActionLabel("__plan__", ev("__plan__"))).toBe("Pianificazione"); }); }); // ─── inferActionDetail ──────────────────────────────────────────────────────── describe("inferActionDetail", () => { it("ritorna path quando presente", () => expect(inferActionDetail(ev("write_file", { path: "/src/App.tsx" }))).toBe("/src/App.tsx")); it("ritorna url quando path assente", () => expect(inferActionDetail(ev("web_search", { url: "https://example.com" }))).toBe("https://example.com")); it("preferisce path su url", () => expect(inferActionDetail(ev("write_file", { path: "/a.ts", url: "https://x.com" }))).toBe("/a.ts")); it("ritorna undefined senza path/url", () => expect(inferActionDetail(ev("planning"))).toBeUndefined()); it("supporta campo file come path", () => expect(inferActionDetail(ev("read_file", { file: "/src/index.ts" }))).toBe("/src/index.ts")); });