From a6e63cbdc08fd53d97b805b8ba6fccd81f9a83d1 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 16 May 2026 15:19:37 +0900 Subject: [PATCH] feat(lsp): inject diagnostics context --- README.md | 2 +- dist/codex-hook.d.ts.map | 2 +- dist/codex-hook.js | 10 ++++++- dist/codex-hook.js.map | 2 +- src/codex-hook.ts | 19 ++++++++++++- test/codex-hook.test.ts | 60 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 90 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4bb9dc4..6450a7e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Codex plugin that ports the standalone LSP runtime from [`pi-lsp-client`](https: |------|--------| | `apply_patch` succeeds | parses `tool_input.command`, extracts added/updated/moved files, and checks each with LSP error diagnostics | | `write` / `edit` / `multiedit` succeeds | checks `path`, `filePath`, or `file_path` aliases | -| diagnostics contain errors | returns Codex `PostToolUse` blocking feedback so Codex fixes the file | +| diagnostics contain errors | returns Codex `PostToolUse` blocking feedback and injects the same diagnostics as additional context so Codex fixes the file | | no diagnostics | emits no hook output | | unsupported extension | emits no hook output | | missing configured language server | surfaces the install/config message through hook or MCP output | diff --git a/dist/codex-hook.d.ts.map b/dist/codex-hook.d.ts.map index 8ca40af..5b21146 100644 --- a/dist/codex-hook.d.ts.map +++ b/dist/codex-hook.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"codex-hook.d.ts","sourceRoot":"","sources":["../src/codex-hook.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEtE,MAAM,WAAW,qBAAqB;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAWD,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7E;AAED,wBAAsB,qBAAqB,CAC1C,KAAK,EAAE,qBAAqB,EAC5B,cAAc,GAAE,iBAAyC,GACvD,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,EAAE,CAgB9E;AAED,wBAAsB,qBAAqB,CAAC,KAAK,GAAE,MAAM,CAAC,UAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlG"} \ No newline at end of file +{"version":3,"file":"codex-hook.d.ts","sourceRoot":"","sources":["../src/codex-hook.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEtE,MAAM,WAAW,qBAAqB;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAoBD,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7E;AAED,wBAAsB,qBAAqB,CAC1C,KAAK,EAAE,qBAAqB,EAC5B,cAAc,GAAE,iBAAyC,GACvD,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,EAAE,CAgB9E;AAED,wBAAsB,qBAAqB,CAAC,KAAK,GAAE,MAAM,CAAC,UAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlG"} \ No newline at end of file diff --git a/dist/codex-hook.js b/dist/codex-hook.js index da73438..80c5234 100644 --- a/dist/codex-hook.js +++ b/dist/codex-hook.js @@ -23,7 +23,15 @@ export async function runLspPostToolUseHook(input, runDiagnostics = runLspDiagno const reason = blocks .map(({ filePath, diagnostics }) => `LSP diagnostics after editing ${filePath}:\n${diagnostics}`) .join("\n\n"); - return `${JSON.stringify({ decision: "block", reason })}\n`; + const output = { + decision: "block", + reason, + hookSpecificOutput: { + hookEventName: "PostToolUse", + additionalContext: reason, + }, + }; + return `${JSON.stringify(output)}\n`; } export function extractMutatedFilePaths(input) { if (!isMutationTool(input.tool_name)) diff --git a/dist/codex-hook.js.map b/dist/codex-hook.js.map index fc7d158..912dab9 100644 --- a/dist/codex-hook.js.map +++ b/dist/codex-hook.js.map @@ -1 +1 @@ -{"version":3,"file":"codex-hook.js","sourceRoot":"","sources":["../src/codex-hook.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"codex-hook.js","sourceRoot":"","sources":["../src/codex-hook.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/codex-hook.ts b/src/codex-hook.ts index 433204a..990beae 100644 --- a/src/codex-hook.ts +++ b/src/codex-hook.ts @@ -15,6 +15,15 @@ interface DiagnosticBlock { diagnostics: string; } +interface PostToolUseHookOutput { + decision: "block"; + reason: string; + hookSpecificOutput: { + hookEventName: "PostToolUse"; + additionalContext: string; + }; +} + const MUTATION_TOOL_NAMES = new Set(["apply_patch", "write", "edit", "multiedit", "multi_edit"]); const CLEAN_DIAGNOSTICS_TEXT = "No diagnostics found"; const UNSUPPORTED_EXTENSION_TEXT = "No LSP server configured for extension:"; @@ -43,7 +52,15 @@ export async function runLspPostToolUseHook( const reason = blocks .map(({ filePath, diagnostics }) => `LSP diagnostics after editing ${filePath}:\n${diagnostics}`) .join("\n\n"); - return `${JSON.stringify({ decision: "block", reason })}\n`; + const output: PostToolUseHookOutput = { + decision: "block", + reason, + hookSpecificOutput: { + hookEventName: "PostToolUse", + additionalContext: reason, + }, + }; + return `${JSON.stringify(output)}\n`; } export function extractMutatedFilePaths(input: CodexPostToolUseInput): string[] { diff --git a/test/codex-hook.test.ts b/test/codex-hook.test.ts index 07a5b62..0bda45d 100644 --- a/test/codex-hook.test.ts +++ b/test/codex-hook.test.ts @@ -51,12 +51,72 @@ describe("codex PostToolUse hook", () => { expect(JSON.parse(output)).toEqual({ decision: "block", + hookSpecificOutput: { + hookEventName: "PostToolUse", + additionalContext: + "LSP diagnostics after editing src/broken.ts:\n" + + "error[typescript] (2304) at 1:1: Cannot find name 'missing'.", + }, reason: "LSP diagnostics after editing src/broken.ts:\n" + "error[typescript] (2304) at 1:1: Cannot find name 'missing'.", }); }); + it("injects only files with diagnostics when multiple files are edited", async () => { + const checkedFilePaths: string[] = []; + const output = await runLspPostToolUseHook( + { + tool_name: "MultiEdit", + tool_input: { + file_paths: ["src/clean.ts", "README.md", "src/broken.ts", "src/broken.ts"], + }, + tool_response: { ok: true }, + }, + async (filePath) => { + checkedFilePaths.push(filePath); + if (filePath === "src/broken.ts") { + return "error[typescript] (2322) at 1:7: Type 'number' is not assignable to type 'string'."; + } + if (filePath === "README.md") { + return "No LSP server configured for extension: .md"; + } + return "No diagnostics found"; + }, + ); + + const expectedDiagnostics = + "LSP diagnostics after editing src/broken.ts:\n" + + "error[typescript] (2322) at 1:7: Type 'number' is not assignable to type 'string'."; + + expect(checkedFilePaths).toEqual(["src/clean.ts", "README.md", "src/broken.ts"]); + expect(JSON.parse(output)).toEqual({ + decision: "block", + hookSpecificOutput: { + hookEventName: "PostToolUse", + additionalContext: expectedDiagnostics, + }, + reason: expectedDiagnostics, + }); + }); + + it("does not run diagnostics for failed mutation tool responses", async () => { + const output = await runLspPostToolUseHook( + { + tool_name: "apply_patch", + tool_input: { + command: "*** Begin Patch\n*** Update File: src/broken.ts\n@@\n+missing();\n*** End Patch\n", + }, + tool_response: { isError: true }, + }, + async () => { + throw new Error("diagnostics should not run after failed mutations"); + }, + ); + + expect(output).toBe(""); + }); + it("is silent for clean diagnostics and unsupported extensions", async () => { const output = await runLspPostToolUseHook( {