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