From ebcd6edf5ae94b1bab89e4a321565b2356298283 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 28 Apr 2026 18:00:21 +0900 Subject: [PATCH] perf(hashline): use write metadata line counts Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/hooks/hashline-read-enhancer/hook.ts | 22 +++++++++++++++++ .../hashline-read-enhancer/index.test.ts | 24 +++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/hooks/hashline-read-enhancer/hook.ts b/src/hooks/hashline-read-enhancer/hook.ts index 652c000f5..093312d4a 100644 --- a/src/hooks/hashline-read-enhancer/hook.ts +++ b/src/hooks/hashline-read-enhancer/hook.ts @@ -141,6 +141,22 @@ function extractFilePath(metadata: unknown): string | undefined { return undefined } +function extractLineCount(metadata: unknown): number | undefined { + if (!metadata || typeof metadata !== "object") { + return undefined + } + + const objectMeta = metadata as Record + const candidates = [objectMeta.lineCount, objectMeta.linesWritten, objectMeta.lines] + for (const candidate of candidates) { + if (typeof candidate === "number" && Number.isInteger(candidate) && candidate >= 0) { + return candidate + } + } + + return undefined +} + async function appendWriteHashlineOutput(output: { output: string; metadata: unknown }): Promise { if (output.output.startsWith(WRITE_SUCCESS_MARKER)) { return @@ -151,6 +167,12 @@ async function appendWriteHashlineOutput(output: { output: string; metadata: unk return } + const metadataLineCount = extractLineCount(output.metadata) + if (metadataLineCount !== undefined) { + output.output = `${WRITE_SUCCESS_MARKER} ${metadataLineCount} lines written.` + return + } + const filePath = extractFilePath(output.metadata) if (!filePath) { return diff --git a/src/hooks/hashline-read-enhancer/index.test.ts b/src/hooks/hashline-read-enhancer/index.test.ts index dcab65bc9..b46ffa88e 100644 --- a/src/hooks/hashline-read-enhancer/index.test.ts +++ b/src/hooks/hashline-read-enhancer/index.test.ts @@ -11,9 +11,9 @@ function mockCtx(): PluginInput { return { client: {} as PluginInput["client"], directory: "/test", - project: "/test" as unknown as PluginInput["project"], + project: "/test" as PluginInput["project"], worktree: "/test", - serverUrl: "http://localhost" as unknown as PluginInput["serverUrl"], + serverUrl: "http://localhost" as PluginInput["serverUrl"], $: {} as PluginInput["$"], } } @@ -238,6 +238,26 @@ describe("hashline-read-enhancer", () => { fs.rmSync(tempDir, { recursive: true, force: true }) }) + it("uses write metadata line count without reading the file", async () => { + //#given + const hook = createHashlineReadEnhancerHook(mockCtx(), { hashline_edit: { enabled: true } }) + const input = { tool: "write", sessionID: "s", callID: "c" } + const output = { + title: "write", + output: "Wrote file successfully.", + metadata: { + filepath: "/tmp/hashline-metadata-fast-path-missing-file.ts", + lineCount: 7, + }, + } + + //#when + await hook["tool.execute.after"](input, output) + + //#then + expect(output.output).toBe("File written successfully. 7 lines written.") + }) + it("does not overwrite write tool error output with success message", async () => { //#given — write tool failed, but stale file exists from previous write const hook = createHashlineReadEnhancerHook(mockCtx(), { hashline_edit: { enabled: true } })