73 lines
2.6 KiB
TypeScript
73 lines
2.6 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
import * as fs from "node:fs/promises";
|
|
import * as os from "node:os";
|
|
import * as path from "node:path";
|
|
import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
|
|
import type { ToolSession } from "@oh-my-pi/pi-coding-agent/tools";
|
|
import { ReadTool } from "@oh-my-pi/pi-coding-agent/tools/read";
|
|
|
|
function getTextOutput(result: { content: Array<{ type: string; text?: string }> }): string {
|
|
return result.content
|
|
.filter(c => c.type === "text" && typeof c.text === "string")
|
|
.map(c => c.text as string)
|
|
.join("\n");
|
|
}
|
|
|
|
function makeSession(cwd: string): ToolSession {
|
|
return {
|
|
cwd,
|
|
hasUI: false,
|
|
getSessionFile: () => path.join(cwd, "session.jsonl"),
|
|
getSessionSpawns: () => "*",
|
|
getArtifactsDir: () => path.join(cwd, "session"),
|
|
settings: Settings.isolated(),
|
|
};
|
|
}
|
|
|
|
describe("read tool raw range exactness", () => {
|
|
let testDir: string;
|
|
let filePath: string;
|
|
let tool: ReadTool;
|
|
|
|
beforeEach(async () => {
|
|
testDir = await fs.mkdtemp(path.join(os.tmpdir(), "read-raw-range-"));
|
|
filePath = path.join(testDir, "data.txt");
|
|
const lines = Array.from({ length: 60 }, (_, index) => `L${String(index + 1).padStart(2, "0")}`);
|
|
await Bun.write(filePath, lines.join("\n"));
|
|
tool = new ReadTool(makeSession(testDir));
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await fs.rm(testDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it("returns exactly the requested single line for raw:N-N", async () => {
|
|
// Regression: raw ranges used to get 1 leading + 3 trailing context
|
|
// lines. Without line numbers the padding is indistinguishable from
|
|
// requested content, so verbatim-extraction callers pasted 5 lines
|
|
// where they asked for 1.
|
|
const result = await tool.execute("call-raw-single", { path: `${filePath}:raw:31-31` });
|
|
const output = getTextOutput(result);
|
|
|
|
expect(output.trimEnd()).toBe("L31");
|
|
});
|
|
|
|
it("returns exactly the requested raw range at the start of the file", async () => {
|
|
const result = await tool.execute("call-raw-head", { path: `${filePath}:raw:1-2` });
|
|
const output = getTextOutput(result);
|
|
|
|
expect(output.trimEnd()).toBe("L01\nL02");
|
|
});
|
|
|
|
it("keeps context padding for numbered range reads", async () => {
|
|
// Numbered mode intentionally pads (leading anchor buffer + trailing
|
|
// disambiguation lines) — line numbers make the padding self-describing.
|
|
const result = await tool.execute("call-numbered", { path: `${filePath}:31-31` });
|
|
const output = getTextOutput(result);
|
|
|
|
expect(output).toContain("L31");
|
|
expect(output).toContain("L30");
|
|
expect(output).toContain("L32");
|
|
});
|
|
});
|