Skip to content

feat: Stream AI responses in real-time via Route Handler#194

Open
Copilot wants to merge 3 commits intomainfrom
copilot/add-streaming-ai-responses
Open

feat: Stream AI responses in real-time via Route Handler#194
Copilot wants to merge 3 commits intomainfrom
copilot/add-streaming-ai-responses

Conversation

Copy link
Contributor

Copilot AI commented Mar 17, 2026

AI responses previously blocked until fully generated before rendering. This replaces the askAI Server Action with a streaming Route Handler, navigating to the chat page as soon as the AI returns the target sectionId and title, then displaying the response token-by-token.

Architecture

Streaming protocol (NDJSON over POST /api/chat):

  • {"type":"chat","chatId":"...","sectionId":"..."} — emitted once the first two lines (sectionId + title) are parsed; triggers DB chat creation and client navigation
  • {"type":"chunk","text":"..."} — streamed for each AI token
  • {"type":"done"} — emitted after messages/diffs are persisted to DB

Two-phase DB write (app/lib/chatHistory.ts):

  • createChatOnly() — inserts the chat row early so navigation can happen immediately
  • addMessagesAndDiffs() — persists messages and parsed diffs after streaming completes, then revalidates cache

Client-side streaming state (app/(docs)/streamingChatContext.tsx):

  • StreamingChatProvider lives in the (docs) layout, so it survives the parallel-route navigation from @docs to @chat
  • chatForm.tsx starts a background ReadableStream reader; on the chat event it calls startStreaming(chatId, userQuestion) and immediately navigates
  • chatArea.tsx renders from streaming context while isStreamingThis is true (showing a loading-dots indicator), then calls router.refresh() on completion and clears context once DB data is available

AI streaming utility (app/lib/ai.ts):

  • generateContentStream() — async generator wrapping Gemini generateContentStream and OpenRouter SSE (stream: true), replacing the non-streaming generateContent used previously in server actions

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • sparrow.cloudflare.com
    • Triggering command: /opt/hostedtoolcache/node/24.14.0/x64/bin/node /opt/hostedtoolcache/node/24.14.0/x64/bin/node --no-warnings --experimental-vm-modules /home/REDACTED/work/my-code/my-code/node_modules/wrangler/wrangler-dist/cli.js types --env-interface CloudflareEnv cloudflare-env.d.ts (dns block)
  • workers.cloudflare.com
    • Triggering command: /opt/hostedtoolcache/node/24.14.0/x64/bin/node /opt/hostedtoolcache/node/24.14.0/x64/bin/node --no-warnings --experimental-vm-modules /home/REDACTED/work/my-code/my-code/node_modules/wrangler/wrangler-dist/cli.js types --env-interface CloudflareEnv cloudflare-env.d.ts (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/my-code/my-code/node_modules/.bin/next build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>AIの回答をストリーミングにする</issue_title>
<issue_description>今は回答が完全に返ってくるまで待っており、遅い
loadingの表示を改善するべきというのもあるが、それよりも普通のAIチャットのようにストリーミングでレスポンスを受け取りリアルタイムで表示するようにしたほうがよさそう
AIの出力は1行目に回答先のセクションid、その次にユーザーへの回答、としているので、回答が途中であっても表示できるはず

ServerActionだとできないらしい?</issue_description>

<agent_instructions>現在の処理は chatForm.tsxでaskAI()を呼び出す→AIの回答を待つ→データベースにchat,message,diffを作成→chatFormに返されたchatIdとsectionIdをもとに画面遷移&再読み込み、という順になっていますが、
chatForm.tsxでaskAI()を呼び出す→AIの回答のsectionIdとタイトルの部分までを受け取ったらデータベースにchatを作成→chatFormにchatIdとsectionIdを返し、画面遷移→AIの回答をストリーミングし、フロントエンドのチャット表示(app/(docs)/@chat/chat/[chatId]/chatArea.tsx)をリアルタイムに更新→AIの回答が完了したらデータベースにmessage,diffを追加→フロントエンド再読み込み
という動作にしてほしい。
ServerActionは結果をストリーミングすることができないようなので、RouteHandlerに変更しても良いです。
</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

- Add app/lib/ai.ts with generateContentStream() for Gemini/OpenRouter
- Add createChatOnly() and addMessagesAndDiffs() to chatHistory.ts
- Create app/api/chat/route.ts Route Handler with NDJSON streaming
- Create app/(docs)/streamingChatContext.tsx for real-time streaming state
- Update layout.tsx to include StreamingChatProvider
- Update chatForm.tsx to use fetch() + stream reading instead of server action
- Update chatArea.tsx to display streaming content in real-time

Co-authored-by: na-trium-144 <100704180+na-trium-144@users.noreply.github.com>
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 17, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
my-code 7c16a3e Commit Preview URL

Branch Preview URL
Mar 18 2026, 12:04 PM

Copilot AI changed the title [WIP] Add streaming responses for AI chat feat: Stream AI responses in real-time via Route Handler Mar 17, 2026
Copilot AI requested a review from na-trium-144 March 17, 2026 15:53
@na-trium-144 na-trium-144 marked this pull request as ready for review March 18, 2026 12:02
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.

AIの回答をストリーミングにする

2 participants