From 1785313f3bada195d9d3f2d758fc02ff1f82f5fc Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 24 Feb 2026 18:21:05 +0900 Subject: [PATCH] fix(hashline-read-enhancer): skip hashifying OpenCode-truncated lines --- src/hooks/hashline-read-enhancer/hook.ts | 4 +++ .../hashline-read-enhancer/index.test.ts | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/hooks/hashline-read-enhancer/hook.ts b/src/hooks/hashline-read-enhancer/hook.ts index 8d0b2a5b4..652c000f5 100644 --- a/src/hooks/hashline-read-enhancer/hook.ts +++ b/src/hooks/hashline-read-enhancer/hook.ts @@ -13,6 +13,7 @@ const CONTENT_OPEN_TAG = "" const CONTENT_CLOSE_TAG = "" const FILE_OPEN_TAG = "" const FILE_CLOSE_TAG = "" +const OPENCODE_LINE_TRUNCATION_SUFFIX = "... (line truncated to 2000 chars)" function isReadTool(toolName: string): boolean { return toolName.toLowerCase() === "read" @@ -56,6 +57,9 @@ function transformLine(line: string): string { if (!parsed) { return line } + if (parsed.content.endsWith(OPENCODE_LINE_TRUNCATION_SUFFIX)) { + return line + } const hash = computeLineHash(parsed.lineNumber, parsed.content) return `${parsed.lineNumber}#${hash}|${parsed.content}` } diff --git a/src/hooks/hashline-read-enhancer/index.test.ts b/src/hooks/hashline-read-enhancer/index.test.ts index 0a3f29df9..dcab65bc9 100644 --- a/src/hooks/hashline-read-enhancer/index.test.ts +++ b/src/hooks/hashline-read-enhancer/index.test.ts @@ -84,6 +84,33 @@ describe("hashline-read-enhancer", () => { expect(lines[7]).toBe("") }) + it("keeps OpenCode-truncated lines unhashed while hashifying normal lines", async () => { + //#given + const hook = createHashlineReadEnhancerHook(mockCtx(), { hashline_edit: { enabled: true } }) + const input = { tool: "read", sessionID: "s", callID: "c" } + const truncatedLine = `${"x".repeat(60)}... (line truncated to 2000 chars)` + const output = { + title: "demo.ts", + output: [ + "/tmp/demo.ts", + "file", + "", + `1: ${truncatedLine}`, + "2: normal line", + "", + ].join("\n"), + metadata: {}, + } + + //#when + await hook["tool.execute.after"](input, output) + + //#then + const lines = output.output.split("\n") + expect(lines[3]).toBe(`1: ${truncatedLine}`) + expect(lines[4]).toMatch(/^2#[ZPMQVRWSNKTXJBYH]{2}\|normal line$/) + }) + it("hashifies plain read output without content tags", async () => { //#given const hook = createHashlineReadEnhancerHook(mockCtx(), { hashline_edit: { enabled: true } })