@agentdocumentformat/cli 0.8.3 → 0.8.4

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 (129) hide show
  1. package/README.md +55 -4
  2. package/dist/adf.mjs +16 -13
  3. package/dist/chunks/{App-UHLJRFZJ.mjs → App-XOPHZTGN.mjs} +336 -296
  4. package/dist/chunks/{auth-manager-TBNKCJ45.mjs → auth-manager-2YHTYI3C.mjs} +2 -1
  5. package/dist/chunks/{build-QF5W473T.mjs → build-BFOCXM5S.mjs} +1 -1
  6. package/dist/chunks/{chunk-RHBGCOS3.mjs → chunk-22ZGZFOV.mjs} +5 -16
  7. package/dist/chunks/chunk-26RK7T5L.mjs +20 -0
  8. package/dist/chunks/{chunk-KCIRFUZH.mjs → chunk-2WIFHJV2.mjs} +2 -2
  9. package/dist/chunks/{chunk-D7A77SNL.mjs → chunk-3FWPIWYM.mjs} +1 -1
  10. package/dist/chunks/chunk-4T745GJA.mjs +431 -0
  11. package/dist/chunks/{chunk-WPT3FAFX.mjs → chunk-7ADDKFT5.mjs} +3 -30
  12. package/dist/chunks/chunk-A53XYNJL.mjs +26 -0
  13. package/dist/chunks/{chunk-MZRXFWPQ.mjs → chunk-AN6USKYQ.mjs} +40 -8
  14. package/dist/chunks/{chunk-2Z7X3UUR.mjs → chunk-DHO5Z6HP.mjs} +14 -12
  15. package/dist/chunks/{chunk-F5ELW46V.mjs → chunk-GJYMGPH4.mjs} +1 -0
  16. package/dist/chunks/chunk-HONGRUAE.mjs +175 -0
  17. package/dist/chunks/{chunk-AEAJDCVK.mjs → chunk-IM5JKLXO.mjs} +1 -1
  18. package/dist/chunks/chunk-J2N63ZUD.mjs +12 -0
  19. package/dist/chunks/{chunk-FUQRYTGX.mjs → chunk-JK6K2BMV.mjs} +9 -35
  20. package/dist/chunks/{chunk-75DC5EWN.mjs → chunk-KBXC5EHK.mjs} +1 -0
  21. package/dist/chunks/chunk-NRTRTR7C.mjs +43 -0
  22. package/dist/chunks/{chunk-BS3USVEA.mjs → chunk-P4G5ZEBI.mjs} +1 -1
  23. package/dist/chunks/{chunk-E7LC6SHP.mjs → chunk-RIAB37IS.mjs} +4 -2
  24. package/dist/chunks/{chunk-LVF2DRBR.mjs → chunk-TBMQOM7Y.mjs} +247 -610
  25. package/dist/chunks/{chunk-SOSPQPEN.mjs → chunk-TDRQG5UO.mjs} +1 -162
  26. package/dist/chunks/{chunk-OHTB4UW4.mjs → chunk-TPA2ITKV.mjs} +32 -18
  27. package/dist/chunks/{chunk-BHY7QDCM.mjs → chunk-UBWWGUMU.mjs} +1 -0
  28. package/dist/chunks/{chunk-3AT7IIP7.mjs → chunk-WZ6S3SQP.mjs} +1 -1
  29. package/dist/chunks/chunk-X6R32YVE.mjs +43 -0
  30. package/dist/chunks/chunk-XJWGENZ5.mjs +5903 -0
  31. package/dist/chunks/{chunk-F3WSCAJD.mjs → chunk-XP4U4A2W.mjs} +1 -1
  32. package/dist/chunks/chunk-XS46KYYY.mjs +31 -0
  33. package/dist/chunks/{chunk-HBOFZRUS.mjs → chunk-XZQVDY3U.mjs} +9 -1
  34. package/dist/chunks/chunk-ZECGH3LT.mjs +88 -0
  35. package/dist/chunks/{claude-subscription-EB4LAAVV.mjs → claude-subscription-42L4YM5L.mjs} +4 -3
  36. package/dist/chunks/{cli-UVIJAGRZ.mjs → cli-JPRYEY4J.mjs} +22 -7
  37. package/dist/chunks/{commands-KOMPXJZS.mjs → commands-TZW2FSXG.mjs} +5 -2
  38. package/dist/chunks/context-AZOIJOUG.mjs +5933 -0
  39. package/dist/chunks/{daemon-YHD7PUQI.mjs → daemon-DK3KUDZJ.mjs} +3362 -6724
  40. package/dist/chunks/{daemon-control-MKN7G5M3.mjs → daemon-control-U4OGCAAJ.mjs} +4 -4
  41. package/dist/chunks/{devtools-H7CI2ZVG.mjs → devtools-AUZWFIPL.mjs} +1 -1
  42. package/dist/chunks/firewall-service-7RGJN4LD.mjs +163 -0
  43. package/dist/chunks/{open-3OR6WT4T.mjs → open-T3VGLWGF.mjs} +6 -5
  44. package/dist/chunks/{pipeline-executor-DRYEEFDR.mjs → pipeline-executor-MHRI7ODL.mjs} +6 -3
  45. package/dist/chunks/{remote-access-cli-GLEEP7DI.mjs → remote-access-cli-EFVCXFOY.mjs} +22 -6
  46. package/dist/chunks/{store-D2WLXEY2.mjs → store-37YHXFJ6.mjs} +4 -3
  47. package/dist/chunks/{tui-ZEI2NAQV.mjs → tui-NJKGFAKU.mjs} +12 -11
  48. package/dist/chunks/web-F4XHDGUX.mjs +149 -0
  49. package/dist/chunks/{whatsapp-YJFFVN4Q.mjs → whatsapp-J7PX7TKT.mjs} +1 -1
  50. package/package.json +4 -3
  51. package/web/assets/EditorPanel-5ZGWvexa.js +161 -0
  52. package/web/assets/MeshGraphView-BZV40eAE.css +1 -0
  53. package/web/assets/MeshGraphView-Vp2R5TLK.js +23 -0
  54. package/web/assets/SettingsPage-_uHkBERV.js +6 -0
  55. package/web/assets/agent-window-B8X7FV4_.js +3 -0
  56. package/web/assets/agent.store-BHweGGTh.js +1 -0
  57. package/web/assets/app.store-j_-OuVPe.js +1 -0
  58. package/web/assets/core-DVezgdzc.js +12 -0
  59. package/web/assets/css-Z72CF80r.js +1 -0
  60. package/web/assets/diff-D97Zzqfu.js +1 -0
  61. package/web/assets/document.store-CMD3_OM0.js +1 -0
  62. package/web/assets/edit-recovery-Ce8tPQZl.js +3 -0
  63. package/web/assets/engine-javascript-CuxHA8oH.js +141 -0
  64. package/web/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  65. package/web/assets/github-light-DAi9KRSo.js +1 -0
  66. package/web/assets/go-C27-OAKa.js +1 -0
  67. package/web/assets/html-BlS82ilI.js +1 -0
  68. package/web/assets/index-B5Eot_tL.js +1 -0
  69. package/web/assets/index-B5FYMbFc.js +3 -0
  70. package/web/assets/index-BQIEMvvt.js +2 -0
  71. package/web/assets/index-C_gf4L3q.js +1 -0
  72. package/web/assets/index-Ca6bEWGu.js +1 -0
  73. package/web/assets/index-CuTaWSEs.css +1 -0
  74. package/web/assets/index-DBFkrLao.js +1 -0
  75. package/web/assets/index-DF1leTEa.js +11 -0
  76. package/web/assets/index-DS9H-PJI.js +1 -0
  77. package/web/assets/index-DkhbLs9K.js +6 -0
  78. package/web/assets/index-KNnHrO8-.js +13 -0
  79. package/web/assets/index-nM_Q5x7Q.js +1 -0
  80. package/web/assets/inter-tight-cyrillic-ext-wght-italic-BJqtfpQe.woff2 +0 -0
  81. package/web/assets/inter-tight-cyrillic-ext-wght-normal-okcGN4Nq.woff2 +0 -0
  82. package/web/assets/inter-tight-cyrillic-wght-italic-HmhN1gQv.woff2 +0 -0
  83. package/web/assets/inter-tight-cyrillic-wght-normal-BS41q_Tv.woff2 +0 -0
  84. package/web/assets/inter-tight-greek-ext-wght-italic-B_3RbJza.woff2 +0 -0
  85. package/web/assets/inter-tight-greek-ext-wght-normal-DQgQPNk4.woff2 +0 -0
  86. package/web/assets/inter-tight-greek-wght-italic-Bb1BGCmL.woff2 +0 -0
  87. package/web/assets/inter-tight-greek-wght-normal-sS1B39LI.woff2 +0 -0
  88. package/web/assets/inter-tight-latin-ext-wght-italic-DYqsmiDd.woff2 +0 -0
  89. package/web/assets/inter-tight-latin-ext-wght-normal-B4u9PlvR.woff2 +0 -0
  90. package/web/assets/inter-tight-latin-wght-italic-DiXukCDG.woff2 +0 -0
  91. package/web/assets/inter-tight-latin-wght-normal-DX-nOvPD.woff2 +0 -0
  92. package/web/assets/inter-tight-vietnamese-wght-italic-CiVF0Juh.woff2 +0 -0
  93. package/web/assets/inter-tight-vietnamese-wght-normal-TKKdAiBA.woff2 +0 -0
  94. package/web/assets/javascript-wDzz0qaB.js +1 -0
  95. package/web/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  96. package/web/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  97. package/web/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  98. package/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  99. package/web/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  100. package/web/assets/json-Cp-IABpG.js +1 -0
  101. package/web/assets/jsx-g9-lgVsj.js +1 -0
  102. package/web/assets/main-Zf3qnQYd.css +1 -0
  103. package/web/assets/main-o2ocfqUC.js +319 -0
  104. package/web/assets/markdown-Cvjx9yec.js +1 -0
  105. package/web/assets/message-queue.store-ke_rFZAb.js +2 -0
  106. package/web/assets/module-RjUF93sV.js +716 -0
  107. package/web/assets/native-48B9X9Wg.js +1 -0
  108. package/web/assets/orbital-render.worker-BovOTauk.js +1 -0
  109. package/web/assets/python-B6aJPvgy.js +1 -0
  110. package/web/assets/react-D-F9gHrJ.js +1 -0
  111. package/web/assets/rust-DPvrY3IQ.js +1 -0
  112. package/web/assets/shellscript-Yzrsuije.js +1 -0
  113. package/web/assets/sql-DkvoVjww.js +1 -0
  114. package/web/assets/stix-two-text-cyrillic-wght-italic-BzL1BdzR.woff2 +0 -0
  115. package/web/assets/stix-two-text-cyrillic-wght-normal-CcrOj1MU.woff2 +0 -0
  116. package/web/assets/stix-two-text-greek-wght-italic-glgrbyRu.woff2 +0 -0
  117. package/web/assets/stix-two-text-greek-wght-normal-DAdwyhkq.woff2 +0 -0
  118. package/web/assets/stix-two-text-latin-ext-wght-italic--XhV508b.woff2 +0 -0
  119. package/web/assets/stix-two-text-latin-ext-wght-normal-BUpo8gM0.woff2 +0 -0
  120. package/web/assets/stix-two-text-latin-wght-italic-BDl6bBME.woff2 +0 -0
  121. package/web/assets/stix-two-text-latin-wght-normal-BTZaHlTl.woff2 +0 -0
  122. package/web/assets/stix-two-text-vietnamese-wght-italic-B1jFRJrJ.woff2 +0 -0
  123. package/web/assets/stix-two-text-vietnamese-wght-normal-CfS0RdBA.woff2 +0 -0
  124. package/web/assets/tsx-COt5Ahok.js +1 -0
  125. package/web/assets/typescript-BPQ3VLAy.js +1 -0
  126. package/web/assets/window-kind-mxlpdE1l.js +1 -0
  127. package/web/assets/with-selector-Ot-ZoUn0.js +1 -0
  128. package/web/assets/yaml-Buea-lGh.js +1 -0
  129. package/web/index.html +15 -0
@@ -4,12 +4,50 @@ import { dirname as __adfDirname } from 'node:path';
4
4
  const require = __adfCreateRequire(import.meta.url);
5
5
  const __filename = __adfFileURLToPath(import.meta.url);
6
6
  const __dirname = __adfDirname(__filename);
7
+ import {
8
+ THEMES,
9
+ applyTheme,
10
+ findTheme,
11
+ nextThemeName,
12
+ themeNames
13
+ } from "./chunk-GAZO6UMI.mjs";
7
14
  import {
8
15
  DaemonClient
9
- } from "./chunk-FUQRYTGX.mjs";
16
+ } from "./chunk-X6R32YVE.mjs";
10
17
  import {
11
18
  auth_flow_exports
12
- } from "./chunk-BHY7QDCM.mjs";
19
+ } from "./chunk-UBWWGUMU.mjs";
20
+ import {
21
+ DaemonError,
22
+ MAIN_LOOP,
23
+ PROMPT_PREFILL_KEY,
24
+ SERVER_STOPPED_TEXT,
25
+ StoreProvider,
26
+ askQuestions,
27
+ emptyTranscript,
28
+ findTracked,
29
+ folderName,
30
+ isAsyncInput,
31
+ isBusyState,
32
+ isCredentialsLocked,
33
+ isTrackedKey,
34
+ parseAskResult,
35
+ parseServer,
36
+ servedText,
37
+ serverBadge,
38
+ serverText,
39
+ shallowEqual,
40
+ shortUrl,
41
+ siteKind,
42
+ siteOf,
43
+ stoppedError,
44
+ stoppedLabel,
45
+ transcriptKey,
46
+ useActions,
47
+ useClient,
48
+ useStore,
49
+ useTuiSelector
50
+ } from "./chunk-TPA2ITKV.mjs";
13
51
  import {
14
52
  createMouseController,
15
53
  getScreenText,
@@ -104,7 +142,18 @@ import {
104
142
  validateCredentials,
105
143
  validateMcpForm,
106
144
  validateProvider
107
- } from "./chunk-2Z7X3UUR.mjs";
145
+ } from "./chunk-DHO5Z6HP.mjs";
146
+ import {
147
+ ThemeContext,
148
+ stateColor,
149
+ useTheme
150
+ } from "./chunk-NZLEPJ5M.mjs";
151
+ import {
152
+ require_jsx_runtime
153
+ } from "./chunk-7CV2SA3H.mjs";
154
+ import {
155
+ cjs
156
+ } from "./chunk-SGUTYISF.mjs";
108
157
  import {
109
158
  WELCOME_INTRO,
110
159
  WELCOME_OVERLAY,
@@ -120,21 +169,23 @@ import {
120
169
  savePrefs
121
170
  } from "./chunk-5QU5VY7N.mjs";
122
171
  import {
123
- THEMES,
124
- applyTheme,
125
- findTheme,
126
- nextThemeName,
127
- themeNames
128
- } from "./chunk-GAZO6UMI.mjs";
172
+ resource_revision_types_exports
173
+ } from "./chunk-XS46KYYY.mjs";
174
+ import "./chunk-JK6K2BMV.mjs";
175
+ import "./chunk-KBXC5EHK.mjs";
129
176
  import {
130
177
  context_breakdown_exports,
131
178
  guarded_fetch_exports,
132
179
  skills_catalog_schema_exports
133
- } from "./chunk-HBOFZRUS.mjs";
134
- import "./chunk-SOSPQPEN.mjs";
180
+ } from "./chunk-XZQVDY3U.mjs";
181
+ import "./chunk-7ADDKFT5.mjs";
182
+ import "./chunk-TDRQG5UO.mjs";
183
+ import "./chunk-NRTRTR7C.mjs";
184
+ import "./chunk-HONGRUAE.mjs";
135
185
  import {
136
186
  Box_default,
137
187
  Text,
188
+ measure_element_default,
138
189
  useAnimation,
139
190
  use_app_default,
140
191
  use_box_metrics_default,
@@ -143,62 +194,20 @@ import {
143
194
  use_stdin_default,
144
195
  use_stdout_default,
145
196
  use_window_size_default
146
- } from "./chunk-3AT7IIP7.mjs";
147
- import {
148
- ThemeContext,
149
- stateColor,
150
- useTheme
151
- } from "./chunk-NZLEPJ5M.mjs";
152
- import {
153
- DaemonError,
154
- MAIN_LOOP,
155
- PROMPT_PREFILL_KEY,
156
- SERVER_STOPPED_TEXT,
157
- StoreProvider,
158
- askQuestions,
159
- emptyTranscript,
160
- findTracked,
161
- folderName,
162
- isAsyncInput,
163
- isBusyState,
164
- isCredentialsLocked,
165
- isTrackedKey,
166
- parseAskResult,
167
- parseServer,
168
- servedText,
169
- serverBadge,
170
- serverText,
171
- shallowEqual,
172
- shortUrl,
173
- siteKind,
174
- siteOf,
175
- stoppedError,
176
- stoppedLabel,
177
- transcriptKey,
178
- useActions,
179
- useClient,
180
- useStore,
181
- useTuiSelector
182
- } from "./chunk-OHTB4UW4.mjs";
183
- import "./chunk-75DC5EWN.mjs";
184
- import {
185
- require_jsx_runtime
186
- } from "./chunk-7CV2SA3H.mjs";
187
- import {
188
- cjs
189
- } from "./chunk-SGUTYISF.mjs";
190
- import "./chunk-WPT3FAFX.mjs";
197
+ } from "./chunk-WZ6S3SQP.mjs";
191
198
  import {
192
199
  require_react
193
200
  } from "./chunk-6GJ4QHRI.mjs";
194
201
  import {
195
202
  ADF_SKILLS_REGISTRY_URL
196
- } from "./chunk-E7LC6SHP.mjs";
203
+ } from "./chunk-RIAB37IS.mjs";
197
204
  import "./chunk-UYY5M2PB.mjs";
198
205
  import "./chunk-2NAP2ZF7.mjs";
199
206
  import "./chunk-LKFHERRV.mjs";
200
- import "./chunk-AEAJDCVK.mjs";
201
- import "./chunk-BS3USVEA.mjs";
207
+ import "./chunk-ZECGH3LT.mjs";
208
+ import "./chunk-26RK7T5L.mjs";
209
+ import "./chunk-IM5JKLXO.mjs";
210
+ import "./chunk-P4G5ZEBI.mjs";
202
211
  import "./chunk-WJGPNHGX.mjs";
203
212
  import "./chunk-PAK5JCO2.mjs";
204
213
  import "./chunk-ZPB3HYM7.mjs";
@@ -218,7 +227,7 @@ import {
218
227
  } from "./chunk-M2RX3S2T.mjs";
219
228
 
220
229
  // src/main/tui/app/App.tsx
221
- var import_react60 = __toESM(require_react(), 1);
230
+ var import_react61 = __toESM(require_react(), 1);
222
231
 
223
232
  // src/main/tui/app/shell-context.ts
224
233
  var import_react = __toESM(require_react(), 1);
@@ -535,7 +544,7 @@ function useShell() {
535
544
  }
536
545
 
537
546
  // src/main/tui/app/Shell.tsx
538
- var import_react25 = __toESM(require_react(), 1);
547
+ var import_react26 = __toESM(require_react(), 1);
539
548
 
540
549
  // src/main/tui/app/clipboard.ts
541
550
  import { spawn } from "node:child_process";
@@ -972,6 +981,7 @@ function isZeroWidth(ch) {
972
981
  return cp >= 768 && cp <= 879 || cp >= 8203 && cp <= 8207 || cp >= 65024 && cp <= 65039;
973
982
  }
974
983
  function displayWidth(text) {
984
+ if (/^[\x00-\x7f]*$/.test(text)) return text.length;
975
985
  let width = 0;
976
986
  for (let ch of text)
977
987
  isZeroWidth(ch) || (width += WIDE.test(ch) ? 2 : 1);
@@ -3547,8 +3557,25 @@ function NewAgentDialog({ overlay, close, width, height }) {
3547
3557
  }
3548
3558
 
3549
3559
  // src/main/tui/auth/AuthDialog.tsx
3560
+ var import_react16 = __toESM(require_react(), 1);
3561
+
3562
+ // src/main/tui/ui/Markdown.tsx
3550
3563
  var import_react15 = __toESM(require_react(), 1);
3551
3564
 
3565
+ // src/main/tui/ui/markdown-window.ts
3566
+ function measuredBlockWindow(signatures, measurements, viewport) {
3567
+ let hidden = Array(signatures.length).fill(!1), below = 0, exact = !0, bottom = Math.max(0, viewport.clipBottom), top = bottom + Math.max(1, viewport.height);
3568
+ for (let i = signatures.length - 1; i >= 0; i--) {
3569
+ let m = measurements.get(i);
3570
+ if (!m || m.signature !== signatures[i]) {
3571
+ exact = !1;
3572
+ continue;
3573
+ }
3574
+ hidden[i] = below >= top || exact && below + m.height <= bottom, below += m.height;
3575
+ }
3576
+ return hidden;
3577
+ }
3578
+
3552
3579
  // src/main/tui/ui/Markdown.tsx
3553
3580
  var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
3554
3581
  function parseBlocks(text) {
@@ -3645,11 +3672,33 @@ function renderBlock(block, index, theme2, color) {
3645
3672
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Inline, { text: block.text, color }, index);
3646
3673
  }
3647
3674
  }
3648
- function Markdown({ text, color, raw = !1 }) {
3649
- let theme2 = useTheme();
3650
- if (raw) return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { wrap: "wrap", color, children: text });
3651
- let blocks = parseBlocks(text);
3652
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box_default, { flexDirection: "column", children: blocks.map((block, i) => renderBlock(block, i, theme2, color)) });
3675
+ function Markdown({ text, color, raw = !1, viewport }) {
3676
+ let theme2 = useTheme(), [, measured] = (0, import_react15.useReducer)((n) => n + 1, 0), cache = (0, import_react15.useRef)(null), nodes = (0, import_react15.useRef)(/* @__PURE__ */ new Map()), blocks = raw ? [] : parseBlocks(text), signatures = viewport ? blocks.map((block) => JSON.stringify(block)) : [];
3677
+ viewport && (!cache.current || cache.current.width !== viewport.width || cache.current.theme !== theme2 || !text.startsWith(cache.current.text)) && (cache.current = { text, width: viewport.width, theme: theme2, heights: /* @__PURE__ */ new Map() });
3678
+ let heights = cache.current?.heights;
3679
+ cache.current && (cache.current.text = text);
3680
+ let hidden = viewport && heights ? measuredBlockWindow(signatures, heights, viewport) : [];
3681
+ if ((0, import_react15.useLayoutEffect)(() => {
3682
+ if (!viewport || !heights) return;
3683
+ for (let [i, node] of nodes.current)
3684
+ i < signatures.length && heights.set(i, { signature: signatures[i], height: measure_element_default(node).height });
3685
+ for (let i of heights.keys()) i >= signatures.length && heights.delete(i);
3686
+ measuredBlockWindow(signatures, heights, viewport).some((value, i) => value !== hidden[i]) && measured();
3687
+ }), raw) return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { wrap: "wrap", color, children: text });
3688
+ if (!viewport || !heights) return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box_default, { flexDirection: "column", children: blocks.map((block, i) => renderBlock(block, i, theme2, color)) });
3689
+ let children = [], spacer = 0, flush = (i) => {
3690
+ spacer > 0 && children.push(/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box_default, { height: spacer, flexShrink: 0 }, `space:${i}`)), spacer = 0;
3691
+ };
3692
+ for (let i = 0; i < blocks.length; i++) {
3693
+ if (hidden[i]) {
3694
+ spacer += heights.get(i).height;
3695
+ continue;
3696
+ }
3697
+ flush(i), children.push(/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box_default, { flexDirection: "column", flexShrink: 0, ref: (node) => {
3698
+ node ? nodes.current.set(i, node) : nodes.current.delete(i);
3699
+ }, children: renderBlock(blocks[i], i, theme2, color) }, i));
3700
+ }
3701
+ return flush(blocks.length), /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box_default, { flexDirection: "column", children });
3653
3702
  }
3654
3703
 
3655
3704
  // src/main/tui/views/chat/model.ts
@@ -4122,8 +4171,8 @@ async function signIn(client, provider, signal, handlers) {
4122
4171
  // src/main/tui/auth/AuthDialog.tsx
4123
4172
  var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
4124
4173
  function AuthDialog({ overlay, close, width }) {
4125
- let theme2 = useTheme(), store = useStore(), auth = useTuiSelector((s) => s.auth), props = overlay.props ?? {}, [cursor, setCursor] = (0, import_react15.useState)(Math.max(0, SUBSCRIPTIONS.indexOf(props.login ?? "chatgpt"))), [flow, setFlow] = (0, import_react15.useState)({ kind: "list" }), [note, setNote] = (0, import_react15.useState)(null), [pasted, setPasted] = (0, import_react15.useState)(""), abort = (0, import_react15.useRef)(null), dialogWidth = Math.max(50, Math.min(width - 4, 84));
4126
- (0, import_react15.useEffect)(() => (store.actions.refreshAuth(), props.login && start(props.login), () => abort.current?.abort()), []);
4174
+ let theme2 = useTheme(), store = useStore(), auth = useTuiSelector((s) => s.auth), props = overlay.props ?? {}, [cursor, setCursor] = (0, import_react16.useState)(Math.max(0, SUBSCRIPTIONS.indexOf(props.login ?? "chatgpt"))), [flow, setFlow] = (0, import_react16.useState)({ kind: "list" }), [note, setNote] = (0, import_react16.useState)(null), [pasted, setPasted] = (0, import_react16.useState)(""), abort = (0, import_react16.useRef)(null), dialogWidth = Math.max(50, Math.min(width - 4, 84));
4175
+ (0, import_react16.useEffect)(() => (store.actions.refreshAuth(), props.login && start(props.login), () => abort.current?.abort()), []);
4127
4176
  let start = (provider) => {
4128
4177
  abort.current?.abort();
4129
4178
  let ctrl = new AbortController();
@@ -4306,11 +4355,11 @@ function TerminalSetupDialog({ close, width, height }) {
4306
4355
  }
4307
4356
 
4308
4357
  // src/main/tui/setup/WelcomeDialog.tsx
4309
- var import_react16 = __toESM(require_react(), 1);
4358
+ var import_react17 = __toESM(require_react(), 1);
4310
4359
  var import_jsx_runtime20 = __toESM(require_jsx_runtime(), 1), LABEL = 21;
4311
4360
  function WelcomeDialog({ close, width, height }) {
4312
- let theme2 = useTheme(), store = useStore(), { registry, exit } = useShell(), identity = useTuiSelector((s) => s.identity), auth = useTuiSelector((s) => s.auth), agents = useTuiSelector((s) => s.agents), agentOrder = useTuiSelector((s) => s.agentOrder), [extras, setExtras] = (0, import_react16.useState)({ adapters: {}, timers: {} });
4313
- (0, import_react16.useEffect)(() => {
4361
+ let theme2 = useTheme(), store = useStore(), { registry, exit } = useShell(), identity = useTuiSelector((s) => s.identity), auth = useTuiSelector((s) => s.auth), agents = useTuiSelector((s) => s.agents), agentOrder = useTuiSelector((s) => s.agentOrder), [extras, setExtras] = (0, import_react17.useState)({ adapters: {}, timers: {} });
4362
+ (0, import_react17.useEffect)(() => {
4314
4363
  let live = !0, ids = store.getState().agentOrder;
4315
4364
  return Promise.all(ids.map(async (id) => {
4316
4365
  let entry = store.getState().agents[id], [config2, timers] = await Promise.all([
@@ -4328,10 +4377,10 @@ function WelcomeDialog({ close, width, height }) {
4328
4377
  live = !1;
4329
4378
  };
4330
4379
  }, [store, agentOrder.join("|")]);
4331
- let steps = (0, import_react16.useMemo)(
4380
+ let steps = (0, import_react17.useMemo)(
4332
4381
  () => welcomeSteps(welcomeFacts({ identity, auth, agents, agentOrder }, extras)),
4333
4382
  [identity, auth, agents, agentOrder, extras]
4334
- ), [index, setIndex] = (0, import_react16.useState)(() => nextStepIndex(steps)), selected = Math.min(index, steps.length - 1), start = () => {
4383
+ ), [index, setIndex] = (0, import_react17.useState)(() => nextStepIndex(steps)), selected = Math.min(index, steps.length - 1), start = () => {
4335
4384
  let step = steps[selected];
4336
4385
  close(), step && runSlash(step.run, registry, store, exit);
4337
4386
  };
@@ -4366,10 +4415,10 @@ function WelcomeDialog({ close, width, height }) {
4366
4415
  }
4367
4416
 
4368
4417
  // src/main/tui/setup/ChannelsDialog.tsx
4369
- var import_react18 = __toESM(require_react(), 1);
4418
+ var import_react19 = __toESM(require_react(), 1);
4370
4419
 
4371
4420
  // src/main/tui/ui/List.tsx
4372
- var import_react17 = __toESM(require_react(), 1);
4421
+ var import_react18 = __toESM(require_react(), 1);
4373
4422
  var import_jsx_runtime21 = __toESM(require_jsx_runtime(), 1);
4374
4423
  function List(props) {
4375
4424
  let {
@@ -4388,19 +4437,19 @@ function List(props) {
4388
4437
  active = !0,
4389
4438
  emptyText = "Nothing here.",
4390
4439
  wheelSelects = !1
4391
- } = props, theme2 = useTheme(), [internalIndex, setInternalIndex] = (0, import_react17.useState)(0), [query, setQuery] = (0, import_react17.useState)(""), [filtering, setFiltering] = (0, import_react17.useState)(!1), offsetRef = (0, import_react17.useRef)(0), visible = (0, import_react17.useMemo)(
4440
+ } = props, theme2 = useTheme(), [internalIndex, setInternalIndex] = (0, import_react18.useState)(0), [query, setQuery] = (0, import_react18.useState)(""), [filtering, setFiltering] = (0, import_react18.useState)(!1), offsetRef = (0, import_react18.useRef)(0), visible = (0, import_react18.useMemo)(
4392
4441
  () => filter && query ? items.filter((item) => filter(item, query)) : items,
4393
4442
  [items, filter, query]
4394
4443
  ), showFilterBar = filtering || query.length > 0, bodyRows = Math.max(1, height - (showFilterBar ? 1 : 0)), perPage = Math.max(1, Math.floor(bodyRows / itemHeight2)), rawIndex = selectedIndex ?? internalIndex, index = visible.length === 0 ? 0 : Math.min(Math.max(0, rawIndex), visible.length - 1), select = (next) => {
4395
4444
  let clamped = visible.length === 0 ? 0 : Math.min(Math.max(0, next), visible.length - 1);
4396
4445
  selectedIndex === void 0 && setInternalIndex(clamped), onSelectedIndexChange?.(clamped, visible[clamped]);
4397
4446
  };
4398
- (0, import_react17.useEffect)(() => {
4447
+ (0, import_react18.useEffect)(() => {
4399
4448
  rawIndex !== index && visible.length > 0 && select(index);
4400
4449
  }, [rawIndex, index, visible.length]);
4401
- let revealed = (0, import_react17.useRef)(null), [, redraw] = (0, import_react17.useState)(0);
4450
+ let revealed = (0, import_react18.useRef)(null), [, redraw] = (0, import_react18.useState)(0);
4402
4451
  revealed.current !== `${index}|${perPage}` && (revealed.current = `${index}|${perPage}`, index < offsetRef.current && (offsetRef.current = index), index >= offsetRef.current + perPage && (offsetRef.current = index - perPage + 1)), offsetRef.current = Math.max(0, Math.min(offsetRef.current, Math.max(0, visible.length - perPage)));
4403
- let boxRef = (0, import_react17.useRef)(null);
4452
+ let boxRef = (0, import_react18.useRef)(null);
4404
4453
  useWheel(boxRef, (delta) => {
4405
4454
  if (wheelSelects) {
4406
4455
  select(index + delta * WHEEL_STEP);
@@ -4484,8 +4533,8 @@ function LockedCredential({ name, title, width, confirming, onUnlock, onReplace,
4484
4533
  // src/main/tui/setup/ChannelsDialog.tsx
4485
4534
  var import_jsx_runtime23 = __toESM(require_jsx_runtime(), 1), POLL_MS = 1e3, POLL_FOR_MS = 2e4;
4486
4535
  function ChannelsDialog({ overlay, close, width, height }) {
4487
- let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, agentId = props.agentId ?? store.getState().selectedAgentId ?? "", agent2 = useTuiSelector((s) => s.agents[agentId]), who = agent2?.summary.handle || agent2?.summary.name || agentId, entries = (0, import_react18.useMemo)(channelEntries, []), direct = findChannel(props.channel), [step, setStep] = (0, import_react18.useState)(direct ? { kind: "form", entry: direct, editing: !1 } : { kind: "list" }), [index, setIndex] = (0, import_react18.useState)(0), [diag, setDiag] = (0, import_react18.useState)(null), [values, setValues] = (0, import_react18.useState)({}), [errors, setErrors] = (0, import_react18.useState)({}), [formError, setFormError] = (0, import_react18.useState)(null), [stored, setStored] = (0, import_react18.useState)(null), alive = (0, import_react18.useRef)(!0);
4488
- (0, import_react18.useEffect)(() => () => {
4536
+ let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, agentId = props.agentId ?? store.getState().selectedAgentId ?? "", agent2 = useTuiSelector((s) => s.agents[agentId]), who = agent2?.summary.handle || agent2?.summary.name || agentId, entries = (0, import_react19.useMemo)(channelEntries, []), direct = findChannel(props.channel), [step, setStep] = (0, import_react19.useState)(direct ? { kind: "form", entry: direct, editing: !1 } : { kind: "list" }), [index, setIndex] = (0, import_react19.useState)(0), [diag, setDiag] = (0, import_react19.useState)(null), [values, setValues] = (0, import_react19.useState)({}), [errors, setErrors] = (0, import_react19.useState)({}), [formError, setFormError] = (0, import_react19.useState)(null), [stored, setStored] = (0, import_react19.useState)(null), alive = (0, import_react19.useRef)(!0);
4537
+ (0, import_react19.useEffect)(() => () => {
4489
4538
  alive.current = !1;
4490
4539
  }, []);
4491
4540
  let configured = diag ? diag.configured.map((c) => c.type) : configuredChannels(agent2?.config), isOn = (type) => configured.includes(type), stateOf = (type) => adapterLiveState(diag, type), refresh2 = async () => {
@@ -4496,9 +4545,9 @@ function ChannelsDialog({ overlay, close, width, height }) {
4496
4545
  return null;
4497
4546
  }
4498
4547
  };
4499
- (0, import_react18.useEffect)(() => {
4548
+ (0, import_react19.useEffect)(() => {
4500
4549
  agentId && refresh2();
4501
- }, [agentId]), (0, import_react18.useEffect)(() => {
4550
+ }, [agentId]), (0, import_react19.useEffect)(() => {
4502
4551
  if (step.kind !== "detail") return;
4503
4552
  let stopped = !1, timer, started = Date.now(), tick = async () => {
4504
4553
  let d = await refresh2();
@@ -4756,10 +4805,10 @@ function LiveLine({ state }) {
4756
4805
  }
4757
4806
 
4758
4807
  // src/main/tui/setup/ProviderDialog.tsx
4759
- var import_react20 = __toESM(require_react(), 1);
4808
+ var import_react21 = __toESM(require_react(), 1);
4760
4809
 
4761
4810
  // src/main/tui/views/inspect/model-picker.tsx
4762
- var import_react19 = __toESM(require_react(), 1);
4811
+ var import_react20 = __toESM(require_react(), 1);
4763
4812
  var import_jsx_runtime24 = __toESM(require_jsx_runtime(), 1), MODEL_OVERLAY = "inspect.model";
4764
4813
  function providerChoices(providers, auth) {
4765
4814
  return providers.map((p) => {
@@ -4805,8 +4854,8 @@ async function applyModel(store, agentId, loop, choice) {
4805
4854
  return await actions4.run("Model", (c) => c.putConfig(agentId, next)) ? (await actions4.loadConfig(agentId), actions4.toast(`${who} now runs ${choice.provider}/${choice.model}`, "success"), !0) : !1;
4806
4855
  }
4807
4856
  function ModelOverlay({ overlay, close, width }) {
4808
- let theme2 = useTheme(), store = useStore(), agentId = String(overlay.props?.agentId ?? ""), loop = String(overlay.props?.loop ?? MAIN_LOOP), current = currentModel(store.getState(), agentId, loop), [providers, setProviders] = (0, import_react19.useState)(null), [models, setModels] = (0, import_react19.useState)(null), [error, setError] = (0, import_react19.useState)(null), [step, setStep] = (0, import_react19.useState)({ kind: "provider" }), [query, setQuery] = (0, import_react19.useState)(""), [index, setIndex] = (0, import_react19.useState)(0);
4809
- (0, import_react19.useEffect)(() => {
4857
+ let theme2 = useTheme(), store = useStore(), agentId = String(overlay.props?.agentId ?? ""), loop = String(overlay.props?.loop ?? MAIN_LOOP), current = currentModel(store.getState(), agentId, loop), [providers, setProviders] = (0, import_react20.useState)(null), [models, setModels] = (0, import_react20.useState)(null), [error, setError] = (0, import_react20.useState)(null), [step, setStep] = (0, import_react20.useState)({ kind: "provider" }), [query, setQuery] = (0, import_react20.useState)(""), [index, setIndex] = (0, import_react20.useState)(0);
4858
+ (0, import_react20.useEffect)(() => {
4810
4859
  store.client.providers().then(
4811
4860
  (d) => {
4812
4861
  let list = providerChoices(d.providers, store.getState().auth);
@@ -4825,7 +4874,7 @@ function ModelOverlay({ overlay, close, width }) {
4825
4874
  setModels([]), setError(err instanceof Error ? err.message : String(err));
4826
4875
  }
4827
4876
  );
4828
- }, providerRows2 = [...loop === MAIN_LOOP ? [] : [{ id: "", name: "inherit", type: "", access: "use the agent\u2019s model", ready: !0 }], ...providers ?? []], shownModels = (0, import_react19.useMemo)(() => (models ?? []).filter((m) => m.toLowerCase().includes(query.toLowerCase())), [models, query]), apply = (choice) => {
4877
+ }, providerRows2 = [...loop === MAIN_LOOP ? [] : [{ id: "", name: "inherit", type: "", access: "use the agent\u2019s model", ready: !0 }], ...providers ?? []], shownModels = (0, import_react20.useMemo)(() => (models ?? []).filter((m) => m.toLowerCase().includes(query.toLowerCase())), [models, query]), apply = (choice) => {
4829
4878
  close(), applyModel(store, agentId, loop, choice);
4830
4879
  };
4831
4880
  useKeys((input, key) => key.escape || key.ctrl && input === "c" ? step.kind === "model" && !(key.ctrl && input === "c") ? query ? (setQuery(""), !0) : (setStep({ kind: "provider" }), setIndex(Math.max(0, providerRows2.findIndex((p) => p.id === step.provider.id))), !0) : (close(), !0) : step.kind !== "model" || key.ctrl || key.meta ? !1 : key.backspace || key.delete ? (setQuery((q) => q.slice(0, -1)), setIndex(0), !0) : key.leftArrow ? (setStep({ kind: "provider" }), !0) : input && !/[\u0000-\u001f\u007f]/.test(input) && !key.return && !key.tab ? (setQuery((q) => q + input), setIndex(0), !0) : !1, { layer: "overlay" });
@@ -4958,8 +5007,8 @@ var complete = (partial) => ["chatgpt", "grok", "claude"].filter((v) => v.starts
4958
5007
  // src/main/tui/setup/ProviderDialog.tsx
4959
5008
  var import_jsx_runtime25 = __toESM(require_jsx_runtime(), 1), GROUP_LABEL = { subscription: "sign in", api: "API key", local: "local", other: "any URL" };
4960
5009
  function ProviderDialog({ overlay, close, width, height }) {
4961
- let theme2 = useTheme(), store = useStore(), rows = (0, import_react20.useMemo)(providerRows, []), preset = findProviderRow(String(overlay.props?.preset ?? "")), [step, setStep] = (0, import_react20.useState)(preset && !preset.signIn ? { kind: "form", entry: preset.entry } : { kind: "pick" }), [index, setIndex] = (0, import_react20.useState)(() => Math.max(0, rows.findIndex((r) => r.entry.group === "api"))), [values, setValues] = (0, import_react20.useState)(() => preset && !preset.signIn ? initialValues(preset.entry) : {}), [errors, setErrors] = (0, import_react20.useState)({}), [formError, setFormError] = (0, import_react20.useState)(null), alive = (0, import_react20.useRef)(!0);
4962
- (0, import_react20.useEffect)(() => () => {
5010
+ let theme2 = useTheme(), store = useStore(), rows = (0, import_react21.useMemo)(providerRows, []), preset = findProviderRow(String(overlay.props?.preset ?? "")), [step, setStep] = (0, import_react21.useState)(preset && !preset.signIn ? { kind: "form", entry: preset.entry } : { kind: "pick" }), [index, setIndex] = (0, import_react21.useState)(() => Math.max(0, rows.findIndex((r) => r.entry.group === "api"))), [values, setValues] = (0, import_react21.useState)(() => preset && !preset.signIn ? initialValues(preset.entry) : {}), [errors, setErrors] = (0, import_react21.useState)({}), [formError, setFormError] = (0, import_react21.useState)(null), alive = (0, import_react21.useRef)(!0);
5011
+ (0, import_react21.useEffect)(() => () => {
4963
5012
  alive.current = !1;
4964
5013
  }, []);
4965
5014
  let dialogWidth = Math.max(50, Math.min(width - 4, 84)), inner = dialogWidth - 4, choose = (row4) => {
@@ -5099,20 +5148,20 @@ function initialValues(entry) {
5099
5148
  }
5100
5149
 
5101
5150
  // src/main/tui/setup/McpDialog.tsx
5102
- var import_react21 = __toESM(require_react(), 1);
5151
+ var import_react22 = __toESM(require_react(), 1);
5103
5152
  var import_jsx_runtime26 = __toESM(require_jsx_runtime(), 1);
5104
5153
  function McpDialog({ overlay, close, width, height }) {
5105
- let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, agentId = props.agentId ?? store.getState().selectedAgentId ?? "", agent2 = useTuiSelector((s) => s.agents[agentId]), who = agent2?.summary.handle || agent2?.summary.name || agentId, sources2 = (0, import_react21.useMemo)(mcpSourceRows, []), [diag, setDiag] = (0, import_react21.useState)(null), [config2, setConfig] = (0, import_react21.useState)(null), [loadError, setLoadError] = (0, import_react21.useState)(null), initial = () => {
5154
+ let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, agentId = props.agentId ?? store.getState().selectedAgentId ?? "", agent2 = useTuiSelector((s) => s.agents[agentId]), who = agent2?.summary.handle || agent2?.summary.name || agentId, sources2 = (0, import_react22.useMemo)(mcpSourceRows, []), [diag, setDiag] = (0, import_react22.useState)(null), [config2, setConfig] = (0, import_react22.useState)(null), [loadError, setLoadError] = (0, import_react22.useState)(null), initial = () => {
5106
5155
  if (props.add !== void 0) {
5107
5156
  let target2 = parseAddTarget(props.add);
5108
5157
  return target2.row ? { kind: "form", row: target2.row } : { kind: "source" };
5109
5158
  }
5110
5159
  return props.server ? { kind: props.view === "logs" ? "logs" : "detail", name: props.server } : { kind: "list" };
5111
- }, [step, setStep] = (0, import_react21.useState)(initial), [index, setIndex] = (0, import_react21.useState)(0), [values, setValues] = (0, import_react21.useState)(() => {
5160
+ }, [step, setStep] = (0, import_react22.useState)(initial), [index, setIndex] = (0, import_react22.useState)(0), [values, setValues] = (0, import_react22.useState)(() => {
5112
5161
  let target2 = parseAddTarget(props.add);
5113
5162
  return target2.row ? initialForm(target2.row, target2.value) : {};
5114
- }), [errors, setErrors] = (0, import_react21.useState)({}), [formError, setFormError] = (0, import_react21.useState)(null), [stored, setStored] = (0, import_react21.useState)(null), pending = (0, import_react21.useRef)(null), alive = (0, import_react21.useRef)(!0);
5115
- (0, import_react21.useEffect)(() => () => {
5163
+ }), [errors, setErrors] = (0, import_react22.useState)({}), [formError, setFormError] = (0, import_react22.useState)(null), [stored, setStored] = (0, import_react22.useState)(null), pending = (0, import_react22.useRef)(null), alive = (0, import_react22.useRef)(!0);
5164
+ (0, import_react22.useEffect)(() => () => {
5116
5165
  alive.current = !1;
5117
5166
  }, []);
5118
5167
  let direct = props.add !== void 0 || !!props.server, refresh2 = async () => {
@@ -5124,13 +5173,13 @@ function McpDialog({ overlay, close, width, height }) {
5124
5173
  alive.current && setLoadError(err instanceof Error ? err.message : String(err));
5125
5174
  }
5126
5175
  };
5127
- (0, import_react21.useEffect)(() => {
5176
+ (0, import_react22.useEffect)(() => {
5128
5177
  agentId && refresh2();
5129
5178
  }, [agentId]);
5130
5179
  let servers = config2?.mcp?.servers ?? [], stateOf = (name2) => diag?.states.find((s) => s.name === name2), serverOf = (name2) => servers.find((s) => s.name === name2), hostAllowed = !!config2?.compute?.host_access, dialogWidth = Math.max(56, Math.min(width - 4, 96)), inner = dialogWidth - 4, back = () => {
5131
5180
  direct ? close() : setStep({ kind: "list" });
5132
5181
  };
5133
- (0, import_react21.useEffect)(() => {
5182
+ (0, import_react22.useEffect)(() => {
5134
5183
  config2 && !hostAllowed && values.runOn === "host" && setValues((v) => ({ ...v, runOn: "container" }));
5135
5184
  }, [config2, step.kind]);
5136
5185
  let restart = async (name2) => {
@@ -5630,7 +5679,7 @@ function parseEnvPairs(text) {
5630
5679
  }
5631
5680
 
5632
5681
  // src/main/tui/templates/TemplatesDialog.tsx
5633
- var import_react22 = __toESM(require_react(), 1);
5682
+ var import_react23 = __toESM(require_react(), 1);
5634
5683
 
5635
5684
  // src/main/tui/templates/model.ts
5636
5685
  var TEMPLATES_OVERLAY = "templates", SHIPPED_ORDER = ["standard", "sandboxed", "full-access"], INSTANTIATE_RULE = "New agents get everything in a template except its identity and history.", NAME_HINT = "Use letters, digits, dashes, underscores and spaces.", NAME_RULE = /^[A-Za-z0-9 _-]+$/;
@@ -5947,9 +5996,9 @@ function errorOf(err) {
5947
5996
  return { message: err instanceof Error ? err.message : String(err) };
5948
5997
  }
5949
5998
  function TemplatesDialog({ overlay, close: closeOverlay, width, height }) {
5950
- let theme2 = useTheme(), store = useStore(), { suspendTerminal } = use_app_default(), props = overlay.props ?? {}, slotKey = `${TEMPLATES_OVERLAY}.dialog:${overlay.id}`, initial = (0, import_react22.useRef)({ step: props.id ? { kind: "detail", id: props.id } : { kind: "list" }, index: 0, fileIndex: 0, list: null, detail: null, loadError: null, error: null }).current, read = () => store.getState().viewState[slotKey] ?? initial, patch = (next) => store.actions.setViewState(slotKey, { ...read(), ...next }), { step, index, fileIndex, list, detail, loadError, error } = useTuiSelector((s) => s.viewState[slotKey] ?? initial), setList = (value) => patch({ list: value }), setDetail = (value) => patch({ detail: value }), setLoadError = (value) => patch({ loadError: value }), setError = (value) => patch({ error: value }), setStep = (value) => patch({ step: value }), setIndex = (value) => patch({ index: value }), setFileIndex = (value) => patch({ fileIndex: value }), close = () => {
5999
+ let theme2 = useTheme(), store = useStore(), { suspendTerminal } = use_app_default(), props = overlay.props ?? {}, slotKey = `${TEMPLATES_OVERLAY}.dialog:${overlay.id}`, initial = (0, import_react23.useRef)({ step: props.id ? { kind: "detail", id: props.id } : { kind: "list" }, index: 0, fileIndex: 0, list: null, detail: null, loadError: null, error: null }).current, read = () => store.getState().viewState[slotKey] ?? initial, patch = (next) => store.actions.setViewState(slotKey, { ...read(), ...next }), { step, index, fileIndex, list, detail, loadError, error } = useTuiSelector((s) => s.viewState[slotKey] ?? initial), setList = (value) => patch({ list: value }), setDetail = (value) => patch({ detail: value }), setLoadError = (value) => patch({ loadError: value }), setError = (value) => patch({ error: value }), setStep = (value) => patch({ step: value }), setIndex = (value) => patch({ index: value }), setFileIndex = (value) => patch({ fileIndex: value }), close = () => {
5951
6000
  closeOverlay(), store.actions.setViewState(slotKey, null);
5952
- }, [values, setValues] = (0, import_react22.useState)({}), [errors, setErrors] = (0, import_react22.useState)({}), dialogWidth = Math.max(56, Math.min(width - 4, 104)), inner = dialogWidth - 4, templates = sortTemplates(list?.templates ?? []), byId = (id) => templates.find((t) => t.id === id), label2 = (id) => byId(id)?.name ?? id, loadList = async () => {
6001
+ }, [values, setValues] = (0, import_react23.useState)({}), [errors, setErrors] = (0, import_react23.useState)({}), dialogWidth = Math.max(56, Math.min(width - 4, 104)), inner = dialogWidth - 4, templates = sortTemplates(list?.templates ?? []), byId = (id) => templates.find((t) => t.id === id), label2 = (id) => byId(id)?.name ?? id, loadList = async () => {
5953
6002
  try {
5954
6003
  let next = await store.client.templates();
5955
6004
  patch({ list: next, loadError: null });
@@ -5966,11 +6015,11 @@ function TemplatesDialog({ overlay, close: closeOverlay, width, height }) {
5966
6015
  }, refresh2 = async (id) => {
5967
6016
  await loadList(), id && await loadDetail(id);
5968
6017
  };
5969
- (0, import_react22.useEffect)(() => {
6018
+ (0, import_react23.useEffect)(() => {
5970
6019
  !read().list && !read().loadError && refresh2(props.id);
5971
6020
  }, []);
5972
6021
  let stepId = "id" in step ? step.id : void 0;
5973
- (0, import_react22.useEffect)(() => {
6022
+ (0, import_react23.useEffect)(() => {
5974
6023
  (step.kind === "detail" || step.kind === "files") && step.id !== detail?.template?.id && loadDetail(step.id);
5975
6024
  }, [step.kind, stepId]);
5976
6025
  let act = async (labelText, back, fn) => {
@@ -6298,7 +6347,7 @@ function TemplatesDialog({ overlay, close: closeOverlay, width, height }) {
6298
6347
  }
6299
6348
 
6300
6349
  // src/main/tui/skills/SkillsDialog.tsx
6301
- var import_react23 = __toESM(require_react(), 1);
6350
+ var import_react24 = __toESM(require_react(), 1);
6302
6351
 
6303
6352
  // src/shared/utils/skill-preview.ts
6304
6353
  var skill_preview_exports = {};
@@ -6619,25 +6668,8 @@ function describeDiff(before, after, preview = 6) {
6619
6668
  return diff.changes.length > preview && lines.push(` \u2026 ${diff.changes.length - preview} more changed lines`), { summary, lines };
6620
6669
  }
6621
6670
 
6622
- // src/shared/types/resource-revision.types.ts
6623
- var resource_revision_types_exports = {};
6624
- __export(resource_revision_types_exports, {
6625
- describeWriter: () => describeWriter
6626
- });
6627
- function describeWriter(writer2) {
6628
- if (!writer2) return "someone else";
6629
- switch (writer2.kind) {
6630
- case "agent":
6631
- return "the agent";
6632
- case "cli":
6633
- return "the CLI or another API client";
6634
- case "client":
6635
- return writer2.client === "studio" ? "another Studio window" : writer2.client === "tui" ? "the terminal app" : `another client (${writer2.client})`;
6636
- }
6637
- }
6638
-
6639
6671
  // src/main/tui/util/revisions.ts
6640
- var { describeWriter: describeWriter2 } = cjs(resource_revision_types_exports);
6672
+ var { describeWriter } = cjs(resource_revision_types_exports);
6641
6673
  function revisionOf(result) {
6642
6674
  let revision = result?.revision;
6643
6675
  return typeof revision == "number" ? revision : void 0;
@@ -6648,7 +6680,7 @@ function staleRevisionOf(err) {
6648
6680
  return body?.code !== "stale_revision" || typeof body.revision != "number" ? null : { revision: body.revision, writer: body.writer ?? null };
6649
6681
  }
6650
6682
  function changedBy(stale) {
6651
- return `changed by ${describeWriter2(stale.writer)}`;
6683
+ return `changed by ${describeWriter(stale.writer)}`;
6652
6684
  }
6653
6685
  async function writeOver(write2) {
6654
6686
  try {
@@ -7133,7 +7165,7 @@ async function readLocalPackage(input, cwd = process.cwd()) {
7133
7165
  // src/main/tui/skills/SkillsDialog.tsx
7134
7166
  var import_jsx_runtime28 = __toESM(require_jsx_runtime(), 1), { catalogSourceLabel: catalogSourceLabel2, filterCatalogEntries: filterCatalogEntries2, mergeCatalogResults: mergeCatalogResults2, unindexedHint: unindexedHint2, MAX_SKILL_FILE_BYTES: MAX_SKILL_FILE_BYTES3 } = cjs(skills_panel_exports), { elideMiddle: elideMiddle2 } = cjs(skill_preview_exports), errorText3 = (err) => err instanceof Error ? err.message : String(err);
7135
7167
  function SkillsDialog({ overlay, close, width, height }) {
7136
- let theme2 = useTheme(), store = useStore(), { suspendTerminal } = use_app_default(), props = overlay.props ?? {}, agentId = props.agentId ?? store.getState().selectedAgentId ?? "", agent2 = useTuiSelector((s) => s.agents[agentId]), who = agent2?.summary.handle || agent2?.summary.name || agentId, direct = props.add !== void 0 || !!props.skill, fresh = (0, import_react23.useMemo)(() => {
7168
+ let theme2 = useTheme(), store = useStore(), { suspendTerminal } = use_app_default(), props = overlay.props ?? {}, agentId = props.agentId ?? store.getState().selectedAgentId ?? "", agent2 = useTuiSelector((s) => s.agents[agentId]), who = agent2?.summary.handle || agent2?.summary.name || agentId, direct = props.add !== void 0 || !!props.skill, fresh = (0, import_react24.useMemo)(() => {
7137
7169
  let start = initialStep(props);
7138
7170
  return { ...EMPTY_VIEW_STATE, overlayId: overlay.id, step: start.step, query: start.query, extra: start.extra };
7139
7171
  }, [overlay.id]), raw = useTuiSelector((s) => s.viewState[SKILLS_OVERLAY]), vs = raw && raw.overlayId === overlay.id ? raw : fresh, read = () => {
@@ -7145,13 +7177,13 @@ function SkillsDialog({ overlay, close, width, height }) {
7145
7177
  let base2 = read();
7146
7178
  store.actions.setViewState(SKILLS_OVERLAY, { ...base2, ...typeof next == "function" ? next(base2) : next, overlayId: overlay.id });
7147
7179
  };
7148
- (0, import_react23.useEffect)(() => {
7180
+ (0, import_react24.useEffect)(() => {
7149
7181
  (!raw || raw.overlayId !== overlay.id) && patch({});
7150
7182
  }, [overlay.id]);
7151
- let step = vs.step, setStep = (next) => patch({ step: next }), [data, setData] = (0, import_react23.useState)(null), [loadError, setLoadError] = (0, import_react23.useState)(null), alive = (0, import_react23.useRef)(!0);
7152
- (0, import_react23.useEffect)(() => () => {
7183
+ let step = vs.step, setStep = (next) => patch({ step: next }), [data, setData] = (0, import_react24.useState)(null), [loadError, setLoadError] = (0, import_react24.useState)(null), alive = (0, import_react24.useRef)(!0);
7184
+ (0, import_react24.useEffect)(() => () => {
7153
7185
  alive.current = !1;
7154
- }, []), (0, import_react23.useEffect)(() => {
7186
+ }, []), (0, import_react24.useEffect)(() => {
7155
7187
  if (!agentId) return;
7156
7188
  let cancelled = !1;
7157
7189
  return loadInstalled(store.client, agentId).then((next) => {
@@ -7162,13 +7194,13 @@ function SkillsDialog({ overlay, close, width, height }) {
7162
7194
  cancelled = !0;
7163
7195
  };
7164
7196
  }, [agentId, vs.rev]);
7165
- let model2 = (0, import_react23.useMemo)(() => data ? buildInstalled(data.files, data.registryText, vs.overrides) : null, [data, vs.overrides]), rows = (0, import_react23.useMemo)(() => model2 ? [
7197
+ let model2 = (0, import_react24.useMemo)(() => data ? buildInstalled(data.files, data.registryText, vs.overrides) : null, [data, vs.overrides]), rows = (0, import_react24.useMemo)(() => model2 ? [
7166
7198
  ...model2.skills.map((skill) => ({ type: "skill", key: `s:${skill.name}`, skill })),
7167
7199
  ...model2.problems.map((p) => ({ type: "problem", key: `p:${p.key}`, label: p.label, path: p.path, reason: p.reason, isPackage: p.isPackage }))
7168
7200
  ] : [], [model2]), bump = () => {
7169
7201
  patch((s) => ({ rev: s.rev + 1 })), setTimeout(() => patch((s) => ({ rev: s.rev + 1 })), 700);
7170
7202
  }, needsCatalog = step.kind === "catalog" || step.kind === "package" && step.source.type === "catalog";
7171
- (0, import_react23.useEffect)(() => {
7203
+ (0, import_react24.useEffect)(() => {
7172
7204
  if (!needsCatalog || read().catalog) return;
7173
7205
  let extra = read().extra;
7174
7206
  patch({ catalog: { loading: !0, sources: extra, results: [] } }), (async () => {
@@ -7183,18 +7215,18 @@ function SkillsDialog({ overlay, close, width, height }) {
7183
7215
  }
7184
7216
  })();
7185
7217
  }, [needsCatalog]);
7186
- let merged = (0, import_react23.useMemo)(() => mergeCatalogResults2(vs.catalog?.results ?? []), [vs.catalog?.results]), visible = (0, import_react23.useMemo)(() => filterCatalogEntries2(merged, vs.query), [merged, vs.query]), pkgKey = step.kind === "package" ? packageKey(step.source) : null, pkgState = pkgKey ? vs.packages[pkgKey] : void 0, loadPkg = (force = !1) => {
7218
+ let merged = (0, import_react24.useMemo)(() => mergeCatalogResults2(vs.catalog?.results ?? []), [vs.catalog?.results]), visible = (0, import_react24.useMemo)(() => filterCatalogEntries2(merged, vs.query), [merged, vs.query]), pkgKey = step.kind === "package" ? packageKey(step.source) : null, pkgState = pkgKey ? vs.packages[pkgKey] : void 0, loadPkg = (force = !1) => {
7187
7219
  if (step.kind !== "package" || !pkgKey || !force && read().packages[pkgKey]) return;
7188
7220
  let source = step.source;
7189
7221
  patch((s) => ({ packages: { ...s.packages, [pkgKey]: { status: "loading" } } })), loadPackage(source).then((result) => {
7190
7222
  patch((s) => ({ packages: { ...s.packages, [pkgKey]: result.ok ? { status: "ready", pkg: result.pkg } : { status: "error", error: result.error } } }));
7191
7223
  }, (err) => patch((s) => ({ packages: { ...s.packages, [pkgKey]: { status: "error", error: errorText3(err) } } })));
7192
7224
  };
7193
- (0, import_react23.useEffect)(() => {
7225
+ (0, import_react24.useEffect)(() => {
7194
7226
  loadPkg();
7195
7227
  }, [pkgKey]);
7196
- let [doc, setDoc] = (0, import_react23.useState)(null), viewPath = step.kind === "view" ? step.path : null;
7197
- (0, import_react23.useEffect)(() => {
7228
+ let [doc, setDoc] = (0, import_react24.useState)(null), viewPath = step.kind === "view" ? step.path : null;
7229
+ (0, import_react24.useEffect)(() => {
7198
7230
  if (!viewPath || !agentId) return;
7199
7231
  let cancelled = !1;
7200
7232
  return readSkillFile(store.client, agentId, viewPath).then(
@@ -7431,7 +7463,7 @@ function CatalogRow({ entry, installed, selected, width }) {
7431
7463
  ] });
7432
7464
  }
7433
7465
  function SkillDoc({ manifest, width, height }) {
7434
- let theme2 = useTheme(), parts = (0, import_react23.useMemo)(() => previewParts(manifest), [manifest]), [offset, setOffset] = (0, import_react23.useState)(0), innerRef = (0, import_react23.useRef)(null), outerRef = (0, import_react23.useRef)(null), metrics = use_box_metrics_default(innerRef), rows = Math.max(1, height - 1), total = metrics.hasMeasured ? metrics.height : 0, maxOffset = Math.max(0, total - rows), at = Math.min(offset, maxOffset), move = (next) => setOffset(Math.max(0, Math.min(maxOffset, next)));
7466
+ let theme2 = useTheme(), parts = (0, import_react24.useMemo)(() => previewParts(manifest), [manifest]), [offset, setOffset] = (0, import_react24.useState)(0), innerRef = (0, import_react24.useRef)(null), outerRef = (0, import_react24.useRef)(null), metrics = use_box_metrics_default(innerRef), rows = Math.max(1, height - 1), total = metrics.hasMeasured ? metrics.height : 0, maxOffset = Math.max(0, total - rows), at = Math.min(offset, maxOffset), move = (next) => setOffset(Math.max(0, Math.min(maxOffset, next)));
7435
7467
  useWheel(outerRef, (delta) => move(at + delta * WHEEL_STEP), { layer: "overlay" }), useKeys((input, key) => key.upArrow || input === "k" && !key.ctrl ? (move(at - 1), !0) : key.downArrow || input === "j" && !key.ctrl ? (move(at + 1), !0) : key.pageUp ? (move(at - rows), !0) : key.pageDown ? (move(at + rows), !0) : key.home || input === "g" ? (move(0), !0) : key.end || input === "G" ? (move(maxOffset), !0) : !1, { layer: "overlay" });
7436
7468
  let keyWidth = Math.min(16, Math.max(4, ...parts.fields.map((f) => f.key.length)) + 1);
7437
7469
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Box_default, { ref: outerRef, flexDirection: "column", width, height, marginTop: 1, children: [
@@ -7448,7 +7480,7 @@ function SkillDoc({ manifest, width, height }) {
7448
7480
  }
7449
7481
 
7450
7482
  // src/main/tui/context/ContextDialog.tsx
7451
- var import_react24 = __toESM(require_react(), 1);
7483
+ var import_react25 = __toESM(require_react(), 1);
7452
7484
 
7453
7485
  // src/main/tui/context/model.ts
7454
7486
  var { resolveLoopThreshold, calibrationNote } = cjs(context_breakdown_exports), CONTEXT_OVERLAY = "context";
@@ -7518,7 +7550,7 @@ function pressureColor(theme2, percent) {
7518
7550
  return p === "high" ? theme2.color.error : p === "warn" ? theme2.color.warn : theme2.color.success;
7519
7551
  }
7520
7552
  function ContextDialog({ overlay, close: closeOverlay, width, height }) {
7521
- let theme2 = useTheme(), store = useStore(), g = theme2.glyph, props = overlay.props ?? {}, agentId = props.agentId ?? "", slotKey = `${CONTEXT_OVERLAY}.dialog:${overlay.id}`, initial = (0, import_react24.useRef)({ loop: props.loop || MAIN_LOOP, data: null, error: null, loading: !1, compacting: !1, cursor: null, expanded: null, start: 0, measuredAt: null }).current, read = () => store.getState().viewState[slotKey] ?? initial, alive = () => store.getState().overlays.some((o) => o.id === overlay.id), patch = (next) => {
7553
+ let theme2 = useTheme(), store = useStore(), g = theme2.glyph, props = overlay.props ?? {}, agentId = props.agentId ?? "", slotKey = `${CONTEXT_OVERLAY}.dialog:${overlay.id}`, initial = (0, import_react25.useRef)({ loop: props.loop || MAIN_LOOP, data: null, error: null, loading: !1, compacting: !1, cursor: null, expanded: null, start: 0, measuredAt: null }).current, read = () => store.getState().viewState[slotKey] ?? initial, alive = () => store.getState().overlays.some((o) => o.id === overlay.id), patch = (next) => {
7522
7554
  alive() && store.actions.setViewState(slotKey, { ...read(), ...next });
7523
7555
  }, s = useTuiSelector((state) => state.viewState[slotKey] ?? initial), agent2 = useTuiSelector((state) => state.agents[agentId]), close = () => {
7524
7556
  closeOverlay(), store.actions.setViewState(slotKey, null);
@@ -7536,7 +7568,7 @@ function ContextDialog({ overlay, close: closeOverlay, width, height }) {
7536
7568
  }
7537
7569
  }
7538
7570
  };
7539
- (0, import_react24.useEffect)(() => {
7571
+ (0, import_react25.useEffect)(() => {
7540
7572
  !read().data && !read().error && load(read().loop), agentId && !store.getState().agents[agentId]?.loops && store.actions.refreshLoops(agentId);
7541
7573
  }, []);
7542
7574
  let compact2 = async () => {
@@ -7550,7 +7582,7 @@ function ContextDialog({ overlay, close: closeOverlay, width, height }) {
7550
7582
  let done = await store.actions.compactLoop(agentId, loop);
7551
7583
  patch({ compacting: !1 }), done && await load(loop);
7552
7584
  }, categories = s.data?.categories ?? [], cursor = categoryIndex(categories, s.cursor), selected = categories[cursor], rows = contextRows(categories, s.expanded), cursorRow = rows.findIndex((r) => r.kind === "category" && r.category.id === selected?.id), dialogWidth = Math.max(40, Math.min(width - 4, 96)), inner = dialogWidth - 4, rowsHeight = Math.max(3, height - 16), start = windowStart(rows.length, Math.max(0, cursorRow), rowsHeight, s.start);
7553
- (0, import_react24.useEffect)(() => {
7585
+ (0, import_react25.useEffect)(() => {
7554
7586
  start !== s.start && patch({ start });
7555
7587
  }, [start]), useKeys((input, key) => {
7556
7588
  if (key.escape) return !1;
@@ -7761,7 +7793,7 @@ async function copySiteUrl(store, agentId) {
7761
7793
  }
7762
7794
 
7763
7795
  // src/main/tui/app/Shell.tsx
7764
- var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1), SIDEBAR_MIN_COLUMNS = 70, PROMPT_ROWS = 3, RESIZE_SETTLE_MS = 150, CLEAR_SCREEN = "\x1B[2J\x1B[H", DOUBLE_ESC_MS = 600, ViewErrorBoundary = class extends import_react25.Component {
7796
+ var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1), SIDEBAR_MIN_COLUMNS = 70, PROMPT_ROWS = 3, RESIZE_SETTLE_MS = 150, CLEAR_SCREEN = "\x1B[2J\x1B[H", DOUBLE_ESC_MS = 600, ViewErrorBoundary = class extends import_react26.Component {
7765
7797
  state = { error: null };
7766
7798
  static getDerivedStateFromError(error) {
7767
7799
  return { error };
@@ -7792,8 +7824,8 @@ function cycleLoop2(store, delta) {
7792
7824
  store.actions.selectLoop(agentId, loops2[(at + delta + loops2.length) % loops2.length].info.name);
7793
7825
  }
7794
7826
  function Shell() {
7795
- let theme2 = useTheme(), store = useStore(), router = useKeyRouter(), { views, exit, reserveRows = 0, reserveColumns = 0 } = useShell(), { columns: windowColumns, rows: windowRows } = use_window_size_default(), columns = Math.max(20, windowColumns - reserveColumns), rows = Math.max(6, windowRows - reserveRows), { write: write2 } = use_stdout_default(), { waitUntilRenderFlush } = use_app_default(), sized = (0, import_react25.useRef)(`${windowColumns}x${windowRows}`);
7796
- (0, import_react25.useEffect)(() => {
7827
+ let theme2 = useTheme(), store = useStore(), router = useKeyRouter(), { views, exit, reserveRows = 0, reserveColumns = 0 } = useShell(), { columns: windowColumns, rows: windowRows } = use_window_size_default(), columns = Math.max(20, windowColumns - reserveColumns), rows = Math.max(6, windowRows - reserveRows), { write: write2 } = use_stdout_default(), { waitUntilRenderFlush } = use_app_default(), sized = (0, import_react26.useRef)(`${windowColumns}x${windowRows}`);
7828
+ (0, import_react26.useEffect)(() => {
7797
7829
  let size = `${windowColumns}x${windowRows}`;
7798
7830
  if (sized.current === size) return;
7799
7831
  sized.current = size;
@@ -7806,23 +7838,23 @@ function Shell() {
7806
7838
  cancelled = !0, clearTimeout(timer);
7807
7839
  };
7808
7840
  }, [windowColumns, windowRows]);
7809
- let activeView = useActiveView(), focus = useFocus(), overlays = useOverlays(), toasts = useToasts(), viewRef = (0, import_react25.useRef)(null), sidebarRef = (0, import_react25.useRef)(null), promptRef = (0, import_react25.useRef)(null), sidebarHidden = useTuiSelector((s) => readLayout(s).sidebarHidden), headerRef = (0, import_react25.useRef)(null), headerHits = (0, import_react25.useMemo)(() => createHeaderHits(), []), metrics = use_box_metrics_default(viewRef), quitGuard = (0, import_react25.useMemo)(() => createQuitGuard(), []), lastEscAt = (0, import_react25.useRef)(0), view2 = views.find((v) => v.id === activeView) ?? views[0], showSidebar = !!view2 && !view2.fullWidth && !sidebarHidden && columns >= SIDEBAR_MIN_COLUMNS, sidebarWidth = Math.max(22, Math.min(34, Math.floor(columns * 0.24))), mainWidth = Math.max(10, columns - (showSidebar ? sidebarWidth : 0)), promptShown = !!view2 && view2.prompt !== !1, toastRows = Math.min(3, toasts.length), bodyHeight = Math.max(3, rows - 2 - toastRows), viewHeight = metrics.hasMeasured ? metrics.height : Math.max(1, bodyHeight - (promptShown ? PROMPT_ROWS : 0)), viewWidth = metrics.hasMeasured ? metrics.width : mainWidth, overlayOpen = overlays.length > 0, zones = [...showSidebar ? ["sidebar"] : [], "main", ...promptShown ? ["input"] : []];
7810
- (0, import_react25.useEffect)(() => {
7841
+ let activeView = useActiveView(), focus = useFocus(), overlays = useOverlays(), toasts = useToasts(), viewRef = (0, import_react26.useRef)(null), sidebarRef = (0, import_react26.useRef)(null), promptRef = (0, import_react26.useRef)(null), sidebarHidden = useTuiSelector((s) => readLayout(s).sidebarHidden), headerRef = (0, import_react26.useRef)(null), headerHits = (0, import_react26.useMemo)(() => createHeaderHits(), []), metrics = use_box_metrics_default(viewRef), quitGuard = (0, import_react26.useMemo)(() => createQuitGuard(), []), lastEscAt = (0, import_react26.useRef)(0), view2 = views.find((v) => v.id === activeView) ?? views[0], showSidebar = !!view2 && !view2.fullWidth && !sidebarHidden && columns >= SIDEBAR_MIN_COLUMNS, sidebarWidth = Math.max(22, Math.min(34, Math.floor(columns * 0.24))), mainWidth = Math.max(10, columns - (showSidebar ? sidebarWidth : 0)), promptShown = !!view2 && view2.prompt !== !1, toastRows = Math.min(3, toasts.length), bodyHeight = Math.max(3, rows - 2 - toastRows), viewHeight = metrics.hasMeasured ? metrics.height : Math.max(1, bodyHeight - (promptShown ? PROMPT_ROWS : 0)), viewWidth = metrics.hasMeasured ? metrics.width : mainWidth, overlayOpen = overlays.length > 0, zones = [...showSidebar ? ["sidebar"] : [], "main", ...promptShown ? ["input"] : []];
7842
+ (0, import_react26.useEffect)(() => {
7811
7843
  focus !== "tabs" && !zones.includes(focus) && store.actions.setFocus("main");
7812
- }, [focus, showSidebar, promptShown]), (0, import_react25.useEffect)(() => {
7844
+ }, [focus, showSidebar, promptShown]), (0, import_react26.useEffect)(() => {
7813
7845
  store.getState().viewState[TABS_CURSOR_KEY] && store.actions.setViewState(TABS_CURSOR_KEY, null);
7814
7846
  }, [activeView]);
7815
- let enterZone = (id) => id === "chat" && views.find((v) => v.id === id)?.prompt !== !1 ? "input" : "main", live = (0, import_react25.useRef)({ columns: windowColumns, rows: windowRows, promptShown });
7847
+ let enterZone = (id) => id === "chat" && views.find((v) => v.id === id)?.prompt !== !1 ? "input" : "main", live = (0, import_react26.useRef)({ columns: windowColumns, rows: windowRows, promptShown });
7816
7848
  live.current = { columns: windowColumns, rows: windowRows, promptShown };
7817
7849
  let { internal_eventEmitter: stdinEvents } = use_stdin_default();
7818
- (0, import_react25.useLayoutEffect)(() => {
7850
+ (0, import_react26.useLayoutEffect)(() => {
7819
7851
  if (!stdinEvents) return;
7820
7852
  let onInput = (data) => noteRawInput(typeof data == "string" ? data : String(data));
7821
7853
  return stdinEvents.prependListener("input", onInput), () => {
7822
7854
  stdinEvents.removeListener("input", onInput);
7823
7855
  };
7824
- }, [stdinEvents]), (0, import_react25.useEffect)(() => (setRepaint(() => write2("")), () => setRepaint(null)), [write2]);
7825
- let mouseCtl = (0, import_react25.useMemo)(() => createMouseController({
7856
+ }, [stdinEvents]), (0, import_react26.useEffect)(() => (setRepaint(() => write2("")), () => setRepaint(null)), [write2]);
7857
+ let mouseCtl = (0, import_react26.useMemo)(() => createMouseController({
7826
7858
  now: () => Date.now(),
7827
7859
  screen: getScreenText,
7828
7860
  paneAt: (x, y) => {
@@ -8813,10 +8845,10 @@ var url = {
8813
8845
  ], BUILTIN_COMMANDS = { commands, actions };
8814
8846
 
8815
8847
  // src/main/tui/ui/Table.tsx
8816
- var import_react26 = __toESM(require_react(), 1);
8848
+ var import_react27 = __toESM(require_react(), 1);
8817
8849
  var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
8818
8850
  function Table({ columns, rows, getKey, width, selectedIndex, height, emptyText = "No rows.", onWheel }) {
8819
- let theme2 = useTheme(), boxRef = (0, import_react26.useRef)(null);
8851
+ let theme2 = useTheme(), boxRef = (0, import_react27.useRef)(null);
8820
8852
  useWheel(boxRef, (delta) => onWheel?.(delta), { active: !!onWheel });
8821
8853
  let gap = 1, fixed = columns.reduce((sum, c) => sum + (c.width ?? 0), 0), flexible = columns.filter((c) => c.width === void 0), spare = Math.max(0, width - fixed - gap * (columns.length - 1) - 2), share = flexible.length ? Math.floor(spare / flexible.length) : 0, widths = columns.map((c) => c.width ?? Math.max(c.minWidth ?? 6, share)), bodyRows = height === void 0 ? rows.length : Math.max(0, height - 1), selected = selectedIndex ?? -1, start = selected >= bodyRows ? selected - bodyRows + 1 : 0, visible = rows.slice(start, start + bodyRows), line = (cells2) => cells2.join(" ".repeat(gap));
8822
8854
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Box_default, { ref: boxRef, flexDirection: "column", width, children: [
@@ -9187,12 +9219,12 @@ var agentsCommand = {
9187
9219
  };
9188
9220
 
9189
9221
  // src/main/tui/views/fleet/LoadDialog.tsx
9190
- var import_react27 = __toESM(require_react(), 1);
9222
+ var import_react28 = __toESM(require_react(), 1);
9191
9223
  import { existsSync as existsSync2, statSync as statSync2 } from "node:fs";
9192
9224
  import { sep as sep2 } from "node:path";
9193
9225
  var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1), LAST_DIR_KEY = "fleet.load.lastDir", MAX_CANDIDATES = 8;
9194
9226
  function LoadDialog({ overlay, close, width }) {
9195
- let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, [lastDir, setLastDir] = useViewState(LAST_DIR_KEY, ""), [value, setValue] = (0, import_react27.useState)(props.path ?? (lastDir || `${process.cwd()}${sep2}`)), [candidates, setCandidates] = (0, import_react27.useState)([]), [requireReview, setRequireReview] = (0, import_react27.useState)(!!props.requireReview), [start, setStart] = (0, import_react27.useState)(!!props.start), [problem, setProblem] = (0, import_react27.useState)(null), [warned, setWarned] = (0, import_react27.useState)(null), dialogWidth = Math.max(40, Math.min(width - 4, 90)), submit = (text) => {
9227
+ let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, [lastDir, setLastDir] = useViewState(LAST_DIR_KEY, ""), [value, setValue] = (0, import_react28.useState)(props.path ?? (lastDir || `${process.cwd()}${sep2}`)), [candidates, setCandidates] = (0, import_react28.useState)([]), [requireReview, setRequireReview] = (0, import_react28.useState)(!!props.requireReview), [start, setStart] = (0, import_react28.useState)(!!props.start), [problem, setProblem] = (0, import_react28.useState)(null), [warned, setWarned] = (0, import_react28.useState)(null), dialogWidth = Math.max(40, Math.min(width - 4, 90)), submit = (text) => {
9196
9228
  let raw = text.trim();
9197
9229
  if (!raw)
9198
9230
  return setProblem("Type a path to an .adf file"), !1;
@@ -9275,11 +9307,11 @@ function LoadDialog({ overlay, close, width }) {
9275
9307
  }
9276
9308
 
9277
9309
  // src/main/tui/views/fleet/TrackDialog.tsx
9278
- var import_react29 = __toESM(require_react(), 1);
9310
+ var import_react30 = __toESM(require_react(), 1);
9279
9311
  import { sep as sep3 } from "node:path";
9280
9312
 
9281
9313
  // src/main/tui/views/fleet/FolderAgentsDialog.tsx
9282
- var import_react28 = __toESM(require_react(), 1);
9314
+ var import_react29 = __toESM(require_react(), 1);
9283
9315
  var import_jsx_runtime34 = __toESM(require_jsx_runtime(), 1);
9284
9316
  function glyphOf(theme2, agent2) {
9285
9317
  if (agent2.error || agent2.status === "unreadable") return { glyph: theme2.glyph.cross, color: theme2.color.error };
@@ -9303,8 +9335,8 @@ function reviewLines2(info) {
9303
9335
  return triggers.length && lines.push(`Triggers: ${triggers.join(", ")}`), lines;
9304
9336
  }
9305
9337
  function FolderAgentsDialog({ overlay, close, width, height }) {
9306
- let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, folder = props.folder, [agents, setAgents] = (0, import_react28.useState)(props.result?.agents ?? null), [loadError, setLoadError] = (0, import_react28.useState)(null), [cursor, setCursor] = (0, import_react28.useState)(0), [mode, setMode] = (0, import_react28.useState)({ kind: "list" }), [busy, setBusy] = (0, import_react28.useState)(null), [note, setNote] = (0, import_react28.useState)(null), [rev, setRev] = (0, import_react28.useState)(props.result?.agents ? 0 : 1), [pendingReview, setPendingReview] = (0, import_react28.useState)(props.review ?? null), [errors, setErrors] = (0, import_react28.useState)(() => Object.fromEntries((props.result?.agents ?? []).filter((a) => a.error && a.status !== "unreadable").map((a) => [a.filePath, a.error]))), dialogWidth = Math.max(44, Math.min(width - 4, 100)), inner = dialogWidth - 4;
9307
- (0, import_react28.useEffect)(() => {
9338
+ let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, folder = props.folder, [agents, setAgents] = (0, import_react29.useState)(props.result?.agents ?? null), [loadError, setLoadError] = (0, import_react29.useState)(null), [cursor, setCursor] = (0, import_react29.useState)(0), [mode, setMode] = (0, import_react29.useState)({ kind: "list" }), [busy, setBusy] = (0, import_react29.useState)(null), [note, setNote] = (0, import_react29.useState)(null), [rev, setRev] = (0, import_react29.useState)(props.result?.agents ? 0 : 1), [pendingReview, setPendingReview] = (0, import_react29.useState)(props.review ?? null), [errors, setErrors] = (0, import_react29.useState)(() => Object.fromEntries((props.result?.agents ?? []).filter((a) => a.error && a.status !== "unreadable").map((a) => [a.filePath, a.error]))), dialogWidth = Math.max(44, Math.min(width - 4, 100)), inner = dialogWidth - 4;
9339
+ (0, import_react29.useEffect)(() => {
9308
9340
  if (rev === 0) return;
9309
9341
  let live = !0;
9310
9342
  return store.client.folderAgents(folder).then(
@@ -9319,7 +9351,7 @@ function FolderAgentsDialog({ overlay, close, width, height }) {
9319
9351
  };
9320
9352
  }, [rev, folder]);
9321
9353
  let rows = (agents ?? []).map((a) => a.status !== "loaded" && !a.error && errors[a.filePath] ? { ...a, error: errors[a.filePath] } : a), at = Math.min(cursor, Math.max(0, rows.length - 1)), selected = rows[at];
9322
- (0, import_react28.useEffect)(() => {
9354
+ (0, import_react29.useEffect)(() => {
9323
9355
  if (!pendingReview || !agents) return;
9324
9356
  let index = rows.findIndex((r) => r.filePath === pendingReview);
9325
9357
  setPendingReview(null), !(index < 0) && (setCursor(index), rows[index].status === "needs_review" && openReview(rows[index]));
@@ -9465,7 +9497,7 @@ function TrackDialog(props) {
9465
9497
  return props.overlay.props?.folder ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(FolderAgentsDialog, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TrackFolderInput, { ...props });
9466
9498
  }
9467
9499
  function TrackFolderInput({ overlay, close, width }) {
9468
- let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, [lastDir, setLastDir] = useViewState(LAST_DIR_KEY2, ""), [value, setValue] = (0, import_react29.useState)(props.path ?? (lastDir || `${process.cwd()}${sep3}`)), [candidates, setCandidates] = (0, import_react29.useState)([]), [problem, setProblem] = (0, import_react29.useState)(null), [busy, setBusy] = (0, import_react29.useState)(!1), dialogWidth = Math.max(40, Math.min(width - 4, 90)), submit = (text) => {
9500
+ let theme2 = useTheme(), store = useStore(), props = overlay.props ?? {}, [lastDir, setLastDir] = useViewState(LAST_DIR_KEY2, ""), [value, setValue] = (0, import_react30.useState)(props.path ?? (lastDir || `${process.cwd()}${sep3}`)), [candidates, setCandidates] = (0, import_react30.useState)([]), [problem, setProblem] = (0, import_react30.useState)(null), [busy, setBusy] = (0, import_react30.useState)(!1), dialogWidth = Math.max(40, Math.min(width - 4, 90)), submit = (text) => {
9469
9501
  if (busy) return !1;
9470
9502
  let raw = text.trim();
9471
9503
  if (!raw)
@@ -9534,10 +9566,10 @@ function TrackFolderInput({ overlay, close, width }) {
9534
9566
  }
9535
9567
 
9536
9568
  // src/main/tui/views/fleet/UntrackDialog.tsx
9537
- var import_react30 = __toESM(require_react(), 1);
9569
+ var import_react31 = __toESM(require_react(), 1);
9538
9570
  var import_jsx_runtime36 = __toESM(require_jsx_runtime(), 1);
9539
9571
  function UntrackDialog({ overlay, close, width }) {
9540
- let theme2 = useTheme(), store = useStore(), path = String(overlay.props?.path ?? ""), [unload, setUnload] = (0, import_react30.useState)(!1);
9572
+ let theme2 = useTheme(), store = useStore(), path = String(overlay.props?.path ?? ""), [unload, setUnload] = (0, import_react31.useState)(!1);
9541
9573
  return useKeys((input, key) => key.return || input === "y" || input === "Y" ? (close(), untrackFolder(store, path, unload), !0) : key.escape || input === "n" || input === "N" || key.ctrl && input === "c" ? (close(), !0) : ((input === "u" || input === " ") && setUnload((v) => !v), !0), { layer: "overlay" }), /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
9542
9574
  Modal,
9543
9575
  {
@@ -9931,10 +9963,10 @@ var fleet = {
9931
9963
  }, fleet_default = fleet;
9932
9964
 
9933
9965
  // src/main/tui/views/chat/index.tsx
9934
- var import_react35 = __toESM(require_react(), 1);
9966
+ var import_react36 = __toESM(require_react(), 1);
9935
9967
 
9936
9968
  // src/main/tui/views/chat/Transcript.tsx
9937
- var import_react31 = __toESM(require_react(), 1);
9969
+ var import_react32 = __toESM(require_react(), 1);
9938
9970
  var import_jsx_runtime38 = __toESM(require_jsx_runtime(), 1);
9939
9971
  function lineCount(text) {
9940
9972
  return text ? text.split(`
@@ -9957,7 +9989,7 @@ function AskForm({ questions, answers }) {
9957
9989
  ] }, i);
9958
9990
  }) });
9959
9991
  }
9960
- function ToolBody({ item, w, expanded }) {
9992
+ function ToolBody({ item, w, expanded, viewportHeight, clipBottom = 0 }) {
9961
9993
  let theme2 = useTheme(), g = theme2.glyph, view2 = toolView(item), failed = item.status === "error", status = item.status === "running" ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Spinner, { color: theme2.color.tool }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { color: failed ? theme2.color.error : theme2.color.success, children: failed ? g.cross : g.check }), asyncBadge = isAsyncTool(item) ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { color: theme2.color.dim, children: " [async]" }) : null;
9962
9994
  if (expanded && isExpandable(item)) {
9963
9995
  let input = capLines(prettyJson(item.input), EXPANDED_TOOL_LINES), ref = shownTaskRef(item), task = ref !== void 0 ? capLines(ref, EXPANDED_TOOL_LINES) : null, result2 = capLines(item.result ?? "", EXPANDED_TOOL_LINES);
@@ -10008,7 +10040,7 @@ ${g.ellipsis} ${result2.more} more lines` : ""
10008
10040
  " "
10009
10041
  ] }),
10010
10042
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(Box_default, { width: w - 2, flexDirection: "column", children: [
10011
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Markdown, { text: sayText(item) || " ", color: theme2.color.assistant }),
10043
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Markdown, { text: sayText(item) || " ", color: theme2.color.assistant, viewport: viewportHeight === void 0 ? void 0 : { width: w - 2, height: viewportHeight + 2, clipBottom: Math.max(0, clipBottom - 1 - (failed ? 1 : 0)) } }),
10012
10044
  failed ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(Text, { wrap: "truncate-end", color: theme2.color.error, children: [
10013
10045
  g.cross,
10014
10046
  " say failed: ",
@@ -10094,7 +10126,7 @@ ${g.ellipsis} ${result2.more} more lines` : ""
10094
10126
  ] }) : null
10095
10127
  ] });
10096
10128
  }
10097
- function ItemBody({ item, width, expanded, showThinking, queued }) {
10129
+ function ItemBody({ item, width, expanded, showThinking, queued, viewportHeight, clipBottom = 0 }) {
10098
10130
  let theme2 = useTheme(), g = theme2.glyph, w = Math.max(8, width);
10099
10131
  switch (item.kind) {
10100
10132
  case "user": {
@@ -10155,7 +10187,7 @@ function ItemBody({ item, width, expanded, showThinking, queued }) {
10155
10187
  " "
10156
10188
  ] }),
10157
10189
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(Box_default, { width: w - 2, flexDirection: "column", children: [
10158
- item.text ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Markdown, { text: item.text, color: theme2.color.assistant }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { children: " " }),
10190
+ item.text ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Markdown, { text: item.text, color: theme2.color.assistant, viewport: viewportHeight === void 0 ? void 0 : { width: w - 2, height: viewportHeight + 2, clipBottom: Math.max(0, clipBottom - 1 - (item.interrupted ? 1 : 0)) } }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { children: " " }),
10159
10191
  item.interrupted ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Text, { color: theme2.color.dim, children: "[interrupted]" }) : null
10160
10192
  ] })
10161
10193
  ] });
@@ -10179,7 +10211,7 @@ function ItemBody({ item, width, expanded, showThinking, queued }) {
10179
10211
  ] });
10180
10212
  }
10181
10213
  case "tool":
10182
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ToolBody, { item, w, expanded });
10214
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ToolBody, { item, w, expanded, viewportHeight, clipBottom });
10183
10215
  case "hil": {
10184
10216
  let tone = item.status === "pending" ? theme2.color.warn : item.status === "approved" || item.status === "completed" ? theme2.color.success : theme2.color.error;
10185
10217
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(Box_default, { flexDirection: "column", width: w, borderStyle: theme2.ascii ? "classic" : "single", borderLeft: !0, borderRight: !1, borderTop: !1, borderBottom: !1, borderColor: tone, paddingLeft: 1, children: [
@@ -10282,7 +10314,7 @@ function ItemBody({ item, width, expanded, showThinking, queued }) {
10282
10314
  ] });
10283
10315
  }
10284
10316
  }
10285
- var TranscriptItemView = (0, import_react31.memo)(function(props) {
10317
+ var TranscriptItemView = (0, import_react32.memo)(function(props) {
10286
10318
  let theme2 = useTheme(), gap = props.item.kind === "notice" || props.item.kind === "context" && !props.expanded ? 0 : 1;
10287
10319
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Box_default, { flexDirection: "row", width: props.width, marginBottom: gap, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10288
10320
  Box_default,
@@ -10346,7 +10378,7 @@ function LoopTabs({ agentLabel: agentLabel5, tabs, selected, unseen, pending, wi
10346
10378
  }
10347
10379
 
10348
10380
  // src/main/tui/views/chat/Dock.tsx
10349
- var import_react32 = __toESM(require_react(), 1);
10381
+ var import_react33 = __toESM(require_react(), 1);
10350
10382
 
10351
10383
  // src/main/tui/views/chat/approvals.ts
10352
10384
  var FEEDBACK_OVERLAY = "chat.deny";
@@ -10394,7 +10426,7 @@ function dockHeight(model2, width) {
10394
10426
  }
10395
10427
  }
10396
10428
  function ActionRow({ buttons: all, focused, width, onAction }) {
10397
- let theme2 = useTheme(), ref = (0, import_react32.useRef)(null), sep4 = ` ${theme2.glyph.sep} `, prefix = focused ? "" : "Shift+Tab: ", spans = [], x = displayWidth(prefix);
10429
+ let theme2 = useTheme(), ref = (0, import_react33.useRef)(null), sep4 = ` ${theme2.glyph.sep} `, prefix = focused ? "" : "Shift+Tab: ", spans = [], x = displayWidth(prefix);
10398
10430
  for (let [i, button] of all.entries()) {
10399
10431
  let text = button.off ? `${button.label}: one-time only` : `${keyLabel(button.keys)} ${button.label}`, start = x + (i > 0 ? displayWidth(sep4) : 0);
10400
10432
  if (start + displayWidth(text) > width) break;
@@ -10534,15 +10566,15 @@ function Dock({ model: model2, width, focused, agentLabel: agentLabel5, onAction
10534
10566
  }
10535
10567
 
10536
10568
  // src/main/tui/views/chat/Footer.tsx
10537
- var import_react33 = __toESM(require_react(), 1);
10569
+ var import_react34 = __toESM(require_react(), 1);
10538
10570
  var import_jsx_runtime41 = __toESM(require_jsx_runtime(), 1);
10539
10571
  function elapsed(ms) {
10540
10572
  let s = Math.max(0, Math.floor(ms / 1e3));
10541
10573
  return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m${String(s % 60).padStart(2, "0")}s`;
10542
10574
  }
10543
10575
  function Footer({ width, running: running2, state, turn, since, model: model2, error, contextPercent }) {
10544
- let theme2 = useTheme(), g = theme2.glyph, [now, setNow] = (0, import_react33.useState)(Date.now());
10545
- (0, import_react33.useEffect)(() => {
10576
+ let theme2 = useTheme(), g = theme2.glyph, [now, setNow] = (0, import_react34.useState)(Date.now());
10577
+ (0, import_react34.useEffect)(() => {
10546
10578
  if (!running2) return;
10547
10579
  setNow(Date.now());
10548
10580
  let timer = setInterval(() => setNow(Date.now()), 1e3);
@@ -10626,13 +10658,13 @@ function Footer({ width, running: running2, state, turn, since, model: model2, e
10626
10658
  }
10627
10659
 
10628
10660
  // src/main/tui/views/chat/overlays.tsx
10629
- var import_react34 = __toESM(require_react(), 1);
10661
+ var import_react35 = __toESM(require_react(), 1);
10630
10662
  var import_jsx_runtime42 = __toESM(require_jsx_runtime(), 1), DENY_OVERLAY = "chat.deny", DETAILS_OVERLAY = "chat.approval";
10631
10663
  function taskProps(props) {
10632
10664
  return props.overlay.props ?? {};
10633
10665
  }
10634
10666
  function DenyOverlay(props) {
10635
- let theme2 = useTheme(), actions4 = useActions(), { agentId, taskId, tool } = taskProps(props), [reason, setReason] = (0, import_react34.useState)("");
10667
+ let theme2 = useTheme(), actions4 = useActions(), { agentId, taskId, tool } = taskProps(props), [reason, setReason] = (0, import_react35.useState)("");
10636
10668
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
10637
10669
  Modal,
10638
10670
  {
@@ -10662,7 +10694,7 @@ function DenyOverlay(props) {
10662
10694
  }
10663
10695
  function ApprovalDetailsOverlay(props) {
10664
10696
  let theme2 = useTheme(), actions4 = useActions(), { agentId, taskId, tool } = taskProps(props), agent2 = useAgent(agentId), task = agent2?.pendingTasks.find((t) => t.id === taskId), body = task ? prettyJson(parseArgs(task.args)) : "(no longer pending)", dialogWidth = Math.min(props.width - 4, 96), lines = body.split(`
10665
- `).flatMap((line) => chunk(line, Math.max(8, dialogWidth - 4))), room = Math.max(4, props.height - 12), [top, setTop] = (0, import_react34.useState)(0), maxTop = Math.max(0, lines.length - room);
10697
+ `).flatMap((line) => chunk(line, Math.max(8, dialogWidth - 4))), room = Math.max(4, props.height - 12), [top, setTop] = (0, import_react35.useState)(0), maxTop = Math.max(0, lines.length - room);
10666
10698
  useKeys((input, key) => key.escape ? (props.close(), !0) : input === "y" && task ? (props.close(), actions4.resolveTask(agentId, taskId, "approve"), !0) : input === "a" && task ? (props.close(), alwaysApprove(actions4, agentId, agent2?.summary.handle || agent2?.summary.name || agentId, task), !0) : input === "n" && task ? (props.close(), actions4.resolveTask(agentId, taskId, "deny"), !0) : input === "f" && task ? (props.close(), actions4.pushOverlay({ kind: DENY_OVERLAY, props: { agentId, taskId, tool } }), !0) : key.downArrow || input === "j" ? (setTop((t) => Math.min(maxTop, t + 1)), !0) : key.upArrow || input === "k" ? (setTop((t) => Math.max(0, t - 1)), !0) : key.pageDown ? (setTop((t) => Math.min(maxTop, t + room)), !0) : (key.pageUp && setTop((t) => Math.max(0, t - room)), !0), { layer: "overlay" });
10667
10699
  let reason = task ? taskReason(task) : void 0;
10668
10700
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
@@ -10907,22 +10939,22 @@ function LateKeys({ handler, layer }) {
10907
10939
  return useKeys(handler, { layer }), null;
10908
10940
  }
10909
10941
  function ChatView({ width: paneWidth, height, focused }) {
10910
- let width = Math.max(10, paneWidth - 2), theme2 = useTheme(), g = theme2.glyph, store = useStore(), actions4 = useActions(), client = useClient(), agent2 = useSelectedAgent(), stopped = useSelectedTracked(), authNeed = useAuthNeed(agent2?.summary.id), agentId = agent2?.summary.id ?? null, loopName = useSelectedLoop(), loop = useLoop(agentId, loopName), transcript = useTranscript(agentId, loopName), [chat2, setChat] = useViewState(CHAT_VIEW, INITIAL_CHAT_STATE), focusZone = useFocus(), key = agentId ? transcriptKey(agentId, loopName) : "", mountedAt = (0, import_react35.useRef)(Date.now()), [late, setLate] = (0, import_react35.useState)(!1);
10911
- (0, import_react35.useEffect)(() => {
10942
+ let width = Math.max(10, paneWidth - 2), theme2 = useTheme(), g = theme2.glyph, store = useStore(), actions4 = useActions(), client = useClient(), agent2 = useSelectedAgent(), stopped = useSelectedTracked(), authNeed = useAuthNeed(agent2?.summary.id), agentId = agent2?.summary.id ?? null, loopName = useSelectedLoop(), loop = useLoop(agentId, loopName), transcript = useTranscript(agentId, loopName), [chat2, setChat] = useViewState(CHAT_VIEW, INITIAL_CHAT_STATE), focusZone = useFocus(), key = agentId ? transcriptKey(agentId, loopName) : "", mountedAt = (0, import_react36.useRef)(Date.now()), [late, setLate] = (0, import_react36.useState)(!1);
10943
+ (0, import_react36.useEffect)(() => {
10912
10944
  setLate(!0);
10913
- }, []), (0, import_react35.useEffect)(() => {
10945
+ }, []), (0, import_react36.useEffect)(() => {
10914
10946
  agentId && actions4.ensureTranscript(agentId, loopName);
10915
10947
  }, [agentId, loopName]);
10916
- let [timers, setTimers] = (0, import_react35.useState)({}), refetchTimers = (id) => {
10948
+ let [timers, setTimers] = (0, import_react36.useState)({}), refetchTimers = (id) => {
10917
10949
  client.timers(id).then((result) => setTimers((prev) => ({ ...prev, [id]: result.timers }))).catch(() => {
10918
10950
  setTimers((prev) => prev[id] ? prev : { ...prev, [id]: [] });
10919
10951
  });
10920
10952
  }, loopCount = agent2?.loops?.length ?? 0;
10921
- (0, import_react35.useEffect)(() => {
10953
+ (0, import_react36.useEffect)(() => {
10922
10954
  agentId && refetchTimers(agentId);
10923
10955
  }, [agentId, loopCount]);
10924
- let lastEvents = useTuiSelector((s) => s.lastEvents), digested = (0, import_react35.useRef)(null), timerAttempts = (0, import_react35.useRef)(/* @__PURE__ */ new Set());
10925
- (0, import_react35.useEffect)(() => {
10956
+ let lastEvents = useTuiSelector((s) => s.lastEvents), digested = (0, import_react36.useRef)(null), timerAttempts = (0, import_react36.useRef)(/* @__PURE__ */ new Set());
10957
+ (0, import_react36.useEffect)(() => {
10926
10958
  let current = store.getState().viewState[CHAT_VIEW] ?? INITIAL_CHAT_STATE;
10927
10959
  digested.current || (digested.current = current.digested);
10928
10960
  let lookup = (id, timerId) => {
@@ -10939,7 +10971,7 @@ function ChatView({ width: paneWidth, height, focused }) {
10939
10971
  for (let a of s.activity) a.agentId === agentId && a.loop !== loopName && UNSEEN_EVENTS.has(a.type) && (out[a.loop] = a.at);
10940
10972
  return out;
10941
10973
  }, shallowEqual);
10942
- (0, import_react35.useEffect)(() => {
10974
+ (0, import_react36.useEffect)(() => {
10943
10975
  if (!agentId) return;
10944
10976
  let k = transcriptKey(agentId, loopName);
10945
10977
  return () => {
@@ -10949,13 +10981,13 @@ function ChatView({ width: paneWidth, height, focused }) {
10949
10981
  }, [agentId, loopName]);
10950
10982
  let transcripts = useTuiSelector((s) => s.transcripts);
10951
10983
  useTuiSelector((s) => s.web?.server), useTuiSelector((s) => s.viewState[ASK_PROGRESS_KEY]);
10952
- let site = siteOf(store.getState(), agentId), tabs = loopTabs(agent2), running2 = loopRunning2(agent2, loop) || transcript.live, state = loopStateLabel(agent2, loop, loopName), turn = chat2.turns[key], turnStart = running2 ? turn && turn.endedAt === void 0 ? turn.startedAt : mountedAt.current : null, tasks2 = pendingTasksFor(agent2, loopName), asks = pendingAsksFor(agent2, loopName, transcripts), queued = queuedItems(transcript.items, running2, turnStart), queuedIds = new Set(queued.map((q) => q.id)), askAnswers2 = agentId && asks[0] ? askProgress(store.getState(), agentId, loopName, asks[0]) : void 0, dockModel = { tasks: tasks2, asks, askAnswers: askAnswers2, suspended: loopName === MAIN_LOOP && agent2?.executorState === "suspended", queued }, unseen = new Set(Object.entries(latest).filter(([name, at]) => at > (chat2.seen[agentId ? transcriptKey(agentId, name) : ""] ?? 0)).map(([name]) => name)), pendingLoops = new Set((agent2?.pendingTasks ?? []).filter((t) => t.status === "pending_approval").map((t) => typeof t.origin == "string" && t.origin.startsWith("loop:") ? t.origin.slice(5) : MAIN_LOOP)), markers = chat2.markers[key], older = transcript.oldestOffset > 0 ? [{ id: "chat:older", at: 0, local: !0, kind: "notice", level: "info", text: transcript.loading ? `loading earlier history${g.ellipsis}` : `${transcript.oldestOffset} earlier rows ${g.sep} scroll up or Home to load` }] : [], items = useMergedItems(transcript.items, markers, older), heightCache = (0, import_react35.useRef)(/* @__PURE__ */ new WeakMap()), isExpanded = (item) => !!chat2.expanded[`${key}|${item.id}`], heights = items.map((item) => {
10984
+ let site = siteOf(store.getState(), agentId), tabs = loopTabs(agent2), running2 = loopRunning2(agent2, loop) || transcript.live, state = loopStateLabel(agent2, loop, loopName), turn = chat2.turns[key], turnStart = running2 ? turn && turn.endedAt === void 0 ? turn.startedAt : mountedAt.current : null, tasks2 = pendingTasksFor(agent2, loopName), asks = pendingAsksFor(agent2, loopName, transcripts), queued = queuedItems(transcript.items, running2, turnStart), queuedIds = new Set(queued.map((q) => q.id)), askAnswers2 = agentId && asks[0] ? askProgress(store.getState(), agentId, loopName, asks[0]) : void 0, dockModel = { tasks: tasks2, asks, askAnswers: askAnswers2, suspended: loopName === MAIN_LOOP && agent2?.executorState === "suspended", queued }, unseen = new Set(Object.entries(latest).filter(([name, at]) => at > (chat2.seen[agentId ? transcriptKey(agentId, name) : ""] ?? 0)).map(([name]) => name)), pendingLoops = new Set((agent2?.pendingTasks ?? []).filter((t) => t.status === "pending_approval").map((t) => typeof t.origin == "string" && t.origin.startsWith("loop:") ? t.origin.slice(5) : MAIN_LOOP)), markers = chat2.markers[key], older = transcript.oldestOffset > 0 ? [{ id: "chat:older", at: 0, local: !0, kind: "notice", level: "info", text: transcript.loading ? `loading earlier history${g.ellipsis}` : `${transcript.oldestOffset} earlier rows ${g.sep} scroll up or Home to load` }] : [], items = useMergedItems(transcript.items, markers, older), heightCache = (0, import_react36.useRef)(/* @__PURE__ */ new WeakMap()), isExpanded = (item) => !!chat2.expanded[`${key}|${item.id}`], heights = items.map((item) => {
10953
10985
  let expanded = isExpanded(item), f = `${expanded ? 1 : 0}${chat2.showThinking ? 1 : 0}${queuedIds.has(item.id) ? 1 : 0}`, cached = heightCache.current.get(item);
10954
10986
  if (cached && cached.w === width && cached.f === f) return cached.h;
10955
10987
  let h = Math.max(1, itemHeight(item, width, { expanded, showThinking: chat2.showThinking }));
10956
10988
  return heightCache.current.set(item, { w: width, f, h }), h;
10957
- }), keys = items.map((item) => item.id), infoRows = 1, dockRows = agentId ? dockHeight(dockModel, width) : 0, paneHeight = Math.max(2, height - 1 - infoRows - 1 - dockRows), offset = offsetOf(chat2.scroll[key], keys, heights), scrolled = offset > 0, viewport = Math.max(1, paneHeight - (scrolled ? 1 : 0)), win = windowAt(heights, offset, viewport), selectedId = chat2.selected[key] ?? null, topVisible = win.start === 0 && heights.slice(0, win.end + 1).reduce((a, b) => a + b, 0) - win.clip <= viewport, loadOlderGuard = (0, import_react35.useRef)("");
10958
- (0, import_react35.useEffect)(() => {
10989
+ }), keys = items.map((item) => item.id), infoRows = 1, dockRows = agentId ? dockHeight(dockModel, width) : 0, paneHeight = Math.max(2, height - 1 - infoRows - 1 - dockRows), offset = offsetOf(chat2.scroll[key], keys, heights), scrolled = offset > 0, viewport = Math.max(1, paneHeight - (scrolled ? 1 : 0)), win = windowAt(heights, offset, viewport), selectedId = chat2.selected[key] ?? null, topVisible = win.start === 0 && heights.slice(0, win.end + 1).reduce((a, b) => a + b, 0) - win.clip <= viewport, loadOlderGuard = (0, import_react36.useRef)("");
10990
+ (0, import_react36.useEffect)(() => {
10959
10991
  if (!agentId || !scrolled || !topVisible || transcript.loading || transcript.oldestOffset <= 0) return;
10960
10992
  let guard = `${key}:${transcript.oldestOffset}`;
10961
10993
  loadOlderGuard.current !== guard && (loadOlderGuard.current = guard, actions4.loadOlder(agentId, loopName));
@@ -11037,7 +11069,7 @@ function ChatView({ width: paneWidth, height, focused }) {
11037
11069
  if (!target2) return;
11038
11070
  let task = target2.task ?? { id: target2.taskId, tool: target2.tool, args: "{}", status: "pending_approval", created_at: 0 };
11039
11071
  action === "approve" ? actions4.resolveTask(agentId, target2.taskId, "approve") : action === "always" ? alwaysApprove(actions4, agentId, agentLabel4(agent2), task) : action === "reject" ? actions4.resolveTask(agentId, target2.taskId, "deny") : action === "feedback" ? rejectWithFeedback(actions4, agentId, task) : actions4.pushOverlay({ kind: DETAILS_OVERLAY, props: { agentId, taskId: target2.taskId, tool: target2.tool } });
11040
- }, interrupt = () => agentId ? (actions4.interrupt(agentId, loopName), !0) : !1, armed = (0, import_react35.useRef)(null), router = useKeyRouter(), pendingArrow = (0, import_react35.useRef)(null), replaying = (0, import_react35.useRef)(!1), queueArrow = (input, k, items2) => {
11072
+ }, interrupt = () => agentId ? (actions4.interrupt(agentId, loopName), !0) : !1, armed = (0, import_react36.useRef)(null), router = useKeyRouter(), pendingArrow = (0, import_react36.useRef)(null), replaying = (0, import_react36.useRef)(!1), queueArrow = (input, k, items2) => {
11041
11073
  let step = k.upArrow ? 1 : -1, pending = pendingArrow.current;
11042
11074
  return pending ? (pending.delta += step, pending.count++, !0) : (pendingArrow.current = { input, key: k, delta: step, count: 1, items: items2 }, setImmediate(() => {
11043
11075
  let p = pendingArrow.current;
@@ -11101,9 +11133,9 @@ function ChatView({ width: paneWidth, height, focused }) {
11101
11133
  }
11102
11134
  return card === "hil" && (input === "n" || input === "f" || input === "v") ? (dockAction(input === "n" ? "reject" : input === "f" ? "feedback" : "details"), !0) : card === "suspend" && (input === "y" || input === "n") ? (dockAction(input === "y" ? "resume" : "shutdown"), !0) : card === "ask" && (input === "a" || input === "x") ? (dockAction(input === "a" ? "answer" : "skip"), !0) : !1;
11103
11135
  }, { layer: "main", active: focused }), useKeys((_input, k) => !k.escape || store.getState().focus === "sidebar" ? !1 : running2 ? interrupt() : !1, { layer: "view" });
11104
- let transcriptRef = (0, import_react35.useRef)(null);
11136
+ let transcriptRef = (0, import_react36.useRef)(null);
11105
11137
  useWheel(transcriptRef, (delta) => scrollBy(-delta * WHEEL_STEP), { active: !!agentId });
11106
- let itemRefs = (0, import_react35.useRef)(/* @__PURE__ */ new Map());
11138
+ let itemRefs = (0, import_react36.useRef)(/* @__PURE__ */ new Map());
11107
11139
  useClick(transcriptRef, (event) => {
11108
11140
  let box = elementRect(transcriptRef.current);
11109
11141
  if (!box || event.y >= box.y + viewport) return !1;
@@ -11167,7 +11199,13 @@ function ChatView({ width: paneWidth, height, focused }) {
11167
11199
  selected: showSelection && item.id === selectedId,
11168
11200
  expanded: isExpanded(item),
11169
11201
  showThinking: chat2.showThinking,
11170
- queued: queuedIds.has(item.id)
11202
+ queued: queuedIds.has(item.id),
11203
+ viewportHeight: (
11204
+ // Raw height estimates can exceed Ink's styled height,
11205
+ // so clipping may extend into earlier visible items.
11206
+ viewport + (item === visible[visible.length - 1] ? 0 : win.clip)
11207
+ ),
11208
+ clipBottom: item === visible[visible.length - 1] ? win.clip : 0
11171
11209
  }
11172
11210
  ) }, item.id)) }) }),
11173
11211
  scrolled ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(Text, { wrap: "truncate-end", color: theme2.color.accent, children: [
@@ -11187,7 +11225,7 @@ function ChatView({ width: paneWidth, height, focused }) {
11187
11225
  ] });
11188
11226
  }
11189
11227
  function useMergedItems(items, markers, older) {
11190
- let cache = (0, import_react35.useRef)(null), olderKey = older.map((o) => o.kind === "notice" ? o.text : "").join(), c = cache.current;
11228
+ let cache = (0, import_react36.useRef)(null), olderKey = older.map((o) => o.kind === "notice" ? o.text : "").join(), c = cache.current;
11191
11229
  if (c && c.items === items && c.markers === markers && c.older === olderKey) return c.out;
11192
11230
  let out = [...older, ...withMarkers(items, markers)];
11193
11231
  return cache.current = { items, markers, older: olderKey, out }, out;
@@ -11318,7 +11356,7 @@ var chat = {
11318
11356
  }, chat_default = chat;
11319
11357
 
11320
11358
  // src/main/tui/views/files/index.tsx
11321
- var import_react40 = __toESM(require_react(), 1);
11359
+ var import_react41 = __toESM(require_react(), 1);
11322
11360
 
11323
11361
  // src/main/tui/views/files/state.ts
11324
11362
  var VIEW_ID = "files", TABS2 = ["files", "inbox", "outbox", "meta"], INITIAL_STATE = { tab: "files", pane: "list", agents: {} };
@@ -11478,10 +11516,10 @@ var tabAction = (tab, title, keywords) => ({
11478
11516
  };
11479
11517
 
11480
11518
  // src/main/tui/views/files/DataTab.tsx
11481
- var import_react37 = __toESM(require_react(), 1);
11519
+ var import_react38 = __toESM(require_react(), 1);
11482
11520
 
11483
11521
  // src/main/tui/views/files/Viewer.tsx
11484
- var import_react36 = __toESM(require_react(), 1);
11522
+ var import_react37 = __toESM(require_react(), 1);
11485
11523
  var import_jsx_runtime44 = __toESM(require_jsx_runtime(), 1);
11486
11524
  function toneColor3(theme2, tone) {
11487
11525
  switch (tone) {
@@ -11506,11 +11544,11 @@ function toneColor3(theme2, tone) {
11506
11544
  }
11507
11545
  }
11508
11546
  function Viewer(props) {
11509
- let { width, height, active, title, meta = [], notice, name, text, bytes, mime, loading, error, plain: plain2 = !1, resetKey, onBack, onEdit, onOpenExternal, onSaveBack, emptyText } = props, theme2 = useTheme(), [top, setTop] = (0, import_react36.useState)(0), [query, setQuery] = (0, import_react36.useState)(""), [typing, setTyping] = (0, import_react36.useState)(!1), [current, setCurrent] = (0, import_react36.useState)(0);
11510
- (0, import_react36.useEffect)(() => {
11547
+ let { width, height, active, title, meta = [], notice, name, text, bytes, mime, loading, error, plain: plain2 = !1, resetKey, onBack, onEdit, onOpenExternal, onSaveBack, emptyText } = props, theme2 = useTheme(), [top, setTop] = (0, import_react37.useState)(0), [query, setQuery] = (0, import_react37.useState)(""), [typing, setTyping] = (0, import_react37.useState)(!1), [current, setCurrent] = (0, import_react37.useState)(0);
11548
+ (0, import_react37.useEffect)(() => {
11511
11549
  setTop(0), setQuery(""), setTyping(!1), setCurrent(0);
11512
11550
  }, [resetKey]);
11513
- let binary = bytes !== void 0, prepared = (0, import_react36.useMemo)(() => binary ? { lines: hexDump(bytes), lang: "text", pretty: !1 } : prepareContent(text ?? "", name), [text, bytes, name, binary]), matches = (0, import_react36.useMemo)(() => findMatches(prepared.lines, query), [prepared, query]), currentIndex = matches.length ? Math.min(current, matches.length - 1) : -1, gutter = plain2 ? 0 : String(prepared.lines.length).length + 1, bodyWidth = Math.max(4, width - gutter - 1), { rows, lineStart: lineStart2 } = (0, import_react36.useMemo)(() => {
11551
+ let binary = bytes !== void 0, prepared = (0, import_react37.useMemo)(() => binary ? { lines: hexDump(bytes), lang: "text", pretty: !1 } : prepareContent(text ?? "", name), [text, bytes, name, binary]), matches = (0, import_react37.useMemo)(() => findMatches(prepared.lines, query), [prepared, query]), currentIndex = matches.length ? Math.min(current, matches.length - 1) : -1, gutter = plain2 ? 0 : String(prepared.lines.length).length + 1, bodyWidth = Math.max(4, width - gutter - 1), { rows, lineStart: lineStart2 } = (0, import_react37.useMemo)(() => {
11514
11552
  let styled = styleLines(prepared.lines, prepared.lang), byLine = /* @__PURE__ */ new Map();
11515
11553
  matches.forEach((m, i) => {
11516
11554
  let list = byLine.get(m.line) ?? [];
@@ -11532,13 +11570,13 @@ function Viewer(props) {
11532
11570
  let next = (currentIndex + delta + matches.length) % matches.length;
11533
11571
  setCurrent(next), reveal(next);
11534
11572
  };
11535
- (0, import_react36.useEffect)(() => {
11573
+ (0, import_react37.useEffect)(() => {
11536
11574
  if (typing && matches.length > 0) {
11537
11575
  let firstVisible = matches.findIndex((m) => (lineStart2[m.line] ?? 0) >= clampedTop), index = firstVisible >= 0 ? firstVisible : 0;
11538
11576
  setCurrent(index), reveal(index);
11539
11577
  }
11540
11578
  }, [query]), useKeys((input, key) => typing ? key.escape ? (setTyping(!1), setQuery(""), !0) : key.return ? (setTyping(!1), !0) : key.backspace || key.delete ? (setQuery((q) => q.slice(0, -1)), !0) : (key.leftArrow || key.rightArrow) && !key.ctrl && !key.shift ? !0 : input && !key.ctrl && !key.meta && !/[\r\n\t]/.test(input) ? (setQuery((q) => q + input), !0) : !1 : (key.ctrl || key.shift) && (key.leftArrow || key.rightArrow) ? !1 : key.upArrow || input === "k" && !key.ctrl ? (scrollTo(clampedTop - 1), !0) : key.downArrow || input === "j" && !key.ctrl ? (scrollTo(clampedTop + 1), !0) : key.pageUp || key.ctrl && input === "u" ? (scrollTo(clampedTop - Math.max(1, bodyRows - 1)), !0) : key.pageDown || input === " " || key.ctrl && input === "d" ? (scrollTo(clampedTop + Math.max(1, bodyRows - 1)), !0) : key.home || input === "g" ? (scrollTo(0), !0) : key.end || input === "G" ? (scrollTo(maxTop), !0) : input === "/" ? (setTyping(!0), setQuery(""), !0) : input === "n" && query ? (jump(1), !0) : input === "N" && query ? (jump(-1), !0) : input === "e" && onEdit ? (onEdit(), !0) : input === "o" && onOpenExternal ? (onOpenExternal(), !0) : input === "s" && onSaveBack ? (onSaveBack(), !0) : key.escape && query ? (setQuery(""), !0) : (key.escape || key.backspace && !key.ctrl && !key.meta) && onBack ? (onBack(), !0) : !1, { layer: "main", active });
11541
- let boxRef = (0, import_react36.useRef)(null);
11579
+ let boxRef = (0, import_react37.useRef)(null);
11542
11580
  useWheel(boxRef, (delta) => scrollTo(clampedTop + delta * WHEEL_STEP));
11543
11581
  let visible = rows.slice(clampedTop, clampedTop + bodyRows), lastLine = visible.length ? visible[visible.length - 1].line + 1 : 0, firstLine2 = visible.length ? visible[0].line + 1 : 0, position = rows.length === 0 ? "" : `L${firstLine2}-${lastLine}/${prepared.lines.length}${maxTop > 0 ? ` ${Math.round(clampedTop / maxTop * 100)}%` : ""}`, search = typing ? `/${query}` : query ? `/${query} ${matches.length ? `${currentIndex + 1}/${matches.length}` : "no match"} n/N` : "", header2 = /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(Text, { wrap: "truncate-end", children: [
11544
11582
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Text, { bold: !0, color: active ? theme2.color.accent : theme2.color.text, inverse: theme2.mono && active, children: truncate(title, Math.max(8, width - 20)) }),
@@ -11690,7 +11728,7 @@ var LIVE_EVENTS = {
11690
11728
  meta: []
11691
11729
  };
11692
11730
  function DataTab({ kind, width, height, focused, agentId, agentLabel: agentLabel5, pane, setPane }) {
11693
- let theme2 = useTheme(), client = useClient(), [records, setRecords] = (0, import_react37.useState)(null), [error, setError] = (0, import_react37.useState)(null), [filterIndex, setFilterIndex] = (0, import_react37.useState)(0), [cursor, setCursor] = (0, import_react37.useState)(void 0), [loadedAt, setLoadedAt] = (0, import_react37.useState)(null), status = STATUS_FILTERS[kind][filterIndex], reload = (0, import_react37.useCallback)(async () => {
11731
+ let theme2 = useTheme(), client = useClient(), [records, setRecords] = (0, import_react38.useState)(null), [error, setError] = (0, import_react38.useState)(null), [filterIndex, setFilterIndex] = (0, import_react38.useState)(0), [cursor, setCursor] = (0, import_react38.useState)(void 0), [loadedAt, setLoadedAt] = (0, import_react38.useState)(null), status = STATUS_FILTERS[kind][filterIndex], reload = (0, import_react38.useCallback)(async () => {
11694
11732
  try {
11695
11733
  let next;
11696
11734
  kind === "inbox" ? next = [...(await client.inbox(agentId, status)).messages].sort((a, b) => b.received_at - a.received_at).map(inboxRecord) : kind === "outbox" ? next = [...(await client.outbox(agentId, status)).messages].sort((a, b) => b.created_at - a.created_at).map(outboxRecord) : next = [...(await client.meta(agentId)).entries].sort((a, b) => a.key.localeCompare(b.key)).map(metaRecord), setRecords(next), setError(null);
@@ -11699,11 +11737,11 @@ function DataTab({ kind, width, height, focused, agentId, agentLabel: agentLabel
11699
11737
  }
11700
11738
  setLoadedAt(Date.now());
11701
11739
  }, [client, agentId, kind, status]);
11702
- (0, import_react37.useEffect)(() => {
11740
+ (0, import_react38.useEffect)(() => {
11703
11741
  setRecords(null), reload();
11704
11742
  }, [reload]);
11705
- let lastEvents = useTuiSelector((s) => s.lastEvents), seen = (0, import_react37.useRef)(lastEvents[lastEvents.length - 1]);
11706
- (0, import_react37.useEffect)(() => {
11743
+ let lastEvents = useTuiSelector((s) => s.lastEvents), seen = (0, import_react38.useRef)(lastEvents[lastEvents.length - 1]);
11744
+ (0, import_react38.useEffect)(() => {
11707
11745
  let hit = !1;
11708
11746
  for (let i = lastEvents.length - 1; i >= 0 && lastEvents[i] !== seen.current; i--)
11709
11747
  lastEvents[i].agent_id === agentId && LIVE_EVENTS[kind].includes(lastEvents[i].event_type) && (hit = !0);
@@ -11813,7 +11851,7 @@ function DataTab({ kind, width, height, focused, agentId, agentLabel: agentLabel
11813
11851
  }
11814
11852
 
11815
11853
  // src/main/tui/views/files/FilesTab.tsx
11816
- var import_react38 = __toESM(require_react(), 1);
11854
+ var import_react39 = __toESM(require_react(), 1);
11817
11855
 
11818
11856
  // src/main/tui/views/files/external.ts
11819
11857
  import { promises as fs4, rmSync, statSync as statSync3 } from "node:fs";
@@ -11882,7 +11920,9 @@ async function saveBackExternal(deps, target2) {
11882
11920
  cancelLabel: "Cancel",
11883
11921
  danger: !!concurrent
11884
11922
  })) return "discarded";
11885
- let written = copy.binary && target2.kind === "file" ? await actions4.run(`Write ${label2}`, (c) => c.writeFile(agentId, target2.path, { contentBase64: edited.toString("base64"), ...copy.mime ? { mimeType: copy.mime } : {} }).then(() => !0)) : await writeOverConflicts(actions4, label2, copy.file, (base2) => actions4.run(`Write ${label2}`, (c) => writeOver(() => writeTarget(c, agentId, target2, edited.toString("utf-8"), base2))), baseRevision);
11923
+ let written = await writeOverConflicts(actions4, label2, copy.file, (base2) => actions4.run(`Write ${label2}`, (c) => writeOver(
11924
+ () => copy.binary && target2.kind === "file" ? c.writeFile(agentId, target2.path, { contentBase64: edited.toString("base64"), ...copy.mime ? { mimeType: copy.mime } : {}, ...base2 !== void 0 ? { baseRevision: base2 } : {} }) : writeTarget(c, agentId, target2, edited.toString("utf-8"), base2)
11925
+ )), baseRevision);
11886
11926
  return written === "reloaded" ? "discarded" : written ? (copy.original = edited, copy.mtimeMs = (await fs4.stat(copy.file)).mtimeMs, actions4.toast(`Saved ${label2} from the app`, "success"), "written") : (actions4.toast(`Write failed. Your copy is still at ${copy.file}`, "error", 12e3), "failed");
11887
11927
  }
11888
11928
 
@@ -11902,18 +11942,18 @@ function parentsOf(path) {
11902
11942
  return parts.map((_p, i) => parts.slice(0, i + 1).join("/"));
11903
11943
  }
11904
11944
  function FilesTab(props) {
11905
- let { width, height, focused, agentId, agentLabel: agentLabel5, pane, setPane, agentState, setAgentState, request, clearRequest } = props, theme2 = useTheme(), actions4 = useActions(), client = useClient(), { suspendTerminal } = use_app_default(), [files2, setFiles] = (0, import_react38.useState)(null), [listError, setListError] = (0, import_react38.useState)(null), [query, setQuery] = (0, import_react38.useState)(""), [filtering, setFiltering] = (0, import_react38.useState)(!1), [content, setContent] = (0, import_react38.useState)({}), [notice, setNotice] = (0, import_react38.useState)(null), [, setTick] = (0, import_react38.useState)(0), busy = (0, import_react38.useRef)(!1), collapsed = (0, import_react38.useMemo)(() => new Set(agentState.collapsed ?? []), [agentState.collapsed]), rows = (0, import_react38.useMemo)(() => buildRows(files2 ?? [], collapsed, query), [files2, collapsed, query]), cursorIndex = Math.max(0, rows.findIndex((r) => r.key === agentState.cursor)), cursorRow = rows[cursorIndex], viewerKey = isOpenable(cursorRow) ? cursorRow.key : agentState.open ?? DOCUMENT_KEY;
11906
- (0, import_react38.useEffect)(() => {
11945
+ let { width, height, focused, agentId, agentLabel: agentLabel5, pane, setPane, agentState, setAgentState, request, clearRequest } = props, theme2 = useTheme(), actions4 = useActions(), client = useClient(), { suspendTerminal } = use_app_default(), [files2, setFiles] = (0, import_react39.useState)(null), [listError, setListError] = (0, import_react39.useState)(null), [query, setQuery] = (0, import_react39.useState)(""), [filtering, setFiltering] = (0, import_react39.useState)(!1), [content, setContent] = (0, import_react39.useState)({}), [notice, setNotice] = (0, import_react39.useState)(null), [, setTick] = (0, import_react39.useState)(0), busy = (0, import_react39.useRef)(!1), collapsed = (0, import_react39.useMemo)(() => new Set(agentState.collapsed ?? []), [agentState.collapsed]), rows = (0, import_react39.useMemo)(() => buildRows(files2 ?? [], collapsed, query), [files2, collapsed, query]), cursorIndex = Math.max(0, rows.findIndex((r) => r.key === agentState.cursor)), cursorRow = rows[cursorIndex], viewerKey = isOpenable(cursorRow) ? cursorRow.key : agentState.open ?? DOCUMENT_KEY;
11946
+ (0, import_react39.useEffect)(() => {
11907
11947
  pane === "viewer" && viewerKey.startsWith("file:") && recordRecentFile(agentId, viewerKey.slice(5));
11908
11948
  }, [pane, viewerKey, agentId]);
11909
- let viewerTarget = targetFromKey(viewerKey), reloadList = (0, import_react38.useCallback)(async () => {
11949
+ let viewerTarget = targetFromKey(viewerKey), reloadList = (0, import_react39.useCallback)(async () => {
11910
11950
  try {
11911
11951
  let next = await listFiles(client, agentId);
11912
11952
  setFiles(next), setListError(null);
11913
11953
  } catch (err) {
11914
11954
  setListError(err instanceof Error ? err.message : String(err)), setFiles((prev) => prev ?? []);
11915
11955
  }
11916
- }, [client, agentId]), loadContent = (0, import_react38.useCallback)(async (key) => {
11956
+ }, [client, agentId]), loadContent = (0, import_react39.useCallback)(async (key) => {
11917
11957
  let target2 = targetFromKey(key);
11918
11958
  if (target2)
11919
11959
  try {
@@ -11923,17 +11963,17 @@ function FilesTab(props) {
11923
11963
  setContent((prev) => ({ ...prev, [key]: { error: err instanceof Error ? err.message : String(err) } }));
11924
11964
  }
11925
11965
  }, [client, agentId]);
11926
- (0, import_react38.useEffect)(() => {
11966
+ (0, import_react39.useEffect)(() => {
11927
11967
  setFiles(null), setContent({}), setNotice(null), reloadList();
11928
- }, [agentId]), (0, import_react38.useEffect)(() => {
11968
+ }, [agentId]), (0, import_react39.useEffect)(() => {
11929
11969
  if (!viewerTarget || content[viewerKey]) return;
11930
11970
  let timer = setTimeout(() => {
11931
11971
  loadContent(viewerKey);
11932
11972
  }, 90);
11933
11973
  return () => clearTimeout(timer);
11934
11974
  }, [viewerKey, content[viewerKey] === void 0]);
11935
- let lastEvents = useTuiSelector((s) => s.lastEvents), seen = (0, import_react38.useRef)(lastEvents[lastEvents.length - 1]);
11936
- (0, import_react38.useEffect)(() => {
11975
+ let lastEvents = useTuiSelector((s) => s.lastEvents), seen = (0, import_react39.useRef)(lastEvents[lastEvents.length - 1]);
11976
+ (0, import_react39.useEffect)(() => {
11937
11977
  let fresh = [];
11938
11978
  for (let i = lastEvents.length - 1; i >= 0 && lastEvents[i] !== seen.current; i--) fresh.unshift(lastEvents[i]);
11939
11979
  seen.current = lastEvents[lastEvents.length - 1];
@@ -11958,7 +11998,7 @@ function FilesTab(props) {
11958
11998
  for (let key of touched) delete next[key];
11959
11999
  return next;
11960
12000
  });
11961
- }, [lastEvents]), (0, import_react38.useEffect)(() => {
12001
+ }, [lastEvents]), (0, import_react39.useEffect)(() => {
11962
12002
  let timer = setInterval(() => setTick((t) => t + 1), 15e3);
11963
12003
  return () => clearInterval(timer);
11964
12004
  }, []);
@@ -12010,7 +12050,7 @@ function FilesTab(props) {
12010
12050
  busy.current = !1, setTick((t) => t + 1);
12011
12051
  }
12012
12052
  }, viewedCopy = viewerTarget ? externalCopy(agentId, viewerTarget) : void 0, copyChanged = viewedCopy ? externalChanged(viewedCopy) : !1;
12013
- (0, import_react38.useEffect)(() => {
12053
+ (0, import_react39.useEffect)(() => {
12014
12054
  if (!viewedCopy || copyChanged) return;
12015
12055
  let timer = setInterval(() => {
12016
12056
  externalChanged(viewedCopy) && setTick((t) => t + 1);
@@ -12083,7 +12123,7 @@ function FilesTab(props) {
12083
12123
  let next = wantCollapsed ? [...collapsed, row4.path] : [...collapsed].filter((p) => p !== row4.path);
12084
12124
  return setAgentState({ collapsed: next }), !0;
12085
12125
  };
12086
- (0, import_react38.useEffect)(() => {
12126
+ (0, import_react39.useEffect)(() => {
12087
12127
  if (request)
12088
12128
  if (clearRequest(), request.kind === "open")
12089
12129
  reveal(request.key), invalidate(request.key), setPane("viewer");
@@ -12248,10 +12288,10 @@ function FilesTab(props) {
12248
12288
  }
12249
12289
 
12250
12290
  // src/main/tui/views/files/InputDialog.tsx
12251
- var import_react39 = __toESM(require_react(), 1);
12291
+ var import_react40 = __toESM(require_react(), 1);
12252
12292
  var import_jsx_runtime47 = __toESM(require_jsx_runtime(), 1);
12253
12293
  function InputDialog({ overlay, close, width }) {
12254
- let theme2 = useTheme(), options = overlay.props ?? {}, [value, setValue] = (0, import_react39.useState)(options.initial ?? ""), finish = (result) => {
12294
+ let theme2 = useTheme(), options = overlay.props ?? {}, [value, setValue] = (0, import_react40.useState)(options.initial ?? ""), finish = (result) => {
12255
12295
  resolveAsk(overlay.id, result), close();
12256
12296
  };
12257
12297
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
@@ -12284,13 +12324,13 @@ function InputDialog({ overlay, close, width }) {
12284
12324
  // src/main/tui/views/files/index.tsx
12285
12325
  var import_jsx_runtime48 = __toESM(require_jsx_runtime(), 1), TAB_TITLES = { files: "Files", inbox: "Inbox", outbox: "Outbox", meta: "Meta" };
12286
12326
  function FilesView({ width, height, focused }) {
12287
- let theme2 = useTheme(), store = useStore(), agent2 = useSelectedAgent(), stopped = useSelectedTracked(), loop = useSelectedLoop(), [state, setState] = useViewState(VIEW_ID, INITIAL_STATE), agentId = agent2?.summary.id ?? null, agentLabel5 = agent2 ? agent2.summary.handle || agent2.summary.name : "", patch = (0, import_react40.useCallback)((next) => {
12327
+ let theme2 = useTheme(), store = useStore(), agent2 = useSelectedAgent(), stopped = useSelectedTracked(), loop = useSelectedLoop(), [state, setState] = useViewState(VIEW_ID, INITIAL_STATE), agentId = agent2?.summary.id ?? null, agentLabel5 = agent2 ? agent2.summary.handle || agent2.summary.name : "", patch = (0, import_react41.useCallback)((next) => {
12288
12328
  setState({ ...readViewState(store.getState()), ...next });
12289
- }, [store, setState]), setPane = (0, import_react40.useCallback)((pane) => patch({ pane }), [patch]), setTab = (tab) => patch({ tab, pane: "list" }), setAgentState = (0, import_react40.useCallback)((next) => {
12329
+ }, [store, setState]), setPane = (0, import_react41.useCallback)((pane) => patch({ pane }), [patch]), setTab = (tab) => patch({ tab, pane: "list" }), setAgentState = (0, import_react41.useCallback)((next) => {
12290
12330
  if (!agentId) return;
12291
12331
  let current = readViewState(store.getState());
12292
12332
  patch({ agents: { ...current.agents, [agentId]: { ...current.agents[agentId], ...next } } });
12293
- }, [agentId, store, patch]), clearRequest = (0, import_react40.useCallback)(() => patch({ request: void 0 }), [patch]);
12333
+ }, [agentId, store, patch]), clearRequest = (0, import_react41.useCallback)(() => patch({ request: void 0 }), [patch]);
12294
12334
  if (useKeys((input, key) => {
12295
12335
  if (key.ctrl || key.meta || key.shift && (key.leftArrow || key.rightArrow)) return !1;
12296
12336
  let step = key.rightArrow || input === "]" ? 1 : key.leftArrow || input === "[" ? -1 : 0;
@@ -12536,7 +12576,7 @@ function row2(cells2, width) {
12536
12576
  }
12537
12577
 
12538
12578
  // src/main/tui/views/loops/hooks.ts
12539
- var import_react41 = __toESM(require_react(), 1);
12579
+ var import_react42 = __toESM(require_react(), 1);
12540
12580
  var LOOPS_REV_KEY = "loops.rev", revCounter = 0;
12541
12581
  function bumpLoopsData(actions4, _state) {
12542
12582
  actions4.setViewState(LOOPS_REV_KEY, ++revCounter);
@@ -12557,15 +12597,15 @@ function useEventTick(agentId, types) {
12557
12597
  });
12558
12598
  }
12559
12599
  function useNow(ms = 3e4) {
12560
- let [now, setNow] = (0, import_react41.useState)(() => Date.now());
12561
- return (0, import_react41.useEffect)(() => {
12600
+ let [now, setNow] = (0, import_react42.useState)(() => Date.now());
12601
+ return (0, import_react42.useEffect)(() => {
12562
12602
  let timer = setInterval(() => setNow(Date.now()), ms);
12563
12603
  return () => clearInterval(timer);
12564
12604
  }, [ms]), now;
12565
12605
  }
12566
12606
  function useAsyncData(load, deps) {
12567
- let client = useClient(), [data, setData] = (0, import_react41.useState)(void 0), [error, setError] = (0, import_react41.useState)(void 0), [loading, setLoading] = (0, import_react41.useState)(!1), [nonce2, setNonce] = (0, import_react41.useState)(0), seq = (0, import_react41.useRef)(0);
12568
- (0, import_react41.useEffect)(() => {
12607
+ let client = useClient(), [data, setData] = (0, import_react42.useState)(void 0), [error, setError] = (0, import_react42.useState)(void 0), [loading, setLoading] = (0, import_react42.useState)(!1), [nonce2, setNonce] = (0, import_react42.useState)(0), seq = (0, import_react42.useRef)(0);
12608
+ (0, import_react42.useEffect)(() => {
12569
12609
  if (!load) {
12570
12610
  setData(void 0), setError(void 0), setLoading(!1);
12571
12611
  return;
@@ -12580,7 +12620,7 @@ function useAsyncData(load, deps) {
12580
12620
  }
12581
12621
  );
12582
12622
  }, [...deps, nonce2, client]);
12583
- let reload = (0, import_react41.useCallback)(() => setNonce((n) => n + 1), []);
12623
+ let reload = (0, import_react42.useCallback)(() => setNonce((n) => n + 1), []);
12584
12624
  return { data, error, loading, reload };
12585
12625
  }
12586
12626
  var TIMER_EVENTS = ["timer.fired", "config.changed", "agent.loaded"];
@@ -12590,7 +12630,7 @@ function useAgentTimers(agentId) {
12590
12630
  }
12591
12631
  function useFleetTimers(enabled) {
12592
12632
  let rev = useLoopsRev(), tick = useEventTick(void 0, TIMER_EVENTS), agents = useTuiSelector((s) => s.agentOrder.map((id) => `${id}\0${s.agents[id]?.summary.handle || s.agents[id]?.summary.name || id}`).join(`
12593
- `)), [failures, setFailures] = (0, import_react41.useState)([]);
12633
+ `)), [failures, setFailures] = (0, import_react42.useState)([]);
12594
12634
  return { ...useAsyncData(enabled ? async (c) => {
12595
12635
  let list = agents ? agents.split(`
12596
12636
  `).map((line) => {
@@ -13225,7 +13265,7 @@ var TIMERS_TAB_HINTS = [
13225
13265
  ];
13226
13266
 
13227
13267
  // src/main/tui/views/loops/TriggersTab.tsx
13228
- var import_react42 = __toESM(require_react(), 1);
13268
+ var import_react43 = __toESM(require_react(), 1);
13229
13269
 
13230
13270
  // src/main/tui/views/loops/trigger-ops.ts
13231
13271
  function diffText(before, after, maxLines = 24) {
@@ -13268,7 +13308,7 @@ It has no targets yet, so it will not wake anything. Add a target with e.` : "";
13268
13308
  var import_jsx_runtime52 = __toESM(require_jsx_runtime(), 1);
13269
13309
  function TriggersTab({ agentId, width, height, focused, view: view2, setView, tabKeys }) {
13270
13310
  let theme2 = useTheme(), actions4 = useActions(), agent2 = useAgent(agentId), runtime3 = useRuntimeTriggers(agentId), config2 = agent2?.config;
13271
- (0, import_react42.useEffect)(() => {
13311
+ (0, import_react43.useEffect)(() => {
13272
13312
  config2 || actions4.loadConfig(agentId);
13273
13313
  }, [agentId, !!config2]);
13274
13314
  let label2 = agent2?.summary.handle || agent2?.summary.name || agentId, index = Math.min(view2.triggerIndex, TRIGGER_TYPES2.length - 1), selectedType = TRIGGER_TYPES2[index], selectedCfg = config2?.triggers?.[selectedType], w = width, detailRows = Math.max(0, Math.min(8, height - TRIGGER_TYPES2.length - 5)), listRows = Math.max(1, height - 4 - detailRows - (runtime3.error ? 1 : 0)), runtimeOf = (type) => runtime3.data?.configured.find((c) => c.type === type), cols = (type) => {
@@ -13436,7 +13476,7 @@ var HISTORY_TAB_HINTS = [
13436
13476
  ];
13437
13477
 
13438
13478
  // src/main/tui/views/loops/LoopWizard.tsx
13439
- var import_react43 = __toESM(require_react(), 1);
13479
+ var import_react44 = __toESM(require_react(), 1);
13440
13480
 
13441
13481
  // src/main/tui/views/loops/templates.ts
13442
13482
  var base = [...DEFAULT_NEW_LOOP_TOOLS], LOOP_TEMPLATES = [
@@ -13544,7 +13584,7 @@ function draftFromValues(v) {
13544
13584
  return { kind: v.scheduleKind ?? "none", value: String(v.scheduleValue ?? ""), payload: String(v.payload ?? ""), maxRuns: String(v.maxRuns ?? "") };
13545
13585
  }
13546
13586
  function LoopWizard({ overlay, close, width, height }) {
13547
- let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), agent2 = useAgent(props.agentId), loops2 = useLoops(props.agentId) ?? [], timers = useAgentTimers(props.agentId), { suspendTerminal } = use_app_default(), config2 = agent2?.config, host = hostLoopTools(config2), existing = props.mode === "edit" ? loops2.find((l) => l.info.name === props.name)?.info.config ?? void 0 : void 0, provider = config2?.model?.provider, models = useModelList(props.agentId, provider), takenNames = loops2.map((l) => l.info.name), initialTemplate = props.mode === "create" ? findTemplate(props.template) : void 0, [step, setStep] = (0, import_react43.useState)(props.mode === "create" && !initialTemplate ? "template" : "form"), [template, setTemplate] = (0, import_react43.useState)(initialTemplate), [values, setValues] = (0, import_react43.useState)(() => initialValues2(props, existing, initialTemplate, host, takenNames)), [touched, setTouched] = (0, import_react43.useState)(!1), [outcome, setOutcome] = (0, import_react43.useState)(null), dialogWidth = Math.max(40, Math.min(width - 4, 96)), inner = dialogWidth - 4, bodyRows = Math.max(6, height - 8), label2 = agent2 ? agentName3(store.getState(), props.agentId) : props.agentId, wanted = Array.isArray(values.tools) ? values.tools : [], options = toolOptions(host, [...wanted, ...existing?.tools ?? [], ...template?.tools ?? []]), draft = draftFromValues(values), loopName = props.mode === "edit" ? props.name ?? "" : String(values.name ?? ""), schedule = scheduleToTimer(draft, loopName), existingTimers = timers.data ? timersForLoop(timers.data, loopName) : [], errors = (0, import_react43.useMemo)(() => {
13587
+ let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), agent2 = useAgent(props.agentId), loops2 = useLoops(props.agentId) ?? [], timers = useAgentTimers(props.agentId), { suspendTerminal } = use_app_default(), config2 = agent2?.config, host = hostLoopTools(config2), existing = props.mode === "edit" ? loops2.find((l) => l.info.name === props.name)?.info.config ?? void 0 : void 0, provider = config2?.model?.provider, models = useModelList(props.agentId, provider), takenNames = loops2.map((l) => l.info.name), initialTemplate = props.mode === "create" ? findTemplate(props.template) : void 0, [step, setStep] = (0, import_react44.useState)(props.mode === "create" && !initialTemplate ? "template" : "form"), [template, setTemplate] = (0, import_react44.useState)(initialTemplate), [values, setValues] = (0, import_react44.useState)(() => initialValues2(props, existing, initialTemplate, host, takenNames)), [touched, setTouched] = (0, import_react44.useState)(!1), [outcome, setOutcome] = (0, import_react44.useState)(null), dialogWidth = Math.max(40, Math.min(width - 4, 96)), inner = dialogWidth - 4, bodyRows = Math.max(6, height - 8), label2 = agent2 ? agentName3(store.getState(), props.agentId) : props.agentId, wanted = Array.isArray(values.tools) ? values.tools : [], options = toolOptions(host, [...wanted, ...existing?.tools ?? [], ...template?.tools ?? []]), draft = draftFromValues(values), loopName = props.mode === "edit" ? props.name ?? "" : String(values.name ?? ""), schedule = scheduleToTimer(draft, loopName), existingTimers = timers.data ? timersForLoop(timers.data, loopName) : [], errors = (0, import_react44.useMemo)(() => {
13548
13588
  let e = {};
13549
13589
  props.mode === "create" && (e.name = validateLoopName(String(values.name ?? ""), takenNames) ?? void 0), e.goal = validateGoal(String(values.goal ?? ""), !!values.autostart) ?? void 0;
13550
13590
  let compact2 = String(values.compact ?? "").trim();
@@ -13800,7 +13840,7 @@ function MissingLoop({ title, name, close, width }) {
13800
13840
  }
13801
13841
 
13802
13842
  // src/main/tui/views/loops/TimerDialog.tsx
13803
- var import_react44 = __toESM(require_react(), 1);
13843
+ var import_react45 = __toESM(require_react(), 1);
13804
13844
  var import_jsx_runtime55 = __toESM(require_jsx_runtime(), 1), WHEN_LABEL2 = { none: "When", every: "Every", daily: "Daily at", cron: "Cron", in: "After", at: "At" }, WHEN_HINT2 = {
13805
13845
  none: "",
13806
13846
  every: "15m, 2h, 1h30m, 1d",
@@ -13817,13 +13857,13 @@ function choiceOf(scope) {
13817
13857
  return agent2 && system ? "both" : system ? "system" : "agent";
13818
13858
  }
13819
13859
  function TimerDialog({ overlay, close, width, height }) {
13820
- let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), agent2 = useAgent(props.agentId), loops2 = useLoops(props.agentId) ?? [], timers = useAgentTimers(props.agentId), existing = props.timerId !== void 0 ? timers.data?.find((t) => t.id === props.timerId) : void 0, editing = props.timerId !== void 0, [values, setValues] = (0, import_react44.useState)(() => editing ? null : initialValues3(void 0, props.loop)), [step, setStep] = (0, import_react44.useState)("form"), [touched, setTouched] = (0, import_react44.useState)(!1), [outcome, setOutcome] = (0, import_react44.useState)([]), current = values ?? (existing ? initialValues3(existing) : null), dialogWidth = Math.max(40, Math.min(width - 4, 90)), inner = dialogWidth - 4, bodyRows = Math.max(6, height - 8), label2 = agentName3(store.getState(), props.agentId), loopNames2 = [MAIN_LOOP, ...loops2.filter((l) => !l.info.isMain).map((l) => l.info.name)];
13860
+ let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), agent2 = useAgent(props.agentId), loops2 = useLoops(props.agentId) ?? [], timers = useAgentTimers(props.agentId), existing = props.timerId !== void 0 ? timers.data?.find((t) => t.id === props.timerId) : void 0, editing = props.timerId !== void 0, [values, setValues] = (0, import_react45.useState)(() => editing ? null : initialValues3(void 0, props.loop)), [step, setStep] = (0, import_react45.useState)("form"), [touched, setTouched] = (0, import_react45.useState)(!1), [outcome, setOutcome] = (0, import_react45.useState)([]), current = values ?? (existing ? initialValues3(existing) : null), dialogWidth = Math.max(40, Math.min(width - 4, 90)), inner = dialogWidth - 4, bodyRows = Math.max(6, height - 8), label2 = agentName3(store.getState(), props.agentId), loopNames2 = [MAIN_LOOP, ...loops2.filter((l) => !l.info.isMain).map((l) => l.info.name)];
13821
13861
  current && !loopNames2.includes(String(current.loop)) && loopNames2.push(String(current.loop));
13822
13862
  let scopeChoice = current?.scope ?? "agent", kind = current?.scheduleKind ?? "every", targetLoop = scopeChoice === "system" ? void 0 : String(current?.loop ?? MAIN_LOOP), result = current ? scheduleToTimer(
13823
13863
  { kind, value: String(current.scheduleValue ?? ""), payload: String(current.payload ?? ""), maxRuns: String(current.maxRuns ?? "") },
13824
13864
  targetLoop,
13825
13865
  { scope: scopeOf(scopeChoice), lambda: String(current.lambda ?? "").trim() || void 0 }
13826
- ) : null, input = result?.input ? { ...result.input, ...current?.locked ? { locked: !0 } : {} } : void 0, oldLoop = existing ? timerLoop2(existing) : null, loopChanged = !!existing && (targetLoop ?? null) !== oldLoop && targetLoop !== void 0 && oldLoop !== null, errors = (0, import_react44.useMemo)(() => {
13866
+ ) : null, input = result?.input ? { ...result.input, ...current?.locked ? { locked: !0 } : {} } : void 0, oldLoop = existing ? timerLoop2(existing) : null, loopChanged = !!existing && (targetLoop ?? null) !== oldLoop && targetLoop !== void 0 && oldLoop !== null, errors = (0, import_react45.useMemo)(() => {
13827
13867
  let e = {};
13828
13868
  return result?.error && (e.scheduleValue = result.error), scopeChoice !== "agent" && !String(current?.lambda ?? "").trim() && (e.lambda = "System-scope timers run a lambda: path/file.ts:functionName"), e;
13829
13869
  }, [result?.error, scopeChoice, current?.lambda]), hasErrors = Object.values(errors).some(Boolean), fields = [
@@ -13948,10 +13988,10 @@ function initialValues3(timer, loop) {
13948
13988
  }
13949
13989
 
13950
13990
  // src/main/tui/views/loops/TriggerDialog.tsx
13951
- var import_react45 = __toESM(require_react(), 1);
13991
+ var import_react46 = __toESM(require_react(), 1);
13952
13992
  var import_jsx_runtime56 = __toESM(require_jsx_runtime(), 1);
13953
13993
  function TriggerDialog({ overlay, close, width, height }) {
13954
- let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), loops2 = useLoops(props.agentId) ?? [], loaded = useAsyncData((c) => c.config(props.agentId), [props.agentId]), original = loaded.data?.config.triggers?.[props.type], [draft, setDraft] = (0, import_react45.useState)(null), current = draft ?? (loaded.data ? original ?? { enabled: !1, targets: [] } : null), [step, setStep] = (0, import_react45.useState)("targets"), [index, setIndex] = (0, import_react45.useState)(0), [editing, setEditing] = (0, import_react45.useState)(null), [targetValues, setTargetValues] = (0, import_react45.useState)({}), [targetErrors, setTargetErrors] = (0, import_react45.useState)({}), [message, setMessage] = (0, import_react45.useState)(""), dialogWidth = Math.max(44, Math.min(width - 4, 96)), inner = dialogWidth - 4, bodyRows = Math.max(6, height - 8), title = `Trigger ${props.type} ${theme2.glyph.sep} ${agentName3(store.getState(), props.agentId)}`, loopNames2 = [MAIN_LOOP, ...loops2.filter((l) => !l.info.isMain).map((l) => l.info.name)], dirty = !!draft && JSON.stringify(draft) !== JSON.stringify(original ?? { enabled: !1, targets: [] }), [confirmClose, setConfirmClose] = (0, import_react45.useState)(!1), update = (next) => setDraft(next), openTarget = (i) => {
13994
+ let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), loops2 = useLoops(props.agentId) ?? [], loaded = useAsyncData((c) => c.config(props.agentId), [props.agentId]), original = loaded.data?.config.triggers?.[props.type], [draft, setDraft] = (0, import_react46.useState)(null), current = draft ?? (loaded.data ? original ?? { enabled: !1, targets: [] } : null), [step, setStep] = (0, import_react46.useState)("targets"), [index, setIndex] = (0, import_react46.useState)(0), [editing, setEditing] = (0, import_react46.useState)(null), [targetValues, setTargetValues] = (0, import_react46.useState)({}), [targetErrors, setTargetErrors] = (0, import_react46.useState)({}), [message, setMessage] = (0, import_react46.useState)(""), dialogWidth = Math.max(44, Math.min(width - 4, 96)), inner = dialogWidth - 4, bodyRows = Math.max(6, height - 8), title = `Trigger ${props.type} ${theme2.glyph.sep} ${agentName3(store.getState(), props.agentId)}`, loopNames2 = [MAIN_LOOP, ...loops2.filter((l) => !l.info.isMain).map((l) => l.info.name)], dirty = !!draft && JSON.stringify(draft) !== JSON.stringify(original ?? { enabled: !1, targets: [] }), [confirmClose, setConfirmClose] = (0, import_react46.useState)(!1), update = (next) => setDraft(next), openTarget = (i) => {
13955
13995
  let target2 = i === null ? void 0 : current?.targets[i];
13956
13996
  setEditing(i), setTargetValues(targetToValues(target2)), setTargetErrors({}), setStep("target");
13957
13997
  }, saveTarget = () => {
@@ -14107,7 +14147,7 @@ function valuesToTarget(v, base2) {
14107
14147
  }
14108
14148
 
14109
14149
  // src/main/tui/views/loops/EntryDialog.tsx
14110
- var import_react46 = __toESM(require_react(), 1);
14150
+ var import_react47 = __toESM(require_react(), 1);
14111
14151
  var import_jsx_runtime57 = __toESM(require_jsx_runtime(), 1);
14112
14152
  function entryLines(entry, width) {
14113
14153
  let out = [], push = (text, tone) => {
@@ -14149,7 +14189,7 @@ function pretty(value) {
14149
14189
  }
14150
14190
  }
14151
14191
  function EntryDialog({ overlay, close, width, height }) {
14152
- let { entry, loop } = overlay.props ?? {}, theme2 = useTheme(), dialogWidth = Math.max(40, Math.min(width - 4, 110)), inner = dialogWidth - 4, rows = Math.max(4, height - 10), lines = entry ? entryLines(entry, inner) : [], [top, setTop] = (0, import_react46.useState)(0), maxTop = Math.max(0, lines.length - rows);
14192
+ let { entry, loop } = overlay.props ?? {}, theme2 = useTheme(), dialogWidth = Math.max(40, Math.min(width - 4, 110)), inner = dialogWidth - 4, rows = Math.max(4, height - 10), lines = entry ? entryLines(entry, inner) : [], [top, setTop] = (0, import_react47.useState)(0), maxTop = Math.max(0, lines.length - rows);
14153
14193
  if (useKeys((input, key) => key.escape || key.backspace || key.return || input === "q" ? (close(), !0) : key.downArrow || input === "j" ? (setTop((t) => Math.min(maxTop, t + 1)), !0) : key.upArrow || input === "k" ? (setTop((t) => Math.max(0, t - 1)), !0) : key.pageDown || input === " " ? (setTop((t) => Math.min(maxTop, t + rows)), !0) : key.pageUp ? (setTop((t) => Math.max(0, t - rows)), !0) : key.home || input === "g" ? (setTop(0), !0) : ((key.end || input === "G") && setTop(maxTop), !0), { layer: "overlay" }), !entry) return null;
14154
14194
  let tokens = formatTokens(entry);
14155
14195
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Modal, { title: `${loop} ${theme2.glyph.sep} entry #${entry.seq}`, width: dialogWidth, hints: [{ keys: "up down", label: "scroll" }, { keys: "pgup pgdn", label: "page" }, { keys: "backspace esc", label: "back" }], children: [
@@ -14177,14 +14217,14 @@ function EntryDialog({ overlay, close, width, height }) {
14177
14217
  }
14178
14218
 
14179
14219
  // src/main/tui/views/loops/SendDialog.tsx
14180
- var import_react47 = __toESM(require_react(), 1);
14220
+ var import_react48 = __toESM(require_react(), 1);
14181
14221
  var import_jsx_runtime58 = __toESM(require_jsx_runtime(), 1);
14182
14222
  async function sendToLoop(actions4, agentId, loop, text, agentLabel5) {
14183
14223
  let ok = await actions4.sendChat(text, { agentId, loop });
14184
14224
  return ok ? actions4.toast(`Sent to ${agentLabel5} ${loop}: turn queued (its reply is in the ${loop} transcript)`, "success") : actions4.toast(`Not sent to ${loop}: see the error in the ${loop} transcript`, "error"), ok;
14185
14225
  }
14186
14226
  function SendDialog({ overlay, close, width }) {
14187
- let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), loop = useLoop(props.agentId, props.loop), [values, setValues] = (0, import_react47.useState)({ text: props.text ?? "" }), [error, setError] = (0, import_react47.useState)(), label2 = agentName3(store.getState(), props.agentId), dialogWidth = Math.max(40, Math.min(width - 4, 90));
14227
+ let props = overlay.props ?? {}, theme2 = useTheme(), store = useStore(), actions4 = useActions(), loop = useLoop(props.agentId, props.loop), [values, setValues] = (0, import_react48.useState)({ text: props.text ?? "" }), [error, setError] = (0, import_react48.useState)(), label2 = agentName3(store.getState(), props.agentId), dialogWidth = Math.max(40, Math.min(width - 4, 90));
14188
14228
  return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Modal, { title: `Send to ${props.loop} ${theme2.glyph.sep} ${label2}`, width: dialogWidth, hints: [{ keys: "enter", label: "send & wake" }, { keys: "esc", label: "cancel" }], children: [
14189
14229
  loop && !loop.info.enabled ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Text, { color: theme2.color.warn, children: [
14190
14230
  theme2.glyph.warn,
@@ -14693,7 +14733,7 @@ function resolutionText(task) {
14693
14733
  }
14694
14734
 
14695
14735
  // src/main/tui/views/inspect/SettingsTab.tsx
14696
- var import_react48 = __toESM(require_react(), 1);
14736
+ var import_react49 = __toESM(require_react(), 1);
14697
14737
 
14698
14738
  // src/main/tui/views/inspect/settings-model.ts
14699
14739
  var TOOL_GROUPS = [
@@ -15158,16 +15198,16 @@ async function actOnSetting(actions4, agentId, row4, config2) {
15158
15198
  }
15159
15199
  }
15160
15200
  function SettingsTab({ agentId, width, height, focused }) {
15161
- let theme2 = useTheme(), actions4 = useActions(), client = useClient(), agent2 = useAgent(agentId), [inspect3, update] = useInspectState(), [extras, setExtras] = (0, import_react48.useState)({}), config2 = agent2?.config, loopNames2 = [MAIN_LOOP, ...(config2?.loops ?? []).map((l) => l.name)], reload = async (announce = !1) => {
15201
+ let theme2 = useTheme(), actions4 = useActions(), client = useClient(), agent2 = useAgent(agentId), [inspect3, update] = useInspectState(), [extras, setExtras] = (0, import_react49.useState)({}), config2 = agent2?.config, loopNames2 = [MAIN_LOOP, ...(config2?.loops ?? []).map((l) => l.name)], reload = async (announce = !1) => {
15162
15202
  let cfg = await actions4.loadConfig(agentId), names = [MAIN_LOOP, ...(cfg?.loops ?? []).map((l) => l.name)], [context, host] = await Promise.all([
15163
15203
  loadContextUsage(client, agentId, names),
15164
15204
  client.setting("compute").then((r) => !!r.value?.hostAccessEnabled, () => null)
15165
15205
  ]);
15166
15206
  setExtras({ context, daemonHostAccess: host }), announce && cfg && actions4.toast("Settings reloaded", "info", 1500);
15167
15207
  };
15168
- (0, import_react48.useEffect)(() => {
15208
+ (0, import_react49.useEffect)(() => {
15169
15209
  reload();
15170
- }, [agentId]), (0, import_react48.useEffect)(() => {
15210
+ }, [agentId]), (0, import_react49.useEffect)(() => {
15171
15211
  config2 && loadContextUsage(client, agentId, loopNames2).then((context) => setExtras((e) => ({ ...e, context })));
15172
15212
  }, [loopNames2.join(",")]);
15173
15213
  let rows = config2 ? settingRows(config2, extras) : [], index = Math.min(inspect3.settingsIndex ?? 0, Math.max(0, rows.length - 1));
@@ -15230,7 +15270,7 @@ function SettingsTab({ agentId, width, height, focused }) {
15230
15270
  }
15231
15271
 
15232
15272
  // src/main/tui/views/inspect/SettingDialogs.tsx
15233
- var import_react49 = __toESM(require_react(), 1);
15273
+ var import_react50 = __toESM(require_react(), 1);
15234
15274
  var import_jsx_runtime62 = __toESM(require_jsx_runtime(), 1);
15235
15275
  function compactionRows(config2) {
15236
15276
  let main = mainThreshold(config2);
@@ -15249,8 +15289,8 @@ async function applyThreshold(store, agentId, loop, value) {
15249
15289
  return loop === MAIN_LOOP ? applyChange(actions4, agentId, (cfg) => setMainThreshold(cfg, value), "Compaction") : await actions4.updateLoop(agentId, loop, { compact_threshold: value }) ? (await actions4.loadConfig(agentId), actions4.toast(value === null ? `${loop} inherits main\u2019s threshold again` : `${loop} compacts at ${formatTokens2(value)} tokens`, "success", 2500), !0) : !1;
15250
15290
  }
15251
15291
  function CompactionOverlay({ overlay, close, width, height }) {
15252
- let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, agentId = String(overlay.props?.agentId ?? ""), agent2 = useAgent(agentId), config2 = agent2?.config, rows = config2 ? compactionRows(config2) : [], initial = Math.max(0, rows.findIndex((r) => r.loop === overlay.props?.loop)), [index, setIndex] = (0, import_react49.useState)(initial), [editing, setEditing] = (0, import_react49.useState)(null), [draft, setDraft] = (0, import_react49.useState)(""), [error, setError] = (0, import_react49.useState)(null), [context, setContext] = (0, import_react49.useState)({});
15253
- (0, import_react49.useEffect)(() => {
15292
+ let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, agentId = String(overlay.props?.agentId ?? ""), agent2 = useAgent(agentId), config2 = agent2?.config, rows = config2 ? compactionRows(config2) : [], initial = Math.max(0, rows.findIndex((r) => r.loop === overlay.props?.loop)), [index, setIndex] = (0, import_react50.useState)(initial), [editing, setEditing] = (0, import_react50.useState)(null), [draft, setDraft] = (0, import_react50.useState)(""), [error, setError] = (0, import_react50.useState)(null), [context, setContext] = (0, import_react50.useState)({});
15293
+ (0, import_react50.useEffect)(() => {
15254
15294
  config2 || actions4.loadConfig(agentId), loadContextUsage(store.client, agentId, [MAIN_LOOP, ...(config2?.loops ?? []).map((l) => l.name)]).then(setContext);
15255
15295
  }, [agentId]);
15256
15296
  let row4 = rows[Math.min(index, Math.max(0, rows.length - 1))], submit = async (value) => {
@@ -15333,7 +15373,7 @@ function CompactionOverlay({ overlay, close, width, height }) {
15333
15373
  );
15334
15374
  }
15335
15375
  function SettingChoiceOverlay({ overlay, close, width }) {
15336
- let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, agentId = String(overlay.props?.agentId ?? ""), setting = overlay.props?.setting === "send" ? "send" : "visibility", m = useAgent(agentId)?.config?.messaging, options = setting === "send" ? SEND_MODES.map((v) => ({ value: v, hint: SEND_MODE_HINTS[v] })) : VISIBILITY_TIERS.map((v) => ({ value: v, hint: VISIBILITY_HINTS[v] })), current = setting === "send" ? m?.mode ?? "respond_only" : m?.visibility ?? "localhost", [index, setIndex] = (0, import_react49.useState)(Math.max(0, options.findIndex((o) => o.value === current))), apply = async (value) => {
15376
+ let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, agentId = String(overlay.props?.agentId ?? ""), setting = overlay.props?.setting === "send" ? "send" : "visibility", m = useAgent(agentId)?.config?.messaging, options = setting === "send" ? SEND_MODES.map((v) => ({ value: v, hint: SEND_MODE_HINTS[v] })) : VISIBILITY_TIERS.map((v) => ({ value: v, hint: VISIBILITY_HINTS[v] })), current = setting === "send" ? m?.mode ?? "respond_only" : m?.visibility ?? "localhost", [index, setIndex] = (0, import_react50.useState)(Math.max(0, options.findIndex((o) => o.value === current))), apply = async (value) => {
15337
15377
  close(), value !== current && (setting === "visibility" && (value === "lan" || value === "public") && !await actions4.confirm({
15338
15378
  title: `Make the agent reachable ${value === "public" ? "from the internet" : "on the local network"}?`,
15339
15379
  message: `Visibility ${value}: ${VISIBILITY_HINTS[value]}. Other agents there can send it messages.`,
@@ -15563,13 +15603,13 @@ var inspect = {
15563
15603
  ], inspectCommands = { commands: [inspect, model, config, tasks, instructions, tools, compaction, media], actions: actions2 };
15564
15604
 
15565
15605
  // src/main/tui/views/inspect/EventsTab.tsx
15566
- var import_react51 = __toESM(require_react(), 1);
15606
+ var import_react52 = __toESM(require_react(), 1);
15567
15607
 
15568
15608
  // src/main/tui/views/inspect/hooks.ts
15569
- var import_react50 = __toESM(require_react(), 1);
15609
+ var import_react51 = __toESM(require_react(), 1);
15570
15610
  function useDaemonData(key, load) {
15571
- let store = useStore(), [data, setData] = (0, import_react50.useState)(void 0), [error, setError] = (0, import_react50.useState)(void 0), [loading, setLoading] = (0, import_react50.useState)(!1), [loadedAt, setLoadedAt] = (0, import_react50.useState)(void 0), [nonce2, setNonce] = (0, import_react50.useState)(0), loadRef = (0, import_react50.useRef)(load);
15572
- loadRef.current = load, (0, import_react50.useEffect)(() => {
15611
+ let store = useStore(), [data, setData] = (0, import_react51.useState)(void 0), [error, setError] = (0, import_react51.useState)(void 0), [loading, setLoading] = (0, import_react51.useState)(!1), [loadedAt, setLoadedAt] = (0, import_react51.useState)(void 0), [nonce2, setNonce] = (0, import_react51.useState)(0), loadRef = (0, import_react51.useRef)(load);
15612
+ loadRef.current = load, (0, import_react51.useEffect)(() => {
15573
15613
  if (key === null) {
15574
15614
  setData(void 0), setError(void 0);
15575
15615
  return;
@@ -15586,12 +15626,12 @@ function useDaemonData(key, load) {
15586
15626
  cancelled = !0;
15587
15627
  };
15588
15628
  }, [store, key, nonce2]);
15589
- let reload = (0, import_react50.useCallback)(() => setNonce((n) => n + 1), []);
15629
+ let reload = (0, import_react51.useCallback)(() => setNonce((n) => n + 1), []);
15590
15630
  return { data, error, loading, loadedAt, reload };
15591
15631
  }
15592
15632
  function useAgentName() {
15593
15633
  let store = useStore();
15594
- return (0, import_react50.useCallback)((agentId) => {
15634
+ return (0, import_react51.useCallback)((agentId) => {
15595
15635
  if (!agentId) return "daemon";
15596
15636
  let summary = store.getState().agents[agentId]?.summary;
15597
15637
  return summary?.handle || summary?.name || agentId.slice(0, 8);
@@ -15699,7 +15739,7 @@ function eventRow(event) {
15699
15739
  // src/main/tui/views/inspect/EventsTab.tsx
15700
15740
  var import_jsx_runtime63 = __toESM(require_jsx_runtime(), 1), EMPTY2 = [], EVENTS_REFRESH_MS = 100;
15701
15741
  function EventsTab({ width, height, focused, filters: stored, update, scope, json: json2 }) {
15702
- let theme2 = useTheme(), filters = scope === "agent" ? { ...stored, agent: "selected" } : stored, live = useThrottledSelector((s) => s.lastEvents ?? EMPTY2, EVENTS_REFRESH_MS), selectedAgentId = useSelectedAgentId(), selectedLoop = useSelectedLoop(), nameOf = useAgentName(), [frozen, setFrozen] = (0, import_react51.useState)(null), [clearedAfter, setClearedAfter] = (0, import_react51.useState)(0), [anchor, setAnchor] = (0, import_react51.useState)(null), [pinned, setPinned] = (0, import_react51.useState)(!0), [detail, setDetail] = (0, import_react51.useState)(!1), [editing, setEditing] = (0, import_react51.useState)(null), [draft, setDraft] = (0, import_react51.useState)(filters.types), [query, setQuery] = (0, import_react51.useState)(""), source = frozen ?? live, { types, agent: agent2, loop } = filters, events2 = (0, import_react51.useMemo)(
15742
+ let theme2 = useTheme(), filters = scope === "agent" ? { ...stored, agent: "selected" } : stored, live = useThrottledSelector((s) => s.lastEvents ?? EMPTY2, EVENTS_REFRESH_MS), selectedAgentId = useSelectedAgentId(), selectedLoop = useSelectedLoop(), nameOf = useAgentName(), [frozen, setFrozen] = (0, import_react52.useState)(null), [clearedAfter, setClearedAfter] = (0, import_react52.useState)(0), [anchor, setAnchor] = (0, import_react52.useState)(null), [pinned, setPinned] = (0, import_react52.useState)(!0), [detail, setDetail] = (0, import_react52.useState)(!1), [editing, setEditing] = (0, import_react52.useState)(null), [draft, setDraft] = (0, import_react52.useState)(filters.types), [query, setQuery] = (0, import_react52.useState)(""), source = frozen ?? live, { types, agent: agent2, loop } = filters, events2 = (0, import_react52.useMemo)(
15703
15743
  () => {
15704
15744
  let matched = filterEvents(source, { types, agent: agent2, loop, follow: !0 }, { selectedAgentId, selectedLoop });
15705
15745
  clearedAfter && (matched = matched.filter((e) => e.timestamp > clearedAfter));
@@ -15707,10 +15747,10 @@ function EventsTab({ width, height, focused, filters: stored, update, scope, jso
15707
15747
  return q && (matched = matched.filter((e) => eventRow(e).search.includes(q) || nameOf(e.agent_id).toLowerCase().includes(q))), matched;
15708
15748
  },
15709
15749
  [source, types, agent2, loop, selectedAgentId, selectedLoop, clearedAfter, query, nameOf]
15710
- ), indexOf = (0, import_react51.useMemo)(() => {
15750
+ ), indexOf = (0, import_react52.useMemo)(() => {
15711
15751
  let map = /* @__PURE__ */ new Map();
15712
15752
  return events2.forEach((e, i) => map.set(eventKey(e), i)), map;
15713
- }, [events2]), lastFrozen = frozen?.at(-1), newWhileFrozen = lastFrozen ? live.length - 1 - live.lastIndexOf(lastFrozen) : 0, following = filters.follow && pinned && !frozen, anchored = anchor === null ? -1 : indexOf.get(anchor) ?? -1, index = following || anchored < 0 ? Math.max(0, events2.length - 1) : anchored, current = events2[index], detailRows = detail && current ? Math.max(4, Math.floor((height - 3) / 2)) : 0, listHeight = Math.max(1, height - 2 - (editing ? 1 : 0) - (detailRows ? detailRows + 1 : 0)), nameWidth = 10, loopWidth = 12, typeWidth = 22, agentLabel5 = filters.agent === "selected" || filters.loop === "selected" ? selectedAgentId ? nameOf(selectedAgentId) : "selected (none)" : "all agents", loopLabel = filters.loop === "selected" ? selectedLoop : "all loops", onSelect = (0, import_react51.useCallback)((i, item) => {
15753
+ }, [events2]), lastFrozen = frozen?.at(-1), newWhileFrozen = lastFrozen ? live.length - 1 - live.lastIndexOf(lastFrozen) : 0, following = filters.follow && pinned && !frozen, anchored = anchor === null ? -1 : indexOf.get(anchor) ?? -1, index = following || anchored < 0 ? Math.max(0, events2.length - 1) : anchored, current = events2[index], detailRows = detail && current ? Math.max(4, Math.floor((height - 3) / 2)) : 0, listHeight = Math.max(1, height - 2 - (editing ? 1 : 0) - (detailRows ? detailRows + 1 : 0)), nameWidth = 10, loopWidth = 12, typeWidth = 22, agentLabel5 = filters.agent === "selected" || filters.loop === "selected" ? selectedAgentId ? nameOf(selectedAgentId) : "selected (none)" : "all agents", loopLabel = filters.loop === "selected" ? selectedLoop : "all loops", onSelect = (0, import_react52.useCallback)((i, item) => {
15714
15754
  setAnchor(item ? eventKey(item) : null), setPinned(i >= events2.length - 1);
15715
15755
  }, [events2.length]), onKey = (input, key) => key.ctrl || key.meta ? !1 : key.return ? (setDetail((d) => !d), !0) : (key.escape || key.backspace) && detail ? (setDetail(!1), !0) : input === " " ? (frozen ? (setFrozen(null), setPinned(!0)) : setFrozen(live), !0) : input === "a" && scope === "all" ? (update({ agent: filters.agent === "all" ? "selected" : "all", loop: filters.agent === "all" ? filters.loop : "all" }), !0) : input === "l" ? (update({ loop: filters.loop === "all" ? "selected" : "all" }), !0) : input === "t" ? (setDraft(filters.types), setEditing("type"), !0) : input === "/" ? (setDraft(query), setEditing("search"), !0) : key.escape && query ? (setQuery(""), !0) : input === "f" ? (update({ follow: !filters.follow }), setPinned(!0), !0) : input === "c" ? (setClearedAfter(Date.now()), !0) : input === "x" && (filters.types || scope === "all" && filters.agent !== "all" || filters.loop !== "all") ? (update({ types: "", agent: scope === "all" ? "all" : "selected", loop: "all" }), !0) : !1, status = [
15716
15756
  frozen ? `paused${newWhileFrozen > 0 ? ` (+${newWhileFrozen} new)` : ""}` : following ? "following" : "scrolled (End follows)",
@@ -15719,7 +15759,7 @@ function EventsTab({ width, height, focused, filters: stored, update, scope, jso
15719
15759
  filters.types ? `type: ${filters.types}` : "all types",
15720
15760
  query ? `search: ${query}` : "",
15721
15761
  clearedAfter ? `cleared ${formatClock(clearedAfter)}` : ""
15722
- ].filter(Boolean).join(` ${theme2.glyph.sep} `), detailLines2 = (0, import_react51.useMemo)(() => detailRows && current ? valueLines(current, json2).slice(0, detailRows) : [], [detailRows, current, json2]);
15762
+ ].filter(Boolean).join(` ${theme2.glyph.sep} `), detailLines2 = (0, import_react52.useMemo)(() => detailRows && current ? valueLines(current, json2).slice(0, detailRows) : [], [detailRows, current, json2]);
15723
15763
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(Box_default, { flexDirection: "column", width, height, children: [
15724
15764
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(Text, { wrap: "truncate-end", children: [
15725
15765
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Text, { bold: !0, color: theme2.color.live, children: "Umbilical " }),
@@ -15817,7 +15857,7 @@ function typeColor(theme2, type) {
15817
15857
  }
15818
15858
 
15819
15859
  // src/main/tui/views/inspect/ConfigTab.tsx
15820
- var import_react52 = __toESM(require_react(), 1);
15860
+ var import_react53 = __toESM(require_react(), 1);
15821
15861
  var import_jsx_runtime64 = __toESM(require_jsx_runtime(), 1);
15822
15862
  import { promises as fs5 } from "node:fs";
15823
15863
  import { tmpdir as tmpdir4 } from "node:os";
@@ -15886,12 +15926,12 @@ Warning: ${check.warnings.join("; ")}` : ""}`,
15886
15926
  }
15887
15927
  }
15888
15928
  function ConfigTab({ agentId, label: label2, width, height, focused }) {
15889
- let theme2 = useTheme(), actions4 = useActions(), { suspendTerminal } = use_app_default(), agent2 = useAgent(agentId), [inspect3, update] = useInspectState(), [busy, setBusy] = (0, import_react52.useState)(!1), config2 = agent2?.config, edit = () => {
15929
+ let theme2 = useTheme(), actions4 = useActions(), { suspendTerminal } = use_app_default(), agent2 = useAgent(agentId), [inspect3, update] = useInspectState(), [busy, setBusy] = (0, import_react53.useState)(!1), config2 = agent2?.config, edit = () => {
15890
15930
  setBusy(!0), editConfigFlow(agentId, label2, actions4, suspendTerminal).finally(() => setBusy(!1));
15891
15931
  };
15892
- (0, import_react52.useEffect)(() => {
15932
+ (0, import_react53.useEffect)(() => {
15893
15933
  !inspect3.editRequest || busy || (update({ editRequest: void 0 }), edit());
15894
- }, [inspect3.editRequest]), (0, import_react52.useEffect)(() => {
15934
+ }, [inspect3.editRequest]), (0, import_react53.useEffect)(() => {
15895
15935
  config2 || actions4.loadConfig(agentId);
15896
15936
  }, [agentId]), useKeys((input, key) => key.ctrl || key.meta || busy ? !1 : input === "e" ? (edit(), !0) : input === "r" ? (actions4.loadConfig(agentId).then((c) => {
15897
15937
  c && actions4.toast("Config reloaded", "info", 1500);
@@ -15925,7 +15965,7 @@ function ConfigTab({ agentId, label: label2, width, height, focused }) {
15925
15965
  }
15926
15966
 
15927
15967
  // src/main/tui/views/inspect/DiagTabs.tsx
15928
- var import_react53 = __toESM(require_react(), 1);
15968
+ var import_react54 = __toESM(require_react(), 1);
15929
15969
 
15930
15970
  // src/main/tui/views/inspect/diag-lines.ts
15931
15971
  function stamp(at) {
@@ -16027,7 +16067,7 @@ var import_jsx_runtime65 = __toESM(require_jsx_runtime(), 1);
16027
16067
  function DiagTab({ agentId, width, height, focused, load, build, hint, prefix, onKey }) {
16028
16068
  let theme2 = useTheme(), [inspect3] = useInspectState(), { data, error, loading, loadedAt, reload } = useDaemonData(agentId, load);
16029
16069
  useKeys((input, key) => key.ctrl || key.meta ? !1 : input === "r" ? (reload(), !0) : onKey?.(input, key) ?? !1, { layer: "main", active: focused });
16030
- let lines = (0, import_react53.useMemo)(() => {
16070
+ let lines = (0, import_react54.useMemo)(() => {
16031
16071
  let head = prefix && !inspect3.json ? prefix : [];
16032
16072
  return error ? [...head, plain(`Could not load: ${error}`, "error"), plain("r retries.", "muted")] : data === void 0 ? head : inspect3.json ? valueLines(data, !0) : [...head, ...build(data)];
16033
16073
  }, [data, error, inspect3.json, build, prefix]);
@@ -16045,7 +16085,7 @@ function DiagTab({ agentId, width, height, focused, load, build, hint, prefix, o
16045
16085
  ] });
16046
16086
  }
16047
16087
  function RuntimeTab(props) {
16048
- let store = useStore(), loops2 = useLoops(props.agentId), build = (0, import_react53.useMemo)(() => (d) => runtimeLines(d, loops2), [loops2]), web = useTuiSelector((s) => s.web), config2 = useTuiSelector((s) => s.agents[props.agentId]?.config), site = siteOf(store.getState(), props.agentId), prefix = (0, import_react53.useMemo)(() => site ? siteLines(site) : void 0, [web, config2, props.agentId]);
16088
+ let store = useStore(), loops2 = useLoops(props.agentId), build = (0, import_react54.useMemo)(() => (d) => runtimeLines(d, loops2), [loops2]), web = useTuiSelector((s) => s.web), config2 = useTuiSelector((s) => s.agents[props.agentId]?.config), site = siteOf(store.getState(), props.agentId), prefix = (0, import_react54.useMemo)(() => site ? siteLines(site) : void 0, [web, config2, props.agentId]);
16049
16089
  return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(DiagTab, { ...props, load: (c) => c.agentRuntime(props.agentId), build, prefix, onKey: (input, key) => !site || key.ctrl || key.meta ? !1 : input === "w" ? (openSite(store, props.agentId), !0) : input === "W" ? (copySiteUrl(store, props.agentId), !0) : !1, hint: site ? "w open site \xB7 W copy URL" : void 0 });
16050
16090
  }
16051
16091
  function siteLines(site) {
@@ -16058,7 +16098,7 @@ function siteLines(site) {
16058
16098
  return out.push([{ text: " server ", tone: "key" }, { text: serverText(site.server), tone: site.url ? "success" : "muted" }]), out.push([{ text: " serves ", tone: "key" }, { text: servedText(site) }]), out.push(blank()), out;
16059
16099
  }
16060
16100
  function UsageTab(props) {
16061
- let agent2 = useAgent(props.agentId), build = (0, import_react53.useMemo)(() => (d) => usageLines(d, agent2?.tokens, agent2?.lastModel), [agent2?.tokens, agent2?.lastModel]);
16101
+ let agent2 = useAgent(props.agentId), build = (0, import_react54.useMemo)(() => (d) => usageLines(d, agent2?.tokens, agent2?.lastModel), [agent2?.tokens, agent2?.lastModel]);
16062
16102
  return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(DiagTab, { ...props, load: (c) => c.agentUsage(props.agentId), build });
16063
16103
  }
16064
16104
  function McpTab(props) {
@@ -16074,7 +16114,7 @@ function IdentityTab(props) {
16074
16114
  }
16075
16115
  var LOG_LIMIT = 200, LOG_POLL_MS = 2e3;
16076
16116
  function LogsTab({ agentId, width, height, focused }) {
16077
- let theme2 = useTheme(), actions4 = useActions(), { client } = useStore(), [inspect3, update] = useInspectState(), follow = inspect3.logsFollow, [logs, setLogs] = (0, import_react53.useState)([]), [error, setError] = (0, import_react53.useState)(void 0), [cursor, setCursor] = (0, import_react53.useState)(0), [pinned, setPinned] = (0, import_react53.useState)(!0), [detail, setDetail] = (0, import_react53.useState)(!1), lastId = (0, import_react53.useRef)(0), loadAll = async () => {
16117
+ let theme2 = useTheme(), actions4 = useActions(), { client } = useStore(), [inspect3, update] = useInspectState(), follow = inspect3.logsFollow, [logs, setLogs] = (0, import_react54.useState)([]), [error, setError] = (0, import_react54.useState)(void 0), [cursor, setCursor] = (0, import_react54.useState)(0), [pinned, setPinned] = (0, import_react54.useState)(!0), [detail, setDetail] = (0, import_react54.useState)(!1), lastId = (0, import_react54.useRef)(0), loadAll = async () => {
16078
16118
  let result = await actions4.run("Logs", (c) => c.logs(agentId, { limit: LOG_LIMIT }));
16079
16119
  if (!result) {
16080
16120
  setError("could not load logs");
@@ -16083,9 +16123,9 @@ function LogsTab({ agentId, width, height, focused }) {
16083
16123
  let sorted = [...result.logs].sort((a, b) => a.id - b.id);
16084
16124
  lastId.current = sorted.at(-1)?.id ?? 0, setLogs(sorted), setError(void 0);
16085
16125
  };
16086
- (0, import_react53.useEffect)(() => {
16126
+ (0, import_react54.useEffect)(() => {
16087
16127
  lastId.current = 0, setLogs([]), loadAll();
16088
- }, [agentId]), (0, import_react53.useEffect)(() => {
16128
+ }, [agentId]), (0, import_react54.useEffect)(() => {
16089
16129
  if (!follow) return;
16090
16130
  let stopped = !1, timer = setInterval(async () => {
16091
16131
  try {
@@ -16173,8 +16213,8 @@ function parseMaybeJson2(text) {
16173
16213
  }
16174
16214
  var PAGE = 50;
16175
16215
  function TablesTab({ agentId, width, height, focused }) {
16176
- let theme2 = useTheme(), [inspect3] = useInspectState(), tables = useDaemonData(agentId, (c) => c.tables(agentId)), [open2, setOpen] = (0, import_react53.useState)(null), [offset, setOffset] = (0, import_react53.useState)(0), [rowIndex, setRowIndex] = (0, import_react53.useState)(0), [rowDetail, setRowDetail] = (0, import_react53.useState)(!1), rows = useDaemonData(open2 ? `${agentId}:${open2}:${offset}` : null, (c) => c.table(agentId, open2 ?? "", { limit: PAGE, offset })), total = tables.data?.tables.find((t) => t.name === open2)?.row_count;
16177
- if ((0, import_react53.useEffect)(() => {
16216
+ let theme2 = useTheme(), [inspect3] = useInspectState(), tables = useDaemonData(agentId, (c) => c.tables(agentId)), [open2, setOpen] = (0, import_react54.useState)(null), [offset, setOffset] = (0, import_react54.useState)(0), [rowIndex, setRowIndex] = (0, import_react54.useState)(0), [rowDetail, setRowDetail] = (0, import_react54.useState)(!1), rows = useDaemonData(open2 ? `${agentId}:${open2}:${offset}` : null, (c) => c.table(agentId, open2 ?? "", { limit: PAGE, offset })), total = tables.data?.tables.find((t) => t.name === open2)?.row_count;
16217
+ if ((0, import_react54.useEffect)(() => {
16178
16218
  setOpen(null), setOffset(0);
16179
16219
  }, [agentId]), useKeys((input, key) => {
16180
16220
  if (!open2 || key.ctrl || key.meta) return !1;
@@ -16249,7 +16289,7 @@ function rowKey(row4, all) {
16249
16289
  }
16250
16290
 
16251
16291
  // src/main/tui/views/inspect/TasksTab.tsx
16252
- var import_react54 = __toESM(require_react(), 1);
16292
+ var import_react55 = __toESM(require_react(), 1);
16253
16293
  var import_jsx_runtime66 = __toESM(require_jsx_runtime(), 1), TASKS_RELOAD_MS = 250, FILTER_LABEL = {
16254
16294
  pending: "pending (awaiting approval or resolve)",
16255
16295
  active: "active (pending + running)",
@@ -16257,7 +16297,7 @@ var import_jsx_runtime66 = __toESM(require_jsx_runtime(), 1), TASKS_RELOAD_MS =
16257
16297
  };
16258
16298
  function useTaskEventReload(agentId, reload) {
16259
16299
  let store = useStore();
16260
- (0, import_react54.useEffect)(() => {
16300
+ (0, import_react55.useEffect)(() => {
16261
16301
  let seen = store.getState().lastEvents.at(-1), timer = null, unsubscribe = store.subscribe(() => {
16262
16302
  let events2 = store.getState().lastEvents, last = events2.at(-1);
16263
16303
  if (last === seen) return;
@@ -16277,12 +16317,12 @@ function useTaskEventReload(agentId, reload) {
16277
16317
  }, [store, agentId, reload]);
16278
16318
  }
16279
16319
  function TasksTab({ agentId, width, height, focused }) {
16280
- let theme2 = useTheme(), actions4 = useActions(), agent2 = useAgent(agentId), agentLabel5 = agent2?.summary.handle || agent2?.summary.name || agentId, [inspect3, update] = useInspectState(), filter = inspect3.tasksFilter, [tick, setTick] = (0, import_react54.useState)(0), refresh2 = (0, import_react54.useMemo)(() => () => setTick((n) => n + 1), []), tasks2 = useDaemonData(`${agentId}:${filter}:${tick}`, (c) => loadTasks(c, agentId, filter)), [selectedId, setSelectedId] = (0, import_react54.useState)(null), [detailId, setDetailId] = (0, import_react54.useState)(null), detail = useDaemonData(detailId ? `${agentId}:${detailId}:${tick}` : null, (c) => c.task(agentId, detailId ?? "")), [editing, setEditing] = (0, import_react54.useState)(!1), [draft, setDraft] = (0, import_react54.useState)(""), [query, setQuery] = (0, import_react54.useState)("");
16281
- useTaskEventReload(agentId, refresh2), (0, import_react54.useEffect)(() => {
16320
+ let theme2 = useTheme(), actions4 = useActions(), agent2 = useAgent(agentId), agentLabel5 = agent2?.summary.handle || agent2?.summary.name || agentId, [inspect3, update] = useInspectState(), filter = inspect3.tasksFilter, [tick, setTick] = (0, import_react55.useState)(0), refresh2 = (0, import_react55.useMemo)(() => () => setTick((n) => n + 1), []), tasks2 = useDaemonData(`${agentId}:${filter}:${tick}`, (c) => loadTasks(c, agentId, filter)), [selectedId, setSelectedId] = (0, import_react55.useState)(null), [detailId, setDetailId] = (0, import_react55.useState)(null), detail = useDaemonData(detailId ? `${agentId}:${detailId}:${tick}` : null, (c) => c.task(agentId, detailId ?? "")), [editing, setEditing] = (0, import_react55.useState)(!1), [draft, setDraft] = (0, import_react55.useState)(""), [query, setQuery] = (0, import_react55.useState)("");
16321
+ useTaskEventReload(agentId, refresh2), (0, import_react55.useEffect)(() => {
16282
16322
  setSelectedId(null), setDetailId(null);
16283
16323
  }, [agentId]);
16284
- let all = (0, import_react54.useMemo)(() => tasks2.data ?? [], [tasks2.data]), visible = (0, import_react54.useMemo)(() => searchTasks(all.filter((t) => matchesFilter(t, filter)), query), [all, filter, query]), found = selectedId ? visible.findIndex((t) => t.id === selectedId) : -1, index = found >= 0 ? found : 0, current = visible[index], adrift = selectedId !== null && found < 0;
16285
- (0, import_react54.useEffect)(() => {
16324
+ let all = (0, import_react55.useMemo)(() => tasks2.data ?? [], [tasks2.data]), visible = (0, import_react55.useMemo)(() => searchTasks(all.filter((t) => matchesFilter(t, filter)), query), [all, filter, query]), found = selectedId ? visible.findIndex((t) => t.id === selectedId) : -1, index = found >= 0 ? found : 0, current = visible[index], adrift = selectedId !== null && found < 0;
16325
+ (0, import_react55.useEffect)(() => {
16286
16326
  selectedId === null && visible[0] && setSelectedId(visible[0].id);
16287
16327
  }, [selectedId, visible]);
16288
16328
  let shown = detailId ? detail.data?.task ?? all.find((t) => t.id === detailId) : void 0, act = (input, task, drifted = !1) => {
@@ -16442,18 +16482,18 @@ function TasksTab({ agentId, width, height, focused }) {
16442
16482
  }
16443
16483
 
16444
16484
  // src/main/tui/views/inspect/ToolsDialog.tsx
16445
- var import_react55 = __toESM(require_react(), 1);
16485
+ var import_react56 = __toESM(require_react(), 1);
16446
16486
  var import_jsx_runtime67 = __toESM(require_jsx_runtime(), 1);
16447
16487
  function stateWords(row4) {
16448
16488
  let parts = [row4.enabled ? "enabled" : "disabled"];
16449
16489
  return row4.enabled && parts.push(row4.visible ? "in the agent\u2019s tool list" : "hidden from the tool list (still callable from code)"), row4.restricted && parts.push(row4.enabled ? "every LLM call waits for your approval" : "needs approval when enabled"), row4.locked && parts.push("locked: the agent cannot change it"), row4.status && parts.push(`MCP: ${row4.status}${row4.status === "changed" ? " (schema changed, review before enabling)" : ""}`), parts.join(" \xB7 ");
16450
16490
  }
16451
16491
  function ToolsOverlay({ overlay, close, width, height }) {
16452
- let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, agentId = String(overlay.props?.agentId ?? ""), agent2 = useAgent(agentId), config2 = agent2?.config, [catalog, setCatalog] = (0, import_react55.useState)(null), [live, setLive] = (0, import_react55.useState)(null), [query, setQuery] = (0, import_react55.useState)(typeof overlay.props?.query == "string" ? overlay.props.query : ""), [typing, setTyping] = (0, import_react55.useState)(!1), [index, setIndex] = (0, import_react55.useState)(0), [busy, setBusy] = (0, import_react55.useState)(0);
16453
- (0, import_react55.useEffect)(() => {
16492
+ let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, agentId = String(overlay.props?.agentId ?? ""), agent2 = useAgent(agentId), config2 = agent2?.config, [catalog, setCatalog] = (0, import_react56.useState)(null), [live, setLive] = (0, import_react56.useState)(null), [query, setQuery] = (0, import_react56.useState)(typeof overlay.props?.query == "string" ? overlay.props.query : ""), [typing, setTyping] = (0, import_react56.useState)(!1), [index, setIndex] = (0, import_react56.useState)(0), [busy, setBusy] = (0, import_react56.useState)(0);
16493
+ (0, import_react56.useEffect)(() => {
16454
16494
  config2 || actions4.loadConfig(agentId), store.client.agentTools(agentId).then((r) => setCatalog(r.tools), () => setCatalog(null)), store.client.agentMcp(agentId).then(setLive, () => setLive(null));
16455
16495
  }, [agentId]);
16456
- let rows = (0, import_react55.useMemo)(() => config2 ? filterToolRows(buildToolRows(config2, catalog), query) : [], [config2, catalog, query]), at = Math.min(index, Math.max(0, rows.length - 1)), row4 = rows[at], act = (field) => {
16496
+ let rows = (0, import_react56.useMemo)(() => config2 ? filterToolRows(buildToolRows(config2, catalog), query) : [], [config2, catalog, query]), at = Math.min(index, Math.max(0, rows.length - 1)), row4 = rows[at], act = (field) => {
16457
16497
  if (!row4) return;
16458
16498
  setBusy((n) => n + 1);
16459
16499
  let done = () => setBusy((n) => n - 1);
@@ -16583,17 +16623,17 @@ function ToolsOverlay({ overlay, close, width, height }) {
16583
16623
  }
16584
16624
 
16585
16625
  // src/main/tui/views/inspect/InstructionsDialog.tsx
16586
- var import_react56 = __toESM(require_react(), 1);
16626
+ var import_react57 = __toESM(require_react(), 1);
16587
16627
  var import_jsx_runtime68 = __toESM(require_jsx_runtime(), 1);
16588
16628
  function InstructionsOverlay({ overlay, close, width, height }) {
16589
- let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, { suspendTerminal } = use_app_default(), agentId = String(overlay.props?.agentId ?? ""), external = overlay.props?.editor === !0, who = store.getState().agents[agentId]?.summary.handle || store.getState().agents[agentId]?.summary.name || agentId, [original, setOriginal] = (0, import_react56.useState)(null), [text, setText] = (0, import_react56.useState)(""), [locked, setLocked] = (0, import_react56.useState)(!1), [busy, setBusy] = (0, import_react56.useState)(external ? `editing in ${editorLabel()}\u2026` : null), closed = (0, import_react56.useRef)(!1), done = () => {
16629
+ let theme2 = useTheme(), store = useStore(), { actions: actions4 } = store, { suspendTerminal } = use_app_default(), agentId = String(overlay.props?.agentId ?? ""), external = overlay.props?.editor === !0, who = store.getState().agents[agentId]?.summary.handle || store.getState().agents[agentId]?.summary.name || agentId, [original, setOriginal] = (0, import_react57.useState)(null), [text, setText] = (0, import_react57.useState)(""), [locked, setLocked] = (0, import_react57.useState)(!1), [busy, setBusy] = (0, import_react57.useState)(external ? `editing in ${editorLabel()}\u2026` : null), closed = (0, import_react57.useRef)(!1), done = () => {
16590
16630
  closed.current || (closed.current = !0, close());
16591
16631
  }, openEditor = async (from) => {
16592
16632
  setBusy(`editing in ${editorLabel()}\u2026`);
16593
16633
  let edited = await editInstructionsExternally(actions4, who, from, suspendTerminal);
16594
16634
  return setBusy(null), edited ?? null;
16595
16635
  };
16596
- (0, import_react56.useEffect)(() => {
16636
+ (0, import_react57.useEffect)(() => {
16597
16637
  (async () => {
16598
16638
  let fresh = await actions4.run("Instructions", (c) => c.config(agentId));
16599
16639
  if (!fresh) {
@@ -16672,13 +16712,13 @@ function InstructionsOverlay({ overlay, close, width, height }) {
16672
16712
  }
16673
16713
 
16674
16714
  // src/main/tui/views/inspect/overlays.tsx
16675
- var import_react57 = __toESM(require_react(), 1);
16715
+ var import_react58 = __toESM(require_react(), 1);
16676
16716
  var import_jsx_runtime69 = __toESM(require_jsx_runtime(), 1);
16677
16717
  function ThemeOverlay({ overlay, close, width }) {
16678
- let theme2 = useTheme(), store = useStore(), requested = typeof overlay.props?.name == "string" ? overlay.props.name : "", currentIndex = Math.max(0, THEMES.findIndex((t) => t.name === theme2.name)), [index, setIndex] = (0, import_react57.useState)(currentIndex), apply = (choice) => {
16718
+ let theme2 = useTheme(), store = useStore(), requested = typeof overlay.props?.name == "string" ? overlay.props.name : "", currentIndex = Math.max(0, THEMES.findIndex((t) => t.name === theme2.name)), [index, setIndex] = (0, import_react58.useState)(currentIndex), apply = (choice) => {
16679
16719
  applyTheme(theme2, choice), close(), store.actions.toast(`Theme: ${choice.label}${choice.colors ? "" : " (no color)"}`, "success", 2500);
16680
16720
  };
16681
- if ((0, import_react57.useEffect)(() => {
16721
+ if ((0, import_react58.useEffect)(() => {
16682
16722
  if (!requested) return;
16683
16723
  let choice = requested === "next" ? findTheme(nextThemeName(theme2.name)) : findTheme(requested);
16684
16724
  choice ? apply(choice) : (close(), store.actions.toast(`No theme "${requested}". Themes: ${THEMES.map((t) => t.name).join(", ")}`, "warn"));
@@ -16903,7 +16943,7 @@ var inspect2 = {
16903
16943
  }, inspect_default = inspect2;
16904
16944
 
16905
16945
  // src/main/tui/views/runtime/index.tsx
16906
- var import_react59 = __toESM(require_react(), 1);
16946
+ var import_react60 = __toESM(require_react(), 1);
16907
16947
 
16908
16948
  // src/main/tui/views/runtime/commands.ts
16909
16949
  var open = (ctx, tab) => openRuntime(ctx.actions, ctx.state(), { tab }), runtime = {
@@ -16959,11 +16999,11 @@ var events = {
16959
16999
  })), runtimeCommands = { commands: commands2, actions: actions3 };
16960
17000
 
16961
17001
  // src/main/tui/views/runtime/FoldersTab.tsx
16962
- var import_react58 = __toESM(require_react(), 1);
17002
+ var import_react59 = __toESM(require_react(), 1);
16963
17003
  var import_jsx_runtime71 = __toESM(require_jsx_runtime(), 1), CURSOR_KEY = "runtime.folders.cursor";
16964
17004
  function FoldersTab({ width, height, focused }) {
16965
17005
  let theme2 = useTheme(), store = useStore(), rev = useTuiSelector((s) => readFolders(s).rev), { data, error, loading, loadedAt, reload } = useDaemonData(`folders:${rev}`, () => loadFolders(store)), [cursor, setCursor] = useViewState(CURSOR_KEY, 0), rows = data ?? [], at = Math.min(cursor, Math.max(0, rows.length - 1));
16966
- (0, import_react58.useEffect)(() => {
17006
+ (0, import_react59.useEffect)(() => {
16967
17007
  at !== cursor && setCursor(at);
16968
17008
  }, [at, cursor, setCursor]), useKeys((input, key) => {
16969
17009
  if (key.ctrl || key.meta) return !1;
@@ -17021,7 +17061,7 @@ var import_jsx_runtime72 = __toESM(require_jsx_runtime(), 1);
17021
17061
  function ReportTab({ kind, width, height, focused, onKey, hint }) {
17022
17062
  let theme2 = useTheme(), store = useStore(), json2 = useStoreJson(), report2 = REPORTS[kind], { data, error, loading, loadedAt, reload } = useDaemonData(kind, (client) => report2.load(client, store.getState()));
17023
17063
  useKeys((input, key) => key.ctrl || key.meta ? !1 : input === "r" ? (reload(), !0) : onKey?.(input, key, reload) ?? !1, { layer: "main", active: focused });
17024
- let lines = (0, import_react59.useMemo)(() => error ? [plain(`Could not load: ${error}`, "error"), plain("r retries.", "muted")] : data ? json2 ? jsonLines(data.data) : data.lines : [], [data, error, json2]);
17064
+ let lines = (0, import_react60.useMemo)(() => error ? [plain(`Could not load: ${error}`, "error"), plain("r retries.", "muted")] : data ? json2 ? jsonLines(data.data) : data.lines : [], [data, error, json2]);
17025
17065
  return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(Box_default, { flexDirection: "column", width, height, children: [
17026
17066
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(LinesView, { lines, width, height: Math.max(1, height - 1), active: focused, emptyText: loading ? `Asking the daemon at ${store.getState().daemonUrl}\u2026` : "Nothing to show." }),
17027
17067
  /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(Text, { color: theme2.color.dim, wrap: "truncate-end", children: [
@@ -17049,7 +17089,7 @@ function IdentityTab2({ width, height, focused }) {
17049
17089
  let choice = choices.find((c) => c.key === input);
17050
17090
  return choice ? (openIdentity(store, { mode: choice.mode }), !0) : !1;
17051
17091
  }, { layer: "main", active: focused });
17052
- let lines = (0, import_react59.useMemo)(() => {
17092
+ let lines = (0, import_react60.useMemo)(() => {
17053
17093
  if (!identity) return [plain("This daemon does not report an owner identity (update the daemon).", "muted")];
17054
17094
  let badge = identityBadge(identity), { title, next } = onboardingLines(identity), out = [heading(title)];
17055
17095
  next && out.push(plain(` ${next}`, "warn")), badge && out.push([{ text: " " }, { text: badge.text, tone: badge.tone === "warn" ? "warn" : "muted" }]), out.push(blank(), ...treeLines(redactSecrets(identity), 2)), out.push(blank(), heading("Actions")), out.push(plain(" Enter identity dialog (status, backup, lock / unlock)", "accent"));
@@ -17165,9 +17205,9 @@ var VIEWS = [chat_default, files_default, loops_default, inspect_default, fleet_
17165
17205
  // src/main/tui/app/App.tsx
17166
17206
  var import_jsx_runtime73 = __toESM(require_jsx_runtime(), 1);
17167
17207
  function App({ store, theme: theme2, views = VIEWS, builtins = [BUILTIN_COMMANDS], onExit, reserveRows = 0, reserveColumns = 0 }) {
17168
- let app = use_app_default(), router = (0, import_react60.useMemo)(() => createKeyRouter(), []), registry = (0, import_react60.useMemo)(() => collectCommands(views, builtins), [views, builtins]), exit = (0, import_react60.useCallback)(() => {
17208
+ let app = use_app_default(), router = (0, import_react61.useMemo)(() => createKeyRouter(), []), registry = (0, import_react61.useMemo)(() => collectCommands(views, builtins), [views, builtins]), exit = (0, import_react61.useCallback)(() => {
17169
17209
  onExit?.(), app.exit();
17170
- }, [app, onExit]), shell = (0, import_react60.useMemo)(() => ({ views, registry, exit, reserveRows, reserveColumns }), [views, registry, exit, reserveRows, reserveColumns]);
17210
+ }, [app, onExit]), shell = (0, import_react61.useMemo)(() => ({ views, registry, exit, reserveRows, reserveColumns }), [views, registry, exit, reserveRows, reserveColumns]);
17171
17211
  return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(ThemeContext.Provider, { value: theme2, children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(StoreProvider, { store, children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(KeyRouterProvider, { router, children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(ShellContext.Provider, { value: shell, children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Shell, {}) }) }) }) });
17172
17212
  }
17173
17213
  export {