From f90649c51f7d90541d9af87b7d0b937d5f4f7195 Mon Sep 17 00:00:00 2001 From: Mehdi Date: Mon, 7 Jul 2025 07:42:12 +0000 Subject: [PATCH 1/3] chat working --- CLAUDE.md | 3 +- README.md | 5 +- assets/chatui.png | Bin 0 -> 15499 bytes src/components/panels/ChatPanel.tsx | 299 ++++++-- src/contexts/ExtensionContext.tsx | 60 ++ src/controllers/RunnerController.ts | 98 +++ src/providers/ClaudeRunnerPanel.ts | 1 + src/services/ClaudeCodeService.ts | 6 +- src/styles/panels.css | 230 ++++++ src/types/runner.ts | 15 + tests/e2e/ChatPanelE2E.test.ts | 457 ++++++++++++ tests/fixtures/scripts/claude-mock.sh | 10 + .../panels/ChatPanel.history.test.tsx | 416 +++++++++++ .../unit/components/panels/ChatPanel.test.tsx | 672 ++++++++++-------- .../services/ClaudeCodeService.chat.test.ts | 175 +++++ 15 files changed, 2062 insertions(+), 385 deletions(-) create mode 100644 assets/chatui.png create mode 100644 tests/e2e/ChatPanelE2E.test.ts create mode 100755 tests/fixtures/scripts/claude-mock.sh create mode 100644 tests/unit/components/panels/ChatPanel.history.test.tsx create mode 100644 tests/unit/services/ClaudeCodeService.chat.test.ts diff --git a/CLAUDE.md b/CLAUDE.md index 91bfcb3..1fa7428 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -104,10 +104,11 @@ src/components/ **TypeScript Standards:** -- Enable strict mode - no `any` types allowed +- Enable strict mode - no `any` types allowed (linter will catch violations) - Use interfaces for all props and data structures - Prefer union types over enums for string constants - Use optional chaining (`?.`) and nullish coalescing (`??`) +- NEVER use `any` - always use proper types or `unknown` when type is truly unknown **Error Handling:** diff --git a/README.md b/README.md index 64b2349..d6521b5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![Claude Runner Logo](https://raw.githubusercontent.com/codingworkflow/claude-runner/main/assets/icon.png) -Create and run multi-step tasks in your VS Code. Create workflows & save them to reuse. +Chat, create and run multi-step tasks in your VS Code. Create workflows & save them to reuse. Get cost usage (estimate if you use subscription), and check conversation history. ## Key Features @@ -13,12 +13,15 @@ Get cost usage (estimate if you use subscription), and check conversation histor Create and execute sophisticated multi-step workflows: +- Chat directly in VScode - Chain multiple Claude Code tasks together - Mix different Claude models per task or keep in Auto mode - Session continuity between tasks - Save and reuse pipelines - Format similar to Claude Code GitHub action +![Chat](https://raw.githubusercontent.com/codingworkflow/claude-runner/main/assets/chatui.png) + ![Create Workflow](https://raw.githubusercontent.com/codingworkflow/claude-runner/main/assets/pipeline.png) ![Save Workflow](https://raw.githubusercontent.com/codingworkflow/claude-runner/main/assets/savepipeline.png) diff --git a/assets/chatui.png b/assets/chatui.png new file mode 100644 index 0000000000000000000000000000000000000000..135f49b80e65e4c776cb4fc3a9efef1127e1d5bd GIT binary patch literal 15499 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 JP = ({ disabled }) => { const { state, actions } = useExtension(); const { main, claude } = state; + const [chatMode, setChatMode] = useState<"terminal" | "extension">( + "extension", + ); + const [messages, setMessages] = useState([]); + const [inputMessage, setInputMessage] = useState(""); + const messagesEndRef = useRef(null); + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages]); - const handleStartChat = () => { + const handleStartTerminalChat = () => { if (main.showChatPrompt && main.chatPrompt.trim()) { actions.startInteractive(main.chatPrompt.trim()); } else { @@ -23,9 +43,59 @@ const ChatPanel: React.FC = ({ disabled }) => { } }; + const handleSendMessage = async () => { + if (!inputMessage.trim() || main.chatSending) { + return; + } + + const messageText = inputMessage.trim(); + const userMessage: ChatMessage = { + role: "user", + content: messageText, + timestamp: new Date().toISOString(), + }; + + // Immediately add user message to local state for responsive UI + setMessages((prev) => [...prev, userMessage]); + setInputMessage(""); + + // Set chatSending to true to show the spinner + actions.updateMainState({ chatSending: true }); + + try { + // Send to extension host - this will handle full conversation + actions.sendChatMessage( + messageText, + (main.chatMessages?.length ?? 0) === 0, + ); + } catch (error) { + console.error("Error sending message:", error); + // Reset chatSending on error + actions.updateMainState({ chatSending: false }); + } + }; + + const handleClearChat = () => { + setMessages([]); + actions.clearChatSession(); + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + handleSendMessage(); + } + }; + + // Sync with extension state - this receives the full conversation from the extension host + useEffect(() => { + if (main.chatMessages !== undefined) { + setMessages(main.chatMessages); + } + }, [main.chatMessages]); + return (
- {/* Claude Version Display - At the very top */} = ({ disabled }) => { isLoading={claude.loading} /> - {/* Root Path */} - -
-
-

- Start an interactive Claude chat session in the VS Code terminal - using the selected model and configuration. -

+ +
+
+ +
+
- {/* Model Selection */} - - - {/* Tool Permissions */} - - -
-
- {!main.showChatPrompt ? ( -
- -
- ) : ( - <> + {chatMode === "terminal" ? ( +
+
+

+ Start an interactive Claude chat session in the VS Code terminal + using the selected model and configuration. +

+
+ + + + + +
+
+ {!main.showChatPrompt ? (
-