Normalize active session ids in frontend
This commit is contained in:
@@ -10,7 +10,7 @@ export async function GET(req: Request) {
|
|||||||
const incoming = new URL(req.url);
|
const incoming = new URL(req.url);
|
||||||
const url = new URL(`${CLAW_API_URL}/api/context-budget`);
|
const url = new URL(`${CLAW_API_URL}/api/context-budget`);
|
||||||
url.searchParams.set("account_id", account.id);
|
url.searchParams.set("account_id", account.id);
|
||||||
const sessionId = incoming.searchParams.get("session_id");
|
const sessionId = incoming.searchParams.get("session_id")?.trim();
|
||||||
if (sessionId) url.searchParams.set("session_id", sessionId);
|
if (sessionId) url.searchParams.set("session_id", sessionId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ export async function GET(
|
|||||||
if (!account)
|
if (!account)
|
||||||
return Response.json({ error: "请先登录账号" }, { status: 401 });
|
return Response.json({ error: "请先登录账号" }, { status: 401 });
|
||||||
|
|
||||||
const { sessionId } = await params;
|
const { sessionId: rawSessionId } = await params;
|
||||||
|
const sessionId = rawSessionId.trim();
|
||||||
const url = new URL(`${CLAW_API_URL}/api/sessions/${sessionId}`);
|
const url = new URL(`${CLAW_API_URL}/api/sessions/${sessionId}`);
|
||||||
url.searchParams.set("account_id", account.id);
|
url.searchParams.set("account_id", account.id);
|
||||||
const response = await fetch(url, { cache: "no-store" });
|
const response = await fetch(url, { cache: "no-store" });
|
||||||
@@ -32,7 +33,8 @@ export async function DELETE(
|
|||||||
if (!account)
|
if (!account)
|
||||||
return Response.json({ error: "请先登录账号" }, { status: 401 });
|
return Response.json({ error: "请先登录账号" }, { status: 401 });
|
||||||
|
|
||||||
const { sessionId } = await params;
|
const { sessionId: rawSessionId } = await params;
|
||||||
|
const sessionId = rawSessionId.trim();
|
||||||
const url = new URL(`${CLAW_API_URL}/api/sessions/${sessionId}`);
|
const url = new URL(`${CLAW_API_URL}/api/sessions/${sessionId}`);
|
||||||
url.searchParams.set("account_id", account.id);
|
url.searchParams.set("account_id", account.id);
|
||||||
const response = await fetch(url, { method: "DELETE", cache: "no-store" });
|
const response = await fetch(url, { method: "DELETE", cache: "no-store" });
|
||||||
@@ -54,7 +56,8 @@ export async function PATCH(
|
|||||||
if (!account)
|
if (!account)
|
||||||
return Response.json({ error: "请先登录账号" }, { status: 401 });
|
return Response.json({ error: "请先登录账号" }, { status: 401 });
|
||||||
|
|
||||||
const { sessionId } = await params;
|
const { sessionId: rawSessionId } = await params;
|
||||||
|
const sessionId = rawSessionId.trim();
|
||||||
const url = new URL(`${CLAW_API_URL}/api/sessions/${sessionId}`);
|
const url = new URL(`${CLAW_API_URL}/api/sessions/${sessionId}`);
|
||||||
url.searchParams.set("account_id", account.id);
|
url.searchParams.set("account_id", account.id);
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
|
|||||||
@@ -209,13 +209,15 @@ function SessionFilesPanel({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
async function loadFiles() {
|
async function loadFiles() {
|
||||||
const activeSessionId =
|
const activeSessionId = normalizeSessionId(
|
||||||
sessionId ?? window.localStorage.getItem("claw.activeSessionId");
|
sessionId ?? window.localStorage.getItem("claw.activeSessionId"),
|
||||||
|
);
|
||||||
if (!activeSessionId) {
|
if (!activeSessionId) {
|
||||||
setPayload({ input: [], output: [] });
|
setPayload({ input: [], output: [] });
|
||||||
setStatus("当前还没有可用会话。");
|
setStatus("当前还没有可用会话。");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
window.localStorage.setItem("claw.activeSessionId", activeSessionId);
|
||||||
setStatus("正在读取聊天中的文件...");
|
setStatus("正在读取聊天中的文件...");
|
||||||
try {
|
try {
|
||||||
const url = new URL("/api/claw/files", window.location.origin);
|
const url = new URL("/api/claw/files", window.location.origin);
|
||||||
@@ -280,6 +282,12 @@ function SessionFilesPanel({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSessionId(value: unknown) {
|
||||||
|
if (typeof value !== "string") return null;
|
||||||
|
const trimmed = value.trim();
|
||||||
|
return trimmed || null;
|
||||||
|
}
|
||||||
|
|
||||||
function FileSection({
|
function FileSection({
|
||||||
title,
|
title,
|
||||||
files,
|
files,
|
||||||
|
|||||||
@@ -519,8 +519,9 @@ function useComposerContextStatus() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof latestSessionId === "string" && latestSessionId) {
|
const cleanLatestSessionId = normalizeSessionId(latestSessionId);
|
||||||
window.localStorage.setItem("claw.activeSessionId", latestSessionId);
|
if (cleanLatestSessionId) {
|
||||||
|
window.localStorage.setItem("claw.activeSessionId", cleanLatestSessionId);
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
window.dispatchEvent(new Event("claw-sessions-changed"));
|
window.dispatchEvent(new Event("claw-sessions-changed"));
|
||||||
}, 0);
|
}, 0);
|
||||||
@@ -548,11 +549,15 @@ function useComposerContextStatus() {
|
|||||||
const statePayload = stateResponse.ok
|
const statePayload = stateResponse.ok
|
||||||
? ((await stateResponse.json()) as ClawState)
|
? ((await stateResponse.json()) as ClawState)
|
||||||
: {};
|
: {};
|
||||||
const sessionId =
|
const sessionId = normalizeSessionId(
|
||||||
(typeof latestSessionId === "string" && latestSessionId) ||
|
normalizeSessionId(latestSessionId) ||
|
||||||
window.localStorage.getItem("claw.activeSessionId") ||
|
normalizeSessionId(
|
||||||
statePayload.active_session_id ||
|
window.localStorage.getItem("claw.activeSessionId"),
|
||||||
null;
|
) ||
|
||||||
|
normalizeSessionId(statePayload.active_session_id),
|
||||||
|
);
|
||||||
|
if (sessionId)
|
||||||
|
window.localStorage.setItem("claw.activeSessionId", sessionId);
|
||||||
let sessionPayload: ClawStoredSession | null = null;
|
let sessionPayload: ClawStoredSession | null = null;
|
||||||
let contextBudget: ContextBudget | undefined;
|
let contextBudget: ContextBudget | undefined;
|
||||||
if (sessionId) {
|
if (sessionId) {
|
||||||
@@ -680,6 +685,12 @@ function readMetadataValue(metadata: unknown, key: string): unknown {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSessionId(value: unknown) {
|
||||||
|
if (typeof value !== "string") return null;
|
||||||
|
const trimmed = value.trim();
|
||||||
|
return trimmed || null;
|
||||||
|
}
|
||||||
|
|
||||||
function formatCompactTokenCount(value: number) {
|
function formatCompactTokenCount(value: number) {
|
||||||
if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}M`;
|
if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}M`;
|
||||||
if (value >= 1_000) return `${(value / 1_000).toFixed(1)}K`;
|
if (value >= 1_000) return `${(value / 1_000).toFixed(1)}K`;
|
||||||
|
|||||||
@@ -357,15 +357,20 @@ function useSidebarSessions(open: boolean) {
|
|||||||
repository: ExportedMessageRepository,
|
repository: ExportedMessageRepository,
|
||||||
) => void,
|
) => void,
|
||||||
) {
|
) {
|
||||||
window.localStorage.setItem("claw.activeSessionId", sessionId);
|
const cleanSessionId = normalizeSessionId(sessionId);
|
||||||
|
if (!cleanSessionId) return;
|
||||||
|
window.localStorage.setItem("claw.activeSessionId", cleanSessionId);
|
||||||
setLoadingSessionId(sessionId);
|
setLoadingSessionId(sessionId);
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/claw/sessions/${sessionId}`, {
|
const response = await fetch(`/api/claw/sessions/${cleanSessionId}`, {
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
});
|
});
|
||||||
if (!response.ok) return;
|
if (!response.ok) return;
|
||||||
const payload = (await response.json()) as ReplaySessionPayload;
|
const payload = (await response.json()) as ReplaySessionPayload;
|
||||||
replaySession(sessionId, toReplayRepository(payload, sessionId));
|
replaySession(
|
||||||
|
cleanSessionId,
|
||||||
|
toReplayRepository(payload, cleanSessionId),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingSessionId(null);
|
setLoadingSessionId(null);
|
||||||
}
|
}
|
||||||
@@ -430,13 +435,15 @@ function AccountMenu({
|
|||||||
: [];
|
: [];
|
||||||
setState(nextState);
|
setState(nextState);
|
||||||
setSessions(nextSessions);
|
setSessions(nextSessions);
|
||||||
const activeSessionId =
|
const activeSessionId = normalizeSessionId(
|
||||||
window.localStorage.getItem("claw.activeSessionId") ??
|
window.localStorage.getItem("claw.activeSessionId") ??
|
||||||
nextState?.active_session_id;
|
nextState?.active_session_id,
|
||||||
|
);
|
||||||
if (!activeSessionId) {
|
if (!activeSessionId) {
|
||||||
setActiveSession(null);
|
setActiveSession(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
window.localStorage.setItem("claw.activeSessionId", activeSessionId);
|
||||||
const response = await fetch(`/api/claw/sessions/${activeSessionId}`, {
|
const response = await fetch(`/api/claw/sessions/${activeSessionId}`, {
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
});
|
});
|
||||||
@@ -610,6 +617,12 @@ function AccountMenu({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSessionId(value: unknown) {
|
||||||
|
if (typeof value !== "string") return null;
|
||||||
|
const trimmed = value.trim();
|
||||||
|
return trimmed || null;
|
||||||
|
}
|
||||||
|
|
||||||
function aggregateUsageByModel(sessions: ClawSessionSummary[]) {
|
function aggregateUsageByModel(sessions: ClawSessionSummary[]) {
|
||||||
const byModel = new Map<
|
const byModel = new Map<
|
||||||
string,
|
string,
|
||||||
|
|||||||
Reference in New Issue
Block a user