"use strict";
/**
* @file gitTools.ts
* Git operations: status, diff, commit, log.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createGitTools = createGitTools;
const sdk_1 = require("@lmstudio/sdk");
const zod_1 = require("zod");
const shared_1 = require("./shared");
const errorCodes_1 = require("./errorCodes");
const spillToDisk_1 = require("./spillToDisk");
function createGitTools(ctx, limits) {
const safePath = (p) => (0, shared_1.validatePath)(ctx.cwd, p, ctx.workspaceRoot);
const gitStatusTool = (0, sdk_1.tool)({
name: "git_status",
description: "Get the current git status of the repository.",
parameters: {},
implementation: async () => {
const { simpleGit } = await Promise.resolve().then(() => __importStar(require("simple-git")));
const git = simpleGit(ctx.cwd);
try {
return await git.status();
}
catch (e) {
return (0, errorCodes_1.toolError)(errorCodes_1.GIT_FAILED, `Git status failed: ${e instanceof Error ? e.message : String(e)}`);
}
},
});
const gitDiffTool = (0, sdk_1.tool)({
name: "git_diff",
description: "Get the git diff of the current repository or specific files.",
parameters: {
file_path: zod_1.z.string().optional().describe("Optional: Path to specific file to diff."),
cached: zod_1.z.boolean().optional().describe("Optional: Show staged changes only (git diff --cached)."),
},
implementation: async ({ file_path, cached }) => {
const { simpleGit } = await Promise.resolve().then(() => __importStar(require("simple-git")));
const git = simpleGit(ctx.cwd);
try {
const args = [];
if (cached)
args.push("--cached");
if (file_path)
args.push(safePath(file_path));
const MAX_DIFF_CHARS = limits?.maxDiff ?? 8_000;
const rawDiff = await git.diff(args);
if (!rawDiff)
return { diff: "No changes." };
const spill = await (0, spillToDisk_1.spillIfNeeded)(rawDiff, MAX_DIFF_CHARS, "git-diff");
return {
diff: spill.preview,
...(spill.spilled ? { diff_full: spill.spillPath, warning: "Diff was truncated. Use file_path to diff a specific file, or read_file on diff_full for the complete diff." } : {}),
};
}
catch (e) {
return (0, errorCodes_1.toolError)(errorCodes_1.GIT_FAILED, `Git diff failed: ${e instanceof Error ? e.message : String(e)}`);
}
},
});
const gitAddTool = (0, sdk_1.tool)({
name: "git_add",
description: "Stage files for the next git commit. Use '.' to stage all changes.",
parameters: {
files: zod_1.z.array(zod_1.z.string()).describe("File paths to stage (e.g. ['src/index.ts', 'README.md']). Use ['.'] to stage all."),
},
implementation: async ({ files }) => {
const { simpleGit } = await Promise.resolve().then(() => __importStar(require("simple-git")));
const git = simpleGit(ctx.cwd);
try {
// Validate paths (except for '.' which means stage all)
const resolvedFiles = files.map(f => f === "." ? f : safePath(f));
await git.add(resolvedFiles);
const status = await git.status();
return {
success: true,
staged: status.staged,
message: `Staged ${status.staged.length} file(s).`,
};
}
catch (e) {
return (0, errorCodes_1.toolError)(errorCodes_1.GIT_FAILED, `Git add failed: ${e instanceof Error ? e.message : String(e)}`);
}
},
});
const gitCommitTool = (0, sdk_1.tool)({
name: "git_commit",
description: "Commit staged changes to the git repository.",
parameters: { message: zod_1.z.string() },
implementation: async ({ message }) => {
const { simpleGit } = await Promise.resolve().then(() => __importStar(require("simple-git")));
const git = simpleGit(ctx.cwd);
try {
const result = await git.commit(message);
return { success: true, summary: result.summary };
}
catch (e) {
return (0, errorCodes_1.toolError)(errorCodes_1.GIT_FAILED, `Git commit failed: ${e instanceof Error ? e.message : String(e)}`);
}
},
});
const gitLogTool = (0, sdk_1.tool)({
name: "git_log",
description: "Get recent git commit history.",
parameters: {
max_count: zod_1.z.number().optional().describe("Max number of commits to return (default: 10)"),
},
implementation: async ({ max_count = 10 }) => {
const { simpleGit } = await Promise.resolve().then(() => __importStar(require("simple-git")));
const git = simpleGit(ctx.cwd);
try {
const log = await git.log({ maxCount: max_count });
return { history: log.all };
}
catch (e) {
return (0, errorCodes_1.toolError)(errorCodes_1.GIT_FAILED, `Git log failed: ${e instanceof Error ? e.message : String(e)}`);
}
},
});
return [gitStatusTool, gitDiffTool, gitAddTool, gitCommitTool, gitLogTool];
}
//# sourceMappingURL=gitTools.js.map