Flow Studio
Observer Panel Store
flowObserverPanelStore is the Zustand store that holds the Observer Panel's UI state. Tab components subscribe to slices of this store and re-render reactively as execution events arrive.
Store Shape
// flow-observer-core/src/store/flowObserverPanelStore.ts
interface FlowObserverPanelState {
// Panel visibility
isOpen: boolean;
isDocked: boolean;
dockPosition: 'right' | 'bottom';
// Tab management
tabs: TabDescriptor[];
activeTabId: string;
// Execution data
executionId: string | null;
executionStatus: ExecutionStatus | null;
executionStartedAt: string | null;
executionCompletedAt: string | null;
completedNodeCount: number;
totalNodeCount: number;
// Log buffer
logs: LogEntry[]; // capped at 10,000 entries
selectedLog: LogEntry | null;
// Node statuses
nodeStatuses: Record<string, NodeExecutionState>;
selectedNodeId: string | null;
// Actions
setActiveTabId: (id: string) => void;
appendLog: (entry: LogEntry) => void;
incrementCompletedCount: () => void;
setNodeStatus: (nodeId: string, state: NodeExecutionState) => void;
setSelectedNodeId: (nodeId: string | null) => void;
setStatus: (status: ExecutionStatus) => void;
reset: () => void;
}
Subscribing in Components
// Reading execution status in ExecutionStatusTabContent
import { useFlowObserverPanelStore } from 'flow-observer-core';
export function ExecutionStatusTabContent() {
const status = useFlowObserverPanelStore(s => s.executionStatus);
const completedCount = useFlowObserverPanelStore(s => s.completedNodeCount);
const totalCount = useFlowObserverPanelStore(s => s.totalNodeCount);
return (
<div>
<StatusBadge status={status} />
<ProgressBar value={completedCount} max={totalCount} />
</div>
);
}
Log Buffer Behaviour
The logs array is capped at 10,000 entries. When a new log arrives and the cap is reached, the oldest entry is removed (FIFO eviction). This prevents memory growth during long-running executions with verbose logging.
// appendLog action (internal implementation)
appendLog: (entry) => set(state => {
const next = [...state.logs, entry];
return { logs: next.length > 10000 ? next.slice(next.length - 10000) : next };
})
Persistence
The following store keys are persisted to localStorage and restored on page load:
isOpen— panel stays open across refreshesisDocked— floating/docked preference is remembereddockPosition— right vs bottom dock rememberedactiveTabId— last viewed tab is restored
Execution data (logs, nodeStatuses, executionId) is NOT persisted — it is always cleared on a new execution.