import { writeFileSync } from "node:fs"; import { join } from "node:path"; import { type } from "arktype"; import { log } from "../utils/cli.ts"; import { formatFilesWithLineNumbers } from "./checkout.ts"; import type { ToolContext } from "./server.ts"; import { execute, tool } from "./shared.ts"; export const CommitInfo = type({ sha: type.string.describe("the commit SHA (full or abbreviated) to fetch"), }); export function CommitInfoTool(ctx: ToolContext) { return tool({ name: "get_commit_info", description: "Retrieve commit metadata and diff via GitHub API. Use this instead of git show for reviewing commits - " + "it works with shallow clones and shows the actual changes in the commit. Returns diffPath pointing to formatted diff file.", parameters: CommitInfo, execute: execute(async ({ sha }) => { const response = await ctx.octokit.rest.repos.getCommit({ owner: ctx.repo.owner, repo: ctx.repo.name, ref: sha, }); const data = response.data; const files = data.files ?? []; // format diff with line numbers and write to file const diffContent = formatFilesWithLineNumbers(files); const tempDir = process.env.PULLFROG_TEMP_DIR; if (!tempDir) { throw new Error( "PULLFROG_TEMP_DIR not set - get_commit_info must run in pullfrog action context" ); } const diffFile = join(tempDir, `commit-${sha.slice(0, 7)}.diff`); writeFileSync(diffFile, diffContent); log.debug(`wrote commit diff to ${diffFile} (${diffContent.length} bytes)`); return { sha: data.sha, message: data.commit.message, author: data.author?.login ?? null, committer: data.committer?.login ?? null, date: data.commit.author?.date ?? data.commit.committer?.date ?? "", url: data.html_url, parents: data.parents.map((p) => p.sha), stats: { additions: data.stats?.additions ?? 0, deletions: data.stats?.deletions ?? 0, total: data.stats?.total ?? 0, }, fileCount: files.length, diffFile, }; }), }); }