codeep 1.0.129 → 1.0.131

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/app.js CHANGED
@@ -35,6 +35,7 @@ import { saveContext, loadContext, clearContext, mergeContext } from './utils/co
35
35
  import { performCodeReview, formatReviewResult } from './utils/codeReview.js';
36
36
  import { learnFromProject, addCustomRule, getLearningStatus } from './utils/learning.js';
37
37
  import { getAllSkills, findSkill, formatSkillsList, formatSkillHelp, generateSkillPrompt, saveCustomSkill, deleteCustomSkill, parseSkillChain, parseSkillArgs, searchSkills, trackSkillUsage, getSkillStats } from './utils/skills.js';
38
+ import { AgentStatusBar } from './components/AgentProgress.js';
38
39
  import { createActionLog } from './utils/tools.js';
39
40
  import { scanProject, saveProjectIntelligence, loadProjectIntelligence, generateContextFromIntelligence } from './utils/projectIntelligence.js';
40
41
  export const App = () => {
@@ -325,76 +326,44 @@ export const App = () => {
325
326
  return updated;
326
327
  });
327
328
  // Add formatted action to streaming content (stays in chat)
329
+ // NO CODE DISPLAY - just clean action lines to prevent terminal jumping
328
330
  const actionType = actionLog.type;
329
331
  const target = actionLog.target.split('/').pop() || actionLog.target; // Just filename
330
- const fullPath = actionLog.target;
331
332
  const status = actionLog.result === 'success' ? '✓' : '✗';
332
- const statusColor = actionLog.result === 'success' ? '' : ' (failed)';
333
- // Get file extension for syntax highlighting
334
- const getLanguage = (filename) => {
335
- const ext = filename.split('.').pop()?.toLowerCase() || '';
336
- const langMap = {
337
- 'ts': 'typescript', 'tsx': 'typescript', 'js': 'javascript', 'jsx': 'javascript',
338
- 'py': 'python', 'rb': 'ruby', 'go': 'go', 'rs': 'rust', 'java': 'java',
339
- 'php': 'php', 'css': 'css', 'scss': 'css', 'html': 'html', 'vue': 'html',
340
- 'json': 'json', 'yml': 'yaml', 'yaml': 'yaml', 'md': 'markdown',
341
- 'sh': 'bash', 'bash': 'bash', 'sql': 'sql',
342
- };
343
- return langMap[ext] || ext || 'code';
344
- };
333
+ const failedText = actionLog.result === 'error' ? '' : '';
334
+ // Count lines in content
335
+ const lineCount = actionLog.details ? actionLog.details.split('\n').length : 0;
345
336
  let actionLine = '';
346
- if (actionType === 'write' && actionLog.details) {
347
- // Show full code with syntax highlighting
348
- const lang = getLanguage(target);
349
- actionLine = `${status} **Created ${fullPath}**\n\`\`\`${lang}\n${actionLog.details}\n\`\`\``;
350
- }
351
- else if (actionType === 'write') {
352
- actionLine = `${status} Created **${target}**${statusColor}`;
353
- }
354
- else if (actionType === 'edit' && actionLog.details) {
355
- // Show edited code with syntax highlighting
356
- const lang = getLanguage(target);
357
- actionLine = `${status} **Edited ${fullPath}**\n\`\`\`${lang}\n${actionLog.details}\n\`\`\``;
337
+ if (actionType === 'write') {
338
+ actionLine = `${status} Created **${target}**${lineCount > 0 ? ` (${lineCount} lines)` : ''}${failedText}`;
358
339
  }
359
340
  else if (actionType === 'edit') {
360
- actionLine = `${status} Edited **${target}**${statusColor}`;
341
+ actionLine = `${status} Edited **${target}**${lineCount > 0 ? ` (${lineCount} lines)` : ''}${failedText}`;
361
342
  }
362
343
  else if (actionType === 'read') {
363
- // Don't show read actions in stream - too noisy
364
- return;
344
+ actionLine = `→ Reading **${target}**`;
365
345
  }
366
346
  else if (actionType === 'delete') {
367
- actionLine = `${status} Deleted **${fullPath}**${statusColor}`;
347
+ actionLine = `${status} Deleted **${target}**${failedText}`;
368
348
  }
369
349
  else if (actionType === 'command') {
370
- const cmd = actionLog.target;
371
- // Show command output if available
372
- if (actionLog.details && actionLog.details.trim()) {
373
- actionLine = `${status} Ran \`${cmd}\`\n\`\`\`\n${actionLog.details.slice(0, 500)}${actionLog.details.length > 500 ? '\n...(truncated)' : ''}\n\`\`\``;
374
- }
375
- else {
376
- actionLine = `${status} Ran \`${cmd}\`${statusColor}`;
377
- }
350
+ const cmd = actionLog.target.length > 40 ? actionLog.target.slice(0, 40) + '...' : actionLog.target;
351
+ actionLine = `${status} Ran \`${cmd}\`${failedText}`;
378
352
  }
379
353
  else if (actionType === 'search') {
380
- // Don't show search actions - too noisy
381
- return;
354
+ actionLine = `→ Searching **${target}**`;
382
355
  }
383
356
  else if (actionType === 'mkdir') {
384
- actionLine = `${status} Created directory **${fullPath}**${statusColor}`;
357
+ actionLine = `${status} Created dir **${target}**`;
385
358
  }
386
359
  else if (actionType === 'fetch') {
387
- actionLine = `${status} Fetched ${target}${statusColor}`;
360
+ actionLine = `→ Fetching **${target}**`;
388
361
  }
389
362
  else if (actionType === 'list') {
390
- // Don't show list actions
391
- return;
392
- }
393
- else {
394
- actionLine = `◦ ${actionType}: ${target}`;
363
+ actionLine = `→ Listing **${target}**`;
395
364
  }
396
365
  if (actionLine) {
397
- setAgentStreamingContent(prev => prev + (prev ? '\n\n' : '') + actionLine);
366
+ setAgentStreamingContent(prev => prev + (prev ? '\n' : '') + actionLine);
398
367
  }
399
368
  },
400
369
  onThinking: (text) => {
@@ -411,10 +380,34 @@ export const App = () => {
411
380
  abortSignal: controller.signal,
412
381
  });
413
382
  setAgentResult(result);
414
- // Add agent summary as assistant message
383
+ // Build action statistics
384
+ const stats = {
385
+ created: result.actions.filter(a => a.type === 'write' && a.result === 'success').length,
386
+ edited: result.actions.filter(a => a.type === 'edit' && a.result === 'success').length,
387
+ deleted: result.actions.filter(a => a.type === 'delete' && a.result === 'success').length,
388
+ commands: result.actions.filter(a => a.type === 'command' && a.result === 'success').length,
389
+ reads: result.actions.filter(a => a.type === 'read').length,
390
+ errors: result.actions.filter(a => a.result === 'error').length,
391
+ };
392
+ // Format statistics line
393
+ const statParts = [];
394
+ if (stats.created > 0)
395
+ statParts.push(`+${stats.created} created`);
396
+ if (stats.edited > 0)
397
+ statParts.push(`~${stats.edited} edited`);
398
+ if (stats.deleted > 0)
399
+ statParts.push(`-${stats.deleted} deleted`);
400
+ if (stats.commands > 0)
401
+ statParts.push(`${stats.commands} commands`);
402
+ if (stats.errors > 0)
403
+ statParts.push(`${stats.errors} errors`);
404
+ const statsLine = statParts.length > 0
405
+ ? `\n\n---\n**${result.iterations} steps** | ${statParts.join(' | ')}`
406
+ : '';
407
+ // Add agent summary as assistant message with stats
415
408
  const summaryMessage = {
416
409
  role: 'assistant',
417
- content: result.finalResponse || formatAgentResult(result),
410
+ content: (result.finalResponse || formatAgentResult(result)) + statsLine,
418
411
  };
419
412
  setMessages(prev => [...prev, summaryMessage]);
420
413
  // Auto-save session
@@ -1444,11 +1437,11 @@ export const App = () => {
1444
1437
  // Helper to check if we're showing an inline menu
1445
1438
  const isInlineMenu = ['help', 'status', 'settings', 'sessions', 'sessions-delete',
1446
1439
  'logout', 'search', 'export', 'model', 'provider', 'protocol', 'language'].includes(screen);
1447
- return (_jsxs(Box, { flexDirection: "column", children: [messages.length === 0 && !isLoading && _jsx(Logo, {}), messages.length === 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Box, { justifyContent: "center", children: _jsxs(Text, { children: ["Connected to ", _jsx(Text, { color: "#f02a30", children: config.get('model') }), ". Type ", _jsx(Text, { color: "#f02a30", children: "/help" }), " for commands."] }) }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "cyan", bold: true, children: "Welcome to Codeep - Your AI Coding Assistant" }) }), _jsx(Text, { children: " " }), _jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Ask questions about your code or request implementations"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Use ", _jsxs(Text, { color: "cyan", children: ["/agent ", '<task>'] }), " for autonomous task execution"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Type ", _jsx(Text, { color: "cyan", children: "/diff" }), " to review changes, ", _jsx(Text, { color: "cyan", children: "/commit" }), " to generate commit messages"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Configure settings with ", _jsx(Text, { color: "cyan", children: "/settings" }), " - enable Agent Mode for auto-execution"] })] }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "gray", children: "Start typing your message or use a command to begin..." }) }), _jsx(Text, { children: " " })] })), _jsx(MessageList, { messages: messages, streamingContent: streamingContent, agentStreamingContent: isAgentRunning ? agentStreamingContent : undefined }, sessionId), isLoading && !isAgentRunning && _jsx(Loading, { isStreaming: !!streamingContent }), pendingFileChanges.length > 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#f02a30", padding: 1, marginY: 1, children: [_jsxs(Text, { color: "#f02a30", bold: true, children: ["\u2713 Detected ", pendingFileChanges.length, " file change(s):"] }), pendingFileChanges.map((change, i) => {
1440
+ return (_jsxs(Box, { flexDirection: "column", children: [messages.length === 0 && !isLoading && _jsx(Logo, {}), messages.length === 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Box, { justifyContent: "center", children: _jsxs(Text, { children: ["Connected to ", _jsx(Text, { color: "#f02a30", children: config.get('model') }), ". Type ", _jsx(Text, { color: "#f02a30", children: "/help" }), " for commands."] }) }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "cyan", bold: true, children: "Welcome to Codeep - Your AI Coding Assistant" }) }), _jsx(Text, { children: " " }), _jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Ask questions about your code or request implementations"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Use ", _jsxs(Text, { color: "cyan", children: ["/agent ", '<task>'] }), " for autonomous task execution"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Type ", _jsx(Text, { color: "cyan", children: "/diff" }), " to review changes, ", _jsx(Text, { color: "cyan", children: "/commit" }), " to generate commit messages"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "\u2022" }), " Configure settings with ", _jsx(Text, { color: "cyan", children: "/settings" }), " - enable Agent Mode for auto-execution"] })] }), _jsx(Text, { children: " " }), _jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "gray", children: "Start typing your message or use a command to begin..." }) }), _jsx(Text, { children: " " })] })), _jsx(MessageList, { messages: messages, streamingContent: streamingContent, agentStreamingContent: isAgentRunning ? agentStreamingContent : undefined }, sessionId), isLoading && !isAgentRunning && _jsx(Loading, { isStreaming: !!streamingContent }), isAgentRunning && (_jsx(AgentStatusBar, { iteration: agentIteration, actionsCount: agentActions.length, dryRun: agentDryRun, currentAction: agentActions.length > 0 ? `${agentActions[agentActions.length - 1].type}: ${agentActions[agentActions.length - 1].target.split('/').pop()}` : undefined })), pendingFileChanges.length > 0 && !isLoading && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#f02a30", padding: 1, marginY: 1, children: [_jsxs(Text, { color: "#f02a30", bold: true, children: ["\u2713 Detected ", pendingFileChanges.length, " file change(s):"] }), pendingFileChanges.map((change, i) => {
1448
1441
  const actionColor = change.action === 'delete' ? 'red' : change.action === 'edit' ? 'yellow' : 'green';
1449
1442
  const actionLabel = change.action === 'delete' ? 'DELETE' : change.action === 'edit' ? 'EDIT' : 'CREATE';
1450
1443
  return (_jsxs(Text, { children: ["\u2022 ", _jsxs(Text, { color: actionColor, children: ["[", actionLabel, "]"] }), " ", change.path, change.action !== 'delete' && change.content.includes('\n') && ` (${change.content.split('\n').length} lines)`] }, i));
1451
- }), _jsx(Text, { children: " " }), _jsxs(Text, { children: ["Apply changes? ", _jsx(Text, { color: "#f02a30", bold: true, children: "[Y/n]" })] }), _jsx(Text, { color: "cyan", children: "Press Y to apply, N or Esc to reject" })] })), notification && (_jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "cyan", children: notification }) })), !isInlineMenu && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "#f02a30", children: '─'.repeat(Math.max(20, stdout?.columns || 80)) }), _jsx(Box, { paddingX: 1, children: _jsx(ChatInput, { onSubmit: handleSubmit, disabled: isLoading || isAgentRunning || pendingFileChanges.length > 0, history: inputHistory, clearTrigger: clearInputTrigger }) }), _jsx(Text, { color: "#f02a30", children: '─'.repeat(Math.max(20, stdout?.columns || 80)) }), isAgentRunning && (_jsxs(Box, { paddingX: 1, children: [_jsxs(Text, { color: agentDryRun ? 'yellow' : '#f02a30', children: [agentDryRun ? '[DRY RUN]' : '[AGENT]', " Step ", agentIteration, " | ", agentActions.length, " actions"] }), _jsx(Text, { color: "gray", children: " | Press Esc to stop" })] }))] })), isInlineMenu && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "#f02a30", children: '─'.repeat(stdout?.columns || 80) }), screen === 'help' && _jsx(Help, { projectPath: projectPath }), screen === 'status' && _jsx(Status, {}), screen === 'settings' && (_jsx(Settings, { onClose: () => setScreen('chat'), notify: notify, hasWriteAccess: hasWriteAccess, hasProjectContext: !!projectContext })), screen === 'sessions' && (_jsx(Sessions, { history: messages, onLoad: handleSessionLoad, onClose: () => setScreen('chat'), projectPath: projectPath })), screen === 'sessions-delete' && (_jsx(Sessions, { history: messages, onLoad: handleSessionLoad, onClose: () => setScreen('chat'), onDelete: (name) => {
1444
+ }), _jsx(Text, { children: " " }), _jsxs(Text, { children: ["Apply changes? ", _jsx(Text, { color: "#f02a30", bold: true, children: "[Y/n]" })] }), _jsx(Text, { color: "cyan", children: "Press Y to apply, N or Esc to reject" })] })), notification && (_jsx(Box, { justifyContent: "center", children: _jsx(Text, { color: "cyan", children: notification }) })), !isInlineMenu && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "#f02a30", children: '─'.repeat(Math.max(20, stdout?.columns || 80)) }), _jsx(Box, { paddingX: 1, children: _jsx(ChatInput, { onSubmit: handleSubmit, disabled: isLoading || isAgentRunning || pendingFileChanges.length > 0, history: inputHistory, clearTrigger: clearInputTrigger }) }), _jsx(Text, { color: "#f02a30", children: '─'.repeat(Math.max(20, stdout?.columns || 80)) })] })), isInlineMenu && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "#f02a30", children: '─'.repeat(stdout?.columns || 80) }), screen === 'help' && _jsx(Help, { projectPath: projectPath }), screen === 'status' && _jsx(Status, {}), screen === 'settings' && (_jsx(Settings, { onClose: () => setScreen('chat'), notify: notify, hasWriteAccess: hasWriteAccess, hasProjectContext: !!projectContext })), screen === 'sessions' && (_jsx(Sessions, { history: messages, onLoad: handleSessionLoad, onClose: () => setScreen('chat'), projectPath: projectPath })), screen === 'sessions-delete' && (_jsx(Sessions, { history: messages, onLoad: handleSessionLoad, onClose: () => setScreen('chat'), onDelete: (name) => {
1452
1445
  notify(`Deleted: ${name}`);
1453
1446
  setScreen('chat');
1454
1447
  }, deleteMode: true, projectPath: projectPath })), screen === 'logout' && (_jsx(LogoutPicker, { onLogout: (providerId) => {
@@ -45,4 +45,15 @@ interface ChangesListProps {
45
45
  actions: ActionLog[];
46
46
  }
47
47
  export declare const ChangesList: React.FC<ChangesListProps>;
48
+ /**
49
+ * Agent Status Bar - fixed height, with spinner animation
50
+ * Shows above input, doesn't cause chat jumping
51
+ */
52
+ interface AgentStatusBarProps {
53
+ iteration: number;
54
+ actionsCount: number;
55
+ dryRun?: boolean;
56
+ currentAction?: string;
57
+ }
58
+ export declare const AgentStatusBar: React.FC<AgentStatusBarProps>;
48
59
  export {};
@@ -361,3 +361,8 @@ export const ChangesList = ({ actions }) => {
361
361
  }
362
362
  return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [_jsxs(Text, { color: "cyan", bold: true, children: ["Session Changes (", totalChanges, " total)"] }), _jsx(Text, { color: "cyan", children: '─'.repeat(40) }), writes.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "green", bold: true, children: ["Created (", writes.length, "):"] }), writes.map((w, i) => (_jsxs(Text, { children: [" + ", w.target] }, i)))] })), edits.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "yellow", bold: true, children: ["Modified (", edits.length, "):"] }), edits.map((e, i) => (_jsxs(Text, { children: [" ~ ", e.target] }, i)))] })), deletes.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "red", bold: true, children: ["Deleted (", deletes.length, "):"] }), deletes.map((d, i) => (_jsxs(Text, { children: [" - ", d.target] }, i)))] })), mkdirs.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "blue", bold: true, children: ["Directories (", mkdirs.length, "):"] }), mkdirs.map((m, i) => (_jsxs(Text, { children: [" + ", m.target, "/"] }, i)))] }))] }));
363
363
  };
364
+ export const AgentStatusBar = memo(({ iteration, actionsCount, dryRun, currentAction }) => {
365
+ const color = dryRun ? 'yellow' : '#f02a30';
366
+ return (_jsxs(Box, { borderStyle: "round", borderColor: color, paddingX: 1, marginY: 1, height: 3, children: [_jsx(AgentSpinner, { color: color }), _jsxs(Text, { color: color, bold: true, children: [" ", dryRun ? 'DRY RUN' : 'AGENT', " "] }), _jsxs(Text, { color: "cyan", children: ["Step ", iteration] }), _jsx(Text, { color: "gray", children: " | " }), _jsxs(Text, { color: "white", children: [actionsCount, " actions"] }), currentAction && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "gray", children: " | " }), _jsx(Text, { color: "cyan", children: currentAction })] })), _jsx(Text, { color: "gray", children: " | Press " }), _jsx(Text, { color: color, children: "Esc" }), _jsx(Text, { color: "gray", children: " to stop" })] }));
367
+ });
368
+ AgentStatusBar.displayName = 'AgentStatusBar';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.0.129",
3
+ "version": "1.0.131",
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",