Project Files
src / tools / gitTools.ts
/**
* @file gitTools.ts
* Git operations: status, diff, commit, log.
*/
import { tool, type Tool } from "@lmstudio/sdk";
import { z } from "zod";
import { validatePath, type ToolContext } from "./shared";
export function createGitTools(ctx: ToolContext): Tool[] {
const gitStatusTool = tool({
name: "git_status",
description: "Get the current git status of the repository.",
parameters: {},
implementation: async () => {
const { simpleGit } = await import("simple-git");
const git = simpleGit(ctx.cwd);
try {
return await git.status();
} catch (e) {
return { error: `Git status failed: ${e instanceof Error ? e.message : String(e)}` };
}
},
});
const gitDiffTool = tool({
name: "git_diff",
description: "Get the git diff of the current repository or specific files.",
parameters: {
file_path: z.string().optional().describe("Optional: Path to specific file to diff."),
cached: z.boolean().optional().describe("Optional: Show staged changes only (git diff --cached)."),
},
implementation: async ({ file_path, cached }) => {
const { simpleGit } = await import("simple-git");
const git = simpleGit(ctx.cwd);
try {
const args: string[] = [];
if (cached) args.push("--cached");
if (file_path) args.push(validatePath(ctx.cwd, file_path));
const MAX_DIFF_CHARS = 8000;
const rawDiff = await git.diff(args);
if (!rawDiff) return { diff: "No changes." };
const truncated = rawDiff.length > MAX_DIFF_CHARS;
return {
diff: rawDiff.substring(0, MAX_DIFF_CHARS) + (truncated ? `\n... (truncated, showing ${MAX_DIFF_CHARS} of ${rawDiff.length} chars)` : ""),
...(truncated ? { warning: "Diff was truncated. Use file_path to diff a specific file." } : {}),
};
} catch (e) {
return { error: `Git diff failed: ${e instanceof Error ? e.message : String(e)}` };
}
},
});
const gitCommitTool = tool({
name: "git_commit",
description: "Commit staged changes to the git repository.",
parameters: { message: z.string() },
implementation: async ({ message }) => {
const { simpleGit } = await import("simple-git");
const git = simpleGit(ctx.cwd);
try {
const result = await git.commit(message);
return { success: true, summary: result.summary };
} catch (e) {
return { error: `Git commit failed: ${e instanceof Error ? e.message : String(e)}` };
}
},
});
const gitLogTool = tool({
name: "git_log",
description: "Get recent git commit history.",
parameters: {
max_count: z.number().optional().describe("Max number of commits to return (default: 10)"),
},
implementation: async ({ max_count = 10 }) => {
const { simpleGit } = await import("simple-git");
const git = simpleGit(ctx.cwd);
try {
const log = await git.log({ maxCount: max_count });
return { history: log.all };
} catch (e) {
return { error: `Git log failed: ${e instanceof Error ? e.message : String(e)}` };
}
},
});
return [gitStatusTool, gitDiffTool, gitCommitTool, gitLogTool];
}