Refine chat session storage and title handling
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
+215
-293
@@ -1,39 +1,21 @@
|
||||
import { openDB, type DBSchema } from "idb";
|
||||
import { apiFetch } from "@/lib/apiFetch";
|
||||
import { config } from "@config/config";
|
||||
|
||||
import type {
|
||||
BranchGroup,
|
||||
ChatSessionRecord,
|
||||
ChatSessionSummary,
|
||||
ChatStorageMeta,
|
||||
LegacyPersistedChatState,
|
||||
LoadedChatState,
|
||||
Message,
|
||||
} from "./GlobalChatbox.types";
|
||||
import {
|
||||
cloneBranchGroups,
|
||||
cloneMessages,
|
||||
createId,
|
||||
} from "./GlobalChatbox.utils";
|
||||
import { cloneBranchGroups, cloneMessages } from "./GlobalChatbox.utils";
|
||||
|
||||
const CHAT_DB_NAME = "tjwater-agent-chat";
|
||||
const CHAT_DB_VERSION = 1;
|
||||
const SESSION_STORE = "sessions";
|
||||
const META_STORE = "meta";
|
||||
const META_KEY = "chat-meta" as const;
|
||||
const LEGACY_CHAT_STORAGE_KEY = "tjwater_agent_chat_state_v1";
|
||||
const ACTIVE_SESSION_STORAGE_KEY = "tjwater_agent_active_session_id_v2";
|
||||
|
||||
type ChatDB = DBSchema & {
|
||||
sessions: {
|
||||
key: string;
|
||||
value: ChatSessionRecord;
|
||||
indexes: {
|
||||
"by-updatedAt": number;
|
||||
};
|
||||
};
|
||||
meta: {
|
||||
key: string;
|
||||
value: ChatStorageMeta;
|
||||
};
|
||||
type RemoteSessionPayload = {
|
||||
id?: string;
|
||||
title?: string;
|
||||
created_at?: string | number;
|
||||
updated_at?: string | number;
|
||||
};
|
||||
|
||||
const emptyLoadedChatState = (): LoadedChatState => ({
|
||||
@@ -51,17 +33,6 @@ const sanitizeMessages = (messages: Message[] | undefined) =>
|
||||
const sanitizeBranchGroups = (branchGroups: BranchGroup[] | undefined) =>
|
||||
Array.isArray(branchGroups) ? cloneBranchGroups(branchGroups) : [];
|
||||
|
||||
const serializeConversationState = (state: {
|
||||
messages: Message[];
|
||||
branchGroups: BranchGroup[];
|
||||
sessionId?: string;
|
||||
}) =>
|
||||
JSON.stringify({
|
||||
messages: sanitizeMessages(state.messages),
|
||||
branchGroups: sanitizeBranchGroups(state.branchGroups),
|
||||
sessionId: state.sessionId ?? null,
|
||||
});
|
||||
|
||||
const hasChatContent = (state: {
|
||||
messages: Message[];
|
||||
branchGroups: BranchGroup[];
|
||||
@@ -72,8 +43,8 @@ const hasChatContent = (state: {
|
||||
Boolean(state.sessionId);
|
||||
|
||||
const compareSessionsByAnchorTime = (
|
||||
left: Pick<ChatSessionRecord, "id" | "createdAt" | "updatedAt">,
|
||||
right: Pick<ChatSessionRecord, "id" | "createdAt" | "updatedAt">,
|
||||
left: Pick<ChatSessionSummary, "id" | "createdAt" | "updatedAt">,
|
||||
right: Pick<ChatSessionSummary, "id" | "createdAt" | "updatedAt">,
|
||||
) => {
|
||||
const createdAtDiff = right.createdAt - left.createdAt;
|
||||
if (createdAtDiff !== 0) return createdAtDiff;
|
||||
@@ -84,167 +55,203 @@ const compareSessionsByAnchorTime = (
|
||||
return right.id.localeCompare(left.id);
|
||||
};
|
||||
|
||||
const toLoadedChatState = (
|
||||
session: ChatSessionRecord | undefined,
|
||||
): LoadedChatState => {
|
||||
if (!session) return emptyLoadedChatState();
|
||||
return {
|
||||
storageSessionId: session.id,
|
||||
title: session.title,
|
||||
isTitleManuallyEdited: session.isTitleManuallyEdited ?? false,
|
||||
messages: sanitizeMessages(session.messages),
|
||||
sessionId: session.sessionId,
|
||||
branchGroups: sanitizeBranchGroups(session.branchGroups),
|
||||
};
|
||||
const toMillis = (value: string | number | undefined) =>
|
||||
typeof value === "number" ? value : value ? new Date(value).getTime() : Date.now();
|
||||
|
||||
const normalizeTitle = (value?: string) => value?.trim() || "新对话";
|
||||
|
||||
const getStoredActiveSessionId = () => {
|
||||
if (typeof window === "undefined") return undefined;
|
||||
const stored = window.localStorage.getItem(ACTIVE_SESSION_STORAGE_KEY)?.trim();
|
||||
return stored || undefined;
|
||||
};
|
||||
|
||||
const toSessionSummary = (session: ChatSessionRecord): ChatSessionSummary => ({
|
||||
id: session.id,
|
||||
title: session.title,
|
||||
createdAt: session.createdAt,
|
||||
updatedAt: session.updatedAt,
|
||||
});
|
||||
|
||||
const getDb = () =>
|
||||
openDB<ChatDB>(CHAT_DB_NAME, CHAT_DB_VERSION, {
|
||||
upgrade(db) {
|
||||
if (!db.objectStoreNames.contains(SESSION_STORE)) {
|
||||
const sessionStore = db.createObjectStore(SESSION_STORE, {
|
||||
keyPath: "id",
|
||||
});
|
||||
sessionStore.createIndex("by-updatedAt", "updatedAt");
|
||||
}
|
||||
|
||||
if (!db.objectStoreNames.contains(META_STORE)) {
|
||||
db.createObjectStore(META_STORE, { keyPath: "key" });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const readLegacyChatState = (): LegacyPersistedChatState | null => {
|
||||
if (typeof window === "undefined") return null;
|
||||
|
||||
try {
|
||||
const storedRaw = window.localStorage.getItem(LEGACY_CHAT_STORAGE_KEY);
|
||||
if (!storedRaw) return null;
|
||||
|
||||
const parsed = JSON.parse(storedRaw) as LegacyPersistedChatState;
|
||||
if (!Array.isArray(parsed.messages)) {
|
||||
window.localStorage.removeItem(LEGACY_CHAT_STORAGE_KEY);
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
messages: sanitizeMessages(parsed.messages),
|
||||
sessionId: parsed.sessionId,
|
||||
branchGroups: sanitizeBranchGroups(parsed.branchGroups),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("[GlobalChatbox] Failed to read legacy chat state:", error);
|
||||
window.localStorage.removeItem(LEGACY_CHAT_STORAGE_KEY);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const clearLegacyChatState = () => {
|
||||
const setStoredActiveSessionId = (sessionId?: string) => {
|
||||
if (typeof window === "undefined") return;
|
||||
window.localStorage.removeItem(LEGACY_CHAT_STORAGE_KEY);
|
||||
if (sessionId) {
|
||||
window.localStorage.setItem(ACTIVE_SESSION_STORAGE_KEY, sessionId);
|
||||
return;
|
||||
}
|
||||
window.localStorage.removeItem(ACTIVE_SESSION_STORAGE_KEY);
|
||||
};
|
||||
|
||||
const getMeta = async () => {
|
||||
const db = await getDb();
|
||||
return db.get(META_STORE, META_KEY);
|
||||
};
|
||||
|
||||
const setMeta = async (meta: Omit<ChatStorageMeta, "key">) => {
|
||||
const db = await getDb();
|
||||
await db.put(META_STORE, {
|
||||
key: META_KEY,
|
||||
...meta,
|
||||
const fetchRemoteChatSessions = async (): Promise<ChatSessionSummary[]> => {
|
||||
const response = await apiFetch(`${config.AGENT_URL}/api/v1/agent/chat/sessions`, {
|
||||
method: "GET",
|
||||
projectHeaderMode: "include",
|
||||
userHeaderMode: "include",
|
||||
skipAuthRedirect: true,
|
||||
});
|
||||
};
|
||||
|
||||
const getLatestSession = async () => {
|
||||
const db = await getDb();
|
||||
const sessions = await db.getAll(SESSION_STORE);
|
||||
if (sessions.length === 0) return undefined;
|
||||
return sessions.sort(compareSessionsByAnchorTime)[0];
|
||||
};
|
||||
|
||||
const migrateLegacyLocalStorage = async () => {
|
||||
const meta = await getMeta();
|
||||
if (meta?.migratedFromLocalStorage) return;
|
||||
|
||||
const legacyState = readLegacyChatState();
|
||||
if (!legacyState) {
|
||||
await setMeta({
|
||||
activeSessionId: meta?.activeSessionId,
|
||||
migratedFromLocalStorage: true,
|
||||
});
|
||||
return;
|
||||
if (!response.ok) {
|
||||
throw new Error(await response.text());
|
||||
}
|
||||
|
||||
const hasContent =
|
||||
legacyState.messages.length > 0 ||
|
||||
(legacyState.branchGroups?.length ?? 0) > 0 ||
|
||||
Boolean(legacyState.sessionId);
|
||||
|
||||
if (!hasContent) {
|
||||
clearLegacyChatState();
|
||||
await setMeta({
|
||||
activeSessionId: undefined,
|
||||
migratedFromLocalStorage: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const sessionRecord: ChatSessionRecord = {
|
||||
id: createId(),
|
||||
title: "新对话",
|
||||
isTitleManuallyEdited: false,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
sessionId: legacyState.sessionId,
|
||||
messages: sanitizeMessages(legacyState.messages),
|
||||
branchGroups: sanitizeBranchGroups(legacyState.branchGroups),
|
||||
const payload = (await response.json()) as {
|
||||
sessions?: RemoteSessionPayload[];
|
||||
};
|
||||
return (payload.sessions ?? [])
|
||||
.map((session) => ({
|
||||
id: session.id ?? "",
|
||||
title: normalizeTitle(session.title),
|
||||
createdAt: toMillis(session.created_at),
|
||||
updatedAt: toMillis(session.updated_at),
|
||||
}))
|
||||
.filter((session) => Boolean(session.id))
|
||||
.sort(compareSessionsByAnchorTime);
|
||||
};
|
||||
|
||||
const db = await getDb();
|
||||
await db.put(SESSION_STORE, sessionRecord);
|
||||
clearLegacyChatState();
|
||||
await setMeta({
|
||||
activeSessionId: sessionRecord.id,
|
||||
migratedFromLocalStorage: true,
|
||||
const fetchRemoteChatSession = async (sessionId: string): Promise<LoadedChatState> => {
|
||||
const response = await apiFetch(
|
||||
`${config.AGENT_URL}/api/v1/agent/chat/session/${encodeURIComponent(sessionId)}`,
|
||||
{
|
||||
method: "GET",
|
||||
projectHeaderMode: "include",
|
||||
userHeaderMode: "include",
|
||||
skipAuthRedirect: true,
|
||||
},
|
||||
);
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
return emptyLoadedChatState();
|
||||
}
|
||||
throw new Error(await response.text());
|
||||
}
|
||||
const payload = (await response.json()) as {
|
||||
id: string;
|
||||
title?: string;
|
||||
is_title_manually_edited?: boolean;
|
||||
session_id?: string;
|
||||
messages?: Message[];
|
||||
branch_groups?: BranchGroup[];
|
||||
};
|
||||
return {
|
||||
storageSessionId: payload.id,
|
||||
title: normalizeTitle(payload.title),
|
||||
isTitleManuallyEdited: payload.is_title_manually_edited ?? false,
|
||||
messages: sanitizeMessages(payload.messages),
|
||||
sessionId: payload.session_id,
|
||||
branchGroups: sanitizeBranchGroups(payload.branch_groups),
|
||||
};
|
||||
};
|
||||
|
||||
const createRemoteChatSession = async (payload?: {
|
||||
sessionId?: string;
|
||||
parentSessionId?: string;
|
||||
}) => {
|
||||
const response = await apiFetch(`${config.AGENT_URL}/api/v1/agent/chat/session`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
session_id: payload?.sessionId,
|
||||
parent_session_id: payload?.parentSessionId,
|
||||
}),
|
||||
projectHeaderMode: "include",
|
||||
userHeaderMode: "include",
|
||||
skipAuthRedirect: true,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(await response.text());
|
||||
}
|
||||
const body = (await response.json()) as {
|
||||
session_id?: string;
|
||||
};
|
||||
const sessionId = body.session_id?.trim();
|
||||
if (!sessionId) {
|
||||
throw new Error("backend did not return session_id");
|
||||
}
|
||||
return sessionId;
|
||||
};
|
||||
|
||||
const saveRemoteChatState = async (
|
||||
sessionId: string,
|
||||
state: LoadedChatState,
|
||||
): Promise<string> => {
|
||||
const response = await apiFetch(
|
||||
`${config.AGENT_URL}/api/v1/agent/chat/session/${encodeURIComponent(sessionId)}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title: normalizeTitle(state.title),
|
||||
is_title_manually_edited: state.isTitleManuallyEdited ?? false,
|
||||
messages: sanitizeMessages(state.messages),
|
||||
branch_groups: sanitizeBranchGroups(state.branchGroups),
|
||||
}),
|
||||
projectHeaderMode: "include",
|
||||
userHeaderMode: "include",
|
||||
skipAuthRedirect: true,
|
||||
},
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(await response.text());
|
||||
}
|
||||
const payload = (await response.json()) as { id?: string; session_id?: string };
|
||||
return payload.id ?? payload.session_id ?? sessionId;
|
||||
};
|
||||
|
||||
const updateRemoteChatSessionTitle = async (
|
||||
sessionId: string,
|
||||
title: string,
|
||||
isTitleManuallyEdited?: boolean,
|
||||
) => {
|
||||
const response = await apiFetch(
|
||||
`${config.AGENT_URL}/api/v1/agent/chat/session/${encodeURIComponent(sessionId)}/title`,
|
||||
{
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title,
|
||||
is_title_manually_edited: isTitleManuallyEdited,
|
||||
}),
|
||||
projectHeaderMode: "include",
|
||||
userHeaderMode: "include",
|
||||
skipAuthRedirect: true,
|
||||
},
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(await response.text());
|
||||
}
|
||||
};
|
||||
|
||||
const deleteRemoteChatSession = async (sessionId: string) => {
|
||||
const response = await apiFetch(
|
||||
`${config.AGENT_URL}/api/v1/agent/chat/session/${encodeURIComponent(sessionId)}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
projectHeaderMode: "include",
|
||||
userHeaderMode: "include",
|
||||
skipAuthRedirect: true,
|
||||
},
|
||||
);
|
||||
if (!response.ok && response.status !== 404) {
|
||||
throw new Error(await response.text());
|
||||
}
|
||||
};
|
||||
|
||||
export const loadActiveChatState = async (): Promise<LoadedChatState> => {
|
||||
if (typeof window === "undefined") return emptyLoadedChatState();
|
||||
|
||||
await migrateLegacyLocalStorage();
|
||||
|
||||
const meta = await getMeta();
|
||||
const db = await getDb();
|
||||
|
||||
if (meta?.activeSessionId) {
|
||||
const activeSession = await db.get(SESSION_STORE, meta.activeSessionId);
|
||||
if (activeSession) {
|
||||
return toLoadedChatState(activeSession);
|
||||
const activeSessionId = getStoredActiveSessionId();
|
||||
if (activeSessionId) {
|
||||
const activeSession = await fetchRemoteChatSession(activeSessionId);
|
||||
if (activeSession.storageSessionId) {
|
||||
return activeSession;
|
||||
}
|
||||
setStoredActiveSessionId(undefined);
|
||||
}
|
||||
|
||||
const latestSession = await getLatestSession();
|
||||
const sessions = await fetchRemoteChatSessions();
|
||||
const latestSession = sessions[0];
|
||||
if (!latestSession) {
|
||||
return emptyLoadedChatState();
|
||||
}
|
||||
|
||||
await setMeta({
|
||||
activeSessionId: latestSession.id,
|
||||
migratedFromLocalStorage: meta?.migratedFromLocalStorage ?? true,
|
||||
});
|
||||
|
||||
return toLoadedChatState(latestSession);
|
||||
setStoredActiveSessionId(latestSession.id);
|
||||
return await fetchRemoteChatSession(latestSession.id);
|
||||
};
|
||||
|
||||
export const saveActiveChatState = async (
|
||||
@@ -252,68 +259,28 @@ export const saveActiveChatState = async (
|
||||
): Promise<string | undefined> => {
|
||||
if (typeof window === "undefined") return state.storageSessionId;
|
||||
|
||||
const hasContent = hasChatContent(state);
|
||||
|
||||
const db = await getDb();
|
||||
const existingSession = state.storageSessionId
|
||||
? await db.get(SESSION_STORE, state.storageSessionId)
|
||||
: undefined;
|
||||
const meta = await getMeta();
|
||||
|
||||
if (!hasContent) {
|
||||
if (state.storageSessionId) {
|
||||
await db.delete(SESSION_STORE, state.storageSessionId);
|
||||
}
|
||||
await setMeta({
|
||||
activeSessionId: undefined,
|
||||
migratedFromLocalStorage: meta?.migratedFromLocalStorage ?? true,
|
||||
});
|
||||
if (!hasChatContent(state)) {
|
||||
setStoredActiveSessionId(undefined);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const storageSessionId = state.storageSessionId ?? createId();
|
||||
const preferredTitle = state.title?.trim();
|
||||
const finalTitle = preferredTitle || existingSession?.title || "新对话";
|
||||
const hasContentChanged =
|
||||
!existingSession ||
|
||||
(existingSession && serializeConversationState(existingSession)) !==
|
||||
serializeConversationState(state);
|
||||
const shouldAnchorCreatedAtToFirstMessage =
|
||||
existingSession && !hasChatContent(existingSession) && hasContent;
|
||||
const nextRecord: ChatSessionRecord = {
|
||||
id: storageSessionId,
|
||||
title: finalTitle,
|
||||
isTitleManuallyEdited:
|
||||
state.isTitleManuallyEdited ??
|
||||
existingSession?.isTitleManuallyEdited ??
|
||||
false,
|
||||
createdAt: shouldAnchorCreatedAtToFirstMessage
|
||||
? now
|
||||
: existingSession?.createdAt ?? now,
|
||||
updatedAt: hasContentChanged ? now : existingSession?.updatedAt ?? now,
|
||||
sessionId: state.sessionId,
|
||||
messages: sanitizeMessages(state.messages),
|
||||
branchGroups: sanitizeBranchGroups(state.branchGroups),
|
||||
};
|
||||
let remoteSessionId = state.sessionId ?? state.storageSessionId;
|
||||
if (!remoteSessionId) {
|
||||
remoteSessionId = await createRemoteChatSession();
|
||||
}
|
||||
|
||||
await db.put(SESSION_STORE, nextRecord);
|
||||
await setMeta({
|
||||
activeSessionId: storageSessionId,
|
||||
migratedFromLocalStorage: meta?.migratedFromLocalStorage ?? true,
|
||||
const savedSessionId = await saveRemoteChatState(remoteSessionId, {
|
||||
...state,
|
||||
storageSessionId: remoteSessionId,
|
||||
sessionId: remoteSessionId,
|
||||
});
|
||||
|
||||
return storageSessionId;
|
||||
setStoredActiveSessionId(savedSessionId);
|
||||
return savedSessionId;
|
||||
};
|
||||
|
||||
export const listChatSessions = async (): Promise<ChatSessionSummary[]> => {
|
||||
if (typeof window === "undefined") return [];
|
||||
|
||||
await migrateLegacyLocalStorage();
|
||||
|
||||
const db = await getDb();
|
||||
const sessions = await db.getAll(SESSION_STORE);
|
||||
return sessions.sort(compareSessionsByAnchorTime).map(toSessionSummary);
|
||||
return await fetchRemoteChatSessions();
|
||||
};
|
||||
|
||||
export const updateChatSessionTitle = async (
|
||||
@@ -327,45 +294,21 @@ export const updateChatSessionTitle = async (
|
||||
|
||||
const normalizedTitle = title.trim();
|
||||
if (!normalizedTitle) return;
|
||||
|
||||
const db = await getDb();
|
||||
const session = await db.get(SESSION_STORE, storageSessionId);
|
||||
if (!session) return;
|
||||
|
||||
await db.put(SESSION_STORE, {
|
||||
...session,
|
||||
title: normalizedTitle,
|
||||
isTitleManuallyEdited:
|
||||
options?.isTitleManuallyEdited ?? session.isTitleManuallyEdited ?? false,
|
||||
});
|
||||
await updateRemoteChatSessionTitle(
|
||||
storageSessionId,
|
||||
normalizedTitle,
|
||||
options?.isTitleManuallyEdited,
|
||||
);
|
||||
};
|
||||
|
||||
export const createEmptyChatSession = async (): Promise<LoadedChatState> => {
|
||||
if (typeof window === "undefined") return emptyLoadedChatState();
|
||||
|
||||
await migrateLegacyLocalStorage();
|
||||
|
||||
const now = Date.now();
|
||||
const session: ChatSessionRecord = {
|
||||
id: createId(),
|
||||
setStoredActiveSessionId(undefined);
|
||||
return {
|
||||
...emptyLoadedChatState(),
|
||||
title: "新对话",
|
||||
isTitleManuallyEdited: false,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
sessionId: undefined,
|
||||
messages: [],
|
||||
branchGroups: [],
|
||||
};
|
||||
|
||||
const db = await getDb();
|
||||
await db.put(SESSION_STORE, session);
|
||||
const meta = await getMeta();
|
||||
await setMeta({
|
||||
activeSessionId: session.id,
|
||||
migratedFromLocalStorage: meta?.migratedFromLocalStorage ?? true,
|
||||
});
|
||||
|
||||
return toLoadedChatState(session);
|
||||
};
|
||||
|
||||
export const loadChatSessionById = async (
|
||||
@@ -373,21 +316,11 @@ export const loadChatSessionById = async (
|
||||
): Promise<LoadedChatState> => {
|
||||
if (typeof window === "undefined") return emptyLoadedChatState();
|
||||
|
||||
await migrateLegacyLocalStorage();
|
||||
|
||||
const db = await getDb();
|
||||
const session = await db.get(SESSION_STORE, sessionId);
|
||||
if (!session) {
|
||||
return emptyLoadedChatState();
|
||||
const loaded = await fetchRemoteChatSession(sessionId);
|
||||
if (loaded.storageSessionId) {
|
||||
setStoredActiveSessionId(sessionId);
|
||||
}
|
||||
|
||||
const meta = await getMeta();
|
||||
await setMeta({
|
||||
activeSessionId: session.id,
|
||||
migratedFromLocalStorage: meta?.migratedFromLocalStorage ?? true,
|
||||
});
|
||||
|
||||
return toLoadedChatState(session);
|
||||
return loaded;
|
||||
};
|
||||
|
||||
export const deleteChatSession = async (
|
||||
@@ -395,19 +328,8 @@ export const deleteChatSession = async (
|
||||
): Promise<string | undefined> => {
|
||||
if (typeof window === "undefined") return undefined;
|
||||
|
||||
const db = await getDb();
|
||||
await db.delete(SESSION_STORE, sessionId);
|
||||
|
||||
const remainingSessions = await db.getAll(SESSION_STORE);
|
||||
const nextActiveSession = remainingSessions.sort(
|
||||
compareSessionsByAnchorTime,
|
||||
)[0];
|
||||
const meta = await getMeta();
|
||||
|
||||
await setMeta({
|
||||
activeSessionId: nextActiveSession?.id,
|
||||
migratedFromLocalStorage: meta?.migratedFromLocalStorage ?? true,
|
||||
});
|
||||
|
||||
await deleteRemoteChatSession(sessionId);
|
||||
const nextActiveSession = (await listChatSessions())[0];
|
||||
setStoredActiveSessionId(nextActiveSession?.id);
|
||||
return nextActiveSession?.id;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user