fix(chat): make cloud the only truth for charts, synastry, and pin/archive
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled

Local fallbacks were creating fake saves and resurrecting deleted rows.
Pin and archive now live on chat_sessions so they follow the account.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-01 21:38:21 +08:00
co-authored by Cursor
parent 31c7b48261
commit ce6a8a7e72
16 changed files with 390 additions and 153 deletions
+8 -5
View File
@@ -9,14 +9,17 @@ export function chartLibrarySessionBranch(
return "persist-self";
}
export function chartLibraryFromCloudOthers<T extends { role: "self" | "other" }>(
export function chartLibraryFromCloudOthers<T extends { role: "self" | "other" }, P>(
cloudLibrary: readonly T[],
profile: unknown,
upsertSelfChart: (library: T[], profile: unknown) => T[],
profile: P,
upsertSelfChart: (library: T[], profile: P) => T[],
): T[] {
return upsertSelfChart(cloudLibrary.filter((record) => record.role !== "self"), profile);
}
export function keepLocalChartLibraryOnCloudFailure<T>(localLibrary: T): T {
return localLibrary;
export function chartLibraryOnCloudFailure<T, P>(
profile: P,
upsertSelfChart: (library: T[], profile: P) => T[],
): T[] {
return upsertSelfChart([], profile);
}
+1 -1
View File
@@ -10,7 +10,7 @@ export type ChatNoticeAction = Readonly<{
}>;
const ongoingNotice = /正在|请稍候|请先|联网后/;
const failedNotice = /失败|无法|不可用|未找到|已写满|已被删除/;
const failedNotice = /失败|无法|不可用|未能|未找到|已写满|已被删除/;
const settledNotice = /^已|^回答已恢复/;
export function noticeTone(message: string): NoticeTone {
@@ -37,6 +37,8 @@ export const chatSessionMetadataPatchSchema = z.object({
title: z.string().trim().min(1).max(160).optional(),
theme: consultationDomainSchema.optional(),
model_id: z.string().trim().min(1).max(64).optional(),
pinned: z.boolean().optional(),
archived_at: z.string().datetime().nullable().optional(),
...chartBindingSchema,
}).strict().refine(
(value) => Object.values(value).some((field) => field !== undefined),
@@ -123,6 +125,8 @@ export function extractChatSessionMetadataPatch(payload: unknown): unknown {
if ("chart_profile_id" in record) patch.chart_profile_id = record.chart_profile_id;
if ("chart_profile_name" in record) patch.chart_profile_name = record.chart_profile_name;
if ("chart_profile_role" in record) patch.chart_profile_role = record.chart_profile_role;
if ("pinned" in record) patch.pinned = record.pinned;
if ("archived_at" in record) patch.archived_at = record.archived_at;
return patch;
}
@@ -130,6 +134,8 @@ export type ChatSessionMetadataPatch = Readonly<{
title?: string;
theme?: ConsultationDomain;
model_id?: string;
pinned?: boolean;
archived_at?: string | null;
chart_profile_id?: string | null;
chart_profile_name?: string | null;
chart_profile_role?: "self" | "other" | null;