refs.ts

 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});