f068311cac
- backend/api/server.py:训练 step-detail / pipeline 卡片排序逻辑 - frontend:thread-list / thread / training-pipeline-panel / step-detail-sheet 配套调整,新增 metrics-chart-panel - src/agent_*:tool spec / runtime / prompting 配套 - .gitignore 加 .logs/ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
106 lines
3.0 KiB
TypeScript
106 lines
3.0 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 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;
|
|
}
|