diff --git a/.example.env b/.example.env index 8b10b61..d6990df 100644 --- a/.example.env +++ b/.example.env @@ -9,7 +9,8 @@ SURREALDB_PASS=root SURREALDB_JWT_SECRET=your-secret-key-here-change-in-production # Google AI API Key (for Gemini embeddings and chat) -GOOGLE_AI_API_KEY=your-google-ai-api-key +GOOGLE_GENERATIVE_AI_API_KEY=your-google-ai-api-key +GOOGLE_AI_MODEL=gemini-pro-latest # Deepgram API Key (for voice-to-text) DEEPGRAM_API_KEY=your-deepgram-api-key diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 0de4e36..173da91 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -4,14 +4,21 @@ import { cookies } from 'next/headers'; import { NodeSuggestionSchema } from '@/lib/ai-schemas'; import { z } from 'zod'; -export const runtime = 'edge'; +// Edge runtime removed - cookies() requires Node.js runtime +export const maxDuration = 30; export async function POST(req: Request) { // Check authentication const cookieStore = await cookies(); const authCookie = cookieStore.get('ponderants-auth'); + console.log('[Chat API] Cookie check:', { + hasCookie: !!authCookie, + allCookies: cookieStore.getAll().map(c => c.name), + }); + if (!authCookie) { + console.log('[Chat API] No auth cookie found, returning 401'); return new Response('Unauthorized', { status: 401 }); } @@ -32,9 +39,16 @@ to propose it as a new "thought node". Do not suggest a node until the idea is fully formed. For all other conversation, just respond as a helpful AI.`; + // Get model from environment variable + const modelName = process.env.GOOGLE_AI_MODEL; + if (!modelName) { + console.error('[Chat API] GOOGLE_AI_MODEL environment variable is not set'); + return new Response('Server configuration error', { status: 500 }); + } + // Use the Vercel AI SDK's streamText function with tools const result = streamText({ - model: google('gemini-1.5-flash'), + model: google(modelName), system: systemPrompt, messages: convertToModelMessages(messages), diff --git a/app/chat/page.tsx b/app/chat/page.tsx index 56f09cf..d87580e 100644 --- a/app/chat/page.tsx +++ b/app/chat/page.tsx @@ -21,13 +21,32 @@ export default function ChatPage() { const viewport = useRef(null); const [input, setInput] = useState(''); - const { messages, sendMessage, isLoading } = useChat({ + const { messages, sendMessage, isLoading, setMessages } = useChat({ api: '/api/chat', body: { persona: 'Socratic', }, + credentials: 'include', }); + // Add initial greeting message on first load + useEffect(() => { + if (messages.length === 0) { + setMessages([ + { + id: 'initial-greeting', + role: 'assistant', + parts: [ + { + type: 'text', + text: 'Welcome to Ponderants! I\'m here to help you explore and structure your ideas through conversation.\n\nWhat would you like to talk about today? I can adapt my interview style to best suit your needs (Socratic questioning, collaborative brainstorming, or other approaches).\n\nJust start sharing your thoughts, and we\'ll discover meaningful insights together.', + }, + ], + }, + ]); + } + }, []); + // Auto-scroll to bottom useEffect(() => { viewport.current?.scrollTo({ @@ -79,6 +98,31 @@ export default function ChatPage() { ); } + + // Handle tool calls (e.g., suggest_node) + if (part.type === 'tool-call') { + return ( + + + 💡 Node Suggestion + + {part.args.title} + + {part.args.content} + + {part.args.tags && part.args.tags.length > 0 && ( + + {part.args.tags.map((tag: string, tagIdx: number) => ( + + #{tag} + + ))} + + )} + + ); + } + return null; })}