agent-orchestrator/ui-electrobun/src/mainview/app-state.svelte.ts
Hibryda 162b5417e4 feat(electrobun): hierarchical state tree (Rule 58)
New files:
- project-state.types.ts: all per-project state interfaces
- project-state.svelte.ts: unified per-project state with version counter
- app-state.svelte.ts: root facade re-exporting all stores as appState.*

Rewired components (no more local $state):
- ProjectCard: reads via appState.agent.* and appState.project.tab.*
- TerminalTabs: state in appState.project.terminals.*
- FileBrowser: state in appState.project.files.*
- CommsTab: state in appState.project.comms.*
- TaskBoardTab: state in appState.project.tasks.*

All follow Rule 57 (no $derived with new objects) and Rule 58
(state tree architecture, components are pure renderers).
2026-03-24 15:20:09 +01:00

190 lines
7.2 KiB
TypeScript

/**
* Root state tree — unified API surface for all application state.
*
* Components import `appState` and access sub-domains:
* appState.ui.getSettingsOpen()
* appState.project.getState(id)
* appState.project.terminals.addTab(id)
*
* This file is a pure re-export facade. No new state lives here.
*/
// ── UI store ──────────────────────────────────────────────────────────────
import {
getSettingsOpen, setSettingsOpen, toggleSettings,
getSettingsCategory, setSettingsCategory, openSettingsCategory,
getPaletteOpen, setPaletteOpen, togglePalette,
getSearchOpen, setSearchOpen, toggleSearch,
getNotifDrawerOpen, setNotifDrawerOpen, toggleNotifDrawer,
getShowWizard, setShowWizard, toggleWizard,
getProjectToDelete, setProjectToDelete,
getShowAddGroup, setShowAddGroup, toggleAddGroup,
getNewGroupName, setNewGroupName, resetAddGroupForm,
} from './ui-store.svelte.ts';
// ── Workspace store ───────────────────────────────────────────────────────
import {
getProjects, setProjects, getGroups, setGroups,
getActiveGroupId, setActiveGroup,
getFilteredProjects, getTotalCostDerived, getTotalTokensDerived,
getMountedGroupIds, getActiveGroup as getActiveGroupObj,
addProject, addProjectFromWizard, deleteProject,
cloneCountForProject, handleClone,
addGroup, loadGroupsFromDb, loadProjectsFromDb, trackAllProjects,
getTotalCost, getTotalTokens,
} from './workspace-store.svelte.ts';
// ── Agent store ───────────────────────────────────────────────────────────
import {
startAgent, stopAgent, sendPrompt,
getSession, hasSession, clearSession,
loadLastSession, purgeSession, purgeProjectSessions,
setAgentToastFn, setRetentionConfig, loadRetentionConfig,
type AgentSession, type AgentMessage, type AgentStatus,
} from './agent-store.svelte.ts';
// ── Project state (per-project tree) ──────────────────────────────────────
import {
getProjectState,
getActiveTab, isTabActivated, setActiveTab,
addTerminalTab, closeTerminalTab, activateTerminalTab, toggleTerminalExpanded,
setFileState, setFileMulti, nextFileRequestToken, getFileRequestToken,
setCommsState, setCommsMulti,
setTaskState, setTaskMulti, nextTaskPollToken, getTaskPollToken,
removeProject as removeProjectState,
} from './project-state.svelte.ts';
// ── Health store ──────────────────────────────────────────────────────────
import {
trackProject, recordActivity, recordToolDone,
recordTokenSnapshot, setProjectStatus,
getProjectHealth, getAttentionQueue, getHealthAggregates,
getActiveTools, getToolHistogram,
untrackProject, stopHealthTick,
} from './health-store.svelte.ts';
// ── Notifications store ───────────────────────────────────────────────────
import {
getNotifications, getNotifCount,
addNotification, removeNotification, clearAll as clearNotifications,
} from './notifications-store.svelte.ts';
// ── Blink store ───────────────────────────────────────────────────────────
import {
getBlinkVisible, startBlink, stopBlink,
} from './blink-store.svelte.ts';
// ── Theme store ───────────────────────────────────────────────────────────
import { themeStore } from './theme-store.svelte.ts';
// ── i18n ──────────────────────────────────────────────────────────────────
import { t, setLocale, getLocale, getDir } from './i18n.svelte.ts';
// ── Unified API ───────────────────────────────────────────────────────────
export const appState = {
ui: {
getSettingsOpen, setSettingsOpen, toggleSettings,
getSettingsCategory, setSettingsCategory, openSettingsCategory,
getPaletteOpen, setPaletteOpen, togglePalette,
getSearchOpen, setSearchOpen, toggleSearch,
getNotifDrawerOpen, setNotifDrawerOpen, toggleNotifDrawer,
getShowWizard, setShowWizard, toggleWizard,
getProjectToDelete, setProjectToDelete,
getShowAddGroup, setShowAddGroup, toggleAddGroup,
getNewGroupName, setNewGroupName, resetAddGroupForm,
},
workspace: {
getProjects, setProjects, getGroups, setGroups,
getActiveGroupId, setActiveGroup,
getFilteredProjects, getTotalCostDerived, getTotalTokensDerived,
getMountedGroupIds, getActiveGroup: getActiveGroupObj,
addProject, addProjectFromWizard, deleteProject,
cloneCountForProject, handleClone,
addGroup, loadGroupsFromDb, loadProjectsFromDb, trackAllProjects,
getTotalCost, getTotalTokens,
},
agent: {
startAgent, stopAgent, sendPrompt,
getSession, hasSession, clearSession,
loadLastSession, purgeSession, purgeProjectSessions,
setToastFn: setAgentToastFn,
setRetentionConfig, loadRetentionConfig,
},
project: {
getState: getProjectState,
removeState: removeProjectState,
tab: {
getActiveTab, isTabActivated, setActiveTab,
},
terminals: {
addTab: addTerminalTab,
closeTab: closeTerminalTab,
activateTab: activateTerminalTab,
toggleExpanded: toggleTerminalExpanded,
},
files: {
setState: setFileState,
setMulti: setFileMulti,
nextRequestToken: nextFileRequestToken,
getRequestToken: getFileRequestToken,
},
comms: {
setState: setCommsState,
setMulti: setCommsMulti,
},
tasks: {
setState: setTaskState,
setMulti: setTaskMulti,
nextPollToken: nextTaskPollToken,
getPollToken: getTaskPollToken,
},
},
health: {
trackProject, recordActivity, recordToolDone,
recordTokenSnapshot, setProjectStatus,
getProjectHealth, getAttentionQueue, getHealthAggregates,
getActiveTools, getToolHistogram,
untrackProject, stopHealthTick,
},
notifications: {
getAll: getNotifications, getCount: getNotifCount,
add: addNotification, remove: removeNotification, clear: clearNotifications,
},
blink: {
getVisible: getBlinkVisible, start: startBlink, stop: stopBlink,
},
theme: themeStore,
i18n: { t, setLocale, getLocale, getDir },
} as const;
// Re-export types for convenience
export type { AgentSession, AgentMessage, AgentStatus };
export type {
ProjectState, TermTab, TerminalState, FileState,
CommsState, TaskState, TabState, DirEntry,
Channel, ChannelMessage, CommsAgent, DM, ChannelMember, Task,
ProjectTab,
} from './project-state.types.ts';