54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { type } from "arktype";
|
|
import type { ToolContext } from "./server.ts";
|
|
import { execute, tool } from "./shared.ts";
|
|
|
|
/** Hard cap on returned content to avoid flooding the model's context window. */
|
|
const MAX_CHARS = 12000;
|
|
|
|
export const ReadFileParams = type({
|
|
path: type.string.describe("absolute path to the file to read"),
|
|
"start_line?": type.number.describe("start line, 1-based inclusive (default: 1)"),
|
|
"end_line?": type.number.describe("end line, 1-based inclusive (default: end of file)"),
|
|
});
|
|
|
|
export function ReadFileTool(_ctx: ToolContext) {
|
|
return tool({
|
|
name: "read_file",
|
|
description:
|
|
"Read lines from a file. Use this to read sections of the PR diff returned by checkout_pr. " +
|
|
`Returns at most ${MAX_CHARS} characters. ` +
|
|
"Prefer fewer, wider reads: read large contiguous ranges rather than many small ones. " +
|
|
"If the TOC lists 10 files, read 3-4 wide ranges that cover them rather than 10 separate calls. " +
|
|
"Example: `read_file({ path: diffPath, start_line: 5, end_line: 200 })`.",
|
|
parameters: ReadFileParams,
|
|
execute: execute(async ({ path, start_line, end_line }) => {
|
|
let content: string;
|
|
try {
|
|
content = readFileSync(path, "utf-8");
|
|
} catch (err) {
|
|
const msg = err instanceof Error ? err.message : String(err);
|
|
throw new Error(`failed to read ${path}: ${msg}`);
|
|
}
|
|
|
|
const lines = content.split("\n");
|
|
const start = Math.max(0, (start_line ?? 1) - 1);
|
|
const end = Math.min(lines.length, end_line ?? lines.length);
|
|
const slice = lines.slice(start, end).join("\n");
|
|
|
|
if (slice.length <= MAX_CHARS) {
|
|
return { content: slice };
|
|
}
|
|
|
|
const truncated = slice.slice(0, MAX_CHARS);
|
|
const linesShown = truncated.split("\n").length;
|
|
const linesTotal = end - start;
|
|
return {
|
|
content: truncated,
|
|
truncated: true,
|
|
note: `Output capped at ${MAX_CHARS} chars (showed ${linesShown}/${linesTotal} lines). Use a narrower line range to read the rest.`,
|
|
};
|
|
}),
|
|
});
|
|
}
|