codeep 1.2.60 → 1.2.62
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/renderer/agentExecution.js +51 -2
- package/dist/utils/agent.js +29 -5
- package/dist/utils/toolParsing.js +18 -0
- package/package.json +1 -1
|
@@ -138,8 +138,12 @@ export async function executeAgentTask(task, dryRun, ctx) {
|
|
|
138
138
|
const result = await runAgent(enrichedTask, context, {
|
|
139
139
|
dryRun,
|
|
140
140
|
chatHistory: app.getChatHistory(),
|
|
141
|
-
onIteration: (iteration) => {
|
|
141
|
+
onIteration: (iteration, message) => {
|
|
142
142
|
app.updateAgentProgress(iteration);
|
|
143
|
+
// Show special status messages (timeout retries, verification) but not generic iteration messages
|
|
144
|
+
if (message && !message.startsWith('Iteration ')) {
|
|
145
|
+
app.addMessage({ role: 'system', content: `_${message}_` });
|
|
146
|
+
}
|
|
143
147
|
},
|
|
144
148
|
onToolCall: (tool) => {
|
|
145
149
|
const toolName = tool.tool.toLowerCase();
|
|
@@ -210,6 +214,31 @@ export async function executeAgentTask(task, dryRun, ctx) {
|
|
|
210
214
|
const filePath = tool.parameters.path;
|
|
211
215
|
app.addMessage({ role: 'system', content: `**Delete** \`${filePath}\`` });
|
|
212
216
|
}
|
|
217
|
+
else if (actionType === 'read') {
|
|
218
|
+
const filePath = tool.parameters.path || shortTarget;
|
|
219
|
+
if (filePath)
|
|
220
|
+
app.addMessage({ role: 'system', content: `**Reading** \`${filePath}\`` });
|
|
221
|
+
}
|
|
222
|
+
else if (actionType === 'search') {
|
|
223
|
+
const pattern = tool.parameters.pattern || tool.parameters.query || shortTarget;
|
|
224
|
+
if (pattern)
|
|
225
|
+
app.addMessage({ role: 'system', content: `**Searching** for \`${pattern}\`` });
|
|
226
|
+
}
|
|
227
|
+
else if (actionType === 'list') {
|
|
228
|
+
const dirPath = tool.parameters.path || shortTarget;
|
|
229
|
+
if (dirPath)
|
|
230
|
+
app.addMessage({ role: 'system', content: `**Listing** \`${dirPath}\`` });
|
|
231
|
+
}
|
|
232
|
+
else if (actionType === 'fetch') {
|
|
233
|
+
const url = tool.parameters.url || shortTarget;
|
|
234
|
+
if (url)
|
|
235
|
+
app.addMessage({ role: 'system', content: `**Fetching** \`${url}\`` });
|
|
236
|
+
}
|
|
237
|
+
else if (actionType === 'command') {
|
|
238
|
+
const cmd = tool.parameters.command || shortTarget;
|
|
239
|
+
if (cmd)
|
|
240
|
+
app.addMessage({ role: 'system', content: `**Running** \`${cmd}\`` });
|
|
241
|
+
}
|
|
213
242
|
},
|
|
214
243
|
onToolResult: (result, toolCall) => {
|
|
215
244
|
const toolName = toolCall.tool.toLowerCase();
|
|
@@ -235,7 +264,27 @@ export async function executeAgentTask(task, dryRun, ctx) {
|
|
|
235
264
|
abortSignal: abortController.signal,
|
|
236
265
|
});
|
|
237
266
|
if (result.success) {
|
|
238
|
-
const
|
|
267
|
+
const fileChanges = result.actions.filter(a => a.type === 'write' || a.type === 'edit' || a.type === 'delete');
|
|
268
|
+
const otherActions = result.actions.filter(a => a.type !== 'write' && a.type !== 'edit' && a.type !== 'delete');
|
|
269
|
+
const completionLines = [];
|
|
270
|
+
if (result.finalResponse) {
|
|
271
|
+
completionLines.push(result.finalResponse);
|
|
272
|
+
completionLines.push('');
|
|
273
|
+
}
|
|
274
|
+
completionLines.push(`**Agent completed** in ${result.iterations} step(s)`);
|
|
275
|
+
if (fileChanges.length > 0) {
|
|
276
|
+
completionLines.push('');
|
|
277
|
+
completionLines.push('**Files changed:**');
|
|
278
|
+
for (const a of fileChanges) {
|
|
279
|
+
const icon = a.type === 'delete' ? '✗' : '✓';
|
|
280
|
+
completionLines.push(` ${icon} ${a.type}: \`${a.target}\``);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (otherActions.length > 0) {
|
|
284
|
+
completionLines.push('');
|
|
285
|
+
completionLines.push(`${otherActions.length} read/search operation(s) performed`);
|
|
286
|
+
}
|
|
287
|
+
const summary = completionLines.join('\n');
|
|
239
288
|
app.addMessage({ role: 'assistant', content: summary });
|
|
240
289
|
app.notify(`Agent completed: ${result.actions.length} actions`);
|
|
241
290
|
// Auto-commit if enabled and there were file changes
|
package/dist/utils/agent.js
CHANGED
|
@@ -236,6 +236,8 @@ export async function runAgent(prompt, projectContext, options = {}) {
|
|
|
236
236
|
// Also remove Tool parameters/tool call artifacts that AI sometimes includes in text
|
|
237
237
|
finalResponse = content
|
|
238
238
|
.replace(/<think>[\s\S]*?<\/think>/gi, '')
|
|
239
|
+
.replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, '')
|
|
240
|
+
.replace(/<arg_key>[\s\S]*?<\/arg_value>/gi, '')
|
|
239
241
|
.replace(/Tool parameters:[\s\S]*?(?=\n\n|$)/gi, '')
|
|
240
242
|
.replace(/\{'path'[\s\S]*?\}/g, '')
|
|
241
243
|
.replace(/```[\s\S]*?```/g, '')
|
|
@@ -325,6 +327,7 @@ export async function runAgent(prompt, projectContext, options = {}) {
|
|
|
325
327
|
const hasFileChanges = actions.some(a => a.type === 'write' || a.type === 'edit' || a.type === 'delete');
|
|
326
328
|
if (hasFileChanges) {
|
|
327
329
|
let fixAttempt = 0;
|
|
330
|
+
let previousErrorSignature = '';
|
|
328
331
|
while (fixAttempt < maxFixAttempts) {
|
|
329
332
|
// Check abort signal
|
|
330
333
|
if (opts.abortSignal?.aborted) {
|
|
@@ -346,18 +349,39 @@ export async function runAgent(prompt, projectContext, options = {}) {
|
|
|
346
349
|
break;
|
|
347
350
|
}
|
|
348
351
|
fixAttempt++;
|
|
349
|
-
// If we've exceeded attempts,
|
|
352
|
+
// If we've exceeded fix attempts, hand back to the main agent loop
|
|
353
|
+
// instead of stopping — let it keep working freely without the verification constraint
|
|
350
354
|
if (fixAttempt >= maxFixAttempts) {
|
|
351
|
-
const
|
|
352
|
-
|
|
355
|
+
const errorMessage = formatErrorsForAgent(verifyResults);
|
|
356
|
+
messages.push({ role: 'assistant', content: finalResponse });
|
|
357
|
+
messages.push({
|
|
358
|
+
role: 'user',
|
|
359
|
+
content: `${errorMessage}\n\nVerification has failed ${fixAttempt} time(s). Stop trying the same approach. Step back, re-read ALL relevant files, and think about the root cause from scratch. Try a fundamentally different solution.`,
|
|
360
|
+
});
|
|
361
|
+
// Re-enter the main agent loop — it will continue until maxIterations
|
|
362
|
+
iteration++;
|
|
353
363
|
break;
|
|
354
364
|
}
|
|
355
|
-
//
|
|
365
|
+
// Detect if the same errors are repeating (previous fix attempt didn't help)
|
|
356
366
|
const errorMessage = formatErrorsForAgent(verifyResults);
|
|
367
|
+
const currentErrorSignature = errorMessage.slice(0, 200);
|
|
368
|
+
const errorsRepeating = previousErrorSignature !== '' && currentErrorSignature === previousErrorSignature;
|
|
369
|
+
previousErrorSignature = currentErrorSignature;
|
|
370
|
+
// Escalate the fix strategy based on attempt number and whether errors are repeating
|
|
371
|
+
let fixPrompt;
|
|
372
|
+
if (errorsRepeating) {
|
|
373
|
+
fixPrompt = `${errorMessage}\n\nYour previous fix attempt did NOT resolve these errors — they are still the same. You MUST try a completely different approach:\n- Re-read the affected files to understand the current state\n- Consider whether the root cause is different from what you assumed\n- Try an alternative implementation strategy\n- If it's a missing dependency, install it with execute_command`;
|
|
374
|
+
}
|
|
375
|
+
else if (fixAttempt === 1) {
|
|
376
|
+
fixPrompt = `${errorMessage}\n\nFix these errors. Read the affected files first to understand the current state before making changes.`;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
fixPrompt = `${errorMessage}\n\nAttempt ${fixAttempt}/${maxFixAttempts}: Your previous fix was partially successful but errors remain. Re-read ALL affected files and take a fresh look — consider whether there are related issues you missed.`;
|
|
380
|
+
}
|
|
357
381
|
messages.push({ role: 'assistant', content: finalResponse });
|
|
358
382
|
messages.push({
|
|
359
383
|
role: 'user',
|
|
360
|
-
content:
|
|
384
|
+
content: fixPrompt,
|
|
361
385
|
});
|
|
362
386
|
iteration++;
|
|
363
387
|
if (iteration >= opts.maxIterations) {
|
|
@@ -289,6 +289,24 @@ export function parseToolCalls(response) {
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
|
+
// Format 3b: Tool <arg_key>param</arg_key><arg_value>value</arg_value> format
|
|
293
|
+
// Some models emit: Tool write_file<arg_key>path</arg_key><arg_value>...</arg_value>
|
|
294
|
+
if (toolCalls.length === 0) {
|
|
295
|
+
const argKeyValueRegex = /Tool\s+(\w+)((?:\s*<arg_key>[\s\S]*?<\/arg_key>\s*<arg_value>[\s\S]*?<\/arg_value>)+)/gi;
|
|
296
|
+
while ((match = argKeyValueRegex.exec(response)) !== null) {
|
|
297
|
+
const toolName = normalizeToolName(match[1]);
|
|
298
|
+
const argBlock = match[2];
|
|
299
|
+
const params = {};
|
|
300
|
+
const pairRegex = /<arg_key>([\s\S]*?)<\/arg_key>\s*<arg_value>([\s\S]*?)<\/arg_value>/gi;
|
|
301
|
+
let pairMatch;
|
|
302
|
+
while ((pairMatch = pairRegex.exec(argBlock)) !== null) {
|
|
303
|
+
params[pairMatch[1].trim()] = pairMatch[2].trim();
|
|
304
|
+
}
|
|
305
|
+
if (toolName && Object.keys(params).length > 0) {
|
|
306
|
+
toolCalls.push({ tool: toolName, parameters: params });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
292
310
|
// Format 4: Inline JSON with tool property (fallback)
|
|
293
311
|
if (toolCalls.length === 0) {
|
|
294
312
|
const jsonRegex = /\{[^{}]*"tool"\s*:\s*"[^"]+"\s*,\s*"parameters"\s*:\s*\{[^{}]*\}[^{}]*\}/g;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeep",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.62",
|
|
4
4
|
"description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|