import { describe, it, expect } from "bun:test"; import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; import { createHashlineReadEnhancerHandler } from "./handler"; const HASHLINE_PATTERN = /^[0-9]+#[ZPMQVRWSNKTXJBYH]{2}\|/; describe("createHashlineReadEnhancerHandler", () => { describe("#given a Read tool output with content tags", () => { describe("#when the handler processes the output", () => { it("#then prepends LINE#HASH| to each file line inside content tags", async () => { const handler = createHashlineReadEnhancerHandler(); const input = { tool: "read", sessionID: "s1", callID: "c1", args: {} }; const output = { title: "demo.ts", output: [ "/tmp/demo.ts", "file", "", "1: const x = 1", "2: const y = 2", "", ].join("\n"), metadata: {}, }; await handler(input, output); const lines = output.output.split("\n"); expect(lines[3]).toMatch(HASHLINE_PATTERN); expect(lines[3]).toContain("const x = 1"); expect(lines[4]).toMatch(HASHLINE_PATTERN); expect(lines[4]).toContain("const y = 2"); }); }); }); describe("#given a Read tool output without content tags", () => { describe("#when the handler processes plain numbered lines", () => { it("#then hashifies each numbered line directly", async () => { const handler = createHashlineReadEnhancerHandler(); const input = { tool: "read", sessionID: "s1", callID: "c1", args: {} }; const output = { title: "README.md", output: ["1: # Title", "2: Some content", "3: More content"].join("\n"), metadata: {}, }; await handler(input, output); const lines = output.output.split("\n"); expect(lines[0]).toMatch(HASHLINE_PATTERN); expect(lines[0]).toContain("# Title"); expect(lines[1]).toMatch(HASHLINE_PATTERN); expect(lines[2]).toMatch(HASHLINE_PATTERN); }); }); }); describe("#given a non-Read tool", () => { describe("#when the handler processes the output", () => { it("#then leaves the output unchanged", async () => { const handler = createHashlineReadEnhancerHandler(); const input = { tool: "bash", sessionID: "s1", callID: "c1", args: {} }; const original = "1: some output"; const output = { title: "bash", output: original, metadata: {}, }; await handler(input, output); expect(output.output).toBe(original); }); }); }); describe("#given a Read tool with empty output", () => { describe("#when the handler processes the output", () => { it("#then returns the empty output unchanged", async () => { const handler = createHashlineReadEnhancerHandler(); const input = { tool: "read", sessionID: "s1", callID: "c1", args: {} }; const output = { title: "empty.ts", output: "", metadata: {}, }; await handler(input, output); expect(output.output).toBe(""); }); }); }); describe("#given a Write tool with a valid file path", () => { describe("#when the handler processes the output", () => { it("#then replaces output with a line count summary", async () => { const handler = createHashlineReadEnhancerHandler(); const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "hashline-read-write-")); const filePath = path.join(tempDir, "demo.ts"); fs.writeFileSync(filePath, "const x = 1\nconst y = 2"); const input = { tool: "write", sessionID: "s1", callID: "c1", args: {} }; const output = { title: "write", output: "Wrote file successfully.", metadata: { filepath: filePath }, }; await handler(input, output); expect(output.output).toContain("File written successfully."); expect(output.output).toContain("2 lines written."); fs.rmSync(tempDir, { recursive: true, force: true }); }); }); }); });