diff --git a/.DS_Store b/.DS_Store index 6a543b8..6f2c1ee 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/prisma/App.tsx b/prisma/App.tsx index a96fb31..044155e 100644 --- a/prisma/App.tsx +++ b/prisma/App.tsx @@ -33,7 +33,8 @@ const App = () => { handleNewChat, handleSelectSession, handleDeleteSession, - stopDeepThink + stopDeepThink, + focusTrigger } = useAppLogic(); return ( @@ -85,6 +86,7 @@ const App = () => { onRun={handleRun} onStop={stopDeepThink} appState={appState} + focusTrigger={focusTrigger} /> diff --git a/prisma/components/ChatArea.tsx b/prisma/components/ChatArea.tsx index 002e699..a13178d 100644 --- a/prisma/components/ChatArea.tsx +++ b/prisma/components/ChatArea.tsx @@ -24,67 +24,69 @@ const ChatArea = ({ processStartTime, processEndTime }: ChatAreaProps) => { + const isIdle = messages.length === 0 && appState === 'idle'; + return (
-
- {messages.length === 0 && appState === 'idle' && ( -
- -

Prisma

-

- Deep multi-agent reasoning. -

-
- )} + {isIdle ? ( +
+ +

Prisma

+

+ Deep multi-agent reasoning. +

+
+ ) : ( +
+ {/* History */} + {messages.map((msg, idx) => ( + + ))} - {/* History */} - {messages.map((msg, idx) => ( - - ))} - - {/* Active Generation (Ghost Message) */} - {appState !== 'idle' && appState !== 'completed' && ( -
+ {/* Active Generation (Ghost Message) */} + {appState !== 'idle' && appState !== 'completed' && ( +
-
-
-
-
-
Prisma
- - {/* Active Thinking Process */} -
- -
+
+
+
+
+
Prisma
+ + {/* Active Thinking Process */} +
+ +
- {/* Streaming Output */} - {finalOutput && ( -
- -
- )} -
+ {/* Streaming Output */} + {finalOutput && ( +
+ +
+ )} +
-
- )} -
+
+ )} +
+ )}
); }; diff --git a/prisma/components/ChatMessage.tsx b/prisma/components/ChatMessage.tsx index b2bc61b..61728b6 100644 --- a/prisma/components/ChatMessage.tsx +++ b/prisma/components/ChatMessage.tsx @@ -1,5 +1,6 @@ + import React, { useState } from 'react'; -import { User, Sparkles, ChevronDown, ChevronRight } from 'lucide-react'; +import { User, Sparkles, ChevronDown, ChevronRight, Copy, Check } from 'lucide-react'; import MarkdownRenderer from './MarkdownRenderer'; import ProcessFlow from './ProcessFlow'; import { ChatMessage } from '../types'; @@ -12,10 +13,18 @@ interface ChatMessageProps { const ChatMessageItem = ({ message, isLast }: ChatMessageProps) => { const isUser = message.role === 'user'; const [showThinking, setShowThinking] = useState(false); + const [copied, setCopied] = useState(false); // Check if there is any thinking data to show const hasThinkingData = message.analysis || (message.experts && message.experts.length > 0); + const handleCopy = () => { + if (!message.content) return; + navigator.clipboard.writeText(message.content); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + return (
@@ -36,8 +45,30 @@ const ChatMessageItem = ({ message, isLast }: ChatMessageProps) => { {/* Content */}
-
- {isUser ? 'You' : 'Prisma'} +
+
+ {isUser ? 'You' : 'Prisma'} +
+ {message.content && ( + + )}
{/* Thinking Process Accordion (Only for AI) */} @@ -100,4 +131,4 @@ const ChatMessageItem = ({ message, isLast }: ChatMessageProps) => { ); }; -export default ChatMessageItem; \ No newline at end of file +export default ChatMessageItem; diff --git a/prisma/components/Header.tsx b/prisma/components/Header.tsx index ba24702..cc38b6d 100644 --- a/prisma/components/Header.tsx +++ b/prisma/components/Header.tsx @@ -15,7 +15,7 @@ interface HeaderProps { const Header = ({ selectedModel, setSelectedModel, onOpenSettings, onToggleSidebar, onNewChat }: HeaderProps) => { return ( -
+