agent-nuvira 1.20.0 → 1.22.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/agents/edit-module.d.ts +121 -0
- package/dist/agents/edit-module.d.ts.map +1 -0
- package/dist/agents/edit-module.js +339 -0
- package/dist/agents/edit-module.js.map +1 -0
- package/dist/agents/inspect-module.d.ts +21 -2
- package/dist/agents/inspect-module.d.ts.map +1 -1
- package/dist/agents/inspect-module.js +96 -10
- package/dist/agents/inspect-module.js.map +1 -1
- package/dist/agents/pipeline-audit.d.ts +128 -0
- package/dist/agents/pipeline-audit.d.ts.map +1 -0
- package/dist/agents/pipeline-audit.js +162 -0
- package/dist/agents/pipeline-audit.js.map +1 -0
- package/dist/agents/plan-module.d.ts +84 -0
- package/dist/agents/plan-module.d.ts.map +1 -0
- package/dist/agents/plan-module.js +261 -0
- package/dist/agents/plan-module.js.map +1 -0
- package/dist/agents/task-execution-pipeline.d.ts +237 -0
- package/dist/agents/task-execution-pipeline.d.ts.map +1 -0
- package/dist/agents/task-execution-pipeline.js +816 -0
- package/dist/agents/task-execution-pipeline.js.map +1 -0
- package/dist/agents/verify-module.d.ts +110 -0
- package/dist/agents/verify-module.d.ts.map +1 -0
- package/dist/agents/verify-module.js +261 -0
- package/dist/agents/verify-module.js.map +1 -0
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +24 -4
- package/dist/cli/execute.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/observability/event-bus.d.ts.map +1 -1
- package/dist/observability/event-bus.js +32 -0
- package/dist/observability/event-bus.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EditModule — Generates code changes from task descriptions and file context.
|
|
3
|
+
* Phase 7 of the architecture migration: extract from WriterAgent into
|
|
4
|
+
* a pluggable module with EventBus integration.
|
|
5
|
+
*
|
|
6
|
+
* The module reads relevant files, calls an LLM to generate modified versions,
|
|
7
|
+
* parses file changes from the response, validates syntax via AST analysis,
|
|
8
|
+
* and returns structured FileChange objects — without writing to disk.
|
|
9
|
+
*
|
|
10
|
+
* @see ARCHITECTURE.md §3.3 — Edit Module specification
|
|
11
|
+
*/
|
|
12
|
+
import type { EventBus } from '../observability/event-bus.js';
|
|
13
|
+
import type { LLMCallFn, FileChange, Artifact } from './agent.js';
|
|
14
|
+
/** Parameters for the EditModule.edit() method */
|
|
15
|
+
export interface EditParams {
|
|
16
|
+
/** The original user goal / task description */
|
|
17
|
+
goal: string;
|
|
18
|
+
/** Absolute path to the working directory */
|
|
19
|
+
workingDirectory: string;
|
|
20
|
+
/** File artifacts discovered during the inspection phase */
|
|
21
|
+
artifacts: Artifact[];
|
|
22
|
+
/** The LLM call function */
|
|
23
|
+
callLLM: LLMCallFn;
|
|
24
|
+
/** Optional structured context overrides */
|
|
25
|
+
taskDescription?: string;
|
|
26
|
+
/** Optional MCP tools description for the LLM */
|
|
27
|
+
mcpToolsFormatted?: string;
|
|
28
|
+
/** Optional rate limit callback */
|
|
29
|
+
onRateLimit?: (info: {
|
|
30
|
+
retryAfterMs: number;
|
|
31
|
+
modelName?: string;
|
|
32
|
+
agentName: string;
|
|
33
|
+
errorMessage: string;
|
|
34
|
+
}) => Promise<{
|
|
35
|
+
action: 'retry' | 'skip' | 'abort' | 'switch-model';
|
|
36
|
+
callLLM?: LLMCallFn;
|
|
37
|
+
}>;
|
|
38
|
+
/** Whether this is a retry attempt (stricter prompt) */
|
|
39
|
+
isRetry?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Output of the edit phase */
|
|
42
|
+
export interface EditOutput {
|
|
43
|
+
/** File changes generated */
|
|
44
|
+
changes: FileChange[];
|
|
45
|
+
/** Human-readable summary */
|
|
46
|
+
summary: string;
|
|
47
|
+
/** How many files were changed */
|
|
48
|
+
changeCount: number;
|
|
49
|
+
/** Syntax warnings, if any */
|
|
50
|
+
warnings?: string[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* EditModule — Generate code changes from task descriptions and file context.
|
|
54
|
+
*
|
|
55
|
+
* The module reads files, calls the LLM to generate modified versions, parses
|
|
56
|
+
* the response, validates syntax, and returns structured FileChange objects.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const module = new DefaultEditModule();
|
|
61
|
+
* const result = await module.edit({
|
|
62
|
+
* goal: 'Add JWT auth',
|
|
63
|
+
* workingDirectory: '/project',
|
|
64
|
+
* artifacts: inspectedFiles,
|
|
65
|
+
* callLLM,
|
|
66
|
+
* });
|
|
67
|
+
* console.log(`Changed ${result.changeCount} files`);
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export interface EditModule {
|
|
71
|
+
/**
|
|
72
|
+
* Generate file changes from the given task and file context.
|
|
73
|
+
*/
|
|
74
|
+
edit(params: EditParams): Promise<EditOutput>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* DefaultEditModule — Built-in edit module implementation.
|
|
78
|
+
*
|
|
79
|
+
* Builds a prompt from file artifacts and task description; calls the LLM;
|
|
80
|
+
* parses file changes from the response; validates syntax via AST analysis;
|
|
81
|
+
* and returns structured FileChange objects without writing to disk.
|
|
82
|
+
*/
|
|
83
|
+
export declare class DefaultEditModule implements EditModule {
|
|
84
|
+
/** The event bus for emitting observability events */
|
|
85
|
+
private eventBus;
|
|
86
|
+
constructor(eventBus?: EventBus);
|
|
87
|
+
/**
|
|
88
|
+
* Generate file changes from the given task and file context.
|
|
89
|
+
*/
|
|
90
|
+
edit(params: EditParams): Promise<EditOutput>;
|
|
91
|
+
/**
|
|
92
|
+
* Build the LLM prompt from file artifacts and task description.
|
|
93
|
+
*/
|
|
94
|
+
private buildPrompt;
|
|
95
|
+
/**
|
|
96
|
+
* Select files within the character budget, prioritizing smaller files.
|
|
97
|
+
*/
|
|
98
|
+
private selectFilesWithinBudget;
|
|
99
|
+
/**
|
|
100
|
+
* Parse the LLM response to extract file changes.
|
|
101
|
+
*/
|
|
102
|
+
private parseFileChanges;
|
|
103
|
+
/**
|
|
104
|
+
* Add a file change entry, comparing with existing content if the file exists.
|
|
105
|
+
*/
|
|
106
|
+
private addFileChange;
|
|
107
|
+
/**
|
|
108
|
+
* Validate file changes via AST syntax checking.
|
|
109
|
+
* Returns warning messages for any files with unbalanced syntax.
|
|
110
|
+
*/
|
|
111
|
+
private validateChanges;
|
|
112
|
+
/**
|
|
113
|
+
* Check if an error message indicates a rate-limit (429) error.
|
|
114
|
+
*/
|
|
115
|
+
private isRateLimitError;
|
|
116
|
+
/**
|
|
117
|
+
* Parse the "try again in Xs" hint from a rate-limit error response.
|
|
118
|
+
*/
|
|
119
|
+
private parseRetryAfterHint;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=edit-module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-module.d.ts","sourceRoot":"","sources":["../../src/agents/edit-module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA+ClE,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,4BAA4B;IAC5B,OAAO,EAAE,SAAS,CAAC;IACnB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mCAAmC;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,cAAc,CAAC;QAAC,OAAO,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IACrM,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,+BAA+B;AAC/B,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC/C;AAID;;;;;;GAMG;AACH,qBAAa,iBAAkB,YAAW,UAAU;IAClD,sDAAsD;IACtD,OAAO,CAAC,QAAQ,CAAW;gBAEf,QAAQ,CAAC,EAAE,QAAQ;IAI/B;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAuInD;;OAEG;IACH,OAAO,CAAC,WAAW;IA4CnB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAqC/B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IA6BrB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAoBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAe5B"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EditModule — Generates code changes from task descriptions and file context.
|
|
3
|
+
* Phase 7 of the architecture migration: extract from WriterAgent into
|
|
4
|
+
* a pluggable module with EventBus integration.
|
|
5
|
+
*
|
|
6
|
+
* The module reads relevant files, calls an LLM to generate modified versions,
|
|
7
|
+
* parses file changes from the response, validates syntax via AST analysis,
|
|
8
|
+
* and returns structured FileChange objects — without writing to disk.
|
|
9
|
+
*
|
|
10
|
+
* @see ARCHITECTURE.md §3.3 — Edit Module specification
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { isAbsolute, join } from 'node:path';
|
|
14
|
+
import { getEventBus, EventNames } from '../observability/event-bus.js';
|
|
15
|
+
import { detectLanguage } from '../editing/types.js';
|
|
16
|
+
import { validateSyntax } from '../editing/ast.js';
|
|
17
|
+
import { buildStructuralContext } from '../editing/edit.js';
|
|
18
|
+
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
19
|
+
const EDIT_SYSTEM_PROMPT = `You are an expert software engineer implementing changes to a codebase.
|
|
20
|
+
|
|
21
|
+
Given file contents and an implementation task, you will:
|
|
22
|
+
1. Read the current file content carefully
|
|
23
|
+
2. Implement the requested changes
|
|
24
|
+
3. Return the COMPLETE updated file content for EACH modified file
|
|
25
|
+
|
|
26
|
+
## Output Format (MANDATORY)
|
|
27
|
+
|
|
28
|
+
Wrap EACH file you modify in its own code block. The file path MUST go right after the opening backticks with the prefix "filepath:".
|
|
29
|
+
|
|
30
|
+
CORRECT (use this format):
|
|
31
|
+
\`\`\`filepath:path/to/file.ts
|
|
32
|
+
// FULL updated file content here
|
|
33
|
+
\`\`\`
|
|
34
|
+
|
|
35
|
+
INCORRECT (do NOT use these):
|
|
36
|
+
- ❌ \`\`\`typescript\n...\n\`\`\` (missing filepath)
|
|
37
|
+
- ❌ \`\`\`\n...\n\`\`\` (missing language and filepath)
|
|
38
|
+
- ❌ Just describing the changes instead of returning the file
|
|
39
|
+
|
|
40
|
+
## Rules
|
|
41
|
+
- Return the FULL file content, not just the changed parts
|
|
42
|
+
- Preserve existing code style and conventions
|
|
43
|
+
- Add appropriate error handling
|
|
44
|
+
- Write clean, well-documented code
|
|
45
|
+
- If you modify multiple files, return ONE code block per file
|
|
46
|
+
`;
|
|
47
|
+
/** Maximum files to include in a single edit prompt */
|
|
48
|
+
const MAX_CONTEXT_FILES = 10;
|
|
49
|
+
/** Maximum total characters across all files sent to the LLM */
|
|
50
|
+
const MAX_CONTEXT_CHARS = 16_000;
|
|
51
|
+
/** Overhead per file in characters for formatting/path prefix */
|
|
52
|
+
const OVERHEAD_PER_FILE = 50;
|
|
53
|
+
// ─── Default EditModule ─────────────────────────────────────────────────────
|
|
54
|
+
/**
|
|
55
|
+
* DefaultEditModule — Built-in edit module implementation.
|
|
56
|
+
*
|
|
57
|
+
* Builds a prompt from file artifacts and task description; calls the LLM;
|
|
58
|
+
* parses file changes from the response; validates syntax via AST analysis;
|
|
59
|
+
* and returns structured FileChange objects without writing to disk.
|
|
60
|
+
*/
|
|
61
|
+
export class DefaultEditModule {
|
|
62
|
+
/** The event bus for emitting observability events */
|
|
63
|
+
eventBus;
|
|
64
|
+
constructor(eventBus) {
|
|
65
|
+
this.eventBus = eventBus ?? getEventBus();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate file changes from the given task and file context.
|
|
69
|
+
*/
|
|
70
|
+
async edit(params) {
|
|
71
|
+
const { goal, workingDirectory, artifacts, callLLM: initialCallLLM, taskDescription, mcpToolsFormatted, onRateLimit, isRetry } = params;
|
|
72
|
+
let currentCallLLM = initialCallLLM;
|
|
73
|
+
// ── Emit: edit generating ──────────────────────────────────────────
|
|
74
|
+
this.eventBus.emit(EventNames.EDIT_GENERATING, {
|
|
75
|
+
goal,
|
|
76
|
+
artifactCount: artifacts.length,
|
|
77
|
+
isRetry: isRetry ?? false,
|
|
78
|
+
}, 'edit-module');
|
|
79
|
+
// Try up to 2 API attempts
|
|
80
|
+
let lastError;
|
|
81
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
82
|
+
try {
|
|
83
|
+
const effectiveIsRetry = attempt > 0 ? true : (isRetry ?? false);
|
|
84
|
+
const prompt = this.buildPrompt(goal, workingDirectory, artifacts, taskDescription, mcpToolsFormatted, effectiveIsRetry);
|
|
85
|
+
const response = await currentCallLLM(prompt, {
|
|
86
|
+
temperature: effectiveIsRetry ? 0.1 : 0.3,
|
|
87
|
+
maxTokens: 4096,
|
|
88
|
+
});
|
|
89
|
+
const fileChanges = this.parseFileChanges(response, workingDirectory);
|
|
90
|
+
const warnings = this.validateChanges(fileChanges);
|
|
91
|
+
// Emit: per-file written events
|
|
92
|
+
for (const change of fileChanges) {
|
|
93
|
+
if (change.newContent) {
|
|
94
|
+
this.eventBus.emit(EventNames.EDIT_WRITTEN, {
|
|
95
|
+
path: change.path,
|
|
96
|
+
status: change.status,
|
|
97
|
+
bytes: change.newContent.length,
|
|
98
|
+
}, 'edit-module');
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
this.eventBus.emit(EventNames.EDIT_SKIPPED, {
|
|
102
|
+
path: change.path,
|
|
103
|
+
reason: 'no new content',
|
|
104
|
+
}, 'edit-module');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const count = fileChanges.length;
|
|
108
|
+
if (count === 0) {
|
|
109
|
+
// Emit empty result
|
|
110
|
+
const excerpt = response.slice(0, 300).replace(/\n/g, '\\n');
|
|
111
|
+
// If first attempt returned empty, retry with stricter prompt
|
|
112
|
+
if (attempt === 0) {
|
|
113
|
+
this.eventBus.emit(EventNames.EDIT_GENERATING, {
|
|
114
|
+
goal,
|
|
115
|
+
artifactCount: artifacts.length,
|
|
116
|
+
isRetry: true,
|
|
117
|
+
reason: 'empty-parse-retry',
|
|
118
|
+
}, 'edit-module');
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
changes: [],
|
|
123
|
+
summary: 'No files needed changes',
|
|
124
|
+
changeCount: 0,
|
|
125
|
+
warnings: ['LLM produced no parseable file changes'],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return { changes: fileChanges, summary: `Proposed changes to ${count} file${count !== 1 ? 's' : ''}`, changeCount: count, warnings: warnings.length > 0 ? warnings : undefined };
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
lastError = err instanceof Error ? err.message : String(err);
|
|
132
|
+
// Handle rate limit
|
|
133
|
+
if (onRateLimit && this.isRateLimitError(lastError)) {
|
|
134
|
+
const retryAfterMs = this.parseRetryAfterHint(lastError) || 5000;
|
|
135
|
+
const action = await onRateLimit({
|
|
136
|
+
retryAfterMs,
|
|
137
|
+
agentName: 'EditModule',
|
|
138
|
+
errorMessage: lastError.slice(0, 300),
|
|
139
|
+
});
|
|
140
|
+
if (action.action === 'abort') {
|
|
141
|
+
return {
|
|
142
|
+
changes: [],
|
|
143
|
+
summary: 'Edit aborted by user due to rate limit',
|
|
144
|
+
changeCount: 0,
|
|
145
|
+
warnings: [lastError],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (action.action === 'skip') {
|
|
149
|
+
return {
|
|
150
|
+
changes: [],
|
|
151
|
+
summary: 'Skipped by user (rate limit)',
|
|
152
|
+
changeCount: 0,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (action.action === 'switch-model' && action.callLLM) {
|
|
156
|
+
// Retry with new callLLM
|
|
157
|
+
currentCallLLM = action.callLLM;
|
|
158
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
// 'retry': wait and retry
|
|
162
|
+
await new Promise((resolve) => setTimeout(resolve, retryAfterMs));
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (attempt === 0) {
|
|
166
|
+
// Transient error — retry once
|
|
167
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// All attempts exhausted
|
|
171
|
+
return {
|
|
172
|
+
changes: [],
|
|
173
|
+
summary: 'Edit failed to generate changes',
|
|
174
|
+
changeCount: 0,
|
|
175
|
+
warnings: [lastError],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
changes: [],
|
|
181
|
+
summary: 'Edit failed after retries',
|
|
182
|
+
changeCount: 0,
|
|
183
|
+
warnings: lastError ? [lastError] : undefined,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
// ─── Prompt Building ─────────────────────────────────────────────────
|
|
187
|
+
/**
|
|
188
|
+
* Build the LLM prompt from file artifacts and task description.
|
|
189
|
+
*/
|
|
190
|
+
buildPrompt(goal, workingDirectory, artifacts, taskDescription, mcpToolsFormatted, isRetry = false) {
|
|
191
|
+
const taskDesc = taskDescription || goal;
|
|
192
|
+
// Select files within the character budget
|
|
193
|
+
const filesToSend = this.selectFilesWithinBudget(artifacts, MAX_CONTEXT_CHARS);
|
|
194
|
+
const fileContext = filesToSend.length > 0
|
|
195
|
+
? filesToSend
|
|
196
|
+
.map(({ artifact, truncated }) => `--- ${artifact.path} ---${truncated ? ` (truncated, ${artifact.content.length}\u2192${truncated.length} chars)` : ''}\n${truncated || artifact.content}`)
|
|
197
|
+
.join('\n\n') +
|
|
198
|
+
(artifacts.length > filesToSend.length
|
|
199
|
+
? `\n\n... and ${artifacts.length - filesToSend.length} more files in the project (excluded to fit token budget)`
|
|
200
|
+
: '')
|
|
201
|
+
: '(No files found in context — you may need to create new files)';
|
|
202
|
+
// Build structural context for AST-aware editing
|
|
203
|
+
const structuralContexts = artifacts
|
|
204
|
+
.filter((a) => a.content)
|
|
205
|
+
.slice(0, 5)
|
|
206
|
+
.map((a) => buildStructuralContext(a.content, a.path))
|
|
207
|
+
.filter((s) => s.length > 0);
|
|
208
|
+
const structureSection = structuralContexts.length > 0
|
|
209
|
+
? `\n## File Structure Overview\n\nHere is the structural layout of the files you need to modify.\nUse these line ranges to understand where each function/class lives.\n\n${structuralContexts.join('\n\n')}\n`
|
|
210
|
+
: '';
|
|
211
|
+
const mcpSection = mcpToolsFormatted ? `\n${mcpToolsFormatted}\n` : '';
|
|
212
|
+
const instructions = isRetry
|
|
213
|
+
? `\n## CRITICAL — Read This Carefully\nThe previous response could not be parsed because the files were not wrapped in correctly formatted code blocks.\n\nYou MUST follow this format EXACTLY for EACH file you modify:\n\n\`\`\`filepath:src/example.ts\n// THE COMPLETE UPDATED FILE CONTENT GOES HERE (every line, full file)\n\`\`\`\n\nIMPORTANT:\n- The filepath: prefix is REQUIRED after the opening backticks\n- Return the FULL file, not a diff or snippet\n- If you modify 2 files, return 2 separate code blocks in this format`
|
|
214
|
+
: `\n## Instructions\nImplement the changes described in the task. Return the complete updated file content for each file you modify. Remember: each file must be wrapped in \`\`\`filepath:...\n\`\`\` format.`;
|
|
215
|
+
return `${EDIT_SYSTEM_PROMPT}\n\n## Task Description\n${taskDesc}\n\n## Working Directory\n${workingDirectory}\n\n## Current File Content\n${fileContext}${structureSection}${mcpSection}\n${instructions}`;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Select files within the character budget, prioritizing smaller files.
|
|
219
|
+
*/
|
|
220
|
+
selectFilesWithinBudget(artifacts, budget) {
|
|
221
|
+
const sorted = [...artifacts]
|
|
222
|
+
.map((a) => ({ artifact: a, size: a.content.length }))
|
|
223
|
+
.sort((a, b) => a.size - b.size);
|
|
224
|
+
const result = [];
|
|
225
|
+
let used = 0;
|
|
226
|
+
for (const { artifact, size } of sorted) {
|
|
227
|
+
if (result.length >= MAX_CONTEXT_FILES)
|
|
228
|
+
break;
|
|
229
|
+
const totalNeeded = size + OVERHEAD_PER_FILE;
|
|
230
|
+
if (used + totalNeeded <= budget) {
|
|
231
|
+
result.push({ artifact, truncated: null });
|
|
232
|
+
used += totalNeeded;
|
|
233
|
+
}
|
|
234
|
+
else if (used + OVERHEAD_PER_FILE < budget) {
|
|
235
|
+
const remaining = budget - used - OVERHEAD_PER_FILE;
|
|
236
|
+
if (remaining > 200) {
|
|
237
|
+
const truncated = artifact.content.slice(0, remaining);
|
|
238
|
+
result.push({ artifact, truncated });
|
|
239
|
+
used = budget;
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
// ─── File Change Parsing ─────────────────────────────────────────────
|
|
250
|
+
/**
|
|
251
|
+
* Parse the LLM response to extract file changes.
|
|
252
|
+
*/
|
|
253
|
+
parseFileChanges(response, workingDir) {
|
|
254
|
+
const changes = [];
|
|
255
|
+
// Match code blocks containing a real file path
|
|
256
|
+
const blockRegex = /```(?:[a-zA-Z0-9+#]*\s+)?(?:filepath:)?([^\n`]+(?:\.[a-zA-Z0-9]+|\/[^\n`]+))\n([\s\S]*?)```/g;
|
|
257
|
+
let match;
|
|
258
|
+
while ((match = blockRegex.exec(response)) !== null) {
|
|
259
|
+
let filePath = match[1].trim();
|
|
260
|
+
const content = match[2].trim();
|
|
261
|
+
// Clean up the file path
|
|
262
|
+
filePath = filePath.replace(/^['"]|['"]$/g, '').trim();
|
|
263
|
+
if (!filePath || !content)
|
|
264
|
+
continue;
|
|
265
|
+
this.addFileChange(changes, filePath, content, workingDir);
|
|
266
|
+
}
|
|
267
|
+
return changes;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Add a file change entry, comparing with existing content if the file exists.
|
|
271
|
+
*/
|
|
272
|
+
addFileChange(changes, filePath, content, workingDir) {
|
|
273
|
+
const absolutePath = isAbsolute(filePath) ? filePath : join(workingDir, filePath);
|
|
274
|
+
if (existsSync(absolutePath)) {
|
|
275
|
+
const originalContent = readFileSync(absolutePath, 'utf-8');
|
|
276
|
+
if (originalContent.trim() !== content.trim()) {
|
|
277
|
+
changes.push({
|
|
278
|
+
path: filePath,
|
|
279
|
+
originalContent,
|
|
280
|
+
newContent: content,
|
|
281
|
+
status: 'modified',
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
changes.push({
|
|
287
|
+
path: filePath,
|
|
288
|
+
newContent: content,
|
|
289
|
+
status: 'created',
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// ─── Validation ──────────────────────────────────────────────────────
|
|
294
|
+
/**
|
|
295
|
+
* Validate file changes via AST syntax checking.
|
|
296
|
+
* Returns warning messages for any files with unbalanced syntax.
|
|
297
|
+
*/
|
|
298
|
+
validateChanges(changes) {
|
|
299
|
+
const warnings = [];
|
|
300
|
+
for (const change of changes) {
|
|
301
|
+
if (change.newContent) {
|
|
302
|
+
const lang = detectLanguage(change.path);
|
|
303
|
+
if (lang !== 'unknown') {
|
|
304
|
+
const isValid = validateSyntax(change.newContent, lang);
|
|
305
|
+
if (!isValid) {
|
|
306
|
+
warnings.push(`Syntax warning: ${change.path} has unbalanced brackets`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return warnings;
|
|
312
|
+
}
|
|
313
|
+
// ─── Rate Limit Helpers ──────────────────────────────────────────────
|
|
314
|
+
/**
|
|
315
|
+
* Check if an error message indicates a rate-limit (429) error.
|
|
316
|
+
*/
|
|
317
|
+
isRateLimitError(errorMessage) {
|
|
318
|
+
return /rate\s*limit|429|too many requests|try again in/i.test(errorMessage);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Parse the "try again in Xs" hint from a rate-limit error response.
|
|
322
|
+
*/
|
|
323
|
+
parseRetryAfterHint(errorMessage) {
|
|
324
|
+
const secondMatch = errorMessage.match(/try again in ([\d.]+)s/i);
|
|
325
|
+
if (secondMatch) {
|
|
326
|
+
const seconds = parseFloat(secondMatch[1]);
|
|
327
|
+
if (!isNaN(seconds) && seconds > 0)
|
|
328
|
+
return Math.ceil(seconds * 1000);
|
|
329
|
+
}
|
|
330
|
+
const msMatch = errorMessage.match(/try again in (\d+)ms/i);
|
|
331
|
+
if (msMatch) {
|
|
332
|
+
const ms = parseInt(msMatch[1], 10);
|
|
333
|
+
if (!isNaN(ms) && ms > 0)
|
|
334
|
+
return ms;
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=edit-module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-module.js","sourceRoot":"","sources":["../../src/agents/edit-module.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* InspectModule — Scans the codebase to discover relevant files, extract
|
|
3
|
-
* structural context, and identify dependencies. Phase
|
|
4
|
-
*
|
|
3
|
+
* structural context, and identify dependencies. Phase 6 adds LLM-based
|
|
4
|
+
* file classification with keyword-scanning fallback.
|
|
5
5
|
*
|
|
6
6
|
* @see ARCHITECTURE.md §3.2 — Inspect Module specification
|
|
7
7
|
*/
|
|
8
8
|
import type { EventBus } from '../observability/event-bus.js';
|
|
9
|
+
import type { LLMCallFn } from './agent.js';
|
|
9
10
|
/**
|
|
10
11
|
* A discovered file artifact with its content.
|
|
11
12
|
* Prefixed with "Inspect" to avoid collision with agent.ts's Artifact type.
|
|
@@ -50,6 +51,13 @@ export interface InspectParams {
|
|
|
50
51
|
taskDescriptions?: string[];
|
|
51
52
|
/** Maximum number of files to inspect (default: 10) */
|
|
52
53
|
maxFiles?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Optional LLM call function for LLM-based file classification.
|
|
56
|
+
* When provided, the module first asks the LLM to identify relevant
|
|
57
|
+
* files. Falls back to keyword scanning if the LLM call fails.
|
|
58
|
+
* When omitted, only keyword scanning is used.
|
|
59
|
+
*/
|
|
60
|
+
callLLM?: LLMCallFn;
|
|
53
61
|
}
|
|
54
62
|
/**
|
|
55
63
|
* PlanStep-like interface for dependency-aware planning.
|
|
@@ -100,6 +108,7 @@ export declare class DefaultInspectModule implements InspectModule {
|
|
|
100
108
|
constructor(eventBus?: EventBus);
|
|
101
109
|
/**
|
|
102
110
|
* Scan the codebase for files relevant to the given goal.
|
|
111
|
+
* Phase 6: Uses LLM-based classification with keyword-scanning fallback.
|
|
103
112
|
*/
|
|
104
113
|
inspect(params: InspectParams): Promise<InspectionResult>;
|
|
105
114
|
/**
|
|
@@ -107,6 +116,16 @@ export declare class DefaultInspectModule implements InspectModule {
|
|
|
107
116
|
* Used when the LLM call fails or as the base implementation.
|
|
108
117
|
*/
|
|
109
118
|
scanByKeywords(goal: string, workingDir: string): string[];
|
|
119
|
+
/**
|
|
120
|
+
* Use the LLM to identify files relevant to the goal.
|
|
121
|
+
* Parses the LLM response as a JSON array of file paths.
|
|
122
|
+
* Throws if parsing fails or file list is empty.
|
|
123
|
+
*/
|
|
124
|
+
private classifyFiles;
|
|
125
|
+
/** Build the prompt for LLM-based file classification */
|
|
126
|
+
private buildClassifyPrompt;
|
|
127
|
+
/** Parse the LLM response into an array of file paths. Throws on failure. */
|
|
128
|
+
private parseClassifyResponse;
|
|
110
129
|
/** Walk the directory tree and score files by keyword relevance */
|
|
111
130
|
private walkAndScore;
|
|
112
131
|
/** Format byte count to human-readable string */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-module.d.ts","sourceRoot":"","sources":["../../src/agents/inspect-module.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"inspect-module.d.ts","sourceRoot":"","sources":["../../src/agents/inspect-module.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI5C;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,4BAA4B;IAC5B,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACrB;AAID;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE1D;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5D;AAYD;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,YAAW,aAAa;IACxD,sDAAsD;IACtD,OAAO,CAAC,QAAQ,CAAW;gBAEf,QAAQ,CAAC,EAAE,QAAQ;IAI/B;;;OAGG;IACG,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkH/D;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAwB1D;;;;OAIG;YACW,aAAa;IAY3B,yDAAyD;IACzD,OAAO,CAAC,mBAAmB;IA8B3B,6EAA6E;IAC7E,OAAO,CAAC,qBAAqB;IA8B7B,mEAAmE;IACnE,OAAO,CAAC,YAAY;IAgDpB,iDAAiD;IACjD,OAAO,CAAC,UAAU;CAKnB"}
|