wip, changing the logic in useStreamResponse
This commit is contained in:
parent
6429f48763
commit
022747ba04
3 changed files with 35 additions and 63 deletions
|
|
@ -115,10 +115,6 @@ export const useStreamResponse = ({
|
||||||
const streamResponse = async (messages: Message[]) => {
|
const streamResponse = async (messages: Message[]) => {
|
||||||
let aiResponse = ''
|
let aiResponse = ''
|
||||||
let currentReasoning = ''
|
let currentReasoning = ''
|
||||||
let currentReasoningStartTime: number | undefined = undefined
|
|
||||||
let currentReasoningEndTime: number | undefined = undefined
|
|
||||||
let assistantMessageIndex = -1 // Track the index of our assistant message
|
|
||||||
let assistantMessageCreated = false // Track if we've created the assistant message yet
|
|
||||||
|
|
||||||
// Check if API key is available
|
// Check if API key is available
|
||||||
let apiKey = getApiKey(selectedModel.provider.id)
|
let apiKey = getApiKey(selectedModel.provider.id)
|
||||||
|
|
@ -165,51 +161,38 @@ export const useStreamResponse = ({
|
||||||
console.log(JSON.stringify(event))
|
console.log(JSON.stringify(event))
|
||||||
try {
|
try {
|
||||||
if (event.type === 'reasoning') {
|
if (event.type === 'reasoning') {
|
||||||
// Track reasoning start time and create assistant message if needed
|
setConversations((prev) => {
|
||||||
if (!currentReasoningStartTime) {
|
const updated = [...prev]
|
||||||
currentReasoningStartTime = Date.now()
|
const conv = updated.find((c) => c.id === conversationId)
|
||||||
currentReasoning = '' // Reset reasoning content for new session
|
if (!conv) {
|
||||||
|
console.error(`Missing conversation for ID ${conversationId}! Ignoring ${JSON.stringify(event)}`)
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
const lastMessage = conv.messages?.at(-1)
|
||||||
|
|
||||||
// Create a new assistant message for reasoning (even if we already have one)
|
if (lastMessage?.role === 'assistant' && lastMessage.type === 'reasoning') {
|
||||||
// This handles multiple reasoning sessions in the same conversation turn
|
// We have an existing reasoning block!
|
||||||
setConversations((prev) => {
|
lastMessage.content = lastMessage.content + event.textDelta.trim()
|
||||||
const updated = [...prev]
|
} else {
|
||||||
const conv = updated.find((c) => c.id === conversationId)
|
// We need a new reasoning block!
|
||||||
|
const currentReasoningStartTime = Date.now()
|
||||||
|
|
||||||
|
// Create a new assistant message for reasoning (even if we already have one)
|
||||||
|
// This handles multiple reasoning sessions in the same conversation turn
|
||||||
if (conv) {
|
if (conv) {
|
||||||
conv.messages.push({
|
conv.messages.push({
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
content: '',
|
type: 'reasoning',
|
||||||
reasoning: '',
|
content: event.textDelta.trim(),
|
||||||
isReasoningStreaming: true,
|
isReasoningStreaming: true,
|
||||||
reasoningStartTime: currentReasoningStartTime,
|
reasoningStartTime: currentReasoningStartTime!,
|
||||||
})
|
})
|
||||||
assistantMessageIndex = conv.messages.length - 1
|
debugMessages('Added new reasoning assistant message at index', conv.messages.length - 1)
|
||||||
debugMessages('Added new reasoning assistant message at index', assistantMessageIndex)
|
|
||||||
debugMessages('Current messages:', JSON.stringify(conv.messages))
|
debugMessages('Current messages:', JSON.stringify(conv.messages))
|
||||||
}
|
}
|
||||||
return updated
|
}
|
||||||
})
|
return updated
|
||||||
assistantMessageCreated = true
|
})
|
||||||
}
|
|
||||||
|
|
||||||
currentReasoning += (event as any).textDelta || ''
|
|
||||||
|
|
||||||
// Update the assistant message with streaming reasoning in real-time
|
|
||||||
if (assistantMessageCreated) {
|
|
||||||
setConversations((prev) => {
|
|
||||||
const updated = [...prev]
|
|
||||||
const conv = updated.find((c) => c.id === conversationId)
|
|
||||||
if (conv && assistantMessageIndex >= 0) {
|
|
||||||
const assistantMessage = conv.messages[assistantMessageIndex]
|
|
||||||
if (assistantMessage && hasContent(assistantMessage) && assistantMessage.role === 'assistant') {
|
|
||||||
assistantMessage.reasoning = currentReasoning.trim()
|
|
||||||
assistantMessage.isReasoningStreaming = true
|
|
||||||
assistantMessage.reasoningStartTime = currentReasoningStartTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return updated
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else if (event.type === 'tool-call') {
|
} else if (event.type === 'tool-call') {
|
||||||
// End reasoning phase immediately when we see a tool call for linear flow
|
// End reasoning phase immediately when we see a tool call for linear flow
|
||||||
if (currentReasoningStartTime && !currentReasoningEndTime) {
|
if (currentReasoningStartTime && !currentReasoningEndTime) {
|
||||||
|
|
@ -345,21 +328,6 @@ export const useStreamResponse = ({
|
||||||
aiResponse = aiResponse.replace(/<chat-title>.*?<\/chat-title>/, '').trim()
|
aiResponse = aiResponse.replace(/<chat-title>.*?<\/chat-title>/, '').trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove thinking tags from the display text (they should be extracted by middleware)
|
|
||||||
let cleanedResponse = aiResponse
|
|
||||||
if (supportsReasoning(selectedModel)) {
|
|
||||||
// Remove complete thinking blocks
|
|
||||||
cleanedResponse = aiResponse.replace(/<think>[\s\S]*?<\/think>/g, '').trim()
|
|
||||||
// Remove unclosed think tags (everything from <think> to end)
|
|
||||||
cleanedResponse = cleanedResponse.replace(/<think>[\s\S]*$/g, '').trim()
|
|
||||||
// Remove any remaining opening think tags
|
|
||||||
cleanedResponse = cleanedResponse.replace(/<think>/g, '').trim()
|
|
||||||
// Remove any remaining closing think tags
|
|
||||||
cleanedResponse = cleanedResponse.replace(/<\/think>/g, '').trim()
|
|
||||||
// Clean up any remaining whitespace or newlines at the start
|
|
||||||
cleanedResponse = cleanedResponse.replace(/^\s+/, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
setConversations((prev) => {
|
setConversations((prev) => {
|
||||||
const updated = [...prev]
|
const updated = [...prev]
|
||||||
const conv = updated.find((c) => c.id === conversationId)
|
const conv = updated.find((c) => c.id === conversationId)
|
||||||
|
|
@ -367,8 +335,7 @@ export const useStreamResponse = ({
|
||||||
// Update the specific assistant message we created, not just the last message
|
// Update the specific assistant message we created, not just the last message
|
||||||
const assistantMessage = conv.messages[assistantMessageIndex]
|
const assistantMessage = conv.messages[assistantMessageIndex]
|
||||||
if (assistantMessage && hasContent(assistantMessage) && assistantMessage.role === 'assistant') {
|
if (assistantMessage && hasContent(assistantMessage) && assistantMessage.role === 'assistant') {
|
||||||
assistantMessage.content = cleanedResponse
|
assistantMessage.content = aiResponse
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,15 @@ export interface SystemMessage extends BaseMessage {
|
||||||
|
|
||||||
export interface AssistantMessage extends BaseMessage {
|
export interface AssistantMessage extends BaseMessage {
|
||||||
role: 'assistant'
|
role: 'assistant'
|
||||||
reasoning?: string
|
type: 'content'
|
||||||
reasoningStartTime?: number
|
}
|
||||||
|
|
||||||
|
export interface AssistantReasoningMessage extends BaseMessage {
|
||||||
|
role: 'assistant'
|
||||||
|
type: 'reasoning'
|
||||||
|
reasoningStartTime: number
|
||||||
reasoningEndTime?: number
|
reasoningEndTime?: number
|
||||||
isReasoningStreaming?: boolean
|
isReasoningStreaming: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ToolCallMessage {
|
export interface ToolCallMessage {
|
||||||
|
|
@ -33,7 +38,7 @@ export interface ToolResultMessage {
|
||||||
callId: string
|
callId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Message = UserMessage | SystemMessage | AssistantMessage | ToolCallMessage | ToolResultMessage
|
export type Message = UserMessage | SystemMessage | AssistantMessage | AssistantReasoningMessage | ToolCallMessage | ToolResultMessage
|
||||||
|
|
||||||
export interface Conversation {
|
export interface Conversation {
|
||||||
id?: number
|
id?: number
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue