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:
2026-05-21 20:32:02 +00:00
parent d58d553503
commit 48ee63a286
15 changed files with 371 additions and 180 deletions

View File

@@ -143,6 +143,11 @@ export const api = {
),
openChatsCount: (id: string) =>
request<{ count: number }>(`/api/sessions/${id}/chats/open-count`),
updateWorkspacePanes: (id: string, panes: Session['workspace_panes']) =>
request<Session>(`/api/sessions/${id}/workspace`, {
method: 'PATCH',
body: JSON.stringify({ workspace_panes: panes }),
}),
},
chats: {

View File

@@ -34,6 +34,8 @@ export interface Session {
agent_id: string | null;
// v1.9: null = inherit from project.default_web_search_enabled.
web_search_enabled: boolean | null;
// v1.12.1: server-authoritative pane layout, replaces localStorage.
workspace_panes: WorkspacePane[];
}
// v1.8.1: 'global' = /data/AGENTS.md (always-on), 'project' = per-project