@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,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Lint Tool
|
|
3
|
+
* Auto-detect and run linter using the appropriate tool
|
|
4
|
+
*/
|
|
5
|
+
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
6
|
+
import { isDirectory, readPackageJson, listDirectory, hasFile, hasDependency, hasScript, runCommand, buildCommand, formatCommand, DEFAULT_TIMEOUT, } from './utils.js';
|
|
7
|
+
const LINTERS = [
|
|
8
|
+
// ESLint (Node.js)
|
|
9
|
+
{
|
|
10
|
+
name: 'eslint',
|
|
11
|
+
detect: (entries, pkg) => hasFile(entries, 'eslint.config.js') ||
|
|
12
|
+
hasFile(entries, 'eslint.config.mjs') ||
|
|
13
|
+
hasFile(entries, 'eslint.config.cjs') ||
|
|
14
|
+
hasFile(entries, '.eslintrc.js') ||
|
|
15
|
+
hasFile(entries, '.eslintrc.json') ||
|
|
16
|
+
hasFile(entries, '.eslintrc.yaml') ||
|
|
17
|
+
hasFile(entries, '.eslintrc.yml') ||
|
|
18
|
+
hasFile(entries, '.eslintrc') ||
|
|
19
|
+
hasDependency(pkg, 'eslint'),
|
|
20
|
+
getCommand: (input) => {
|
|
21
|
+
const args = ['eslint'];
|
|
22
|
+
if (input.files && input.files.length > 0) {
|
|
23
|
+
args.push(...input.files);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
args.push('.');
|
|
27
|
+
}
|
|
28
|
+
if (input.fix)
|
|
29
|
+
args.push('--fix');
|
|
30
|
+
if (input.format)
|
|
31
|
+
args.push('--format', input.format);
|
|
32
|
+
return { command: 'npx', args, useNpx: false };
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
// Biome (Node.js)
|
|
36
|
+
{
|
|
37
|
+
name: 'biome',
|
|
38
|
+
detect: (entries, pkg) => hasFile(entries, 'biome.json') ||
|
|
39
|
+
hasFile(entries, 'biome.jsonc') ||
|
|
40
|
+
hasDependency(pkg, '@biomejs/biome'),
|
|
41
|
+
getCommand: (input) => {
|
|
42
|
+
const args = ['biome', 'lint'];
|
|
43
|
+
if (input.files && input.files.length > 0) {
|
|
44
|
+
args.push(...input.files);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
args.push('.');
|
|
48
|
+
}
|
|
49
|
+
if (input.fix)
|
|
50
|
+
args.push('--apply');
|
|
51
|
+
return { command: 'npx', args, useNpx: false };
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
// npm lint script fallback (Node.js)
|
|
55
|
+
{
|
|
56
|
+
name: 'npm lint',
|
|
57
|
+
detect: (_entries, pkg) => hasScript(pkg, 'lint'),
|
|
58
|
+
getCommand: (input) => {
|
|
59
|
+
const args = ['run', 'lint'];
|
|
60
|
+
if (input.fix && hasScript(null, 'lint:fix')) {
|
|
61
|
+
return {
|
|
62
|
+
command: 'npm',
|
|
63
|
+
args: ['run', 'lint:fix'],
|
|
64
|
+
useScript: true,
|
|
65
|
+
scriptName: 'lint:fix',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return { command: 'npm', args, useScript: true, scriptName: 'lint' };
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
// Ruff (Python)
|
|
72
|
+
{
|
|
73
|
+
name: 'ruff',
|
|
74
|
+
detect: (entries) => hasFile(entries, 'ruff.toml') || hasFile(entries, '.ruff.toml'),
|
|
75
|
+
getCommand: (input) => {
|
|
76
|
+
const args = ['check'];
|
|
77
|
+
if (input.files && input.files.length > 0) {
|
|
78
|
+
args.push(...input.files);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
args.push('.');
|
|
82
|
+
}
|
|
83
|
+
if (input.fix)
|
|
84
|
+
args.push('--fix');
|
|
85
|
+
if (input.format === 'json')
|
|
86
|
+
args.push('--output-format', 'json');
|
|
87
|
+
return { command: 'ruff', args };
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
// Pylint (Python)
|
|
91
|
+
{
|
|
92
|
+
name: 'pylint',
|
|
93
|
+
detect: (entries) => hasFile(entries, '.pylintrc') || hasFile(entries, 'pylintrc'),
|
|
94
|
+
getCommand: (input) => {
|
|
95
|
+
const args = [];
|
|
96
|
+
if (input.files && input.files.length > 0) {
|
|
97
|
+
args.push(...input.files);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
args.push('.');
|
|
101
|
+
}
|
|
102
|
+
if (input.format === 'json')
|
|
103
|
+
args.push('--output-format=json');
|
|
104
|
+
return { command: 'pylint', args };
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
// Flake8 (Python)
|
|
108
|
+
{
|
|
109
|
+
name: 'flake8',
|
|
110
|
+
detect: (entries) => hasFile(entries, '.flake8') || hasFile(entries, 'setup.cfg'),
|
|
111
|
+
getCommand: (input) => {
|
|
112
|
+
const args = [];
|
|
113
|
+
if (input.files && input.files.length > 0) {
|
|
114
|
+
args.push(...input.files);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
args.push('.');
|
|
118
|
+
}
|
|
119
|
+
if (input.format === 'json')
|
|
120
|
+
args.push('--format=json');
|
|
121
|
+
return { command: 'flake8', args };
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
// Clippy (Rust)
|
|
125
|
+
{
|
|
126
|
+
name: 'clippy',
|
|
127
|
+
detect: (entries) => hasFile(entries, 'Cargo.toml'),
|
|
128
|
+
getCommand: (input) => {
|
|
129
|
+
const args = ['clippy'];
|
|
130
|
+
if (input.fix)
|
|
131
|
+
args.push('--fix', '--allow-dirty');
|
|
132
|
+
args.push('--', '-D', 'warnings');
|
|
133
|
+
return { command: 'cargo', args };
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
// golangci-lint (Go)
|
|
137
|
+
{
|
|
138
|
+
name: 'golangci-lint',
|
|
139
|
+
detect: (entries) => hasFile(entries, '.golangci.yml') ||
|
|
140
|
+
hasFile(entries, '.golangci.yaml') ||
|
|
141
|
+
hasFile(entries, '.golangci.json') ||
|
|
142
|
+
hasFile(entries, 'go.mod'),
|
|
143
|
+
getCommand: (input) => {
|
|
144
|
+
const args = ['run'];
|
|
145
|
+
if (input.files && input.files.length > 0) {
|
|
146
|
+
args.push(...input.files);
|
|
147
|
+
}
|
|
148
|
+
if (input.fix)
|
|
149
|
+
args.push('--fix');
|
|
150
|
+
if (input.format === 'json')
|
|
151
|
+
args.push('--out-format', 'json');
|
|
152
|
+
return { command: 'golangci-lint', args };
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
/**
|
|
157
|
+
* Run Lint Tool
|
|
158
|
+
*/
|
|
159
|
+
export const runLintTool = defineTool({
|
|
160
|
+
name: 'run_lint',
|
|
161
|
+
description: 'Run linter using the auto-detected linting tool. ' +
|
|
162
|
+
'Supports ESLint, Biome, Ruff, Pylint, Flake8, Clippy, golangci-lint, and npm lint scripts. ' +
|
|
163
|
+
'Options: files (specific files), fix (auto-fix), format (output format).',
|
|
164
|
+
inputSchema: {
|
|
165
|
+
type: 'object',
|
|
166
|
+
properties: {
|
|
167
|
+
path: {
|
|
168
|
+
type: 'string',
|
|
169
|
+
description: 'Working directory (default: current directory)',
|
|
170
|
+
},
|
|
171
|
+
files: {
|
|
172
|
+
type: 'array',
|
|
173
|
+
items: { type: 'string' },
|
|
174
|
+
description: 'Specific files to lint',
|
|
175
|
+
},
|
|
176
|
+
fix: {
|
|
177
|
+
type: 'boolean',
|
|
178
|
+
description: 'Auto-fix issues (if supported)',
|
|
179
|
+
},
|
|
180
|
+
format: {
|
|
181
|
+
type: 'string',
|
|
182
|
+
description: 'Output format (json, stylish, etc.)',
|
|
183
|
+
},
|
|
184
|
+
timeout: {
|
|
185
|
+
type: 'number',
|
|
186
|
+
description: 'Timeout in milliseconds (default: 300000)',
|
|
187
|
+
},
|
|
188
|
+
dryRun: {
|
|
189
|
+
type: 'boolean',
|
|
190
|
+
description: 'Detect linter and return command without executing (default: false)',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
required: [],
|
|
194
|
+
},
|
|
195
|
+
execute: executeRunLint,
|
|
196
|
+
});
|
|
197
|
+
/**
|
|
198
|
+
* Execute run lint
|
|
199
|
+
*/
|
|
200
|
+
async function executeRunLint(input) {
|
|
201
|
+
const targetPath = input.path ?? process.cwd();
|
|
202
|
+
const timeout = input.timeout ?? DEFAULT_TIMEOUT;
|
|
203
|
+
// Check if directory exists
|
|
204
|
+
if (!(await isDirectory(targetPath))) {
|
|
205
|
+
return createErrorResult(`Directory not found: ${targetPath}`);
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
// Read directory and package.json
|
|
209
|
+
const entries = await listDirectory(targetPath);
|
|
210
|
+
const packageJson = await readPackageJson(targetPath);
|
|
211
|
+
// Detect linter
|
|
212
|
+
let linter;
|
|
213
|
+
for (const l of LINTERS) {
|
|
214
|
+
if (l.detect(entries, packageJson)) {
|
|
215
|
+
linter = l;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (!linter) {
|
|
220
|
+
return createErrorResult('No linter detected. Supported: ESLint, Biome, Ruff, Pylint, Flake8, Clippy, golangci-lint, npm lint script.');
|
|
221
|
+
}
|
|
222
|
+
// Build command
|
|
223
|
+
const template = linter.getCommand(input);
|
|
224
|
+
const { command, args } = buildCommand(template);
|
|
225
|
+
const commandString = formatCommand(command, args);
|
|
226
|
+
// Dry run - return detected info without executing
|
|
227
|
+
if (input.dryRun) {
|
|
228
|
+
const lintResult = {
|
|
229
|
+
command: commandString,
|
|
230
|
+
output: '(dry run - command not executed)',
|
|
231
|
+
exitCode: 0,
|
|
232
|
+
duration: 0,
|
|
233
|
+
success: true,
|
|
234
|
+
linter: linter.name,
|
|
235
|
+
};
|
|
236
|
+
return createSuccessResult(lintResult);
|
|
237
|
+
}
|
|
238
|
+
// Run linter
|
|
239
|
+
const result = await runCommand(command, args, {
|
|
240
|
+
cwd: targetPath,
|
|
241
|
+
timeout,
|
|
242
|
+
env: {
|
|
243
|
+
FORCE_COLOR: '1',
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
// Combine output
|
|
247
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
248
|
+
// Parse error/warning counts from output (best effort)
|
|
249
|
+
const counts = parseLintCounts(output, linter.name);
|
|
250
|
+
const lintResult = {
|
|
251
|
+
command: commandString,
|
|
252
|
+
output,
|
|
253
|
+
exitCode: result.exitCode,
|
|
254
|
+
duration: result.duration,
|
|
255
|
+
success: result.exitCode === 0,
|
|
256
|
+
linter: linter.name,
|
|
257
|
+
...counts,
|
|
258
|
+
};
|
|
259
|
+
return createSuccessResult(lintResult);
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
return createErrorResult(error instanceof Error ? error.message : String(error));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Parse lint error/warning counts from output (best effort)
|
|
267
|
+
*/
|
|
268
|
+
function parseLintCounts(output, _linter) {
|
|
269
|
+
const counts = {};
|
|
270
|
+
// ESLint pattern: "✖ 5 problems (3 errors, 2 warnings)"
|
|
271
|
+
const eslintMatch = output.match(/(\d+)\s+errors?,\s+(\d+)\s+warnings?/i);
|
|
272
|
+
if (eslintMatch) {
|
|
273
|
+
counts.errors = parseInt(eslintMatch[1], 10);
|
|
274
|
+
counts.warnings = parseInt(eslintMatch[2], 10);
|
|
275
|
+
}
|
|
276
|
+
// Ruff pattern: "Found 10 errors."
|
|
277
|
+
const ruffMatch = output.match(/Found\s+(\d+)\s+errors?/i);
|
|
278
|
+
if (ruffMatch) {
|
|
279
|
+
counts.errors = parseInt(ruffMatch[1], 10);
|
|
280
|
+
}
|
|
281
|
+
// Pylint pattern: "Your code has been rated at 8.5/10"
|
|
282
|
+
// Pylint doesn't give direct counts easily, but we can try
|
|
283
|
+
const pylintErrorMatch = output.match(/E\d{4}:/g);
|
|
284
|
+
if (pylintErrorMatch) {
|
|
285
|
+
counts.errors = pylintErrorMatch.length;
|
|
286
|
+
}
|
|
287
|
+
const pylintWarnMatch = output.match(/W\d{4}:/g);
|
|
288
|
+
if (pylintWarnMatch) {
|
|
289
|
+
counts.warnings = pylintWarnMatch.length;
|
|
290
|
+
}
|
|
291
|
+
// Clippy pattern: "error:" and "warning:"
|
|
292
|
+
const clippyErrorMatch = output.match(/^error(\[E\d+\])?:/gm);
|
|
293
|
+
if (clippyErrorMatch) {
|
|
294
|
+
counts.errors = clippyErrorMatch.length;
|
|
295
|
+
}
|
|
296
|
+
const clippyWarnMatch = output.match(/^warning(\[.+\])?:/gm);
|
|
297
|
+
if (clippyWarnMatch) {
|
|
298
|
+
counts.warnings = clippyWarnMatch.length;
|
|
299
|
+
}
|
|
300
|
+
// golangci-lint pattern counts errors by lines with issues
|
|
301
|
+
const goLintMatch = output.match(/^[^:]+:\d+:\d+:/gm);
|
|
302
|
+
if (goLintMatch) {
|
|
303
|
+
counts.errors = goLintMatch.length;
|
|
304
|
+
}
|
|
305
|
+
return counts;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Factory function to create run lint tool with custom options
|
|
309
|
+
*/
|
|
310
|
+
export function createRunLintTool(options) {
|
|
311
|
+
return defineTool({
|
|
312
|
+
name: 'run_lint',
|
|
313
|
+
description: 'Run linter using the auto-detected linting tool. ' +
|
|
314
|
+
'Supports ESLint, Biome, Ruff, Pylint, Flake8, Clippy, golangci-lint.',
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: 'object',
|
|
317
|
+
properties: {
|
|
318
|
+
path: {
|
|
319
|
+
type: 'string',
|
|
320
|
+
description: 'Working directory (default: current directory)',
|
|
321
|
+
},
|
|
322
|
+
files: {
|
|
323
|
+
type: 'array',
|
|
324
|
+
items: { type: 'string' },
|
|
325
|
+
description: 'Specific files to lint',
|
|
326
|
+
},
|
|
327
|
+
fix: {
|
|
328
|
+
type: 'boolean',
|
|
329
|
+
description: 'Auto-fix issues',
|
|
330
|
+
},
|
|
331
|
+
format: {
|
|
332
|
+
type: 'string',
|
|
333
|
+
description: 'Output format',
|
|
334
|
+
},
|
|
335
|
+
timeout: {
|
|
336
|
+
type: 'number',
|
|
337
|
+
description: 'Timeout in milliseconds',
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
required: [],
|
|
341
|
+
},
|
|
342
|
+
execute: async (input) => {
|
|
343
|
+
let targetPath = input.path ?? '.';
|
|
344
|
+
// Resolve relative paths
|
|
345
|
+
if (options?.baseDir && !targetPath.startsWith('/')) {
|
|
346
|
+
const nodePath = await import('node:path');
|
|
347
|
+
targetPath = nodePath.join(options.baseDir, targetPath);
|
|
348
|
+
}
|
|
349
|
+
return executeRunLint({
|
|
350
|
+
...input,
|
|
351
|
+
path: targetPath,
|
|
352
|
+
timeout: input.timeout ?? options?.defaultTimeout,
|
|
353
|
+
});
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Tests Tool
|
|
3
|
+
* Auto-detect and run tests using the appropriate framework
|
|
4
|
+
*/
|
|
5
|
+
import type { Tool } from '@compilr-dev/agents';
|
|
6
|
+
import type { RunTestsInput } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Run Tests Tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const runTestsTool: Tool<RunTestsInput>;
|
|
11
|
+
/**
|
|
12
|
+
* Factory function to create run tests tool with custom options
|
|
13
|
+
*/
|
|
14
|
+
export declare function createRunTestsTool(options?: {
|
|
15
|
+
/** Base directory for relative paths */
|
|
16
|
+
baseDir?: string;
|
|
17
|
+
/** Default timeout */
|
|
18
|
+
defaultTimeout?: number;
|
|
19
|
+
}): Tool<RunTestsInput>;
|