fix: scope onboarding fallback greeting
This commit is contained in:
@@ -46,6 +46,7 @@ import { chatMessageViews, type ChatMessage } from "@/lib/chat-message-view";
|
||||
import {
|
||||
OnboardingAuthenticationError,
|
||||
type OnboardingContent,
|
||||
createOnboardingFallbackGreeting,
|
||||
createStartGreeting,
|
||||
isCurrentOnboardingRequest,
|
||||
onboardingProfileFingerprint,
|
||||
@@ -2320,7 +2321,7 @@ export default function Home() {
|
||||
<OnboardingChatMessage role="assistant" text={onboarding?.greeting
|
||||
|| (onboardingPending
|
||||
? `${profile.name.trim()},稍等一下,我正在准备几个适合开始的问题。`
|
||||
: startGreeting || `${profile.name.trim()},从你此刻最关心的问题开始吧。`)} />
|
||||
: createOnboardingFallbackGreeting(profile.name))} />
|
||||
)}
|
||||
|
||||
{!profileComplete && onboardingStep === "birth" && onboardingCardReady && (
|
||||
|
||||
@@ -104,6 +104,10 @@ export function createStartGreeting(
|
||||
return variants[Math.floor(variantSelection * variants.length)](displayName);
|
||||
}
|
||||
|
||||
export function createOnboardingFallbackGreeting(name: string): string {
|
||||
return `${name.trim()},从你此刻最关心的问题开始吧。`;
|
||||
}
|
||||
|
||||
export function onboardingProfileFingerprint(profile: OnboardingProfileFingerprintInput): string {
|
||||
return JSON.stringify([
|
||||
profile.name,
|
||||
|
||||
@@ -3,10 +3,6 @@ import test from "node:test";
|
||||
import {
|
||||
OnboardingAuthenticationError,
|
||||
OnboardingRequestError,
|
||||
createStartGreeting,
|
||||
isCurrentOnboardingRequest,
|
||||
onboardingProfileFingerprint,
|
||||
onboardingRequestIdentity,
|
||||
requestOnboardingWithRecovery,
|
||||
} from "../src/lib/onboarding-client.ts";
|
||||
|
||||
@@ -20,28 +16,6 @@ const personalizedOnboarding = {
|
||||
source: "cache",
|
||||
} as const;
|
||||
|
||||
const completeProfile = {
|
||||
name: "林遥", date: "1990-06-15", time: "12:30", reportedTime: "12:30",
|
||||
birthTimeSource: "hospital_record", birthTimePeriod: "", birthTimeClue: "出生证明", birthTimeStatus: "confirmed",
|
||||
uncertaintyBeforeMinutes: 0, uncertaintyAfterMinutes: 0, rectificationCaseId: "", countryCode: "CN", provinceCode: "110000", cityCode: "110000-city", districtCode: "110101",
|
||||
} as const;
|
||||
|
||||
test("rejects a stale completion after a complete profile changes", () => {
|
||||
// Given: one account starts onboarding for a complete persisted profile.
|
||||
const firstIdentity = onboardingRequestIdentity("account-1", onboardingProfileFingerprint(completeProfile));
|
||||
|
||||
// When: a presentation-affecting profile field changes before that request completes.
|
||||
const changedFingerprint = onboardingProfileFingerprint({ ...completeProfile, name: "周宁" });
|
||||
const currentIdentity = onboardingRequestIdentity("account-1", changedFingerprint);
|
||||
const committedGreeting = createStartGreeting("周宁", new Date("2026-07-19T08:00:00+08:00"), 0);
|
||||
|
||||
// Then: the new profile has a distinct identity and its greeting cannot retain the old name.
|
||||
assert.notEqual(currentIdentity, firstIdentity);
|
||||
assert.equal(isCurrentOnboardingRequest(currentIdentity, firstIdentity), false);
|
||||
assert.match(committedGreeting, /周宁/);
|
||||
assert.doesNotMatch(committedGreeting, /林遥/);
|
||||
});
|
||||
|
||||
test("returns personalized cache content after a timeout and pending response", async () => {
|
||||
// Given: the first request times out, the second is provisional, and the third is terminal.
|
||||
const originalFetch = globalThis.fetch;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import {
|
||||
createOnboardingFallbackGreeting,
|
||||
createStartGreeting,
|
||||
isCurrentOnboardingRequest,
|
||||
onboardingProfileFingerprint,
|
||||
onboardingRequestIdentity,
|
||||
} from "../src/lib/onboarding-client.ts";
|
||||
|
||||
const completeProfile = {
|
||||
name: "林遥", date: "1990-06-15", time: "12:30", reportedTime: "12:30",
|
||||
birthTimeSource: "hospital_record", birthTimePeriod: "", birthTimeClue: "出生证明", birthTimeStatus: "confirmed",
|
||||
uncertaintyBeforeMinutes: 0, uncertaintyAfterMinutes: 0, rectificationCaseId: "", countryCode: "CN", provinceCode: "110000", cityCode: "110000-city", districtCode: "110101",
|
||||
} as const;
|
||||
|
||||
test("rejects stale A presentation and derives terminal and fallback greetings from profile B", () => {
|
||||
// Given: one account starts onboarding for a complete persisted profile A.
|
||||
const firstIdentity = onboardingRequestIdentity("account-1", onboardingProfileFingerprint(completeProfile));
|
||||
|
||||
// When: the name changes before that request completes and profile B is presented.
|
||||
const changedProfile = { ...completeProfile, name: "周宁" };
|
||||
const currentIdentity = onboardingRequestIdentity("account-1", onboardingProfileFingerprint(changedProfile));
|
||||
const terminalGreeting = createStartGreeting(changedProfile.name, new Date("2026-07-19T08:00:00+08:00"), 0);
|
||||
const fallbackGreeting = createOnboardingFallbackGreeting(changedProfile.name);
|
||||
|
||||
// Then: stale work is rejected and neither presentation path can retain A's name.
|
||||
assert.notEqual(currentIdentity, firstIdentity);
|
||||
assert.equal(isCurrentOnboardingRequest(currentIdentity, firstIdentity), false);
|
||||
for (const greeting of [terminalGreeting, fallbackGreeting]) {
|
||||
assert.match(greeting, /周宁/);
|
||||
assert.doesNotMatch(greeting, /林遥/);
|
||||
}
|
||||
assert.equal(fallbackGreeting, "周宁,从你此刻最关心的问题开始吧。");
|
||||
});
|
||||
Reference in New Issue
Block a user