82 lines
3.0 KiB
TypeScript
82 lines
3.0 KiB
TypeScript
import { useEffect, useMemo } from "react";
|
|
import { useAppStore } from "@/components/state-provider";
|
|
import { getWebSocketClient } from "@/lib/ws/connection";
|
|
import type { ContextWindowEntry } from "@/lib/state/store";
|
|
|
|
export function useSessionContextWindow(sessionId: string | null): ContextWindowEntry | undefined {
|
|
// Subscribe to individual primitive values to ensure reactivity
|
|
const size = useAppStore((state) =>
|
|
sessionId ? state.contextWindow.bySessionId[sessionId]?.size : undefined,
|
|
);
|
|
const used = useAppStore((state) =>
|
|
sessionId ? state.contextWindow.bySessionId[sessionId]?.used : undefined,
|
|
);
|
|
const remaining = useAppStore((state) =>
|
|
sessionId ? state.contextWindow.bySessionId[sessionId]?.remaining : undefined,
|
|
);
|
|
const efficiency = useAppStore((state) =>
|
|
sessionId ? state.contextWindow.bySessionId[sessionId]?.efficiency : undefined,
|
|
);
|
|
const timestamp = useAppStore((state) =>
|
|
sessionId ? state.contextWindow.bySessionId[sessionId]?.timestamp : undefined,
|
|
);
|
|
|
|
// Memoize the combined object
|
|
const contextWindow = useMemo(() => {
|
|
if (size === undefined) return undefined;
|
|
return {
|
|
size,
|
|
used: used ?? 0,
|
|
remaining: remaining ?? 0,
|
|
efficiency: efficiency ?? 0,
|
|
timestamp,
|
|
};
|
|
}, [size, used, remaining, efficiency, timestamp]);
|
|
|
|
const session = useAppStore((state) =>
|
|
sessionId ? state.taskSessions.items[sessionId] : undefined,
|
|
);
|
|
const setContextWindow = useAppStore((state) => state.setContextWindow);
|
|
const connectionStatus = useAppStore((state) => state.connection.status);
|
|
|
|
// Populate context window from session metadata if not already in store
|
|
useEffect(() => {
|
|
if (!sessionId || contextWindow) return;
|
|
|
|
// Try to extract context_window from session metadata
|
|
const metadata = session?.metadata;
|
|
if (!metadata || typeof metadata !== "object") return;
|
|
|
|
const storedContextWindow = (metadata as Record<string, unknown>).context_window;
|
|
if (!storedContextWindow || typeof storedContextWindow !== "object") return;
|
|
|
|
// Map stored context window to ContextWindowEntry
|
|
const cw = storedContextWindow as Record<string, unknown>;
|
|
const entry: ContextWindowEntry = {
|
|
size: (cw.size as number) ?? 0,
|
|
used: (cw.used as number) ?? 0,
|
|
remaining: (cw.remaining as number) ?? 0,
|
|
efficiency: (cw.efficiency as number) ?? 0,
|
|
timestamp: (cw.timestamp as string) ?? undefined,
|
|
};
|
|
|
|
setContextWindow(sessionId, entry);
|
|
}, [sessionId, contextWindow, session?.metadata, setContextWindow]);
|
|
|
|
// Subscribe to session updates via WebSocket
|
|
useEffect(() => {
|
|
if (!sessionId) return;
|
|
if (connectionStatus !== "connected") return;
|
|
const client = getWebSocketClient();
|
|
if (client) {
|
|
const unsubscribe = client.subscribeSession(sessionId);
|
|
return () => {
|
|
unsubscribe();
|
|
// Don't clear context window on cleanup - keep it cached
|
|
};
|
|
}
|
|
}, [sessionId, connectionStatus]);
|
|
|
|
return contextWindow;
|
|
}
|