@heretek-ai/epistemic-swarm 1.1.0 → 1.1.3

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.
package/dist/tui.js CHANGED
@@ -4,6 +4,7 @@ import { userInfo } from "os";
4
4
  import { Plugin } from "@opencode/plugin/tui";
5
5
 
6
6
  // src/panels.tsx
7
+ import { mergeProps as _$mergeProps } from "@opentui/solid";
7
8
  import { memo as _$memo } from "@opentui/solid";
8
9
  import { createComponent as _$createComponent } from "@opentui/solid";
9
10
  import { createTextNode as _$createTextNode } from "@opentui/solid";
@@ -13,11 +14,12 @@ import { setProp as _$setProp } from "@opentui/solid";
13
14
  import { createElement as _$createElement } from "@opentui/solid";
14
15
  import { createResource, createSignal, For, onCleanup, Show } from "solid-js";
15
16
  var PANEL_REFRESH_MS = 2000;
16
- function usePanelState(props, method) {
17
+ var FOOTER_REFRESH_MS = 5000;
18
+ function usePanelState(props, method, everyMs = PANEL_REFRESH_MS) {
17
19
  const [version, setVersion] = createSignal(0);
18
20
  const bump = () => setVersion((value) => value + 1);
19
21
  const unsubscribe = props.subscribe(bump);
20
- const timer = setInterval(bump, PANEL_REFRESH_MS);
22
+ const timer = setInterval(bump, everyMs);
21
23
  onCleanup(() => {
22
24
  unsubscribe();
23
25
  clearInterval(timer);
@@ -29,17 +31,40 @@ function usePanelState(props, method) {
29
31
  })));
30
32
  return {
31
33
  data: () => state.latest?.data,
32
- error: () => state.latest?.error
34
+ error: () => state.latest?.error,
35
+ refresh: bump
33
36
  };
34
37
  }
38
+ function usePanelKeys(props, refresh) {
39
+ const panel = props.panel;
40
+ if (!panel || !props.layer)
41
+ return;
42
+ props.layer(() => ({
43
+ commands: [{
44
+ title: "close",
45
+ bind: "escape,q",
46
+ run: () => panel.close()
47
+ }, {
48
+ title: "fullscreen",
49
+ bind: "f",
50
+ run: () => panel.toggleFullscreen()
51
+ }, {
52
+ title: "refresh",
53
+ bind: "r",
54
+ run: refresh
55
+ }]
56
+ }));
57
+ }
35
58
  var Frame = (props) => (() => {
36
- var _el$ = _$createElement("box"), _el$2 = _$createElement("text");
59
+ var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("text");
37
60
  _$insertNode(_el$, _el$2);
61
+ _$insertNode(_el$, _el$3);
38
62
  _$setProp(_el$, "flexDirection", "column");
39
63
  _$setProp(_el$, "padding", 1);
40
64
  _$setProp(_el$, "gap", 1);
41
65
  _$insert(_el$2, () => props.title);
42
- _$insert(_el$, () => props.children, null);
66
+ _$insert(_el$, () => props.children, _el$3);
67
+ _$insertNode(_el$3, _$createTextNode(`esc/q close \xB7 f fullscreen \xB7 r refresh`));
43
68
  return _el$;
44
69
  })();
45
70
  var Failed = (props) => _$createComponent(Show, {
@@ -47,14 +72,15 @@ var Failed = (props) => _$createComponent(Show, {
47
72
  return props.error();
48
73
  },
49
74
  get children() {
50
- var _el$3 = _$createElement("text"), _el$4 = _$createTextNode(`Could not load: `);
51
- _$insertNode(_el$3, _el$4);
52
- _$insert(_el$3, () => props.error(), null);
53
- return _el$3;
75
+ var _el$5 = _$createElement("text"), _el$6 = _$createTextNode(`Could not load: `);
76
+ _$insertNode(_el$5, _el$6);
77
+ _$insert(_el$5, () => props.error(), null);
78
+ return _el$5;
54
79
  }
55
80
  });
56
81
  var FactoryPanel = (props) => {
57
82
  const state = usePanelState(props, "factoryState");
83
+ usePanelKeys(props, state.refresh);
58
84
  return _$createComponent(Frame, {
59
85
  title: "Factory dashboard",
60
86
  get children() {
@@ -68,134 +94,229 @@ var FactoryPanel = (props) => {
68
94
  },
69
95
  get fallback() {
70
96
  return (() => {
71
- var _el$5 = _$createElement("text");
72
- _$insert(_el$5, () => state.error() ? "" : "Loading factory state\u2026");
73
- return _el$5;
97
+ var _el$7 = _$createElement("text");
98
+ _$insert(_el$7, () => state.error() ? "" : "Loading factory state\u2026");
99
+ return _el$7;
74
100
  })();
75
101
  },
76
102
  children: (data) => [(() => {
77
- var _el$6 = _$createElement("text"), _el$7 = _$createTextNode(`Stage: `);
78
- _$insertNode(_el$6, _el$7);
79
- _$insert(_el$6, () => data().stage, null);
80
- _$insert(_el$6, (() => {
81
- var _c$ = _$memo(() => !!data().runId);
82
- return () => _c$() ? ` \xB7 ${data().runId}` : "";
83
- })(), null);
84
- return _el$6;
85
- })(), (() => {
86
- var _el$8 = _$createElement("text"), _el$9 = _$createTextNode(`Spend: $`);
87
- _$insertNode(_el$8, _el$9);
88
- _$insert(_el$8, () => data().spend.usd.toFixed(2), null);
89
- _$insert(_el$8, (() => {
90
- var _c$2 = _$memo(() => !!data().spend.ceilingUSD);
91
- return () => _c$2() ? ` / $${data().spend.ceilingUSD}` : "";
92
- })(), null);
93
- _$insert(_el$8, () => data().spend.estimated ? " (estimated)" : "", null);
103
+ var _el$8 = _$createElement("text");
104
+ _$insert(_el$8, () => data().headline);
94
105
  return _el$8;
95
106
  })(), _$createComponent(Show, {
96
107
  get when() {
97
- return data().tree;
108
+ return data().header;
109
+ },
110
+ get fallback() {
111
+ return (() => {
112
+ var _el$41 = _$createElement("text"), _el$42 = _$createTextNode(`Stage: `);
113
+ _$insertNode(_el$41, _el$42);
114
+ _$insert(_el$41, () => data().stage, null);
115
+ return _el$41;
116
+ })();
98
117
  },
99
118
  get children() {
100
- var _el$0 = _$createElement("text"), _el$1 = _$createTextNode(`Design tree (round `), _el$10 = _$createTextNode(`): `), _el$11 = _$createTextNode(` settled \xB7 `), _el$12 = _$createTextNode(` open \xB7 `), _el$14 = _$createTextNode(` deferred`);
119
+ var _el$9 = _$createElement("text");
120
+ _$insert(_el$9, () => data().header);
121
+ return _el$9;
122
+ }
123
+ }), _$createComponent(Show, {
124
+ get when() {
125
+ return data().stage !== "NONE";
126
+ },
127
+ get children() {
128
+ var _el$0 = _$createElement("text"), _el$1 = _$createTextNode(`Spend: $`);
101
129
  _$insertNode(_el$0, _el$1);
102
- _$insertNode(_el$0, _el$10);
103
- _$insertNode(_el$0, _el$11);
104
- _$insertNode(_el$0, _el$12);
105
- _$insertNode(_el$0, _el$14);
106
- _$insert(_el$0, () => data().tree.round, _el$10);
107
- _$insert(_el$0, () => data().tree.settled, _el$11);
108
- _$insert(_el$0, () => data().tree.open, _el$12);
109
- _$insert(_el$0, () => data().tree.deferred, _el$14);
130
+ _$insert(_el$0, () => data().spend.usd.toFixed(2), null);
110
131
  _$insert(_el$0, (() => {
111
- var _c$3 = _$memo(() => !!data().tree.facts);
112
- return () => _c$3() ? ` (${data().tree.facts} for research)` : "";
132
+ var _c$ = _$memo(() => !!data().spend.ceilingUSD);
133
+ return () => _c$() ? ` / $${data().spend.ceilingUSD}` : "";
113
134
  })(), null);
135
+ _$insert(_el$0, () => data().spend.estimated ? " (estimated)" : "", null);
114
136
  return _el$0;
115
137
  }
116
138
  }), _$createComponent(Show, {
117
139
  get when() {
118
- return data().halt;
140
+ return data().tree;
119
141
  },
120
142
  get children() {
121
- var _el$15 = _$createElement("text"), _el$16 = _$createTextNode(`HALTED: `);
122
- _$insertNode(_el$15, _el$16);
123
- _$insert(_el$15, () => data().halt, null);
124
- return _el$15;
143
+ var _el$10 = _$createElement("text"), _el$11 = _$createTextNode(`Design tree (round `), _el$12 = _$createTextNode(`): `), _el$13 = _$createTextNode(` settled \xB7 `), _el$14 = _$createTextNode(` open \xB7 `), _el$16 = _$createTextNode(` deferred`);
144
+ _$insertNode(_el$10, _el$11);
145
+ _$insertNode(_el$10, _el$12);
146
+ _$insertNode(_el$10, _el$13);
147
+ _$insertNode(_el$10, _el$14);
148
+ _$insertNode(_el$10, _el$16);
149
+ _$insert(_el$10, () => data().tree.round, _el$12);
150
+ _$insert(_el$10, () => data().tree.settled, _el$13);
151
+ _$insert(_el$10, () => data().tree.open, _el$14);
152
+ _$insert(_el$10, () => data().tree.deferred, _el$16);
153
+ _$insert(_el$10, (() => {
154
+ var _c$2 = _$memo(() => !!data().tree.facts);
155
+ return () => _c$2() ? ` (${data().tree.facts} for research)` : "";
156
+ })(), null);
157
+ return _el$10;
125
158
  }
126
159
  }), _$createComponent(Show, {
127
160
  get when() {
128
- return data().release;
161
+ return data().paused;
129
162
  },
130
163
  get children() {
131
- var _el$17 = _$createElement("text"), _el$18 = _$createTextNode(`PR: `);
164
+ var _el$17 = _$createElement("text"), _el$18 = _$createTextNode(`\u23F8 `);
132
165
  _$insertNode(_el$17, _el$18);
133
- _$insert(_el$17, () => data().release, null);
166
+ _$insert(_el$17, () => data().paused, null);
134
167
  return _el$17;
135
168
  }
136
169
  }), _$createComponent(Show, {
137
170
  get when() {
138
- return data().pending.length;
171
+ return data().halt;
139
172
  },
140
173
  get children() {
141
- var _el$19 = _$createElement("text"), _el$20 = _$createTextNode(`Waiting on human: `);
174
+ var _el$19 = _$createElement("text"), _el$20 = _$createTextNode(`HALTED: `);
142
175
  _$insertNode(_el$19, _el$20);
143
- _$insert(_el$19, () => data().pending.join(", "), null);
176
+ _$insert(_el$19, () => data().halt, null);
144
177
  return _el$19;
145
178
  }
179
+ }), _$createComponent(Show, {
180
+ get when() {
181
+ return data().pending.length;
182
+ },
183
+ get children() {
184
+ var _el$21 = _$createElement("text"), _el$22 = _$createTextNode(`Waiting on you: approve `), _el$23 = _$createTextNode(`: run \`es approve `), _el$24 = _$createTextNode(`\` in a terminal (/es-approve previews it)`);
185
+ _$insertNode(_el$21, _el$22);
186
+ _$insertNode(_el$21, _el$23);
187
+ _$insertNode(_el$21, _el$24);
188
+ _$insert(_el$21, () => data().pending.join(", "), _el$23);
189
+ _$insert(_el$21, () => data().pending[0], _el$24);
190
+ return _el$21;
191
+ }
192
+ }), _$createComponent(Show, {
193
+ get when() {
194
+ return data().seats.length;
195
+ },
196
+ get children() {
197
+ var _el$25 = _$createElement("box"), _el$26 = _$createElement("text");
198
+ _$insertNode(_el$25, _el$26);
199
+ _$setProp(_el$25, "flexDirection", "column");
200
+ _$insertNode(_el$26, _$createTextNode(`Seats:`));
201
+ _$insert(_el$25, _$createComponent(For, {
202
+ get each() {
203
+ return data().seats;
204
+ },
205
+ children: (line) => (() => {
206
+ var _el$43 = _$createElement("text");
207
+ _$insert(_el$43, ` ${line}`);
208
+ return _el$43;
209
+ })()
210
+ }), null);
211
+ return _el$25;
212
+ }
213
+ }), _$createComponent(Show, {
214
+ get when() {
215
+ return data().research;
216
+ },
217
+ get children() {
218
+ var _el$28 = _$createElement("text"), _el$29 = _$createTextNode(`Research: `);
219
+ _$insertNode(_el$28, _el$29);
220
+ _$insert(_el$28, () => data().research, null);
221
+ return _el$28;
222
+ }
223
+ }), _$createComponent(Show, {
224
+ get when() {
225
+ return data().phases.length;
226
+ },
227
+ get children() {
228
+ var _el$30 = _$createElement("box"), _el$31 = _$createElement("text");
229
+ _$insertNode(_el$30, _el$31);
230
+ _$setProp(_el$30, "flexDirection", "column");
231
+ _$insertNode(_el$31, _$createTextNode(`Phases:`));
232
+ _$insert(_el$30, _$createComponent(For, {
233
+ get each() {
234
+ return data().phases;
235
+ },
236
+ children: (phase) => (() => {
237
+ var _el$44 = _$createElement("text"), _el$45 = _$createTextNode(` \xB7 `), _el$46 = _$createTextNode(` \xB7 failures `);
238
+ _$insertNode(_el$44, _el$45);
239
+ _$insertNode(_el$44, _el$46);
240
+ _$insert(_el$44, () => phase.id === data().activePhase ? "\u25B6 " : " ", _el$45);
241
+ _$insert(_el$44, () => phase.id, _el$45);
242
+ _$insert(_el$44, (() => {
243
+ var _c$3 = _$memo(() => !!phase.title);
244
+ return () => _c$3() ? ` ${phase.title}` : "";
245
+ })(), _el$45);
246
+ _$insert(_el$44, () => phase.status, _el$46);
247
+ _$insert(_el$44, () => phase.failures, null);
248
+ return _el$44;
249
+ })()
250
+ }), null);
251
+ return _el$30;
252
+ }
146
253
  }), _$createComponent(Show, {
147
254
  get when() {
148
255
  return data().audits?.length;
149
256
  },
150
257
  get children() {
151
- return [(() => {
152
- var _el$21 = _$createElement("text");
153
- _$insertNode(_el$21, _$createTextNode(`Audits:`));
154
- return _el$21;
155
- })(), _$createComponent(For, {
258
+ var _el$33 = _$createElement("box"), _el$34 = _$createElement("text");
259
+ _$insertNode(_el$33, _el$34);
260
+ _$setProp(_el$33, "flexDirection", "column");
261
+ _$insertNode(_el$34, _$createTextNode(`Audits:`));
262
+ _$insert(_el$33, _$createComponent(For, {
156
263
  get each() {
157
264
  return data().audits;
158
265
  },
159
266
  children: (audit) => (() => {
160
- var _el$25 = _$createElement("text"), _el$26 = _$createTextNode(` `), _el$27 = _$createTextNode(` \xB7 `), _el$28 = _$createTextNode(` \xB7 `), _el$29 = _$createTextNode(` r`), _el$30 = _$createTextNode(` \xB7 t:`), _el$31 = _$createTextNode(` a:`);
161
- _$insertNode(_el$25, _el$26);
162
- _$insertNode(_el$25, _el$27);
163
- _$insertNode(_el$25, _el$28);
164
- _$insertNode(_el$25, _el$29);
165
- _$insertNode(_el$25, _el$30);
166
- _$insertNode(_el$25, _el$31);
167
- _$insert(_el$25, () => audit.id, _el$27);
168
- _$insert(_el$25, () => audit.target, _el$28);
169
- _$insert(_el$25, () => audit.status, _el$29);
170
- _$insert(_el$25, () => audit.round, _el$30);
171
- _$insert(_el$25, () => audit.thesis, _el$31);
172
- _$insert(_el$25, () => audit.antithesis, null);
173
- _$insert(_el$25, (() => {
267
+ var _el$47 = _$createElement("text"), _el$48 = _$createTextNode(` `), _el$49 = _$createTextNode(` \xB7 `), _el$50 = _$createTextNode(` \xB7 `), _el$51 = _$createTextNode(` r`), _el$52 = _$createTextNode(` \xB7 t:`), _el$53 = _$createTextNode(` a:`);
268
+ _$insertNode(_el$47, _el$48);
269
+ _$insertNode(_el$47, _el$49);
270
+ _$insertNode(_el$47, _el$50);
271
+ _$insertNode(_el$47, _el$51);
272
+ _$insertNode(_el$47, _el$52);
273
+ _$insertNode(_el$47, _el$53);
274
+ _$insert(_el$47, () => audit.id, _el$49);
275
+ _$insert(_el$47, () => audit.target, _el$50);
276
+ _$insert(_el$47, () => audit.status, _el$51);
277
+ _$insert(_el$47, () => audit.round, _el$52);
278
+ _$insert(_el$47, () => audit.thesis, _el$53);
279
+ _$insert(_el$47, () => audit.antithesis, null);
280
+ _$insert(_el$47, (() => {
174
281
  var _c$4 = _$memo(() => !!audit.tiebreak);
175
282
  return () => _c$4() ? ` x:${audit.tiebreak}` : "";
176
283
  })(), null);
177
- return _el$25;
284
+ return _el$47;
178
285
  })()
179
- })];
286
+ }), null);
287
+ return _el$33;
180
288
  }
181
- }), (() => {
182
- var _el$23 = _$createElement("text");
183
- _$insertNode(_el$23, _$createTextNode(`Phases:`));
184
- return _el$23;
185
- })(), _$createComponent(For, {
186
- get each() {
187
- return data().phases;
289
+ }), _$createComponent(Show, {
290
+ get when() {
291
+ return data().events.length;
188
292
  },
189
- children: (phase) => (() => {
190
- var _el$32 = _$createElement("text"), _el$33 = _$createTextNode(` \xB7 `), _el$34 = _$createTextNode(` \xB7 failures `);
191
- _$insertNode(_el$32, _el$33);
192
- _$insertNode(_el$32, _el$34);
193
- _$insert(_el$32, () => phase.id === data().activePhase ? "\u25B6 " : " ", _el$33);
194
- _$insert(_el$32, () => phase.id, _el$33);
195
- _$insert(_el$32, () => phase.status, _el$34);
196
- _$insert(_el$32, () => phase.failures, null);
197
- return _el$32;
198
- })()
293
+ get children() {
294
+ var _el$36 = _$createElement("box"), _el$37 = _$createElement("text");
295
+ _$insertNode(_el$36, _el$37);
296
+ _$setProp(_el$36, "flexDirection", "column");
297
+ _$insertNode(_el$37, _$createTextNode(`Recent events:`));
298
+ _$insert(_el$36, _$createComponent(For, {
299
+ get each() {
300
+ return data().events;
301
+ },
302
+ children: (line) => (() => {
303
+ var _el$54 = _$createElement("text");
304
+ _$insert(_el$54, ` ${line}`);
305
+ return _el$54;
306
+ })()
307
+ }), null);
308
+ return _el$36;
309
+ }
310
+ }), _$createComponent(Show, {
311
+ get when() {
312
+ return data().release;
313
+ },
314
+ get children() {
315
+ var _el$39 = _$createElement("text"), _el$40 = _$createTextNode(`PR: `);
316
+ _$insertNode(_el$39, _el$40);
317
+ _$insert(_el$39, () => data().release, null);
318
+ return _el$39;
319
+ }
199
320
  })]
200
321
  })];
201
322
  }
@@ -203,6 +324,7 @@ var FactoryPanel = (props) => {
203
324
  };
204
325
  var LspPanel = (props) => {
205
326
  const state = usePanelState(props, "lspState");
327
+ usePanelKeys(props, state.refresh);
206
328
  return _$createComponent(Frame, {
207
329
  title: "Language servers",
208
330
  get children() {
@@ -216,43 +338,43 @@ var LspPanel = (props) => {
216
338
  },
217
339
  get fallback() {
218
340
  return (() => {
219
- var _el$35 = _$createElement("text");
220
- _$insert(_el$35, () => state.error() ? "" : "Loading language servers\u2026");
221
- return _el$35;
341
+ var _el$55 = _$createElement("text");
342
+ _$insert(_el$55, () => state.error() ? "" : "Loading language servers\u2026");
343
+ return _el$55;
222
344
  })();
223
345
  },
224
346
  children: (data) => [(() => {
225
- var _el$36 = _$createElement("text");
226
- _$insert(_el$36, () => data().enabled ? "LSP is on." : "LSP is disabled (lsp: false).");
227
- return _el$36;
347
+ var _el$56 = _$createElement("text");
348
+ _$insert(_el$56, () => data().enabled ? "LSP is on." : "LSP is disabled (lsp: false).");
349
+ return _el$56;
228
350
  })(), _$createComponent(For, {
229
351
  get each() {
230
352
  return data().servers;
231
353
  },
232
354
  children: (server) => (() => {
233
- var _el$37 = _$createElement("text"), _el$38 = _$createTextNode(` `), _el$39 = _$createTextNode(` [`), _el$40 = _$createTextNode(`]`);
234
- _$insertNode(_el$37, _el$38);
235
- _$insertNode(_el$37, _el$39);
236
- _$insertNode(_el$37, _el$40);
237
- _$insert(_el$37, () => server.available ? "\u25CF" : "\u25CB", _el$38);
238
- _$insert(_el$37, () => server.id, _el$39);
239
- _$insert(_el$37, () => server.extensions.join(" "), _el$40);
240
- _$insert(_el$37, (() => {
355
+ var _el$57 = _$createElement("text"), _el$58 = _$createTextNode(` `), _el$59 = _$createTextNode(` [`), _el$60 = _$createTextNode(`]`);
356
+ _$insertNode(_el$57, _el$58);
357
+ _$insertNode(_el$57, _el$59);
358
+ _$insertNode(_el$57, _el$60);
359
+ _$insert(_el$57, () => server.available ? "\u25CF" : "\u25CB", _el$58);
360
+ _$insert(_el$57, () => server.id, _el$59);
361
+ _$insert(_el$57, () => server.extensions.join(" "), _el$60);
362
+ _$insert(_el$57, (() => {
241
363
  var _c$5 = _$memo(() => !!server.running);
242
364
  return () => _c$5() ? ` \xB7 ${server.running} running` : "";
243
365
  })(), null);
244
- _$insert(_el$37, () => server.available ? "" : " \u2014 not installed", null);
245
- return _el$37;
366
+ _$insert(_el$57, () => server.available ? "" : " \u2014 not installed", null);
367
+ return _el$57;
246
368
  })()
247
369
  }), _$createComponent(For, {
248
370
  get each() {
249
371
  return data().diagnostics;
250
372
  },
251
373
  children: (diagnostic) => (() => {
252
- var _el$41 = _$createElement("text"), _el$42 = _$createTextNode(`! `);
253
- _$insertNode(_el$41, _el$42);
254
- _$insert(_el$41, diagnostic, null);
255
- return _el$41;
374
+ var _el$61 = _$createElement("text"), _el$62 = _$createTextNode(`! `);
375
+ _$insertNode(_el$61, _el$62);
376
+ _$insert(_el$61, diagnostic, null);
377
+ return _el$61;
256
378
  })()
257
379
  })]
258
380
  })];
@@ -261,6 +383,7 @@ var LspPanel = (props) => {
261
383
  };
262
384
  var HooksPanel = (props) => {
263
385
  const state = usePanelState(props, "hooksState");
386
+ usePanelKeys(props, state.refresh);
264
387
  return _$createComponent(Frame, {
265
388
  title: "Hook bridge",
266
389
  get children() {
@@ -274,30 +397,30 @@ var HooksPanel = (props) => {
274
397
  },
275
398
  get fallback() {
276
399
  return (() => {
277
- var _el$43 = _$createElement("text");
278
- _$insert(_el$43, () => state.error() ? "" : "Loading hooks\u2026");
279
- return _el$43;
400
+ var _el$63 = _$createElement("text");
401
+ _$insert(_el$63, () => state.error() ? "" : "Loading hooks\u2026");
402
+ return _el$63;
280
403
  })();
281
404
  },
282
405
  children: (data) => [(() => {
283
- var _el$44 = _$createElement("text"), _el$45 = _$createTextNode(` handler(s) \xB7 `), _el$46 = _$createTextNode(` from the project \xB7 `);
284
- _$insertNode(_el$44, _el$45);
285
- _$insertNode(_el$44, _el$46);
286
- _$insert(_el$44, () => data().handlers, _el$45);
287
- _$insert(_el$44, () => data().projectHandlers, _el$46);
288
- _$insert(_el$44, (() => {
406
+ var _el$64 = _$createElement("text"), _el$65 = _$createTextNode(` handler(s) \xB7 `), _el$66 = _$createTextNode(` from the project \xB7 `);
407
+ _$insertNode(_el$64, _el$65);
408
+ _$insertNode(_el$64, _el$66);
409
+ _$insert(_el$64, () => data().handlers, _el$65);
410
+ _$insert(_el$64, () => data().projectHandlers, _el$66);
411
+ _$insert(_el$64, (() => {
289
412
  var _c$6 = _$memo(() => data().projectHandlers === 0);
290
413
  return () => _c$6() ? "nothing to trust" : data().trusted ? "trusted" : "NOT trusted";
291
414
  })(), null);
292
- return _el$44;
415
+ return _el$64;
293
416
  })(), _$createComponent(For, {
294
417
  get each() {
295
418
  return data().projectLines;
296
419
  },
297
420
  children: (line) => (() => {
298
- var _el$50 = _$createElement("text");
299
- _$insert(_el$50, line);
300
- return _el$50;
421
+ var _el$70 = _$createElement("text");
422
+ _$insert(_el$70, line);
423
+ return _el$70;
301
424
  })()
302
425
  }), _$createComponent(Show, {
303
426
  get when() {
@@ -305,24 +428,24 @@ var HooksPanel = (props) => {
305
428
  },
306
429
  get children() {
307
430
  return [(() => {
308
- var _el$48 = _$createElement("text");
309
- _$insertNode(_el$48, _$createTextNode(`Capability loss (advisory rows):`));
310
- return _el$48;
431
+ var _el$68 = _$createElement("text");
432
+ _$insertNode(_el$68, _$createTextNode(`Capability loss (advisory rows):`));
433
+ return _el$68;
311
434
  })(), _$createComponent(For, {
312
435
  get each() {
313
436
  return data().loss;
314
437
  },
315
438
  children: (item) => (() => {
316
- var _el$51 = _$createElement("text"), _el$52 = _$createTextNode(`! `), _el$53 = _$createTextNode(` \xB7 `), _el$54 = _$createTextNode(` \u2014 `), _el$55 = _$createTextNode(`: `);
317
- _$insertNode(_el$51, _el$52);
318
- _$insertNode(_el$51, _el$53);
319
- _$insertNode(_el$51, _el$54);
320
- _$insertNode(_el$51, _el$55);
321
- _$insert(_el$51, () => item.event, _el$53);
322
- _$insert(_el$51, () => item.handler, _el$54);
323
- _$insert(_el$51, () => item.support, _el$55);
324
- _$insert(_el$51, () => item.reason, null);
325
- return _el$51;
439
+ var _el$71 = _$createElement("text"), _el$72 = _$createTextNode(`! `), _el$73 = _$createTextNode(` \xB7 `), _el$74 = _$createTextNode(` \u2014 `), _el$75 = _$createTextNode(`: `);
440
+ _$insertNode(_el$71, _el$72);
441
+ _$insertNode(_el$71, _el$73);
442
+ _$insertNode(_el$71, _el$74);
443
+ _$insertNode(_el$71, _el$75);
444
+ _$insert(_el$71, () => item.event, _el$73);
445
+ _$insert(_el$71, () => item.handler, _el$74);
446
+ _$insert(_el$71, () => item.support, _el$75);
447
+ _$insert(_el$71, () => item.reason, null);
448
+ return _el$71;
326
449
  })()
327
450
  })];
328
451
  }
@@ -331,20 +454,20 @@ var HooksPanel = (props) => {
331
454
  return data().diagnostics;
332
455
  },
333
456
  children: (item) => (() => {
334
- var _el$56 = _$createElement("text"), _el$57 = _$createTextNode(`! `);
335
- _$insertNode(_el$56, _el$57);
336
- _$insert(_el$56, item, null);
337
- return _el$56;
457
+ var _el$76 = _$createElement("text"), _el$77 = _$createTextNode(`! `);
458
+ _$insertNode(_el$76, _el$77);
459
+ _$insert(_el$76, item, null);
460
+ return _el$76;
338
461
  })()
339
462
  }), _$createComponent(For, {
340
463
  get each() {
341
464
  return data().recent;
342
465
  },
343
466
  children: (item) => (() => {
344
- var _el$58 = _$createElement("text"), _el$59 = _$createTextNode(`recent error: `);
345
- _$insertNode(_el$58, _el$59);
346
- _$insert(_el$58, item, null);
347
- return _el$58;
467
+ var _el$78 = _$createElement("text"), _el$79 = _$createTextNode(`recent error: `);
468
+ _$insertNode(_el$78, _el$79);
469
+ _$insert(_el$78, item, null);
470
+ return _el$78;
348
471
  })()
349
472
  })]
350
473
  })];
@@ -353,6 +476,7 @@ var HooksPanel = (props) => {
353
476
  };
354
477
  var BrainstormPanel = (props) => {
355
478
  const state = usePanelState(props, "brainstormState");
479
+ usePanelKeys(props, state.refresh);
356
480
  return _$createComponent(Frame, {
357
481
  title: "Brainstorm board",
358
482
  get children() {
@@ -366,9 +490,9 @@ var BrainstormPanel = (props) => {
366
490
  },
367
491
  get fallback() {
368
492
  return (() => {
369
- var _el$60 = _$createElement("text");
370
- _$insert(_el$60, () => state.error() ? "" : "Loading brainstorm\u2026");
371
- return _el$60;
493
+ var _el$80 = _$createElement("text");
494
+ _$insert(_el$80, () => state.error() ? "" : "Loading brainstorm\u2026");
495
+ return _el$80;
372
496
  })();
373
497
  },
374
498
  children: (data) => _$createComponent(Show, {
@@ -377,41 +501,41 @@ var BrainstormPanel = (props) => {
377
501
  },
378
502
  get fallback() {
379
503
  return (() => {
380
- var _el$75 = _$createElement("text");
381
- _$insertNode(_el$75, _$createTextNode(`No brainstorm in .factory/brainstorm yet. Run /brainstorm.`));
382
- return _el$75;
504
+ var _el$95 = _$createElement("text");
505
+ _$insertNode(_el$95, _$createTextNode(`No brainstorm in .factory/brainstorm yet. Run /brainstorm.`));
506
+ return _el$95;
383
507
  })();
384
508
  },
385
509
  get children() {
386
510
  return [(() => {
387
- var _el$61 = _$createElement("text"), _el$62 = _$createTextNode(`Brief: `);
388
- _$insertNode(_el$61, _el$62);
389
- _$insert(_el$61, () => data().brief, null);
390
- return _el$61;
511
+ var _el$81 = _$createElement("text"), _el$82 = _$createTextNode(`Brief: `);
512
+ _$insertNode(_el$81, _el$82);
513
+ _$insert(_el$81, () => data().brief, null);
514
+ return _el$81;
391
515
  })(), (() => {
392
- var _el$63 = _$createElement("text"), _el$64 = _$createTextNode(` idea(s) \xB7 `), _el$65 = _$createTextNode(` duplicate(s) \xB7 `), _el$66 = _$createTextNode(` scored \xB7 `);
393
- _$insertNode(_el$63, _el$64);
394
- _$insertNode(_el$63, _el$65);
395
- _$insertNode(_el$63, _el$66);
396
- _$insert(_el$63, () => data().ideas, _el$64);
397
- _$insert(_el$63, () => data().duplicates, _el$65);
398
- _$insert(_el$63, () => data().scored, _el$66);
399
- _$insert(_el$63, () => data().complete ? "complete" : "in progress", null);
400
- return _el$63;
516
+ var _el$83 = _$createElement("text"), _el$84 = _$createTextNode(` idea(s) \xB7 `), _el$85 = _$createTextNode(` duplicate(s) \xB7 `), _el$86 = _$createTextNode(` scored \xB7 `);
517
+ _$insertNode(_el$83, _el$84);
518
+ _$insertNode(_el$83, _el$85);
519
+ _$insertNode(_el$83, _el$86);
520
+ _$insert(_el$83, () => data().ideas, _el$84);
521
+ _$insert(_el$83, () => data().duplicates, _el$85);
522
+ _$insert(_el$83, () => data().scored, _el$86);
523
+ _$insert(_el$83, () => data().complete ? "complete" : "in progress", null);
524
+ return _el$83;
401
525
  })(), (() => {
402
- var _el$68 = _$createElement("text"), _el$69 = _$createTextNode(`Coverage: `);
403
- _$insertNode(_el$68, _el$69);
404
- _$insert(_el$68, () => data().lenses.map((lens) => `${lens} ${data().coverage[lens] ?? 0}`).join(" \xB7 "), null);
405
- return _el$68;
526
+ var _el$88 = _$createElement("text"), _el$89 = _$createTextNode(`Coverage: `);
527
+ _$insertNode(_el$88, _el$89);
528
+ _$insert(_el$88, () => data().lenses.map((lens) => `${lens} ${data().coverage[lens] ?? 0}`).join(" \xB7 "), null);
529
+ return _el$88;
406
530
  })(), _$createComponent(Show, {
407
531
  get when() {
408
532
  return data().gaps.length;
409
533
  },
410
534
  get children() {
411
- var _el$71 = _$createElement("text"), _el$72 = _$createTextNode(`Gaps: `);
412
- _$insertNode(_el$71, _el$72);
413
- _$insert(_el$71, () => data().gaps.join(", "), null);
414
- return _el$71;
535
+ var _el$91 = _$createElement("text"), _el$92 = _$createTextNode(`Gaps: `);
536
+ _$insertNode(_el$91, _el$92);
537
+ _$insert(_el$91, () => data().gaps.join(", "), null);
538
+ return _el$91;
415
539
  }
416
540
  }), _$createComponent(Show, {
417
541
  get when() {
@@ -419,24 +543,24 @@ var BrainstormPanel = (props) => {
419
543
  },
420
544
  get children() {
421
545
  return [(() => {
422
- var _el$73 = _$createElement("text");
423
- _$insertNode(_el$73, _$createTextNode(`Shortlist:`));
424
- return _el$73;
546
+ var _el$93 = _$createElement("text");
547
+ _$insertNode(_el$93, _$createTextNode(`Shortlist:`));
548
+ return _el$93;
425
549
  })(), _$createComponent(For, {
426
550
  get each() {
427
551
  return data().shortlist;
428
552
  },
429
553
  children: (entry) => (() => {
430
- var _el$77 = _$createElement("text"), _el$78 = _$createTextNode(` `), _el$79 = _$createTextNode(` (`), _el$80 = _$createTextNode(`/20) \u2014 `);
431
- _$insertNode(_el$77, _el$78);
432
- _$insertNode(_el$77, _el$79);
433
- _$insertNode(_el$77, _el$80);
434
- _$insert(_el$77, () => entry.outlier ? "\u25C7" : "\u25C6", _el$78);
435
- _$insert(_el$77, () => entry.id, _el$79);
436
- _$insert(_el$77, () => entry.total, _el$80);
437
- _$insert(_el$77, () => entry.title, null);
438
- _$insert(_el$77, () => entry.outlier ? " (forced outlier)" : "", null);
439
- return _el$77;
554
+ var _el$97 = _$createElement("text"), _el$98 = _$createTextNode(` `), _el$99 = _$createTextNode(` (`), _el$100 = _$createTextNode(`/20) \u2014 `);
555
+ _$insertNode(_el$97, _el$98);
556
+ _$insertNode(_el$97, _el$99);
557
+ _$insertNode(_el$97, _el$100);
558
+ _$insert(_el$97, () => entry.outlier ? "\u25C7" : "\u25C6", _el$98);
559
+ _$insert(_el$97, () => entry.id, _el$99);
560
+ _$insert(_el$97, () => entry.total, _el$100);
561
+ _$insert(_el$97, () => entry.title, null);
562
+ _$insert(_el$97, () => entry.outlier ? " (forced outlier)" : "", null);
563
+ return _el$97;
440
564
  })()
441
565
  })];
442
566
  }
@@ -453,40 +577,59 @@ var PANEL_COMPONENTS = {
453
577
  hooks: HooksPanel,
454
578
  brainstorm: BrainstormPanel
455
579
  };
456
- var PANELS = Object.entries(PANEL_COMPONENTS).map(([name, Panel]) => ({
457
- name,
458
- render: (props) => _$createComponent(Panel, {
459
- get call() {
460
- return props.call;
580
+ var FactoryFooter = (props) => {
581
+ const state = usePanelState(props, "status", FOOTER_REFRESH_MS);
582
+ return _$createComponent(Show, {
583
+ get when() {
584
+ return state.data()?.footer;
461
585
  },
462
- get subscribe() {
463
- return props.subscribe;
586
+ get children() {
587
+ var _el$101 = _$createElement("text");
588
+ _$insert(_el$101, () => state.data().footer);
589
+ return _el$101;
464
590
  }
465
- })
466
- }));
467
- function registerPanels(context, call, subscribe) {
591
+ });
592
+ };
593
+ function claimSlot(context, name, render) {
468
594
  const slotFn = typeof context.slot === "function" ? context.slot : context.ui?.slot;
469
595
  if (typeof slotFn !== "function")
470
- return () => {};
596
+ return;
597
+ const dispose = slotFn.length <= 1 ? slotFn({
598
+ append: name,
599
+ render
600
+ }) : slotFn(name, render);
601
+ return typeof dispose === "function" ? dispose : undefined;
602
+ }
603
+ function registerPanels(context, call, subscribe) {
604
+ const layer = typeof context.keymap?.layer === "function" ? (factory) => context.keymap.layer(factory) : undefined;
471
605
  const disposers = [];
472
- for (const panel of PANELS) {
473
- const render = (input) => input.name === panel.name ? panel.render({
606
+ for (const [name, Panel] of Object.entries(PANEL_COMPONENTS)) {
607
+ const dispose = claimSlot(context, "session.panel", (input) => input.name === name ? _$createComponent(Panel, _$mergeProps({
474
608
  call,
475
609
  subscribe
476
- }) : null;
477
- const dispose = slotFn.length <= 1 ? slotFn({
478
- append: "session.panel",
479
- render
480
- }) : slotFn("session.panel", render);
481
- if (typeof dispose === "function")
610
+ }, () => input.close && input.toggleFullscreen ? {
611
+ panel: {
612
+ close: input.close,
613
+ toggleFullscreen: input.toggleFullscreen
614
+ }
615
+ } : {}, layer ? {
616
+ layer
617
+ } : {})) : null);
618
+ if (dispose)
482
619
  disposers.push(dispose);
483
620
  }
621
+ const footer = claimSlot(context, "prompt.footer.status", () => _$createComponent(FactoryFooter, {
622
+ call,
623
+ subscribe
624
+ }));
625
+ if (footer)
626
+ disposers.push(footer);
484
627
  return () => {
485
628
  for (const dispose of disposers)
486
629
  dispose();
487
630
  };
488
631
  }
489
- var PANEL_NAMES = PANELS.map((panel) => panel.name);
632
+ var PANEL_NAMES = Object.keys(PANEL_COMPONENTS);
490
633
 
491
634
  // ../../node_modules/.bun/@opencode+schema@2.0.24/node_modules/@opencode/schema/dist/rpc.js
492
635
  function define(definition) {
@@ -515,27 +658,22 @@ var EsRpc = define({
515
658
  methods: {
516
659
  status: {
517
660
  input: obj({}),
518
- output: obj({ summary: str, stage: str, pending: strArray }, ["summary", "stage", "pending"])
661
+ output: obj({ summary: str, stage: str, pending: strArray, headline: str, footer: str, paused: str }, [
662
+ "summary",
663
+ "stage",
664
+ "pending",
665
+ "headline"
666
+ ])
667
+ },
668
+ configState: {
669
+ input: obj({}),
670
+ output: obj({ config: str, sources: strArray, warnings: strArray }, ["config", "sources", "warnings"])
519
671
  },
520
672
  previewApproval: {
521
673
  input: obj({ stage: { type: "string", enum: ["frontier", "spec"] } }, ["stage"]),
522
674
  output: Preview
523
675
  },
524
- approve: {
525
- input: obj({ stage: { type: "string", enum: ["frontier", "spec"] }, user: str, token: str }, [
526
- "stage",
527
- "user",
528
- "token"
529
- ]),
530
- output: obj({ message: str }, ["message"]),
531
- errors: { refused: obj({ reason: str }, ["reason"]) }
532
- },
533
676
  previewTrust: { input: obj({}), output: Preview },
534
- trust: {
535
- input: obj({ user: str, token: str }, ["user", "token"]),
536
- output: obj({ message: str }, ["message"]),
537
- errors: { refused: obj({ reason: str }, ["reason"]) }
538
- },
539
677
  previewResume: { input: obj({}), output: Preview },
540
678
  previewLspInstall: { input: obj({ id: str }, ["id"]), output: Preview },
541
679
  lspInstall: {
@@ -543,17 +681,6 @@ var EsRpc = define({
543
681
  output: obj({ message: str }, ["message"]),
544
682
  errors: { refused: obj({ reason: str }, ["reason"]) }
545
683
  },
546
- resume: {
547
- input: obj({
548
- user: str,
549
- token: str,
550
- acceptControlDrift: { type: "boolean" },
551
- raiseCeilingUSD: { type: "number" },
552
- extendRuntime: { type: "boolean" }
553
- }, ["user", "token"]),
554
- output: obj({ message: str }, ["message"]),
555
- errors: { refused: obj({ reason: str }, ["reason"]) }
556
- },
557
684
  factoryState: {
558
685
  input: obj({}),
559
686
  output: obj({
@@ -569,11 +696,17 @@ var EsRpc = define({
569
696
  phases: { type: "array" },
570
697
  pending: strArray,
571
698
  audits: { type: "array" },
699
+ headline: str,
700
+ header: str,
701
+ seats: strArray,
702
+ research: str,
703
+ events: strArray,
704
+ paused: str,
572
705
  tree: obj(Object.fromEntries(["round", "total", "settled", "open", "deferred", "facts", "frontier"].map((key) => [
573
706
  key,
574
707
  { type: "number" }
575
708
  ])), ["round", "total", "settled", "open", "deferred", "facts", "frontier"])
576
- }, ["stage", "spend", "phases", "pending"])
709
+ }, ["stage", "spend", "phases", "pending", "headline", "seats", "events"])
577
710
  },
578
711
  lspState: {
579
712
  input: obj({}),
@@ -612,7 +745,7 @@ var EsRpc = define({
612
745
  }
613
746
  },
614
747
  events: {
615
- changed: { schema: obj({ stage: str, summary: str }, ["stage", "summary"]) }
748
+ changed: { schema: obj({ stage: str, summary: str, notice: str }, ["stage", "summary"]) }
616
749
  }
617
750
  });
618
751
 
@@ -632,6 +765,12 @@ var tui_default = Plugin.define({
632
765
  message,
633
766
  variant
634
767
  });
768
+ call("configState").then((view) => {
769
+ for (const warning of view.warnings)
770
+ toast(warning, "error");
771
+ }).catch(() => {
772
+ return;
773
+ });
635
774
  const confirm = async (preview, label) => {
636
775
  if (!preview.ok || !preview.token) {
637
776
  await context.ui.dialog.alert({
@@ -673,55 +812,59 @@ var tui_default = Plugin.define({
673
812
  }));
674
813
  if (stage !== "frontier" && stage !== "spec")
675
814
  return;
676
- const token = await confirm(await call("previewApproval", {
815
+ const preview = await call("previewApproval", {
677
816
  stage
678
- }), "Approve");
817
+ });
818
+ const token = await confirm(preview, "Approve");
679
819
  if (!token)
680
820
  return;
681
- toast((await call("approve", {
682
- stage,
683
- user,
684
- token
685
- })).message, "success");
821
+ await context.ui.dialog.alert({
822
+ title: preview.title,
823
+ message: `${preview.lines.join(`
824
+ `)}
825
+
826
+ Run \`es approve ${stage}\` at a terminal with your passphrase (1.1.1: approvals need the sealed human key).`
827
+ });
686
828
  });
687
829
  const trust = guarded(async () => {
688
- const token = await confirm(await call("previewTrust"), "Trust");
830
+ const preview = await call("previewTrust");
831
+ const token = await confirm(preview, "Trust");
689
832
  if (!token)
690
833
  return;
691
- toast((await call("trust", {
692
- user,
693
- token
694
- })).message, "success");
834
+ await context.ui.dialog.alert({
835
+ title: preview.title,
836
+ message: `${preview.lines.join(`
837
+ `)}
838
+
839
+ Run \`es trust\` at a terminal with your passphrase to sign these.`
840
+ });
695
841
  });
696
842
  const resume = guarded(async () => {
697
843
  const preview = await call("previewResume");
698
844
  const token = await confirm(preview, "Resume");
699
845
  if (!token)
700
846
  return;
847
+ const lines = preview.lines.join(`
848
+ `);
701
849
  const drift = preview.lines.some((line) => line.startsWith("Control-file drift"));
702
- let raiseCeilingUSD;
850
+ let raise = "";
703
851
  if (/spend ceiling/i.test(preview.lines[0] ?? "")) {
704
852
  const raised = await context.ui.dialog.prompt({
705
853
  title: "New spend ceiling (USD)",
706
854
  placeholder: "e.g. 50"
707
855
  });
708
- raiseCeilingUSD = raised ? Number(raised) : undefined;
856
+ if (raised)
857
+ raise = ` --raise-ceiling ${raised}`;
709
858
  }
710
- const extendRuntime = /runtime cap/i.test(preview.lines[0] ?? "");
711
- const result = await call("resume", {
712
- user,
713
- token,
714
- ...drift ? {
715
- acceptControlDrift: true
716
- } : {},
717
- ...raiseCeilingUSD ? {
718
- raiseCeilingUSD
719
- } : {},
720
- ...extendRuntime ? {
721
- extendRuntime: true
722
- } : {}
859
+ const extend = /runtime cap/i.test(lines) ? " --extend-runtime" : "";
860
+ const flags = `${drift ? " --accept-drift" : ""}${raise}${extend}`;
861
+ await context.ui.dialog.alert({
862
+ title: preview.title,
863
+ message: `${preview.lines.join(`
864
+ `)}
865
+
866
+ Run \`es factory resume${flags}\` at a terminal with your passphrase.`
723
867
  });
724
- toast(result.message, "success");
725
868
  });
726
869
  const lspInstall = guarded(async (input) => {
727
870
  const id = input?.trim() || await context.ui.dialog.prompt({
@@ -741,6 +884,12 @@ var tui_default = Plugin.define({
741
884
  token
742
885
  })).message, "success");
743
886
  });
887
+ const openPanel = (name) => {
888
+ if (!context.ui.panel.open(name, {
889
+ presentation: "panel"
890
+ }))
891
+ toast("Open a session first: Epistemic Swarm panels show beside a session.", "info");
892
+ };
744
893
  const status = guarded(async () => {
745
894
  const result = await call("status");
746
895
  await context.ui.dialog.alert({
@@ -805,11 +954,16 @@ var tui_default = Plugin.define({
805
954
  slash: {
806
955
  name: "es-factory"
807
956
  },
808
- run: () => {
809
- context.ui.panel.open("factory", {
810
- presentation: "fullscreen"
811
- });
812
- }
957
+ run: () => openPanel("factory")
958
+ }, {
959
+ id: "es.panel.close",
960
+ title: "Epistemic Swarm: close the panel",
961
+ group: "Epistemic Swarm",
962
+ palette: true,
963
+ slash: {
964
+ name: "es-close"
965
+ },
966
+ run: () => context.ui.panel.close()
813
967
  }, {
814
968
  id: "es.panel.lsp",
815
969
  title: "Epistemic Swarm: language server panel",
@@ -818,11 +972,7 @@ var tui_default = Plugin.define({
818
972
  slash: {
819
973
  name: "es-lsp-panel"
820
974
  },
821
- run: () => {
822
- context.ui.panel.open("lsp", {
823
- presentation: "fullscreen"
824
- });
825
- }
975
+ run: () => openPanel("lsp")
826
976
  }, {
827
977
  id: "es.panel.hooks",
828
978
  title: "Epistemic Swarm: hook inspector",
@@ -831,11 +981,7 @@ var tui_default = Plugin.define({
831
981
  slash: {
832
982
  name: "es-hooks"
833
983
  },
834
- run: () => {
835
- context.ui.panel.open("hooks", {
836
- presentation: "fullscreen"
837
- });
838
- }
984
+ run: () => openPanel("hooks")
839
985
  }, {
840
986
  id: "es.panel.brainstorm",
841
987
  title: "Epistemic Swarm: brainstorm board",
@@ -844,14 +990,21 @@ var tui_default = Plugin.define({
844
990
  slash: {
845
991
  name: "es-brainstorm"
846
992
  },
847
- run: () => {
848
- context.ui.panel.open("brainstorm", {
849
- presentation: "fullscreen"
850
- });
851
- }
993
+ run: () => openPanel("brainstorm")
852
994
  }]
853
995
  }));
854
- const stop = rpc.events.on("changed", (event) => toast(`Factory \u2192 ${event.data.stage}`));
996
+ let lastStage;
997
+ const stop = rpc.events.on("changed", (event) => {
998
+ const {
999
+ stage,
1000
+ notice
1001
+ } = event.data ?? {};
1002
+ if (notice)
1003
+ toast(notice, "info");
1004
+ if (lastStage !== undefined && stage !== lastStage)
1005
+ toast(`Factory \u2192 ${stage}`);
1006
+ lastStage = stage;
1007
+ });
855
1008
  return () => {
856
1009
  stopPanels();
857
1010
  stop();