Replace RSC streaming with /api/ai Route Handler for Docker reliability.

Server Actions + createStreamableValue kept failing in production; fetch-based text stream avoids RSC serialization issues and shows readable error messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-10 22:39:09 +08:00
parent 0f3bc2c50a
commit dba0245cb1
13 changed files with 342 additions and 384 deletions
+11 -16
View File
@@ -1,7 +1,6 @@
"use client";
import { useState } from "react";
import { readStreamableValue } from "ai/rsc";
import { BrainCircuit } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
@@ -12,8 +11,7 @@ import RegionSelect, {
useRegionLocation,
} from "@/components/shared/region-select";
import { calculateBazi, type BaziChart } from "@/lib/calc/bazi";
import { getBaziAnswer } from "@/app/actions/bazi";
import { ERROR_PREFIX } from "@/lib/constant";
import { streamAiCompletion } from "@/lib/ai/client-stream";
export default function BaziForm() {
const [date, setDate] = useState(nowDateString());
@@ -70,20 +68,17 @@ export default function BaziForm() {
setIsLoading(true);
setShowAi(true);
try {
const stream = await getBaziAnswer(
input,
question,
location!.name,
await streamAiCompletion(
{
mode: "bazi",
payload: {
input,
question,
birthPlaceName: location!.name,
},
},
setCompletion,
);
let ret = "";
for await (const delta of readStreamableValue(stream)) {
if (typeof delta === "string" && delta.startsWith(ERROR_PREFIX)) {
setError(delta.slice(ERROR_PREFIX.length));
return;
}
ret += delta ?? "";
setCompletion(ret);
}
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
} finally {