From 6153a43c39f02d46ca91beb5fc492bf7cbcc18c8 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 21 Feb 2026 03:33:26 +0900 Subject: [PATCH] fix(hashline-read-enhancer): support plain read output without content tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) --- assets/oh-my-opencode.schema.json | 3 ++ src/hooks/hashline-read-enhancer/hook.ts | 29 ++++++++++++++----- .../hashline-read-enhancer/index.test.ts | 27 +++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index b9fbe2404..edbfd36a6 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -3208,6 +3208,9 @@ "disable_omo_env": { "type": "boolean" }, + "hashline_edit": { + "type": "boolean" + }, "model_fallback_title": { "type": "boolean" } diff --git a/src/hooks/hashline-read-enhancer/hook.ts b/src/hooks/hashline-read-enhancer/hook.ts index 63a88035d..9a3b58635 100644 --- a/src/hooks/hashline-read-enhancer/hook.ts +++ b/src/hooks/hashline-read-enhancer/hook.ts @@ -6,7 +6,7 @@ interface HashlineReadEnhancerConfig { hashline_edit?: { enabled: boolean } } -const READ_LINE_PATTERN = /^(\d+): (.*)$/ +const READ_LINE_PATTERN = /^(\d+): ?(.*)$/ const CONTENT_OPEN_TAG = "" const CONTENT_CLOSE_TAG = "" @@ -47,25 +47,38 @@ function transformOutput(output: string): string { const contentStart = lines.indexOf(CONTENT_OPEN_TAG) const contentEnd = lines.indexOf(CONTENT_CLOSE_TAG) - if (contentStart === -1 || contentEnd === -1 || contentEnd <= contentStart + 1) { - return output + if (contentStart !== -1 && contentEnd !== -1 && contentEnd > contentStart + 1) { + const fileLines = lines.slice(contentStart + 1, contentEnd) + if (!isTextFile(fileLines[0] ?? "")) { + return output + } + + const result: string[] = [] + for (const line of fileLines) { + if (!READ_LINE_PATTERN.test(line)) { + result.push(...fileLines.slice(result.length)) + break + } + result.push(transformLine(line)) + } + + return [...lines.slice(0, contentStart + 1), ...result, ...lines.slice(contentEnd)].join("\n") } - const fileLines = lines.slice(contentStart + 1, contentEnd) - if (!isTextFile(fileLines[0] ?? "")) { + if (!isTextFile(lines[0] ?? "")) { return output } const result: string[] = [] - for (const line of fileLines) { + for (const line of lines) { if (!READ_LINE_PATTERN.test(line)) { - result.push(...fileLines.slice(result.length)) + result.push(...lines.slice(result.length)) break } result.push(transformLine(line)) } - return [...lines.slice(0, contentStart + 1), ...result, ...lines.slice(contentEnd)].join("\n") + return result.join("\n") } function extractFilePath(metadata: unknown): string | undefined { diff --git a/src/hooks/hashline-read-enhancer/index.test.ts b/src/hooks/hashline-read-enhancer/index.test.ts index 7486132d5..6081a6f55 100644 --- a/src/hooks/hashline-read-enhancer/index.test.ts +++ b/src/hooks/hashline-read-enhancer/index.test.ts @@ -50,6 +50,33 @@ describe("hashline-read-enhancer", () => { expect(lines[10]).toBe("1: keep this unchanged") }) + it("hashifies plain read output without content tags", async () => { + //#given + const hook = createHashlineReadEnhancerHook(mockCtx(), { hashline_edit: { enabled: true } }) + const input = { tool: "read", sessionID: "s", callID: "c" } + const output = { + title: "README.md", + output: [ + "1: # Oh-My-OpenCode Features", + "2:", + "3: Hashline test", + "", + "(End of file - total 3 lines)", + ].join("\n"), + metadata: {}, + } + + //#when + await hook["tool.execute.after"](input, output) + + //#then + const lines = output.output.split("\n") + expect(lines[0]).toMatch(/^1#[ZPMQVRWSNKTXJBYH]{2}:# Oh-My-OpenCode Features$/) + expect(lines[1]).toMatch(/^2#[ZPMQVRWSNKTXJBYH]{2}:$/) + expect(lines[2]).toMatch(/^3#[ZPMQVRWSNKTXJBYH]{2}:Hashline test$/) + expect(lines[4]).toBe("(End of file - total 3 lines)") + }) + it("appends LINE#ID output for write tool using metadata filepath", async () => { //#given const hook = createHashlineReadEnhancerHook(mockCtx(), { hashline_edit: { enabled: true } })