MCPcopy
hub / github.com/coder/mux / WorkspaceStore

Class WorkspaceStore

src/browser/stores/WorkspaceStore.ts:611–4434  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

609 * components re-render when workspace state changes.
610 */
611export class WorkspaceStore {
612 // Per-workspace state (lazy computed on get)
613 private states = new MapStore<string, WorkspaceState>();
614
615 // Stable subset for WorkspaceShell so message deltas do not re-render shell chrome.
616 private workspaceShellStatusCache = new Map<string, WorkspaceShellStatus>();
617
618 // Derived aggregate state (computed from multiple workspaces)
619 private derived = new MapStore<string, DerivedState>();
620
621 // Usage and consumer stores (two-store approach for CostsTab optimization)
622 private usageStore = new MapStore<string, WorkspaceUsageState>();
623 private client: RouterClient<AppRouter> | null = null;
624 private clientChangeController = new AbortController();
625 private providersConfig: ProvidersConfigMap | null = null;
626 /** Stable fingerprint for cache freshness checks across reconnects/app restarts.
627 * `null` until the first successful config fetch — prevents hydrating stale caches
628 * and blocks tokenization until we know the real configuration. */
629 private providersConfigFingerprint: number | null = null;
630 /** Monotonic request counter for serializing provider config refreshes (latest wins). */
631 private providersConfigVersion = 0;
632 /** Version of the last successfully applied provider config (prevents stale overwrites). */
633 private providersConfigAppliedVersion = 0;
634 /** Consecutive provider-config subscription/refresh failures (used for exponential backoff). */
635 private providersConfigFailureStreak = 0;
636 // Workspaces that need a clean history replay once a new iterator is established.
637 // We keep the existing UI visible until the replay can actually start.
638 private pendingReplayReset = new Set<string>();
639 // Last usage snapshot captured right before full replay clears the aggregator.
640 // Used as a temporary fallback so context/cost indicators don't flash empty
641 // during reconnect until replayed usage catches up.
642 private preReplayUsageSnapshot = new Map<string, WorkspaceUsageState>();
643 private consumersStore = new MapStore<string, WorkspaceConsumersState>();
644
645 // Manager for consumer calculations (debouncing, caching, lazy loading)
646 // Architecture: WorkspaceStore orchestrates (decides when), manager executes (performs calculations)
647 // Dual-cache: consumersStore (MapStore) handles subscriptions, manager owns data cache
648 private readonly consumerManager: WorkspaceConsumerManager;
649
650 // Supporting data structures
651 private aggregators = new Map<string, StreamingMessageAggregator>();
652 // Active onChat subscription cleanup handlers (must stay size <= 1).
653 private ipcUnsubscribers = new Map<string, () => void>();
654
655 // Workspace selected in the UI (set from WorkspaceContext routing state).
656 private activeWorkspaceId: string | null = null;
657
658 // Workspace currently owning the live onChat subscription.
659 private activeOnChatWorkspaceId: string | null = null;
660
661 // Lightweight activity snapshots from workspace.activity.list/subscribe.
662 private workspaceActivity = new Map<string, WorkspaceActivitySnapshot>();
663 // Recency timestamp observed when a workspace transitions into streaming=true.
664 // Used to distinguish true stream completion (recency bumps on stream-end) from
665 // abort/error transitions (streaming=false without recency advance).
666 private activityStreamingStartRecency = new Map<string, number>();
667 private activityAbortController: AbortController | null = null;
668 // True once the initial activity.list() snapshot has been applied (or the

Callers

nothing calls this directly

Tested by

no test coverage detected