1import { Type } from "@sinclair/typebox";
2import type { AgentTool } from "@mariozechner/pi-ai";
3import simpleGit from "simple-git";
4import { formatSize, truncateHead } from "../../../util/truncate.js";
5
6const RefsSchema = Type.Object({
7 type: Type.Union([
8 Type.Literal("branches"),
9 Type.Literal("tags"),
10 Type.Literal("remotes"),
11 ]),
12});
13
14export const createGitRefsTool = (workspacePath: string): AgentTool => ({
15 name: "git_refs",
16 label: "Git Refs",
17 description: "List branches or tags.",
18 parameters: RefsSchema as any,
19 execute: async (_toolCallId: string, params: any) => {
20 const git = simpleGit(workspacePath);
21
22 let raw: string;
23 let baseDetails: Record<string, any> = {};
24
25 if (params.type === "tags") {
26 const tags = await git.tags();
27 raw = tags.all.join("\n");
28 baseDetails = { count: tags.all.length };
29 } else if (params.type === "remotes") {
30 raw = await git.raw(["branch", "-r"]);
31 } else {
32 raw = await git.raw(["branch", "-a"]);
33 }
34
35 const truncation = truncateHead(raw);
36 let text = truncation.content;
37 if (truncation.truncated) {
38 text += `\n\n[truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${formatSize(truncation.outputBytes)} of ${formatSize(truncation.totalBytes)})]`;
39 }
40
41 return {
42 content: [{ type: "text", text }],
43 details: { ...baseDetails, ...(truncation.truncated ? { truncation } : {}) },
44 };
45 },
46});