mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-05-25 18:55:19 +02:00
refactor chat component
This commit is contained in:
parent
ca3c80e96d
commit
faef91f0a1
1 changed files with 41 additions and 41 deletions
|
|
@ -42,6 +42,7 @@ export function Chat({
|
||||||
const [showSuccessMessage, setShowSuccessMessage] = useState(false);
|
const [showSuccessMessage, setShowSuccessMessage] = useState(false);
|
||||||
// Add state for explain (no modal needed, just direct trigger)
|
// Add state for explain (no modal needed, just direct trigger)
|
||||||
const [showExplainSuccess, setShowExplainSuccess] = useState(false);
|
const [showExplainSuccess, setShowExplainSuccess] = useState(false);
|
||||||
|
const [pendingFixIndex, setPendingFixIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
// --- Scroll/auto-scroll/unread bubble logic ---
|
// --- Scroll/auto-scroll/unread bubble logic ---
|
||||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
@ -49,6 +50,15 @@ export function Chat({
|
||||||
const [autoScroll, setAutoScroll] = useState(true);
|
const [autoScroll, setAutoScroll] = useState(true);
|
||||||
const [showUnreadBubble, setShowUnreadBubble] = useState(false);
|
const [showUnreadBubble, setShowUnreadBubble] = useState(false);
|
||||||
|
|
||||||
|
// collect published tool call results
|
||||||
|
const toolCallResults: Record<string, z.infer<typeof ToolMessage>> = {};
|
||||||
|
optimisticMessages
|
||||||
|
.filter((message) => message.role == 'tool')
|
||||||
|
.forEach((message) => {
|
||||||
|
toolCallResults[message.toolCallId] = message;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const handleScroll = useCallback(() => {
|
const handleScroll = useCallback(() => {
|
||||||
const container = scrollContainerRef.current;
|
const container = scrollContainerRef.current;
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
@ -58,18 +68,6 @@ export function Chat({
|
||||||
if (atBottom) setShowUnreadBubble(false);
|
if (atBottom) setShowUnreadBubble(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const container = scrollContainerRef.current;
|
|
||||||
if (!container) return;
|
|
||||||
if (autoScroll) {
|
|
||||||
container.scrollTop = container.scrollHeight;
|
|
||||||
setShowUnreadBubble(false);
|
|
||||||
} else {
|
|
||||||
setShowUnreadBubble(true);
|
|
||||||
}
|
|
||||||
}, [optimisticMessages, loadingAssistantResponse, autoScroll]);
|
|
||||||
// --- End scroll/auto-scroll logic ---
|
|
||||||
|
|
||||||
const getCopyContent = useCallback(() => {
|
const getCopyContent = useCallback(() => {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
messages,
|
messages,
|
||||||
|
|
@ -78,18 +76,7 @@ export function Chat({
|
||||||
}, null, 2);
|
}, null, 2);
|
||||||
}, [messages, lastAgenticRequest, lastAgenticResponse]);
|
}, [messages, lastAgenticRequest, lastAgenticResponse]);
|
||||||
|
|
||||||
// Expose copy function to parent
|
|
||||||
useEffect(() => {
|
|
||||||
onCopyClick(getCopyContent);
|
|
||||||
}, [getCopyContent, onCopyClick]);
|
|
||||||
|
|
||||||
// reset optimistic messages when messages change
|
|
||||||
useEffect(() => {
|
|
||||||
setOptimisticMessages(messages);
|
|
||||||
}, [messages]);
|
|
||||||
|
|
||||||
// Handle fix functionality
|
// Handle fix functionality
|
||||||
const [pendingFixIndex, setPendingFixIndex] = useState<number | null>(null);
|
|
||||||
const handleFix = useCallback((message: string, index: number) => {
|
const handleFix = useCallback((message: string, index: number) => {
|
||||||
setPendingFixMessage(message);
|
setPendingFixMessage(message);
|
||||||
setPendingFixIndex(index);
|
setPendingFixIndex(index);
|
||||||
|
|
@ -144,13 +131,14 @@ export function Chat({
|
||||||
}
|
}
|
||||||
}, [projectId, triggerCopilotChat]);
|
}, [projectId, triggerCopilotChat]);
|
||||||
|
|
||||||
// collect published tool call results
|
// Add a stop handler function
|
||||||
const toolCallResults: Record<string, z.infer<typeof ToolMessage>> = {};
|
const handleStop = useCallback(() => {
|
||||||
optimisticMessages
|
if (eventSourceRef.current) {
|
||||||
.filter((message) => message.role == 'tool')
|
eventSourceRef.current.close();
|
||||||
.forEach((message) => {
|
eventSourceRef.current = null;
|
||||||
toolCallResults[message.toolCallId] = message;
|
setLoadingAssistantResponse(false);
|
||||||
});
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
function handleUserMessage(prompt: string) {
|
function handleUserMessage(prompt: string) {
|
||||||
const updatedMessages: z.infer<typeof Message>[] = [...messages, {
|
const updatedMessages: z.infer<typeof Message>[] = [...messages, {
|
||||||
|
|
@ -162,6 +150,27 @@ export function Chat({
|
||||||
setIsLastInteracted(true);
|
setIsLastInteracted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const container = scrollContainerRef.current;
|
||||||
|
if (!container) return;
|
||||||
|
if (autoScroll) {
|
||||||
|
container.scrollTop = container.scrollHeight;
|
||||||
|
setShowUnreadBubble(false);
|
||||||
|
} else {
|
||||||
|
setShowUnreadBubble(true);
|
||||||
|
}
|
||||||
|
}, [optimisticMessages, loadingAssistantResponse, autoScroll]);
|
||||||
|
|
||||||
|
// Expose copy function to parent
|
||||||
|
useEffect(() => {
|
||||||
|
onCopyClick(getCopyContent);
|
||||||
|
}, [getCopyContent, onCopyClick]);
|
||||||
|
|
||||||
|
// reset optimistic messages when messages change
|
||||||
|
useEffect(() => {
|
||||||
|
setOptimisticMessages(messages);
|
||||||
|
}, [messages]);
|
||||||
|
|
||||||
// reset state when workflow changes
|
// reset state when workflow changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMessages([]);
|
setMessages([]);
|
||||||
|
|
@ -187,7 +196,7 @@ export function Chat({
|
||||||
// Reset request/response state before making new request
|
// Reset request/response state before making new request
|
||||||
setLastAgenticRequest(null);
|
setLastAgenticRequest(null);
|
||||||
setLastAgenticResponse(null);
|
setLastAgenticResponse(null);
|
||||||
|
|
||||||
let streamId: string | null = null;
|
let streamId: string | null = null;
|
||||||
try {
|
try {
|
||||||
const response = await getAssistantResponseStreamId(
|
const response = await getAssistantResponseStreamId(
|
||||||
|
|
@ -202,7 +211,7 @@ export function Chat({
|
||||||
setBillingError(response.billingError);
|
setBillingError(response.billingError);
|
||||||
setFetchResponseError(response.billingError);
|
setFetchResponseError(response.billingError);
|
||||||
setLoadingAssistantResponse(false);
|
setLoadingAssistantResponse(false);
|
||||||
console.log('returning from getAssistantResponseStreamId due to billing error');
|
console.log('returning from getAssistantResponseStreamId due to billing error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
streamId = response.streamId;
|
streamId = response.streamId;
|
||||||
|
|
@ -313,15 +322,6 @@ export function Chat({
|
||||||
fetchResponseError,
|
fetchResponseError,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Add a stop handler function
|
|
||||||
const handleStop = useCallback(() => {
|
|
||||||
if (eventSourceRef.current) {
|
|
||||||
eventSourceRef.current.close();
|
|
||||||
eventSourceRef.current = null;
|
|
||||||
setLoadingAssistantResponse(false);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-11/12 max-w-6xl mx-auto h-full flex flex-col relative">
|
<div className="w-11/12 max-w-6xl mx-auto h-full flex flex-col relative">
|
||||||
<div className="sticky top-0 z-10 bg-white dark:bg-zinc-900 pt-4 pb-4">
|
<div className="sticky top-0 z-10 bg-white dark:bg-zinc-900 pt-4 pb-4">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue