@wrongstack/webui 0.298.3 → 0.300.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/assets/AgentRosterView-wkALMOGD.js +9 -0
  2. package/dist/assets/{AnalyticsDashboard-irejsLMt.js → AnalyticsDashboard-CIN35A_u.js} +1 -1
  3. package/dist/assets/AudienceMemoryPanel-BAY2Bh8z.js +3 -0
  4. package/dist/assets/ChangesView-CVWSTGmX.js +1 -0
  5. package/dist/assets/ChronicleDashboard-Bg3W7C9U.js +1 -0
  6. package/dist/assets/CodeEditor-CWY_6cQD.js +1 -0
  7. package/dist/assets/CodeMap-CjmKO0lB.js +1 -0
  8. package/dist/assets/CronJobsPanel-BinzTWNs.js +1 -0
  9. package/dist/assets/DeadCodeScanPanel-C3CgaNVv.js +2 -0
  10. package/dist/assets/DebugDashboard-BqUghn06.js +1 -0
  11. package/dist/assets/DesignGalleryView-CuWWQAlD.js +1 -0
  12. package/dist/assets/GoalView-2weuLiPM.js +1 -0
  13. package/dist/assets/KanbanView-DXYRrshJ.js +3 -0
  14. package/dist/assets/{MailboxDetailView-Dh8ekyMw.js → MailboxDetailView-aaHx9Nma.js} +1 -1
  15. package/dist/assets/MemoryManager-BgcicCyg.js +1 -0
  16. package/dist/assets/{ModelPicker-BxYMTEEN.js → ModelPicker-B3BqjJnT.js} +1 -1
  17. package/dist/assets/OfficeMapPanel-Ck8NUOEs.js +4 -0
  18. package/dist/assets/OfficeMapPanel-CpexsBed.css +1 -0
  19. package/dist/assets/{ProcessMonitor-DVUCtVHZ.js → ProcessMonitor-CoMYZcdS.js} +1 -1
  20. package/dist/assets/{QueuePanel-n9lScdWu.js → QueuePanel-CA3CVCO_.js} +1 -1
  21. package/dist/assets/{RefreshDebugView-eZQ3wdxU.js → RefreshDebugView-cqBtyNna.js} +1 -1
  22. package/dist/assets/RequirementIntakeView-BBtUk8mC.js +1 -0
  23. package/dist/assets/SageTabs-Di49i4Yu.js +2 -0
  24. package/dist/assets/SddHub-D8iV6l9A.js +2 -0
  25. package/dist/assets/SessionInspectView-DHC_xTzG.js +1 -0
  26. package/dist/assets/SessionList-DH-ZsHmv.js +1 -0
  27. package/dist/assets/SessionsDashboard-Coi6htwg.js +1 -0
  28. package/dist/assets/SetupScreen-CD2Sx4n9.js +1 -0
  29. package/dist/assets/SkillDetailView-D7wSJWUX.js +3 -0
  30. package/dist/assets/SpecsView-BRWSI1iV.js +1 -0
  31. package/dist/assets/TechStackView-BOjkuJLe.js +1 -0
  32. package/dist/assets/{TerminalPanel-BgMsGfGa.js → TerminalPanel-Dg8WR5Un.js} +1 -1
  33. package/dist/assets/{Toaster-EXqX2jqp.js → Toaster-DSKFSuK3.js} +1 -1
  34. package/dist/assets/activity-BWbV0byu.js +9 -0
  35. package/dist/assets/activity-Bjb_mil3.js +9 -0
  36. package/dist/assets/activity-Bze6njDy.js +9 -0
  37. package/dist/assets/activity-Ciqcr7Ps.js +9 -0
  38. package/dist/assets/activity-DA9hmVZV.js +9 -0
  39. package/dist/assets/activity-GdnS66AB.js +9 -0
  40. package/dist/assets/activity-eawh_OWs.js +9 -0
  41. package/dist/assets/{button-DwmC7ENW.js → button-Dcy288Mc.js} +1 -1
  42. package/dist/assets/{chat-DzPxYALH.js → chat-4NEOESoU.js} +1 -1
  43. package/dist/assets/{chat-DLn1hY01.js → chat-BSg62iwX.js} +1 -1
  44. package/dist/assets/{chat-OunddzYy.js → chat-Bb1TpPfJ.js} +1 -1
  45. package/dist/assets/{chat-DxLD17ER.js → chat-COLKjtcx.js} +1 -1
  46. package/dist/assets/{chat-DSEq1Bdz.js → chat-CfRKV9iX.js} +1 -1
  47. package/dist/assets/{chat-CwnuX7tG.js → chat-EbeT4kiS.js} +1 -1
  48. package/dist/assets/{chat-store-LHzJqRCp.js → chat-store-CtOyUCdF.js} +2 -2
  49. package/dist/assets/{chat-CRmMDzCb.js → chat-ux_gymOJ.js} +1 -1
  50. package/dist/assets/{codemap-activity-store-B6n7KiS8.js → codemap-activity-store-DQfjo7-j.js} +1 -1
  51. package/dist/assets/codemap-index-store-COStDU-8.js +1 -0
  52. package/dist/assets/{common-DMM-xyW3.js → common-BXJbu5Y-.js} +1 -1
  53. package/dist/assets/{common-C9ikgX7d.js → common-BiNu_WzQ.js} +1 -1
  54. package/dist/assets/common-COVxQ0FV.js +1 -0
  55. package/dist/assets/{common-D29Zdkxb.js → common-Ch7JihXD.js} +1 -1
  56. package/dist/assets/{common-DoUBSHRY.js → common-DPaTeTls.js} +1 -1
  57. package/dist/assets/{common-vdwxzODB.js → common-DdGpRh8j.js} +1 -1
  58. package/dist/assets/{common-C5hY-d_0.js → common-pI6fYZW3.js} +1 -1
  59. package/dist/assets/{dialog-DsCmc6eL.js → dialog-ftgTihmF.js} +1 -1
  60. package/dist/assets/{empty-state-02bIS4x7.js → empty-state-RRSqQaCk.js} +1 -1
  61. package/dist/assets/i18n-C31PI0Up.js +2 -0
  62. package/dist/assets/index-5IWUhPO4.css +1 -0
  63. package/dist/assets/index-D1izXztg.js +132 -0
  64. package/dist/assets/{input-UhWgodVi.js → input-fo9-BPBC.js} +1 -1
  65. package/dist/assets/{mailbox-store-xh2Ux-Xs.js → mailbox-store-Bc9ER3Ph.js} +1 -1
  66. package/dist/assets/{progress-ring-C0O73ZjR.js → progress-ring-D_d6hn_4.js} +1 -1
  67. package/dist/assets/{roster-ws-DlQQL7Eh.js → roster-ws-D6dGRfC5.js} +1 -1
  68. package/dist/assets/{session-store-BE_S1f5v.js → session-store-b2KGFwkX.js} +1 -1
  69. package/dist/assets/settings-BKuhxUSF.js +1 -0
  70. package/dist/assets/settings-CeK0doV7.js +1 -0
  71. package/dist/assets/settings-DZ-H89lu.js +1 -0
  72. package/dist/assets/settings-DvrdpSdA.js +1 -0
  73. package/dist/assets/settings-SBUqq0ll.js +1 -0
  74. package/dist/assets/settings-W8t1ZrxM.js +1 -0
  75. package/dist/assets/settings-tOqZkk9R.js +1 -0
  76. package/dist/assets/{shared-bBntASiy.js → shared-KAzksK0C.js} +1 -1
  77. package/dist/assets/stores-OBoFiAKe.js +7 -0
  78. package/dist/assets/ui-store-CE4-TlwB.js +1 -0
  79. package/dist/assets/useWebSocket-DuLtH2jI.js +29 -0
  80. package/dist/assets/{utils-_s0GyctV.js → utils-B-9lSDIn.js} +1 -1
  81. package/dist/assets/{vendor-CxV3l5PQ.js → vendor-BuarzSSb.js} +30 -30
  82. package/dist/assets/{view-navigation-DLdE7qHU.js → view-navigation-DIDEcp4V.js} +1 -1
  83. package/dist/assets/ws-client-Bw1ixxwI.js +1 -0
  84. package/dist/components/AutonomyPicker.d.ts +1 -1
  85. package/dist/components/ChatView/auto-collapse.d.ts +42 -0
  86. package/dist/components/CouncilLogTimeline.d.ts +2 -0
  87. package/dist/components/FallbackModal.d.ts +2 -0
  88. package/dist/components/KanbanVerificationDashboard.d.ts +0 -6
  89. package/dist/components/QuickModelSwitcher.filter.d.ts +9 -4
  90. package/dist/components/RequirementIntakeView.d.ts +2 -0
  91. package/dist/components/SessionInspectView.d.ts +2 -0
  92. package/dist/components/SettingsPanel/ModelCatalogPicker.d.ts +1 -2
  93. package/dist/components/SettingsPanel/PluginToggleList.d.ts +11 -3
  94. package/dist/components/SettingsPanel/brain-section-options.d.ts +41 -55
  95. package/dist/components/TaskCard.d.ts +0 -1
  96. package/dist/components/TaskRiskPanel.d.ts +10 -3
  97. package/dist/components/TechStackView/shared.d.ts +11 -6
  98. package/dist/components/ThemeProvider.d.ts +6 -1
  99. package/dist/components/ViewRouter.d.ts +1 -1
  100. package/dist/components/agent-roster-data.d.ts +2 -1
  101. package/dist/hooks/useWebSocket.d.ts +1 -0
  102. package/dist/hooks/ws-handlers/files-mailbox-handlers.d.ts +1 -0
  103. package/dist/hooks/ws-handlers/misc-handlers.d.ts +13 -0
  104. package/dist/hooks/ws-handlers/session-handlers.d.ts +1 -0
  105. package/dist/index.css +30 -0
  106. package/dist/index.html +24 -24
  107. package/dist/index.js +26845 -11968
  108. package/dist/lib/file-icons.d.ts +3 -3
  109. package/dist/lib/palettes.d.ts +37 -0
  110. package/dist/lib/view-navigation.d.ts +2 -2
  111. package/dist/lib/ws-client-actions.d.ts +1 -0
  112. package/dist/lib/ws-client.d.ts +3 -3
  113. package/dist/providers.json +7 -7
  114. package/dist/stores/config-store.d.ts +9 -1
  115. package/dist/stores/context-editor-store.d.ts +9 -1
  116. package/dist/stores/council-log-store.d.ts +67 -0
  117. package/dist/stores/fallback-store.d.ts +30 -0
  118. package/dist/stores/fleet-store.d.ts +13 -0
  119. package/dist/stores/index.d.ts +5 -1
  120. package/dist/stores/local-prefs.d.ts +4 -0
  121. package/dist/stores/mailbox-store.d.ts +2 -0
  122. package/dist/stores/session-inspect-store.d.ts +51 -0
  123. package/dist/stores/ui-store.d.ts +19 -7
  124. package/dist/stores/viz-store.d.ts +1 -1
  125. package/dist/types/brain.d.ts +15 -0
  126. package/dist/types/client-message.d.ts +17 -1
  127. package/dist/types/protocol-core.d.ts +19 -0
  128. package/dist/types/runtime.d.ts +8 -0
  129. package/dist/types/server-message.d.ts +15 -4
  130. package/dist/types/system.d.ts +35 -0
  131. package/package.json +9 -9
  132. package/dist/assets/AgentRosterView-RvxaV08Y.js +0 -11
  133. package/dist/assets/AudienceMemoryPanel-DDW_WPjf.js +0 -3
  134. package/dist/assets/ChangesView-Bnd167hf.js +0 -1
  135. package/dist/assets/ChronicleDashboard-DC62FDEt.js +0 -1
  136. package/dist/assets/CodeEditor-DCWcCQPO.js +0 -1
  137. package/dist/assets/CodeMap-DSqqgBuD.js +0 -1
  138. package/dist/assets/CronJobsPanel-BXujnpGC.js +0 -1
  139. package/dist/assets/DeadCodeScanPanel-HTbGUTMl.js +0 -2
  140. package/dist/assets/DebugDashboard-B5kJBUv0.js +0 -1
  141. package/dist/assets/DesignGalleryView-BQ0CZpQm.js +0 -1
  142. package/dist/assets/GoalView-DvaSR6CO.js +0 -1
  143. package/dist/assets/KanbanView-DpWs_i8T.js +0 -3
  144. package/dist/assets/MemoryManager-CUAbNwsz.js +0 -1
  145. package/dist/assets/OfficeMapPanel-BFIF-EMt.css +0 -1
  146. package/dist/assets/OfficeMapPanel-HgERknuN.js +0 -4
  147. package/dist/assets/SageTabs-B-eQ--Sb.js +0 -2
  148. package/dist/assets/SddHub-D81poT6w.js +0 -2
  149. package/dist/assets/SessionsDashboard-CR3NZeHw.js +0 -1
  150. package/dist/assets/SetupScreen-t6wrhv6l.js +0 -1
  151. package/dist/assets/SkillDetailView-D6TOvMQU.js +0 -3
  152. package/dist/assets/SpecsView-BYiJr__T.js +0 -1
  153. package/dist/assets/TechStackView-HEMM3PkG.js +0 -1
  154. package/dist/assets/activity-BBPMHCAJ.js +0 -5
  155. package/dist/assets/activity-BJijwuIr.js +0 -5
  156. package/dist/assets/activity-DReNmuta.js +0 -5
  157. package/dist/assets/activity-DeEOo2zu.js +0 -5
  158. package/dist/assets/activity-Dyh19u3P.js +0 -5
  159. package/dist/assets/activity-GR8KiHvf.js +0 -5
  160. package/dist/assets/activity-iuGHFz2B.js +0 -5
  161. package/dist/assets/codemap-index-store-oapPwtvI.js +0 -1
  162. package/dist/assets/common-BfVFjVhf.js +0 -1
  163. package/dist/assets/i18n-DxnYsmc-.js +0 -2
  164. package/dist/assets/index-Bf75VrDE.js +0 -132
  165. package/dist/assets/index-NFp5CXyK.css +0 -1
  166. package/dist/assets/settings-B5xal2R3.js +0 -1
  167. package/dist/assets/settings-BHtFy8EG.js +0 -1
  168. package/dist/assets/settings-Bss5hBla.js +0 -1
  169. package/dist/assets/settings-BzrLCVRP.js +0 -1
  170. package/dist/assets/settings-C7RdvmLZ.js +0 -1
  171. package/dist/assets/settings-Dd94HoV6.js +0 -1
  172. package/dist/assets/settings-Dm9THFe8.js +0 -1
  173. package/dist/assets/stores-BS-Bdi-5.js +0 -7
  174. package/dist/assets/ui-store-C4Ybfoon.js +0 -1
  175. package/dist/assets/useWebSocket-x8PMoTq8.js +0 -28
  176. package/dist/assets/ws-client-Cy3oRAmZ.js +0 -1
  177. package/dist/lib/accent-colors.d.ts +0 -136
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Returns a Tailwind text color class for a file extension.
3
- * Colors match the WrongStack semantic palette same hues used in
4
- * syntax highlighting and Monaco editor themes for visual consistency.
2
+ * Returns a semantic Tailwind text-color class for a file extension.
3
+ * The classes resolve through WebUI theme tokens so file icons adapt to
4
+ * light/dark mode and the selected product palette.
5
5
  */
6
6
  export declare function fileIconColor(name: string, isDirectory: boolean): string;
7
7
  export declare function fileIcon(name: string): React.ComponentType<{
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Color palette registry — the WebUI's "main color" system.
3
+ *
4
+ * Users can pick a palette on top of the light/dark theme toggle. The actual
5
+ * token values live in `index.css` as `:root[data-palette="…"]` /
6
+ * `.dark[data-palette="…"]` blocks (rendering is driven by `hsl(var(--token))`),
7
+ * so this module only describes the palettes for the picker UI: id, i18n
8
+ * label, and the two swatch colors that preview the palette's two brand
9
+ * signals. `applyPalette` toggles the `data-palette` attribute on `<html>`.
10
+ *
11
+ * To add a palette: add a CSS token block in `index.css`, an entry here (in
12
+ * the same order), and an i18n label key in all 7 locale files. The default
13
+ * "signal" palette needs no CSS block — it is the base token set.
14
+ */
15
+ export type PaletteId = 'signal' | 'emerald-gold' | 'blue-navy' | 'purple-pink' | 'cyan-teal' | 'rose-copper' | 'indigo-amber';
16
+ export interface PaletteDefinition {
17
+ id: PaletteId;
18
+ /** i18n key for the palette name, e.g. 'settings:general.paletteEmeraldGold'. */
19
+ labelKey: string;
20
+ /** CSS color for the main (primary) swatch stripe — dark-mode value so it reads on both themes. */
21
+ swatch: string;
22
+ /** CSS color for the secondary (brand) swatch stripe. */
23
+ swatchSecondary: string;
24
+ }
25
+ export declare const DEFAULT_PALETTE: PaletteId;
26
+ /** localStorage key for the persisted palette — shared by ThemeProvider and the config store's merge. */
27
+ export declare const PALETTE_STORAGE_KEY = "wrongstack-palette";
28
+ export declare const PALETTES: readonly PaletteDefinition[];
29
+ export declare function isPaletteId(value: unknown): value is PaletteId;
30
+ export declare function getPalette(value: unknown): PaletteDefinition;
31
+ /** Guarded read of a persisted palette id; invalid/missing/blocked storage
32
+ * falls back to `fallback`. Shared by ThemeProvider (initial state) and the
33
+ * config store's `merge` so the two persistence layers agree. */
34
+ export declare function readStoredPalette(storageKey: string, fallback: PaletteId): PaletteId;
35
+ /** Apply a palette to <html> by setting `data-palette`; removes it for the default. */
36
+ export declare function applyPalette(root: HTMLElement, palette: PaletteId): void;
37
+ //# sourceMappingURL=palettes.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { type Activity } from '@/stores/ui-store';
2
2
  export type PanelMainView = 'chat' | 'files' | 'skill' | 'officemap' | 'changes' | 'mailbox' | 'design-gallery';
3
- export type MainView = 'goal' | 'kanban' | 'sddhub' | 'settings' | 'memory' | 'roster' | 'codemap' | 'techstack' | 'chronicle';
4
- export type AppView = PanelMainView | MainView | 'sessions' | 'setup' | 'debug' | 'refresh-debug' | 'analytics';
3
+ export type MainView = 'goal' | 'kanban' | 'sddhub' | 'settings' | 'memory' | 'roster' | 'codemap' | 'techstack' | 'chronicle' | 'intake';
4
+ export type AppView = PanelMainView | MainView | 'sessions' | 'session-inspect' | 'setup' | 'debug' | 'refresh-debug' | 'analytics';
5
5
  export declare const PANEL_VIEW_BY_ACTIVITY: Record<Activity, PanelMainView>;
6
6
  export declare const VIEW_ACTIVITY: Partial<Record<AppView, Activity>>;
7
7
  export declare const ACTIVITY_SHORTCUT_BY_KEY: Readonly<Record<string, Activity>>;
@@ -104,6 +104,7 @@ export interface WsClientActionMethods {
104
104
  listSessions(limit?: number): void;
105
105
  deleteSession(id: string): void;
106
106
  renameSession(id: string, name: string): void;
107
+ inspectSession(id: string): void;
107
108
  setWorkingDir(path: string): void;
108
109
  resumeSession(sessionId: string): void;
109
110
  ping(): void;
@@ -1,6 +1,6 @@
1
1
  import type { WSClientMessage, WSModelSwitchResult, WSServerMessage, WSUserMessageImage } from '../types';
2
2
  import type { ProviderCustomModelWire } from '../types/client-message';
3
- import type { ContextEditorMessage } from '../types/runtime';
3
+ import type { ContextEditorMessage, ContextEditorRemoval } from '../types/runtime';
4
4
  import { type WsClientActionMethods } from './ws-client-actions';
5
5
  import type { WSSendOptions } from './ws-client-contracts';
6
6
  import { type EventHandler, type WsStatus } from './ws-client-utils';
@@ -154,8 +154,8 @@ declare class WrongStackWebSocketClientBase {
154
154
  compactContext(aggressive?: boolean): void;
155
155
  repairContext(): void;
156
156
  openContextEditor(): void;
157
- validateContextEditor(baseRevision: string, messages: ContextEditorMessage[], allowRepair: boolean): void;
158
- applyContextEditor(baseRevision: string, messages: ContextEditorMessage[], allowRepair: boolean): void;
157
+ validateContextEditor(baseRevision: string, messages: ContextEditorMessage[], removals: ContextEditorRemoval[], allowRepair: boolean): void;
158
+ applyContextEditor(baseRevision: string, messages: ContextEditorMessage[], removals: ContextEditorRemoval[], allowRepair: boolean): void;
159
159
  debugContext(options?: WSSendOptions): void;
160
160
  listContextModes(): void;
161
161
  switchContextMode(id: string): void;
@@ -45,14 +45,14 @@
45
45
  }
46
46
  },
47
47
  {
48
- "id": "zyloo",
49
- "name": "Zyloo",
48
+ "id": "ai-gateway",
49
+ "name": "Vercel AI Gateway",
50
50
  "family": "openai-compatible",
51
- "description": "Zyloo API OpenAI-compatible with a 128-tool limit per request",
52
- "icon": "🚀",
53
- "color": "from-accent/12 to-accent/5 border-accent/30 hover:border-accent/50",
54
- "keyPlaceholder": "zy-...",
55
- "docsUrl": "https://docs.zyloo.io/"
51
+ "description": "Every model behind one key routed by Vercel AI Gateway",
52
+ "icon": "",
53
+ "color": "from-primary/12 to-primary/5 border-primary/30 hover:border-primary/50",
54
+ "keyPlaceholder": "vck_...",
55
+ "docsUrl": "https://vercel.com/docs/ai-gateway"
56
56
  },
57
57
  {
58
58
  "id": "openrouter",
@@ -1,3 +1,4 @@
1
+ import { type PaletteId } from '@/lib/palettes';
1
2
  export interface ConfigState {
2
3
  provider: string;
3
4
  model: string;
@@ -21,6 +22,10 @@ export interface ConfigState {
21
22
  lastError?: string | undefined;
22
23
  };
23
24
  theme: 'light' | 'dark' | 'system';
25
+ /** Selected color palette id — see `lib/palettes.ts` + `index.css` token
26
+ * blocks. Mirrors the ThemeProvider's `wrongstack-palette` localStorage
27
+ * entry so the choice survives reloads and cross-surface config reads. */
28
+ palette: PaletteId;
24
29
  autoConnect: boolean;
25
30
  /** Play a soft synthesized chime when run.result lands with status=done.
26
31
  * Off by default — opt-in via the Command Palette. Persisted so the
@@ -29,8 +34,9 @@ export interface ConfigState {
29
34
  soundOnComplete: boolean;
30
35
  setProvider: (provider: string) => void;
31
36
  setModel: (model: string) => void;
32
- setConfig: (config: Partial<Omit<ConfigState, 'setProvider' | 'setModel' | 'setConfig' | 'setTheme'>>) => void;
37
+ setConfig: (config: Partial<Omit<ConfigState, 'setProvider' | 'setModel' | 'setConfig' | 'setTheme' | 'setPalette'>>) => void;
33
38
  setTheme: (theme: 'light' | 'dark' | 'system') => void;
39
+ setPalette: (palette: PaletteId) => void;
34
40
  setWsConnected: (connected: boolean) => void;
35
41
  setWsStatus: (s: ConfigState['wsStatus']) => void;
36
42
  setSoundOnComplete: (on: boolean) => void;
@@ -44,6 +50,7 @@ export declare const useConfigStore: import("zustand").UseBoundStore<Omit<import
44
50
  model: string;
45
51
  baseUrl: string | undefined;
46
52
  theme: "dark" | "light" | "system";
53
+ palette: PaletteId;
47
54
  autoConnect: boolean;
48
55
  soundOnComplete: boolean;
49
56
  }, unknown>>) => void;
@@ -57,6 +64,7 @@ export declare const useConfigStore: import("zustand").UseBoundStore<Omit<import
57
64
  model: string;
58
65
  baseUrl: string | undefined;
59
66
  theme: "dark" | "light" | "system";
67
+ palette: PaletteId;
60
68
  autoConnect: boolean;
61
69
  soundOnComplete: boolean;
62
70
  }, unknown>>;
@@ -1,4 +1,4 @@
1
- import type { ContextEditorMessage, ContextEditorMetrics, ContextEditorRepairPreview, ContextEditorValidationError, ContextEditorWarning, ContextEditorConflict, ContextEditorDiagnostics } from '@/types/runtime';
1
+ import type { ContextEditorMessage, ContextEditorMetrics, ContextEditorRemoval, ContextEditorRepairPreview, ContextEditorValidationError, ContextEditorWarning, ContextEditorConflict, ContextEditorDiagnostics } from '@/types/runtime';
2
2
  export type ContextEditorPhase = 'closed' | 'loading_snapshot' | 'clean_snapshot' | 'dirty' | 'validating' | 'validated' | 'invalid' | 'conflicted' | 'applying' | 'applied_success' | 'apply_failed';
3
3
  interface ReadonlyContext {
4
4
  systemPromptTokens: number;
@@ -14,6 +14,7 @@ interface MessageBreakdownEntry {
14
14
  preview: string;
15
15
  blockCount: number | null;
16
16
  warnings: ContextEditorWarning[];
17
+ pairedAssistantIndices: number[];
17
18
  }
18
19
  interface ValidationResult {
19
20
  ok: boolean;
@@ -44,6 +45,9 @@ export interface ContextEditorState {
44
45
  messageBreakdown: MessageBreakdownEntry[];
45
46
  diagnostics: ContextEditorDiagnostics | null;
46
47
  removeMessages: Set<number>;
48
+ /** Messages selected directly by the user, excluding required assistant pairing. */
49
+ explicitRemoveMessages: Set<number>;
50
+ removeRanges: ContextEditorRemoval[];
47
51
  validation: ValidationResult | null;
48
52
  appliedResult: AppliedResult | null;
49
53
  errorMessage: string | null;
@@ -59,7 +63,10 @@ export interface ContextEditorActions {
59
63
  diagnostics: ContextEditorDiagnostics;
60
64
  }) => void;
61
65
  toggleRemoveMessage: (index: number) => void;
66
+ markRangeForRemoval: (removal: ContextEditorRemoval) => void;
62
67
  clearRemovals: () => void;
68
+ beginValidation: () => void;
69
+ beginApply: () => void;
63
70
  setValidation: (result: ValidationResult) => void;
64
71
  setApplied: (result: AppliedResult) => void;
65
72
  setError: (message: string | null) => void;
@@ -68,6 +75,7 @@ export interface ContextEditorActions {
68
75
  getProposedMessages: () => ContextEditorMessage[];
69
76
  }
70
77
  export type ContextEditorStore = ContextEditorState & ContextEditorActions;
78
+ export declare function findPairedAssistantIndices(messages: readonly ContextEditorMessage[], userIndex: number): number[];
71
79
  export declare const useContextEditorStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ContextEditorStore>>;
72
80
  export {};
73
81
  //# sourceMappingURL=context-editor-store.d.ts.map
@@ -0,0 +1,67 @@
1
+ export type CouncilVoteStatus = 'valid' | 'invalid' | 'failed' | 'cancelled';
2
+ /** One seat's observable vote. No hidden chain-of-thought is retained. */
3
+ export interface CouncilSeatVote {
4
+ seatId: string;
5
+ persona: string;
6
+ status: CouncilVoteStatus | string;
7
+ /** The option this seat voted for, on an option-bearing question. */
8
+ optionId?: string | undefined;
9
+ /** Free-text stance / rationale — only present when trace content is 'full'. */
10
+ stance?: string | undefined;
11
+ rationale?: string | undefined;
12
+ providerId?: string | undefined;
13
+ model?: string | undefined;
14
+ veto?: boolean | undefined;
15
+ weight?: number | undefined;
16
+ durationMs?: number | undefined;
17
+ error?: string | undefined;
18
+ at: number;
19
+ }
20
+ export interface CouncilPanelEntry {
21
+ requestId: string;
22
+ /** `voting` until the resolution lands; a failed council can stay here. */
23
+ phase: 'voting' | 'resolved';
24
+ startedAt: number;
25
+ resolvedAt?: number | undefined;
26
+ seats: CouncilSeatVote[];
27
+ /** Folded in from the matching `brain.decision_*` event, when it arrives. */
28
+ question?: string | undefined;
29
+ status?: string | undefined;
30
+ resolution?: string | undefined;
31
+ optionId?: string | undefined;
32
+ reason?: string | undefined;
33
+ configuredSeatCount?: number | undefined;
34
+ validVoteCount?: number | undefined;
35
+ /** Distinct provider/model targets that served the valid votes. */
36
+ distinctTargetCount?: number | undefined;
37
+ judgeUsed?: boolean | undefined;
38
+ totalTokens?: number | undefined;
39
+ durationMs?: number | undefined;
40
+ /** Structural warnings — most importantly a CORRELATED (non-diverse) panel. */
41
+ warnings?: string[] | undefined;
42
+ }
43
+ /** Newest-first ring buffer bound. */
44
+ export declare const MAX_COUNCIL_PANELS = 50;
45
+ interface CouncilLogState {
46
+ /** Newest first. */
47
+ panels: CouncilPanelEntry[];
48
+ recordVote: (payload: Record<string, unknown>) => void;
49
+ recordResolution: (payload: Record<string, unknown>) => void;
50
+ noteQuestion: (requestId: string, question: string) => void;
51
+ clear: () => void;
52
+ }
53
+ export declare function toCouncilSeatVote(payload: Record<string, unknown>, now: number): CouncilSeatVote;
54
+ /**
55
+ * One-line panel summary.
56
+ *
57
+ * `distinctTargetCount` sits next to the seat count deliberately: a panel whose
58
+ * seats all resolved to the SAME model produces a perfectly normal-looking
59
+ * unanimous verdict while adding cost without adding independence, and nothing
60
+ * else on the row reveals it.
61
+ */
62
+ export declare function summarizeCouncilPanel(entry: CouncilPanelEntry): string;
63
+ /** True when the panel resolved to a refusal, denial or non-verdict. */
64
+ export declare function isCouncilPanelAdverse(entry: CouncilPanelEntry): boolean;
65
+ export declare const useCouncilLogStore: import("zustand").UseBoundStore<import("zustand").StoreApi<CouncilLogState>>;
66
+ export {};
67
+ //# sourceMappingURL=council-log-store.d.ts.map
@@ -0,0 +1,30 @@
1
+ export interface FallbackCandidate {
2
+ providerId: string;
3
+ model: string;
4
+ }
5
+ export interface FallbackPendingState {
6
+ requestId: string;
7
+ from: {
8
+ providerId: string;
9
+ model: string;
10
+ };
11
+ status: number;
12
+ candidates: FallbackCandidate[];
13
+ autoSwitchSeconds: number;
14
+ timestamp: number;
15
+ }
16
+ interface FallbackStore {
17
+ pending: FallbackPendingState | null;
18
+ selected: number;
19
+ /** Set the pending state from a WS event. */
20
+ setPending: (state: FallbackPendingState) => void;
21
+ /** Clear the pending state (switch happened or dismissed). */
22
+ clear: () => void;
23
+ /** Move the selection index (wraps). */
24
+ move: (delta: number) => void;
25
+ /** Set selection to a specific index. */
26
+ setSelected: (index: number) => void;
27
+ }
28
+ export declare const useFallbackStore: import("zustand").UseBoundStore<import("zustand").StoreApi<FallbackStore>>;
29
+ export {};
30
+ //# sourceMappingURL=fallback-store.d.ts.map
@@ -10,6 +10,13 @@ interface FleetState {
10
10
  /** Current / max concurrency from server. */
11
11
  fleetConcurrency: number;
12
12
  fleetConcurrencyMax: number;
13
+ /** Lifetime spawn budget from server (issue #323). Undefined until first budget frame. */
14
+ fleetMaxSpawns: number | undefined;
15
+ fleetUsedSpawns: number | undefined;
16
+ fleetRemainingSpawns: number | undefined;
17
+ fleetBudgetSource: string | undefined;
18
+ fleetCheckpointMaxSpawns: number | undefined;
19
+ fleetCeilingMismatch: boolean;
13
20
  /** Last 20 fleet events for the Fleet Monitor timeline. */
14
21
  eventTimeline: FleetTimelineEvent[];
15
22
  /** Agent conversation timeline entries (agent.timeline.message + agent.status_changed). */
@@ -38,6 +45,12 @@ export interface FleetSummary {
38
45
  tokensOut: number;
39
46
  concurrency: number;
40
47
  concurrencyMax: number;
48
+ maxSpawns?: number | undefined;
49
+ usedSpawns?: number | undefined;
50
+ remainingSpawns?: number | undefined;
51
+ budgetSource?: string | undefined;
52
+ ceilingMismatch?: boolean | undefined;
53
+ checkpointMaxSpawns?: number | undefined;
41
54
  }
42
55
  /** Shallow comparison for zustand selector equality checks.
43
56
  * Compares own enumerable string-keyed properties by reference.
@@ -29,6 +29,8 @@ export type { ClientCounts, CurrentSessionStats, MailActivity } from './monitor-
29
29
  export { useMonitorStore } from './monitor-store.js';
30
30
  export { type BackgroundStyle, useOfficeMapStore } from './office-map-store.js';
31
31
  export { type ProviderHealthEntry, type ProviderHealthState, useProviderStatusStore, } from './provider-status-store.js';
32
+ export { useFallbackStore } from './fallback-store.js';
33
+ export type { FallbackCandidate, FallbackPendingState } from './fallback-store.js';
32
34
  export { type SddBoardFeedEntry, type SddBoardSnapshotUI, type SddBoardStatus, type SddBoardSummary, type SddLifecycleResultUI, useSddBoardStore, } from './sdd-board-store.js';
33
35
  export { type SddWizardPhase, type SddWizardSnapshot, useSddWizardStore, } from './sdd-wizard-store.js';
34
36
  export { useSessionStore } from './session-store.js';
@@ -36,8 +38,10 @@ export { type SideEffectEntry, useSideEffectStore } from './side-effect-store.js
36
38
  export { type BoardTaskItem, type BoardTaskStatus, type SpecColumn, type SpecDetail, type SpecListItem, useSpecsStore, } from './specs-store.js';
37
39
  export { type TechStackCoverage, type TechStackDependency, type TechStackEvidence, type TechStackFinding, type TechStackFindingAction, type TechStackFindingSeverity, type TechStackFindingType, type TechStackJobKind, type TechStackJobStatus, type TechStackJobView, type TechStackProgress, type TechStackSnapshot, type TechStackWorkspace, useTechStackStore, } from './techstack-store.js';
38
40
  export type { AgentTranscriptEntry, AgentTranscriptKind, ChatMessage, FleetTimelineEvent, MessageContent, SessionHistoryEntry, SessionInfo, SubagentEvent, SubagentView, ToolExecution, } from './types.js';
39
- export type { Activity, DockSection, WorkDashboardTab } from './ui-store.js';
41
+ export type { Activity, DockSection, InspectorTab, WorkDashboardTab } from './ui-store.js';
40
42
  export { coerceActivity, resetUiNavigationToHome, SIDEBAR_DEFAULT_WIDTH, SIDEBAR_MAX_WIDTH, SIDEBAR_MIN_WIDTH, useUIStore, } from './ui-store.js';
43
+ export type { CouncilPanelEntry, CouncilSeatVote } from './council-log-store.js';
44
+ export { isCouncilPanelAdverse, MAX_COUNCIL_PANELS, summarizeCouncilPanel, toCouncilSeatVote, useCouncilLogStore, } from './council-log-store.js';
41
45
  export type { VizEdge, VizEvent, VizNode } from './viz-store.js';
42
46
  export { useVizStore } from './viz-store.js';
43
47
  export { useWorktreeStore } from './worktree-store.js';
@@ -96,6 +96,10 @@ export interface LocalPrefs {
96
96
  showThinkingLogs: boolean;
97
97
  /** Group consecutive tool calls into collapsible chips */
98
98
  groupToolCalls: boolean;
99
+ /** Auto-collapse the chat input under the history when a session with
100
+ * messages loads (opt-in; off by default). When off, the input always
101
+ * starts expanded. Independent of the manual collapse/expand buttons. */
102
+ autoCollapseInput: boolean;
99
103
  /** Show model reasoning/thinking blocks inline in the chat */
100
104
  showModelReasoning: boolean;
101
105
  /** Agent swarm panel placement: bottom, sidebar, or off */
@@ -71,6 +71,8 @@ interface MailboxState {
71
71
  setMessages: (messages: MailboxMessage[]) => void;
72
72
  setAgents: (agents: MailboxAgent[]) => void;
73
73
  setLastCompaction: (result: MailboxCompactionResult | null) => void;
74
+ /** Drop one agent by id (mailbox.agent_deregistered push). */
75
+ removeAgent: (agentId: string) => void;
74
76
  }
75
77
  export declare const useMailboxStore: import("zustand").UseBoundStore<import("zustand").StoreApi<MailboxState>>;
76
78
  /** Incomplete messages where no agent has acted yet (readByCount === 0).
@@ -0,0 +1,51 @@
1
+ interface InspectEvent {
2
+ ts: string;
3
+ type: string;
4
+ label: string;
5
+ detail: string;
6
+ }
7
+ interface InspectFileEntry {
8
+ operation: string;
9
+ filePath: string;
10
+ toolName: string;
11
+ ts: string;
12
+ }
13
+ export interface SessionInspectData {
14
+ id: string;
15
+ title: string;
16
+ name?: string | undefined;
17
+ model: string;
18
+ provider: string;
19
+ startedAt: string;
20
+ endedAt?: string | undefined;
21
+ tokenTotal: number;
22
+ outcome?: 'completed' | 'error' | 'timeout' | 'aborted' | undefined;
23
+ messageCount: number;
24
+ iterationCount: number;
25
+ toolCallCount: number;
26
+ toolErrorCount: number;
27
+ fileChangeCount: number;
28
+ compactionCount: number;
29
+ toolBreakdown: Record<string, number>;
30
+ events: InspectEvent[];
31
+ fileEvents: InspectFileEntry[];
32
+ lastUserMessage?: string | undefined;
33
+ }
34
+ interface SessionInspectState {
35
+ payload: SessionInspectData | null;
36
+ loading: boolean;
37
+ error: string | null;
38
+ setPayload: (payload: SessionInspectData) => void;
39
+ setError: (error: string) => void;
40
+ setLoading: (loading: boolean) => void;
41
+ clear: () => void;
42
+ }
43
+ export declare const useSessionInspectStore: import("zustand").UseBoundStore<import("zustand").StoreApi<SessionInspectState>>;
44
+ /**
45
+ * Idempotently registers a WS handler for `session.inspect` responses.
46
+ * Safe to call multiple times — only the first call installs the handler.
47
+ * The handler updates the Zustand store with the response payload.
48
+ */
49
+ export declare function ensureInspectHandlerInstalled(): void;
50
+ export {};
51
+ //# sourceMappingURL=session-inspect-store.d.ts.map
@@ -4,7 +4,7 @@ export type Activity = 'chat' | 'agents' | 'files' | 'changes' | 'mailbox' | 'sk
4
4
  /** Map any persisted (possibly legacy) activity value onto the current set. */
5
5
  export declare function coerceActivity(value: unknown): Activity;
6
6
  /** All valid currentView values. Kept in sync with the union on UIState. */
7
- declare const VIEWS: readonly ['chat', 'settings', 'memory', 'roster', 'context', 'goal', 'kanban', 'sddhub', 'files', 'changes', 'sessions', 'setup', 'skill', 'officemap', 'mailbox', 'debug', 'design-gallery', 'refresh-debug', 'analytics', 'codemap', 'techstack', 'chronicle', 'deadcode'];
7
+ declare const VIEWS: readonly ['chat', 'settings', 'memory', 'roster', 'context', 'goal', 'kanban', 'sddhub', 'files', 'changes', 'sessions', 'session-inspect', 'setup', 'skill', 'officemap', 'mailbox', 'debug', 'design-gallery', 'refresh-debug', 'analytics', 'codemap', 'techstack', 'chronicle', 'intake', 'deadcode'];
8
8
  type View = (typeof VIEWS)[number];
9
9
  /** Coerce an arbitrary value onto the current view union. Used by migrate
10
10
  * when reading from localStorage so a stale value (e.g. 'context', a view
@@ -17,6 +17,14 @@ export declare const SIDEBAR_DEFAULT_WIDTH = 304;
17
17
  /** Sections of the WorkspaceDock strip above the chat transcript. */
18
18
  export type DockSection = 'goal' | 'goal-state' | 'fleet' | 'work' | 'worktrees' | 'collab';
19
19
  export type WorkDashboardTab = 'todos' | 'tasks' | 'plan';
20
+ /**
21
+ * Tabs of the global right inspector drawer.
22
+ *
23
+ * `council` is the live Brain council panel log — the most expensive Brain
24
+ * tier (one provider call per seat) and, until it got a tab, the only one with
25
+ * no observable surface at all.
26
+ */
27
+ export type InspectorTab = 'fleet' | 'agents' | 'sideEffects' | 'council';
20
28
  interface UIState {
21
29
  sidebarOpen: boolean;
22
30
  /** Which activity icon is selected in the ActivityBar — controls secondary panel content. */
@@ -74,7 +82,7 @@ interface UIState {
74
82
  /** Global right inspector drawer open (non-modal overlay on desktop). */
75
83
  inspectorOpen: boolean;
76
84
  /** Active tab inside the global right inspector drawer. */
77
- inspectorTab: 'fleet' | 'agents' | 'sideEffects';
85
+ inspectorTab: InspectorTab;
78
86
  /** Agent ID to focus when opening the inspector on the agents tab. Cleared on read. */
79
87
  inspectorFocusedAgentId: string | null;
80
88
  /** Process Monitor overlay — triggered by /kill slash command. */
@@ -83,6 +91,8 @@ interface UIState {
83
91
  queuePanelOpen: boolean;
84
92
  /** Cron Jobs overlay — triggered by /cron slash command. */
85
93
  cronJobsOpen: boolean;
94
+ /** Session ID currently being inspected (session-inspect view). */
95
+ inspectSessionId: string | null;
86
96
  /** Integrated terminal bottom-dock — toggled by Ctrl+` or /terminal. */
87
97
  terminalOpen: boolean;
88
98
  /** Monotonic signal consumed by TerminalPanel to create another PTY tab. */
@@ -98,6 +108,8 @@ interface UIState {
98
108
  setProcessMonitorOpen: (open: boolean) => void;
99
109
  setQueuePanelOpen: (open: boolean) => void;
100
110
  setCronJobsOpen: (open: boolean) => void;
111
+ setInspectSession: (id: string) => void;
112
+ clearInspectSession: () => void;
101
113
  setTerminalOpen: (open: boolean) => void;
102
114
  toggleTerminal: () => void;
103
115
  requestTerminalCreate: () => void;
@@ -224,7 +236,7 @@ interface UIState {
224
236
  setFleetMonitorOpen: (open: boolean) => void;
225
237
  setAgentsMonitorOpen: (open: boolean) => void;
226
238
  setInspectorOpen: (open: boolean) => void;
227
- setInspectorTab: (tab: 'fleet' | 'agents' | 'sideEffects') => void;
239
+ setInspectorTab: (tab: InspectorTab) => void;
228
240
  setInspectorFocusedAgentId: (id: string | null) => void;
229
241
  toggleInspector: () => void;
230
242
  }
@@ -246,7 +258,7 @@ export declare const useUIStore: import("zustand").UseBoundStore<Omit<import("zu
246
258
  hiddenChips: DockSection[];
247
259
  workDashboardTab: WorkDashboardTab;
248
260
  inspectorOpen: boolean;
249
- inspectorTab: "agents" | "fleet" | "sideEffects";
261
+ inspectorTab: InspectorTab;
250
262
  skillsState: {
251
263
  /** The skill currently shown in the detail pane. */
252
264
  selectedSkill: {
@@ -281,7 +293,7 @@ export declare const useUIStore: import("zustand").UseBoundStore<Omit<import("zu
281
293
  /** Number of installed skills with a newer ref available than knownRefs. */
282
294
  updateAvailableCount: number;
283
295
  };
284
- currentView: "analytics" | "changes" | "chat" | "chronicle" | "codemap" | "context" | "deadcode" | "debug" | "design-gallery" | "files" | "goal" | "kanban" | "mailbox" | "memory" | "officemap" | "refresh-debug" | "roster" | "sddhub" | "sessions" | "settings" | "setup" | "skill" | "techstack";
296
+ currentView: "analytics" | "changes" | "chat" | "chronicle" | "codemap" | "context" | "deadcode" | "debug" | "design-gallery" | "files" | "goal" | "intake" | "kanban" | "mailbox" | "memory" | "officemap" | "refresh-debug" | "roster" | "sddhub" | "session-inspect" | "sessions" | "settings" | "setup" | "skill" | "techstack";
285
297
  dockSection: DockSection | null;
286
298
  settingsActiveTab: string;
287
299
  scrollPositions: Record<string, number>;
@@ -306,7 +318,7 @@ export declare const useUIStore: import("zustand").UseBoundStore<Omit<import("zu
306
318
  hiddenChips: DockSection[];
307
319
  workDashboardTab: WorkDashboardTab;
308
320
  inspectorOpen: boolean;
309
- inspectorTab: "agents" | "fleet" | "sideEffects";
321
+ inspectorTab: InspectorTab;
310
322
  skillsState: {
311
323
  /** The skill currently shown in the detail pane. */
312
324
  selectedSkill: {
@@ -341,7 +353,7 @@ export declare const useUIStore: import("zustand").UseBoundStore<Omit<import("zu
341
353
  /** Number of installed skills with a newer ref available than knownRefs. */
342
354
  updateAvailableCount: number;
343
355
  };
344
- currentView: "analytics" | "changes" | "chat" | "chronicle" | "codemap" | "context" | "deadcode" | "debug" | "design-gallery" | "files" | "goal" | "kanban" | "mailbox" | "memory" | "officemap" | "refresh-debug" | "roster" | "sddhub" | "sessions" | "settings" | "setup" | "skill" | "techstack";
356
+ currentView: "analytics" | "changes" | "chat" | "chronicle" | "codemap" | "context" | "deadcode" | "debug" | "design-gallery" | "files" | "goal" | "intake" | "kanban" | "mailbox" | "memory" | "officemap" | "refresh-debug" | "roster" | "sddhub" | "session-inspect" | "sessions" | "settings" | "setup" | "skill" | "techstack";
345
357
  dockSection: DockSection | null;
346
358
  settingsActiveTab: string;
347
359
  scrollPositions: Record<string, number>;
@@ -6,7 +6,7 @@
6
6
  * Every event is typed with a `vizKind` for the renderer to pattern-match on.
7
7
  */
8
8
  /** Categories the cinematic renderer understands. */
9
- export type VizEventKind = 'provider:call' | 'provider:delta' | 'provider:response' | 'agent:spawned' | 'agent:tool' | 'agent:status' | 'agent:ctx' | 'agent:text' | 'tool:started' | 'tool:executed' | 'tool:progress' | 'mailbox:send' | 'mailbox:deliver' | 'collab:event' | 'memory:event' | 'session:start' | 'session:end' | 'iteration:start' | 'iteration:end' | 'eternal:iteration' | 'error' | 'context:compacted' | 'context:repaired' | 'budget:warning' | 'budget:extended' | 'cost:update' | 'fleet:snapshot';
9
+ export type VizEventKind = 'provider:call' | 'provider:delta' | 'provider:response' | 'agent:spawned' | 'agent:tool' | 'agent:status' | 'agent:ctx' | 'agent:text' | 'tool:started' | 'tool:executed' | 'tool:progress' | 'mailbox:send' | 'mailbox:deliver' | 'collab:event' | 'memory:event' | 'brain:council_vote' | 'session:start' | 'session:end' | 'iteration:start' | 'iteration:end' | 'eternal:iteration' | 'error' | 'context:compacted' | 'context:repaired' | 'budget:warning' | 'budget:extended' | 'cost:update' | 'fleet:snapshot';
10
10
  export interface VizEvent {
11
11
  id: string;
12
12
  kind: VizEventKind;
@@ -134,6 +134,14 @@ export interface BrainCouncilSeatWire {
134
134
  persona: string;
135
135
  veto?: boolean | undefined;
136
136
  }
137
+ /** One selectable Council decision lens, published from the server's registry. */
138
+ export interface BrainCouncilPersonaWire {
139
+ id: string;
140
+ name: string;
141
+ description: string;
142
+ /** Seats using this lens get veto power unless the seat overrides it. */
143
+ defaultVeto?: boolean | undefined;
144
+ }
137
145
  /** Headless escalation variant. */
138
146
  export type BrainTerminalPolicyWire = 'conservative' | 'deny-all' | 'continue-on-recommended';
139
147
  /** JSON-safe snapshot of the live Brain config (mirrors core's BrainConfigSnapshot). */
@@ -159,6 +167,13 @@ export interface BrainConfigWire {
159
167
  judgeMaxTokens?: number | undefined;
160
168
  seats: BrainCouncilSeatWire[];
161
169
  };
170
+ /**
171
+ * Decision lenses the server's Council persona registry offers. Optional so
172
+ * an older server still renders: the section then falls back to the three
173
+ * lenses it used to hard-code, which is what hid `security`, `maintainer`
174
+ * and `user-advocate` from every surface.
175
+ */
176
+ personaCatalog?: BrainCouncilPersonaWire[] | undefined;
162
177
  ledger: {
163
178
  enabled: boolean;
164
179
  autoDenyAfterFailures?: number | undefined;
@@ -2,7 +2,7 @@ import type { BrainConfigPatchWire } from './brain.js';
2
2
  import type { ChronicleFacet, ChronicleMetricsView, ChronicleQuery } from './chronicle.js';
3
3
  import type { WSCollabAnnotate, WSCollabGrantControl, WSCollabInjectTool, WSCollabJoin, WSCollabLeave, WSCollabRequestPause, WSCollabResolve, WSCollabResume } from './collab.js';
4
4
  import type { SessionScopedPayload, WSUserMessage } from './protocol-core.js';
5
- import type { ContextEditorMessage, WSModelSwitch, WSToolConfirmResult } from './runtime.js';
5
+ import type { ContextEditorMessage, ContextEditorRemoval, WSModelSwitch, WSToolConfirmResult } from './runtime.js';
6
6
  import type { SageAnchor, SageScope, SageStatus, WSMemorySageForFileRequest } from './sage.js';
7
7
  import type { OAuthKind, WSCompletionRequest } from './system.js';
8
8
  /** Metadata persisted by the custom-provider model editor in provider add/update messages. */
@@ -332,6 +332,11 @@ export type WSClientMessageCore = WSUserMessage | WSToolConfirmResult | {
332
332
  payload: {
333
333
  id: string;
334
334
  } & SessionScopedPayload;
335
+ } | {
336
+ type: 'session.inspect';
337
+ payload: {
338
+ id: string;
339
+ };
335
340
  } | {
336
341
  type: 'session.new';
337
342
  payload?: SessionScopedPayload;
@@ -365,6 +370,7 @@ export type WSClientMessageCore = WSUserMessage | WSToolConfirmResult | {
365
370
  payload: SessionScopedPayload & {
366
371
  baseRevision: string;
367
372
  messages: ContextEditorMessage[];
373
+ removals: ContextEditorRemoval[];
368
374
  allowRepair: boolean;
369
375
  };
370
376
  } | {
@@ -372,6 +378,7 @@ export type WSClientMessageCore = WSUserMessage | WSToolConfirmResult | {
372
378
  payload: SessionScopedPayload & {
373
379
  baseRevision: string;
374
380
  messages: ContextEditorMessage[];
381
+ removals: ContextEditorRemoval[];
375
382
  allowRepair: boolean;
376
383
  };
377
384
  } | {
@@ -1185,6 +1192,15 @@ export type WSClientMessageCore = WSUserMessage | WSToolConfirmResult | {
1185
1192
  payload: {
1186
1193
  template: string;
1187
1194
  };
1195
+ } | {
1196
+ type: 'model.fallback_choice';
1197
+ payload: {
1198
+ requestId: string;
1199
+ providerId?: string | undefined;
1200
+ model?: string | undefined;
1201
+ /** When true, auto-switch to the next candidate (countdown expired or Esc). */
1202
+ autoSwitch?: boolean | undefined;
1203
+ };
1188
1204
  } | {
1189
1205
  type: 'webui.shutdown';
1190
1206
  };
@@ -238,6 +238,25 @@ export interface WSProviderFallback {
238
238
  };
239
239
  status: number;
240
240
  providerSwitched: boolean;
241
+ /** Gate correlation id — present when a fallback gate mediated the switch. */
242
+ requestId?: string | undefined;
243
+ };
244
+ }
245
+ export interface WSProviderFallbackPending {
246
+ type: 'provider.fallback_pending';
247
+ payload: SessionScopedPayload & {
248
+ from: {
249
+ providerId: string;
250
+ model: string;
251
+ };
252
+ status: number;
253
+ candidates: Array<{
254
+ providerId: string;
255
+ model: string;
256
+ }>;
257
+ autoSwitchSeconds: number;
258
+ requestId: string;
259
+ timestamp: number;
241
260
  };
242
261
  }
243
262
  export interface WSProviderStatusChanged {