Files
zhimingge/app/actions/combined.ts
T
dekun 0f3bc2c50a Fix AI stream by returning stream.value directly from Server Actions.
createStreamableValue must be created and returned in the action itself; wrapping in { data } or a helper return caused production RSC serialization errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 22:24:57 +08:00

89 lines
2.2 KiB
TypeScript

"use server";
import { createStreamableValue } from "ai/rsc";
import { pumpAIStream } from "@/lib/ai/stream";
import {
calculateBazi,
formatBaziForPrompt,
type BaziInput,
} from "@/lib/calc/bazi";
import {
formatTimingForPrompt,
getTimingInfoWithLongitude,
} from "@/lib/calc/timing";
import { COMBINED_SYSTEM_PROMPT } from "@/lib/prompts";
import {
extractChangeDetails,
extractZhangMingRen,
readGuaMarkdown,
} from "@/lib/content/zhouyi";
export interface CombinedInput {
birth: BaziInput;
birthPlaceName: string;
currentPlaceName: string;
currentLongitude: number;
calcDate: string;
calcTime: string;
question: string;
hexagram?: {
guaMark: string;
guaTitle: string;
guaResult: string;
guaChange: string;
};
}
export async function getCombinedAnswer(input: CombinedInput) {
const chart = calculateBazi(input.birth);
const chartText = formatBaziForPrompt(chart);
const { timing, trueSolarTime } = getTimingInfoWithLongitude(
input.calcDate,
input.calcTime,
input.currentLongitude,
);
const timingText = [
formatTimingForPrompt(timing, input.currentPlaceName, input.currentLongitude),
`真太阳时:${trueSolarTime}`,
].join("\n");
let hexagramText = "";
if (input.hexagram) {
const { guaMark, guaTitle, guaResult, guaChange } = input.hexagram;
try {
const guaDetail = await readGuaMarkdown(guaMark);
const explain = extractZhangMingRen(guaDetail) ?? "";
const changeList = extractChangeDetails(guaDetail, guaChange, guaTitle);
hexagramText = [
"",
"【卦象 · 可选六爻】",
`${guaTitle} ${guaResult} ${guaChange}`,
explain,
changeList.join("\n"),
].join("\n");
} catch {
hexagramText = [
"",
"【卦象 · 可选六爻】",
`${input.hexagram.guaTitle} ${input.hexagram.guaResult} ${input.hexagram.guaChange}`,
].join("\n");
}
}
const stream = createStreamableValue<string>();
pumpAIStream(
stream,
COMBINED_SYSTEM_PROMPT,
`【人和 · 八字排盘】
出生地:${input.birthPlaceName}
${chartText}
${timingText}
${hexagramText}
【问事】
${input.question}`,
);
return stream.value;
}