Skip to content

Commit 1b3b85f

Browse files
committed
Checkpoint
1 parent 4b60bba commit 1b3b85f

File tree

6 files changed

+198
-203
lines changed

6 files changed

+198
-203
lines changed

apps/sim/app/api/copilot/route.ts

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type NextRequest, NextResponse } from 'next/server'
22
import { z } from 'zod'
33
import { getSession } from '@/lib/auth'
4-
import { createChat, deleteChat, getChat, listChats, sendMessage } from '@/lib/copilot/service'
4+
import { createChat, deleteChat, generateChatTitle, getChat, listChats, sendMessage, updateChat } from '@/lib/copilot/service'
55
import { createLogger } from '@/lib/logs/console-logger'
66

77
const logger = createLogger('CopilotAPI')
@@ -34,6 +34,24 @@ const CreateChatSchema = z.object({
3434
initialMessage: z.string().optional(),
3535
})
3636

37+
// Schema for updating chats
38+
const UpdateChatSchema = z.object({
39+
chatId: z.string().min(1, 'Chat ID is required'),
40+
messages: z.array(z.object({
41+
id: z.string(),
42+
role: z.enum(['user', 'assistant', 'system']),
43+
content: z.string(),
44+
timestamp: z.string(),
45+
citations: z.array(z.object({
46+
id: z.number(),
47+
title: z.string(),
48+
url: z.string(),
49+
similarity: z.number().optional(),
50+
})).optional(),
51+
})).optional(),
52+
title: z.string().optional(),
53+
})
54+
3755
// Schema for listing chats
3856
const ListChatsSchema = z.object({
3957
workflowId: z.string().min(1, 'Workflow ID is required'),
@@ -102,6 +120,37 @@ export async function POST(req: NextRequest) {
102120
// Handle StreamingExecution (from providers with tool calls)
103121
logger.info(`[${requestId}] StreamingExecution detected`)
104122
streamToRead = (result.response as any).stream
123+
124+
// Extract citations from StreamingExecution at API level
125+
const execution = (result.response as any).execution
126+
logger.info(`[${requestId}] Extracting citations from StreamingExecution`, {
127+
hasExecution: !!execution,
128+
hasToolResults: !!execution?.toolResults,
129+
toolResultsLength: execution?.toolResults?.length || 0,
130+
})
131+
132+
if (execution?.toolResults) {
133+
for (const toolResult of execution.toolResults) {
134+
logger.info(`[${requestId}] Processing tool result for citations`, {
135+
hasResult: !!toolResult,
136+
resultKeys: toolResult && typeof toolResult === 'object' ? Object.keys(toolResult) : [],
137+
hasResultsArray: !!(toolResult && typeof toolResult === 'object' && toolResult.results),
138+
})
139+
140+
if (toolResult && typeof toolResult === 'object' && toolResult.results) {
141+
// Convert documentation search results to citations
142+
const extractedCitations = toolResult.results.map((res: any, index: number) => ({
143+
id: index + 1,
144+
title: res.title || 'Documentation',
145+
url: res.url || '#',
146+
similarity: res.similarity,
147+
}))
148+
result.citations = extractedCitations
149+
logger.info(`[${requestId}] Extracted ${extractedCitations.length} citations from tool results:`, extractedCitations)
150+
break // Use first set of results found
151+
}
152+
}
153+
}
105154
}
106155

107156
if (streamToRead) {
@@ -287,6 +336,68 @@ export async function PUT(req: NextRequest) {
287336
}
288337
}
289338

339+
/**
340+
* PATCH /api/copilot
341+
* Update a chat with new messages
342+
*/
343+
export async function PATCH(req: NextRequest) {
344+
try {
345+
const session = await getSession()
346+
if (!session?.user?.id) {
347+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
348+
}
349+
350+
const body = await req.json()
351+
const { chatId, messages, title } = UpdateChatSchema.parse(body)
352+
353+
logger.info(`Updating chat ${chatId} for user ${session.user.id}`)
354+
355+
// Get the current chat to check if it has a title
356+
const existingChat = await getChat(chatId, session.user.id)
357+
358+
let titleToUse = title
359+
360+
// Generate title if chat doesn't have one and we have messages
361+
if (!titleToUse && existingChat && !existingChat.title && messages && messages.length > 0) {
362+
const firstUserMessage = messages.find(msg => msg.role === 'user')
363+
if (firstUserMessage) {
364+
logger.info('Generating LLM-based title for chat without title')
365+
try {
366+
titleToUse = await generateChatTitle(firstUserMessage.content)
367+
logger.info(`Generated title: ${titleToUse}`)
368+
} catch (error) {
369+
logger.error('Failed to generate chat title:', error)
370+
titleToUse = 'New Chat'
371+
}
372+
}
373+
}
374+
375+
const chat = await updateChat(chatId, session.user.id, {
376+
messages,
377+
title: titleToUse,
378+
})
379+
380+
if (!chat) {
381+
return NextResponse.json({ error: 'Chat not found or access denied' }, { status: 404 })
382+
}
383+
384+
return NextResponse.json({
385+
success: true,
386+
chat,
387+
})
388+
} catch (error) {
389+
if (error instanceof z.ZodError) {
390+
return NextResponse.json(
391+
{ error: 'Invalid request data', details: error.errors },
392+
{ status: 400 }
393+
)
394+
}
395+
396+
logger.error('Failed to update chat:', error)
397+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
398+
}
399+
}
400+
290401
/**
291402
* DELETE /api/copilot
292403
* Delete a chat

0 commit comments

Comments
 (0)