fix: resume conversation (#346)

This commit is contained in:
Felarof
2026-02-20 16:23:15 -08:00
committed by GitHub
parent 3955d6ee62
commit 38471f6b6a
3 changed files with 37 additions and 32 deletions

View File

@@ -1,16 +1,24 @@
import type { UIMessage } from 'ai'
const MAX_MESSAGES = 10
const MAX_MESSAGE_CHARS = 65536 // 16K context window size
const MAX_MESSAGE_CHARS = 65536
export function formatConversationHistory(messages: UIMessage[]): string {
if (messages.length === 0) return ''
interface ConversationMessage {
role: 'user' | 'assistant'
content: string
}
export function formatConversationHistory(
messages: UIMessage[],
): ConversationMessage[] {
if (messages.length === 0) return []
const recentMessages = messages.slice(-MAX_MESSAGES)
const formatted = recentMessages
return recentMessages
.map((msg) => {
const role = msg.role === 'user' ? 'user' : 'assistant'
const role: 'user' | 'assistant' =
msg.role === 'user' ? 'user' : 'assistant'
const textContent = msg.parts
.filter((part) => part.type === 'text')
.map((part) => part.text)
@@ -18,15 +26,12 @@ export function formatConversationHistory(messages: UIMessage[]): string {
if (!textContent.trim()) return null
const truncatedContent =
const content =
textContent.length > MAX_MESSAGE_CHARS
? `${textContent.slice(0, MAX_MESSAGE_CHARS)}... [truncated]`
: textContent
return `<${role}>${truncatedContent}</${role}>`
return { role, content }
})
.filter(Boolean)
.join('\n\n')
return formatted
.filter((msg): msg is ConversationMessage => msg !== null)
}

View File

@@ -383,36 +383,29 @@ export class GeminiAgent {
honoStream: HonoSSEStream,
signal?: AbortSignal,
browserContext?: BrowserContext,
previousConversation?: string,
previousConversation?: { role: 'user' | 'assistant'; content: string }[],
): Promise<void> {
const abortSignal = signal || new AbortController().signal
const promptId = `${this.conversationId}-${Date.now()}`
const contextPrefix = this.formatBrowserContext(browserContext)
// User query
const userQuery = `<USER_QUERY>
${message}
</USER_QUERY>`
// Inject previous conversation if resuming (no server-side history)
let fullMessage = userQuery
if (previousConversation) {
fullMessage = `<previous_conversation>
The user is resuming a previous conversation. Here is the conversation history for context:
${previousConversation}
</previous_conversation>
Continue the conversation based on the above context. Here is the user's new message:
${userQuery}`
logger.info('Injecting previous conversation for resume', {
if (previousConversation?.length) {
const historyContents: Content[] = previousConversation.map((msg) => ({
role: msg.role === 'assistant' ? 'model' : 'user',
parts: [{ text: msg.content }],
}))
this.client.setHistory(historyContents)
logger.info('Restored conversation history for resume', {
conversationId: this.conversationId,
historyLength: previousConversation.length,
messageCount: previousConversation.length,
})
}
const fullMessage = `<USER_QUERY>
${message}
</USER_QUERY>`
let currentParts: Part[] = [{ text: contextPrefix + fullMessage }]
let turnCount = 0

View File

@@ -42,7 +42,14 @@ export const ChatRequestSchema = VercelAIConfigSchema.extend({
userWorkingDir: z.string().min(1).optional(),
supportsImages: z.boolean().optional().default(true),
mode: z.enum(['chat', 'agent']).optional().default('agent'),
previousConversation: z.string().optional(),
previousConversation: z
.array(
z.object({
role: z.enum(['user', 'assistant']),
content: z.string(),
}),
)
.optional(),
})
export type ChatRequest = z.infer<typeof ChatRequestSchema>