codeep 1.0.23 → 1.0.25
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/config/index.js +2 -2
- package/dist/utils/agent.js +51 -41
- package/dist/utils/tools.js +27 -7
- package/package.json +1 -1
package/dist/config/index.js
CHANGED
|
@@ -68,14 +68,14 @@ export const config = new Conf({
|
|
|
68
68
|
agentMaxFixAttempts: 3,
|
|
69
69
|
agentMaxIterations: 100,
|
|
70
70
|
agentMaxDuration: 20, // minutes
|
|
71
|
-
agentApiTimeout:
|
|
71
|
+
agentApiTimeout: 120000, // 120 seconds base timeout for agent (dynamically adjusted)
|
|
72
72
|
protocol: 'openai',
|
|
73
73
|
plan: 'lite',
|
|
74
74
|
language: 'en',
|
|
75
75
|
autoSave: true,
|
|
76
76
|
currentSessionId: '',
|
|
77
77
|
temperature: 0.7,
|
|
78
|
-
maxTokens:
|
|
78
|
+
maxTokens: 8192,
|
|
79
79
|
apiTimeout: 60000,
|
|
80
80
|
rateLimitApi: 30, // 30 requests per minute
|
|
81
81
|
rateLimitCommands: 100, // 100 commands per minute
|
package/dist/utils/agent.js
CHANGED
|
@@ -15,46 +15,19 @@ class TimeoutError extends Error {
|
|
|
15
15
|
* Complex tasks (creating pages, multiple files) need more time
|
|
16
16
|
*/
|
|
17
17
|
function calculateDynamicTimeout(prompt, iteration, baseTimeout) {
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
const complexKeywords = [
|
|
21
|
-
'create', 'build', 'implement', 'generate', 'make', 'develop', 'setup',
|
|
22
|
-
'website', 'app', 'application', 'page', 'component', 'feature',
|
|
23
|
-
'kreiraj', 'napravi', 'izgradi', 'generiraj', 'razvij', 'stranica', 'aplikacija'
|
|
24
|
-
];
|
|
25
|
-
// Keywords indicating very large tasks
|
|
26
|
-
const veryComplexKeywords = [
|
|
27
|
-
'full', 'complete', 'entire', 'whole', 'multiple', 'all',
|
|
28
|
-
'cijeli', 'kompletni', 'sve', 'višestruki'
|
|
29
|
-
];
|
|
18
|
+
// Simple approach: just use base timeout with small multiplier for later iterations
|
|
19
|
+
// Complex calculations were causing more problems than they solved
|
|
30
20
|
let multiplier = 1.0;
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
multiplier = 2.0; // Double timeout for complex tasks
|
|
21
|
+
// Later iterations have larger context, may need slightly more time
|
|
22
|
+
if (iteration > 3) {
|
|
23
|
+
multiplier = 1.2;
|
|
35
24
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (hasVeryComplexKeyword) {
|
|
39
|
-
multiplier = 3.0; // Triple timeout for very complex tasks
|
|
25
|
+
if (iteration > 8) {
|
|
26
|
+
multiplier = 1.5;
|
|
40
27
|
}
|
|
41
|
-
//
|
|
42
|
-
if (prompt.length > 200) {
|
|
43
|
-
multiplier = Math.max(multiplier, 2.0);
|
|
44
|
-
}
|
|
45
|
-
if (prompt.length > 500) {
|
|
46
|
-
multiplier = Math.max(multiplier, 3.0);
|
|
47
|
-
}
|
|
48
|
-
// Later iterations might need more time (context is larger)
|
|
49
|
-
if (iteration > 5) {
|
|
50
|
-
multiplier *= 1.2;
|
|
51
|
-
}
|
|
52
|
-
if (iteration > 10) {
|
|
53
|
-
multiplier *= 1.3;
|
|
54
|
-
}
|
|
55
|
-
// Minimum 60 seconds, maximum 5 minutes for a single API call
|
|
28
|
+
// Minimum 120 seconds, maximum 5 minutes for a single API call
|
|
56
29
|
const calculatedTimeout = baseTimeout * multiplier;
|
|
57
|
-
return Math.min(Math.max(calculatedTimeout,
|
|
30
|
+
return Math.min(Math.max(calculatedTimeout, 120000), 300000);
|
|
58
31
|
}
|
|
59
32
|
import { parseToolCalls, executeTool, createActionLog, formatToolDefinitions, getOpenAITools, getAnthropicTools, parseOpenAIToolCalls, parseAnthropicToolCalls } from './tools.js';
|
|
60
33
|
import { config, getApiKey } from '../config/index.js';
|
|
@@ -261,10 +234,27 @@ async function agentChat(messages, systemPrompt, onChunk, abortSignal, dynamicTi
|
|
|
261
234
|
throw new Error(`API error: ${response.status} - ${errorText}`);
|
|
262
235
|
}
|
|
263
236
|
const data = await response.json();
|
|
237
|
+
// Debug: log raw API response
|
|
238
|
+
console.error(`[DEBUG] Raw API response:`, JSON.stringify(data, null, 2).substring(0, 1000));
|
|
264
239
|
if (protocol === 'openai') {
|
|
265
240
|
const message = data.choices?.[0]?.message;
|
|
266
241
|
const content = message?.content || '';
|
|
267
|
-
const
|
|
242
|
+
const rawToolCalls = message?.tool_calls || [];
|
|
243
|
+
// Debug: log raw tool calls from API
|
|
244
|
+
console.error(`[DEBUG] Raw tool_calls from API:`, JSON.stringify(rawToolCalls, null, 2));
|
|
245
|
+
const toolCalls = parseOpenAIToolCalls(rawToolCalls);
|
|
246
|
+
// Debug: log parsed tool calls
|
|
247
|
+
console.error(`[DEBUG] Parsed tool calls:`, JSON.stringify(toolCalls, null, 2));
|
|
248
|
+
// If no native tool calls, try parsing from content (some models return text-based)
|
|
249
|
+
if (toolCalls.length === 0 && content) {
|
|
250
|
+
console.error(`[DEBUG] No native tool calls, checking content for text-based calls...`);
|
|
251
|
+
console.error(`[DEBUG] Content preview:`, content.substring(0, 500));
|
|
252
|
+
const textToolCalls = parseToolCalls(content);
|
|
253
|
+
if (textToolCalls.length > 0) {
|
|
254
|
+
console.error(`[DEBUG] Found ${textToolCalls.length} text-based tool calls`);
|
|
255
|
+
return { content, toolCalls: textToolCalls, usedNativeTools: false };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
268
258
|
if (onChunk && content) {
|
|
269
259
|
onChunk(content);
|
|
270
260
|
}
|
|
@@ -636,13 +626,33 @@ export async function runAgent(prompt, projectContext, options = {}) {
|
|
|
636
626
|
toolCalls = textToolCalls;
|
|
637
627
|
}
|
|
638
628
|
}
|
|
639
|
-
// If no tool calls,
|
|
629
|
+
// If no tool calls, check if model wants to continue or is really done
|
|
640
630
|
if (toolCalls.length === 0) {
|
|
641
|
-
console.error(`[DEBUG] No tool calls at iteration ${iteration}
|
|
631
|
+
console.error(`[DEBUG] No tool calls at iteration ${iteration}`);
|
|
642
632
|
// Remove <think>...</think> tags from response (some models include thinking)
|
|
643
633
|
finalResponse = content.replace(/<think>[\s\S]*?<\/think>/gi, '').trim();
|
|
644
|
-
//
|
|
645
|
-
|
|
634
|
+
// Check if model indicates it wants to continue (incomplete response)
|
|
635
|
+
const continueIndicators = [
|
|
636
|
+
'let me', 'i will', 'i\'ll', 'now i', 'next i',
|
|
637
|
+
'creating', 'writing', 'generating',
|
|
638
|
+
'let\'s', 'going to', 'need to create', 'need to write'
|
|
639
|
+
];
|
|
640
|
+
const lowerResponse = finalResponse.toLowerCase();
|
|
641
|
+
const wantsToContinue = continueIndicators.some(indicator => lowerResponse.includes(indicator));
|
|
642
|
+
// Also check if there were tool call parsing failures in this iteration
|
|
643
|
+
// by looking for incomplete actions (e.g., write_file without content)
|
|
644
|
+
const hasIncompleteWork = iteration < 10 && wantsToContinue && finalResponse.length < 500;
|
|
645
|
+
if (hasIncompleteWork) {
|
|
646
|
+
console.error(`[DEBUG] Model wants to continue, prompting for next action`);
|
|
647
|
+
messages.push({ role: 'assistant', content });
|
|
648
|
+
messages.push({
|
|
649
|
+
role: 'user',
|
|
650
|
+
content: 'Continue. Execute the tool calls now.'
|
|
651
|
+
});
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
// Model is done
|
|
655
|
+
console.error(`[DEBUG] Agent finished at iteration ${iteration}`);
|
|
646
656
|
break;
|
|
647
657
|
}
|
|
648
658
|
// Add assistant response to history
|
package/dist/utils/tools.js
CHANGED
|
@@ -204,20 +204,40 @@ function normalizeToolName(name) {
|
|
|
204
204
|
export function parseOpenAIToolCalls(toolCalls) {
|
|
205
205
|
if (!toolCalls || !Array.isArray(toolCalls))
|
|
206
206
|
return [];
|
|
207
|
-
|
|
207
|
+
const parsed = [];
|
|
208
|
+
for (const tc of toolCalls) {
|
|
209
|
+
const toolName = normalizeToolName(tc.function?.name || '');
|
|
210
|
+
if (!toolName)
|
|
211
|
+
continue;
|
|
208
212
|
let parameters = {};
|
|
209
213
|
try {
|
|
210
214
|
parameters = JSON.parse(tc.function?.arguments || '{}');
|
|
211
215
|
}
|
|
212
|
-
catch {
|
|
213
|
-
|
|
216
|
+
catch (e) {
|
|
217
|
+
// JSON parsing failed - likely truncated response
|
|
218
|
+
console.error(`[DEBUG] Failed to parse tool arguments for ${toolName}:`, tc.function?.arguments?.substring(0, 100));
|
|
219
|
+
continue; // Skip this tool call entirely
|
|
214
220
|
}
|
|
215
|
-
|
|
216
|
-
|
|
221
|
+
// Validate required parameters for specific tools
|
|
222
|
+
if (toolName === 'write_file' && (!parameters.path || parameters.content === undefined)) {
|
|
223
|
+
console.error(`[DEBUG] Skipping write_file with missing path or content`);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (toolName === 'read_file' && !parameters.path) {
|
|
227
|
+
console.error(`[DEBUG] Skipping read_file with missing path`);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (toolName === 'edit_file' && (!parameters.path || parameters.old_text === undefined || parameters.new_text === undefined)) {
|
|
231
|
+
console.error(`[DEBUG] Skipping edit_file with missing parameters`);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
parsed.push({
|
|
235
|
+
tool: toolName,
|
|
217
236
|
parameters,
|
|
218
237
|
id: tc.id,
|
|
219
|
-
};
|
|
220
|
-
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return parsed;
|
|
221
241
|
}
|
|
222
242
|
/**
|
|
223
243
|
* Parse tool calls from Anthropic response
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeep",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
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",
|