@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.
- package/README.md +788 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +75 -0
- package/dist/skills/index.d.ts +39 -0
- package/dist/skills/index.js +322 -0
- package/dist/tools/git/branch.d.ts +17 -0
- package/dist/tools/git/branch.js +264 -0
- package/dist/tools/git/commit.d.ts +23 -0
- package/dist/tools/git/commit.js +280 -0
- package/dist/tools/git/diff.d.ts +19 -0
- package/dist/tools/git/diff.js +221 -0
- package/dist/tools/git/index.d.ts +10 -0
- package/dist/tools/git/index.js +11 -0
- package/dist/tools/git/log.d.ts +19 -0
- package/dist/tools/git/log.js +235 -0
- package/dist/tools/git/stash.d.ts +17 -0
- package/dist/tools/git/stash.js +294 -0
- package/dist/tools/git/status.d.ts +19 -0
- package/dist/tools/git/status.js +160 -0
- package/dist/tools/git/types.d.ts +293 -0
- package/dist/tools/git/types.js +4 -0
- package/dist/tools/git/utils.d.ts +58 -0
- package/dist/tools/git/utils.js +197 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/project/detect.d.ts +19 -0
- package/dist/tools/project/detect.js +341 -0
- package/dist/tools/project/find-root.d.ts +21 -0
- package/dist/tools/project/find-root.js +239 -0
- package/dist/tools/project/index.d.ts +6 -0
- package/dist/tools/project/index.js +5 -0
- package/dist/tools/project/types.d.ts +83 -0
- package/dist/tools/project/types.js +4 -0
- package/dist/tools/runners/build.d.ts +19 -0
- package/dist/tools/runners/build.js +306 -0
- package/dist/tools/runners/format.d.ts +19 -0
- package/dist/tools/runners/format.js +376 -0
- package/dist/tools/runners/index.d.ts +9 -0
- package/dist/tools/runners/index.js +9 -0
- package/dist/tools/runners/lint.d.ts +19 -0
- package/dist/tools/runners/lint.js +356 -0
- package/dist/tools/runners/test.d.ts +19 -0
- package/dist/tools/runners/test.js +386 -0
- package/dist/tools/runners/types.d.ts +97 -0
- package/dist/tools/runners/types.js +4 -0
- package/dist/tools/runners/utils.d.ts +69 -0
- package/dist/tools/runners/utils.js +179 -0
- package/dist/tools/search/definition.d.ts +19 -0
- package/dist/tools/search/definition.js +305 -0
- package/dist/tools/search/index.d.ts +8 -0
- package/dist/tools/search/index.js +8 -0
- package/dist/tools/search/references.d.ts +19 -0
- package/dist/tools/search/references.js +179 -0
- package/dist/tools/search/todos.d.ts +19 -0
- package/dist/tools/search/todos.js +269 -0
- package/dist/tools/search/types.d.ts +132 -0
- package/dist/tools/search/types.js +4 -0
- package/dist/tools/search/utils.d.ts +45 -0
- package/dist/tools/search/utils.js +152 -0
- package/package.json +88 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Diff Tool
|
|
3
|
+
* Shows changes between commits, working tree, etc.
|
|
4
|
+
*/
|
|
5
|
+
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
6
|
+
import { runGitCommand, isGitRepository, isDirectory } from './utils.js';
|
|
7
|
+
/**
|
|
8
|
+
* Git diff tool
|
|
9
|
+
*/
|
|
10
|
+
export const gitDiffTool = defineTool({
|
|
11
|
+
name: 'git_diff',
|
|
12
|
+
description: 'Show changes between commits, commit and working tree, etc. ' +
|
|
13
|
+
'By default shows unstaged changes. Use staged=true for staged changes. ' +
|
|
14
|
+
'Can compare specific files or refs.',
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
path: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Working directory path (default: current directory)',
|
|
21
|
+
},
|
|
22
|
+
staged: {
|
|
23
|
+
type: 'boolean',
|
|
24
|
+
description: 'Show staged changes instead of unstaged (default: false)',
|
|
25
|
+
},
|
|
26
|
+
file: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Specific file to diff',
|
|
29
|
+
},
|
|
30
|
+
ref: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'Compare working tree with this commit/branch',
|
|
33
|
+
},
|
|
34
|
+
refA: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: 'First ref for comparison (use with refB)',
|
|
37
|
+
},
|
|
38
|
+
refB: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'Second ref for comparison (use with refA)',
|
|
41
|
+
},
|
|
42
|
+
context: {
|
|
43
|
+
type: 'number',
|
|
44
|
+
description: 'Number of context lines (default: 3)',
|
|
45
|
+
},
|
|
46
|
+
statOnly: {
|
|
47
|
+
type: 'boolean',
|
|
48
|
+
description: 'Show only statistics, no diff content (default: false)',
|
|
49
|
+
},
|
|
50
|
+
nameOnly: {
|
|
51
|
+
type: 'boolean',
|
|
52
|
+
description: 'Show only names of changed files (default: false)',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
required: [],
|
|
56
|
+
},
|
|
57
|
+
execute: executeGitDiff,
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Execute git diff
|
|
61
|
+
*/
|
|
62
|
+
async function executeGitDiff(input) {
|
|
63
|
+
const targetPath = input.path ?? process.cwd();
|
|
64
|
+
// Check if path exists
|
|
65
|
+
if (!(await isDirectory(targetPath))) {
|
|
66
|
+
return createErrorResult(`Directory not found: ${targetPath}`);
|
|
67
|
+
}
|
|
68
|
+
// Check if it's a git repository
|
|
69
|
+
if (!(await isGitRepository(targetPath))) {
|
|
70
|
+
return createErrorResult(`Not a git repository: ${targetPath}`);
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
// Build git diff command
|
|
74
|
+
const args = ['diff'];
|
|
75
|
+
// Context lines
|
|
76
|
+
if (input.context !== undefined) {
|
|
77
|
+
args.push(`-U${String(input.context)}`);
|
|
78
|
+
}
|
|
79
|
+
// Staged changes
|
|
80
|
+
if (input.staged) {
|
|
81
|
+
args.push('--cached');
|
|
82
|
+
}
|
|
83
|
+
// Ref comparison
|
|
84
|
+
if (input.refA && input.refB) {
|
|
85
|
+
args.push(input.refA, input.refB);
|
|
86
|
+
}
|
|
87
|
+
else if (input.ref) {
|
|
88
|
+
args.push(input.ref);
|
|
89
|
+
}
|
|
90
|
+
// Stat only or name only
|
|
91
|
+
if (input.statOnly) {
|
|
92
|
+
args.push('--stat');
|
|
93
|
+
}
|
|
94
|
+
else if (input.nameOnly) {
|
|
95
|
+
args.push('--name-only');
|
|
96
|
+
}
|
|
97
|
+
// Specific file
|
|
98
|
+
if (input.file) {
|
|
99
|
+
args.push('--', input.file);
|
|
100
|
+
}
|
|
101
|
+
// Run the diff
|
|
102
|
+
const result = await runGitCommand(args, { cwd: targetPath });
|
|
103
|
+
if (!result.success && result.exitCode !== 0 && result.stdout === '') {
|
|
104
|
+
// git diff returns exit code 1 if there are changes, 0 if no changes
|
|
105
|
+
// But if stderr has content, it's an error
|
|
106
|
+
if (result.stderr) {
|
|
107
|
+
return createErrorResult(`git diff failed: ${result.stderr}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Get stats separately for structured output
|
|
111
|
+
const statsArgs = ['diff', '--numstat'];
|
|
112
|
+
if (input.staged)
|
|
113
|
+
statsArgs.push('--cached');
|
|
114
|
+
if (input.refA && input.refB) {
|
|
115
|
+
statsArgs.push(input.refA, input.refB);
|
|
116
|
+
}
|
|
117
|
+
else if (input.ref) {
|
|
118
|
+
statsArgs.push(input.ref);
|
|
119
|
+
}
|
|
120
|
+
if (input.file)
|
|
121
|
+
statsArgs.push('--', input.file);
|
|
122
|
+
const statsResult = await runGitCommand(statsArgs, { cwd: targetPath });
|
|
123
|
+
// Parse stats
|
|
124
|
+
const files = [];
|
|
125
|
+
let totalInsertions = 0;
|
|
126
|
+
let totalDeletions = 0;
|
|
127
|
+
if (statsResult.success && statsResult.stdout) {
|
|
128
|
+
const lines = statsResult.stdout.split('\n').filter(Boolean);
|
|
129
|
+
for (const line of lines) {
|
|
130
|
+
// Format: <additions>\t<deletions>\t<path>
|
|
131
|
+
const match = line.match(/^(\d+|-)\t(\d+|-)\t(.+)$/);
|
|
132
|
+
if (match) {
|
|
133
|
+
const additions = match[1] === '-' ? 0 : parseInt(match[1], 10);
|
|
134
|
+
const deletions = match[2] === '-' ? 0 : parseInt(match[2], 10);
|
|
135
|
+
const path = match[3];
|
|
136
|
+
files.push({ path, additions, deletions });
|
|
137
|
+
totalInsertions += additions;
|
|
138
|
+
totalDeletions += deletions;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const diffResult = {
|
|
143
|
+
diff: input.statOnly || input.nameOnly ? '' : result.stdout,
|
|
144
|
+
files,
|
|
145
|
+
stats: {
|
|
146
|
+
filesChanged: files.length,
|
|
147
|
+
insertions: totalInsertions,
|
|
148
|
+
deletions: totalDeletions,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
return createSuccessResult(diffResult);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
return createErrorResult(error instanceof Error ? error.message : String(error));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Factory function to create git diff tool with custom options
|
|
159
|
+
*/
|
|
160
|
+
export function createGitDiffTool(options) {
|
|
161
|
+
return defineTool({
|
|
162
|
+
name: 'git_diff',
|
|
163
|
+
description: 'Show changes between commits, commit and working tree, etc. ' +
|
|
164
|
+
'By default shows unstaged changes. Use staged=true for staged changes.',
|
|
165
|
+
inputSchema: {
|
|
166
|
+
type: 'object',
|
|
167
|
+
properties: {
|
|
168
|
+
path: {
|
|
169
|
+
type: 'string',
|
|
170
|
+
description: 'Working directory path (default: current directory)',
|
|
171
|
+
},
|
|
172
|
+
staged: {
|
|
173
|
+
type: 'boolean',
|
|
174
|
+
description: 'Show staged changes instead of unstaged (default: false)',
|
|
175
|
+
},
|
|
176
|
+
file: {
|
|
177
|
+
type: 'string',
|
|
178
|
+
description: 'Specific file to diff',
|
|
179
|
+
},
|
|
180
|
+
ref: {
|
|
181
|
+
type: 'string',
|
|
182
|
+
description: 'Compare working tree with this commit/branch',
|
|
183
|
+
},
|
|
184
|
+
refA: {
|
|
185
|
+
type: 'string',
|
|
186
|
+
description: 'First ref for comparison (use with refB)',
|
|
187
|
+
},
|
|
188
|
+
refB: {
|
|
189
|
+
type: 'string',
|
|
190
|
+
description: 'Second ref for comparison (use with refA)',
|
|
191
|
+
},
|
|
192
|
+
context: {
|
|
193
|
+
type: 'number',
|
|
194
|
+
description: `Number of context lines (default: ${String(options?.defaultContext ?? 3)})`,
|
|
195
|
+
},
|
|
196
|
+
statOnly: {
|
|
197
|
+
type: 'boolean',
|
|
198
|
+
description: 'Show only statistics, no diff content (default: false)',
|
|
199
|
+
},
|
|
200
|
+
nameOnly: {
|
|
201
|
+
type: 'boolean',
|
|
202
|
+
description: 'Show only names of changed files (default: false)',
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
required: [],
|
|
206
|
+
},
|
|
207
|
+
execute: async (input) => {
|
|
208
|
+
let targetPath = input.path ?? '.';
|
|
209
|
+
// Resolve relative paths
|
|
210
|
+
if (options?.baseDir && !targetPath.startsWith('/')) {
|
|
211
|
+
const nodePath = await import('node:path');
|
|
212
|
+
targetPath = nodePath.join(options.baseDir, targetPath);
|
|
213
|
+
}
|
|
214
|
+
return executeGitDiff({
|
|
215
|
+
...input,
|
|
216
|
+
path: targetPath,
|
|
217
|
+
context: input.context ?? options?.defaultContext,
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git tools
|
|
3
|
+
*/
|
|
4
|
+
export { gitStatusTool, createGitStatusTool } from './status.js';
|
|
5
|
+
export { gitDiffTool, createGitDiffTool } from './diff.js';
|
|
6
|
+
export { gitLogTool, createGitLogTool } from './log.js';
|
|
7
|
+
export { gitCommitTool, createGitCommitTool } from './commit.js';
|
|
8
|
+
export { gitBranchTool, createGitBranchTool } from './branch.js';
|
|
9
|
+
export { gitStashTool, createGitStashTool } from './stash.js';
|
|
10
|
+
export type { GitStatusInput, GitStatusResult, GitFileStatus, GitFileStatusType, GitDiffInput, GitDiffResult, DiffFileStats, GitLogInput, GitLogResult, GitCommit, GitCommitInput, GitCommitResult, CommitSafetyWarning, GitBranchAction, GitBranchInput, GitBranchInfo, GitBranchResult, GitStashAction, GitStashInput, GitStashEntry, GitStashResult, } from './types.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git tools
|
|
3
|
+
*/
|
|
4
|
+
// Phase 1: Read-only git tools
|
|
5
|
+
export { gitStatusTool, createGitStatusTool } from './status.js';
|
|
6
|
+
export { gitDiffTool, createGitDiffTool } from './diff.js';
|
|
7
|
+
export { gitLogTool, createGitLogTool } from './log.js';
|
|
8
|
+
// Phase 2: Core git tools
|
|
9
|
+
export { gitCommitTool, createGitCommitTool } from './commit.js';
|
|
10
|
+
export { gitBranchTool, createGitBranchTool } from './branch.js';
|
|
11
|
+
export { gitStashTool, createGitStashTool } from './stash.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Log Tool
|
|
3
|
+
* Shows commit history with various filtering options
|
|
4
|
+
*/
|
|
5
|
+
import type { Tool } from '@compilr-dev/agents';
|
|
6
|
+
import type { GitLogInput } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Git log tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const gitLogTool: Tool<GitLogInput>;
|
|
11
|
+
/**
|
|
12
|
+
* Factory function to create git log tool with custom options
|
|
13
|
+
*/
|
|
14
|
+
export declare function createGitLogTool(options?: {
|
|
15
|
+
/** Base directory for relative paths */
|
|
16
|
+
baseDir?: string;
|
|
17
|
+
/** Default limit */
|
|
18
|
+
defaultLimit?: number;
|
|
19
|
+
}): Tool<GitLogInput>;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Log Tool
|
|
3
|
+
* Shows commit history with various filtering options
|
|
4
|
+
*/
|
|
5
|
+
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
6
|
+
import { runGitCommand, isGitRepository, isDirectory } from './utils.js';
|
|
7
|
+
/**
|
|
8
|
+
* Git log tool
|
|
9
|
+
*/
|
|
10
|
+
export const gitLogTool = defineTool({
|
|
11
|
+
name: 'git_log',
|
|
12
|
+
description: 'Show commit history. ' +
|
|
13
|
+
'Returns structured commit data including hash, author, date, and message. ' +
|
|
14
|
+
'Supports filtering by author, date range, file path, and message content.',
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
path: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Working directory path (default: current directory)',
|
|
21
|
+
},
|
|
22
|
+
limit: {
|
|
23
|
+
type: 'number',
|
|
24
|
+
description: 'Number of commits to return (default: 10)',
|
|
25
|
+
},
|
|
26
|
+
file: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Filter commits by file path',
|
|
29
|
+
},
|
|
30
|
+
author: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'Filter by author name or email',
|
|
33
|
+
},
|
|
34
|
+
since: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: 'Show commits since date (ISO format or relative like "2 weeks ago")',
|
|
37
|
+
},
|
|
38
|
+
until: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'Show commits until date (ISO format or relative)',
|
|
41
|
+
},
|
|
42
|
+
oneline: {
|
|
43
|
+
type: 'boolean',
|
|
44
|
+
description: 'One-line format (hash + message only, no author/date)',
|
|
45
|
+
},
|
|
46
|
+
stat: {
|
|
47
|
+
type: 'boolean',
|
|
48
|
+
description: 'Include diff statistics for each commit',
|
|
49
|
+
},
|
|
50
|
+
grep: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
description: 'Filter by pattern in commit message',
|
|
53
|
+
},
|
|
54
|
+
ref: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'Branch or ref to show log for (default: HEAD)',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
required: [],
|
|
60
|
+
},
|
|
61
|
+
execute: executeGitLog,
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Execute git log
|
|
65
|
+
*/
|
|
66
|
+
async function executeGitLog(input) {
|
|
67
|
+
const targetPath = input.path ?? process.cwd();
|
|
68
|
+
const limit = input.limit ?? 10;
|
|
69
|
+
// Check if path exists
|
|
70
|
+
if (!(await isDirectory(targetPath))) {
|
|
71
|
+
return createErrorResult(`Directory not found: ${targetPath}`);
|
|
72
|
+
}
|
|
73
|
+
// Check if it's a git repository
|
|
74
|
+
if (!(await isGitRepository(targetPath))) {
|
|
75
|
+
return createErrorResult(`Not a git repository: ${targetPath}`);
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
// Use a custom format for structured parsing
|
|
79
|
+
// Format: hash%x00shortHash%x00author%x00email%x00date%x00subject%x00body%x00%x01
|
|
80
|
+
const format = '%H%x00%h%x00%an%x00%ae%x00%aI%x00%s%x00%b%x00%x01';
|
|
81
|
+
const args = ['log', `--format=${format}`, `-n${String(limit)}`];
|
|
82
|
+
// Ref/branch
|
|
83
|
+
if (input.ref) {
|
|
84
|
+
args.push(input.ref);
|
|
85
|
+
}
|
|
86
|
+
// Filters
|
|
87
|
+
if (input.author) {
|
|
88
|
+
args.push(`--author=${input.author}`);
|
|
89
|
+
}
|
|
90
|
+
if (input.since) {
|
|
91
|
+
args.push(`--since=${input.since}`);
|
|
92
|
+
}
|
|
93
|
+
if (input.until) {
|
|
94
|
+
args.push(`--until=${input.until}`);
|
|
95
|
+
}
|
|
96
|
+
if (input.grep) {
|
|
97
|
+
args.push(`--grep=${input.grep}`);
|
|
98
|
+
}
|
|
99
|
+
// File filter (must be after --)
|
|
100
|
+
if (input.file) {
|
|
101
|
+
args.push('--', input.file);
|
|
102
|
+
}
|
|
103
|
+
const result = await runGitCommand(args, { cwd: targetPath });
|
|
104
|
+
if (!result.success) {
|
|
105
|
+
return createErrorResult(`git log failed: ${result.stderr}`);
|
|
106
|
+
}
|
|
107
|
+
// Parse commits
|
|
108
|
+
const commits = [];
|
|
109
|
+
if (result.stdout) {
|
|
110
|
+
// Split by the separator we used (0x01)
|
|
111
|
+
const entries = result.stdout.split('\x01').filter((e) => e.trim());
|
|
112
|
+
for (const entry of entries) {
|
|
113
|
+
const parts = entry.trim().split('\x00');
|
|
114
|
+
if (parts.length >= 6) {
|
|
115
|
+
const commit = {
|
|
116
|
+
hash: parts[0],
|
|
117
|
+
shortHash: parts[1],
|
|
118
|
+
author: parts[2],
|
|
119
|
+
email: parts[3],
|
|
120
|
+
date: parts[4],
|
|
121
|
+
message: parts[5],
|
|
122
|
+
body: parts[6]?.trim() || undefined,
|
|
123
|
+
};
|
|
124
|
+
commits.push(commit);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Get stat info if requested
|
|
129
|
+
if (input.stat && commits.length > 0) {
|
|
130
|
+
const statArgs = ['log', '--stat', '--format=%H%x00', `-n${String(limit)}`];
|
|
131
|
+
if (input.ref)
|
|
132
|
+
statArgs.push(input.ref);
|
|
133
|
+
if (input.author)
|
|
134
|
+
statArgs.push(`--author=${input.author}`);
|
|
135
|
+
if (input.since)
|
|
136
|
+
statArgs.push(`--since=${input.since}`);
|
|
137
|
+
if (input.until)
|
|
138
|
+
statArgs.push(`--until=${input.until}`);
|
|
139
|
+
if (input.file)
|
|
140
|
+
statArgs.push('--', input.file);
|
|
141
|
+
const statResult = await runGitCommand(statArgs, { cwd: targetPath });
|
|
142
|
+
if (statResult.success && statResult.stdout) {
|
|
143
|
+
// Parse stat output and attach to commits
|
|
144
|
+
const statEntries = statResult.stdout.split('\x00').filter(Boolean);
|
|
145
|
+
for (let i = 0; i < statEntries.length && i < commits.length; i++) {
|
|
146
|
+
// Each entry is hash followed by stat lines
|
|
147
|
+
const lines = statEntries[i].trim().split('\n');
|
|
148
|
+
const hash = lines[0].trim();
|
|
149
|
+
const statLines = lines.slice(1).filter(Boolean);
|
|
150
|
+
// Find matching commit
|
|
151
|
+
const commit = commits.find((c) => c.hash === hash);
|
|
152
|
+
if (commit && statLines.length > 0) {
|
|
153
|
+
commit.stat = statLines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const logResult = {
|
|
159
|
+
commits,
|
|
160
|
+
};
|
|
161
|
+
return createSuccessResult(logResult);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
return createErrorResult(error instanceof Error ? error.message : String(error));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Factory function to create git log tool with custom options
|
|
169
|
+
*/
|
|
170
|
+
export function createGitLogTool(options) {
|
|
171
|
+
return defineTool({
|
|
172
|
+
name: 'git_log',
|
|
173
|
+
description: 'Show commit history. ' +
|
|
174
|
+
'Returns structured commit data including hash, author, date, and message.',
|
|
175
|
+
inputSchema: {
|
|
176
|
+
type: 'object',
|
|
177
|
+
properties: {
|
|
178
|
+
path: {
|
|
179
|
+
type: 'string',
|
|
180
|
+
description: 'Working directory path (default: current directory)',
|
|
181
|
+
},
|
|
182
|
+
limit: {
|
|
183
|
+
type: 'number',
|
|
184
|
+
description: `Number of commits to return (default: ${String(options?.defaultLimit ?? 10)})`,
|
|
185
|
+
},
|
|
186
|
+
file: {
|
|
187
|
+
type: 'string',
|
|
188
|
+
description: 'Filter commits by file path',
|
|
189
|
+
},
|
|
190
|
+
author: {
|
|
191
|
+
type: 'string',
|
|
192
|
+
description: 'Filter by author name or email',
|
|
193
|
+
},
|
|
194
|
+
since: {
|
|
195
|
+
type: 'string',
|
|
196
|
+
description: 'Show commits since date (ISO format or relative)',
|
|
197
|
+
},
|
|
198
|
+
until: {
|
|
199
|
+
type: 'string',
|
|
200
|
+
description: 'Show commits until date (ISO format or relative)',
|
|
201
|
+
},
|
|
202
|
+
oneline: {
|
|
203
|
+
type: 'boolean',
|
|
204
|
+
description: 'One-line format (hash + message only)',
|
|
205
|
+
},
|
|
206
|
+
stat: {
|
|
207
|
+
type: 'boolean',
|
|
208
|
+
description: 'Include diff statistics for each commit',
|
|
209
|
+
},
|
|
210
|
+
grep: {
|
|
211
|
+
type: 'string',
|
|
212
|
+
description: 'Filter by pattern in commit message',
|
|
213
|
+
},
|
|
214
|
+
ref: {
|
|
215
|
+
type: 'string',
|
|
216
|
+
description: 'Branch or ref to show log for',
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
required: [],
|
|
220
|
+
},
|
|
221
|
+
execute: async (input) => {
|
|
222
|
+
let targetPath = input.path ?? '.';
|
|
223
|
+
// Resolve relative paths
|
|
224
|
+
if (options?.baseDir && !targetPath.startsWith('/')) {
|
|
225
|
+
const nodePath = await import('node:path');
|
|
226
|
+
targetPath = nodePath.join(options.baseDir, targetPath);
|
|
227
|
+
}
|
|
228
|
+
return executeGitLog({
|
|
229
|
+
...input,
|
|
230
|
+
path: targetPath,
|
|
231
|
+
limit: input.limit ?? options?.defaultLimit ?? 10,
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Stash Tool
|
|
3
|
+
* Stash and restore changes
|
|
4
|
+
*/
|
|
5
|
+
import type { Tool } from '@compilr-dev/agents';
|
|
6
|
+
import type { GitStashInput } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Git stash tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const gitStashTool: Tool<GitStashInput>;
|
|
11
|
+
/**
|
|
12
|
+
* Factory function to create git stash tool with custom options
|
|
13
|
+
*/
|
|
14
|
+
export declare function createGitStashTool(options?: {
|
|
15
|
+
/** Base directory for relative paths */
|
|
16
|
+
baseDir?: string;
|
|
17
|
+
}): Tool<GitStashInput>;
|