@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,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Format Tool
|
|
3
|
+
* Auto-detect and run formatter 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 FORMATTERS = [
|
|
8
|
+
// Prettier (Node.js)
|
|
9
|
+
{
|
|
10
|
+
name: 'prettier',
|
|
11
|
+
detect: (entries, pkg) => hasFile(entries, '.prettierrc') ||
|
|
12
|
+
hasFile(entries, '.prettierrc.js') ||
|
|
13
|
+
hasFile(entries, '.prettierrc.json') ||
|
|
14
|
+
hasFile(entries, '.prettierrc.yaml') ||
|
|
15
|
+
hasFile(entries, '.prettierrc.yml') ||
|
|
16
|
+
hasFile(entries, 'prettier.config.js') ||
|
|
17
|
+
hasFile(entries, 'prettier.config.mjs') ||
|
|
18
|
+
hasDependency(pkg, 'prettier'),
|
|
19
|
+
getCommand: (input) => {
|
|
20
|
+
const args = ['prettier'];
|
|
21
|
+
if (input.check) {
|
|
22
|
+
args.push('--check');
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
args.push('--write');
|
|
26
|
+
}
|
|
27
|
+
if (input.files && input.files.length > 0) {
|
|
28
|
+
args.push(...input.files);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
args.push('.');
|
|
32
|
+
}
|
|
33
|
+
return { command: 'npx', args, useNpx: false };
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
// Biome (Node.js)
|
|
37
|
+
{
|
|
38
|
+
name: 'biome',
|
|
39
|
+
detect: (entries, pkg) => hasFile(entries, 'biome.json') ||
|
|
40
|
+
hasFile(entries, 'biome.jsonc') ||
|
|
41
|
+
hasDependency(pkg, '@biomejs/biome'),
|
|
42
|
+
getCommand: (input) => {
|
|
43
|
+
const args = ['biome', 'format'];
|
|
44
|
+
if (!input.check) {
|
|
45
|
+
args.push('--write');
|
|
46
|
+
}
|
|
47
|
+
if (input.files && input.files.length > 0) {
|
|
48
|
+
args.push(...input.files);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
args.push('.');
|
|
52
|
+
}
|
|
53
|
+
return { command: 'npx', args, useNpx: false };
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
// dprint (Node.js)
|
|
57
|
+
{
|
|
58
|
+
name: 'dprint',
|
|
59
|
+
detect: (entries, pkg) => hasFile(entries, 'dprint.json') ||
|
|
60
|
+
hasFile(entries, '.dprint.json') ||
|
|
61
|
+
hasDependency(pkg, 'dprint'),
|
|
62
|
+
getCommand: (input) => {
|
|
63
|
+
const args = ['dprint'];
|
|
64
|
+
if (input.check) {
|
|
65
|
+
args.push('check');
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
args.push('fmt');
|
|
69
|
+
}
|
|
70
|
+
if (input.files && input.files.length > 0) {
|
|
71
|
+
args.push(...input.files);
|
|
72
|
+
}
|
|
73
|
+
return { command: 'npx', args, useNpx: false };
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
// npm format script fallback (Node.js)
|
|
77
|
+
{
|
|
78
|
+
name: 'npm format',
|
|
79
|
+
detect: (_entries, pkg) => hasScript(pkg, 'format'),
|
|
80
|
+
getCommand: (input) => {
|
|
81
|
+
if (input.check && hasScript(null, 'format:check')) {
|
|
82
|
+
return {
|
|
83
|
+
command: 'npm',
|
|
84
|
+
args: ['run', 'format:check'],
|
|
85
|
+
useScript: true,
|
|
86
|
+
scriptName: 'format:check',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return { command: 'npm', args: ['run', 'format'], useScript: true, scriptName: 'format' };
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
// Black (Python)
|
|
93
|
+
{
|
|
94
|
+
name: 'black',
|
|
95
|
+
detect: (entries) => hasFile(entries, 'pyproject.toml') || hasFile(entries, '.black'),
|
|
96
|
+
getCommand: (input) => {
|
|
97
|
+
const args = [];
|
|
98
|
+
if (input.check)
|
|
99
|
+
args.push('--check');
|
|
100
|
+
if (input.files && input.files.length > 0) {
|
|
101
|
+
args.push(...input.files);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
args.push('.');
|
|
105
|
+
}
|
|
106
|
+
return { command: 'black', args };
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
// Ruff format (Python)
|
|
110
|
+
{
|
|
111
|
+
name: 'ruff format',
|
|
112
|
+
detect: (entries) => hasFile(entries, 'ruff.toml') || hasFile(entries, '.ruff.toml'),
|
|
113
|
+
getCommand: (input) => {
|
|
114
|
+
const args = ['format'];
|
|
115
|
+
if (input.check)
|
|
116
|
+
args.push('--check');
|
|
117
|
+
if (input.files && input.files.length > 0) {
|
|
118
|
+
args.push(...input.files);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
args.push('.');
|
|
122
|
+
}
|
|
123
|
+
return { command: 'ruff', args };
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
// autopep8 (Python)
|
|
127
|
+
{
|
|
128
|
+
name: 'autopep8',
|
|
129
|
+
detect: (entries) => hasFile(entries, '.pep8') || hasFile(entries, 'setup.cfg'),
|
|
130
|
+
getCommand: (input) => {
|
|
131
|
+
const args = [];
|
|
132
|
+
if (input.check) {
|
|
133
|
+
args.push('--diff');
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
args.push('--in-place');
|
|
137
|
+
}
|
|
138
|
+
args.push('--recursive');
|
|
139
|
+
if (input.files && input.files.length > 0) {
|
|
140
|
+
args.push(...input.files);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
args.push('.');
|
|
144
|
+
}
|
|
145
|
+
return { command: 'autopep8', args };
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
// rustfmt (Rust)
|
|
149
|
+
{
|
|
150
|
+
name: 'rustfmt',
|
|
151
|
+
detect: (entries) => hasFile(entries, 'Cargo.toml'),
|
|
152
|
+
getCommand: (input) => {
|
|
153
|
+
const args = ['fmt'];
|
|
154
|
+
if (input.check)
|
|
155
|
+
args.push('--check');
|
|
156
|
+
return { command: 'cargo', args };
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
// gofmt (Go)
|
|
160
|
+
{
|
|
161
|
+
name: 'gofmt',
|
|
162
|
+
detect: (entries) => hasFile(entries, 'go.mod'),
|
|
163
|
+
getCommand: (input) => {
|
|
164
|
+
const args = [];
|
|
165
|
+
if (input.check) {
|
|
166
|
+
args.push('-l');
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
args.push('-w');
|
|
170
|
+
}
|
|
171
|
+
if (input.files && input.files.length > 0) {
|
|
172
|
+
args.push(...input.files);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
args.push('.');
|
|
176
|
+
}
|
|
177
|
+
return { command: 'gofmt', args };
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
// goimports (Go) - preferred over gofmt
|
|
181
|
+
{
|
|
182
|
+
name: 'goimports',
|
|
183
|
+
detect: (entries) => hasFile(entries, 'go.mod'),
|
|
184
|
+
getCommand: (input) => {
|
|
185
|
+
const args = [];
|
|
186
|
+
if (input.check) {
|
|
187
|
+
args.push('-l');
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
args.push('-w');
|
|
191
|
+
}
|
|
192
|
+
if (input.files && input.files.length > 0) {
|
|
193
|
+
args.push(...input.files);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
args.push('.');
|
|
197
|
+
}
|
|
198
|
+
return { command: 'goimports', args };
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
/**
|
|
203
|
+
* Run Format Tool
|
|
204
|
+
*/
|
|
205
|
+
export const runFormatTool = defineTool({
|
|
206
|
+
name: 'run_format',
|
|
207
|
+
description: 'Run formatter using the auto-detected formatting tool. ' +
|
|
208
|
+
'Supports Prettier, Biome, dprint, Black, Ruff, rustfmt, gofmt, and npm format scripts. ' +
|
|
209
|
+
"Options: files (specific files), check (check only, don't write).",
|
|
210
|
+
inputSchema: {
|
|
211
|
+
type: 'object',
|
|
212
|
+
properties: {
|
|
213
|
+
path: {
|
|
214
|
+
type: 'string',
|
|
215
|
+
description: 'Working directory (default: current directory)',
|
|
216
|
+
},
|
|
217
|
+
files: {
|
|
218
|
+
type: 'array',
|
|
219
|
+
items: { type: 'string' },
|
|
220
|
+
description: 'Specific files to format',
|
|
221
|
+
},
|
|
222
|
+
check: {
|
|
223
|
+
type: 'boolean',
|
|
224
|
+
description: "Check only, don't write changes",
|
|
225
|
+
},
|
|
226
|
+
timeout: {
|
|
227
|
+
type: 'number',
|
|
228
|
+
description: 'Timeout in milliseconds (default: 300000)',
|
|
229
|
+
},
|
|
230
|
+
dryRun: {
|
|
231
|
+
type: 'boolean',
|
|
232
|
+
description: 'Detect formatter and return command without executing (default: false)',
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
required: [],
|
|
236
|
+
},
|
|
237
|
+
execute: executeRunFormat,
|
|
238
|
+
});
|
|
239
|
+
/**
|
|
240
|
+
* Execute run format
|
|
241
|
+
*/
|
|
242
|
+
async function executeRunFormat(input) {
|
|
243
|
+
const targetPath = input.path ?? process.cwd();
|
|
244
|
+
const timeout = input.timeout ?? DEFAULT_TIMEOUT;
|
|
245
|
+
// Check if directory exists
|
|
246
|
+
if (!(await isDirectory(targetPath))) {
|
|
247
|
+
return createErrorResult(`Directory not found: ${targetPath}`);
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
// Read directory and package.json
|
|
251
|
+
const entries = await listDirectory(targetPath);
|
|
252
|
+
const packageJson = await readPackageJson(targetPath);
|
|
253
|
+
// Detect formatter
|
|
254
|
+
let formatter;
|
|
255
|
+
for (const f of FORMATTERS) {
|
|
256
|
+
if (f.detect(entries, packageJson)) {
|
|
257
|
+
formatter = f;
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (!formatter) {
|
|
262
|
+
return createErrorResult('No formatter detected. Supported: Prettier, Biome, dprint, Black, Ruff, rustfmt, gofmt, npm format script.');
|
|
263
|
+
}
|
|
264
|
+
// Build command
|
|
265
|
+
const template = formatter.getCommand(input);
|
|
266
|
+
const { command, args } = buildCommand(template);
|
|
267
|
+
const commandString = formatCommand(command, args);
|
|
268
|
+
// Dry run - return detected info without executing
|
|
269
|
+
if (input.dryRun) {
|
|
270
|
+
const formatResult = {
|
|
271
|
+
command: commandString,
|
|
272
|
+
output: '(dry run - command not executed)',
|
|
273
|
+
exitCode: 0,
|
|
274
|
+
duration: 0,
|
|
275
|
+
success: true,
|
|
276
|
+
formatter: formatter.name,
|
|
277
|
+
};
|
|
278
|
+
return createSuccessResult(formatResult);
|
|
279
|
+
}
|
|
280
|
+
// Run formatter
|
|
281
|
+
const result = await runCommand(command, args, {
|
|
282
|
+
cwd: targetPath,
|
|
283
|
+
timeout,
|
|
284
|
+
});
|
|
285
|
+
// Combine output
|
|
286
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
287
|
+
// Parse file count from output (best effort)
|
|
288
|
+
const filesProcessed = parseFormatFileCount(output, formatter.name);
|
|
289
|
+
const formatResult = {
|
|
290
|
+
command: commandString,
|
|
291
|
+
output,
|
|
292
|
+
exitCode: result.exitCode,
|
|
293
|
+
duration: result.duration,
|
|
294
|
+
success: result.exitCode === 0,
|
|
295
|
+
formatter: formatter.name,
|
|
296
|
+
filesProcessed,
|
|
297
|
+
};
|
|
298
|
+
return createSuccessResult(formatResult);
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
return createErrorResult(error instanceof Error ? error.message : String(error));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Parse file count from format output (best effort)
|
|
306
|
+
*/
|
|
307
|
+
function parseFormatFileCount(output, _formatter) {
|
|
308
|
+
// Prettier pattern: "N files changed" or lists files
|
|
309
|
+
const prettierMatch = output.match(/(\d+)\s+files?\s+(changed|formatted)/i);
|
|
310
|
+
if (prettierMatch) {
|
|
311
|
+
return parseInt(prettierMatch[1], 10);
|
|
312
|
+
}
|
|
313
|
+
// Count lines that look like file paths
|
|
314
|
+
const fileLines = output.split('\n').filter((line) => {
|
|
315
|
+
// Skip empty lines and common noise
|
|
316
|
+
const trimmed = line.trim();
|
|
317
|
+
if (!trimmed)
|
|
318
|
+
return false;
|
|
319
|
+
if (trimmed.startsWith('['))
|
|
320
|
+
return false; // Log prefixes
|
|
321
|
+
if (trimmed.startsWith('Checking') || trimmed.startsWith('Formatting'))
|
|
322
|
+
return false;
|
|
323
|
+
// Check if line looks like a file path
|
|
324
|
+
return /\.(ts|tsx|js|jsx|py|rs|go|java|json|md|css|scss|html)$/i.test(trimmed);
|
|
325
|
+
});
|
|
326
|
+
if (fileLines.length > 0) {
|
|
327
|
+
return fileLines.length;
|
|
328
|
+
}
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Factory function to create run format tool with custom options
|
|
333
|
+
*/
|
|
334
|
+
export function createRunFormatTool(options) {
|
|
335
|
+
return defineTool({
|
|
336
|
+
name: 'run_format',
|
|
337
|
+
description: 'Run formatter using the auto-detected formatting tool. ' +
|
|
338
|
+
'Supports Prettier, Biome, dprint, Black, Ruff, rustfmt, gofmt.',
|
|
339
|
+
inputSchema: {
|
|
340
|
+
type: 'object',
|
|
341
|
+
properties: {
|
|
342
|
+
path: {
|
|
343
|
+
type: 'string',
|
|
344
|
+
description: 'Working directory (default: current directory)',
|
|
345
|
+
},
|
|
346
|
+
files: {
|
|
347
|
+
type: 'array',
|
|
348
|
+
items: { type: 'string' },
|
|
349
|
+
description: 'Specific files to format',
|
|
350
|
+
},
|
|
351
|
+
check: {
|
|
352
|
+
type: 'boolean',
|
|
353
|
+
description: "Check only, don't write changes",
|
|
354
|
+
},
|
|
355
|
+
timeout: {
|
|
356
|
+
type: 'number',
|
|
357
|
+
description: 'Timeout in milliseconds',
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
required: [],
|
|
361
|
+
},
|
|
362
|
+
execute: async (input) => {
|
|
363
|
+
let targetPath = input.path ?? '.';
|
|
364
|
+
// Resolve relative paths
|
|
365
|
+
if (options?.baseDir && !targetPath.startsWith('/')) {
|
|
366
|
+
const nodePath = await import('node:path');
|
|
367
|
+
targetPath = nodePath.join(options.baseDir, targetPath);
|
|
368
|
+
}
|
|
369
|
+
return executeRunFormat({
|
|
370
|
+
...input,
|
|
371
|
+
path: targetPath,
|
|
372
|
+
timeout: input.timeout ?? options?.defaultTimeout,
|
|
373
|
+
});
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Runner Tools
|
|
3
|
+
* Auto-detect and run tests, lint, build, and format
|
|
4
|
+
*/
|
|
5
|
+
export { runTestsTool, createRunTestsTool } from './test.js';
|
|
6
|
+
export { runLintTool, createRunLintTool } from './lint.js';
|
|
7
|
+
export { runBuildTool, createRunBuildTool } from './build.js';
|
|
8
|
+
export { runFormatTool, createRunFormatTool } from './format.js';
|
|
9
|
+
export type { BaseRunnerInput, BaseRunnerResult, RunTestsInput, RunTestsResult, RunLintInput, RunLintResult, RunBuildInput, RunBuildResult, RunFormatInput, RunFormatResult, } from './types.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Runner Tools
|
|
3
|
+
* Auto-detect and run tests, lint, build, and format
|
|
4
|
+
*/
|
|
5
|
+
// Tools
|
|
6
|
+
export { runTestsTool, createRunTestsTool } from './test.js';
|
|
7
|
+
export { runLintTool, createRunLintTool } from './lint.js';
|
|
8
|
+
export { runBuildTool, createRunBuildTool } from './build.js';
|
|
9
|
+
export { runFormatTool, createRunFormatTool } from './format.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Lint Tool
|
|
3
|
+
* Auto-detect and run linter using the appropriate tool
|
|
4
|
+
*/
|
|
5
|
+
import type { Tool } from '@compilr-dev/agents';
|
|
6
|
+
import type { RunLintInput } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Run Lint Tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const runLintTool: Tool<RunLintInput>;
|
|
11
|
+
/**
|
|
12
|
+
* Factory function to create run lint tool with custom options
|
|
13
|
+
*/
|
|
14
|
+
export declare function createRunLintTool(options?: {
|
|
15
|
+
/** Base directory for relative paths */
|
|
16
|
+
baseDir?: string;
|
|
17
|
+
/** Default timeout */
|
|
18
|
+
defaultTimeout?: number;
|
|
19
|
+
}): Tool<RunLintInput>;
|