codeep 1.1.7 → 1.1.8
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 +4 -18
- package/dist/components/AgentActions.d.ts +19 -0
- package/dist/components/AgentActions.js +121 -0
- package/dist/utils/agent.js +0 -3
- package/dist/utils/console.js +0 -3
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -35,9 +35,9 @@ 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 { AgentActions } from './components/AgentActions.js';
|
|
38
39
|
import { createActionLog } from './utils/tools.js';
|
|
39
40
|
import { scanProject, saveProjectIntelligence, loadProjectIntelligence, generateContextFromIntelligence } from './utils/projectIntelligence.js';
|
|
40
|
-
import { logAction, startAgentSpinner, updateSpinner, stopSpinner, logAgentComplete, logSeparator, setAgentRunning } from './utils/console.js';
|
|
41
41
|
export const App = () => {
|
|
42
42
|
const { exit } = useApp();
|
|
43
43
|
const { stdout } = useStdout();
|
|
@@ -269,10 +269,6 @@ export const App = () => {
|
|
|
269
269
|
setAgentResult(null);
|
|
270
270
|
setAgentDryRun(dryRun);
|
|
271
271
|
setAgentStreamingContent(''); // Reset streaming content
|
|
272
|
-
// Start console spinner for agent
|
|
273
|
-
logSeparator();
|
|
274
|
-
setAgentRunning(true, dryRun);
|
|
275
|
-
startAgentSpinner('Starting...', dryRun);
|
|
276
272
|
// Add user message
|
|
277
273
|
const userMessage = {
|
|
278
274
|
role: 'user',
|
|
@@ -287,7 +283,6 @@ export const App = () => {
|
|
|
287
283
|
dryRun,
|
|
288
284
|
onIteration: (iteration, message) => {
|
|
289
285
|
setAgentIteration(iteration);
|
|
290
|
-
updateSpinner(`Step ${iteration}`, dryRun);
|
|
291
286
|
},
|
|
292
287
|
onToolCall: (tool) => {
|
|
293
288
|
// Create action log with content for live code preview
|
|
@@ -330,8 +325,7 @@ export const App = () => {
|
|
|
330
325
|
}
|
|
331
326
|
return updated;
|
|
332
327
|
});
|
|
333
|
-
//
|
|
334
|
-
logAction(actionLog.type, actionLog.target, actionLog.result, actionLog.details);
|
|
328
|
+
// Actions are now displayed via AgentActions component with Static
|
|
335
329
|
},
|
|
336
330
|
onThinking: (text) => {
|
|
337
331
|
// Strip <think> and <tool_call> tags from thinking text
|
|
@@ -357,11 +351,7 @@ export const App = () => {
|
|
|
357
351
|
reads: result.actions.filter(a => a.type === 'read').length,
|
|
358
352
|
errors: result.actions.filter(a => a.result === 'error').length,
|
|
359
353
|
};
|
|
360
|
-
//
|
|
361
|
-
setAgentRunning(false);
|
|
362
|
-
logAgentComplete(stats, result.success);
|
|
363
|
-
logSeparator();
|
|
364
|
-
// Add agent summary as assistant message (without duplicate stats - they're in console)
|
|
354
|
+
// Add agent summary as assistant message
|
|
365
355
|
const summaryMessage = {
|
|
366
356
|
role: 'assistant',
|
|
367
357
|
content: result.finalResponse || formatAgentResult(result),
|
|
@@ -381,13 +371,9 @@ export const App = () => {
|
|
|
381
371
|
}
|
|
382
372
|
catch (error) {
|
|
383
373
|
const err = error;
|
|
384
|
-
setAgentRunning(false);
|
|
385
|
-
stopSpinner();
|
|
386
374
|
notify(`Agent error: ${err.message}`);
|
|
387
375
|
}
|
|
388
376
|
finally {
|
|
389
|
-
setAgentRunning(false);
|
|
390
|
-
stopSpinner();
|
|
391
377
|
setIsAgentRunning(false);
|
|
392
378
|
setAbortController(null);
|
|
393
379
|
setAgentThinking('');
|
|
@@ -1398,7 +1384,7 @@ export const App = () => {
|
|
|
1398
1384
|
// Helper to check if we're showing an inline menu
|
|
1399
1385
|
const isInlineMenu = ['help', 'status', 'settings', 'sessions', 'sessions-delete',
|
|
1400
1386
|
'logout', 'search', 'export', 'model', 'provider', 'protocol', 'language'].includes(screen);
|
|
1401
|
-
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 }, 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) => {
|
|
1387
|
+
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 }, sessionId), isLoading && !isAgentRunning && _jsx(Loading, { isStreaming: !!streamingContent }), isAgentRunning && (_jsx(AgentActions, { actions: agentActions, isRunning: isAgentRunning, currentStep: agentIteration, dryRun: agentDryRun })), 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) => {
|
|
1402
1388
|
const actionColor = change.action === 'delete' ? 'red' : change.action === 'edit' ? 'yellow' : 'green';
|
|
1403
1389
|
const actionLabel = change.action === 'delete' ? 'DELETE' : change.action === 'edit' ? 'EDIT' : 'CREATE';
|
|
1404
1390
|
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));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Actions component using Static to prevent re-rendering/jumping
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { ActionLog } from '../utils/tools';
|
|
6
|
+
interface AgentActionsProps {
|
|
7
|
+
actions: ActionLog[];
|
|
8
|
+
isRunning: boolean;
|
|
9
|
+
currentStep: number;
|
|
10
|
+
dryRun?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Agent Actions display using Static component
|
|
14
|
+
*
|
|
15
|
+
* Static renders items once and never re-renders them,
|
|
16
|
+
* preventing terminal jumping when new actions are added.
|
|
17
|
+
*/
|
|
18
|
+
export declare const AgentActions: React.FC<AgentActionsProps>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Agent Actions component using Static to prevent re-rendering/jumping
|
|
4
|
+
*/
|
|
5
|
+
import { useState, useEffect, memo } from 'react';
|
|
6
|
+
import { Box, Text, Static } from 'ink';
|
|
7
|
+
// Spinner frames
|
|
8
|
+
const SPINNER_FRAMES = ['/', '-', '\\', '|'];
|
|
9
|
+
/**
|
|
10
|
+
* Isolated spinner - doesn't cause parent re-renders
|
|
11
|
+
*/
|
|
12
|
+
const Spinner = memo(({ color = '#f02a30' }) => {
|
|
13
|
+
const [frame, setFrame] = useState(0);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const timer = setInterval(() => {
|
|
16
|
+
setFrame(f => (f + 1) % SPINNER_FRAMES.length);
|
|
17
|
+
}, 100);
|
|
18
|
+
return () => clearInterval(timer);
|
|
19
|
+
}, []);
|
|
20
|
+
return _jsxs(Text, { color: color, children: ["[", SPINNER_FRAMES[frame], "]"] });
|
|
21
|
+
});
|
|
22
|
+
Spinner.displayName = 'Spinner';
|
|
23
|
+
/**
|
|
24
|
+
* Format action for display
|
|
25
|
+
*/
|
|
26
|
+
function formatAction(action) {
|
|
27
|
+
const filename = action.target.split('/').pop() || action.target;
|
|
28
|
+
const lineCount = action.details ? action.details.split('\n').length : 0;
|
|
29
|
+
const lineInfo = lineCount > 0 ? ` (${lineCount} lines)` : '';
|
|
30
|
+
switch (action.type) {
|
|
31
|
+
case 'write':
|
|
32
|
+
return {
|
|
33
|
+
icon: action.result === 'success' ? '✓' : '✗',
|
|
34
|
+
color: action.result === 'success' ? 'green' : 'red',
|
|
35
|
+
text: `Created ${filename}${lineInfo}`,
|
|
36
|
+
};
|
|
37
|
+
case 'edit':
|
|
38
|
+
return {
|
|
39
|
+
icon: action.result === 'success' ? '✓' : '✗',
|
|
40
|
+
color: action.result === 'success' ? 'yellow' : 'red',
|
|
41
|
+
text: `Edited ${filename}${lineInfo}`,
|
|
42
|
+
};
|
|
43
|
+
case 'read':
|
|
44
|
+
return {
|
|
45
|
+
icon: '→',
|
|
46
|
+
color: 'blue',
|
|
47
|
+
text: `Reading ${filename}`,
|
|
48
|
+
};
|
|
49
|
+
case 'delete':
|
|
50
|
+
return {
|
|
51
|
+
icon: action.result === 'success' ? '✓' : '✗',
|
|
52
|
+
color: 'red',
|
|
53
|
+
text: `Deleted ${filename}`,
|
|
54
|
+
};
|
|
55
|
+
case 'command':
|
|
56
|
+
const cmd = action.target.length > 30 ? action.target.slice(0, 30) + '...' : action.target;
|
|
57
|
+
return {
|
|
58
|
+
icon: action.result === 'success' ? '✓' : '✗',
|
|
59
|
+
color: action.result === 'success' ? 'magenta' : 'red',
|
|
60
|
+
text: `Ran \`${cmd}\``,
|
|
61
|
+
};
|
|
62
|
+
case 'search':
|
|
63
|
+
return {
|
|
64
|
+
icon: '→',
|
|
65
|
+
color: 'cyan',
|
|
66
|
+
text: `Searching ${filename}`,
|
|
67
|
+
};
|
|
68
|
+
case 'mkdir':
|
|
69
|
+
return {
|
|
70
|
+
icon: action.result === 'success' ? '✓' : '✗',
|
|
71
|
+
color: 'blue',
|
|
72
|
+
text: `Created dir ${filename}`,
|
|
73
|
+
};
|
|
74
|
+
case 'fetch':
|
|
75
|
+
return {
|
|
76
|
+
icon: '→',
|
|
77
|
+
color: 'cyan',
|
|
78
|
+
text: `Fetching ${filename}`,
|
|
79
|
+
};
|
|
80
|
+
case 'list':
|
|
81
|
+
return {
|
|
82
|
+
icon: '→',
|
|
83
|
+
color: 'gray',
|
|
84
|
+
text: `Listing ${filename}`,
|
|
85
|
+
};
|
|
86
|
+
default:
|
|
87
|
+
return {
|
|
88
|
+
icon: '◦',
|
|
89
|
+
color: 'white',
|
|
90
|
+
text: `${action.type}: ${filename}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Single action line component
|
|
96
|
+
*/
|
|
97
|
+
const ActionLine = memo(({ action }) => {
|
|
98
|
+
const { icon, color, text } = formatAction(action);
|
|
99
|
+
return (_jsxs(Text, { children: [_jsx(Text, { color: color, children: icon }), _jsxs(Text, { children: [" ", text] })] }));
|
|
100
|
+
});
|
|
101
|
+
ActionLine.displayName = 'ActionLine';
|
|
102
|
+
/**
|
|
103
|
+
* Agent Actions display using Static component
|
|
104
|
+
*
|
|
105
|
+
* Static renders items once and never re-renders them,
|
|
106
|
+
* preventing terminal jumping when new actions are added.
|
|
107
|
+
*/
|
|
108
|
+
export const AgentActions = memo(({ actions, isRunning, currentStep, dryRun, }) => {
|
|
109
|
+
const color = dryRun ? 'yellow' : '#f02a30';
|
|
110
|
+
const label = dryRun ? 'DRY RUN' : 'AGENT';
|
|
111
|
+
// Get completed actions (all except potentially the last one if still pending)
|
|
112
|
+
const completedActions = actions.filter(a => a.result === 'success' || a.result === 'error');
|
|
113
|
+
// Current action (last one if result is pending or the running state)
|
|
114
|
+
const currentAction = actions.length > 0 ? actions[actions.length - 1] : null;
|
|
115
|
+
const isCurrentPending = currentAction && currentAction.result !== 'success' && currentAction.result !== 'error';
|
|
116
|
+
if (!isRunning && actions.length === 0) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Static, { items: completedActions.map((a, i) => ({ ...a, id: `action-${i}-${a.timestamp}` })), children: (action) => (_jsx(ActionLine, { action: action }, action.id)) }), isRunning && (_jsxs(Box, { children: [_jsx(Spinner, { color: color }), _jsxs(Text, { color: color, bold: true, children: [" ", label, " "] }), _jsxs(Text, { color: "cyan", children: ["Step ", currentStep] }), currentAction && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "gray", children: " | " }), _jsx(Text, { children: formatAction(currentAction).text })] }))] }))] }));
|
|
120
|
+
});
|
|
121
|
+
AgentActions.displayName = 'AgentActions';
|
package/dist/utils/agent.js
CHANGED
|
@@ -686,9 +686,6 @@ export async function runAgent(prompt, projectContext, options = {}) {
|
|
|
686
686
|
// Actually execute the tool
|
|
687
687
|
toolResult = executeTool(toolCall, projectContext.root || process.cwd());
|
|
688
688
|
}
|
|
689
|
-
// Debug - write to file since Ink captures stdout/stderr
|
|
690
|
-
const fs = require('fs');
|
|
691
|
-
fs.appendFileSync('/tmp/codeep-debug.log', `[${new Date().toISOString()}] Tool executed: ${toolCall.tool}, onToolResult exists: ${!!opts.onToolResult}\n`);
|
|
692
689
|
opts.onToolResult?.(toolResult, toolCall);
|
|
693
690
|
// Log action
|
|
694
691
|
const actionLog = createActionLog(toolCall, toolResult);
|
package/dist/utils/console.js
CHANGED
|
@@ -70,9 +70,6 @@ export function setAgentRunning(running, dryRun = false) {
|
|
|
70
70
|
* Log agent action
|
|
71
71
|
*/
|
|
72
72
|
export function logAction(type, target, result, details) {
|
|
73
|
-
// Debug - write to file since Ink captures stdout/stderr
|
|
74
|
-
const fs = require('fs');
|
|
75
|
-
fs.appendFileSync('/tmp/codeep-debug.log', `[${new Date().toISOString()}] logAction called: ${type} ${target} ${result}\n`);
|
|
76
73
|
stopSpinner(); // Stop spinner before logging
|
|
77
74
|
const filename = target.split('/').pop() || target;
|
|
78
75
|
const lineCount = details ? details.split('\n').length : 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeep",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
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",
|