Fix Jupyter workspace session handoff

This commit is contained in:
wuyang6
2026-05-13 13:52:37 +08:00
parent 28d73afaa0
commit e5095268d8
3 changed files with 62 additions and 2 deletions
+14 -2
View File
@@ -20,6 +20,7 @@ import {
SidebarTrigger,
} from "@/components/ui/sidebar";
import {
consumePendingWorkspaceSessionId,
readActiveSessionId,
writeActiveSessionId,
} from "@/lib/claw-active-session";
@@ -37,10 +38,21 @@ export const Assistant = () => {
const messages = options.messages as UIMessage[];
const selectedSessionId = readActiveSessionId();
const lastSessionId = getLastSessionId(messages);
const pendingWorkspaceSessionId =
messages.length <= 1 ? consumePendingWorkspaceSessionId() : null;
const usablePendingWorkspaceSessionId =
pendingWorkspaceSessionId &&
(!selectedSessionId ||
selectedSessionId === pendingWorkspaceSessionId)
? pendingWorkspaceSessionId
: null;
const selectedResumeSessionId =
messages.length > 1 ? selectedSessionId : null;
const outgoingSessionId =
lastSessionId ?? selectedResumeSessionId ?? options.id;
lastSessionId ??
selectedResumeSessionId ??
usablePendingWorkspaceSessionId ??
options.id;
const lastUserMessage = [...messages]
.reverse()
.find((message) => message.role === "user");
@@ -49,7 +61,7 @@ export const Assistant = () => {
return {
body: {
...body,
id: options.id,
id: outgoingSessionId,
messages: lastUserMessage ? [lastUserMessage] : [],
resumeSessionId:
lastSessionId ?? selectedResumeSessionId ?? undefined,
@@ -83,6 +83,7 @@ import {
clearActiveSessionId,
readActiveSessionId,
writeActiveSessionId,
writePendingWorkspaceSessionId,
} from "@/lib/claw-active-session";
import { useClawSessionReplay } from "@/lib/claw-session-replay";
import { cn } from "@/lib/utils";
@@ -437,6 +438,7 @@ function WorkspaceSwitchDialog({
setSubmitting(true);
const progressTimer = startWorkspaceProgress(setProgress);
try {
const needsFirstMessageSession = !normalizeSessionId(sessionId);
const response = await fetch("/api/claw/jupyter", {
method: "POST",
headers: { "content-type": "application/json" },
@@ -455,6 +457,9 @@ function WorkspaceSwitchDialog({
return;
}
writeActiveSessionId(sessionIdForRequest);
if (needsFirstMessageSession) {
writePendingWorkspaceSessionId(sessionIdForRequest);
}
setStatus(payload as JupyterWorkspaceStatus);
setProgress({ percent: 100, label: "切换完成" });
setMessage("工作区切换成功,后续工具会在远端 Jupyter 工作区执行。");
+43
View File
@@ -1,6 +1,7 @@
"use client";
const ACTIVE_SESSION_ID_KEY = "claw.activeSessionId";
const PENDING_WORKSPACE_SESSION_ID_KEY = "claw.pendingWorkspaceSessionId";
export const ACTIVE_SESSION_CHANGED_EVENT = "claw-active-session-changed";
export function readActiveSessionId() {
@@ -20,6 +21,10 @@ export function writeActiveSessionId(sessionId: string | null | undefined) {
}
window.sessionStorage.setItem(ACTIVE_SESSION_ID_KEY, normalized);
window.localStorage.setItem(ACTIVE_SESSION_ID_KEY, normalized);
const pendingSessionId = readPendingWorkspaceSessionId();
if (pendingSessionId && pendingSessionId !== normalized) {
clearPendingWorkspaceSessionId();
}
window.dispatchEvent(
new CustomEvent(ACTIVE_SESSION_CHANGED_EVENT, {
detail: { sessionId: normalized },
@@ -31,6 +36,7 @@ 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 },
@@ -38,6 +44,43 @@ export function clearActiveSessionId() {
);
}
export function writePendingWorkspaceSessionId(
sessionId: string | null | undefined,
) {
if (typeof window === "undefined") return;
const normalized = normalizeSessionId(sessionId);
if (!normalized) {
clearPendingWorkspaceSessionId();
return;
}
window.sessionStorage.setItem(PENDING_WORKSPACE_SESSION_ID_KEY, normalized);
window.localStorage.setItem(PENDING_WORKSPACE_SESSION_ID_KEY, normalized);
}
export function consumePendingWorkspaceSessionId() {
const sessionId = readPendingWorkspaceSessionId();
clearPendingWorkspaceSessionId();
return sessionId;
}
function readPendingWorkspaceSessionId() {
if (typeof window === "undefined") return null;
return (
normalizeSessionId(
window.sessionStorage.getItem(PENDING_WORKSPACE_SESSION_ID_KEY),
) ??
normalizeSessionId(
window.localStorage.getItem(PENDING_WORKSPACE_SESSION_ID_KEY),
)
);
}
function clearPendingWorkspaceSessionId() {
if (typeof window === "undefined") return;
window.sessionStorage.removeItem(PENDING_WORKSPACE_SESSION_ID_KEY);
window.localStorage.removeItem(PENDING_WORKSPACE_SESSION_ID_KEY);
}
function normalizeSessionId(value: unknown) {
if (typeof value !== "string") return null;
const trimmed = value.trim();