Files
zk-data-agent/frontend/app/lib/claw-active-session.ts
T
2026-06-12 16:51:17 +08:00

113 lines
3.3 KiB
TypeScript

"use client";
const ACTIVE_SESSION_ID_KEY = "claw.activeSessionId";
export const ACTIVE_SESSION_CHANGED_EVENT = "claw-active-session-changed";
export const PENDING_WORKSPACE_SESSION_CHANGED_EVENT =
"claw-pending-workspace-session-changed";
declare global {
interface Window {
__clawPendingWorkspaceSessionId?: string | null;
}
}
export function readActiveSessionId() {
if (typeof window === "undefined") return null;
return normalizeSessionId(
window.sessionStorage.getItem(ACTIVE_SESSION_ID_KEY),
);
}
export function writeActiveSessionId(sessionId: string | null | undefined) {
if (typeof window === "undefined") return;
const normalized = normalizeSessionId(sessionId);
if (!normalized) {
clearActiveSessionId();
return;
}
window.sessionStorage.setItem(ACTIVE_SESSION_ID_KEY, normalized);
window.localStorage.removeItem(ACTIVE_SESSION_ID_KEY);
const pendingSessionId = readPendingWorkspaceSessionId();
if (pendingSessionId && pendingSessionId !== normalized) {
clearPendingWorkspaceSessionId();
}
window.dispatchEvent(
new CustomEvent(ACTIVE_SESSION_CHANGED_EVENT, {
detail: { sessionId: normalized },
}),
);
}
export function clearActiveSessionId() {
if (typeof window === "undefined") return;
window.sessionStorage.removeItem(ACTIVE_SESSION_ID_KEY);
window.localStorage.removeItem(ACTIVE_SESSION_ID_KEY);
clearPendingWorkspaceSessionId();
window.dispatchEvent(
new CustomEvent(ACTIVE_SESSION_CHANGED_EVENT, {
detail: { sessionId: null },
}),
);
}
export function createLocalSessionId() {
if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
return `__LOCALID_${crypto.randomUUID().replace(/-/g, "").slice(0, 8)}`;
}
return `__LOCALID_${Math.random().toString(36).slice(2, 10)}`;
}
export function writePendingWorkspaceSessionId(
sessionId: string | null | undefined,
) {
if (typeof window === "undefined") return;
const normalized = normalizeSessionId(sessionId);
if (!normalized) {
clearPendingWorkspaceSessionId();
return;
}
window.__clawPendingWorkspaceSessionId = normalized;
window.dispatchEvent(
new CustomEvent(PENDING_WORKSPACE_SESSION_CHANGED_EVENT, {
detail: { sessionId: normalized },
}),
);
}
export function readPendingWorkspaceSessionId() {
if (typeof window === "undefined") return null;
return normalizeSessionId(window.__clawPendingWorkspaceSessionId);
}
export function clearPendingWorkspaceSessionId() {
if (typeof window === "undefined") return;
window.__clawPendingWorkspaceSessionId = null;
window.dispatchEvent(
new CustomEvent(PENDING_WORKSPACE_SESSION_CHANGED_EVENT, {
detail: { sessionId: null },
}),
);
}
function normalizeSessionId(value: unknown) {
if (typeof value !== "string") return null;
const trimmed = value.trim();
return trimmed || null;
}
// 记录"前端刚生成的 LOCALID"。AssistantWorkspace 的 draft cache effect 用它
// 区分:从 newTask 切到一个**新生成**的 LOCALID(草稿应继承)vs 切到一个
// **侧栏点击**的老 LOCALID(草稿不应继承)。
const freshLocalIds = new Set<string>();
export function markFreshLocalId(sessionId: string) {
freshLocalIds.add(sessionId);
}
export function consumeFreshLocalId(sessionId: string | null): boolean {
if (!sessionId) return false;
if (!freshLocalIds.has(sessionId)) return false;
freshLocalIds.delete(sessionId);
return true;
}