developer-ai 1.1.0 → 1.1.2

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 (57) hide show
  1. package/dist/cli.js +24 -12
  2. package/dist/cli.js.map +1 -1
  3. package/dist/constants.d.ts +1 -1
  4. package/dist/constants.js +1 -1
  5. package/dist/core/agent.d.ts +10 -0
  6. package/dist/core/agent.d.ts.map +1 -1
  7. package/dist/core/agent.js +74 -6
  8. package/dist/core/agent.js.map +1 -1
  9. package/dist/core/system-prompt.d.ts.map +1 -1
  10. package/dist/core/system-prompt.js +52 -10
  11. package/dist/core/system-prompt.js.map +1 -1
  12. package/dist/skills/loader.d.ts +7 -3
  13. package/dist/skills/loader.d.ts.map +1 -1
  14. package/dist/skills/loader.js +109 -12
  15. package/dist/skills/loader.js.map +1 -1
  16. package/dist/tools/git-commit.d.ts +7 -0
  17. package/dist/tools/git-commit.d.ts.map +1 -0
  18. package/dist/tools/git-commit.js +84 -0
  19. package/dist/tools/git-commit.js.map +1 -0
  20. package/dist/tools/git-diff.d.ts +6 -0
  21. package/dist/tools/git-diff.d.ts.map +1 -0
  22. package/dist/tools/git-diff.js +84 -0
  23. package/dist/tools/git-diff.js.map +1 -0
  24. package/dist/tools/git-status.d.ts +7 -0
  25. package/dist/tools/git-status.d.ts.map +1 -0
  26. package/dist/tools/git-status.js +70 -0
  27. package/dist/tools/git-status.js.map +1 -0
  28. package/dist/tools/index.d.ts.map +1 -1
  29. package/dist/tools/index.js +19 -0
  30. package/dist/tools/index.js.map +1 -1
  31. package/dist/tools/patch-file.d.ts +13 -0
  32. package/dist/tools/patch-file.d.ts.map +1 -0
  33. package/dist/tools/patch-file.js +120 -0
  34. package/dist/tools/patch-file.js.map +1 -0
  35. package/dist/tools/project-detect.d.ts +8 -0
  36. package/dist/tools/project-detect.d.ts.map +1 -0
  37. package/dist/tools/project-detect.js +201 -0
  38. package/dist/tools/project-detect.js.map +1 -0
  39. package/dist/tools/read-file.d.ts.map +1 -1
  40. package/dist/tools/read-file.js +27 -3
  41. package/dist/tools/read-file.js.map +1 -1
  42. package/dist/tools/run-command.d.ts.map +1 -1
  43. package/dist/tools/run-command.js +29 -8
  44. package/dist/tools/run-command.js.map +1 -1
  45. package/dist/tools/stat-file.d.ts +7 -0
  46. package/dist/tools/stat-file.d.ts.map +1 -0
  47. package/dist/tools/stat-file.js +96 -0
  48. package/dist/tools/stat-file.js.map +1 -0
  49. package/dist/tools/test-run.d.ts +7 -0
  50. package/dist/tools/test-run.d.ts.map +1 -0
  51. package/dist/tools/test-run.js +181 -0
  52. package/dist/tools/test-run.js.map +1 -0
  53. package/dist/ui/spinner.d.ts +21 -0
  54. package/dist/ui/spinner.d.ts.map +1 -0
  55. package/dist/ui/spinner.js +76 -0
  56. package/dist/ui/spinner.js.map +1 -0
  57. package/package.json +1 -1
@@ -0,0 +1,96 @@
1
+ import fs from 'node:fs/promises';
2
+ import crypto from 'node:crypto';
3
+ import { z } from 'zod';
4
+ import { resolveSafePath } from './utils.js';
5
+ const schema = z.object({
6
+ path: z.string().describe('Workspace-relative file path'),
7
+ hash: z.boolean().optional().default(false).describe('Compute SHA-256 hash'),
8
+ });
9
+ /**
10
+ * File metadata tool — lets the agent verify reality before/after edits.
11
+ * Returns size, modified time, type, permissions, and optional hash.
12
+ */
13
+ export const statFileTool = {
14
+ name: 'stat_file',
15
+ description: 'Get metadata about a file or directory: size, modified date, type (file/dir/symlink), ' +
16
+ 'and optionally a SHA-256 hash. Use to verify files exist, check sizes, or confirm edits landed.',
17
+ schema,
18
+ jsonSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ path: { type: 'string', description: 'Workspace-relative file path' },
22
+ hash: {
23
+ type: 'boolean',
24
+ description: 'If true, compute and return a SHA-256 content hash (default: false)',
25
+ },
26
+ },
27
+ required: ['path'],
28
+ },
29
+ async execute(input, ctx) {
30
+ const { path: filePath, hash: computeHash } = schema.parse(input);
31
+ const resolved = resolveSafePath(ctx.workspaceDir, filePath);
32
+ if (!resolved) {
33
+ return { success: false, output: '', error: 'Path escapes workspace directory' };
34
+ }
35
+ try {
36
+ const stat = await fs.stat(resolved);
37
+ const type = stat.isDirectory()
38
+ ? 'directory'
39
+ : stat.isSymbolicLink()
40
+ ? 'symlink'
41
+ : stat.isFile()
42
+ ? 'file'
43
+ : 'other';
44
+ const info = {
45
+ path: filePath,
46
+ type,
47
+ size: stat.size,
48
+ sizeHuman: formatBytes(stat.size),
49
+ modified: stat.mtime.toISOString(),
50
+ created: stat.birthtime.toISOString(),
51
+ permissions: `0${(stat.mode & 0o777).toString(8)}`,
52
+ lines: undefined,
53
+ sha256: undefined,
54
+ };
55
+ // For files, compute line count and optional hash
56
+ if (stat.isFile()) {
57
+ const content = await fs.readFile(resolved, 'utf-8').catch(() => null);
58
+ if (content !== null) {
59
+ info['lines'] = content.split('\n').length;
60
+ if (computeHash) {
61
+ info['sha256'] = crypto
62
+ .createHash('sha256')
63
+ .update(content)
64
+ .digest('hex');
65
+ }
66
+ }
67
+ else if (computeHash) {
68
+ // Binary file — hash from buffer
69
+ const buf = await fs.readFile(resolved);
70
+ info['sha256'] = crypto
71
+ .createHash('sha256')
72
+ .update(buf)
73
+ .digest('hex');
74
+ }
75
+ }
76
+ // Clean undefined keys
77
+ const clean = Object.fromEntries(Object.entries(info).filter(([, v]) => v !== undefined));
78
+ return { success: true, output: JSON.stringify(clean, null, 2) };
79
+ }
80
+ catch (err) {
81
+ const message = err.message;
82
+ if (message.includes('ENOENT')) {
83
+ return { success: true, output: JSON.stringify({ path: filePath, exists: false }) };
84
+ }
85
+ return { success: false, output: '', error: `stat failed: ${message}` };
86
+ }
87
+ },
88
+ };
89
+ function formatBytes(bytes) {
90
+ if (bytes < 1024)
91
+ return `${bytes} B`;
92
+ if (bytes < 1024 * 1024)
93
+ return `${(bytes / 1024).toFixed(1)} KB`;
94
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
95
+ }
96
+ //# sourceMappingURL=stat-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-file.js","sourceRoot":"","sources":["../../src/tools/stat-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ToolHandler } from './registry.js';
2
+ /**
3
+ * Test runner tool — auto-detects and runs the project's test suite.
4
+ * Parses failures into structured output for the agent to act on.
5
+ */
6
+ export declare const testRunTool: ToolHandler;
7
+ //# sourceMappingURL=test-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-run.d.ts","sourceRoot":"","sources":["../../src/tools/test-run.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,eAAe,CAAC;AA+E9D;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,WAyGzB,CAAC"}
@@ -0,0 +1,181 @@
1
+ import { execSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { z } from 'zod';
5
+ import { MAX_OUTPUT_LENGTH } from '../constants.js';
6
+ const schema = z.object({
7
+ command: z.string().optional(),
8
+ filter: z.string().optional(),
9
+ coverage: z.boolean().optional().default(false),
10
+ });
11
+ /** Auto-detect the test command for common project types. */
12
+ function detectTestCommand(root) {
13
+ // package.json scripts.test
14
+ const pkgPath = path.join(root, 'package.json');
15
+ if (fs.existsSync(pkgPath)) {
16
+ try {
17
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
18
+ if (pkg.scripts?.test && pkg.scripts.test !== 'echo "Error: no test specified" && exit 1') {
19
+ // Determine package manager
20
+ if (fs.existsSync(path.join(root, 'pnpm-lock.yaml')))
21
+ return 'pnpm test';
22
+ if (fs.existsSync(path.join(root, 'yarn.lock')))
23
+ return 'yarn test';
24
+ if (fs.existsSync(path.join(root, 'bun.lockb')))
25
+ return 'bun test';
26
+ return 'npm test';
27
+ }
28
+ }
29
+ catch { /* ignore */ }
30
+ }
31
+ // Python
32
+ if (fs.existsSync(path.join(root, 'pyproject.toml')) || fs.existsSync(path.join(root, 'pytest.ini'))) {
33
+ return 'python -m pytest -v';
34
+ }
35
+ if (fs.existsSync(path.join(root, 'setup.py'))) {
36
+ return 'python -m pytest -v';
37
+ }
38
+ // Go
39
+ if (fs.existsSync(path.join(root, 'go.mod')))
40
+ return 'go test ./...';
41
+ // Rust
42
+ if (fs.existsSync(path.join(root, 'Cargo.toml')))
43
+ return 'cargo test';
44
+ return null;
45
+ }
46
+ /**
47
+ * Parse structured test failures from common test runner outputs.
48
+ * Returns an array of { file, line, message } objects.
49
+ */
50
+ function parseFailures(output) {
51
+ const failures = [];
52
+ // Jest / Vitest pattern: "● Test Suite > test name" or "FAIL src/file.test.ts"
53
+ const jestFail = /FAIL\s+(.+)/g;
54
+ let m;
55
+ while ((m = jestFail.exec(output)) !== null) {
56
+ failures.push({ file: m[1]?.trim(), message: `FAIL: ${m[1]?.trim()}` });
57
+ }
58
+ // Vitest/Jest assertion errors: "at Object.<anonymous> (src/file.ts:123:45)"
59
+ const stackLine = /at\s+\S+\s+\((.+?):(\d+):\d+\)/g;
60
+ while ((m = stackLine.exec(output)) !== null) {
61
+ failures.push({ file: m[1], line: Number(m[2]), message: `Error at ${m[1]}:${m[2]}` });
62
+ }
63
+ // Pytest pattern: "FAILED tests/test_file.py::test_name"
64
+ const pytestFail = /FAILED\s+(.+?)::(.+)/g;
65
+ while ((m = pytestFail.exec(output)) !== null) {
66
+ failures.push({ file: m[1], message: `FAILED: ${m[1]}::${m[2]}` });
67
+ }
68
+ // Go pattern: "--- FAIL: TestName (0.00s)"
69
+ const goFail = /---\s+FAIL:\s+(\S+)/g;
70
+ while ((m = goFail.exec(output)) !== null) {
71
+ failures.push({ message: `FAIL: ${m[1]}` });
72
+ }
73
+ return failures;
74
+ }
75
+ /**
76
+ * Test runner tool — auto-detects and runs the project's test suite.
77
+ * Parses failures into structured output for the agent to act on.
78
+ */
79
+ export const testRunTool = {
80
+ name: 'test_run',
81
+ description: 'Run the project\'s test suite. Auto-detects the test command (npm test, pytest, go test, cargo test). ' +
82
+ 'Optionally provide a custom command or filter to run specific tests. ' +
83
+ 'Returns structured failure information when tests fail.',
84
+ schema,
85
+ jsonSchema: {
86
+ type: 'object',
87
+ properties: {
88
+ command: {
89
+ type: 'string',
90
+ description: 'Custom test command to run (auto-detected if omitted)',
91
+ },
92
+ filter: {
93
+ type: 'string',
94
+ description: 'Test name filter / pattern to run specific tests',
95
+ },
96
+ coverage: {
97
+ type: 'boolean',
98
+ description: 'Include coverage report if supported (default: false)',
99
+ },
100
+ },
101
+ required: [],
102
+ },
103
+ async execute(input, ctx) {
104
+ const { command: customCmd, filter, coverage } = schema.parse(input);
105
+ let testCmd = customCmd ?? detectTestCommand(ctx.workspaceDir);
106
+ if (!testCmd) {
107
+ return {
108
+ success: false,
109
+ output: '',
110
+ error: 'Could not auto-detect test command. No package.json scripts.test, pytest, go.mod, or Cargo.toml found. ' +
111
+ 'Provide a custom `command` parameter.',
112
+ };
113
+ }
114
+ // Append filter if provided
115
+ if (filter) {
116
+ // Common pattern: append -- --grep or -k or -t depending on runner
117
+ if (testCmd.includes('jest') || testCmd.includes('vitest')) {
118
+ testCmd += ` -- -t "${filter}"`;
119
+ }
120
+ else if (testCmd.includes('pytest')) {
121
+ testCmd += ` -k "${filter}"`;
122
+ }
123
+ else if (testCmd.includes('go test')) {
124
+ testCmd += ` -run "${filter}"`;
125
+ }
126
+ else {
127
+ testCmd += ` ${filter}`;
128
+ }
129
+ }
130
+ // Coverage flag
131
+ if (coverage) {
132
+ if (testCmd.includes('jest') || testCmd.includes('vitest')) {
133
+ testCmd += ' --coverage';
134
+ }
135
+ else if (testCmd.includes('pytest')) {
136
+ testCmd += ' --cov';
137
+ }
138
+ else if (testCmd.includes('go test')) {
139
+ testCmd += ' -cover';
140
+ }
141
+ }
142
+ try {
143
+ const stdout = execSync(testCmd, {
144
+ cwd: ctx.workspaceDir,
145
+ encoding: 'utf-8',
146
+ timeout: 120_000, // Tests can take a while
147
+ maxBuffer: 4 * 1024 * 1024,
148
+ stdio: ['pipe', 'pipe', 'pipe'],
149
+ env: { ...process.env, FORCE_COLOR: '0', CI: 'true' },
150
+ });
151
+ return {
152
+ success: true,
153
+ output: `✅ Tests passed.\n\n${stdout.slice(0, MAX_OUTPUT_LENGTH)}`,
154
+ };
155
+ }
156
+ catch (err) {
157
+ const e = err;
158
+ const combined = `${e.stdout ?? ''}\n${e.stderr ?? ''}`.trim();
159
+ const truncated = combined.slice(0, MAX_OUTPUT_LENGTH);
160
+ // Parse structured failures
161
+ const failures = parseFailures(combined);
162
+ let failureSummary = '';
163
+ if (failures.length > 0) {
164
+ failureSummary = '\n\n📋 Parsed failures:\n' +
165
+ failures
166
+ .slice(0, 20) // cap at 20 failures
167
+ .map((f, i) => {
168
+ const loc = f.file ? ` (${f.file}${f.line ? `:${f.line}` : ''})` : '';
169
+ return ` ${i + 1}. ${f.message}${loc}`;
170
+ })
171
+ .join('\n');
172
+ }
173
+ return {
174
+ success: false,
175
+ output: truncated + failureSummary,
176
+ error: `Tests failed (exit code ${e.status ?? 1})`,
177
+ };
178
+ }
179
+ },
180
+ };
181
+ //# sourceMappingURL=test-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-run.js","sourceRoot":"","sources":["../../src/tools/test-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Terminal shimmer animation for thinking indicators.
3
+ * Creates a gentle left-to-right glow sweep effect using ANSI colours.
4
+ */
5
+ export declare class ShimmerSpinner {
6
+ private interval;
7
+ private frame;
8
+ private readonly text;
9
+ private readonly stream;
10
+ private static readonly PALETTE;
11
+ private static readonly THINKING_FRAMES;
12
+ constructor(text?: string, stream?: NodeJS.WriteStream);
13
+ start(): void;
14
+ stop(clearLine?: boolean): void;
15
+ private render;
16
+ }
17
+ /**
18
+ * Show reasoning/thinking text with a distinct visual style.
19
+ */
20
+ export declare function formatThinking(text: string): string;
21
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAG5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAQ7B;IAEF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAKrC;gBAEU,IAAI,SAAa,EAAE,MAAM,GAAE,MAAM,CAAC,WAA4B;IAK1E,KAAK,IAAI,IAAI;IAUb,IAAI,CAAC,SAAS,UAAO,GAAG,IAAI;IAW5B,OAAO,CAAC,MAAM;CAkBf;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD"}
@@ -0,0 +1,76 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Terminal shimmer animation for thinking indicators.
4
+ * Creates a gentle left-to-right glow sweep effect using ANSI colours.
5
+ */
6
+ export class ShimmerSpinner {
7
+ interval = null;
8
+ frame = 0;
9
+ text;
10
+ stream;
11
+ // Shimmer colour palette — subtle glow sweep
12
+ static PALETTE = [
13
+ chalk.dim.gray,
14
+ chalk.gray,
15
+ chalk.white,
16
+ chalk.bold.white,
17
+ chalk.white,
18
+ chalk.gray,
19
+ chalk.dim.gray,
20
+ ];
21
+ static THINKING_FRAMES = [
22
+ '🧠 Thinking',
23
+ '🧠 Thinking.',
24
+ '🧠 Thinking..',
25
+ '🧠 Thinking...',
26
+ ];
27
+ constructor(text = 'Thinking', stream = process.stderr) {
28
+ this.text = text;
29
+ this.stream = stream;
30
+ }
31
+ start() {
32
+ if (this.interval)
33
+ return;
34
+ this.stream.write('\n');
35
+ this.interval = setInterval(() => {
36
+ this.render();
37
+ this.frame++;
38
+ }, 120);
39
+ }
40
+ stop(clearLine = true) {
41
+ if (!this.interval)
42
+ return;
43
+ clearInterval(this.interval);
44
+ this.interval = null;
45
+ if (clearLine) {
46
+ // Clear the spinner line
47
+ this.stream.write('\r\x1b[2K');
48
+ }
49
+ }
50
+ render() {
51
+ const palette = ShimmerSpinner.PALETTE;
52
+ const paletteLen = palette.length;
53
+ // Build the shimmer text character by character
54
+ const dots = ShimmerSpinner.THINKING_FRAMES[this.frame % 4];
55
+ let shimmer = '';
56
+ for (let i = 0; i < dots.length; i++) {
57
+ const char = dots[i];
58
+ // Each character gets a colour based on its position + current frame offset
59
+ const colourIdx = (i + this.frame) % paletteLen;
60
+ const colourFn = palette[colourIdx];
61
+ shimmer += colourFn(char);
62
+ }
63
+ this.stream.write(`\r\x1b[2K ${shimmer}`);
64
+ }
65
+ }
66
+ /**
67
+ * Show reasoning/thinking text with a distinct visual style.
68
+ */
69
+ export function formatThinking(text) {
70
+ const border = chalk.dim.magenta('│');
71
+ const header = chalk.dim.magenta('┌─ 💭 Reasoning ─────────────────');
72
+ const footer = chalk.dim.magenta('└────────────────────────────────');
73
+ const lines = text.split('\n').map((line) => `${border} ${chalk.dim.italic(line)}`);
74
+ return `${header}\n${lines.join('\n')}\n${footer}`;
75
+ }
76
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "developer-ai",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "A production-grade terminal AI coding assistant. Supports OpenAI and Ollama, MCP servers, web search, and agent skills.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",