diff --git a/src/games/storywriter/components/chat-sidebar.tsx b/src/games/storywriter/components/chat-sidebar.tsx index 3004d44..a6b5efa 100644 --- a/src/games/storywriter/components/chat-sidebar.tsx +++ b/src/games/storywriter/components/chat-sidebar.tsx @@ -186,8 +186,8 @@ export const ChatPanel = () => { const content = delta?.content; if (content) { accumulatedContent += content; - if (currentWorld?.chatOnly && accumulatedContent.startsWith(prefix)) { - accumulatedContent = accumulatedContent.slice(prefix.length); + if (currentWorld?.chatOnly && accumulatedContent.trimStart().startsWith(prefix)) { + accumulatedContent = accumulatedContent.trimStart().slice(prefix.length).trimStart(); } } const reasoningContent = delta?.reasoning_content; @@ -258,8 +258,44 @@ export const ChatPanel = () => { } }, [currentStory, connection, model]); + const handleRegenerate = useCallback(async () => { + if (!currentStory || !connection || !model || isLoading) return; + + // Only regenerate if last message is assistant + const lastMessage = currentStory.chatMessages.at(-1); + const isAssistant = lastMessage?.role === 'assistant'; + + setIsLoading(true); + setError(null); + abortControllerRef.current = new AbortController(); + + const excludedMessages: string[] = []; + try { + if (isAssistant) { + // Delete the last assistant message and regenerate + dispatch({ + type: 'DELETE_CHAT_MESSAGES_FROM', + worldId: currentWorld!.id, + storyId: currentStory.id, + messageId: lastMessage.id, + }); + excludedMessages.push(lastMessage.id); + } + await sendMessage([], excludedMessages); + } finally { + setIsLoading(false); + } + }, [currentStory, currentWorld, connection, model, isLoading, sendMessage]); + const handleSendMessage = useCallback(async () => { - if (!currentStory || !input.trim() || !connection || !model || isLoading) return; + if (!currentStory || !connection || !model || isLoading) return; + + if (!input.trim()) { + if (lastMessage?.role === 'user') { + handleRegenerate(); + } + return; + } setInput(''); setIsLoading(true); @@ -275,7 +311,7 @@ export const ChatPanel = () => { } finally { setIsLoading(false); } - }, [currentStory, input, connection, model, isLoading, sendMessage]); + }, [currentStory, input, connection, model, isLoading, sendMessage, handleRegenerate]); const handleContinue = useCallback(async () => { if (!currentStory || !connection || !model || isLoading) return; @@ -352,32 +388,6 @@ export const ChatPanel = () => { setEditingContent(''); }, [setEditingContent]); - const handleRegenerate = useCallback(async () => { - if (!currentStory || !connection || !model || isLoading) return; - - // Only regenerate if last message is assistant - const lastMessage = currentStory.chatMessages.at(-1); - if (!lastMessage || lastMessage.role !== 'assistant') return; - - setIsLoading(true); - setError(null); - abortControllerRef.current = new AbortController(); - - try { - // Delete the last assistant message and regenerate - dispatch({ - type: 'DELETE_CHAT_MESSAGES_FROM', - worldId: currentWorld!.id, - storyId: currentStory.id, - messageId: lastMessage.id, - }); - - await sendMessage([], [lastMessage.id]); - } finally { - setIsLoading(false); - } - }, [currentStory, currentWorld, connection, model, isLoading, dispatch, sendMessage]); - const isDisabled = !currentStory || !connection || !model || isLoading; return ( @@ -501,9 +511,9 @@ export const ChatPanel = () => { )} {currentStory && (