feat: memory v2, prompt styles, Dream/GAZE integration, Wyoming TTS fix
SQLite + sqlite-vec replaces JSON memory files with semantic search, follow-up injection, privacy levels, and lifecycle management. Six prompt styles (quick/standard/creative/roleplayer/game-master/storyteller) with per-style Claude model tiering (Haiku/Sonnet/Opus), temperature control, and section stripping. Characters can set default style and per-style overrides. Dream character import and GAZE character linking in the dashboard editor with auto-populated fields, cover image resolution, and preset assignment. Bridge: session isolation (conversation_id / 12h satellite buckets), model routing refactor, PUT/DELETE support, memory REST endpoints. Dashboard: mobile-responsive sidebar, retry button, style picker in chat, follow-up banner, memory lifecycle/privacy UI, cloud model options in editor. Wyoming TTS: upgraded to v1.8.0 for HA 1.7.2 compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -70,7 +70,8 @@ export function useChat(conversationId, conversationMeta, onConversationUpdate)
|
||||
}, [conversationMeta, onConversationUpdate])
|
||||
|
||||
// send accepts an optional overrideId for when the conversation was just created
|
||||
const send = useCallback(async (text, overrideId) => {
|
||||
// and an optional promptStyle to control response style
|
||||
const send = useCallback(async (text, overrideId, promptStyle) => {
|
||||
if (!text.trim() || isLoading) return null
|
||||
|
||||
const userMsg = { id: Date.now(), role: 'user', content: text.trim(), timestamp: new Date().toISOString() }
|
||||
@@ -80,13 +81,15 @@ export function useChat(conversationId, conversationMeta, onConversationUpdate)
|
||||
setIsLoading(true)
|
||||
|
||||
try {
|
||||
const { response, model } = await sendMessage(text.trim(), conversationMeta?.characterId || null)
|
||||
const activeConvId = overrideId || idRef.current
|
||||
const { response, model, prompt_style } = await sendMessage(text.trim(), conversationMeta?.characterId || null, promptStyle, activeConvId)
|
||||
const assistantMsg = {
|
||||
id: Date.now() + 1,
|
||||
role: 'assistant',
|
||||
content: response,
|
||||
timestamp: new Date().toISOString(),
|
||||
...(model && { model }),
|
||||
...(prompt_style && { prompt_style }),
|
||||
}
|
||||
const allMessages = [...newMessages, assistantMsg]
|
||||
setMessages(allMessages)
|
||||
@@ -114,6 +117,52 @@ export function useChat(conversationId, conversationMeta, onConversationUpdate)
|
||||
}
|
||||
}, [isLoading, messages, persist])
|
||||
|
||||
// Retry: remove the error message, re-send the preceding user message
|
||||
const retry = useCallback(async (errorMsgId, promptStyle) => {
|
||||
const idx = messages.findIndex(m => m.id === errorMsgId)
|
||||
if (idx < 1) return null
|
||||
// Find the user message right before the error
|
||||
const userMsg = messages[idx - 1]
|
||||
if (!userMsg || userMsg.role !== 'user') return null
|
||||
// Remove the error message
|
||||
const cleaned = messages.filter(m => m.id !== errorMsgId)
|
||||
setMessages(cleaned)
|
||||
await persist(cleaned)
|
||||
// Re-send (but we need to temporarily set messages back without the error so send picks up correctly)
|
||||
// Instead, inline the send logic with the cleaned message list
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const activeConvId = idRef.current
|
||||
const { response, model, prompt_style } = await sendMessage(userMsg.content, conversationMeta?.characterId || null, promptStyle, activeConvId)
|
||||
const assistantMsg = {
|
||||
id: Date.now() + 1,
|
||||
role: 'assistant',
|
||||
content: response,
|
||||
timestamp: new Date().toISOString(),
|
||||
...(model && { model }),
|
||||
...(prompt_style && { prompt_style }),
|
||||
}
|
||||
const allMessages = [...cleaned, assistantMsg]
|
||||
setMessages(allMessages)
|
||||
await persist(allMessages)
|
||||
return response
|
||||
} catch (err) {
|
||||
const newError = {
|
||||
id: Date.now() + 1,
|
||||
role: 'assistant',
|
||||
content: `Error: ${err.message}`,
|
||||
timestamp: new Date().toISOString(),
|
||||
isError: true,
|
||||
}
|
||||
const allMessages = [...cleaned, newError]
|
||||
setMessages(allMessages)
|
||||
await persist(allMessages)
|
||||
return null
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [messages, persist, conversationMeta])
|
||||
|
||||
const clearHistory = useCallback(async () => {
|
||||
setMessages([])
|
||||
if (idRef.current) {
|
||||
@@ -121,5 +170,5 @@ export function useChat(conversationId, conversationMeta, onConversationUpdate)
|
||||
}
|
||||
}, [persist])
|
||||
|
||||
return { messages, isLoading, isLoadingConv, send, clearHistory }
|
||||
return { messages, isLoading, isLoadingConv, send, retry, clearHistory }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user