codeep 1.0.52 → 1.0.54
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.
|
@@ -15,6 +15,7 @@ export declare const AgentProgress: React.FC<AgentProgressProps>;
|
|
|
15
15
|
/**
|
|
16
16
|
* Live Code Stream component - shows ALL code being written/edited by agent
|
|
17
17
|
* Displayed ABOVE the AgentProgress component
|
|
18
|
+
* Enhanced with better syntax highlighting and visual organization
|
|
18
19
|
*/
|
|
19
20
|
interface LiveCodeStreamProps {
|
|
20
21
|
actions: ActionLog[];
|
|
@@ -42,30 +42,133 @@ export const AgentProgress = ({ isRunning, iteration, maxIterations, actions, cu
|
|
|
42
42
|
const totalFileChanges = fileChanges.created + fileChanges.modified + fileChanges.deleted;
|
|
43
43
|
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: dryRun ? 'yellow' : '#f02a30', padding: 1, marginY: 1, children: [_jsx(Box, { children: isRunning ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: dryRun ? 'yellow' : '#f02a30', children: ["[", SPINNER_FRAMES[spinnerFrame], "]"] }), _jsxs(Text, { color: dryRun ? 'yellow' : '#f02a30', bold: true, children: [' ', dryRun ? 'DRY RUN' : 'AGENT', ' '] }), _jsx(Text, { color: "gray", children: "|" }), _jsxs(Text, { color: "cyan", children: [" step ", iteration] }), _jsx(Text, { color: "gray", children: " | " }), actionCounts.reads > 0 && _jsxs(Text, { color: "blue", children: [actionCounts.reads, "R "] }), actionCounts.writes > 0 && _jsxs(Text, { color: "green", children: [actionCounts.writes, "W "] }), actionCounts.edits > 0 && _jsxs(Text, { color: "yellow", children: [actionCounts.edits, "E "] }), actionCounts.commands > 0 && _jsxs(Text, { color: "magenta", children: [actionCounts.commands, "C "] }), actionCounts.searches > 0 && _jsxs(Text, { color: "cyan", children: [actionCounts.searches, "S "] }), actions.length === 0 && _jsx(Text, { color: "gray", children: "0 actions" })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { color: "green", bold: true, children: "[DONE] " }), _jsx(Text, { children: "Agent completed" }), _jsx(Text, { color: "gray", children: " | " }), _jsxs(Text, { color: "white", children: [actions.length, " actions"] })] })) }), isRunning && currentAction && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "white", bold: true, children: "Now: " }), _jsxs(Text, { color: getActionColor(currentAction.type), children: [getActionLabel(currentAction.type), " "] }), _jsx(Text, { color: "white", children: formatTarget(currentAction.target) })] })), _jsx(Text, { color: "gray", children: '─'.repeat(50) }), recentActions.length > 1 && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "gray", dimColor: true, children: "Recent:" }), recentActions.slice(0, -1).map((action, i) => (_jsx(ActionItem, { action: action }, i)))] })), isRunning && totalFileChanges > 0 && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Changes: " }), fileChanges.created > 0 && _jsxs(Text, { color: "green", children: ["+", fileChanges.created, " "] }), fileChanges.modified > 0 && _jsxs(Text, { color: "yellow", children: ["~", fileChanges.modified, " "] }), fileChanges.deleted > 0 && _jsxs(Text, { color: "red", children: ["-", fileChanges.deleted] })] })), isRunning && currentThinking && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", wrap: "truncate-end", children: ["> ", currentThinking.slice(0, 80), currentThinking.length > 80 ? '...' : ''] }) })), isRunning && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Press " }), _jsx(Text, { color: "#f02a30", children: "Esc" }), _jsx(Text, { color: "gray", children: " to stop" })] })), !isRunning && totalFileChanges > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, children: "File Changes:" }), fileChanges.created > 0 && (_jsxs(Text, { color: "green", children: [" + ", fileChanges.created, " file(s) created"] })), fileChanges.modified > 0 && (_jsxs(Text, { color: "yellow", children: [" ~ ", fileChanges.modified, " file(s) modified"] })), fileChanges.deleted > 0 && (_jsxs(Text, { color: "red", children: [" - ", fileChanges.deleted, " file(s) deleted"] }))] }))] }));
|
|
44
44
|
};
|
|
45
|
-
//
|
|
46
|
-
const
|
|
45
|
+
// Get file extension for language detection
|
|
46
|
+
const getFileExtension = (filename) => {
|
|
47
|
+
const parts = filename.split('.');
|
|
48
|
+
return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : '';
|
|
49
|
+
};
|
|
50
|
+
// Get language label from extension
|
|
51
|
+
const getLanguageLabel = (ext) => {
|
|
52
|
+
const langMap = {
|
|
53
|
+
'js': 'JavaScript',
|
|
54
|
+
'jsx': 'React JSX',
|
|
55
|
+
'ts': 'TypeScript',
|
|
56
|
+
'tsx': 'React TSX',
|
|
57
|
+
'html': 'HTML',
|
|
58
|
+
'css': 'CSS',
|
|
59
|
+
'scss': 'SCSS',
|
|
60
|
+
'json': 'JSON',
|
|
61
|
+
'md': 'Markdown',
|
|
62
|
+
'py': 'Python',
|
|
63
|
+
'rb': 'Ruby',
|
|
64
|
+
'go': 'Go',
|
|
65
|
+
'rs': 'Rust',
|
|
66
|
+
'java': 'Java',
|
|
67
|
+
'kt': 'Kotlin',
|
|
68
|
+
'swift': 'Swift',
|
|
69
|
+
'php': 'PHP',
|
|
70
|
+
'sql': 'SQL',
|
|
71
|
+
'sh': 'Shell',
|
|
72
|
+
'bash': 'Bash',
|
|
73
|
+
'yml': 'YAML',
|
|
74
|
+
'yaml': 'YAML',
|
|
75
|
+
'xml': 'XML',
|
|
76
|
+
'vue': 'Vue',
|
|
77
|
+
'svelte': 'Svelte',
|
|
78
|
+
};
|
|
79
|
+
return langMap[ext] || ext.toUpperCase();
|
|
80
|
+
};
|
|
81
|
+
// Enhanced syntax highlighting with more colors
|
|
82
|
+
const getCodeColor = (line, ext) => {
|
|
47
83
|
const trimmed = line.trim();
|
|
48
|
-
//
|
|
49
|
-
if (trimmed
|
|
84
|
+
// Empty lines
|
|
85
|
+
if (!trimmed)
|
|
86
|
+
return 'gray';
|
|
87
|
+
// Comments - multiple styles
|
|
88
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('#') || trimmed.startsWith('/*') ||
|
|
89
|
+
trimmed.startsWith('*') || trimmed.startsWith('<!--') || trimmed.startsWith('"""') ||
|
|
90
|
+
trimmed.startsWith("'''")) {
|
|
50
91
|
return 'gray';
|
|
51
92
|
}
|
|
52
|
-
//
|
|
53
|
-
if (/^(import|export|
|
|
93
|
+
// Import/export statements
|
|
94
|
+
if (/^(import|export|from|require)\b/.test(trimmed)) {
|
|
54
95
|
return 'magenta';
|
|
55
96
|
}
|
|
56
|
-
//
|
|
57
|
-
if (
|
|
97
|
+
// Function/class definitions
|
|
98
|
+
if (/^(function|class|interface|type|enum|const\s+\w+\s*=\s*(\(|async)|def |class |fn |func |pub fn)\b/.test(trimmed)) {
|
|
99
|
+
return 'yellow';
|
|
100
|
+
}
|
|
101
|
+
// Control flow keywords
|
|
102
|
+
if (/^(if|else|for|while|switch|case|try|catch|finally|return|throw|break|continue|async|await)\b/.test(trimmed)) {
|
|
103
|
+
return 'blue';
|
|
104
|
+
}
|
|
105
|
+
// Variable declarations
|
|
106
|
+
if (/^(const|let|var|val|mut)\b/.test(trimmed)) {
|
|
58
107
|
return 'cyan';
|
|
59
108
|
}
|
|
60
|
-
//
|
|
61
|
-
if (
|
|
109
|
+
// HTML/JSX tags
|
|
110
|
+
if ((ext === 'html' || ext === 'jsx' || ext === 'tsx' || ext === 'vue' || ext === 'svelte') &&
|
|
111
|
+
(trimmed.startsWith('<') || trimmed.startsWith('</'))) {
|
|
112
|
+
return 'cyan';
|
|
113
|
+
}
|
|
114
|
+
// CSS selectors and properties
|
|
115
|
+
if ((ext === 'css' || ext === 'scss') && (trimmed.includes('{') || trimmed.includes(':'))) {
|
|
116
|
+
return 'green';
|
|
117
|
+
}
|
|
118
|
+
// JSON keys
|
|
119
|
+
if (ext === 'json' && trimmed.includes(':')) {
|
|
120
|
+
return 'cyan';
|
|
121
|
+
}
|
|
122
|
+
// Strings (but not the whole line)
|
|
123
|
+
if (/["'`]/.test(trimmed)) {
|
|
62
124
|
return 'green';
|
|
63
125
|
}
|
|
64
126
|
return 'white';
|
|
65
127
|
};
|
|
128
|
+
// Check if line is a section separator (empty or comment-only)
|
|
129
|
+
const isSectionBreak = (line, prevLine) => {
|
|
130
|
+
const trimmed = line.trim();
|
|
131
|
+
const prevTrimmed = prevLine?.trim() || '';
|
|
132
|
+
// Empty line after non-empty line
|
|
133
|
+
if (!trimmed && prevTrimmed)
|
|
134
|
+
return true;
|
|
135
|
+
// Comment after code
|
|
136
|
+
if ((trimmed.startsWith('//') || trimmed.startsWith('#') || trimmed.startsWith('/*')) &&
|
|
137
|
+
prevTrimmed && !prevTrimmed.startsWith('//') && !prevTrimmed.startsWith('#')) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
};
|
|
66
142
|
export const LiveCodeStream = ({ actions, isRunning }) => {
|
|
143
|
+
// State for streaming effect - show lines progressively
|
|
144
|
+
const [visibleLines, setVisibleLines] = useState(0);
|
|
145
|
+
const [lastActionId, setLastActionId] = useState(null);
|
|
67
146
|
// Find the current write/edit action with code content
|
|
68
147
|
const currentAction = actions.length > 0 ? actions[actions.length - 1] : null;
|
|
148
|
+
// Create a unique ID for the current action
|
|
149
|
+
const actionId = currentAction ? `${currentAction.target}-${currentAction.timestamp}` : null;
|
|
150
|
+
// Reset visible lines when action changes, then stream progressively
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (!currentAction || !currentAction.details) {
|
|
153
|
+
setVisibleLines(0);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// If this is a new action, reset and start streaming
|
|
157
|
+
if (actionId !== lastActionId) {
|
|
158
|
+
setLastActionId(actionId);
|
|
159
|
+
setVisibleLines(10); // Start with first 10 lines
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Stream more lines progressively
|
|
163
|
+
const totalLines = currentAction.details.split('\n').length;
|
|
164
|
+
if (visibleLines < totalLines) {
|
|
165
|
+
const timer = setTimeout(() => {
|
|
166
|
+
// Add 10 more lines every 100ms
|
|
167
|
+
setVisibleLines(prev => Math.min(prev + 10, totalLines));
|
|
168
|
+
}, 100);
|
|
169
|
+
return () => clearTimeout(timer);
|
|
170
|
+
}
|
|
171
|
+
}, [currentAction, actionId, lastActionId, visibleLines]);
|
|
69
172
|
// Only show for write/edit actions with content
|
|
70
173
|
if (!isRunning || !currentAction)
|
|
71
174
|
return null;
|
|
@@ -74,14 +177,31 @@ export const LiveCodeStream = ({ actions, isRunning }) => {
|
|
|
74
177
|
if (!currentAction.details)
|
|
75
178
|
return null;
|
|
76
179
|
const code = currentAction.details;
|
|
77
|
-
const
|
|
180
|
+
const fullPath = currentAction.target;
|
|
181
|
+
const filename = fullPath.split('/').pop() || fullPath;
|
|
182
|
+
const ext = getFileExtension(filename);
|
|
183
|
+
const langLabel = getLanguageLabel(ext);
|
|
78
184
|
const allLines = code.split('\n');
|
|
79
185
|
const totalLines = allLines.length;
|
|
80
|
-
const actionLabel = currentAction.type === 'write' ? 'Creating' : 'Editing';
|
|
81
|
-
|
|
186
|
+
const actionLabel = currentAction.type === 'write' ? '✨ Creating' : '✏️ Editing';
|
|
187
|
+
const actionColor = currentAction.type === 'write' ? 'green' : 'yellow';
|
|
188
|
+
// Only show lines up to visibleLines (streaming effect)
|
|
189
|
+
const linesToShow = allLines.slice(0, visibleLines);
|
|
190
|
+
const remainingLines = totalLines - visibleLines;
|
|
191
|
+
// Calculate code stats
|
|
192
|
+
const commentLines = allLines.filter(l => {
|
|
193
|
+
const t = l.trim();
|
|
194
|
+
return t.startsWith('//') || t.startsWith('#') || t.startsWith('/*') || t.startsWith('*');
|
|
195
|
+
}).length;
|
|
196
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsxs(Text, { color: actionColor, bold: true, children: [actionLabel, " "] }), _jsx(Text, { color: "white", bold: true, children: filename })] }), _jsxs(Box, { children: [_jsxs(Text, { color: "gray", children: [langLabel, " \u2022 "] }), _jsx(Text, { color: "cyan", children: visibleLines }), _jsxs(Text, { color: "gray", children: ["/", totalLines, " lines"] }), remainingLines > 0 && (_jsx(Text, { color: "yellow", children: " \u25BC streaming..." }))] })] }), fullPath !== filename && (_jsxs(Text, { color: "gray", dimColor: true, children: [" \uD83D\uDCC1 ", fullPath] })), _jsx(Text, { color: actionColor, children: '┌' + '─'.repeat(78) + '┐' }), _jsx(Box, { flexDirection: "column", children: linesToShow.map((line, i) => {
|
|
82
197
|
const lineNum = i + 1;
|
|
83
|
-
|
|
84
|
-
|
|
198
|
+
const prevLine = i > 0 ? allLines[i - 1] : null;
|
|
199
|
+
const showSeparator = isSectionBreak(line, prevLine);
|
|
200
|
+
const lineColor = getCodeColor(line, ext);
|
|
201
|
+
// Zebra striping for better readability (subtle)
|
|
202
|
+
const isEvenLine = i % 2 === 0;
|
|
203
|
+
return (_jsxs(Box, { flexDirection: "column", children: [showSeparator && i > 0 && (_jsx(Text, { color: "gray", dimColor: true, children: '│' + ' '.repeat(78) + '│' })), _jsxs(Text, { children: [_jsx(Text, { color: actionColor, children: "\u2502" }), _jsx(Text, { color: isEvenLine ? 'gray' : 'white', dimColor: !isEvenLine, children: String(lineNum).padStart(4, ' ') }), _jsx(Text, { color: "gray", dimColor: true, children: " \u2502 " }), _jsx(Text, { color: lineColor, children: line.slice(0, 70) }), line.length > 70 && _jsx(Text, { color: "gray", children: "\u2026" }), line.length <= 70 && _jsx(Text, { children: ' '.repeat(Math.max(0, 70 - line.length)) }), _jsx(Text, { color: actionColor, children: "\u2502" })] })] }, i));
|
|
204
|
+
}) }), remainingLines > 0 && (_jsxs(Text, { color: "yellow", children: ['│', " ... ", remainingLines, " more lines loading... ", '│'] })), _jsx(Text, { color: actionColor, children: '└' + '─'.repeat(78) + '┘' })] }));
|
|
85
205
|
};
|
|
86
206
|
// Helper functions for action display
|
|
87
207
|
const getActionColor = (type) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeep",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.54",
|
|
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",
|