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.
- package/dist/auto-docs.d.ts +4 -0
- package/dist/auto-docs.d.ts.map +1 -0
- package/dist/auto-docs.js +57 -0
- package/dist/auto-docs.js.map +1 -0
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +290 -0
- package/dist/chat.js.map +1 -1
- package/dist/code-graph.d.ts +14 -0
- package/dist/code-graph.d.ts.map +1 -0
- package/dist/code-graph.js +167 -0
- package/dist/code-graph.js.map +1 -0
- package/dist/critique.d.ts +4 -0
- package/dist/critique.d.ts.map +1 -0
- package/dist/critique.js +36 -0
- package/dist/critique.js.map +1 -0
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +111 -0
- package/dist/daemon.js.map +1 -0
- package/dist/debugger.d.ts +4 -0
- package/dist/debugger.d.ts.map +1 -0
- package/dist/debugger.js +104 -0
- package/dist/debugger.js.map +1 -0
- package/dist/engine.d.ts +5 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +22 -5
- package/dist/engine.js.map +1 -1
- package/dist/health.d.ts +2 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +201 -0
- package/dist/health.js.map +1 -0
- package/dist/index.js +167 -0
- package/dist/index.js.map +1 -1
- package/dist/issues.d.ts +3 -0
- package/dist/issues.d.ts.map +1 -0
- package/dist/issues.js +77 -0
- package/dist/issues.js.map +1 -0
- package/dist/knowledge-graph.d.ts +3 -0
- package/dist/knowledge-graph.d.ts.map +1 -0
- package/dist/knowledge-graph.js +85 -0
- package/dist/knowledge-graph.js.map +1 -0
- package/dist/memory.d.ts +7 -0
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +89 -2
- package/dist/memory.js.map +1 -1
- package/dist/pipeline.d.ts +3 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +79 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/plugin-packs.d.ts +14 -0
- package/dist/plugin-packs.d.ts.map +1 -0
- package/dist/plugin-packs.js +136 -0
- package/dist/plugin-packs.js.map +1 -0
- package/dist/reasoning-cache.d.ts +9 -0
- package/dist/reasoning-cache.d.ts.map +1 -0
- package/dist/reasoning-cache.js +67 -0
- package/dist/reasoning-cache.js.map +1 -0
- package/dist/recon.d.ts +2 -0
- package/dist/recon.d.ts.map +1 -0
- package/dist/recon.js +121 -0
- package/dist/recon.js.map +1 -0
- package/dist/refactor.d.ts +10 -0
- package/dist/refactor.d.ts.map +1 -0
- package/dist/refactor.js +182 -0
- package/dist/refactor.js.map +1 -0
- package/dist/test-gen.d.ts +3 -0
- package/dist/test-gen.d.ts.map +1 -0
- package/dist/test-gen.js +136 -0
- package/dist/test-gen.js.map +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- 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"}
|
package/dist/critique.js
ADDED
|
@@ -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"}
|
package/dist/daemon.d.ts
ADDED
|
@@ -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"}
|
package/dist/debugger.js
ADDED
|
@@ -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":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,gFAAgF;AAEhF,KAAK,UAAU,gBAAgB,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;QACtE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyC,CAAC;QACpE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;YAC5C,IAAI,OAAO,CAAC,GAAG,CAAC;gBAAE,OAAO,WAAW,GAAG,EAAE,CAAC;QAC5C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;IAC5D,CAAC;IAED,4CAA4C;IAC5C,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC,UAAU,CAAC;IAE5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACtF,EAAE,CAAC,QAAQ,CAAC,8BAA8B,EAAE,CAAC,MAAM,EAAE,EAAE;YACrD,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAc;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACxB,IACE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YACpB,4DAA4D,CAAC,IAAI,CAAC,IAAI,CAAC;YACvE,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YACvB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAC1B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACzE,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AACD,SAAS,cAAc,CAAC,OAAe,EAAE,WAAmB,EAAE,UAAkB;IAC9E,OAAO;;eAEM,OAAO;;;EAGpB,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;;;EAG1B,UAAU;;;;;;wCAM4B,CAAC;AACzC,CAAC;AAED,gFAAgF;AAEhF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAmB,EAAE,YAAqB;IAC1E,MAAM,OAAO,GAAG,YAAY,IAAI,CAAC,MAAM,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAErE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC,CAAC;IAEhD,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;QACpC,GAAG,EAAE,IAAI;QACT,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,MAAM,CAAC,GAAG;KAChB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAElD,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAE9D,MAAM,QAAQ,CAAC,SAAS,EAAE,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,MAAmB;IACzE,MAAM,IAAI,GAAG;;;EAGb,WAAW;;;;;;+CAMkC,CAAC;IAE9C,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC"}
|
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[];
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|