codeep 1.0.58 → 1.0.59

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.
@@ -140,25 +140,21 @@ const isSectionBreak = (line, prevLine) => {
140
140
  return false;
141
141
  };
142
142
  export const LiveCodeStream = ({ actions, isRunning }) => {
143
- // Use ref for tracking to avoid re-render loops
143
+ // Use refs for mutable state to minimize re-renders
144
144
  const lastActionIdRef = useRef(null);
145
145
  const timerRef = useRef(null);
146
- const totalLinesRef = useRef(0);
147
- // State for visible lines - only update when batch is ready
148
- const [displayState, setDisplayState] = useState({
149
- endLine: 0,
150
- actionId: null,
151
- });
146
+ const visibleEndLineRef = useRef(0);
147
+ // Single state for forcing re-render - increment only when needed
148
+ const [, forceRender] = useState(0);
152
149
  // Find the current write/edit action with code content
153
150
  const currentAction = actions.length > 0 ? actions[actions.length - 1] : null;
154
151
  // Only show for write/edit actions
155
152
  const isWriteOrEdit = currentAction && (currentAction.type === 'write' || currentAction.type === 'edit');
156
153
  // Create a unique ID for the current action
157
154
  const actionId = currentAction ? `${currentAction.target}-${currentAction.timestamp}` : null;
158
- // Get total lines for current action and store in ref
155
+ // Get total lines for current action
159
156
  const totalLines = currentAction?.details ? currentAction.details.split('\n').length : 0;
160
- totalLinesRef.current = totalLines;
161
- // Stream lines progressively using interval instead of recursive setTimeout
157
+ // Stream lines progressively - minimize state updates
162
158
  useEffect(() => {
163
159
  // Clear any existing timer
164
160
  if (timerRef.current) {
@@ -167,31 +163,33 @@ export const LiveCodeStream = ({ actions, isRunning }) => {
167
163
  }
168
164
  // Only stream for write/edit actions with content
169
165
  if (!currentAction || !currentAction.details || !isRunning || !isWriteOrEdit) {
170
- if (displayState.endLine !== 0 || displayState.actionId !== null) {
171
- setDisplayState({ endLine: 0, actionId: null });
166
+ if (visibleEndLineRef.current !== 0) {
167
+ visibleEndLineRef.current = 0;
168
+ lastActionIdRef.current = null;
172
169
  }
173
170
  return;
174
171
  }
175
172
  // If this is a new action, reset and start streaming
176
173
  if (actionId !== lastActionIdRef.current) {
177
174
  lastActionIdRef.current = actionId;
178
- const initialLines = Math.min(10, totalLinesRef.current);
179
- setDisplayState({ endLine: initialLines, actionId });
175
+ const lines = currentAction.details.split('\n').length;
176
+ visibleEndLineRef.current = Math.min(10, lines);
177
+ forceRender(n => n + 1);
180
178
  // Only start interval if there are more lines to show
181
- if (totalLinesRef.current > 10) {
179
+ if (lines > 10) {
182
180
  timerRef.current = setInterval(() => {
183
- setDisplayState(prev => {
184
- // Use ref to get current totalLines value
185
- const currentTotal = totalLinesRef.current;
186
- const newEndLine = Math.min(prev.endLine + 10, currentTotal);
187
- // Stop interval when we've shown all lines
188
- if (newEndLine >= currentTotal && timerRef.current) {
189
- clearInterval(timerRef.current);
190
- timerRef.current = null;
191
- }
192
- return { ...prev, endLine: newEndLine };
193
- });
194
- }, 150);
181
+ const currentLines = currentAction.details?.split('\n').length || 0;
182
+ const newEndLine = Math.min(visibleEndLineRef.current + 10, currentLines);
183
+ if (newEndLine !== visibleEndLineRef.current) {
184
+ visibleEndLineRef.current = newEndLine;
185
+ forceRender(n => n + 1);
186
+ }
187
+ // Stop interval when we've shown all lines
188
+ if (newEndLine >= currentLines && timerRef.current) {
189
+ clearInterval(timerRef.current);
190
+ timerRef.current = null;
191
+ }
192
+ }, 200); // Slower interval to reduce flickering
195
193
  }
196
194
  }
197
195
  return () => {
@@ -200,7 +198,7 @@ export const LiveCodeStream = ({ actions, isRunning }) => {
200
198
  timerRef.current = null;
201
199
  }
202
200
  };
203
- }, [actionId, isRunning, isWriteOrEdit]);
201
+ }, [actionId, isRunning, isWriteOrEdit, currentAction]);
204
202
  // Only show for write/edit actions with content while running
205
203
  if (!isRunning || !currentAction)
206
204
  return null;
@@ -216,19 +214,20 @@ export const LiveCodeStream = ({ actions, isRunning }) => {
216
214
  const allLines = code.split('\n');
217
215
  const actionLabel = currentAction.type === 'write' ? '✨ Creating' : '✏️ Editing';
218
216
  const actionColor = currentAction.type === 'write' ? 'green' : 'yellow';
219
- // Use displayState for rendering
220
- const visibleEndLine = displayState.endLine;
221
- // Sliding window: show only last 10 lines of what's been "written" so far
217
+ // Use ref value for rendering
218
+ const visibleEndLine = visibleEndLineRef.current || Math.min(10, totalLines);
219
+ // Sliding window: show only last 10 lines
222
220
  const WINDOW_SIZE = 10;
223
221
  const startLine = Math.max(0, visibleEndLine - WINDOW_SIZE);
224
222
  const linesToShow = allLines.slice(startLine, visibleEndLine);
225
223
  const remainingLines = totalLines - visibleEndLine;
226
224
  const linesAbove = startLine;
227
- return (_jsxs(Box, { flexDirection: "column", 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: visibleEndLine }), _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(80) }), linesAbove > 0 && (_jsxs(Text, { color: "gray", dimColor: true, children: [" \u22EE ", linesAbove, " lines above"] })), _jsx(Box, { flexDirection: "column", children: linesToShow.map((line, i) => {
228
- const lineNum = startLine + i + 1;
229
- const lineColor = getCodeColor(line, ext);
230
- return (_jsxs(Text, { children: [_jsx(Text, { color: "gray", dimColor: true, children: String(lineNum).padStart(4, ' ') }), _jsx(Text, { color: "gray", dimColor: true, children: " \u2502 " }), _jsx(Text, { color: lineColor, children: line.slice(0, 72) }), line.length > 72 && _jsx(Text, { color: "gray", children: "\u2026" })] }, i));
231
- }) }), remainingLines > 0 && (_jsxs(Text, { color: "yellow", children: [" \u22EE ", remainingLines, " more lines..."] })), _jsx(Text, { color: actionColor, children: '─'.repeat(80) })] }));
225
+ // Pad lines to fixed height to prevent layout shifts
226
+ const paddedLines = [...linesToShow];
227
+ while (paddedLines.length < WINDOW_SIZE) {
228
+ paddedLines.push('');
229
+ }
230
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { color: actionColor, bold: true, children: [actionLabel, " "] }), _jsx(Text, { color: "white", bold: true, children: filename }), _jsxs(Text, { color: "gray", children: [" \u2022 ", langLabel, " \u2022 "] }), _jsx(Text, { color: "cyan", children: visibleEndLine }), _jsxs(Text, { color: "gray", children: ["/", totalLines] }), remainingLines > 0 && _jsx(Text, { color: "yellow", children: " \u25BC" })] }), _jsx(Text, { color: actionColor, children: '─'.repeat(76) }), _jsx(Text, { color: "gray", dimColor: true, children: linesAbove > 0 ? ` ⋮ ${linesAbove} lines above` : ' ' }), paddedLines.map((line, i) => (_jsxs(Text, { children: [_jsxs(Text, { color: "gray", dimColor: true, children: [line ? String(startLine + i + 1).padStart(4, ' ') : ' ', " \u2502", ' '] }), _jsx(Text, { color: line ? getCodeColor(line, ext) : 'gray', children: line.slice(0, 68) }), line.length > 68 && _jsx(Text, { color: "gray", children: "\u2026" })] }, `line-${startLine + i}`))), _jsx(Text, { color: "yellow", children: remainingLines > 0 ? ` ⋮ ${remainingLines} more lines...` : ' ' }), _jsx(Text, { color: actionColor, children: '─'.repeat(76) })] }));
232
231
  };
233
232
  // Helper functions for action display
234
233
  const getActionColor = (type) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.0.58",
3
+ "version": "1.0.59",
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",