({
userId,
input,
cancelling,
project,
proposals,
projectId,
threadId,
setInput,
setLoading,
setCancelling,
stream,
model,
}: UseChatProps)
| 27 | } |
| 28 | |
| 29 | export const useChat = ({ |
| 30 | userId, |
| 31 | input, |
| 32 | cancelling, |
| 33 | project, |
| 34 | proposals, |
| 35 | projectId, |
| 36 | threadId, |
| 37 | setInput, |
| 38 | setLoading, |
| 39 | setCancelling, |
| 40 | stream, |
| 41 | model, |
| 42 | }: UseChatProps) => { |
| 43 | const { runs, runOrder, createRun, addAction, updateAction, setRunStatus } = |
| 44 | useRuns() |
| 45 | const { setLastEditorSync, shouldSyncOnNextRun, setSyncOnNextRun } = |
| 46 | useProjects() |
| 47 | const sendPrompt = useCallback(async () => { |
| 48 | if (!input.trim()) return |
| 49 | // In production, require NEXT_PUBLIC_API_URL to be set; otherwise show a user-facing error |
| 50 | const isProd = (process.env.NODE_ENV || '').trim() === 'production' |
| 51 | const hasApiUrl = Boolean((process.env.NEXT_PUBLIC_API_URL || '').trim()) |
| 52 | if (isProd && !hasApiUrl) { |
| 53 | const errorRunId = `config_error_${Date.now()}` |
| 54 | createRun(errorRunId, input, projectId, threadId) |
| 55 | addAction(errorRunId, { |
| 56 | id: `notice_${Date.now()}`, |
| 57 | kind: 'system_notice', |
| 58 | status: 'done', |
| 59 | message: |
| 60 | 'Missing environment variable: NEXT_PUBLIC_API_URL is not set. Set it to your backend URL and reload.', |
| 61 | timestamp: new Date().toISOString(), |
| 62 | } as Action) |
| 63 | return |
| 64 | } |
| 65 | setLoading(true) |
| 66 | setInput('') |
| 67 | |
| 68 | // Build ordered message history with both user and assistant messages from prior runs |
| 69 | const message_history = runOrder.flatMap((id) => { |
| 70 | const run = runs[id] |
| 71 | if (!run) return [] as { role: string; content: string }[] |
| 72 | if (run.projectId !== projectId) |
| 73 | return [] as { role: string; content: string }[] |
| 74 | if (run.threadId !== threadId) |
| 75 | return [] as { role: string; content: string }[] |
| 76 | const messages: { role: string; content: string }[] = [] |
| 77 | for (const a of run.actions) { |
| 78 | if (a.kind === 'user_message') |
| 79 | messages.push({ |
| 80 | role: 'user', |
| 81 | content: (a as Action & { content: string }).content, |
| 82 | }) |
| 83 | if (a.kind === 'final_answer') |
| 84 | messages.push({ |
| 85 | role: 'assistant', |
| 86 | content: (a as Action & { content: string }).content, |
no test coverage detected