codeep 1.0.112 → 1.0.113
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 +2 -12
- package/dist/components/MessageList.d.ts +10 -3
- package/dist/components/MessageList.js +19 -15
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
3
3
|
import { Box, Text, useApp, useInput, useStdout } from 'ink';
|
|
4
4
|
import clipboardy from 'clipboardy';
|
|
5
5
|
import { logger } from './utils/logger.js';
|
|
@@ -42,7 +42,6 @@ export const App = () => {
|
|
|
42
42
|
const { stdout } = useStdout();
|
|
43
43
|
// Start with 'chat' screen, will switch to login if needed after loading API key
|
|
44
44
|
const [screen, setScreen] = useState('chat');
|
|
45
|
-
const [chatRenderKey, setChatRenderKey] = useState(0); // Increment to force re-render of Static
|
|
46
45
|
const [messages, setMessages] = useState([]);
|
|
47
46
|
const [inputHistory, setInputHistory] = useState([]);
|
|
48
47
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -164,15 +163,6 @@ export const App = () => {
|
|
|
164
163
|
return () => clearTimeout(timer);
|
|
165
164
|
}
|
|
166
165
|
}, [notification, notificationDuration]);
|
|
167
|
-
// Force re-render of MessageList (and its Static component) when returning to chat
|
|
168
|
-
// This prevents ghost content from previous screen
|
|
169
|
-
const prevScreenRef = React.useRef(screen);
|
|
170
|
-
useEffect(() => {
|
|
171
|
-
if (screen === 'chat' && prevScreenRef.current !== 'chat') {
|
|
172
|
-
setChatRenderKey(k => k + 1);
|
|
173
|
-
}
|
|
174
|
-
prevScreenRef.current = screen;
|
|
175
|
-
}, [screen]);
|
|
176
166
|
// Handle keyboard shortcuts
|
|
177
167
|
useInput((input, key) => {
|
|
178
168
|
// Ctrl+L to clear chat (F5 doesn't work reliably in all terminals)
|
|
@@ -1400,7 +1390,7 @@ export const App = () => {
|
|
|
1400
1390
|
// If we got here, we're in an unknown state - default to chat
|
|
1401
1391
|
return null;
|
|
1402
1392
|
}
|
|
1403
|
-
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
|
|
1393
|
+
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 ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(LiveCodeStream, { actions: agentActions, isRunning: true, terminalWidth: stdout?.columns || 80 }), _jsx(AgentProgress, { isRunning: true, iteration: agentIteration, maxIterations: 50, actions: agentActions, currentThinking: agentThinking, dryRun: agentDryRun })] }, "agent-running")) : agentResult ? (_jsx(Box, { flexDirection: "column", children: _jsx(AgentSummary, { success: agentResult.success, iterations: agentResult.iterations, actions: agentActions, error: agentResult.error, aborted: agentResult.aborted }) }, "agent-complete")) : null, 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) => {
|
|
1404
1394
|
const actionColor = change.action === 'delete' ? 'red' : change.action === 'edit' ? 'yellow' : 'green';
|
|
1405
1395
|
const actionLabel = change.action === 'delete' ? 'DELETE' : change.action === 'edit' ? 'EDIT' : 'CREATE';
|
|
1406
1396
|
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));
|
|
@@ -7,9 +7,16 @@ interface MessageListProps {
|
|
|
7
7
|
terminalHeight?: number;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Message list
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Message list WITHOUT Static component
|
|
11
|
+
*
|
|
12
|
+
* We removed the Static component because:
|
|
13
|
+
* - Static preserves content in terminal scroll history even after unmount
|
|
14
|
+
* - This causes ghost/duplicate content when switching screens
|
|
15
|
+
* - The trade-off is that messages will re-render on each update
|
|
16
|
+
* - We mitigate this with memoization at the individual message level
|
|
17
|
+
*
|
|
18
|
+
* NOTE: This is a temporary solution until we implement a custom renderer
|
|
19
|
+
* like Claude CLI uses (DEC Mode 2026 / synchronized output).
|
|
13
20
|
*/
|
|
14
21
|
export declare const MessageList: React.FC<MessageListProps>;
|
|
15
22
|
export {};
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from 'react';
|
|
3
|
-
import { Box
|
|
2
|
+
import { memo, useMemo } from 'react';
|
|
3
|
+
import { Box } from 'ink';
|
|
4
4
|
import { MessageView } from './Message.js';
|
|
5
5
|
import { StreamingMessage } from './StreamingMessage.js';
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Memoized individual message component
|
|
8
|
+
* Only re-renders when its specific content changes
|
|
9
9
|
*/
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const contentHash = msg.content.slice(0, 50).split('').reduce((acc, char) => {
|
|
13
|
-
return ((acc << 5) - acc) + char.charCodeAt(0);
|
|
14
|
-
}, 0);
|
|
15
|
-
return `${msg.role}-${index}-${Math.abs(contentHash)}`;
|
|
16
|
-
};
|
|
10
|
+
const MemoizedMessage = memo(({ msg }) => _jsx(MessageView, { role: msg.role, content: msg.content }), (prev, next) => prev.msg.content === next.msg.content && prev.msg.role === next.msg.role);
|
|
11
|
+
MemoizedMessage.displayName = 'MemoizedMessage';
|
|
17
12
|
/**
|
|
18
|
-
* Message list
|
|
19
|
-
*
|
|
20
|
-
*
|
|
13
|
+
* Message list WITHOUT Static component
|
|
14
|
+
*
|
|
15
|
+
* We removed the Static component because:
|
|
16
|
+
* - Static preserves content in terminal scroll history even after unmount
|
|
17
|
+
* - This causes ghost/duplicate content when switching screens
|
|
18
|
+
* - The trade-off is that messages will re-render on each update
|
|
19
|
+
* - We mitigate this with memoization at the individual message level
|
|
20
|
+
*
|
|
21
|
+
* NOTE: This is a temporary solution until we implement a custom renderer
|
|
22
|
+
* like Claude CLI uses (DEC Mode 2026 / synchronized output).
|
|
21
23
|
*/
|
|
22
24
|
export const MessageList = memo(({ messages, streamingContent, }) => {
|
|
23
|
-
|
|
25
|
+
// Memoize the messages array rendering
|
|
26
|
+
const renderedMessages = useMemo(() => (messages.map((msg, index) => (_jsx(MemoizedMessage, { msg: msg, index: index }, `msg-${index}-${msg.role}`)))), [messages]);
|
|
27
|
+
return (_jsxs(Box, { flexDirection: "column", children: [renderedMessages, streamingContent && (_jsx(StreamingMessage, { content: streamingContent }))] }));
|
|
24
28
|
});
|
|
25
29
|
MessageList.displayName = 'MessageList';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeep",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.113",
|
|
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",
|