v1.12.1: rich status indicator + server-side workspace pane sync
Status indicator (StatusDot): drops the flat amber pulse for a richer set of states — orbiting amber for streaming, spinning sky ring for tool_running, static violet for waiting_for_input, plus the existing idle/error. Backend chat_status frame widens from 'working|idle|error' to discriminate streaming vs tool execution vs paused for user input. Workspace pane sync: pane layout moves from per-device localStorage to server-side sessions.workspace_panes jsonb. PATCH /api/sessions/:id/workspace broadcasts session_workspace_updated on the user channel for cross-device live sync. Echo dedup via JSON comparison so the round-trip frame doesn't loop. Legacy localStorage seeds the server on first hydrate, then is deleted. Deprecated session_panes table dropped. Resilience: startup sweep marks any stale 'streaming' message older than 5 minutes as 'failed' so v1.12.0-style hung rows clear on container restart. useWorkspacePanes gains validatePanes() to prune dead chatId references from saved pane state when the chat list lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ export interface UseSessionChatsOpts {
|
||||
// about pane indexing.
|
||||
openChatInActivePane: (chatId: string) => void;
|
||||
initializeFirstChatIfEmpty: (chatId: string) => void;
|
||||
validatePanes: (validChatIds: Set<string>) => void;
|
||||
}
|
||||
|
||||
export interface UseSessionChatsResult {
|
||||
@@ -44,12 +45,15 @@ export function useSessionChats(
|
||||
openChatInActivePaneRef.current = opts.openChatInActivePane;
|
||||
const initializeFirstChatIfEmptyRef = useRef(opts.initializeFirstChatIfEmpty);
|
||||
initializeFirstChatIfEmptyRef.current = opts.initializeFirstChatIfEmpty;
|
||||
const validatePanesRef = useRef(opts.validatePanes);
|
||||
validatePanesRef.current = opts.validatePanes;
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
api.chats.listForSession(sessionId).then((list) => {
|
||||
if (cancelled) return;
|
||||
setChats(list);
|
||||
validatePanesRef.current(new Set(list.map((c) => c.id)));
|
||||
const openChat = list.find((c) => c.status === 'open');
|
||||
if (openChat) {
|
||||
initializeFirstChatIfEmptyRef.current(openChat.id);
|
||||
|
||||
Reference in New Issue
Block a user