Fix active session replay state

This commit is contained in:
wuyang6
2026-05-11 21:35:23 +08:00
parent 413a37b32c
commit 535e4b2c83
7 changed files with 88 additions and 46 deletions
@@ -37,6 +37,10 @@ import {
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import {
readActiveSessionId,
writeActiveSessionId,
} from "@/lib/claw-active-session";
import { cn } from "@/lib/utils";
type ActivityContextValue = {
@@ -71,12 +75,7 @@ export function ActivityProvider({ children }: { children: ReactNode }) {
}, []);
const openFiles = useCallback((nextSessionId?: string | null) => {
setMode("files");
setSessionId(
nextSessionId ??
(typeof window !== "undefined"
? window.localStorage.getItem("claw.activeSessionId")
: null),
);
setSessionId(nextSessionId ?? readActiveSessionId());
setFilesRefreshToken((value) => value + 1);
setOpen(true);
}, []);
@@ -257,7 +256,7 @@ function SessionFilesPanel({
let cancelled = false;
async function loadFiles() {
const activeSessionId = normalizeSessionId(
sessionId ?? window.localStorage.getItem("claw.activeSessionId"),
sessionId ?? readActiveSessionId(),
);
setStatus("正在读取聊天中的文件...");
try {
@@ -285,10 +284,7 @@ function SessionFilesPanel({
return;
}
if (nextPayload.session_id) {
window.localStorage.setItem(
"claw.activeSessionId",
nextPayload.session_id,
);
writeActiveSessionId(nextPayload.session_id);
}
setPayload(nextPayload);
setStatus("");
@@ -19,6 +19,11 @@ import {
useState,
} from "react";
import { Button } from "@/components/ui/button";
import {
clearActiveSessionId,
readActiveSessionId,
writeActiveSessionId,
} from "@/lib/claw-active-session";
import { useClawSessionReplay } from "@/lib/claw-session-replay";
type ClawSession = {
@@ -106,7 +111,7 @@ const ThreadListNew: FC = () => {
return (
<div
onClickCapture={() => {
window.localStorage.removeItem("claw.activeSessionId");
clearActiveSessionId();
window.dispatchEvent(new Event("claw-active-session-cleared"));
}}
>
@@ -141,7 +146,7 @@ const ClawSessionList: FC = () => {
const renameInputRef = useRef<HTMLInputElement | null>(null);
useEffect(() => {
setActiveSessionId(window.localStorage.getItem("claw.activeSessionId"));
setActiveSessionId(readActiveSessionId());
const refreshSessions = () => {
fetch("/api/claw/sessions")
.then((res) => (res.ok ? res.json() : []))
@@ -247,10 +252,7 @@ const ClawSessionList: FC = () => {
className="aui-thread-list-item-trigger flex h-full min-w-0 flex-1 items-center truncate px-3 text-start text-sm"
onClick={async () => {
setOpenMenuSessionId(null);
window.localStorage.setItem(
"claw.activeSessionId",
session.session_id,
);
writeActiveSessionId(session.session_id);
setActiveSessionId(session.session_id);
setLoadingSessionId(session.session_id);
try {
@@ -333,9 +335,7 @@ const ClawSessionList: FC = () => {
);
setOpenMenuSessionId(null);
if (activeSessionId === session.session_id) {
window.localStorage.removeItem(
"claw.activeSessionId",
);
clearActiveSessionId();
setActiveSessionId(null);
window.dispatchEvent(
new Event("claw-active-session-cleared"),
@@ -62,6 +62,11 @@ import {
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import {
clearActiveSessionId,
readActiveSessionId,
writeActiveSessionId,
} from "@/lib/claw-active-session";
import { useClawSessionReplay } from "@/lib/claw-session-replay";
import { cn } from "@/lib/utils";
@@ -193,6 +198,15 @@ function useRefreshReplayedRun() {
const runStatus = await fetchLatestRunStatus(activeSessionId);
if (cancelled) return;
if (runStatus?.status === "queued" || runStatus?.status === "running") {
const response = await fetch(`/api/claw/sessions/${activeSessionId}`, {
cache: "no-store",
});
if (!response.ok || cancelled) return;
const payload = await response.json();
replaySession(
activeSessionId,
toReplayRepository(payload, activeSessionId, runStatus),
);
return;
}
const response = await fetch(`/api/claw/sessions/${activeSessionId}`, {
@@ -243,7 +257,7 @@ function useReplayedRunState() {
});
const localSessionId =
typeof window !== "undefined"
? normalizeSessionId(window.localStorage.getItem("claw.activeSessionId"))
? normalizeSessionId(readActiveSessionId())
: null;
const sessionId = replaySessionId ?? latestSessionId ?? localSessionId;
return useMemo(
@@ -722,7 +736,7 @@ function useComposerContextStatus() {
useEffect(() => {
const cleanLatestSessionId = normalizeSessionId(latestSessionId);
if (cleanLatestSessionId) {
window.localStorage.setItem("claw.activeSessionId", cleanLatestSessionId);
writeActiveSessionId(cleanLatestSessionId);
window.setTimeout(() => {
window.dispatchEvent(new Event("claw-sessions-changed"));
}, 0);
@@ -752,13 +766,10 @@ function useComposerContextStatus() {
: {};
let sessionId = normalizeSessionId(
normalizeSessionId(latestSessionId) ||
normalizeSessionId(
window.localStorage.getItem("claw.activeSessionId"),
) ||
normalizeSessionId(readActiveSessionId()) ||
normalizeSessionId(statePayload.active_session_id),
);
if (sessionId)
window.localStorage.setItem("claw.activeSessionId", sessionId);
if (sessionId) writeActiveSessionId(sessionId);
let sessionPayload: ClawStoredSession | null = null;
let contextBudget: ContextBudget | undefined;
if (sessionId) {
@@ -772,7 +783,7 @@ function useComposerContextStatus() {
sessionPayload =
(await sessionResponse.json()) as ClawStoredSession;
} else if (sessionResponse.status === 404) {
window.localStorage.removeItem("claw.activeSessionId");
clearActiveSessionId();
sessionId = null;
}
}
@@ -43,6 +43,11 @@ import {
SidebarTrigger,
useSidebar,
} from "@/components/ui/sidebar";
import {
clearActiveSessionId,
readActiveSessionId,
writeActiveSessionId,
} from "@/lib/claw-active-session";
import { useClawSessionReplay } from "@/lib/claw-session-replay";
type ThreadListSidebarProps = React.ComponentProps<typeof Sidebar> & {
@@ -157,7 +162,7 @@ function CollapsedSidebarRail({
<div className="flex flex-col items-center gap-3">
<div
onClickCapture={() => {
window.localStorage.removeItem("claw.activeSessionId");
clearActiveSessionId();
window.dispatchEvent(new Event("claw-active-session-cleared"));
}}
>
@@ -360,7 +365,7 @@ function useSidebarSessions(open: boolean) {
) {
const cleanSessionId = normalizeSessionId(sessionId);
if (!cleanSessionId) return;
window.localStorage.setItem("claw.activeSessionId", cleanSessionId);
writeActiveSessionId(cleanSessionId);
setLoadingSessionId(sessionId);
try {
const response = await fetch(`/api/claw/sessions/${cleanSessionId}`, {
@@ -438,14 +443,13 @@ function AccountMenu({
setState(nextState);
setSessions(nextSessions);
const activeSessionId = normalizeSessionId(
window.localStorage.getItem("claw.activeSessionId") ??
nextState?.active_session_id,
readActiveSessionId() ?? nextState?.active_session_id,
);
if (!activeSessionId) {
setActiveSession(null);
return;
}
window.localStorage.setItem("claw.activeSessionId", activeSessionId);
writeActiveSessionId(activeSessionId);
const response = await fetch(`/api/claw/sessions/${activeSessionId}`, {
cache: "no-store",
});
@@ -460,7 +464,7 @@ function AccountMenu({
async function logout() {
await fetch("/api/claw/auth/logout", { method: "POST" });
window.localStorage.removeItem("claw.activeSessionId");
clearActiveSessionId();
onLogout();
}