fix(chat): honor new-chat intent from secondary pages
Independent Staging Quality Gate / validate (push) Successful in 13m41s
Independent Staging Quality Gate / publish (push) Successful in 3m30s

Create a fresh local consultation for explicit new-chat navigation and keep reserved recovery from taking over its landing. Add regression tests and record validation gaps for remote review.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
jesse-ux
2026-09-24 00:25:28 +08:00
co-authored by Claude Code
parent 1c95eb3979
commit 8902e48468
17 changed files with 368 additions and 6 deletions
+20 -1
View File
@@ -1,4 +1,5 @@
export const SESSION_URL_QUERY_KEY = "c";
export const NEW_CHAT_QUERY_KEY = "new";
export const SESSION_URL_RETURN_STORAGE_KEY = "jyotisha.session-url-return";
export const SESSION_MISSING_NOTICE = "该对话不存在或已被删除";
export const SESSION_LOOKUP_FAILED_NOTICE = "这条对话暂时读不到,请稍后重试。";
@@ -11,11 +12,20 @@ export type SessionUrlQuery = {
export type BootstrapSessionSelection = {
readonly sessionId: string;
readonly urlAction: "keep" | "replace-selected" | "replace-clear" | "none" | "lookup";
readonly urlAction: "keep" | "replace-selected" | "replace-clear" | "none" | "lookup" | "new-chat";
readonly missing: boolean;
readonly clearStoredReturn: boolean;
};
export function newChatHref(): string {
return "/?new=1";
}
export function parseNewChatIntent(search: string): boolean {
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
return params.has(NEW_CHAT_QUERY_KEY);
}
export function parseSessionUrlQuery(search: string): SessionUrlQuery {
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
if (!params.has(SESSION_URL_QUERY_KEY)) {
@@ -30,6 +40,7 @@ export function parseSessionUrlQuery(search: string): SessionUrlQuery {
export function sessionHref(search: string, sessionId: string | null, pathname = "/"): string {
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
params.delete(NEW_CHAT_QUERY_KEY);
if (sessionId) params.set(SESSION_URL_QUERY_KEY, sessionId);
else params.delete(SESSION_URL_QUERY_KEY);
const query = params.toString();
@@ -79,6 +90,14 @@ export function resolveBootstrapSessionSelection(input: {
readonly search: string;
readonly storedReturnId: string | null;
}): BootstrapSessionSelection {
if (parseNewChatIntent(input.search)) {
return {
sessionId: input.defaultSessionId,
urlAction: "new-chat",
missing: false,
clearStoredReturn: true,
};
}
const query = parseSessionUrlQuery(input.search);
if (query.present) {
if (query.sessionId && input.listedIds.includes(query.sessionId)) {
+3 -2
View File
@@ -18,7 +18,7 @@ export type LandingSession = Readonly<{
messages: readonly unknown[];
}>;
export type LandingUrlAction = "keep" | "replace-selected" | "replace-clear" | "none" | "lookup";
export type LandingUrlAction = "keep" | "replace-selected" | "replace-clear" | "none" | "lookup" | "new-chat";
/**
* A rectification Case is opened only when the address bar names that session
@@ -43,7 +43,7 @@ export function resolveStarterHomeLandingSessionId(
selectedId: string,
urlAction: LandingUrlAction,
): string {
if (urlAction === "keep" || urlAction === "replace-selected" || urlAction === "lookup") {
if (urlAction === "keep" || urlAction === "replace-selected" || urlAction === "lookup" || urlAction === "new-chat") {
return selectedId;
}
const selected = sessions.find((session) => session.id === selectedId);
@@ -61,6 +61,7 @@ export function starterHomeLandingNeedsConsultation(
landingId: string,
urlAction: LandingUrlAction,
): boolean {
if (urlAction === "new-chat") return true;
if (urlAction === "keep" || urlAction === "replace-selected" || urlAction === "lookup") return false;
const landing = sessions.find((session) => session.id === landingId);
return !landing || landing.sessionType === "birth_time_rectification";