codeep 1.0.21 → 1.0.23

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.
@@ -62,7 +62,7 @@ import { getProviderBaseUrl, getProviderAuthHeader, supportsNativeTools } from '
62
62
  import { startSession, endSession, undoLastAction, undoAllActions, getCurrentSession, getRecentSessions, formatSession } from './history.js';
63
63
  import { runAllVerifications, formatErrorsForAgent, hasVerificationErrors, getVerificationSummary } from './verify.js';
64
64
  import { gatherSmartContext, formatSmartContext, extractTargetFile } from './smartContext.js';
65
- import { planTasks, getNextTask, formatTaskPlan } from './taskPlanner.js';
65
+ import { planTasks, formatTaskPlan } from './taskPlanner.js';
66
66
  const DEFAULT_OPTIONS = {
67
67
  maxIterations: 100, // Increased for large tasks
68
68
  maxDuration: 20 * 60 * 1000, // 20 minutes
@@ -636,83 +636,13 @@ export async function runAgent(prompt, projectContext, options = {}) {
636
636
  toolCalls = textToolCalls;
637
637
  }
638
638
  }
639
- // If no tool calls, check if agent is really done
639
+ // If no tool calls, agent is done - simple and clean like Claude Code/Aider
640
640
  if (toolCalls.length === 0) {
641
- console.error(`[DEBUG] No tool calls at iteration ${iteration}, content length: ${content.length}, actions so far: ${actions.length}`);
642
- console.error(`[DEBUG] Response preview:`, content.substring(0, 200));
641
+ console.error(`[DEBUG] No tool calls at iteration ${iteration}, agent finished`);
643
642
  // Remove <think>...</think> tags from response (some models include thinking)
644
643
  finalResponse = content.replace(/<think>[\s\S]*?<\/think>/gi, '').trim();
645
- // CRITICAL: Don't stop prematurely if we haven't done much work yet
646
- // Check if prompt contains "create", "build", "make", "implement", "add" etc.
647
- const taskKeywords = ['create', 'build', 'make', 'implement', 'add', 'generate', 'write', 'setup', 'develop', 'kreiraj', 'napravi', 'dodaj', 'website', 'app', 'feature'];
648
- const promptLowerCase = prompt.toLowerCase();
649
- const isCreationTask = taskKeywords.some(kw => promptLowerCase.includes(kw));
650
- // Only count actual FILE writes, not directories
651
- const hasCreatedFiles = actions.some(a => a.type === 'write');
652
- const writeFileCount = actions.filter(a => a.type === 'write').length;
653
- const hasMkdir = actions.some(a => a.type === 'mkdir');
654
- const isVeryEarlyIteration = iteration <= 5; // Extended to 5 iterations
655
- console.error(`[DEBUG] Task check: isCreationTask=${isCreationTask}, hasCreatedFiles=${hasCreatedFiles}, writeFileCount=${writeFileCount}, hasMkdir=${hasMkdir}, iteration=${iteration}`);
656
- console.error(`[DEBUG] Actions breakdown:`, actions.map(a => `${a.type}:${a.target}`).join(', '));
657
- // STRICT RULE: If it's a creation task, agent MUST create FILES (not just directories)
658
- // Creating a directory is not enough - we need actual file content
659
- if (isCreationTask && !hasCreatedFiles && iteration <= 10) {
660
- console.error(`[DEBUG] BLOCKING early stop - creation task detected but NO files created yet (iteration ${iteration}, ${actions.length} actions)`);
661
- // Force agent to create files
662
- messages.push({ role: 'assistant', content: finalResponse });
663
- messages.push({
664
- role: 'user',
665
- content: `❌ STOP. You have NOT created any files yet!\n\nYou MUST use write_file and create_directory tools to create the actual files I asked for.\n\nDo NOT respond with explanations. Execute the tools NOW:\n1. Use create_directory if needed\n2. Use write_file to create EACH file\n3. Only after creating ALL files, respond with a summary.`
666
- });
667
- finalResponse = ''; // Reset
668
- continue;
669
- }
670
- // If creation task but not enough files created, keep pushing
671
- if (isCreationTask && writeFileCount < 2 && iteration <= 10) {
672
- console.error(`[DEBUG] BLOCKING early stop - only ${writeFileCount} files created, need more (iteration ${iteration})`);
673
- messages.push({ role: 'assistant', content: finalResponse });
674
- messages.push({
675
- role: 'user',
676
- content: `You've only created ${writeFileCount} file(s). The task requires creating multiple files. Continue creating the remaining files now.`
677
- });
678
- finalResponse = ''; // Reset
679
- continue;
680
- }
681
- // General safety: very few actions in early iterations
682
- if (isVeryEarlyIteration && actions.length < 2) {
683
- console.error(`[DEBUG] BLOCKING early stop - very few actions (iteration ${iteration}, only ${actions.length} actions)`);
684
- messages.push({ role: 'assistant', content: finalResponse });
685
- messages.push({
686
- role: 'user',
687
- content: `Continue working on the task. Use the available tools to complete what I asked for.`
688
- });
689
- finalResponse = ''; // Reset
690
- continue;
691
- }
692
- // Check if we're using task planning and there are more tasks
693
- if (taskPlan && taskPlan.tasks.some(t => t.status === 'pending')) {
694
- const nextTask = getNextTask(taskPlan.tasks);
695
- if (nextTask) {
696
- // Mark previous task as completed
697
- const prevTask = taskPlan.tasks.find(t => t.status === 'in_progress' && t.id !== nextTask.id);
698
- if (prevTask) {
699
- prevTask.status = 'completed';
700
- }
701
- // Move to next task
702
- nextTask.status = 'in_progress';
703
- opts.onTaskUpdate?.(nextTask);
704
- // Build progress summary
705
- const completedTasks = taskPlan.tasks.filter(t => t.status === 'completed');
706
- const progressSummary = completedTasks.map(t => `✓ ${t.id}. ${t.description}`).join('\n');
707
- messages.push({ role: 'assistant', content: finalResponse });
708
- messages.push({
709
- role: 'user',
710
- content: `Good! Task ${prevTask?.id} done.\n\nCompleted:\n${progressSummary}\n\nNEXT TASK (do it now):\n${nextTask.id}. ${nextTask.description}\n\nUse your tools immediately to complete this task. Do NOT ask for permission or confirmation.`
711
- });
712
- finalResponse = ''; // Reset for next task
713
- continue;
714
- }
715
- }
644
+ // Trust the model - if it says it's done, it's done
645
+ // No forcing, no blocking, no artificial requirements
716
646
  break;
717
647
  }
718
648
  // Add assistant response to history
@@ -196,9 +196,6 @@ export declare function getOpenAITools(): OpenAITool[];
196
196
  * Get tools in Anthropic Tool Use format
197
197
  */
198
198
  export declare function getAnthropicTools(): AnthropicTool[];
199
- /**
200
- * Parse tool calls from OpenAI response
201
- */
202
199
  export declare function parseOpenAIToolCalls(toolCalls: any[]): ToolCall[];
203
200
  /**
204
201
  * Parse tool calls from Anthropic response
@@ -174,6 +174,33 @@ export function getAnthropicTools() {
174
174
  /**
175
175
  * Parse tool calls from OpenAI response
176
176
  */
177
+ /**
178
+ * Normalize tool name to lowercase with underscores
179
+ */
180
+ function normalizeToolName(name) {
181
+ const toolNameMap = {
182
+ 'executecommand': 'execute_command',
183
+ 'execute_command': 'execute_command',
184
+ 'readfile': 'read_file',
185
+ 'read_file': 'read_file',
186
+ 'writefile': 'write_file',
187
+ 'write_file': 'write_file',
188
+ 'editfile': 'edit_file',
189
+ 'edit_file': 'edit_file',
190
+ 'deletefile': 'delete_file',
191
+ 'delete_file': 'delete_file',
192
+ 'listfiles': 'list_files',
193
+ 'list_files': 'list_files',
194
+ 'searchcode': 'search_code',
195
+ 'search_code': 'search_code',
196
+ 'createdirectory': 'create_directory',
197
+ 'create_directory': 'create_directory',
198
+ 'fetchurl': 'fetch_url',
199
+ 'fetch_url': 'fetch_url',
200
+ };
201
+ const lower = name.toLowerCase().replace(/-/g, '_');
202
+ return toolNameMap[lower] || lower;
203
+ }
177
204
  export function parseOpenAIToolCalls(toolCalls) {
178
205
  if (!toolCalls || !Array.isArray(toolCalls))
179
206
  return [];
@@ -186,7 +213,7 @@ export function parseOpenAIToolCalls(toolCalls) {
186
213
  parameters = {};
187
214
  }
188
215
  return {
189
- tool: tc.function?.name || '',
216
+ tool: normalizeToolName(tc.function?.name || ''),
190
217
  parameters,
191
218
  id: tc.id,
192
219
  };
@@ -201,7 +228,7 @@ export function parseAnthropicToolCalls(content) {
201
228
  return content
202
229
  .filter(block => block.type === 'tool_use')
203
230
  .map(block => ({
204
- tool: block.name || '',
231
+ tool: normalizeToolName(block.name || ''),
205
232
  parameters: block.input || {},
206
233
  id: block.id,
207
234
  }))
@@ -386,7 +413,7 @@ function tryParseToolCall(str) {
386
413
  const parsed = JSON.parse(cleaned);
387
414
  if (parsed.tool && typeof parsed.tool === 'string') {
388
415
  return {
389
- tool: parsed.tool,
416
+ tool: normalizeToolName(parsed.tool),
390
417
  parameters: parsed.parameters || {},
391
418
  id: parsed.id,
392
419
  };
@@ -394,9 +421,9 @@ function tryParseToolCall(str) {
394
421
  }
395
422
  catch {
396
423
  // Try to extract tool name and parameters manually for malformed JSON
397
- const toolMatch = str.match(/"tool"\s*:\s*"([^"]+)"/);
424
+ const toolMatch = str.match(/"tool"\s*:\s*"([^"]+)"/i);
398
425
  if (toolMatch) {
399
- const tool = toolMatch[1];
426
+ const tool = normalizeToolName(toolMatch[1]);
400
427
  const params = {};
401
428
  // Extract simple string parameters
402
429
  const paramMatches = str.matchAll(/"(\w+)"\s*:\s*"([^"]*)"/g);
@@ -432,7 +459,9 @@ function validatePath(path, projectRoot) {
432
459
  * Execute a tool call
433
460
  */
434
461
  export function executeTool(toolCall, projectRoot) {
435
- const { tool, parameters } = toolCall;
462
+ // Normalize tool name to handle case variations (WRITE_FILE -> write_file)
463
+ const tool = normalizeToolName(toolCall.tool);
464
+ const parameters = toolCall.parameters;
436
465
  try {
437
466
  switch (tool) {
438
467
  case 'read_file': {
@@ -705,6 +734,8 @@ function listDirectory(dir, projectRoot, recursive, prefix = '') {
705
734
  * Create action log from tool result
706
735
  */
707
736
  export function createActionLog(toolCall, result) {
737
+ // Normalize tool name to handle case variations
738
+ const normalizedTool = normalizeToolName(toolCall.tool);
708
739
  const typeMap = {
709
740
  read_file: 'read',
710
741
  write_file: 'write',
@@ -722,7 +753,7 @@ export function createActionLog(toolCall, result) {
722
753
  toolCall.parameters.url ||
723
754
  'unknown';
724
755
  return {
725
- type: typeMap[toolCall.tool] || 'command',
756
+ type: typeMap[normalizedTool] || 'command',
726
757
  target,
727
758
  result: result.success ? 'success' : 'error',
728
759
  details: result.success ? result.output.slice(0, 200) : result.error,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
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",