@compilr-dev/agents-coding 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +788 -0
  2. package/dist/index.d.ts +39 -0
  3. package/dist/index.js +75 -0
  4. package/dist/skills/index.d.ts +39 -0
  5. package/dist/skills/index.js +322 -0
  6. package/dist/tools/git/branch.d.ts +17 -0
  7. package/dist/tools/git/branch.js +264 -0
  8. package/dist/tools/git/commit.d.ts +23 -0
  9. package/dist/tools/git/commit.js +280 -0
  10. package/dist/tools/git/diff.d.ts +19 -0
  11. package/dist/tools/git/diff.js +221 -0
  12. package/dist/tools/git/index.d.ts +10 -0
  13. package/dist/tools/git/index.js +11 -0
  14. package/dist/tools/git/log.d.ts +19 -0
  15. package/dist/tools/git/log.js +235 -0
  16. package/dist/tools/git/stash.d.ts +17 -0
  17. package/dist/tools/git/stash.js +294 -0
  18. package/dist/tools/git/status.d.ts +19 -0
  19. package/dist/tools/git/status.js +160 -0
  20. package/dist/tools/git/types.d.ts +293 -0
  21. package/dist/tools/git/types.js +4 -0
  22. package/dist/tools/git/utils.d.ts +58 -0
  23. package/dist/tools/git/utils.js +197 -0
  24. package/dist/tools/index.d.ts +5 -0
  25. package/dist/tools/index.js +5 -0
  26. package/dist/tools/project/detect.d.ts +19 -0
  27. package/dist/tools/project/detect.js +341 -0
  28. package/dist/tools/project/find-root.d.ts +21 -0
  29. package/dist/tools/project/find-root.js +239 -0
  30. package/dist/tools/project/index.d.ts +6 -0
  31. package/dist/tools/project/index.js +5 -0
  32. package/dist/tools/project/types.d.ts +83 -0
  33. package/dist/tools/project/types.js +4 -0
  34. package/dist/tools/runners/build.d.ts +19 -0
  35. package/dist/tools/runners/build.js +306 -0
  36. package/dist/tools/runners/format.d.ts +19 -0
  37. package/dist/tools/runners/format.js +376 -0
  38. package/dist/tools/runners/index.d.ts +9 -0
  39. package/dist/tools/runners/index.js +9 -0
  40. package/dist/tools/runners/lint.d.ts +19 -0
  41. package/dist/tools/runners/lint.js +356 -0
  42. package/dist/tools/runners/test.d.ts +19 -0
  43. package/dist/tools/runners/test.js +386 -0
  44. package/dist/tools/runners/types.d.ts +97 -0
  45. package/dist/tools/runners/types.js +4 -0
  46. package/dist/tools/runners/utils.d.ts +69 -0
  47. package/dist/tools/runners/utils.js +179 -0
  48. package/dist/tools/search/definition.d.ts +19 -0
  49. package/dist/tools/search/definition.js +305 -0
  50. package/dist/tools/search/index.d.ts +8 -0
  51. package/dist/tools/search/index.js +8 -0
  52. package/dist/tools/search/references.d.ts +19 -0
  53. package/dist/tools/search/references.js +179 -0
  54. package/dist/tools/search/todos.d.ts +19 -0
  55. package/dist/tools/search/todos.js +269 -0
  56. package/dist/tools/search/types.d.ts +132 -0
  57. package/dist/tools/search/types.js +4 -0
  58. package/dist/tools/search/utils.d.ts +45 -0
  59. package/dist/tools/search/utils.js +152 -0
  60. package/package.json +88 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Git Branch Tool
3
+ * List, create, delete, switch, and rename branches
4
+ */
5
+ import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
6
+ import { runGitCommand, isGitRepository, isDirectory } from './utils.js';
7
+ /**
8
+ * Git branch tool
9
+ */
10
+ export const gitBranchTool = defineTool({
11
+ name: 'git_branch',
12
+ description: 'Manage git branches. Actions: list (show all branches), create (new branch), ' +
13
+ 'delete (remove branch), switch (checkout branch), rename (change branch name).',
14
+ inputSchema: {
15
+ type: 'object',
16
+ properties: {
17
+ path: {
18
+ type: 'string',
19
+ description: 'Working directory path (default: current directory)',
20
+ },
21
+ action: {
22
+ type: 'string',
23
+ enum: ['list', 'create', 'delete', 'switch', 'rename'],
24
+ description: 'Action to perform',
25
+ },
26
+ name: {
27
+ type: 'string',
28
+ description: 'Branch name (for create/delete/switch/rename)',
29
+ },
30
+ newName: {
31
+ type: 'string',
32
+ description: 'New branch name (for rename action)',
33
+ },
34
+ remotes: {
35
+ type: 'boolean',
36
+ description: 'Include remote branches in list',
37
+ },
38
+ force: {
39
+ type: 'boolean',
40
+ description: 'Force delete even if not merged',
41
+ },
42
+ startPoint: {
43
+ type: 'string',
44
+ description: 'Start point for new branch (commit/branch)',
45
+ },
46
+ },
47
+ required: ['action'],
48
+ },
49
+ execute: executeGitBranch,
50
+ });
51
+ /**
52
+ * Execute git branch
53
+ */
54
+ async function executeGitBranch(input) {
55
+ const targetPath = input.path ?? process.cwd();
56
+ // Check if path exists
57
+ if (!(await isDirectory(targetPath))) {
58
+ return createErrorResult(`Directory not found: ${targetPath}`);
59
+ }
60
+ // Check if it's a git repository
61
+ if (!(await isGitRepository(targetPath))) {
62
+ return createErrorResult(`Not a git repository: ${targetPath}`);
63
+ }
64
+ try {
65
+ switch (input.action) {
66
+ case 'list':
67
+ return await listBranches(targetPath, input.remotes ?? false);
68
+ case 'create':
69
+ if (!input.name) {
70
+ return createErrorResult('Branch name is required for create action');
71
+ }
72
+ return await createBranch(targetPath, input.name, input.startPoint);
73
+ case 'delete':
74
+ if (!input.name) {
75
+ return createErrorResult('Branch name is required for delete action');
76
+ }
77
+ return await deleteBranch(targetPath, input.name, input.force ?? false);
78
+ case 'switch':
79
+ if (!input.name) {
80
+ return createErrorResult('Branch name is required for switch action');
81
+ }
82
+ return await switchBranch(targetPath, input.name);
83
+ case 'rename':
84
+ if (!input.name || !input.newName) {
85
+ return createErrorResult('Both name and newName are required for rename action');
86
+ }
87
+ return await renameBranch(targetPath, input.name, input.newName);
88
+ default:
89
+ return createErrorResult(`Unknown action: ${String(input.action)}`);
90
+ }
91
+ }
92
+ catch (error) {
93
+ return createErrorResult(error instanceof Error ? error.message : String(error));
94
+ }
95
+ }
96
+ /**
97
+ * List branches
98
+ */
99
+ async function listBranches(repoPath, includeRemotes) {
100
+ // Get current branch
101
+ const currentResult = await runGitCommand(['rev-parse', '--abbrev-ref', 'HEAD'], {
102
+ cwd: repoPath,
103
+ });
104
+ const currentBranch = currentResult.success ? currentResult.stdout : '';
105
+ // List branches with format
106
+ const args = ['branch', '--format=%(refname:short)\t%(upstream:short)\t%(objectname:short)'];
107
+ if (includeRemotes) {
108
+ args.push('-a');
109
+ }
110
+ const result = await runGitCommand(args, { cwd: repoPath });
111
+ if (!result.success) {
112
+ return createErrorResult(`Failed to list branches: ${result.stderr}`);
113
+ }
114
+ const branches = [];
115
+ for (const line of result.stdout.split('\n').filter(Boolean)) {
116
+ const [name, tracking, lastCommit] = line.split('\t');
117
+ const isRemote = name.startsWith('remotes/') || name.includes('/');
118
+ branches.push({
119
+ name: isRemote ? name.replace(/^remotes\//, '') : name,
120
+ isRemote,
121
+ isCurrent: name === currentBranch,
122
+ tracking: tracking || undefined,
123
+ lastCommit: lastCommit || undefined,
124
+ });
125
+ }
126
+ const branchResult = {
127
+ current: currentBranch,
128
+ branches,
129
+ message: `Found ${String(branches.length)} branch(es)`,
130
+ };
131
+ return createSuccessResult(branchResult);
132
+ }
133
+ /**
134
+ * Create a new branch
135
+ */
136
+ async function createBranch(repoPath, name, startPoint) {
137
+ const args = ['branch', name];
138
+ if (startPoint) {
139
+ args.push(startPoint);
140
+ }
141
+ const result = await runGitCommand(args, { cwd: repoPath });
142
+ if (!result.success) {
143
+ return createErrorResult(`Failed to create branch: ${result.stderr}`);
144
+ }
145
+ const branchResult = {
146
+ message: `Created branch '${name}'${startPoint ? ` from '${startPoint}'` : ''}`,
147
+ };
148
+ return createSuccessResult(branchResult);
149
+ }
150
+ /**
151
+ * Delete a branch
152
+ */
153
+ async function deleteBranch(repoPath, name, force) {
154
+ // Check if trying to delete current branch
155
+ const currentResult = await runGitCommand(['rev-parse', '--abbrev-ref', 'HEAD'], {
156
+ cwd: repoPath,
157
+ });
158
+ if (currentResult.success && currentResult.stdout === name) {
159
+ return createErrorResult(`Cannot delete the currently checked out branch '${name}'`);
160
+ }
161
+ const args = ['branch', force ? '-D' : '-d', name];
162
+ const result = await runGitCommand(args, { cwd: repoPath });
163
+ if (!result.success) {
164
+ if (result.stderr.includes('not fully merged')) {
165
+ return createErrorResult(`Branch '${name}' is not fully merged. Use force=true to delete anyway.`);
166
+ }
167
+ return createErrorResult(`Failed to delete branch: ${result.stderr}`);
168
+ }
169
+ const branchResult = {
170
+ message: `Deleted branch '${name}'`,
171
+ };
172
+ return createSuccessResult(branchResult);
173
+ }
174
+ /**
175
+ * Switch to a branch
176
+ */
177
+ async function switchBranch(repoPath, name) {
178
+ // First try 'git switch' (Git 2.23+), fall back to 'git checkout'
179
+ let result = await runGitCommand(['switch', name], { cwd: repoPath });
180
+ if (!result.success && result.stderr.includes('not a git command')) {
181
+ // Fall back to checkout for older Git versions
182
+ result = await runGitCommand(['checkout', name], { cwd: repoPath });
183
+ }
184
+ if (!result.success) {
185
+ // Check if branch exists
186
+ const checkResult = await runGitCommand(['rev-parse', '--verify', name], { cwd: repoPath });
187
+ if (!checkResult.success) {
188
+ return createErrorResult(`Branch '${name}' does not exist`);
189
+ }
190
+ return createErrorResult(`Failed to switch branch: ${result.stderr}`);
191
+ }
192
+ const branchResult = {
193
+ current: name,
194
+ message: `Switched to branch '${name}'`,
195
+ };
196
+ return createSuccessResult(branchResult);
197
+ }
198
+ /**
199
+ * Rename a branch
200
+ */
201
+ async function renameBranch(repoPath, oldName, newName) {
202
+ const args = ['branch', '-m', oldName, newName];
203
+ const result = await runGitCommand(args, { cwd: repoPath });
204
+ if (!result.success) {
205
+ return createErrorResult(`Failed to rename branch: ${result.stderr}`);
206
+ }
207
+ const branchResult = {
208
+ message: `Renamed branch '${oldName}' to '${newName}'`,
209
+ };
210
+ return createSuccessResult(branchResult);
211
+ }
212
+ /**
213
+ * Factory function to create git branch tool with custom options
214
+ */
215
+ export function createGitBranchTool(options) {
216
+ return defineTool({
217
+ name: 'git_branch',
218
+ description: 'Manage git branches. Actions: list, create, delete, switch, rename.',
219
+ inputSchema: {
220
+ type: 'object',
221
+ properties: {
222
+ path: {
223
+ type: 'string',
224
+ description: 'Working directory path (default: current directory)',
225
+ },
226
+ action: {
227
+ type: 'string',
228
+ enum: ['list', 'create', 'delete', 'switch', 'rename'],
229
+ description: 'Action to perform',
230
+ },
231
+ name: {
232
+ type: 'string',
233
+ description: 'Branch name',
234
+ },
235
+ newName: {
236
+ type: 'string',
237
+ description: 'New branch name (for rename)',
238
+ },
239
+ remotes: {
240
+ type: 'boolean',
241
+ description: 'Include remote branches in list',
242
+ },
243
+ force: {
244
+ type: 'boolean',
245
+ description: 'Force delete even if not merged',
246
+ },
247
+ startPoint: {
248
+ type: 'string',
249
+ description: 'Start point for new branch',
250
+ },
251
+ },
252
+ required: ['action'],
253
+ },
254
+ execute: async (input) => {
255
+ let targetPath = input.path ?? '.';
256
+ // Resolve relative paths
257
+ if (options?.baseDir && !targetPath.startsWith('/')) {
258
+ const nodePath = await import('node:path');
259
+ targetPath = nodePath.join(options.baseDir, targetPath);
260
+ }
261
+ return executeGitBranch({ ...input, path: targetPath });
262
+ },
263
+ });
264
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Git Commit Tool
3
+ * Creates commits with safety features to prevent accidental commits of secrets
4
+ */
5
+ import type { Tool } from '@compilr-dev/agents';
6
+ import type { GitCommitInput } from './types.js';
7
+ /**
8
+ * Git commit tool
9
+ */
10
+ export declare const gitCommitTool: Tool<GitCommitInput>;
11
+ /**
12
+ * Factory function to create git commit tool with custom options
13
+ */
14
+ export declare function createGitCommitTool(options?: {
15
+ /** Base directory for relative paths */
16
+ baseDir?: string;
17
+ /** Additional secret patterns to check */
18
+ additionalSecretPatterns?: RegExp[];
19
+ /** Disable secret checking */
20
+ disableSecretCheck?: boolean;
21
+ /** Custom large file threshold in bytes */
22
+ largeFileThreshold?: number;
23
+ }): Tool<GitCommitInput>;
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Git Commit Tool
3
+ * Creates commits with safety features to prevent accidental commits of secrets
4
+ */
5
+ import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
6
+ import { runGitCommand, isGitRepository, isDirectory } from './utils.js';
7
+ /**
8
+ * Patterns that indicate potential secrets
9
+ */
10
+ const SECRET_PATTERNS = [
11
+ // Environment files
12
+ /^\.env$/,
13
+ /^\.env\..+$/,
14
+ /\.env\.local$/,
15
+ // Credential files
16
+ /credentials\.json$/,
17
+ /\.credentials$/,
18
+ /secrets\.json$/,
19
+ /secrets\.ya?ml$/,
20
+ // Key files
21
+ /\.pem$/,
22
+ /\.key$/,
23
+ /id_rsa$/,
24
+ /id_ed25519$/,
25
+ /\.p12$/,
26
+ /\.pfx$/,
27
+ // Cloud provider files
28
+ /\.aws\/credentials$/,
29
+ /gcloud.*\.json$/,
30
+ /service[-_]?account.*\.json$/,
31
+ // Token files
32
+ /\.npmrc$/,
33
+ /\.pypirc$/,
34
+ /\.netrc$/,
35
+ ];
36
+ /**
37
+ * Large file threshold (1MB)
38
+ */
39
+ const LARGE_FILE_THRESHOLD = 1024 * 1024;
40
+ /**
41
+ * Git commit tool
42
+ */
43
+ export const gitCommitTool = defineTool({
44
+ name: 'git_commit',
45
+ description: 'Create a git commit. Includes safety checks for secrets and large files. ' +
46
+ 'Can optionally stage files before committing. ' +
47
+ 'Use with caution: amend and noVerify options can be dangerous.',
48
+ inputSchema: {
49
+ type: 'object',
50
+ properties: {
51
+ path: {
52
+ type: 'string',
53
+ description: 'Working directory path (default: current directory)',
54
+ },
55
+ message: {
56
+ type: 'string',
57
+ description: 'Commit message (required)',
58
+ },
59
+ files: {
60
+ type: 'array',
61
+ items: { type: 'string' },
62
+ description: 'Specific files to stage before commit',
63
+ },
64
+ addModified: {
65
+ type: 'boolean',
66
+ description: 'Stage all modified/deleted tracked files (git add -u)',
67
+ },
68
+ addAll: {
69
+ type: 'boolean',
70
+ description: 'Stage all files including untracked (git add -A)',
71
+ },
72
+ allowEmpty: {
73
+ type: 'boolean',
74
+ description: 'Allow creating an empty commit',
75
+ },
76
+ amend: {
77
+ type: 'boolean',
78
+ description: 'Amend the previous commit (dangerous!)',
79
+ },
80
+ noVerify: {
81
+ type: 'boolean',
82
+ description: 'Skip pre-commit hooks (dangerous!)',
83
+ },
84
+ },
85
+ required: ['message'],
86
+ },
87
+ execute: executeGitCommit,
88
+ });
89
+ /**
90
+ * Execute git commit
91
+ */
92
+ async function executeGitCommit(input) {
93
+ const targetPath = input.path ?? process.cwd();
94
+ // Validate message
95
+ if (!input.message || input.message.trim().length === 0) {
96
+ return createErrorResult('Commit message is required');
97
+ }
98
+ // Check if path exists
99
+ if (!(await isDirectory(targetPath))) {
100
+ return createErrorResult(`Directory not found: ${targetPath}`);
101
+ }
102
+ // Check if it's a git repository
103
+ if (!(await isGitRepository(targetPath))) {
104
+ return createErrorResult(`Not a git repository: ${targetPath}`);
105
+ }
106
+ try {
107
+ // Stage files if requested
108
+ if (input.files && input.files.length > 0) {
109
+ const addResult = await runGitCommand(['add', '--', ...input.files], { cwd: targetPath });
110
+ if (!addResult.success) {
111
+ return createErrorResult(`Failed to stage files: ${addResult.stderr}`);
112
+ }
113
+ }
114
+ else if (input.addAll) {
115
+ const addResult = await runGitCommand(['add', '-A'], { cwd: targetPath });
116
+ if (!addResult.success) {
117
+ return createErrorResult(`Failed to stage files: ${addResult.stderr}`);
118
+ }
119
+ }
120
+ else if (input.addModified) {
121
+ const addResult = await runGitCommand(['add', '-u'], { cwd: targetPath });
122
+ if (!addResult.success) {
123
+ return createErrorResult(`Failed to stage files: ${addResult.stderr}`);
124
+ }
125
+ }
126
+ // Check what's staged
127
+ const stagedResult = await runGitCommand(['diff', '--cached', '--name-only'], {
128
+ cwd: targetPath,
129
+ });
130
+ const stagedFiles = stagedResult.stdout.split('\n').filter(Boolean);
131
+ // Safety checks
132
+ const warnings = await checkStagedFiles(targetPath, stagedFiles);
133
+ if (warnings.length > 0) {
134
+ const secretWarnings = warnings.filter((w) => w.type === 'secrets');
135
+ if (secretWarnings.length > 0) {
136
+ return createErrorResult(`Refusing to commit potential secrets:\n${secretWarnings.map((w) => ` - ${w.file}: ${w.message}`).join('\n')}\n\nUnstage these files or add them to .gitignore.`);
137
+ }
138
+ // Log other warnings but don't block
139
+ const otherWarnings = warnings.filter((w) => w.type !== 'secrets');
140
+ if (otherWarnings.length > 0) {
141
+ // These are warnings, not errors - we'll include them in success result
142
+ }
143
+ }
144
+ // Check if there's anything to commit
145
+ if (stagedFiles.length === 0 && !input.allowEmpty) {
146
+ return createErrorResult('Nothing to commit. Stage files first or use addAll/addModified options.');
147
+ }
148
+ // Build commit command
149
+ const commitArgs = ['commit', '-m', input.message];
150
+ if (input.allowEmpty) {
151
+ commitArgs.push('--allow-empty');
152
+ }
153
+ if (input.amend) {
154
+ commitArgs.push('--amend');
155
+ }
156
+ if (input.noVerify) {
157
+ commitArgs.push('--no-verify');
158
+ }
159
+ // Execute commit
160
+ const commitResult = await runGitCommand(commitArgs, { cwd: targetPath });
161
+ if (!commitResult.success) {
162
+ return createErrorResult(`Commit failed: ${commitResult.stderr}`);
163
+ }
164
+ // Get commit info
165
+ const hashResult = await runGitCommand(['rev-parse', 'HEAD'], { cwd: targetPath });
166
+ const shortHashResult = await runGitCommand(['rev-parse', '--short', 'HEAD'], {
167
+ cwd: targetPath,
168
+ });
169
+ const branchResult = await runGitCommand(['rev-parse', '--abbrev-ref', 'HEAD'], {
170
+ cwd: targetPath,
171
+ });
172
+ // Parse stats from commit output
173
+ const statsMatch = commitResult.stdout.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
174
+ const filesCommitted = statsMatch ? parseInt(statsMatch[1], 10) : stagedFiles.length;
175
+ const insertions = statsMatch && statsMatch[2] ? parseInt(statsMatch[2], 10) : 0;
176
+ const deletions = statsMatch && statsMatch[3] ? parseInt(statsMatch[3], 10) : 0;
177
+ const result = {
178
+ hash: hashResult.stdout,
179
+ shortHash: shortHashResult.stdout,
180
+ branch: branchResult.stdout,
181
+ filesCommitted,
182
+ insertions,
183
+ deletions,
184
+ message: input.message,
185
+ };
186
+ return createSuccessResult(result);
187
+ }
188
+ catch (error) {
189
+ return createErrorResult(error instanceof Error ? error.message : String(error));
190
+ }
191
+ }
192
+ /**
193
+ * Check staged files for potential issues
194
+ */
195
+ async function checkStagedFiles(repoPath, files) {
196
+ const warnings = [];
197
+ for (const file of files) {
198
+ // Check for secret patterns
199
+ for (const pattern of SECRET_PATTERNS) {
200
+ if (pattern.test(file)) {
201
+ warnings.push({
202
+ type: 'secrets',
203
+ file,
204
+ message: `File matches secret pattern: ${pattern.toString()}`,
205
+ });
206
+ break;
207
+ }
208
+ }
209
+ // Check file size (only for files, not deletions)
210
+ const sizeResult = await runGitCommand(['cat-file', '-s', `:${file}`], { cwd: repoPath });
211
+ if (sizeResult.success) {
212
+ const size = parseInt(sizeResult.stdout, 10);
213
+ if (size > LARGE_FILE_THRESHOLD) {
214
+ warnings.push({
215
+ type: 'large_file',
216
+ file,
217
+ message: `File is ${String(Math.round(size / 1024))}KB (threshold: ${String(Math.round(LARGE_FILE_THRESHOLD / 1024))}KB)`,
218
+ });
219
+ }
220
+ }
221
+ }
222
+ return warnings;
223
+ }
224
+ /**
225
+ * Factory function to create git commit tool with custom options
226
+ */
227
+ export function createGitCommitTool(options) {
228
+ return defineTool({
229
+ name: 'git_commit',
230
+ description: 'Create a git commit. Includes safety checks for secrets and large files.',
231
+ inputSchema: {
232
+ type: 'object',
233
+ properties: {
234
+ path: {
235
+ type: 'string',
236
+ description: 'Working directory path (default: current directory)',
237
+ },
238
+ message: {
239
+ type: 'string',
240
+ description: 'Commit message (required)',
241
+ },
242
+ files: {
243
+ type: 'array',
244
+ items: { type: 'string' },
245
+ description: 'Specific files to stage before commit',
246
+ },
247
+ addModified: {
248
+ type: 'boolean',
249
+ description: 'Stage all modified/deleted tracked files',
250
+ },
251
+ addAll: {
252
+ type: 'boolean',
253
+ description: 'Stage all files including untracked',
254
+ },
255
+ allowEmpty: {
256
+ type: 'boolean',
257
+ description: 'Allow creating an empty commit',
258
+ },
259
+ amend: {
260
+ type: 'boolean',
261
+ description: 'Amend the previous commit',
262
+ },
263
+ noVerify: {
264
+ type: 'boolean',
265
+ description: 'Skip pre-commit hooks',
266
+ },
267
+ },
268
+ required: ['message'],
269
+ },
270
+ execute: async (input) => {
271
+ let targetPath = input.path ?? '.';
272
+ // Resolve relative paths
273
+ if (options?.baseDir && !targetPath.startsWith('/')) {
274
+ const nodePath = await import('node:path');
275
+ targetPath = nodePath.join(options.baseDir, targetPath);
276
+ }
277
+ return executeGitCommit({ ...input, path: targetPath });
278
+ },
279
+ });
280
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Git Diff Tool
3
+ * Shows changes between commits, working tree, etc.
4
+ */
5
+ import type { Tool } from '@compilr-dev/agents';
6
+ import type { GitDiffInput } from './types.js';
7
+ /**
8
+ * Git diff tool
9
+ */
10
+ export declare const gitDiffTool: Tool<GitDiffInput>;
11
+ /**
12
+ * Factory function to create git diff tool with custom options
13
+ */
14
+ export declare function createGitDiffTool(options?: {
15
+ /** Base directory for relative paths */
16
+ baseDir?: string;
17
+ /** Default context lines */
18
+ defaultContext?: number;
19
+ }): Tool<GitDiffInput>;