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.
Files changed (40) hide show
  1. package/README.md +16 -1
  2. package/dist/agent.js +23 -1
  3. package/dist/cli.js +1 -1
  4. package/dist/providers/anthropic.js +27 -1
  5. package/dist/providers/openai.d.ts +4 -0
  6. package/dist/providers/openai.js +54 -2
  7. package/dist/retry.d.ts +5 -0
  8. package/dist/retry.js +24 -0
  9. package/dist/tools/code-analysis.d.ts +33 -0
  10. package/dist/tools/code-analysis.js +232 -0
  11. package/dist/tools/code-review.d.ts +32 -0
  12. package/dist/tools/code-review.js +228 -0
  13. package/dist/tools/database.d.ts +35 -0
  14. package/dist/tools/database.js +129 -0
  15. package/dist/tools/diff-viewer.d.ts +39 -0
  16. package/dist/tools/diff-viewer.js +145 -0
  17. package/dist/tools/docker.d.ts +26 -0
  18. package/dist/tools/docker.js +101 -0
  19. package/dist/tools/git.d.ts +26 -0
  20. package/dist/tools/git.js +58 -0
  21. package/dist/tools/http-client.d.ts +39 -0
  22. package/dist/tools/http-client.js +114 -0
  23. package/dist/tools/image-info.d.ts +23 -0
  24. package/dist/tools/image-info.js +170 -0
  25. package/dist/tools/index.js +34 -0
  26. package/dist/tools/multi-search.d.ts +28 -0
  27. package/dist/tools/multi-search.js +153 -0
  28. package/dist/tools/notification.d.ts +38 -0
  29. package/dist/tools/notification.js +96 -0
  30. package/dist/tools/package-manager.d.ts +31 -0
  31. package/dist/tools/package-manager.js +161 -0
  32. package/dist/tools/pdf-extract.d.ts +33 -0
  33. package/dist/tools/pdf-extract.js +178 -0
  34. package/dist/tools/ssh-remote.d.ts +39 -0
  35. package/dist/tools/ssh-remote.js +84 -0
  36. package/dist/tools/task-planner.d.ts +42 -0
  37. package/dist/tools/task-planner.js +161 -0
  38. package/dist/tools/test-runner.d.ts +36 -0
  39. package/dist/tools/test-runner.js +193 -0
  40. package/package.json +1 -1
@@ -0,0 +1,178 @@
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.PdfExtractTool = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ class PdfExtractTool {
40
+ name = 'pdf_extract';
41
+ description = 'Extract text and metadata from PDF files. Actions: text, info, pages.';
42
+ permission = 'auto';
43
+ parameters = {
44
+ type: 'object',
45
+ properties: {
46
+ action: { type: 'string', description: 'Action: text (extract text), info (file info), pages (page count)' },
47
+ path: { type: 'string', description: 'Path to PDF file' },
48
+ max_pages: { type: 'number', description: 'Max pages to extract (default: 10)' },
49
+ },
50
+ required: ['action', 'path'],
51
+ };
52
+ async execute(args) {
53
+ const action = args.action;
54
+ const filePath = args.path;
55
+ if (!action)
56
+ return 'Error: action is required';
57
+ if (!filePath)
58
+ return 'Error: path is required';
59
+ if (!fs.existsSync(filePath))
60
+ return `Error: file not found: ${filePath}`;
61
+ const ext = path.extname(filePath).toLowerCase();
62
+ if (ext !== '.pdf')
63
+ return `Error: not a PDF file (got ${ext})`;
64
+ switch (action) {
65
+ case 'text': return this.extractText(filePath, args);
66
+ case 'info': return this.getInfo(filePath);
67
+ case 'pages': return this.countPages(filePath);
68
+ default: return `Error: unknown action "${action}". Use: text, info, pages`;
69
+ }
70
+ }
71
+ extractText(filePath, args) {
72
+ const maxPages = args.max_pages || 10;
73
+ try {
74
+ const content = fs.readFileSync(filePath);
75
+ const text = this.extractFromBuffer(content, maxPages);
76
+ if (!text.trim()) {
77
+ return 'No extractable text found. The PDF may contain scanned images or use non-standard encoding.';
78
+ }
79
+ return `Extracted text from ${path.basename(filePath)}:\n\n${text}`;
80
+ }
81
+ catch (err) {
82
+ return `Error: ${err instanceof Error ? err.message : 'failed to read PDF'}`;
83
+ }
84
+ }
85
+ getInfo(filePath) {
86
+ const stat = fs.statSync(filePath);
87
+ const sizeMB = (stat.size / (1024 * 1024)).toFixed(2);
88
+ const content = fs.readFileSync(filePath);
89
+ const pages = this.estimatePageCount(content);
90
+ // Extract PDF metadata
91
+ const text = content.toString('latin1');
92
+ const title = this.extractMeta(text, 'Title');
93
+ const author = this.extractMeta(text, 'Author');
94
+ const creator = this.extractMeta(text, 'Creator');
95
+ let result = `File: ${path.basename(filePath)}\nSize: ${sizeMB} MB\nPages: ~${pages}\nModified: ${stat.mtime.toISOString()}`;
96
+ if (title)
97
+ result += `\nTitle: ${title}`;
98
+ if (author)
99
+ result += `\nAuthor: ${author}`;
100
+ if (creator)
101
+ result += `\nCreator: ${creator}`;
102
+ return result;
103
+ }
104
+ countPages(filePath) {
105
+ const content = fs.readFileSync(filePath);
106
+ const pages = this.estimatePageCount(content);
107
+ return `${path.basename(filePath)}: approximately ${pages} page(s)`;
108
+ }
109
+ estimatePageCount(buf) {
110
+ // Count /Type /Page occurrences (not /Pages)
111
+ const text = buf.toString('latin1');
112
+ const matches = text.match(/\/Type\s*\/Page(?!\s*s)/g);
113
+ return matches ? matches.length : 1;
114
+ }
115
+ extractFromBuffer(buf, maxPages) {
116
+ // Simple text extraction — find text between BT/ET markers and decode
117
+ const text = buf.toString('latin1');
118
+ const chunks = [];
119
+ let pageCount = 0;
120
+ // Find stream content
121
+ const streamRegex = /stream\r?\n([\s\S]*?)endstream/g;
122
+ let match;
123
+ while ((match = streamRegex.exec(text)) !== null && pageCount < maxPages) {
124
+ const stream = match[1];
125
+ // Extract text from BT...ET blocks
126
+ const btRegex = /BT\s([\s\S]*?)ET/g;
127
+ let btMatch;
128
+ while ((btMatch = btRegex.exec(stream)) !== null) {
129
+ const block = btMatch[1];
130
+ // Extract text strings in parentheses: (Hello World) Tj
131
+ const tjRegex = /\(([^)]*)\)\s*Tj/g;
132
+ let tjMatch;
133
+ while ((tjMatch = tjRegex.exec(block)) !== null) {
134
+ const decoded = this.decodePdfString(tjMatch[1]);
135
+ if (decoded.trim())
136
+ chunks.push(decoded);
137
+ }
138
+ // Extract TJ arrays: [(text1) 10 (text2)] TJ
139
+ const tjArrayRegex = /\[(.*?)\]\s*TJ/g;
140
+ let arrMatch;
141
+ while ((arrMatch = tjArrayRegex.exec(block)) !== null) {
142
+ const inner = arrMatch[1];
143
+ const strRegex = /\(([^)]*)\)/g;
144
+ let strMatch;
145
+ const parts = [];
146
+ while ((strMatch = strRegex.exec(inner)) !== null) {
147
+ parts.push(this.decodePdfString(strMatch[1]));
148
+ }
149
+ if (parts.length > 0)
150
+ chunks.push(parts.join(''));
151
+ }
152
+ }
153
+ if (chunks.length > 0)
154
+ pageCount++;
155
+ }
156
+ // Clean up and join
157
+ return chunks
158
+ .map(c => c.trim())
159
+ .filter(c => c.length > 0)
160
+ .join('\n')
161
+ .substring(0, 20_000);
162
+ }
163
+ decodePdfString(s) {
164
+ return s
165
+ .replace(/\\n/g, '\n')
166
+ .replace(/\\r/g, '\r')
167
+ .replace(/\\t/g, '\t')
168
+ .replace(/\\\\/g, '\\')
169
+ .replace(/\\([()])/g, '$1');
170
+ }
171
+ extractMeta(text, key) {
172
+ const regex = new RegExp(`/${key}\\s*\\(([^)]*)\\)`);
173
+ const match = text.match(regex);
174
+ return match ? match[1] : null;
175
+ }
176
+ }
177
+ exports.PdfExtractTool = PdfExtractTool;
178
+ //# sourceMappingURL=pdf-extract.js.map
@@ -0,0 +1,39 @@
1
+ import { Tool } from '../types';
2
+ export declare class SshRemoteTool implements Tool {
3
+ name: string;
4
+ description: string;
5
+ permission: Tool['permission'];
6
+ parameters: {
7
+ type: string;
8
+ properties: {
9
+ action: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ host: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ command: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ local_path: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ remote_path: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ port: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ };
34
+ required: string[];
35
+ };
36
+ execute(args: Record<string, unknown>): Promise<string>;
37
+ private runSsh;
38
+ }
39
+ //# sourceMappingURL=ssh-remote.d.ts.map
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SshRemoteTool = void 0;
4
+ const child_process_1 = require("child_process");
5
+ // Block shell injection characters in host/user inputs
6
+ const SAFE_HOST = /^[a-zA-Z0-9._\-@:]+$/;
7
+ class SshRemoteTool {
8
+ name = 'ssh_remote';
9
+ description = 'Execute commands on remote servers via SSH, or upload/download files via SCP. Actions: exec, upload, download.';
10
+ permission = 'always-ask';
11
+ parameters = {
12
+ type: 'object',
13
+ properties: {
14
+ action: { type: 'string', description: 'Action: exec, upload, download' },
15
+ host: { type: 'string', description: 'SSH target (user@hostname or hostname)' },
16
+ command: { type: 'string', description: 'Command to execute remotely (for exec)' },
17
+ local_path: { type: 'string', description: 'Local file path (for upload/download)' },
18
+ remote_path: { type: 'string', description: 'Remote file path (for upload/download)' },
19
+ port: { type: 'number', description: 'SSH port (default: 22)' },
20
+ },
21
+ required: ['action', 'host'],
22
+ };
23
+ async execute(args) {
24
+ const action = args.action;
25
+ const host = args.host;
26
+ if (!action)
27
+ return 'Error: action is required';
28
+ if (!host)
29
+ return 'Error: host is required';
30
+ if (!SAFE_HOST.test(host))
31
+ return 'Error: host contains invalid characters (possible injection)';
32
+ const port = args.port || 22;
33
+ const portFlag = port !== 22 ? `-p ${port}` : '';
34
+ const scpPortFlag = port !== 22 ? `-P ${port}` : '';
35
+ switch (action) {
36
+ case 'exec': {
37
+ const cmd = args.command;
38
+ if (!cmd)
39
+ return 'Error: command is required for exec';
40
+ return this.runSsh(`ssh ${portFlag} -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new ${host} ${JSON.stringify(cmd)}`);
41
+ }
42
+ case 'upload': {
43
+ const local = args.local_path;
44
+ const remote = args.remote_path;
45
+ if (!local || !remote)
46
+ return 'Error: local_path and remote_path are required';
47
+ return this.runSsh(`scp ${scpPortFlag} -o ConnectTimeout=10 "${local}" ${host}:"${remote}"`);
48
+ }
49
+ case 'download': {
50
+ const local = args.local_path;
51
+ const remote = args.remote_path;
52
+ if (!local || !remote)
53
+ return 'Error: local_path and remote_path are required';
54
+ return this.runSsh(`scp ${scpPortFlag} -o ConnectTimeout=10 ${host}:"${remote}" "${local}"`);
55
+ }
56
+ default:
57
+ return `Error: unknown action "${action}". Use: exec, upload, download`;
58
+ }
59
+ }
60
+ runSsh(cmd) {
61
+ try {
62
+ const output = (0, child_process_1.execSync)(cmd, {
63
+ timeout: 60_000,
64
+ maxBuffer: 2 * 1024 * 1024,
65
+ encoding: 'utf-8',
66
+ stdio: ['pipe', 'pipe', 'pipe'],
67
+ });
68
+ return output.trim() || '(no output)';
69
+ }
70
+ catch (err) {
71
+ const e = err;
72
+ const msg = (e.stderr || 'SSH command failed').trim();
73
+ if (msg.includes('Connection refused') || msg.includes('Connection timed out')) {
74
+ return `Error: could not connect to host. ${msg}`;
75
+ }
76
+ if (msg.includes('Permission denied')) {
77
+ return 'Error: authentication failed. Check SSH key or credentials.';
78
+ }
79
+ return `Exit ${e.status || 1}: ${msg}`;
80
+ }
81
+ }
82
+ }
83
+ exports.SshRemoteTool = SshRemoteTool;
84
+ //# sourceMappingURL=ssh-remote.js.map
@@ -0,0 +1,42 @@
1
+ import { Tool } from '../types';
2
+ export declare class TaskPlannerTool implements Tool {
3
+ name: string;
4
+ description: string;
5
+ permission: Tool['permission'];
6
+ parameters: {
7
+ type: string;
8
+ properties: {
9
+ action: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ title: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ id: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ priority: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ status: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ };
30
+ required: string[];
31
+ };
32
+ execute(args: Record<string, unknown>): Promise<string>;
33
+ private addTask;
34
+ private listTasks;
35
+ private updateTask;
36
+ private completeTask;
37
+ private removeTask;
38
+ private clearDone;
39
+ private load;
40
+ private save;
41
+ }
42
+ //# sourceMappingURL=task-planner.d.ts.map
@@ -0,0 +1,161 @@
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.TaskPlannerTool = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const TASKS_DIR = path.join(process.cwd(), '.codebot');
40
+ const TASKS_FILE = path.join(TASKS_DIR, 'tasks.json');
41
+ class TaskPlannerTool {
42
+ name = 'task_planner';
43
+ description = 'Plan and track tasks. Actions: add, list, update, complete, remove, clear.';
44
+ permission = 'auto';
45
+ parameters = {
46
+ type: 'object',
47
+ properties: {
48
+ action: { type: 'string', description: 'Action: add, list, update, complete, remove, clear' },
49
+ title: { type: 'string', description: 'Task title (for add action)' },
50
+ id: { type: 'number', description: 'Task ID (for update/complete/remove)' },
51
+ priority: { type: 'string', description: 'Priority: high, medium, low (default: medium)' },
52
+ status: { type: 'string', description: 'New status for update action' },
53
+ },
54
+ required: ['action'],
55
+ };
56
+ async execute(args) {
57
+ const action = args.action;
58
+ if (!action)
59
+ return 'Error: action is required';
60
+ switch (action) {
61
+ case 'add': return this.addTask(args);
62
+ case 'list': return this.listTasks();
63
+ case 'update': return this.updateTask(args);
64
+ case 'complete': return this.completeTask(args);
65
+ case 'remove': return this.removeTask(args);
66
+ case 'clear': return this.clearDone();
67
+ default: return `Error: unknown action "${action}". Use: add, list, update, complete, remove, clear`;
68
+ }
69
+ }
70
+ addTask(args) {
71
+ const title = args.title;
72
+ if (!title)
73
+ return 'Error: title is required for add';
74
+ const tasks = this.load();
75
+ const id = tasks.length > 0 ? Math.max(...tasks.map(t => t.id)) + 1 : 1;
76
+ const priority = (['high', 'medium', 'low'].includes(args.priority) ? args.priority : 'medium');
77
+ tasks.push({ id, title, status: 'pending', priority, created: new Date().toISOString() });
78
+ this.save(tasks);
79
+ return `Added task #${id}: ${title} [${priority}]`;
80
+ }
81
+ listTasks() {
82
+ const tasks = this.load();
83
+ if (tasks.length === 0)
84
+ return 'No tasks.';
85
+ const icons = { pending: '○', in_progress: '◐', done: '●' };
86
+ const priIcons = { high: '!!!', medium: '!!', low: '!' };
87
+ const lines = tasks.map(t => ` ${icons[t.status] || '○'} #${t.id} [${priIcons[t.priority] || '!!'}] ${t.title} (${t.status})`);
88
+ const pending = tasks.filter(t => t.status === 'pending').length;
89
+ const inProgress = tasks.filter(t => t.status === 'in_progress').length;
90
+ const done = tasks.filter(t => t.status === 'done').length;
91
+ return `Tasks (${pending} pending, ${inProgress} active, ${done} done):\n${lines.join('\n')}`;
92
+ }
93
+ updateTask(args) {
94
+ const id = args.id;
95
+ if (!id)
96
+ return 'Error: id is required for update';
97
+ const tasks = this.load();
98
+ const task = tasks.find(t => t.id === id);
99
+ if (!task)
100
+ return `Error: task #${id} not found`;
101
+ if (args.status && ['pending', 'in_progress', 'done'].includes(args.status)) {
102
+ task.status = args.status;
103
+ if (task.status === 'done')
104
+ task.completed = new Date().toISOString();
105
+ }
106
+ if (args.title)
107
+ task.title = args.title;
108
+ if (args.priority && ['high', 'medium', 'low'].includes(args.priority)) {
109
+ task.priority = args.priority;
110
+ }
111
+ this.save(tasks);
112
+ return `Updated task #${id}: ${task.title} (${task.status})`;
113
+ }
114
+ completeTask(args) {
115
+ const id = args.id;
116
+ if (!id)
117
+ return 'Error: id is required for complete';
118
+ const tasks = this.load();
119
+ const task = tasks.find(t => t.id === id);
120
+ if (!task)
121
+ return `Error: task #${id} not found`;
122
+ task.status = 'done';
123
+ task.completed = new Date().toISOString();
124
+ this.save(tasks);
125
+ return `Completed task #${id}: ${task.title}`;
126
+ }
127
+ removeTask(args) {
128
+ const id = args.id;
129
+ if (!id)
130
+ return 'Error: id is required for remove';
131
+ const tasks = this.load();
132
+ const idx = tasks.findIndex(t => t.id === id);
133
+ if (idx === -1)
134
+ return `Error: task #${id} not found`;
135
+ const removed = tasks.splice(idx, 1)[0];
136
+ this.save(tasks);
137
+ return `Removed task #${id}: ${removed.title}`;
138
+ }
139
+ clearDone() {
140
+ const tasks = this.load();
141
+ const before = tasks.length;
142
+ const remaining = tasks.filter(t => t.status !== 'done');
143
+ this.save(remaining);
144
+ return `Cleared ${before - remaining.length} completed tasks. ${remaining.length} remaining.`;
145
+ }
146
+ load() {
147
+ try {
148
+ if (fs.existsSync(TASKS_FILE)) {
149
+ return JSON.parse(fs.readFileSync(TASKS_FILE, 'utf-8'));
150
+ }
151
+ }
152
+ catch { /* corrupt */ }
153
+ return [];
154
+ }
155
+ save(tasks) {
156
+ fs.mkdirSync(TASKS_DIR, { recursive: true });
157
+ fs.writeFileSync(TASKS_FILE, JSON.stringify(tasks, null, 2) + '\n');
158
+ }
159
+ }
160
+ exports.TaskPlannerTool = TaskPlannerTool;
161
+ //# sourceMappingURL=task-planner.js.map
@@ -0,0 +1,36 @@
1
+ import { Tool } from '../types';
2
+ export declare class TestRunnerTool implements Tool {
3
+ name: string;
4
+ description: string;
5
+ permission: Tool['permission'];
6
+ parameters: {
7
+ type: string;
8
+ properties: {
9
+ action: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ path: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ filter: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ cwd: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ };
26
+ required: string[];
27
+ };
28
+ execute(args: Record<string, unknown>): Promise<string>;
29
+ private detectFramework;
30
+ private listTestFiles;
31
+ private runTests;
32
+ private detect;
33
+ private summarize;
34
+ private findTests;
35
+ }
36
+ //# sourceMappingURL=test-runner.d.ts.map