fix(home): request the daily card on the same condition that renders it
Independent Staging Quality Gate / validate (pull_request) Successful in 9m16s
Independent Staging Quality Gate / publish (pull_request) Has been skipped
Independent Staging Quality Gate / validate (push) Successful in 9m44s
Independent Staging Quality Gate / publish (push) Successful in 8m41s
Independent Staging Quality Gate / validate (pull_request) Successful in 9m16s
Independent Staging Quality Gate / publish (pull_request) Has been skipped
Independent Staging Quality Gate / validate (push) Successful in 9m44s
Independent Staging Quality Gate / publish (push) Successful in 8m41s
The daily starlanguage card sat on "正在结合你的星盘写今天的星语。" forever for every account whose birth time was usable. Its effect bailed out on birthTimeDisplayState(profile), which returns a value precisely when the birth time is candidate, accepted or confirmed, so the request went out only for accounts that had nothing to read. The guard predates the Agent rewrite and was masked by the written-in client fallback that rewrite deleted. It now gates on personalChartAvailable, the same fact the card uses to render personal content, and retries once before admitting that today has no card. The route stops letting one engine call take the whole card down silently: /api/chart fails into a named reason like the other four layers, and the engine and agent budgets leave room for a cold chart and an observed 30s generation inside the 60s ceiling. The home also had three greeting implementations. The hero heading drew from a static pool while the time-aware greeting lived elsewhere and the Agent's own greeting was overwritten client-side into a field nothing rendered. createStartGreeting now exposes its salutation and question halves, the hero uses both, and the served greeting reaches the hero note. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,15 +20,19 @@ export const maxDuration = 60;
|
||||
type Profile = GlobalBirthProfile & { birthTimeStatus?: string };
|
||||
type BirthPayload = NonNullable<Awaited<ReturnType<typeof dailyProfilePayload>>>;
|
||||
type CacheEntry = { readonly day: string; readonly card: DailyStarlanguageCard };
|
||||
type GenerationFailure = "chart_unavailable" | "model_unavailable" | "agent_generation_failed";
|
||||
type Generated =
|
||||
| { readonly kind: "card"; readonly card: DailyStarlanguageCard }
|
||||
| { readonly kind: "failed"; readonly reason: GenerationFailure };
|
||||
|
||||
const jyotishApiBase = process.env.JYOTISH_API_BASE ?? "http://127.0.0.1:5200";
|
||||
const engineTimeoutMs = 8_000;
|
||||
const agentTimeoutMs = 30_000;
|
||||
const engineTimeoutMs = 20_000;
|
||||
const agentTimeoutMs = 45_000;
|
||||
const cacheLimit = 500;
|
||||
|
||||
const state = globalThis as typeof globalThis & {
|
||||
jyotishaDailyStarlanguageCache?: Map<string, CacheEntry>;
|
||||
jyotishaDailyStarlanguagePending?: Map<string, Promise<DailyStarlanguageCard | null>>;
|
||||
jyotishaDailyStarlanguagePending?: Map<string, Promise<Generated>>;
|
||||
};
|
||||
|
||||
function cache() {
|
||||
@@ -85,9 +89,12 @@ function chartPoints(chart: Record<string, unknown>) {
|
||||
}
|
||||
|
||||
async function collectLayers(payload: BirthPayload, today: string) {
|
||||
const chart = await fetchEngine("/api/chart", payload);
|
||||
const points = chartPoints(chart);
|
||||
if (!points) return null;
|
||||
const chart = await fetchEngine("/api/chart", payload).catch((error: unknown) => {
|
||||
console.warn("daily_starlanguage_chart_unavailable", error);
|
||||
return null;
|
||||
});
|
||||
const points = chart === null ? null : chartPoints(chart);
|
||||
if (chart === null || !points) return null;
|
||||
const tomorrow = new Date(`${today}T00:00:00.000Z`);
|
||||
tomorrow.setUTCDate(tomorrow.getUTCDate() + 1);
|
||||
const withPoints = { ...payload, planets: points.planets, ascendant: points.ascendant };
|
||||
@@ -106,21 +113,22 @@ async function collectLayers(payload: BirthPayload, today: string) {
|
||||
return { chart, vimshottari, narayana, varga, transit };
|
||||
}
|
||||
|
||||
async function generateCard(payload: BirthPayload, profile: Profile, today: string) {
|
||||
async function generateCard(payload: BirthPayload, profile: Profile, today: string): Promise<Generated> {
|
||||
const layers = await collectLayers(payload, today);
|
||||
if (!layers) return null;
|
||||
if (!layers) return { kind: "failed", reason: "chart_unavailable" };
|
||||
const modelId = process.env.DAILY_STARLANGUAGE_MODEL_ID?.trim() || "deepseek-v4-flash";
|
||||
const catalog = await loadLanguageModelCatalog();
|
||||
const model = catalog.models.find((entry) => entry.id === modelId)
|
||||
?? catalog.models.find((entry) => entry.id === catalog.defaultModelId)
|
||||
?? null;
|
||||
if (!model) return null;
|
||||
if (!model) return { kind: "failed", reason: "model_unavailable" };
|
||||
const evidence = dailyStarlanguageEvidence(layers, today, profile.birthTimeStatus === "confirmed");
|
||||
const result = await getDailyStarlanguageAgent(model).generate(
|
||||
[{ role: "user", content: dailyStarlanguagePrompt(evidence) }],
|
||||
{ abortSignal: AbortSignal.timeout(agentTimeoutMs) },
|
||||
);
|
||||
return parseDailyStarlanguageText(result.text);
|
||||
const card = parseDailyStarlanguageText(result.text);
|
||||
return card ? { kind: "card", card } : { kind: "failed", reason: "agent_generation_failed" };
|
||||
}
|
||||
|
||||
function unavailable(reason: string) {
|
||||
@@ -156,19 +164,19 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
const inFlight = pending().get(key) ?? generateCard(payload, profile, today)
|
||||
.catch((error: unknown) => {
|
||||
.catch((error: unknown): Generated => {
|
||||
console.warn("daily_starlanguage_generation_failed", error);
|
||||
return null;
|
||||
return { kind: "failed", reason: "agent_generation_failed" };
|
||||
})
|
||||
.finally(() => pending().delete(key));
|
||||
pending().set(key, inFlight);
|
||||
|
||||
const card = await inFlight;
|
||||
if (!card) return unavailable("agent_generation_failed");
|
||||
writeCache(key, today, card);
|
||||
const generated = await inFlight;
|
||||
if (generated.kind === "failed") return unavailable(generated.reason);
|
||||
writeCache(key, today, generated.card);
|
||||
return NextResponse.json({
|
||||
status: "ok",
|
||||
card,
|
||||
card: generated.card,
|
||||
source: "agent",
|
||||
claim_status: "exploratory_unvalidated",
|
||||
boundary: "not_deterministic_prediction",
|
||||
|
||||
Reference in New Issue
Block a user