codebot-ai 1.3.0 → 1.4.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 +16 -1
- package/dist/agent.js +23 -1
- package/dist/cli.js +1 -1
- package/dist/providers/anthropic.js +27 -1
- package/dist/providers/openai.d.ts +4 -0
- package/dist/providers/openai.js +54 -2
- package/dist/retry.d.ts +5 -0
- package/dist/retry.js +24 -0
- package/dist/tools/code-analysis.d.ts +33 -0
- package/dist/tools/code-analysis.js +232 -0
- package/dist/tools/code-review.d.ts +32 -0
- package/dist/tools/code-review.js +228 -0
- package/dist/tools/database.d.ts +35 -0
- package/dist/tools/database.js +129 -0
- package/dist/tools/diff-viewer.d.ts +39 -0
- package/dist/tools/diff-viewer.js +145 -0
- package/dist/tools/docker.d.ts +26 -0
- package/dist/tools/docker.js +101 -0
- package/dist/tools/git.d.ts +26 -0
- package/dist/tools/git.js +58 -0
- package/dist/tools/http-client.d.ts +39 -0
- package/dist/tools/http-client.js +114 -0
- package/dist/tools/image-info.d.ts +23 -0
- package/dist/tools/image-info.js +170 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/multi-search.d.ts +28 -0
- package/dist/tools/multi-search.js +153 -0
- package/dist/tools/notification.d.ts +38 -0
- package/dist/tools/notification.js +96 -0
- package/dist/tools/package-manager.d.ts +31 -0
- package/dist/tools/package-manager.js +161 -0
- package/dist/tools/pdf-extract.d.ts +33 -0
- package/dist/tools/pdf-extract.js +178 -0
- package/dist/tools/ssh-remote.d.ts +39 -0
- package/dist/tools/ssh-remote.js +84 -0
- package/dist/tools/task-planner.d.ts +42 -0
- package/dist/tools/task-planner.js +161 -0
- package/dist/tools/test-runner.d.ts +36 -0
- package/dist/tools/test-runner.js +193 -0
- package/package.json +1 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TestRunnerTool = void 0;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
class TestRunnerTool {
|
|
41
|
+
name = 'test_runner';
|
|
42
|
+
description = 'Run tests with auto-detected framework. Actions: run (execute tests), detect (show detected framework), list (list test files).';
|
|
43
|
+
permission = 'prompt';
|
|
44
|
+
parameters = {
|
|
45
|
+
type: 'object',
|
|
46
|
+
properties: {
|
|
47
|
+
action: { type: 'string', description: 'Action: run, detect, list' },
|
|
48
|
+
path: { type: 'string', description: 'Test file or directory (defaults to project root)' },
|
|
49
|
+
filter: { type: 'string', description: 'Test name filter / grep pattern' },
|
|
50
|
+
cwd: { type: 'string', description: 'Working directory' },
|
|
51
|
+
},
|
|
52
|
+
required: ['action'],
|
|
53
|
+
};
|
|
54
|
+
async execute(args) {
|
|
55
|
+
const action = args.action;
|
|
56
|
+
if (!action)
|
|
57
|
+
return 'Error: action is required';
|
|
58
|
+
const cwd = args.cwd || process.cwd();
|
|
59
|
+
switch (action) {
|
|
60
|
+
case 'detect': return this.detectFramework(cwd);
|
|
61
|
+
case 'list': return this.listTestFiles(cwd);
|
|
62
|
+
case 'run': return this.runTests(cwd, args);
|
|
63
|
+
default: return `Error: unknown action "${action}". Use: run, detect, list`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
detectFramework(cwd) {
|
|
67
|
+
const fw = this.detect(cwd);
|
|
68
|
+
if (!fw)
|
|
69
|
+
return 'No test framework detected. Checked for: jest, vitest, mocha, node:test, pytest, go test, cargo test.';
|
|
70
|
+
return `Detected: ${fw.name}\nCommand: ${fw.command}\nTest files: ${fw.filePattern}`;
|
|
71
|
+
}
|
|
72
|
+
listTestFiles(cwd) {
|
|
73
|
+
const patterns = ['**/*.test.*', '**/*.spec.*', '**/test_*.py', '**/*_test.go', '**/tests/**'];
|
|
74
|
+
const files = [];
|
|
75
|
+
const skip = new Set(['node_modules', '.git', 'dist', 'build', 'coverage']);
|
|
76
|
+
this.findTests(cwd, files, skip, 0, 4);
|
|
77
|
+
if (files.length === 0)
|
|
78
|
+
return 'No test files found.';
|
|
79
|
+
return `Test files (${files.length}):\n${files.map(f => ` ${f}`).join('\n')}`;
|
|
80
|
+
}
|
|
81
|
+
runTests(cwd, args) {
|
|
82
|
+
const fw = this.detect(cwd);
|
|
83
|
+
if (!fw)
|
|
84
|
+
return 'Error: no test framework detected';
|
|
85
|
+
let cmd = fw.command;
|
|
86
|
+
const target = args.path;
|
|
87
|
+
const filter = args.filter;
|
|
88
|
+
if (target)
|
|
89
|
+
cmd += ` ${target}`;
|
|
90
|
+
if (filter) {
|
|
91
|
+
if (fw.name.includes('jest') || fw.name.includes('vitest'))
|
|
92
|
+
cmd += ` -t "${filter}"`;
|
|
93
|
+
else if (fw.name === 'pytest')
|
|
94
|
+
cmd += ` -k "${filter}"`;
|
|
95
|
+
else if (fw.name === 'go test')
|
|
96
|
+
cmd += ` -run "${filter}"`;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const output = (0, child_process_1.execSync)(cmd, {
|
|
100
|
+
cwd,
|
|
101
|
+
timeout: 120_000,
|
|
102
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
103
|
+
encoding: 'utf-8',
|
|
104
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
105
|
+
});
|
|
106
|
+
return this.summarize(output, fw.name);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
const e = err;
|
|
110
|
+
const combined = `${e.stdout || ''}\n${e.stderr || ''}`.trim();
|
|
111
|
+
return `Tests failed (exit ${e.status || 1}):\n${this.summarize(combined, fw.name)}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
detect(cwd) {
|
|
115
|
+
// Check package.json for JS/TS projects
|
|
116
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
117
|
+
if (fs.existsSync(pkgPath)) {
|
|
118
|
+
try {
|
|
119
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
120
|
+
const scripts = pkg.scripts || {};
|
|
121
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
122
|
+
if (scripts.test) {
|
|
123
|
+
if (scripts.test.includes('vitest'))
|
|
124
|
+
return { name: 'vitest', command: 'npx vitest run', filePattern: '*.test.ts' };
|
|
125
|
+
if (scripts.test.includes('jest'))
|
|
126
|
+
return { name: 'jest', command: 'npx jest', filePattern: '*.test.ts' };
|
|
127
|
+
if (scripts.test.includes('mocha'))
|
|
128
|
+
return { name: 'mocha', command: 'npx mocha', filePattern: '*.test.ts' };
|
|
129
|
+
if (scripts.test.includes('node --test'))
|
|
130
|
+
return { name: 'node:test', command: scripts.test, filePattern: '*.test.ts' };
|
|
131
|
+
// Generic npm test
|
|
132
|
+
return { name: 'npm test', command: 'npm test', filePattern: '*.test.*' };
|
|
133
|
+
}
|
|
134
|
+
if (deps['vitest'])
|
|
135
|
+
return { name: 'vitest', command: 'npx vitest run', filePattern: '*.test.ts' };
|
|
136
|
+
if (deps['jest'])
|
|
137
|
+
return { name: 'jest', command: 'npx jest', filePattern: '*.test.ts' };
|
|
138
|
+
}
|
|
139
|
+
catch { /* invalid package.json */ }
|
|
140
|
+
}
|
|
141
|
+
// Python
|
|
142
|
+
if (fs.existsSync(path.join(cwd, 'pytest.ini')) || fs.existsSync(path.join(cwd, 'setup.py')) || fs.existsSync(path.join(cwd, 'pyproject.toml'))) {
|
|
143
|
+
return { name: 'pytest', command: 'python -m pytest -v', filePattern: 'test_*.py' };
|
|
144
|
+
}
|
|
145
|
+
// Go
|
|
146
|
+
if (fs.existsSync(path.join(cwd, 'go.mod'))) {
|
|
147
|
+
return { name: 'go test', command: 'go test ./...', filePattern: '*_test.go' };
|
|
148
|
+
}
|
|
149
|
+
// Rust
|
|
150
|
+
if (fs.existsSync(path.join(cwd, 'Cargo.toml'))) {
|
|
151
|
+
return { name: 'cargo test', command: 'cargo test', filePattern: '*.rs' };
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
summarize(output, framework) {
|
|
156
|
+
const lines = output.split('\n');
|
|
157
|
+
const summary = [];
|
|
158
|
+
// Extract pass/fail counts
|
|
159
|
+
for (const line of lines) {
|
|
160
|
+
if (/(?:pass|fail|error|skip|pending|test|ok|FAIL)/i.test(line) && line.trim().length < 200) {
|
|
161
|
+
summary.push(line);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (summary.length > 30) {
|
|
165
|
+
return summary.slice(-30).join('\n') + '\n...(truncated)';
|
|
166
|
+
}
|
|
167
|
+
return summary.length > 0 ? summary.join('\n') : output.substring(0, 2000);
|
|
168
|
+
}
|
|
169
|
+
findTests(dir, files, skip, depth, maxDepth) {
|
|
170
|
+
if (depth >= maxDepth)
|
|
171
|
+
return;
|
|
172
|
+
let entries;
|
|
173
|
+
try {
|
|
174
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
for (const entry of entries) {
|
|
180
|
+
if (entry.name.startsWith('.') || skip.has(entry.name))
|
|
181
|
+
continue;
|
|
182
|
+
const full = path.join(dir, entry.name);
|
|
183
|
+
if (entry.isDirectory()) {
|
|
184
|
+
this.findTests(full, files, skip, depth + 1, maxDepth);
|
|
185
|
+
}
|
|
186
|
+
else if (/\.(test|spec)\.\w+$/.test(entry.name) || /^test_.*\.py$/.test(entry.name) || /_test\.go$/.test(entry.name)) {
|
|
187
|
+
files.push(full);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
exports.TestRunnerTool = TestRunnerTool;
|
|
193
|
+
//# sourceMappingURL=test-runner.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebot-ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Zero-dependency autonomous AI agent. Code, browse, search, automate. Works with any LLM — Ollama, Claude, GPT, Gemini, DeepSeek, Groq, Mistral, Grok.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|