koneck 1.0.3 → 2.1.0

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 (72) hide show
  1. package/dist/auto-docs.d.ts +4 -0
  2. package/dist/auto-docs.d.ts.map +1 -0
  3. package/dist/auto-docs.js +57 -0
  4. package/dist/auto-docs.js.map +1 -0
  5. package/dist/chat.d.ts.map +1 -1
  6. package/dist/chat.js +290 -0
  7. package/dist/chat.js.map +1 -1
  8. package/dist/code-graph.d.ts +14 -0
  9. package/dist/code-graph.d.ts.map +1 -0
  10. package/dist/code-graph.js +167 -0
  11. package/dist/code-graph.js.map +1 -0
  12. package/dist/critique.d.ts +4 -0
  13. package/dist/critique.d.ts.map +1 -0
  14. package/dist/critique.js +36 -0
  15. package/dist/critique.js.map +1 -0
  16. package/dist/daemon.d.ts +3 -0
  17. package/dist/daemon.d.ts.map +1 -0
  18. package/dist/daemon.js +111 -0
  19. package/dist/daemon.js.map +1 -0
  20. package/dist/debugger.d.ts +4 -0
  21. package/dist/debugger.d.ts.map +1 -0
  22. package/dist/debugger.js +104 -0
  23. package/dist/debugger.js.map +1 -0
  24. package/dist/engine.d.ts +5 -0
  25. package/dist/engine.d.ts.map +1 -1
  26. package/dist/engine.js +22 -5
  27. package/dist/engine.js.map +1 -1
  28. package/dist/health.d.ts +2 -0
  29. package/dist/health.d.ts.map +1 -0
  30. package/dist/health.js +201 -0
  31. package/dist/health.js.map +1 -0
  32. package/dist/index.js +167 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/issues.d.ts +3 -0
  35. package/dist/issues.d.ts.map +1 -0
  36. package/dist/issues.js +77 -0
  37. package/dist/issues.js.map +1 -0
  38. package/dist/knowledge-graph.d.ts +3 -0
  39. package/dist/knowledge-graph.d.ts.map +1 -0
  40. package/dist/knowledge-graph.js +85 -0
  41. package/dist/knowledge-graph.js.map +1 -0
  42. package/dist/memory.d.ts +7 -0
  43. package/dist/memory.d.ts.map +1 -1
  44. package/dist/memory.js +89 -2
  45. package/dist/memory.js.map +1 -1
  46. package/dist/pipeline.d.ts +3 -0
  47. package/dist/pipeline.d.ts.map +1 -0
  48. package/dist/pipeline.js +79 -0
  49. package/dist/pipeline.js.map +1 -0
  50. package/dist/plugin-packs.d.ts +14 -0
  51. package/dist/plugin-packs.d.ts.map +1 -0
  52. package/dist/plugin-packs.js +136 -0
  53. package/dist/plugin-packs.js.map +1 -0
  54. package/dist/reasoning-cache.d.ts +9 -0
  55. package/dist/reasoning-cache.d.ts.map +1 -0
  56. package/dist/reasoning-cache.js +67 -0
  57. package/dist/reasoning-cache.js.map +1 -0
  58. package/dist/recon.d.ts +2 -0
  59. package/dist/recon.d.ts.map +1 -0
  60. package/dist/recon.js +121 -0
  61. package/dist/recon.js.map +1 -0
  62. package/dist/refactor.d.ts +10 -0
  63. package/dist/refactor.d.ts.map +1 -0
  64. package/dist/refactor.js +182 -0
  65. package/dist/refactor.js.map +1 -0
  66. package/dist/test-gen.d.ts +3 -0
  67. package/dist/test-gen.d.ts.map +1 -0
  68. package/dist/test-gen.js +136 -0
  69. package/dist/test-gen.js.map +1 -0
  70. package/dist/types.d.ts +16 -0
  71. package/dist/types.d.ts.map +1 -1
  72. package/package.json +2 -2
@@ -0,0 +1,167 @@
1
+ import { readFile, writeFile, mkdir } from 'fs/promises';
2
+ import { existsSync } from 'fs';
3
+ import path from 'path';
4
+ import { Project, SyntaxKind } from 'ts-morph';
5
+ import ora from 'ora';
6
+ import { execa } from 'execa';
7
+ function graphPath(cwd) {
8
+ return path.join(cwd, '.koneck', 'code-graph.json');
9
+ }
10
+ async function loadGraph(cwd) {
11
+ const p = graphPath(cwd);
12
+ if (!existsSync(p))
13
+ return null;
14
+ try {
15
+ return JSON.parse(await readFile(p, 'utf-8'));
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ export async function buildCodeGraph(cwd) {
22
+ const spinner = ora('Building code graph…').start();
23
+ const project = new Project({
24
+ skipAddingFilesFromTsConfig: true,
25
+ compilerOptions: { skipLibCheck: true, noEmit: true },
26
+ });
27
+ project.addSourceFilesAtPaths([
28
+ `${cwd}/**/*.ts`,
29
+ `!${cwd}/node_modules/**`,
30
+ `!${cwd}/dist/**`,
31
+ `!${cwd}/.koneck/**`,
32
+ ]);
33
+ const sourceFiles = project.getSourceFiles();
34
+ const symbols = [];
35
+ const callMap = new Map();
36
+ for (const sf of sourceFiles) {
37
+ const file = path.relative(cwd, sf.getFilePath());
38
+ spinner.text = `Indexing ${file}`;
39
+ try {
40
+ // Functions
41
+ for (const fn of sf.getFunctions()) {
42
+ const name = fn.getName() ?? '<anonymous>';
43
+ const callees = new Set();
44
+ fn.getDescendantsOfKind(SyntaxKind.CallExpression).forEach(ce => {
45
+ const leaf = ce.getExpression().getText().split('.').pop()?.trim();
46
+ if (leaf)
47
+ callees.add(leaf);
48
+ });
49
+ callMap.set(name, callees);
50
+ symbols.push({
51
+ name, kind: 'function', file,
52
+ line: fn.getStartLineNumber(),
53
+ exported: fn.isExported(),
54
+ calls: [...callees],
55
+ });
56
+ }
57
+ // Classes
58
+ for (const cls of sf.getClasses()) {
59
+ const name = cls.getName() ?? '<anonymous>';
60
+ symbols.push({ name, kind: 'class', file, line: cls.getStartLineNumber(), exported: cls.isExported() });
61
+ }
62
+ // Interfaces
63
+ for (const iface of sf.getInterfaces()) {
64
+ symbols.push({ name: iface.getName(), kind: 'interface', file, line: iface.getStartLineNumber(), exported: iface.isExported() });
65
+ }
66
+ // Type aliases
67
+ for (const ta of sf.getTypeAliases()) {
68
+ symbols.push({ name: ta.getName(), kind: 'type', file, line: ta.getStartLineNumber(), exported: ta.isExported() });
69
+ }
70
+ // Exported variable declarations
71
+ for (const vd of sf.getVariableDeclarations()) {
72
+ const stmt = vd.getVariableStatement();
73
+ if (stmt?.isExported()) {
74
+ symbols.push({ name: vd.getName(), kind: 'variable', file, line: vd.getStartLineNumber(), exported: true });
75
+ }
76
+ }
77
+ }
78
+ catch {
79
+ // skip unparseable file
80
+ }
81
+ }
82
+ // Build calledBy reverse index
83
+ const calledByMap = new Map();
84
+ for (const [caller, callees] of callMap) {
85
+ for (const callee of callees) {
86
+ if (!calledByMap.has(callee))
87
+ calledByMap.set(callee, new Set());
88
+ calledByMap.get(callee).add(caller);
89
+ }
90
+ }
91
+ for (const sym of symbols) {
92
+ const cb = calledByMap.get(sym.name);
93
+ if (cb?.size)
94
+ sym.calledBy = [...cb];
95
+ }
96
+ const data = { builtAt: new Date().toISOString(), cwd, symbols };
97
+ await mkdir(path.join(cwd, '.koneck'), { recursive: true });
98
+ await writeFile(graphPath(cwd), JSON.stringify(data, null, 2));
99
+ spinner.succeed(`Code graph built — ${symbols.length} symbols indexed`);
100
+ }
101
+ export async function findUsages(symbolName, cwd) {
102
+ let graph = await loadGraph(cwd);
103
+ if (!graph) {
104
+ await buildCodeGraph(cwd);
105
+ graph = await loadGraph(cwd);
106
+ }
107
+ const results = [];
108
+ if (graph) {
109
+ for (const sym of graph.symbols) {
110
+ if (sym.name === symbolName) {
111
+ results.push(`${sym.file}:${sym.line} — definition (${sym.kind})`);
112
+ }
113
+ else if (sym.calls?.includes(symbolName)) {
114
+ results.push(`${sym.file}:${sym.line} — called by ${sym.name}`);
115
+ }
116
+ }
117
+ }
118
+ if (results.length === 0) {
119
+ try {
120
+ const { stdout } = await execa('grep', [
121
+ '-rn', symbolName, cwd,
122
+ '--include=*.ts',
123
+ '--exclude-dir=node_modules',
124
+ '--exclude-dir=dist',
125
+ '--exclude-dir=.koneck',
126
+ ]);
127
+ for (const line of stdout.split('\n').filter(Boolean)) {
128
+ const colonIdx = line.indexOf(':');
129
+ const rest = line.slice(colonIdx + 1);
130
+ const lineNoIdx = rest.indexOf(':');
131
+ const file = path.relative(cwd, line.slice(0, colonIdx));
132
+ const lineNo = rest.slice(0, lineNoIdx);
133
+ const context = rest.slice(lineNoIdx + 1).trim();
134
+ results.push(`${file}:${lineNo} — ${context}`);
135
+ }
136
+ }
137
+ catch {
138
+ // grep found nothing or is unavailable
139
+ }
140
+ }
141
+ return results;
142
+ }
143
+ export async function getCallGraph(cwd) {
144
+ let graph = await loadGraph(cwd);
145
+ if (!graph) {
146
+ await buildCodeGraph(cwd);
147
+ graph = await loadGraph(cwd);
148
+ }
149
+ if (!graph)
150
+ return '(no graph available)';
151
+ const top = graph.symbols
152
+ .filter(s => s.calls?.length || s.calledBy?.length)
153
+ .map(s => ({ s, score: (s.calls?.length ?? 0) + (s.calledBy?.length ?? 0) }))
154
+ .sort((a, b) => b.score - a.score)
155
+ .slice(0, 20);
156
+ return top
157
+ .map(({ s }) => `${s.name} → [${(s.calls ?? []).join(', ')}]`)
158
+ .join('\n');
159
+ }
160
+ export async function queryGraph(query, cwd) {
161
+ const graph = await loadGraph(cwd);
162
+ if (!graph)
163
+ return [];
164
+ const q = query.toLowerCase();
165
+ return graph.symbols.filter(s => s.name.toLowerCase().includes(q));
166
+ }
167
+ //# sourceMappingURL=code-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-graph.js","sourceRoot":"","sources":["../src/code-graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Message, AgentConfig, TokenStats } from './types.js';
2
+ export declare function detectFileWrites(messages: Message[]): boolean;
3
+ export declare function runSelfCritique(messages: Message[], config: AgentConfig, cwd: string, stats: TokenStats, hadFileWrites: boolean): Promise<void>;
4
+ //# sourceMappingURL=critique.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critique.d.ts","sourceRoot":"","sources":["../src/critique.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAInE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAO7D;AAUD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,UAAU,EACjB,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAiBf"}
@@ -0,0 +1,36 @@
1
+ import chalk from 'chalk';
2
+ // NOTE: runReActLoop must be exported from engine.ts
3
+ import { buildClient, runReActLoop } from './engine.js';
4
+ import { TOOL_DEFINITIONS } from './tools.js';
5
+ const WRITE_TOOLS = new Set(['write_file', 'apply_diff', 'delete_file', 'move_file']);
6
+ export function detectFileWrites(messages) {
7
+ for (const m of messages) {
8
+ if (m.role !== 'assistant')
9
+ continue;
10
+ const msg = m;
11
+ if (msg.tool_calls?.some(tc => WRITE_TOOLS.has(tc.function?.name ?? '')))
12
+ return true;
13
+ }
14
+ return false;
15
+ }
16
+ const CRITIQUE_PROMPT = 'Self-critique: review your work so far.\n' +
17
+ 'Check: (1) Did you update tests for changed code? (2) Could this introduce bugs or regressions? ' +
18
+ '(3) Did you update docs/comments? (4) Could this break the API or existing callers? ' +
19
+ '(5) Any TODOs left incomplete? (6) Any obvious lint/type errors?\n' +
20
+ 'If you find issues, fix them now using the available tools. ' +
21
+ 'If everything looks good, respond with exactly: "Self-critique: all clear."';
22
+ export async function runSelfCritique(messages, config, cwd, stats, hadFileWrites) {
23
+ if (!hadFileWrites)
24
+ return;
25
+ console.log(chalk.cyan('\n── Self-critique phase ──'));
26
+ messages.push({ role: 'user', content: CRITIQUE_PROMPT });
27
+ const client = buildClient(config);
28
+ const critiqueConfig = { ...config, maxTurns: 6 };
29
+ const openaiTools = TOOL_DEFINITIONS.map(def => ({
30
+ type: 'function',
31
+ function: { name: def.name, description: def.description, parameters: def.parameters },
32
+ }));
33
+ await runReActLoop(messages, client, critiqueConfig, cwd, stats, [], [], openaiTools);
34
+ console.log(chalk.cyan('Self-critique complete.'));
35
+ }
36
+ //# sourceMappingURL=critique.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critique.js","sourceRoot":"","sources":["../src/critique.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,qDAAqD;AACrD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;AAEtF,MAAM,UAAU,gBAAgB,CAAC,QAAmB;IAClD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS;QACrC,MAAM,GAAG,GAAG,CAA6D,CAAC;QAC1E,IAAI,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IACxF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,eAAe,GACnB,2CAA2C;IAC3C,kGAAkG;IAClG,sFAAsF;IACtF,oEAAoE;IACpE,8DAA8D;IAC9D,6EAA6E,CAAC;AAEhF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAmB,EACnB,MAAmB,EACnB,GAAW,EACX,KAAiB,EACjB,aAAsB;IAEtB,IAAI,CAAC,aAAa;QAAE,OAAO;IAE3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAEvD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,cAAc,GAAgB,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC/D,MAAM,WAAW,GAAqC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjF,IAAI,EAAE,UAAmB;QACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;KACvF,CAAC,CAAC,CAAC;IAEJ,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;IAEtF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AgentConfig } from './types.js';
2
+ export declare function runDaemon(action: 'start' | 'stop' | 'status', config: AgentConfig): Promise<void>;
3
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAmD9C,wBAAsB,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA8CvG"}
package/dist/daemon.js ADDED
@@ -0,0 +1,111 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { execa } from 'execa';
4
+ import chalk from 'chalk';
5
+ import { runAgent } from './engine.js';
6
+ const PID_FILE = '.koneck/daemon.pid';
7
+ function readPid() {
8
+ try {
9
+ return JSON.parse(fs.readFileSync(PID_FILE, 'utf8'));
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ function writePid(pid) {
16
+ fs.mkdirSync('.koneck', { recursive: true });
17
+ fs.writeFileSync(PID_FILE, JSON.stringify({ pid, startTime: Date.now() }));
18
+ }
19
+ function deletePid() {
20
+ try {
21
+ fs.unlinkSync(PID_FILE);
22
+ }
23
+ catch { /* already gone */ }
24
+ }
25
+ function isAlive(pid) {
26
+ try {
27
+ process.kill(pid, 0);
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ async function reviewCommit(config) {
35
+ const { stdout: commitInfo } = await execa('git', ['log', '-1', '--format=%H %s']);
36
+ const { stdout: diffStat } = await execa('git', ['diff', 'HEAD~1', '--stat']);
37
+ const task = `Review this commit and suggest improvements. Commit: ${commitInfo}\nChanged files:\n${diffStat}\n\nCheck for: bugs, security issues, missing tests, documentation needs. Be concise.`;
38
+ console.log(chalk.cyan('\n── Commit Review ──────────────────────────────'));
39
+ await runAgent(task, { ...config, silent: false });
40
+ console.log(chalk.cyan('────────────────────────────────────────────────\n'));
41
+ }
42
+ async function runCICheck(config) {
43
+ try {
44
+ await execa('npm', ['test'], { cwd: config.cwd });
45
+ }
46
+ catch (err) {
47
+ const output = err.stderr ?? err.stdout ?? '';
48
+ const task = `npm test is failing. Fix the failing tests.\n\nTest output:\n${output}`;
49
+ console.log(chalk.red('\n── CI Failure — Auto-fixing ───────────────────'));
50
+ await runAgent(task, { ...config, silent: false });
51
+ console.log(chalk.red('────────────────────────────────────────────────\n'));
52
+ }
53
+ }
54
+ export async function runDaemon(action, config) {
55
+ if (action === 'stop') {
56
+ const entry = readPid();
57
+ if (!entry) {
58
+ console.log('No daemon running.');
59
+ return;
60
+ }
61
+ try {
62
+ process.kill(entry.pid, 'SIGTERM');
63
+ }
64
+ catch { /* already dead */ }
65
+ deletePid();
66
+ console.log('Daemon stopped.');
67
+ return;
68
+ }
69
+ if (action === 'status') {
70
+ const entry = readPid();
71
+ if (!entry) {
72
+ console.log('Daemon is not running.');
73
+ return;
74
+ }
75
+ if (!isAlive(entry.pid)) {
76
+ console.log('Daemon PID file exists but process is dead.');
77
+ deletePid();
78
+ return;
79
+ }
80
+ const uptime = Math.floor((Date.now() - entry.startTime) / 1000);
81
+ console.log(chalk.green(`Daemon running (PID: ${entry.pid}, uptime: ${uptime}s)`));
82
+ return;
83
+ }
84
+ // start
85
+ writePid(process.pid);
86
+ console.log(chalk.green(`Daemon started (PID: ${process.pid}). Watching for commits...`));
87
+ let debounceTimer = null;
88
+ const commitMsgPath = path.join(config.cwd, '.git', 'COMMIT_EDITMSG');
89
+ try {
90
+ fs.watch(path.join(config.cwd, '.git'), (_, filename) => {
91
+ if (filename !== 'COMMIT_EDITMSG')
92
+ return;
93
+ if (debounceTimer)
94
+ clearTimeout(debounceTimer);
95
+ debounceTimer = setTimeout(() => {
96
+ reviewCommit(config).catch((e) => console.error('Review error:', e));
97
+ }, 2000);
98
+ });
99
+ }
100
+ catch {
101
+ console.error(chalk.red('Could not watch .git directory — is this a git repo?'));
102
+ }
103
+ // CI check every 30 minutes
104
+ setInterval(() => {
105
+ runCICheck(config).catch((e) => console.error('CI check error:', e));
106
+ }, 30 * 60 * 1000);
107
+ process.on('SIGTERM', () => { deletePid(); process.exit(0); });
108
+ process.stdin.resume();
109
+ void commitMsgPath; // referenced to satisfy linters
110
+ }
111
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AgentConfig } from './types.js';
2
+ export declare function runDebugger(config: AgentConfig, startCommand?: string): Promise<void>;
3
+ export declare function analyzeError(errorOutput: string, config: AgentConfig): Promise<void>;
4
+ //# sourceMappingURL=debugger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugger.d.ts","sourceRoot":"","sources":["../src/debugger.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAwE9C,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B3F;AAED,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAa1F"}
@@ -0,0 +1,104 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import readline from 'readline';
4
+ import chalk from 'chalk';
5
+ import { execa } from 'execa';
6
+ import { runAgent } from './engine.js';
7
+ import { detectProject } from './project.js';
8
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
9
+ async function findStartCommand(cwd) {
10
+ try {
11
+ const raw = await fs.readFile(path.join(cwd, 'package.json'), 'utf8');
12
+ const pkg = JSON.parse(raw);
13
+ const scripts = pkg.scripts ?? {};
14
+ for (const key of ['start', 'dev', 'serve']) {
15
+ if (scripts[key])
16
+ return `npm run ${key}`;
17
+ }
18
+ }
19
+ catch {
20
+ // no package.json or parse error — fall through to prompt
21
+ }
22
+ // Also check project info for a run command
23
+ const info = await detectProject(cwd);
24
+ if (info.runCommand)
25
+ return info.runCommand;
26
+ return new Promise((resolve) => {
27
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
28
+ rl.question('What command runs your app? ', (answer) => {
29
+ rl.close();
30
+ resolve(answer.trim());
31
+ });
32
+ });
33
+ }
34
+ function extractStackTrace(output) {
35
+ const lines = output.split('\n');
36
+ const matched = [];
37
+ lines.forEach((line, i) => {
38
+ if (/^\s+at /.test(line) ||
39
+ /\b(Error|TypeError|ReferenceError|SyntaxError|Exception):/i.test(line) ||
40
+ /File ".+?"/.test(line) ||
41
+ /\.(ts|js):\d+/.test(line)) {
42
+ matched.push(i);
43
+ }
44
+ });
45
+ if (matched.length === 0)
46
+ return output.slice(0, 2000);
47
+ const first = Math.max(0, matched[0] - 5);
48
+ const last = Math.min(lines.length - 1, matched[matched.length - 1] + 5);
49
+ return lines.slice(first, Math.min(last + 1, first + 50)).join('\n');
50
+ }
51
+ function buildDebugTask(command, crashOutput, stackTrace) {
52
+ return `The application crashed. Analyze the error and fix it.
53
+
54
+ Command run: ${command}
55
+
56
+ Crash output:
57
+ ${crashOutput.slice(0, 3000)}
58
+
59
+ Stack trace (extracted):
60
+ ${stackTrace}
61
+
62
+ Steps:
63
+ 1. Read the source files mentioned in the stack trace
64
+ 2. Identify the root cause
65
+ 3. Apply a fix
66
+ 4. Run the app again to verify it works`;
67
+ }
68
+ // ─── Exports ─────────────────────────────────────────────────────────────────
69
+ export async function runDebugger(config, startCommand) {
70
+ const command = startCommand ?? (await findStartCommand(config.cwd));
71
+ console.log(chalk.bold.cyan('\n━━━ AI Debugger ━━━━━━━━━━━━━━━━━━━━━━━'));
72
+ console.log(chalk.white(`Command: ${command}`));
73
+ const [bin, ...args] = command.split(' ');
74
+ const result = await execa(bin, args, {
75
+ all: true,
76
+ reject: false,
77
+ timeout: 30_000,
78
+ cwd: config.cwd,
79
+ });
80
+ if (result.exitCode === 0) {
81
+ console.log(chalk.green('App ran successfully — no crash detected.'));
82
+ return;
83
+ }
84
+ const output = result.all ?? '';
85
+ console.log(chalk.red(`Exit code: ${result.exitCode}`));
86
+ console.log(chalk.yellow('Analyzing crash...\n'));
87
+ const stackTrace = extractStackTrace(output);
88
+ const debugTask = buildDebugTask(command, output, stackTrace);
89
+ await runAgent(debugTask, { ...config, maxTurns: 20 });
90
+ }
91
+ export async function analyzeError(errorOutput, config) {
92
+ const task = `The user has pasted an error message. Diagnose the root cause and apply a fix.
93
+
94
+ Error output:
95
+ ${errorOutput}
96
+
97
+ Steps:
98
+ 1. Read any source files referenced in the error
99
+ 2. Identify the root cause
100
+ 3. Apply a fix
101
+ 4. If possible, run the app to verify it works`;
102
+ await runAgent(task, { ...config, maxTurns: 20 });
103
+ }
104
+ //# sourceMappingURL=debugger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugger.js","sourceRoot":"","sources":["../src/debugger.ts"],"names":[],"mappings":"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"}
package/dist/engine.d.ts CHANGED
@@ -1,4 +1,9 @@
1
+ import OpenAI from 'openai';
2
+ import { type PluginEntry } from './plugins.js';
3
+ import { type MCPClientEntry } from './mcp.js';
1
4
  import type { Message, AgentConfig, TokenStats } from './types.js';
5
+ export declare function buildClient(config: AgentConfig): OpenAI;
6
+ export declare function runReActLoop(messages: Message[], client: OpenAI, config: AgentConfig, effectiveCwd: string, stats: TokenStats, mcpClients: MCPClientEntry[], plugins: PluginEntry[], openaiTools: OpenAI.Chat.ChatCompletionTool[], turnOffset?: number, abortSignal?: AbortSignal): Promise<boolean>;
2
7
  export interface AgentSession {
3
8
  readonly id: string;
4
9
  readonly messages: Message[];
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EAEX,UAAU,EAIX,MAAM,YAAY,CAAC;AAubpB,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE,GAC1B,OAAO,CAAC,YAAY,CAAC,CA2CvB;AAID,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE,GAC1B,OAAO,CAAC,YAAY,CAAC,CAwDvB"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAY5B,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAIlB,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EAEX,UAAU,EAIX,MAAM,YAAY,CAAC;AAIpB,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAQvD;AAsMD,wBAAsB,YAAY,CAChC,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,cAAc,EAAE,EAC5B,OAAO,EAAE,WAAW,EAAE,EACtB,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAC7C,UAAU,SAAI,EACd,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,OAAO,CAAC,CAsNlB;AAID,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE,GAC1B,OAAO,CAAC,YAAY,CAAC,CA6CvB;AAID,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE,GAC1B,OAAO,CAAC,YAAY,CAAC,CAuEvB"}
package/dist/engine.js CHANGED
@@ -12,8 +12,11 @@ import { detectProject, loadAgentInstructions, projectSummary } from './project.
12
12
  import { estimateCost, formatCost } from './pricing.js';
13
13
  import { loadPlugins, callPlugin } from './plugins.js';
14
14
  import { loadMCPConfig, connectMCPServers, callMCPTool, } from './mcp.js';
15
+ import { gatherRecon } from './recon.js';
16
+ import { runSelfCritique, detectFileWrites } from './critique.js';
17
+ import { getPackSystemPrompt } from './plugin-packs.js';
15
18
  // ─── Client ──────────────────────────────────────────────────────────────────
16
- function buildClient(config) {
19
+ export function buildClient(config) {
17
20
  const provider = resolveProvider(config.provider, config.baseURL);
18
21
  const apiKey = getApiKey(provider, config.apiKey);
19
22
  return new OpenAI({
@@ -182,7 +185,7 @@ async function handleSpawnAgents(args, config, cwd) {
182
185
  .join('\n\n');
183
186
  }
184
187
  // ─── ReAct loop ───────────────────────────────────────────────────────────────
185
- async function runReActLoop(messages, client, config, effectiveCwd, stats, mcpClients, plugins, openaiTools, turnOffset = 0, abortSignal) {
188
+ export async function runReActLoop(messages, client, config, effectiveCwd, stats, mcpClients, plugins, openaiTools, turnOffset = 0, abortSignal) {
186
189
  const silent = Boolean(config.silent);
187
190
  const seenSignatures = new Set();
188
191
  let budgetWarned = false;
@@ -408,13 +411,15 @@ export async function createAgentSession(config, initialMessages) {
408
411
  const stats = { promptTokens: 0, completionTokens: 0, totalTokens: 0, turns: 0 };
409
412
  const messages = initialMessages ? [...initialMessages] : [];
410
413
  if (!initialMessages) {
411
- const [ctx, memory, project, agentInstructions] = await Promise.all([
414
+ const [ctx, memory, project, agentInstructions, packPrompt] = await Promise.all([
412
415
  discoverEnvironment(config.cwd),
413
416
  loadMemory(config.cwd),
414
417
  detectProject(config.cwd),
415
418
  loadAgentInstructions(config.cwd),
419
+ getPackSystemPrompt(config.cwd).catch(() => ''),
416
420
  ]);
417
- messages.push({ role: 'system', content: buildSystemPrompt(ctx, memory, project, agentInstructions) });
421
+ const basePrompt = buildSystemPrompt(ctx, memory, project, agentInstructions);
422
+ messages.push({ role: 'system', content: packPrompt ? basePrompt + '\n\n' + packPrompt : basePrompt });
418
423
  }
419
424
  // Load MCP and plugins only at top level (spawnDepth === 0)
420
425
  const isTopLevel = (config.spawnDepth ?? 0) === 0;
@@ -469,7 +474,19 @@ export async function runAgent(task, config, initialMessages) {
469
474
  tui.printThinking('');
470
475
  }
471
476
  const agentStart = Date.now();
472
- await session.send(task);
477
+ // Evidence-first recon: gather context before the first LLM call
478
+ let enrichedTask = task;
479
+ if (!config.silent && !config.ci && (config.spawnDepth ?? 0) === 0) {
480
+ const reconContext = await gatherRecon(task, effectiveCwd);
481
+ if (reconContext)
482
+ enrichedTask = reconContext + '\n\nTask: ' + task;
483
+ }
484
+ await session.send(enrichedTask);
485
+ // Self-critique: one review pass if files were changed
486
+ if (!config.silent && !config.ci && (config.spawnDepth ?? 0) === 0) {
487
+ const hadWrites = detectFileWrites(session.messages);
488
+ await runSelfCritique(session.messages, effectiveConfig, effectiveCwd, session.stats, hadWrites);
489
+ }
473
490
  const agentElapsed = Date.now() - agentStart;
474
491
  if (!config.silent) {
475
492
  if (session.completed) {