feat: add read_file tool

This commit is contained in:
2026-05-31 12:11:09 -05:00
parent 3f0d9a80c7
commit 0dc0f7eb53
5 changed files with 49 additions and 10 deletions
+2 -3
View File
@@ -487,9 +487,8 @@ export function CheckoutPrTool(ctx: ToolContext) {
hookWarning: checkoutResult.hookWarning,
instructions:
`the diff file at diffPath contains a table of contents (TOC) listing every changed file with its line range. ` +
`to read the diff, use the shell MCP tool — for example: shell({ command: 'sed -n "<start>,<end>p" ${join(tempDir, `pr-${pull_number}-${headShort}.diff`)}', description: 'read diff section' }). ` +
`use the TOC line ranges as your checklist and read specific sections. ` +
`for example, if the TOC says "src/foo.ts → lines 5-42", run: shell({ command: 'sed -n "5,42p" <diffPath>', description: 'read foo.ts diff' }). ` +
`use the read_file MCP tool to read sections of it. ` +
`for example, if the TOC says "src/foo.ts → lines 5-42", call: read_file({ path: diffPath, start_line: 5, end_line: 42 }). ` +
`IMPORTANT: to inspect the PR's changed files, read diffPath directly — ` +
`do NOT run git diff or git show. The PR base branch is '${pr.baseRef}', NOT necessarily 'main' — ` +
`if you must use git, use 'origin/${pr.baseRef}' as the base (e.g. git log origin/${pr.baseRef}..HEAD), ` +
+38
View File
@@ -0,0 +1,38 @@
import { readFileSync } from "node:fs";
import { type } from "arktype";
import type { ToolContext } from "./server.ts";
import { execute, tool } from "./shared.ts";
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. " +
"Example: `read_file({ path: diffPath, start_line: 5, end_line: 42 })`.",
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}`);
}
if (start_line === undefined && end_line === undefined) {
return { content };
}
const lines = content.split("\n");
const start = Math.max(0, (start_line ?? 1) - 1);
const end = Math.min(lines.length, end_line ?? lines.length);
return { content: lines.slice(start, end).join("\n") };
}),
});
}
+2
View File
@@ -35,6 +35,7 @@ import {
GetReviewCommentsTool,
ListPullRequestReviewsTool,
} from "./reviewComments.ts";
import { ReadFileTool } from "./readFile.ts";
import { SelectModeTool } from "./selectMode.ts";
import { addTools } from "./shared.ts";
import { KillBackgroundTool, ShellTool } from "./shell.ts";
@@ -118,6 +119,7 @@ function buildCommonTools(ctx: ToolContext, outputSchema?: JsonSchema): Tool<any
GitTool(ctx),
GitFetchTool(ctx),
UploadFileTool(ctx),
ReadFileTool(ctx),
];
const isStandalone = ctx.payload.event.trigger === "unknown";