fix(chat): fold natal reports and drop homepage topic cards
Independent Staging Quality Gate / validate (push) Failing after 9m47s
Independent Staging Quality Gate / publish (push) Skipped

Homepage no longer waits on /api/onboarding for six starter questions.
Natal answers show the spoken layer first; the Level 2 skeleton sits in a
collapsed 完整分析 block. Wide tables scroll sideways on a phone. Form
inputs are 16px so iOS does not zoom on focus.
This commit is contained in:
jesse-ux
2026-09-15 12:27:16 +08:00
parent 899f955d4b
commit 8144fca27d
46 changed files with 966 additions and 2303 deletions
+2 -2
View File
@@ -1353,7 +1353,7 @@ export async function POST(request: Request) {
content: consultationUserTurnContent({
currentTime: currentTimeContext(requestTime),
name,
instruction: "先用 3–6 句口语直接回答下面的问题,不要加标题;然后再按 skill Level 2 骨架写:原始结构、六步宫位、Yoga 表、时机、综合、文末技法审计表,最后才是现代生活。骨架不可省略。星盘事实只使用系统里已经注入的计算结果,不要复述内部字段、JSON 或再跑一遍咨询流程。",
instruction: "先用 3–6 句口语直接回答下面的问题,不要加标题;形状为一句结论、2–3 条短要点(每条完整句子、不超过 30 字)、一句下一步,总量不超过 400 字;然后再按 skill Level 2 骨架写:原始结构、六步宫位、Yoga 表、时机、综合、文末技法审计表,最后才是现代生活。骨架不可省略。星盘事实只使用系统里已经注入的计算结果,不要复述内部字段、JSON 或再跑一遍咨询流程。",
summaryText: historyWindow.summaryText,
question: resolvedQuestion.modelQuestion,
}),
@@ -1377,7 +1377,7 @@ export async function POST(request: Request) {
content: consultationUserTurnContent({
currentTime: currentTimeContext(requestTime),
name,
instruction: "先用 3–6 句口语直接回答下面的问题,不要加标题;然后再按 skill Level 2 骨架写:原始结构、六步宫位、Yoga 表、时机、综合、文末技法审计表,最后才是现代生活。骨架不可省略。星盘事实只使用系统里已经注入的计算结果,不要复述内部字段、JSON 或再跑一遍咨询流程。",
instruction: "先用 3–6 句口语直接回答下面的问题,不要加标题;形状为一句结论、2–3 条短要点(每条完整句子、不超过 30 字)、一句下一步,总量不超过 400 字;然后再按 skill Level 2 骨架写:原始结构、六步宫位、Yoga 表、时机、综合、文末技法审计表,最后才是现代生活。骨架不可省略。星盘事实只使用系统里已经注入的计算结果,不要复述内部字段、JSON 或再跑一遍咨询流程。",
summaryText: historyWindow.summaryText,
question: resolvedQuestion.modelQuestion,
}),
-95
View File
@@ -1,95 +0,0 @@
import {
createOnboardingPost,
type OnboardingProfileRepository,
} from "@/lib/onboarding-post";
import { consultationDomainDefinition } from "@/lib/consultation-domain-registry";
import { onboardingSuggestionThemes } from "@/lib/onboarding-payload";
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
import { createServerSupabaseClient } from "@/lib/supabase/server";
import { getOnboardingAgent } from "@/mastra";
import { loadLanguageModelCatalog } from "@/lib/model-catalog";
export const runtime = "nodejs";
// Ten questions in one call take materially longer than the previous three.
export const maxDuration = 60;
function createProfileRepository(
admin: ReturnType<typeof createAdminSupabaseClient>,
): OnboardingProfileRepository {
return {
async loadProfile(userId) {
return admin
.from("profiles")
.select("id,name,birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,declared_window_start,declared_window_end,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source,ayanamsa,onboarding_payload,onboarding_version,onboarding_generated_at")
.eq("id", userId)
.maybeSingle();
},
async claimProfile(command) {
let claim = admin
.from("profiles")
.update({
onboarding_version: command.pendingVersion,
onboarding_generated_at: command.claimedAt,
})
.eq("id", command.userId);
claim = command.expectedVersion === null
? claim.is("onboarding_version", null)
: claim.eq("onboarding_version", command.expectedVersion);
claim = command.expectedGeneratedAt === null
? claim.is("onboarding_generated_at", null)
: claim.eq("onboarding_generated_at", command.expectedGeneratedAt);
return claim.select("id").maybeSingle();
},
async completeProfile(command) {
return admin
.from("profiles")
.update({
onboarding_payload: command.payload,
onboarding_version: command.readyVersion,
onboarding_generated_at: command.generatedAt,
})
.eq("id", command.userId)
.eq("onboarding_version", command.expectedPendingVersion)
.select("id")
.maybeSingle();
},
};
}
export const POST = createOnboardingPost({
openSession: async () => {
const supabase = await createServerSupabaseClient();
const admin = createAdminSupabaseClient();
const { data: { user }, error } = await supabase.auth.getUser();
return {
userId: user?.id ?? null,
authError: Boolean(error),
repository: createProfileRepository(admin),
};
},
generateText: async (name, signal) => {
const preferredModelId = process.env.ONBOARDING_MODEL_ID?.trim() || "deepseek-v4-flash";
const catalog = await loadLanguageModelCatalog();
const model = catalog.models.find((entry) => entry.id === preferredModelId)
?? catalog.models.find((entry) => entry.id === catalog.defaultModelId)
?? null;
if (!model) return null;
const result = await getOnboardingAgent(model).generate([
{
role: "user",
content: [
name ? `用户称呼:${name.slice(0, 80)}` : "用户未填写称呼。",
`需要的主题,按此顺序各写一个问题:${onboardingSuggestionThemes.join("、")}`,
...onboardingSuggestionThemes.map((theme) => {
const domain = consultationDomainDefinition(theme);
return `- ${theme}${domain.label}):${domain.claimBoundary}`;
}),
"只返回 suggestions 数组,不要欢迎语。",
].join("\n"),
},
], { abortSignal: signal });
return result.text;
},
now: () => new Date(),
warn: (message, detail) => console.warn(message, detail),
});
+65 -144
View File
@@ -563,8 +563,7 @@ button:disabled { cursor: default; opacity: .45; }
.chat-header > div { min-width: 0; flex: 1; }
.chat-header strong { max-width: 100%; }
.onboarding-card { padding: 16px; }
.starter-list > button { min-height: 64px; }
.starter-content span { font-size: 13px; }
.message-assistant .message-content { max-width: 100%; }
.message-user p { font-size: 14px; }
.composer { min-height: 56px; }
@@ -1002,13 +1001,6 @@ button:disabled { cursor: default; opacity: .45; }
.phrase-nowrap { white-space: nowrap; }
.starter-list { border-top: 1px solid var(--color-border); display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); border: 0; }
.starter-list > button { width: 100%; display: grid; align-items: end; border-bottom: 1px solid var(--color-border); cursor: pointer; text-align: left; transition: background-color 120ms ease-out, transform 120ms ease-out; min-height: 136px; grid-template-columns: minmax(0, 1fr) 20px; gap: var(--space-3); padding: var(--space-5); border: 1px solid transparent; border-radius: var(--radius-lg); background: var(--color-canvas-muted); }
.starter-list > button:first-of-type { border-color: color-mix(in srgb, var(--color-action) 18%, var(--color-border)); background: var(--color-action-soft); color: var(--color-ink); }
.starter-list > button:first-of-type .starter-content span { color: var(--color-ink); white-space: normal; }
.starter-list > button:first-of-type .starter-arrow { color: var(--color-action); }
.starter-content { min-width: 0; display: grid; gap: var(--space-2); }
.starter-content b { color: var(--color-action); font-size: var(--type-overline); font-weight: 500; letter-spacing: 1.5px; }
.starter-content span { overflow: hidden; color: var(--color-ink); font-family: var(--font-display); font-size: var(--type-title-md); line-height: 1.4; text-overflow: clip; text-wrap: pretty; white-space: normal; }
.starter-arrow { width: 17px; height: 17px; color: var(--color-ink-secondary); }
.product-entrypoints { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, .88fr); gap: var(--space-3); }
.product-entrypoints small { color: var(--color-ink-secondary); line-height: 1.45; font-size: var(--type-caption); }
@@ -1040,7 +1032,6 @@ button:disabled { cursor: default; opacity: .45; }
.product-entrypoint-action { display: inline-flex; flex: 0 0 auto; align-items: center; justify-content: flex-end; gap: var(--space-1); color: var(--color-action); font-size: var(--type-caption); font-weight: 600; white-space: nowrap; }
.product-entrypoint-action .starter-arrow { width: 15px; height: 15px; color: currentColor; }
.rectification-entry-error { grid-column: 1 / -1; margin: 0; }
.starter-note { margin: var(--space-3) 0 0; color: var(--color-ink-secondary); line-height: 1.5; grid-column: 1 / -1; font-size: var(--type-caption); }
.message-list {
--assistant-content-inset: calc(32px + var(--space-3));
margin: 0 auto;
@@ -1418,6 +1409,50 @@ button:disabled { cursor: default; opacity: .45; }
font-size: inherit;
font-variant-numeric: tabular-nums;
}
.answer-detail {
margin-top: var(--space-5);
padding-top: var(--space-3);
border-top: 1px solid color-mix(in srgb, var(--color-border) 72%, transparent);
}
.answer-detail > summary {
width: fit-content;
display: flex;
align-items: center;
gap: var(--space-2);
min-height: 32px;
margin-inline: calc(var(--space-1) * -1);
padding: 0 var(--space-2);
border-radius: var(--radius-sm);
color: var(--color-ink-tertiary);
cursor: pointer;
list-style: none;
font-size: var(--type-caption);
font-weight: 500;
}
.answer-detail > summary::-webkit-details-marker { display: none; }
.answer-detail > summary::before {
width: 6px;
height: 6px;
border-inline-end: 1.5px solid currentColor;
border-bottom: 1.5px solid currentColor;
content: "";
transform: rotate(-45deg);
transition: transform 120ms ease-out;
}
.answer-detail[open] > summary::before { transform: rotate(45deg) translate(-1px, -1px); }
.answer-detail > summary:hover { background: var(--color-canvas-muted); color: var(--color-ink-secondary); }
.answer-detail > summary:focus-visible {
outline: 2px solid color-mix(in srgb, var(--color-focus) 52%, transparent);
outline-offset: 1px;
}
.answer-detail > summary small {
color: var(--color-ink-tertiary);
font-size: inherit;
font-variant-numeric: tabular-nums;
}
.answer-detail-panel {
margin-top: var(--space-3);
}
.technique-audit-panel {
max-width: 100%;
margin-top: var(--space-2);
@@ -1518,6 +1553,23 @@ button:disabled { cursor: default; opacity: .45; }
.technique-audit-panel tbody tr:last-child {
border-bottom: 0;
}
/* Four-or-more-column tables (Yoga, raw structure) scroll sideways.
Three-column audit tables keep the card stack above. Scoped to chat
so personal-report tables stay on their own rules. */
.conversation .markdown-table:has(table:not(:has(thead th:nth-child(3):last-child))) {
background:
linear-gradient(to right, var(--color-canvas) 30%, transparent) left center / 1.5rem 100% local no-repeat,
linear-gradient(to left, var(--color-canvas) 30%, transparent) right center / 1.5rem 100% local no-repeat,
linear-gradient(to right, color-mix(in srgb, var(--color-ink) 16%, transparent), transparent) left center / 0.75rem 100% scroll no-repeat,
linear-gradient(to left, color-mix(in srgb, var(--color-ink) 16%, transparent), transparent) right center / 0.75rem 100% scroll no-repeat;
overscroll-behavior-x: contain;
}
.conversation .markdown-table table:not(:has(thead th:nth-child(3):last-child)) {
width: auto;
min-width: max-content;
}
}
.error-message { margin: var(--space-3) 0 0; padding: var(--space-3) var(--space-4); border-left: 3px solid var(--color-danger); background: var(--color-danger-muted); color: var(--color-danger); font-size: var(--type-caption); line-height: 1.6; border-color: var(--color-danger); border-radius: 0 var(--radius-md) var(--radius-md) 0; }
.message-stopped-notice { margin: var(--space-2) 0 0; color: var(--color-ink-tertiary); font-size: var(--type-caption); line-height: 1.5; }
@@ -1746,7 +1798,7 @@ button.chart-library-item { cursor: pointer; text-align: left; }
.synastry-history-item { display: grid; gap: 3px; padding: var(--space-3); border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-canvas); color: var(--color-ink); text-align: left; }
.synastry-history-item small { color: var(--color-ink-secondary); font-size: var(--type-caption); }
input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class*=" ant-"]):not(.ant-picker input), select:not([class^="ant-"]):not([class*=" ant-"]) { width: 100%; min-height: 44px; padding: 0 var(--space-3); border: 1px solid var(--color-border-strong); color: var(--color-ink); border-color: var(--color-border-strong); border-radius: var(--radius-md); background: var(--color-canvas); font-size: var(--type-body-sm); }
input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class*=" ant-"]):not(.ant-picker input), select:not([class^="ant-"]):not([class*=" ant-"]) { width: 100%; min-height: 44px; padding: 0 var(--space-3); border: 1px solid var(--color-border-strong); color: var(--color-ink); border-color: var(--color-border-strong); border-radius: var(--radius-md); background: var(--color-canvas); font-size: var(--type-body-md); }
input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class*=" ant-"]):not(.ant-picker input):disabled, select:not([class^="ant-"]):not([class*=" ant-"]):disabled { color: var(--color-ink-tertiary); background: var(--color-canvas-muted); }
.button-primary, .button-secondary { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0 var(--space-4); border: 1px solid var(--color-action); cursor: pointer; text-decoration: none; transition: background-color 120ms ease-out, color 120ms ease-out, transform 120ms ease-out; border-radius: var(--radius-md); font-size: var(--type-body-sm); font-weight: 500; }
.button-primary { border-color: var(--color-action); background: var(--color-action); color: var(--color-on-dark); }
@@ -1883,7 +1935,6 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.birth-time-evidence-actions > button, .birth-time-guided-actions > button, .birth-time-candidate-terminal > button, .birth-time-confirmation-panel > button { width: 100%; }
.birth-time-draft-fields { grid-template-columns: 1fr; }
.welcome > .onboarding-message:first-child .message-bubble p { font-size: var(--type-title-lg); }
.starter-content span { font-size: var(--type-title-sm); }
.account-modal h2 { font-size: var(--type-title-lg); }
.account-redeem-form > div { grid-template-columns: 1fr; }
.paywall-footer { align-items: stretch; flex-direction: column; }
@@ -1929,8 +1980,7 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
}
.starter-hero,
.product-entrypoints,
.starter-themes {
.product-entrypoints {
width: 100%;
min-width: 0;
}
@@ -2133,98 +2183,6 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
color: currentColor;
}
.starter-themes {
display: grid;
gap: var(--space-4);
}
.starter-section-heading {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: var(--space-5);
}
.starter-section-heading h2 {
margin: 0;
color: var(--color-ink);
font-family: var(--font-display);
font-size: var(--type-title-lg);
font-weight: 400;
letter-spacing: -.025em;
}
.starter-section-heading p {
margin: 0;
color: var(--color-ink-tertiary);
font-size: var(--type-caption);
}
.starter-theme-accordion {
min-width: 0;
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: var(--space-3);
}
.starter-theme-card {
position: relative;
min-width: 0;
min-height: 156px;
display: grid;
grid-template-columns: minmax(0, 1fr) 20px;
align-items: end;
gap: var(--space-3);
padding: var(--space-5);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
background: var(--color-canvas-soft);
cursor: pointer;
text-align: left;
transition: border-color 180ms ease-out, background-color 180ms ease-out, box-shadow 180ms ease-out, transform 180ms var(--ease-out);
}
.starter-theme-card:not(:disabled):active {
background: color-mix(in srgb, var(--color-action-soft) 56%, var(--color-canvas));
}
.starter-theme-card:focus-visible {
border-color: color-mix(in srgb, var(--color-action) 38%, var(--color-border));
box-shadow: var(--shadow-soft);
}
@media (hover: hover) {
.starter-theme-card:not(:disabled):hover .starter-arrow {
color: var(--color-action);
transform: translate(2px, -2px);
}
}
.starter-content {
min-width: 0;
display: grid;
gap: var(--space-3);
}
.starter-content b {
color: var(--color-action);
font-size: var(--type-body-sm);
font-weight: 600;
letter-spacing: .04em;
}
.starter-content span {
max-width: none;
overflow: visible;
color: var(--color-ink);
font-family: var(--font-display);
font-size: var(--type-title-md);
line-height: 1.38;
text-overflow: clip;
text-wrap: pretty;
white-space: normal;
}
.starter-arrow {
width: 17px;
height: 17px;
@@ -2232,14 +2190,6 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
transition: color 180ms ease-out, transform 180ms var(--ease-out);
}
.starter-note {
margin: calc(var(--space-2) * -1) 0 0;
color: var(--color-ink-secondary);
line-height: 1.5;
font-size: var(--type-caption);
}
.composer-wrap-starter .composer,
.composer-wrap-starter .composer-footer {
width: min(1040px, 100%);
@@ -2277,14 +2227,6 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
margin-left: 0;
justify-content: flex-start;
}
.starter-theme-accordion {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.starter-theme-card {
min-height: 142px;
}
}
@media (max-width: 767px) {
@@ -2342,34 +2284,12 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
font-size: var(--type-body-sm);
font-weight: 500;
}
.starter-section-heading {
display: grid;
gap: var(--space-1);
}
.starter-theme-accordion {
grid-template-columns: 1fr;
gap: var(--space-3);
}
.starter-theme-card {
min-height: 112px;
}
.starter-content span {
max-width: 440px;
}
}
@media (max-width: 480px) {
.starter-hero {
padding: var(--space-6) var(--space-5);
}
.starter-content span {
font-size: var(--type-title-sm);
}
}
/* Session conversation */
@@ -4587,4 +4507,5 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
-webkit-text-fill-color: currentColor;
}
.technique-audit > summary::before { transition: none; }
.answer-detail > summary::before { transition: none; }
}
+2 -68
View File
@@ -85,7 +85,7 @@ import {
isGuidedBirthTimePreview,
previewRectificationJourney,
} from "@/lib/birth-time-guided-preview";
import { generalGuidedJyotishTopics } from "@/lib/guided-jyotish-topics";
import { keepFocusWithin } from "@/lib/focus-trap";
import {
BALANCE_SYNC_KEY,
@@ -132,15 +132,9 @@ import {
} from "@/lib/chat-session-url";
import { consultationReportMarkdown } from "@/lib/consultation-report-export";
import {
OnboardingAuthenticationError,
type OnboardingContent,
createStartGreeting,
createStartGreetingParts,
isCurrentOnboardingRequest,
onboardingProfileFingerprint,
onboardingRequestIdentity,
requestOnboardingWithRecovery,
} from "@/lib/onboarding-client";
} from "@/lib/starter-greeting";
import {
calendarDateInTimeZone,
dailyStarlanguageProfileKey,
@@ -161,7 +155,6 @@ import {
pendingConsultationStorageKey,
presetOnboardingMessage,
previewModelCatalog,
themes,
timestamp,
type Account,
type AccountDialog,
@@ -314,8 +307,6 @@ export default function Home() {
const [creatingSession, setCreatingSession] = useState(false);
const [sessionDetailLoadingId, setSessionDetailLoadingId] = useState<string | null>(null);
const [sessionFullPrompt, setSessionFullPrompt] = useState<{ question: string; theme: Theme } | null>(null);
const [onboarding, setOnboarding] = useState<OnboardingContent | null>(null);
const [onboardingError, setOnboardingError] = useState("");
const [onboardingStep, setOnboardingStep] = useState<OnboardingStep>("name");
const [onboardingJustCompleted, setOnboardingJustCompleted] = useState(false);
const [onboardingPaywallOpen, setOnboardingPaywallOpen] = useState(false);
@@ -357,7 +348,6 @@ export default function Home() {
onRegenerate() {},
onFollowUp() {},
});
const activeOnboardingRequestIdentity = useRef("");
const accountRefreshGuard = useRef(createLatestAccountRequestGuard());
const resumeRectificationSession = useRef<(session: ChatSession) => void>(() => undefined);
const rectificationOpenInFlight = useRef(false);
@@ -429,8 +419,6 @@ export default function Home() {
const rectificationErrorMessage = rectificationError === "profile_incomplete"
? "服务端未能读取完整出生资料,请重新确认并保存后再开始生时校正。"
: rectificationError;
const onboardingFingerprint = onboardingProfileFingerprint(profile);
const {
updateSession,
persistSession,
@@ -657,11 +645,8 @@ export default function Home() {
const birthTimeRoute = resolveBirthTimeConsultationRoute(profile, birthTimeConsultationConsent, activeSessionId);
const natalMinuteAvailable = birthTimeRoute.kind === "consult"
&& (birthTimeRoute.mode === "verified_chart" || birthTimeRoute.mode === "unverified_birth_time");
const personalConsultationAvailable = birthTimeRoute.kind === "consult"
&& birthTimeRoute.mode !== "general_no_birth_time";
const dailyStarlanguageFingerprint = dailyStarlanguageProfileKey(profile);
const starterThemes = personalConsultationAvailable ? themes : generalGuidedJyotishTopics;
const dailyStarlanguageQuestion = !natalMinuteAvailable
? GENERAL_NO_MINUTE_DAILY_FORTUNE_QUESTION
: dailyStarlanguage.kind === "unavailable"
@@ -671,10 +656,7 @@ export default function Home() {
? dailyStarlanguage.card.trend
: "今天的星语还没写出来。";
const dailyStarlanguageAction = dailyStarlanguage.kind === "ready" ? dailyStarlanguage.card.action : "";
const onboardingPending = profileComplete && !onboarding && !onboardingError;
const bootstrapPrepareReady = bootstrapPrepareSettled({
profileComplete,
onboardingSettled: onboarding !== null || onboardingError !== "",
dailyStarlanguageApplicable: Boolean(accountId) && profileComplete && natalMinuteAvailable,
dailyStarlanguageSettled: dailyStarlanguage.kind !== "pending",
entrySummarySettled: rectificationEntrySummarySettled,
@@ -726,12 +708,8 @@ export default function Home() {
const shouldStreamOnboarding = !profileComplete;
const presetMessageFinished = !shouldStreamOnboarding || presetMessageLength >= currentOnboardingMessage.length;
const onboardingCardReady = presetMessageFinished || birthTimeAssessmentPhase !== null;
const starterSuggestions = starterThemes.map((theme) => personalConsultationAvailable
? onboarding?.suggestions.find((item) => item.theme === theme.id) ?? { theme: theme.id, text: theme.prompt }
: { theme: theme.id, text: theme.prompt });
const starterHomeVisible = profileComplete
&& presetMessageFinished
&& !onboardingPending
&& !rectificationSurfaceOpen
&& Boolean(activeSession?.messagesHydrated)
&& !activeSession.messages.length;
@@ -931,9 +909,6 @@ export default function Home() {
setActiveSessionId(previewSession.id);
const previewGreeting = previewProfile.name.trim() ? createStartGreeting(previewProfile.name) : "";
setStartGreeting(previewGreeting);
setOnboarding(previewMode === "onboarding"
? null
: { suggestions: themes.map(({ id, prompt }) => ({ theme: id, text: prompt })) });
setHydrated(true);
return;
}
@@ -1261,43 +1236,6 @@ export default function Home() {
return () => window.clearInterval(timer);
}, [currentOnboardingMessage, hydrated, shouldStreamOnboarding]);
useEffect(() => {
if (bootstrapPhase === "account" || !accountId || !profileComplete || uiPreview.current) return;
const requestIdentity = onboardingRequestIdentity(accountId, onboardingFingerprint);
if (isCurrentOnboardingRequest(activeOnboardingRequestIdentity.current, requestIdentity)) return;
activeOnboardingRequestIdentity.current = requestIdentity;
const controller = new AbortController();
setOnboarding(null);
setOnboardingError("");
void requestOnboardingWithRecovery(controller.signal, () => {
if (!controller.signal.aborted
&& isCurrentOnboardingRequest(activeOnboardingRequestIdentity.current, requestIdentity)) {
setOnboardingError("个性化入门问题准备超时");
}
})
.then((content) => {
if (controller.signal.aborted
|| !isCurrentOnboardingRequest(activeOnboardingRequestIdentity.current, requestIdentity)) return;
setOnboarding(content);
setOnboardingError("");
})
.catch((caught: unknown) => {
if (controller.signal.aborted
|| !isCurrentOnboardingRequest(activeOnboardingRequestIdentity.current, requestIdentity)) return;
if (caught instanceof OnboardingAuthenticationError) {
window.location.assign("/login");
return;
}
setOnboardingError(caught instanceof Error ? caught.message : "暂时无法准备初始问题");
});
return () => {
if (isCurrentOnboardingRequest(activeOnboardingRequestIdentity.current, requestIdentity)) {
activeOnboardingRequestIdentity.current = "";
}
controller.abort();
};
}, [accountId, bootstrapPhase, onboardingFingerprint, profile.name, profileComplete]);
useEffect(() => {
if (bootstrapPhase === "account" || !accountId || !profileComplete || !natalMinuteAvailable) return;
const today = calendarDateInTimeZone(new Date(), profile.timezoneId);
@@ -1882,10 +1820,6 @@ export default function Home() {
rectificationError={rectificationErrorSessionId ? "" : rectificationError}
rectificationSurfaceOpen={rectificationSurfaceOpen}
rectificationErrorMessage={rectificationErrorSessionId ? "" : rectificationErrorMessage}
starterThemes={starterThemes}
starterSuggestions={starterSuggestions}
startSuggestedConsultation={startSuggestedConsultation}
onboardingError={onboardingError}
/>
)}
</div>