This commit is contained in:
Siddharth Ganesan
2025-07-08 20:08:42 -07:00
parent 1b3b85f4c4
commit 88282378ea
3 changed files with 46 additions and 27 deletions
+39 -20
View File
@@ -1,7 +1,15 @@
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { getSession } from '@/lib/auth'
import { createChat, deleteChat, generateChatTitle, getChat, listChats, sendMessage, updateChat } from '@/lib/copilot/service'
import {
createChat,
deleteChat,
generateChatTitle,
getChat,
listChats,
sendMessage,
updateChat,
} from '@/lib/copilot/service'
import { createLogger } from '@/lib/logs/console-logger'
const logger = createLogger('CopilotAPI')
@@ -37,18 +45,26 @@ const CreateChatSchema = z.object({
// Schema for updating chats
const UpdateChatSchema = z.object({
chatId: z.string().min(1, 'Chat ID is required'),
messages: z.array(z.object({
id: z.string(),
role: z.enum(['user', 'assistant', 'system']),
content: z.string(),
timestamp: z.string(),
citations: z.array(z.object({
id: z.number(),
title: z.string(),
url: z.string(),
similarity: z.number().optional(),
})).optional(),
})).optional(),
messages: z
.array(
z.object({
id: z.string(),
role: z.enum(['user', 'assistant', 'system']),
content: z.string(),
timestamp: z.string(),
citations: z
.array(
z.object({
id: z.number(),
title: z.string(),
url: z.string(),
similarity: z.number().optional(),
})
)
.optional(),
})
)
.optional(),
title: z.string().optional(),
})
@@ -120,7 +136,7 @@ export async function POST(req: NextRequest) {
// Handle StreamingExecution (from providers with tool calls)
logger.info(`[${requestId}] StreamingExecution detected`)
streamToRead = (result.response as any).stream
// Extract citations from StreamingExecution at API level
const execution = (result.response as any).execution
logger.info(`[${requestId}] Extracting citations from StreamingExecution`, {
@@ -128,7 +144,7 @@ export async function POST(req: NextRequest) {
hasToolResults: !!execution?.toolResults,
toolResultsLength: execution?.toolResults?.length || 0,
})
if (execution?.toolResults) {
for (const toolResult of execution.toolResults) {
logger.info(`[${requestId}] Processing tool result for citations`, {
@@ -136,7 +152,7 @@ export async function POST(req: NextRequest) {
resultKeys: toolResult && typeof toolResult === 'object' ? Object.keys(toolResult) : [],
hasResultsArray: !!(toolResult && typeof toolResult === 'object' && toolResult.results),
})
if (toolResult && typeof toolResult === 'object' && toolResult.results) {
// Convert documentation search results to citations
const extractedCitations = toolResult.results.map((res: any, index: number) => ({
@@ -146,7 +162,10 @@ export async function POST(req: NextRequest) {
similarity: res.similarity,
}))
result.citations = extractedCitations
logger.info(`[${requestId}] Extracted ${extractedCitations.length} citations from tool results:`, extractedCitations)
logger.info(
`[${requestId}] Extracted ${extractedCitations.length} citations from tool results:`,
extractedCitations
)
break // Use first set of results found
}
}
@@ -354,12 +373,12 @@ export async function PATCH(req: NextRequest) {
// Get the current chat to check if it has a title
const existingChat = await getChat(chatId, session.user.id)
let titleToUse = title
// Generate title if chat doesn't have one and we have messages
if (!titleToUse && existingChat && !existingChat.title && messages && messages.length > 0) {
const firstUserMessage = messages.find(msg => msg.role === 'user')
const firstUserMessage = messages.find((msg) => msg.role === 'user')
if (firstUserMessage) {
logger.info('Generating LLM-based title for chat without title')
try {
-2
View File
@@ -19,8 +19,6 @@ const DocsQuerySchema = z.object({
stream: z.boolean().optional().default(false), // Enable streaming responses
})
/**
* Generate embedding for search query
*/
+7 -5
View File
@@ -493,20 +493,22 @@ export const useCopilotStore = create<CopilotStore>()(
saveChatMessages: async (chatId: string) => {
try {
const { messages, currentChat } = get()
logger.info(`Saving ${messages.length} messages for chat ${chatId}`)
// Let the API handle title generation if needed
const result = await updateChatMessages(chatId, messages)
if (result.success && result.chat) {
// Update local state with the saved chat
set({
currentChat: result.chat,
messages: result.chat.messages,
})
logger.info(`Successfully saved chat ${chatId} with ${result.chat.messages.length} messages`)
logger.info(
`Successfully saved chat ${chatId} with ${result.chat.messages.length} messages`
)
} else {
logger.error(`Failed to save chat ${chatId}:`, result.error)
}