Skip to content

Conversation

@codeunia-dev
Copy link
Owner

@codeunia-dev codeunia-dev commented Nov 25, 2025

This PR introduces real-time streaming responses for the Unio AI assistant using Server-Sent Events (SSE). Instead of waiting for the full response, users now see messages appear word-by-word, similar to ChatGPT and Claude.
This enhancement significantly improves perceived performance and overall UX.


Key Changes

Backend (SSE + Streaming API Integration)

Files Updated:

  • app/api/ai/route.ts

Major updates:

  • Added callOpenRouterAPIStream() (Lines 156–228)

    • Enables stream: true support
    • Returns ReadableStream directly from OpenRouter
    • Reuses full fallback chain from non-streaming mode
  • Updated POST handler (Lines 948–1088)

    • Detects streaming capability via content-type
    • If supported → responds with SSE stream
    • If not → falls back to normal JSON mode
    • Accumulates full text for database logging
  • Implemented correct SSE chunk parsing:

controller.enqueue(`data: ${JSON.stringify(...)}\n\n`);

How it works

Screenshot 2025-11-25 at 4 14 34 PM

Frontend (Real-Time Streaming UI)

Files Updated:

  • components/ai/AIChat.tsx
  • app/ai/page.tsx

Enhancements:

  • Detects streaming mode via response headers
  • Creates placeholder message and updates it incrementally
  • Smooth real-time rendering without flicker
  • Auto-scroll during streaming
  • Graceful fallback to JSON mode if streaming fails
  • Removes partial messages on errors for clean UX

User Experience Improvements

✅ Immediate “time-to-first-token” (~500–800ms)
✅ Smooth word-by-word updates
✅ No loading delay
✅ Matches modern AI chat UX (ChatGPT-style)
✅ Backwards compatible with non-streaming mode


Testing Done

  • Verified real-time streaming in both:

    • Chat widget
    • Full page /ai
  • Tested long messages (1000+ tokens)

  • Confirmed ai_training_data logs full responses

  • Error cases:

    • Network interruption → graceful fallback
    • SSE unsupported → automatic JSON mode
    • Partial messages cleaned up properly

Performance

  • Perceived latency dramatically reduced
  • No additional infra or config required
  • No breaking changes

Security

  • Authentication unchanged
  • Rate limiting intact
  • No sensitive data exposed in stream

Optional Future Enhancements

  • Typing cursor ()
  • User-stop streaming button
  • Token usage tracking
  • Conversation memory (last 5 messages)

Status

✅ Fully implemented
✅ Backwards compatible
🚀 Ready for deployment


Authored by: @akshay0611

Summary by CodeRabbit

  • New Features

    • AI responses now stream in real-time, displaying progressively as they're generated instead of appearing all at once.
    • Added typing indicators and progress placeholders to show when the AI is thinking and responding.
    • Enhanced mobile-friendly interface with quick suggestions and improved layout.
  • Bug Fixes

    • Improved error handling and messaging when the AI service is unavailable or unreachable.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Nov 25, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
codeunia Ready Ready Preview Comment Nov 25, 2025 10:45am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 25, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This PR introduces Server-Sent Events (SSE) streaming support for AI responses. The backend now streams responses from OpenRouter API models while maintaining a non-streaming fallback. The frontend displays typing indicators and progressively updates messages as chunks arrive. Dynamic date computation replaces hard-coded dates, and database logging is added for streamed responses.

Changes

Cohort / File(s) Summary
Streaming Response Handler
app/ai/page.tsx
Adds SSE streaming consumer that detects content-type, reads chunks, parses JSON-prefixed data lines, and progressively updates AI message text/context. Introduces typing indicator and streaming placeholder messages. Extends error handling to remove placeholders on failure and display error messages.
AI API Backend
app/api/ai/route.ts
Implements callOpenRouterAPIStream() for streaming OpenRouter responses via ReadableStream with SSE formatting. Switches default behavior to streaming (controlled by x-use-streaming header). Replaces hard-coded dates with dynamic currentDate/formattedCurrentDate computation. Adds post-stream database logging for ai_training_data. Maintains non-streaming fallback path.
Chat Component Refactor
components/ai/AIChat.tsx
Refactors message flow to support streaming SSE responses with real-time UI updates. Replaces single-response handler with streaming chunk parser. Adds thinking/typing placeholder, improves error handling for both streaming/non-streaming paths. Reorganizes UI rendering with unified message structure, persistent quick suggestions, and enhanced input area.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AIChat as AIChat.tsx
    participant Backend as api/ai/route.ts
    participant OpenRouter as OpenRouter API

    User->>AIChat: Send message
    AIChat->>AIChat: Show typing indicator
    AIChat->>Backend: POST /api/ai (with prompt)
    activate Backend
    Backend->>OpenRouter: callOpenRouterAPIStream(prompt)
    activate OpenRouter
    Backend->>AIChat: Response with<br/>content-type: text/event-stream
    deactivate OpenRouter
    AIChat->>AIChat: Replace typing with<br/>streaming placeholder
    
    loop Stream chunks arrive
        Backend-->>AIChat: SSE chunk (data: {...})
        AIChat->>AIChat: Parse JSON<br/>Accumulate content<br/>Update message UI
    end
    
    Backend->>Backend: Save complete<br/>response to DB
    Backend-->>AIChat: Stream end
    deactivate Backend
    AIChat->>AIChat: Finalize AI message<br/>with full context

    alt Error occurs
        Backend-->>AIChat: Error response
        AIChat->>AIChat: Remove placeholders<br/>Display error message
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Streaming parser logic: SSE chunk parsing and accumulation in AIChat.tsx and page.tsx requires careful validation of data format, error recovery, and state management
  • API route streaming implementation: callOpenRouterAPIStream() function and ReadableStream error handling paths need verification, especially model fallback logic on rate-limits
  • Database interactions: Post-stream logging in route.ts must correctly capture full response context and handle race conditions
  • Date computation logic: Dynamic date calculations and their impact on status derivations (events/hackathons) need validation across both frontend and backend
  • Error handling complexity: Multiple error paths for streaming (network failures, parse errors, API failures) across three files

Poem

🐰 Streams of thought now flow so bright,
Chunks arriving, piece by piece in flight,
Placeholders dance while data takes its stage,
Real-time wisdom writes upon the page,
No more waiting—watch the AI unfold,
A streamed story elegantly told!

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/supabase-disaster-recovery-system

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b610119 and fe523e0.

📒 Files selected for processing (3)
  • app/ai/page.tsx (12 hunks)
  • app/api/ai/route.ts (18 hunks)
  • components/ai/AIChat.tsx (6 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants