wherdr 1.3.2 → 1.3.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 (188) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{AgentView.C4YOwvZG.css → AgentView.DzFWBd2A.css} +1 -1
  3. package/.output/public/_nuxt/{Cd8j9O5w.js → BEJHMUrj.js} +1 -1
  4. package/.output/public/_nuxt/BOtcEDnA.js +1 -0
  5. package/.output/public/_nuxt/BUaYhQ2r.js +6 -0
  6. package/.output/public/_nuxt/{yzABg5xl.js → Bpoxvzh6.js} +1 -1
  7. package/.output/public/_nuxt/C25ROUa9.js +3 -0
  8. package/.output/public/_nuxt/CDWjMk9C.js +2 -0
  9. package/.output/public/_nuxt/CJKsMzIp.js +1 -0
  10. package/.output/public/_nuxt/CJNhn9sA.js +36 -0
  11. package/.output/public/_nuxt/COCvtdHN.js +89 -0
  12. package/.output/public/_nuxt/{Ci8N4mWR.js → CXJnLmWv.js} +1 -1
  13. package/.output/public/_nuxt/Cl45J6_Q.js +1 -0
  14. package/.output/public/_nuxt/CndPDbMI.js +2 -0
  15. package/.output/public/_nuxt/Ctbx58Um.js +23 -0
  16. package/.output/public/_nuxt/{8ksjcuDu.js → DMLmW6JM.js} +49 -56
  17. package/.output/public/_nuxt/Dl1PHLOB.js +1 -0
  18. package/.output/public/_nuxt/Nhex3_iH.js +1 -0
  19. package/.output/public/_nuxt/OpWX45i7.js +89 -0
  20. package/.output/public/_nuxt/builds/latest.json +1 -1
  21. package/.output/public/_nuxt/builds/meta/4994f3a4-4126-4f57-a9e5-c7ebb25850bc.json +1 -0
  22. package/.output/public/_nuxt/dTj21DMs.js +1 -0
  23. package/.output/public/_nuxt/entry.BohTWE-n.css +2 -0
  24. package/.output/public/_nuxt/kwSoIiM7.js +1 -0
  25. package/.output/public/_nuxt/mkEwYka4.js +1 -0
  26. package/.output/public/_nuxt/pdf.min.t82Z80JU.mjs +28 -0
  27. package/.output/public/_nuxt/pdf.worker.min.wgc6bjNh.mjs +28 -0
  28. package/.output/public/_nuxt/w7Rm7unj.js +1 -0
  29. package/.output/public/sw.js +1 -1
  30. package/.output/server/chunks/_/branding.mjs +1 -1
  31. package/.output/server/chunks/_/filePaths.mjs +25 -0
  32. package/.output/server/chunks/_/files.mjs +217 -0
  33. package/.output/server/chunks/_/machineOrder.mjs +1 -1
  34. package/.output/server/chunks/_/onboarding.mjs +1 -1
  35. package/.output/server/chunks/_/package.mjs +5 -2
  36. package/.output/server/chunks/_/pluginPolicy.mjs +93 -0
  37. package/.output/server/chunks/_/plugins.mjs +9 -96
  38. package/.output/server/chunks/_/projectBoard.mjs +124 -36
  39. package/.output/server/chunks/_/projectDocs.mjs +106 -0
  40. package/.output/server/chunks/_/projectInbox.mjs +135 -0
  41. package/.output/server/chunks/_/projectThreads.mjs +46 -0
  42. package/.output/server/chunks/_/projectThreads2.mjs +61 -0
  43. package/.output/server/chunks/_/projectsActions.mjs +1 -1
  44. package/.output/server/chunks/_/projectsPlugin.mjs +24 -50
  45. package/.output/server/chunks/_/projectsPlugin2.mjs +57 -0
  46. package/.output/server/chunks/_/restart.mjs +2 -312
  47. package/.output/server/chunks/_/reveal.mjs +2 -24
  48. package/.output/server/chunks/_/selfupdate.mjs +3 -2
  49. package/.output/server/chunks/_/settingstabs.mjs +36 -0
  50. package/.output/server/chunks/_/updates.mjs +51 -10
  51. package/.output/server/chunks/_/worktrees.mjs +1 -1
  52. package/.output/server/chunks/_/ws.mjs +1 -1
  53. package/.output/server/chunks/nitro/nitro.mjs +1718 -417
  54. package/.output/server/chunks/raw/bump-homebrew.mjs +1 -1
  55. package/.output/server/chunks/raw/herdr-plugin.mjs +1 -1
  56. package/.output/server/chunks/raw/release-ready.mjs +5 -0
  57. package/.output/server/chunks/routes/api/_..._.mjs +1 -1
  58. package/.output/server/chunks/routes/api/agents.post.mjs +1 -1
  59. package/.output/server/chunks/routes/api/ask-tab.post.mjs +1 -1
  60. package/.output/server/chunks/routes/api/attach.post.mjs +1 -1
  61. package/.output/server/chunks/routes/api/auth/disable.post.mjs +1 -1
  62. package/.output/server/chunks/routes/api/auth/lock-all.post.mjs +1 -1
  63. package/.output/server/chunks/routes/api/auth/lock.post.mjs +1 -1
  64. package/.output/server/chunks/routes/api/auth/login/options.post.mjs +1 -1
  65. package/.output/server/chunks/routes/api/auth/login/verify.post.mjs +1 -1
  66. package/.output/server/chunks/routes/api/auth/max-session.post.mjs +1 -1
  67. package/.output/server/chunks/routes/api/auth/register/options.post.mjs +1 -1
  68. package/.output/server/chunks/routes/api/auth/register/verify.post.mjs +1 -1
  69. package/.output/server/chunks/routes/api/auth/status.get.mjs +1 -1
  70. package/.output/server/chunks/routes/api/board.get.mjs +148 -0
  71. package/.output/server/chunks/routes/api/changes.get.mjs +2 -2
  72. package/.output/server/chunks/routes/api/chat/image.get.mjs +2 -2
  73. package/.output/server/chunks/routes/api/chat.get.mjs +26 -6
  74. package/.output/server/chunks/routes/api/choose.post.mjs +40 -14
  75. package/.output/server/chunks/routes/api/claude-statusline.post.mjs +2 -2
  76. package/.output/server/chunks/routes/api/close/status.get.mjs +2 -2
  77. package/.output/server/chunks/routes/api/close.post.mjs +1 -1
  78. package/.output/server/chunks/routes/api/codex-update.post.mjs +2 -2
  79. package/.output/server/chunks/routes/api/commands.get.mjs +4 -3
  80. package/.output/server/chunks/routes/api/config.get.mjs +3 -2
  81. package/.output/server/chunks/routes/api/dirs.get.mjs +2 -2
  82. package/.output/server/chunks/routes/api/dismiss-stopped.post.mjs +43 -0
  83. package/.output/server/chunks/routes/api/dismiss.post.mjs +2 -2
  84. package/.output/server/chunks/routes/api/effort.post.mjs +2 -2
  85. package/.output/server/chunks/routes/api/efforts.get.mjs +2 -2
  86. package/.output/server/chunks/routes/api/file.post.mjs +2 -2
  87. package/.output/server/chunks/routes/api/files/download.get.mjs +60 -0
  88. package/.output/server/chunks/routes/api/files/read.get.mjs +45 -0
  89. package/.output/server/chunks/routes/api/files.get.mjs +44 -0
  90. package/.output/server/chunks/routes/api/gitroot.get.mjs +2 -2
  91. package/.output/server/chunks/routes/api/health.get.mjs +1 -1
  92. package/.output/server/chunks/routes/api/index.get.mjs +2 -1
  93. package/.output/server/chunks/routes/api/input.post.mjs +32 -5
  94. package/.output/server/chunks/routes/api/interrupt.post.mjs +2 -2
  95. package/.output/server/chunks/routes/api/isgit.get.mjs +2 -2
  96. package/.output/server/chunks/routes/api/machine/awake.get.mjs +2 -2
  97. package/.output/server/chunks/routes/api/machine/awake.post.mjs +2 -2
  98. package/.output/server/chunks/routes/api/machine/order.get.mjs +1 -1
  99. package/.output/server/chunks/routes/api/machine/order.post.mjs +1 -1
  100. package/.output/server/chunks/routes/api/machine/rename.post.mjs +2 -2
  101. package/.output/server/chunks/routes/api/menu.post.mjs +5 -2
  102. package/.output/server/chunks/routes/api/model.post.mjs +2 -2
  103. package/.output/server/chunks/routes/api/models.get.mjs +2 -2
  104. package/.output/server/chunks/routes/api/nav.post.mjs +36 -22
  105. package/.output/server/chunks/routes/api/onboarding.get.mjs +1 -1
  106. package/.output/server/chunks/routes/api/onboarding.post.mjs +1 -1
  107. package/.output/server/chunks/routes/api/phone.get.mjs +2 -2
  108. package/.output/server/chunks/routes/api/phone.post.mjs +2 -2
  109. package/.output/server/chunks/routes/api/plugins/actions.get.mjs +4 -1
  110. package/.output/server/chunks/routes/api/plugins/invoke.post.mjs +4 -1
  111. package/.output/server/chunks/routes/api/plugins/profiles.get.mjs +4 -1
  112. package/.output/server/chunks/routes/api/plugins/projects.get.mjs +4 -3
  113. package/.output/server/chunks/routes/api/plugins/projects.post.mjs +4 -3
  114. package/.output/server/chunks/routes/api/plugins/thread-limits.get.mjs +2 -2
  115. package/.output/server/chunks/routes/api/plugins/thread-limits.post.mjs +2 -2
  116. package/.output/server/chunks/routes/api/project/inbox.get.mjs +44 -0
  117. package/.output/server/chunks/routes/api/project/inbox.post.mjs +44 -0
  118. package/.output/server/chunks/routes/api/project/memory.get.mjs +43 -0
  119. package/.output/server/chunks/routes/api/project/report.get.mjs +3 -2
  120. package/.output/server/chunks/routes/api/project/routines.get.mjs +44 -0
  121. package/.output/server/chunks/routes/api/project/settings.get.mjs +42 -0
  122. package/.output/server/chunks/routes/api/project/thread.get.mjs +45 -0
  123. package/.output/server/chunks/routes/api/project/thread.post.mjs +47 -0
  124. package/.output/server/chunks/routes/api/prompt.post.mjs +21 -3
  125. package/.output/server/chunks/routes/api/push/quiet.post.mjs +2 -2
  126. package/.output/server/chunks/routes/api/push/subscribe.post.mjs +2 -2
  127. package/.output/server/chunks/routes/api/push/test.post.mjs +2 -2
  128. package/.output/server/chunks/routes/api/push/unsubscribe.post.mjs +2 -2
  129. package/.output/server/chunks/routes/api/quotas.get.mjs +2 -2
  130. package/.output/server/chunks/routes/api/rename.post.mjs +1 -1
  131. package/.output/server/chunks/routes/api/requeue.post.mjs +2 -2
  132. package/.output/server/chunks/routes/api/restart.get.mjs +1 -1
  133. package/.output/server/chunks/routes/api/restart.post.mjs +1 -1
  134. package/.output/server/chunks/routes/api/reveal.post.mjs +2 -1
  135. package/.output/server/chunks/routes/api/screen-key.post.mjs +14 -11
  136. package/.output/server/chunks/routes/api/screen.get.mjs +6 -37
  137. package/.output/server/chunks/routes/api/search.get.mjs +2 -2
  138. package/.output/server/chunks/routes/api/seen.post.mjs +2 -2
  139. package/.output/server/chunks/routes/api/sessions.get.mjs +2 -2
  140. package/.output/server/chunks/routes/api/sessions.post.mjs +2 -2
  141. package/.output/server/chunks/routes/api/settings-tab.post.mjs +89 -0
  142. package/.output/server/chunks/routes/api/space.post.mjs +14 -14
  143. package/.output/server/chunks/routes/api/state.get.mjs +2 -2
  144. package/.output/server/chunks/routes/api/unqueue.post.mjs +2 -2
  145. package/.output/server/chunks/routes/api/update/status.get.mjs +1 -1
  146. package/.output/server/chunks/routes/api/update.get.mjs +2 -2
  147. package/.output/server/chunks/routes/api/update.post.mjs +2 -2
  148. package/.output/server/chunks/routes/api/upload.post.mjs +2 -2
  149. package/.output/server/chunks/routes/api/worktrees/remove.post.mjs +1 -1
  150. package/.output/server/chunks/routes/api/worktrees.get.mjs +1 -1
  151. package/.output/server/chunks/routes/favicon.ico.get.mjs +1 -1
  152. package/.output/server/chunks/routes/icons/_name_.get.mjs +2 -2
  153. package/.output/server/chunks/routes/renderer.mjs +3 -3
  154. package/.output/server/chunks/routes/uploads/_...name_.get.mjs +2 -2
  155. package/.output/server/chunks/routes/ws/_..._.mjs +2 -2
  156. package/.output/server/chunks/routes/ws/events.mjs +2 -2
  157. package/.output/server/chunks/routes/ws/term.mjs +2 -2
  158. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  159. package/.output/server/index.mjs +2 -2
  160. package/.output/server/package.json +1 -1
  161. package/README.md +368 -40
  162. package/bin/install-docker-skill.sh +20 -0
  163. package/bin/lib/commands.mjs +5 -1
  164. package/bin/lib/core.mjs +1 -0
  165. package/bin/lib/install-skill.sh +100 -0
  166. package/bin/lib/skill.mjs +16 -0
  167. package/bin/lib/updater.mjs +65 -12
  168. package/bin/lib/verify-release.mjs +20 -0
  169. package/package.json +5 -2
  170. package/skills/wherdr/SKILL.md +186 -0
  171. package/.output/public/_nuxt/B7QP1TFs.js +0 -23
  172. package/.output/public/_nuxt/BDNMzG2s.js +0 -1
  173. package/.output/public/_nuxt/BOpBIziZ.js +0 -6
  174. package/.output/public/_nuxt/BWXdFfeg.js +0 -17
  175. package/.output/public/_nuxt/COFCNFpG.js +0 -83
  176. package/.output/public/_nuxt/CWwyK2XK.js +0 -2
  177. package/.output/public/_nuxt/CXG-cOdh.js +0 -1
  178. package/.output/public/_nuxt/CkZ8t6uB.js +0 -1
  179. package/.output/public/_nuxt/D4Yz4rat.js +0 -65
  180. package/.output/public/_nuxt/D7sxNXx1.js +0 -1
  181. package/.output/public/_nuxt/DViwOclv.js +0 -1
  182. package/.output/public/_nuxt/DoD7Qb5P.js +0 -30
  183. package/.output/public/_nuxt/DyBZDSCV.js +0 -2
  184. package/.output/public/_nuxt/SiL1FJ5s.js +0 -3
  185. package/.output/public/_nuxt/bLP7Jj-b.js +0 -1
  186. package/.output/public/_nuxt/builds/meta/7afbf062-5369-4002-b20d-7a582ff6e0f1.json +0 -1
  187. package/.output/public/_nuxt/entry.Crt1r4l3.css +0 -2
  188. package/.output/server/chunks/routes/ws/mirror.mjs +0 -161
@@ -19,8 +19,8 @@ import webpush from 'web-push';
19
19
  import os from 'node:os';
20
20
  import { spawn, execFile } from 'node:child_process';
21
21
  import net from 'node:net';
22
- import readline from 'node:readline';
23
22
  import fs$1 from 'node:fs/promises';
23
+ import readline from 'node:readline';
24
24
  import dns from 'node:dns';
25
25
  import { promisify } from 'node:util';
26
26
  import QRCode from 'qrcode-terminal/vendor/QRCode/index.js';
@@ -8646,83 +8646,87 @@ async function dispose(driver) {
8646
8646
  const _assets = {
8647
8647
  ["scripts:build-nerd-font.py"]: {
8648
8648
  import: () => import('../raw/build-nerd-font.mjs').then(r => r.default || r),
8649
- meta: {"type":"text/plain; charset=utf-8","etag":"\"13aa-ys9YUI0kyQcBWrUDXjdBVLF8Z3E\"","mtime":"2026-10-10T00:23:41.677Z"}
8649
+ meta: {"type":"text/plain; charset=utf-8","etag":"\"13aa-ys9YUI0kyQcBWrUDXjdBVLF8Z3E\"","mtime":"2026-10-17T18:43:08.766Z"}
8650
8650
  },
8651
8651
  ["scripts:build-terminal-font.py"]: {
8652
8652
  import: () => import('../raw/build-terminal-font.mjs').then(r => r.default || r),
8653
- meta: {"type":"text/plain; charset=utf-8","etag":"\"cf5-BDqHg2xDFu+6dg84HBWtyBtrEoU\"","mtime":"2026-10-10T00:23:41.677Z"}
8653
+ meta: {"type":"text/plain; charset=utf-8","etag":"\"cf5-BDqHg2xDFu+6dg84HBWtyBtrEoU\"","mtime":"2026-10-17T18:43:08.767Z"}
8654
8654
  },
8655
8655
  ["scripts:bump-homebrew.sh"]: {
8656
8656
  import: () => import('../raw/bump-homebrew.mjs').then(r => r.default || r),
8657
- meta: {"type":"application/x-sh","etag":"\"61b-suAgb/6azMZO/UmEjog8x0wZsQA\"","mtime":"2026-10-10T00:23:41.677Z"}
8657
+ meta: {"type":"application/x-sh","etag":"\"8b5-n/EiMEIUoHPuQl2XTJU0tSNn7FY\"","mtime":"2026-10-17T18:43:08.767Z"}
8658
8658
  },
8659
8659
  ["scripts:check-leaks.mjs"]: {
8660
8660
  import: () => import('../raw/check-leaks.mjs').then(r => r.default || r),
8661
- meta: {"type":"text/javascript; charset=utf-8","etag":"\"35b3-41HZueHfw7xuicx4q83qwdTEpbc\"","mtime":"2026-10-10T00:23:41.677Z"}
8661
+ meta: {"type":"text/javascript; charset=utf-8","etag":"\"35b3-41HZueHfw7xuicx4q83qwdTEpbc\"","mtime":"2026-10-17T18:43:08.767Z"}
8662
8662
  },
8663
8663
  ["scripts:dev.wherdr.open.plist"]: {
8664
8664
  import: () => import('../raw/dev.wherdr.open.mjs').then(r => r.default || r),
8665
- meta: {"type":"text/plain; charset=utf-8","etag":"\"1de-12VO2xq63mciP26rEzRh3cGfEkI\"","mtime":"2026-10-10T00:23:41.677Z"}
8665
+ meta: {"type":"text/plain; charset=utf-8","etag":"\"1de-12VO2xq63mciP26rEzRh3cGfEkI\"","mtime":"2026-10-17T18:43:08.767Z"}
8666
8666
  },
8667
8667
  ["scripts:docker-entrypoint.sh"]: {
8668
8668
  import: () => import('../raw/docker-entrypoint.mjs').then(r => r.default || r),
8669
- meta: {"type":"application/x-sh","etag":"\"3f3-8om3/mMriIIJYO+YcdXNJsv8tkI\"","mtime":"2026-10-10T00:23:41.677Z"}
8669
+ meta: {"type":"application/x-sh","etag":"\"3f3-8om3/mMriIIJYO+YcdXNJsv8tkI\"","mtime":"2026-10-17T18:43:08.767Z"}
8670
8670
  },
8671
8671
  ["scripts:herdr-plugin.sh"]: {
8672
8672
  import: () => import('../raw/herdr-plugin.mjs').then(r => r.default || r),
8673
- meta: {"type":"application/x-sh","etag":"\"994f-jk8Je2eDp1XdX/Sk4mufv2vrJOc\"","mtime":"2026-10-10T00:23:41.677Z"}
8673
+ meta: {"type":"application/x-sh","etag":"\"9b85-YfAcqPKGuMgKmGSVqEIuA91sAE4\"","mtime":"2026-10-17T18:43:08.767Z"}
8674
8674
  },
8675
8675
  ["scripts:install-claude-statusline.sh"]: {
8676
8676
  import: () => import('../raw/install-claude-statusline.mjs').then(r => r.default || r),
8677
- meta: {"type":"application/x-sh","etag":"\"db6-p7KGlvbZ+Qjt+JiT5yVtU4w3kfg\"","mtime":"2026-10-10T00:23:41.677Z"}
8677
+ meta: {"type":"application/x-sh","etag":"\"db6-p7KGlvbZ+Qjt+JiT5yVtU4w3kfg\"","mtime":"2026-10-17T18:43:08.767Z"}
8678
8678
  },
8679
8679
  ["scripts:install-host-open.sh"]: {
8680
8680
  import: () => import('../raw/install-host-open.mjs').then(r => r.default || r),
8681
- meta: {"type":"application/x-sh","etag":"\"103a-/zplHeQSS471/Vz3quwajHmzFQs\"","mtime":"2026-10-10T00:23:41.677Z"}
8681
+ meta: {"type":"application/x-sh","etag":"\"103a-/zplHeQSS471/Vz3quwajHmzFQs\"","mtime":"2026-10-17T18:43:08.767Z"}
8682
8682
  },
8683
8683
  ["scripts:pack-output.mjs"]: {
8684
8684
  import: () => import('../raw/pack-output.mjs').then(r => r.default || r),
8685
- meta: {"type":"text/javascript; charset=utf-8","etag":"\"54b-eU4eNNIxIecG1kwaLdtiTYODSSI\"","mtime":"2026-10-10T00:23:41.677Z"}
8685
+ meta: {"type":"text/javascript; charset=utf-8","etag":"\"54b-eU4eNNIxIecG1kwaLdtiTYODSSI\"","mtime":"2026-10-17T18:43:08.767Z"}
8686
+ },
8687
+ ["scripts:release-ready.mjs"]: {
8688
+ import: () => import('../raw/release-ready.mjs').then(r => r.default || r),
8689
+ meta: {"type":"text/javascript; charset=utf-8","etag":"\"a44-ceu/5BQO5TUWzE/HNW2C/LvdCqw\"","mtime":"2026-10-17T18:43:08.767Z"}
8686
8690
  },
8687
8691
  ["scripts:reveal.sh"]: {
8688
8692
  import: () => import('../raw/reveal.mjs').then(r => r.default || r),
8689
- meta: {"type":"application/x-sh","etag":"\"72e-h/LTEU7exXdiR3GKqhj71UOwAqQ\"","mtime":"2026-10-10T00:23:41.677Z"}
8693
+ meta: {"type":"application/x-sh","etag":"\"72e-h/LTEU7exXdiR3GKqhj71UOwAqQ\"","mtime":"2026-10-17T18:43:08.767Z"}
8690
8694
  },
8691
8695
  ["scripts:wherdr-open.sh"]: {
8692
8696
  import: () => import('../raw/wherdr-open.mjs').then(r => r.default || r),
8693
- meta: {"type":"application/x-sh","etag":"\"b5b-U5OyQk3hziU9KiUyB/1FT5TkOxk\"","mtime":"2026-10-10T00:23:41.677Z"}
8697
+ meta: {"type":"application/x-sh","etag":"\"b5b-U5OyQk3hziU9KiUyB/1FT5TkOxk\"","mtime":"2026-10-17T18:43:08.767Z"}
8694
8698
  },
8695
8699
  ["server:branding:favicon.ico"]: {
8696
8700
  import: () => import('../raw/favicon.mjs').then(r => r.default || r),
8697
- meta: {"type":"image/vnd.microsoft.icon","etag":"\"3aee-Oem7XTWv+9HEwv9u/3K5QcIjS3E\"","mtime":"2026-10-10T00:23:41.681Z"}
8701
+ meta: {"type":"image/vnd.microsoft.icon","etag":"\"3aee-Oem7XTWv+9HEwv9u/3K5QcIjS3E\"","mtime":"2026-10-17T18:43:08.771Z"}
8698
8702
  },
8699
8703
  ["server:branding:icons:apple-touch-icon.png"]: {
8700
8704
  import: () => import('../raw/apple-touch-icon.mjs').then(r => r.default || r),
8701
- meta: {"type":"image/png","etag":"\"1f8-AVRrBnAhalXrGkFPGdvl0fM7DH8\"","mtime":"2026-10-10T00:23:41.681Z"}
8705
+ meta: {"type":"image/png","etag":"\"1f8-AVRrBnAhalXrGkFPGdvl0fM7DH8\"","mtime":"2026-10-17T18:43:08.771Z"}
8702
8706
  },
8703
8707
  ["server:branding:icons:favicon-32.png"]: {
8704
8708
  import: () => import('../raw/favicon-32.mjs').then(r => r.default || r),
8705
- meta: {"type":"image/png","etag":"\"a3-hAEc+Ymq1aYS3kFLyZK/H18Pge8\"","mtime":"2026-10-10T00:23:41.681Z"}
8709
+ meta: {"type":"image/png","etag":"\"a3-hAEc+Ymq1aYS3kFLyZK/H18Pge8\"","mtime":"2026-10-17T18:43:08.771Z"}
8706
8710
  },
8707
8711
  ["server:branding:icons:icon-192.png"]: {
8708
8712
  import: () => import('../raw/icon-192.mjs').then(r => r.default || r),
8709
- meta: {"type":"image/png","etag":"\"222-kioUoPaSCUaRhKKWw0PRtFbAhxk\"","mtime":"2026-10-10T00:23:41.681Z"}
8713
+ meta: {"type":"image/png","etag":"\"222-kioUoPaSCUaRhKKWw0PRtFbAhxk\"","mtime":"2026-10-17T18:43:08.771Z"}
8710
8714
  },
8711
8715
  ["server:branding:icons:icon-512-maskable.png"]: {
8712
8716
  import: () => import('../raw/icon-512-maskable.mjs').then(r => r.default || r),
8713
- meta: {"type":"image/png","etag":"\"84b-mCXgbBkXk7sqOhmJ8hjp80SN3Qk\"","mtime":"2026-10-10T00:23:41.681Z"}
8717
+ meta: {"type":"image/png","etag":"\"84b-mCXgbBkXk7sqOhmJ8hjp80SN3Qk\"","mtime":"2026-10-17T18:43:08.771Z"}
8714
8718
  },
8715
8719
  ["server:branding:icons:icon-512.png"]: {
8716
8720
  import: () => import('../raw/icon-512.mjs').then(r => r.default || r),
8717
- meta: {"type":"image/png","etag":"\"8fc-ZwRMqAqQZeLLx4iNTZxs09C4Q1I\"","mtime":"2026-10-10T00:23:41.681Z"}
8721
+ meta: {"type":"image/png","etag":"\"8fc-ZwRMqAqQZeLLx4iNTZxs09C4Q1I\"","mtime":"2026-10-17T18:43:08.771Z"}
8718
8722
  },
8719
8723
  ["server:branding:icons:icon-maskable.svg"]: {
8720
8724
  import: () => import('../raw/icon-maskable.mjs').then(r => r.default || r),
8721
- meta: {"type":"image/svg+xml","etag":"\"4a1-7XtnuN5ZOwiwIjpgpj+/Rg9LssY\"","mtime":"2026-10-10T00:23:41.681Z"}
8725
+ meta: {"type":"image/svg+xml","etag":"\"4a1-7XtnuN5ZOwiwIjpgpj+/Rg9LssY\"","mtime":"2026-10-17T18:43:08.771Z"}
8722
8726
  },
8723
8727
  ["server:branding:icons:icon.svg"]: {
8724
8728
  import: () => import('../raw/icon.mjs').then(r => r.default || r),
8725
- meta: {"type":"image/svg+xml","etag":"\"49c-O1XxkWwKTf6VBoC0i4TEPdGPsCw\"","mtime":"2026-10-10T00:23:41.681Z"}
8729
+ meta: {"type":"image/svg+xml","etag":"\"49c-O1XxkWwKTf6VBoC0i4TEPdGPsCw\"","mtime":"2026-10-17T18:43:08.771Z"}
8726
8730
  }
8727
8731
  };
8728
8732
 
@@ -9625,7 +9629,7 @@ function _expandFromEnv(value) {
9625
9629
  const _inlineRuntimeConfig = {
9626
9630
  "app": {
9627
9631
  "baseURL": "/",
9628
- "buildId": "7afbf062-5369-4002-b20d-7a582ff6e0f1",
9632
+ "buildId": "4994f3a4-4126-4f57-a9e5-c7ebb25850bc",
9629
9633
  "buildAssetsDir": "/_nuxt/",
9630
9634
  "cdnURL": ""
9631
9635
  },
@@ -10214,8 +10218,8 @@ function savedAppUrl() {
10214
10218
  if (!ENV_APP_URL && savedAppUrl()) env.APP_URL = savedAppUrl();
10215
10219
  const appUrl = () => env.APP_URL || "mailto:herdr-web@localhost";
10216
10220
  const HOST_LABEL = (env.HOST_LABEL || os.hostname()).trim().slice(0, 40);
10217
- function machineLabel(tailnetName, fallback = HOST_LABEL, containerName = IN_DOCKER && !(env.HOST_LABEL || "").trim()) {
10218
- const short = (tailnetName || "").split(".")[0].trim().slice(0, 40);
10221
+ function machineLabel(tailnetName2, fallback = HOST_LABEL, containerName = IN_DOCKER && !(env.HOST_LABEL || "").trim()) {
10222
+ const short = (tailnetName2 || "").split(".")[0].trim().slice(0, 40);
10219
10223
  return containerName && short ? short : fallback;
10220
10224
  }
10221
10225
  const PASSKEY_USER = (env.PASSKEY_USER || "wherdr").trim().slice(0, 64);
@@ -10320,9 +10324,9 @@ function kindLabel(kind) {
10320
10324
  return kind ? kind[0].toUpperCase() + kind.slice(1) : "Shell";
10321
10325
  }
10322
10326
 
10323
- var __defProp$7 = Object.defineProperty;
10324
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10325
- var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
10327
+ var __defProp$9 = Object.defineProperty;
10328
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10329
+ var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
10326
10330
  function shouldNotify(scope, p) {
10327
10331
  return scope === "all" || !isProjectThread(p);
10328
10332
  }
@@ -10343,8 +10347,8 @@ function findThreadPane(panes, project, thread) {
10343
10347
  }
10344
10348
  class NoticeDeduper {
10345
10349
  constructor(windowMs = 6e4) {
10346
- __publicField$7(this, "windowMs", windowMs);
10347
- __publicField$7(this, "seen", /* @__PURE__ */ new Map());
10350
+ __publicField$9(this, "windowMs", windowMs);
10351
+ __publicField$9(this, "seen", /* @__PURE__ */ new Map());
10348
10352
  }
10349
10353
  fresh(key, now = Date.now()) {
10350
10354
  for (const [k, at] of this.seen) if (now - at >= this.windowMs) this.seen.delete(k);
@@ -10483,17 +10487,86 @@ function parseSessionList(raw, baseKey, baseSession) {
10483
10487
  return out.sort((a, b) => a.name === baseSession ? -1 : b.name === baseSession ? 1 : a.name.localeCompare(b.name));
10484
10488
  }
10485
10489
 
10490
+ var __defProp$8 = Object.defineProperty;
10491
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10492
+ var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
10493
+ const SCREEN_MACHINE_MAX = 2;
10494
+ const SCREEN_TOTAL_MAX = 4;
10495
+ class ScreenGate {
10496
+ constructor() {
10497
+ __publicField$8(this, "active", 0);
10498
+ __publicField$8(this, "background", 0);
10499
+ __publicField$8(this, "backgroundMachines", /* @__PURE__ */ new Map());
10500
+ __publicField$8(this, "machines", /* @__PURE__ */ new Map());
10501
+ __publicField$8(this, "priority", () => false);
10502
+ __publicField$8(this, "reserved", () => false);
10503
+ __publicField$8(this, "queue", []);
10504
+ }
10505
+ run(machine, work, pane) {
10506
+ return new Promise((resolve, reject) => {
10507
+ this.queue.push({ machine, pane, start: () => {
10508
+ const background = !this.priority(machine, pane);
10509
+ if (background) {
10510
+ this.background++;
10511
+ this.backgroundMachines.set(machine, (this.backgroundMachines.get(machine) || 0) + 1);
10512
+ }
10513
+ this.active++;
10514
+ this.machines.set(machine, (this.machines.get(machine) || 0) + 1);
10515
+ Promise.resolve().then(work).then(resolve, reject).finally(() => {
10516
+ if (background) {
10517
+ this.background--;
10518
+ const n = this.backgroundMachines.get(machine) - 1;
10519
+ if (n) this.backgroundMachines.set(machine, n);
10520
+ else this.backgroundMachines.delete(machine);
10521
+ }
10522
+ this.active--;
10523
+ const remaining = this.machines.get(machine) - 1;
10524
+ if (remaining) this.machines.set(machine, remaining);
10525
+ else this.machines.delete(machine);
10526
+ this.drain();
10527
+ });
10528
+ } });
10529
+ this.drain();
10530
+ });
10531
+ }
10532
+ drain() {
10533
+ while (this.active < SCREEN_TOTAL_MAX) {
10534
+ const eligible = (q) => {
10535
+ const active = this.machines.get(q.machine) || 0;
10536
+ if (active >= SCREEN_MACHINE_MAX) return false;
10537
+ if (this.priority(q.machine, q.pane)) {
10538
+ return active - (this.backgroundMachines.get(q.machine) || 0) < SCREEN_MACHINE_MAX - 1 || !this.queue.some((p) => p.machine === q.machine && !this.priority(p.machine, p.pane));
10539
+ }
10540
+ return (this.backgroundMachines.get(q.machine) || 0) < SCREEN_MACHINE_MAX - Number(this.reserved(q.machine)) && this.background < SCREEN_TOTAL_MAX - Number(this.reserved());
10541
+ };
10542
+ const first = this.queue.findIndex((q) => eligible(q) && this.priority(q.machine, q.pane));
10543
+ const i = first < 0 ? this.queue.findIndex(eligible) : first;
10544
+ if (i < 0) return;
10545
+ this.queue.splice(i, 1)[0].start();
10546
+ }
10547
+ }
10548
+ }
10549
+ const workGate = new ScreenGate();
10550
+ const screenRpcGate = new ScreenGate();
10551
+ async function mapScreenPanes(panes, machine, work, viewed, publish) {
10552
+ const order = panes.map((pane, index) => ({ pane, index })).sort((a, b) => Number(viewed(b.pane)) - Number(viewed(a.pane)));
10553
+ await Promise.all(order.map(({ pane, index }) => workGate.run(machine, async () => {
10554
+ await work(pane, index);
10555
+ if (viewed(pane)) publish == null ? void 0 : publish(pane);
10556
+ })));
10557
+ }
10558
+
10486
10559
  function fmt(template, params) {
10487
10560
  return template.replace(/\{(\w+)\}/g, (all, k) => params[k] == null ? all : String(params[k]));
10488
10561
  }
10489
10562
 
10490
- var __defProp$6 = Object.defineProperty;
10491
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10492
- var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, key + "" , value);
10563
+ var __defProp$7 = Object.defineProperty;
10564
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10565
+ var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, key + "" , value);
10493
10566
  class HerdrError extends Error {
10494
10567
  constructor(code, message) {
10495
10568
  super(message);
10496
- __publicField$6(this, "code");
10569
+ __publicField$7(this, "code");
10497
10570
  this.code = code;
10498
10571
  }
10499
10572
  }
@@ -10514,7 +10587,8 @@ function herdr(method, params = {}, timeoutMs = 15e3) {
10514
10587
  function herdrOn(machine, method, params = {}, timeoutMs = 15e3) {
10515
10588
  const r = resolveSocket(machine);
10516
10589
  if (!r.sock) return Promise.reject(new HerdrError("unreachable", r.error || "Machine unreachable"));
10517
- return herdrSock(r.sock, method, params, timeoutMs);
10590
+ const read = () => herdrSock(r.sock, method, params, timeoutMs);
10591
+ return method === "pane.read" ? screenRpcGate.run(machine, read, params.pane_id) : read();
10518
10592
  }
10519
10593
  let reqSeq = 0;
10520
10594
  function herdrSock(path, method, params = {}, timeoutMs = 15e3) {
@@ -10552,24 +10626,24 @@ function herdrSock(path, method, params = {}, timeoutMs = 15e3) {
10552
10626
  sock.on("close", () => finish(new HerdrError("closed", "Herdr connection closed without a response")));
10553
10627
  });
10554
10628
  }
10555
- async function agentPrompt(target, text) {
10629
+ async function agentPrompt(target2, text) {
10556
10630
  try {
10557
- await herdr("agent.prompt", { target, text });
10631
+ await herdr("agent.prompt", { target: target2, text });
10558
10632
  } catch (e) {
10559
10633
  if (!(e instanceof HerdrError) || e.code !== "agent_not_ready") throw e;
10560
10634
  try {
10561
- await herdr("agent.get", { target });
10635
+ await herdr("agent.get", { target: target2 });
10562
10636
  } catch {
10563
10637
  throw e;
10564
10638
  }
10565
- await herdr("agent.prompt", { target, text });
10639
+ await herdr("agent.prompt", { target: target2, text });
10566
10640
  }
10567
10641
  }
10568
10642
  const sleep$1 = (ms) => new Promise((r) => setTimeout(r, ms));
10569
10643
 
10570
- var __defProp$5 = Object.defineProperty;
10571
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10572
- var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, key + "" , value);
10644
+ var __defProp$6 = Object.defineProperty;
10645
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10646
+ var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, key + "" , value);
10573
10647
  const fsp$4 = fs.promises;
10574
10648
  const toStat = (st) => ({ size: st.size, mtimeMs: st.mtimeMs, isFile: st.isFile(), isDir: st.isDirectory() });
10575
10649
  const localFs = {
@@ -10591,7 +10665,7 @@ const localFs = {
10591
10665
  class FsError extends Error {
10592
10666
  constructor(code, message) {
10593
10667
  super(message);
10594
- __publicField$5(this, "code");
10668
+ __publicField$6(this, "code");
10595
10669
  this.code = code;
10596
10670
  }
10597
10671
  }
@@ -10603,6 +10677,9 @@ for f; do
10603
10677
  elif [ -n "$bsd" ]; then stat -f '%z %m %HT' "$f" 2>/dev/null || echo x
10604
10678
  else stat -c '%s %Y %F' "$f" 2>/dev/null || echo x; fi
10605
10679
  done`;
10680
+ const MISSING_PATH_EXIT = 44;
10681
+ const REQUIRE_PATH = `[ -e "$1" ] || exit ${MISSING_PATH_EXIT}
10682
+ `;
10606
10683
  function parseStatLine(line) {
10607
10684
  const m = /^(\d+) (\d+) (.+)$/.exec(String(line || "").trim());
10608
10685
  if (!m) return null;
@@ -10617,7 +10694,7 @@ function createShellFs(exec, opts = {}) {
10617
10694
  const r = await exec(script, args, { timeoutMs, input });
10618
10695
  if (r.code !== 0) {
10619
10696
  const reason = (r.stderr || `code ${r.code}`).trim().split("\n").pop() || "failed";
10620
- const code = r.code === 255 || r.code === 124 ? "unreachable" : /no such file/i.test(r.stderr) ? "ENOENT" : "remote";
10697
+ const code = r.code === 255 || r.code === 124 ? "unreachable" : r.code === MISSING_PATH_EXIT || /no such file/i.test(r.stderr) ? "ENOENT" : "remote";
10621
10698
  throw new FsError(code, reason);
10622
10699
  }
10623
10700
  return r.stdout;
@@ -10653,24 +10730,33 @@ function createShellFs(exec, opts = {}) {
10653
10730
  },
10654
10731
  statMany,
10655
10732
  async readdir(p) {
10656
- const b = await run('cd "$1" && ls -1A', [p]);
10733
+ const b = await run(REQUIRE_PATH + 'cd "$1" && ls -1A', [p]);
10657
10734
  return b.toString("utf8").split("\n").filter(Boolean);
10658
10735
  },
10659
10736
  async readFile(p) {
10660
- return (await run('cat "$1"', [p])).toString("utf8");
10737
+ return (await run(REQUIRE_PATH + 'cat "$1"', [p])).toString("utf8");
10661
10738
  },
10662
10739
  async read(p, start, len, timeoutMs) {
10663
10740
  if (len <= 0) return Buffer.alloc(0);
10664
- return run('tail -c +"$2" "$1" | head -c "$3"', [p, String(start + 1), String(len)], timeoutMs || 6e4);
10741
+ return run(REQUIRE_PATH + 'exec 3< "$1" || exit $?\ntail -c +"$2" <&3 | head -c "$3"', [p, String(start + 1), String(len)], timeoutMs || 6e4);
10665
10742
  }
10666
10743
  };
10667
10744
  }
10668
- const LIST_DIRS_SCRIPT = `cd "$1" || exit 1
10745
+ const LIST_DIRS_SCRIPT = `why() { case "$1" in *"not permitted"*) [ "$(uname -s)" = Darwin ] && exit 3 ;; esac; exit 2; }
10746
+ e=$(cd "$1" 2>&1) || { [ -d "$1" ] || exit 1; why "$e"; }
10747
+ cd "$1" || exit 1
10748
+ e=$(LC_ALL=C ls -A 2>&1 >/dev/null) || why "$e"
10669
10749
  for d in * ; do
10670
10750
  [ -d "$d" ] || continue
10671
10751
  [ "$d" = node_modules ] && continue
10672
10752
  if [ -e "$d/.git" ]; then echo "g $d"; else echo "d $d"; fi
10673
10753
  done`;
10754
+ const dirDeniedFromCode = (code) => code === 3 ? "macos" : code === 2 ? "permission" : null;
10755
+ function dirDeniedFromError(err, platform = process.platform) {
10756
+ const code = err == null ? void 0 : err.code;
10757
+ if (code === "EPERM" && platform === "darwin") return "macos";
10758
+ return code === "EACCES" || code === "EPERM" ? "permission" : null;
10759
+ }
10674
10760
  function parseDirList(out) {
10675
10761
  return String(out || "").split("\n").filter((l) => /^[gd] ./.test(l)).map((l) => ({ name: l.slice(2), git: l[0] === "g" }));
10676
10762
  }
@@ -10690,9 +10776,9 @@ async function listDirsLocal(dir) {
10690
10776
  return out;
10691
10777
  }
10692
10778
 
10693
- var __defProp$4 = Object.defineProperty;
10694
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10695
- var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
10779
+ var __defProp$5 = Object.defineProperty;
10780
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10781
+ var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
10696
10782
  const SSH_MAX_SESSIONS = 10;
10697
10783
  const STREAM_MARGIN = 2;
10698
10784
  const EXEC_MAX = 6;
@@ -10701,13 +10787,13 @@ const REFUSED_RE = /session open refused|session request failed|administratively
10701
10787
  const isRefused = (stderr) => REFUSED_RE.test(stderr);
10702
10788
  class SessionGate {
10703
10789
  constructor(opts = {}) {
10704
- __publicField$4(this, "opts", opts);
10705
- __publicField$4(this, "execs", 0);
10706
- __publicField$4(this, "streams", 0);
10707
- __publicField$4(this, "peak", 0);
10708
- __publicField$4(this, "refusals", 0);
10709
- __publicField$4(this, "waiting", []);
10710
- __publicField$4(this, "inflight", /* @__PURE__ */ new Map());
10790
+ __publicField$5(this, "opts", opts);
10791
+ __publicField$5(this, "execs", 0);
10792
+ __publicField$5(this, "streams", 0);
10793
+ __publicField$5(this, "peak", 0);
10794
+ __publicField$5(this, "refusals", 0);
10795
+ __publicField$5(this, "waiting", []);
10796
+ __publicField$5(this, "inflight", /* @__PURE__ */ new Map());
10711
10797
  }
10712
10798
  // Short commands allowed at once with the streams currently open.
10713
10799
  capacity() {
@@ -10717,7 +10803,7 @@ class SessionGate {
10717
10803
  stats() {
10718
10804
  return { execs: this.execs, streams: this.streams, queued: this.waiting.length, peak: this.peak, refusals: this.refusals };
10719
10805
  }
10720
- // A long-lived session (terminal, mirror) opens; call the result when it closes.
10806
+ // A long-lived session (terminal) opens; call the result when it closes.
10721
10807
  openStream() {
10722
10808
  this.streams++;
10723
10809
  this.track();
@@ -11268,7 +11354,7 @@ const CLAUDE_CHAT = "Chat about this";
11268
11354
  const CHECKBOX = /^\[([ ✔✓x×])\]\s+/;
11269
11355
  const SUBMIT = "Submit";
11270
11356
  const CLAUDE_FREE_BOX = "Type something";
11271
- function parseChoices(text, { strict = false } = {}) {
11357
+ function parseChoices(text, { strict = false, full = false } = {}) {
11272
11358
  if (!text) return null;
11273
11359
  let lines = text.replace(/\s+$/, "").split("\n").slice(-60);
11274
11360
  let c = -1;
@@ -11361,11 +11447,11 @@ function parseChoices(text, { strict = false } = {}) {
11361
11447
  }
11362
11448
  question = question || asks || nearest;
11363
11449
  const out = {
11364
- question: question ? (/\?\s*$/.test(question.t) ? joinQuestion(lines, question.i) : question.t).replace(/^[☐☒✔●◆▸•│\s]+/, "").slice(0, 300) : null,
11450
+ question: question ? (/\?\s*$/.test(question.t) ? joinQuestion(lines, question.i) : question.t).replace(/^[☐☒✔●◆▸•│\s]+/, "").slice(0, full ? void 0 : 300) : null,
11365
11451
  cursor,
11366
11452
  options: options.map((o) => ({
11367
- label: o.label.slice(0, 200),
11368
- hint: o.hint ? o.hint.slice(0, 300) : null,
11453
+ label: o.label.slice(0, full ? void 0 : 200),
11454
+ hint: o.hint ? o.hint.slice(0, full ? void 0 : 300) : null,
11369
11455
  ...o.n !== null ? { n: o.n } : {}
11370
11456
  }))
11371
11457
  };
@@ -11384,7 +11470,7 @@ function parseChoices(text, { strict = false } = {}) {
11384
11470
  const review = lastMatch(lines.slice(0, top), /^\s*Review your answers\s*$/);
11385
11471
  if (review >= 0 && out.options[0] && /^Submit answers$/.test(out.options[0].label)) {
11386
11472
  const answers = lines.slice(review + 1, top).map((l) => l.match(/^\s*→\s+(.+?)\s*$/)).filter(Boolean).map((m) => m[1]);
11387
- if (answers.length) out.options[0] = { ...out.options[0], hint: answers.join(" \xB7 ").slice(0, 300) };
11473
+ if (answers.length) out.options[0] = { ...out.options[0], hint: answers.join(" \xB7 ").slice(0, full ? void 0 : 300) };
11388
11474
  }
11389
11475
  if (question && isPermissionQuestion(out.question)) {
11390
11476
  const detail = screenDetail(lines, question.i, top);
@@ -11470,12 +11556,12 @@ function readOmpField(lines) {
11470
11556
  function parseOmpField(text) {
11471
11557
  return text ? readOmpField(text.replace(/\s+$/, "").split("\n")) : null;
11472
11558
  }
11473
- function parseOmpAsk(text) {
11559
+ function parseOmpAsk(text, full = false) {
11474
11560
  if (!text) return null;
11475
11561
  const lines = text.replace(/\s+$/, "").split("\n");
11476
11562
  const field = readOmpField(lines);
11477
11563
  if (field) {
11478
- const hint = field.value.replace(/\s+/g, " ").trim().slice(0, 200) || null;
11564
+ const hint = field.value.replace(/\s+/g, " ").trim().slice(0, full ? void 0 : 200) || null;
11479
11565
  return { question: field.question, cursor: 0, options: [{ label: OMP_OTHER, hint, free: true }], typing: true };
11480
11566
  }
11481
11567
  const top = lastMatch(lines, OMP_ASK);
@@ -11494,7 +11580,7 @@ function parseOmpAsk(text) {
11494
11580
  const header = sections[0].filter((l) => l.trim());
11495
11581
  const bar = header.slice(0, 3).findIndex((l) => /(?:^| {2,})Submit$/.test(l.trim()));
11496
11582
  const tabs = bar >= 0 ? header.splice(0, bar + 1).join(" ").trim().split(/ {2,}/) : null;
11497
- const question = header.map((l) => l.trim()).join(" ").slice(0, 300) || null;
11583
+ const question = header.map((l) => l.trim()).join(" ").slice(0, full ? void 0 : 300) || null;
11498
11584
  const list = sections[1];
11499
11585
  const options = [];
11500
11586
  let cursor = -1;
@@ -11504,15 +11590,15 @@ function parseOmpAsk(text) {
11504
11590
  if (m) {
11505
11591
  if (m[1]) cursor = options.length;
11506
11592
  multi || (multi = OMP_CHECK.includes(m[2]));
11507
- options.push({ label: m[3].slice(0, 200), hint: null, ...OMP_CHECKED.has(m[2]) ? { checked: true } : {}, ...m[3] === OMP_OTHER ? { free: true } : {} });
11593
+ options.push({ label: m[3].slice(0, full ? void 0 : 200), hint: null, ...OMP_CHECKED.has(m[2]) ? { checked: true } : {}, ...m[3] === OMP_OTHER ? { free: true } : {} });
11508
11594
  } else if (options.length && line.trim() && !options[options.length - 1].hint) {
11509
- options[options.length - 1].hint = line.trim().replace(/^↳\s*/, "").slice(0, 200);
11595
+ options[options.length - 1].hint = line.trim().replace(/^↳\s*/, "").slice(0, full ? void 0 : 200);
11510
11596
  }
11511
11597
  }
11512
11598
  if (!options.length) {
11513
11599
  if (!list.some((l) => OMP_CURSOR.some((c) => l.trim() === `${c} Submit`))) return null;
11514
11600
  const answers = list.map((l) => l.trim()).filter((l) => /^\d+\.\s/.test(l)).map((l) => l.replace(/^\d+\.\s+/, ""));
11515
- return { question, cursor: 0, options: [{ label: "Submit", hint: answers.join(" \xB7 ").slice(0, 200) || null }], ...tabs ? { tabs, tab: tabs.length - 1 } : {} };
11601
+ return { question, cursor: 0, options: [{ label: "Submit", hint: answers.join(" \xB7 ").slice(0, full ? void 0 : 200) || null }], ...tabs ? { tabs, tab: tabs.length - 1 } : {} };
11516
11602
  }
11517
11603
  if (cursor < 0) return null;
11518
11604
  const shown = multi ? options.map((o) => ({ ...o, checked: Boolean(o.checked) })) : options;
@@ -11521,7 +11607,7 @@ function parseOmpAsk(text) {
11521
11607
  const OMP_SELECT_TOP = /^\s*[╭+][─-] (.+?) [─-]+[╮+]\s*$/;
11522
11608
  const OMP_SELECT_LEGEND = new RegExp(`^\\s*[\u2502|] ${ompAlt(OMP_UP_DOWN)} navigate\\b.*\\bselect\\b`);
11523
11609
  const OMP_SELECT_OPTION = new RegExp(`^ (?:(${ompAlt(OMP_CURSOR)})|\\s)\\s(\\S.*)$`);
11524
- function parseOmpSelect(text) {
11610
+ function parseOmpSelect(text, full = false) {
11525
11611
  var _a;
11526
11612
  if (!text) return null;
11527
11613
  const lines = text.replace(/\s+$/, "").split("\n");
@@ -11538,7 +11624,7 @@ function parseOmpSelect(text) {
11538
11624
  const m = s ? OMP_SELECT_OPTION.exec(s) : null;
11539
11625
  if (!m) break;
11540
11626
  if (m[1]) cursor = options.length;
11541
- options.unshift({ label: m[2].trim().slice(0, 200), hint: null });
11627
+ options.unshift({ label: m[2].trim().slice(0, full ? void 0 : 200), hint: null });
11542
11628
  }
11543
11629
  if (cursor < 0) return null;
11544
11630
  cursor = options.length - 1 - cursor;
@@ -11560,8 +11646,8 @@ function parseOmpSelect(text) {
11560
11646
  const detail = tool || !title && body.length ? { tool: tool || "tool", ...body.length ? { command: body.join("\n") } : {} } : void 0;
11561
11647
  return { question: title, cursor, options, ...detail ? { detail } : {} };
11562
11648
  }
11563
- function parseOmpPrompt(text) {
11564
- return parseOmpSelect(text) || parseOmpAsk(text);
11649
+ function parseOmpPrompt(text, full = false) {
11650
+ return parseOmpSelect(text, full) || parseOmpAsk(text, full);
11565
11651
  }
11566
11652
  function ompActiveTab(ansi, tabs) {
11567
11653
  const rows = String(ansi || "").split("\n").map(ansiCells);
@@ -11744,9 +11830,20 @@ function sameQuestion(a, b) {
11744
11830
  const y = questionKey(b);
11745
11831
  return x && y ? x.startsWith(y) || y.startsWith(x) : x === y;
11746
11832
  }
11833
+ const identity = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
11834
+ function promptIdentity(text, agent) {
11835
+ const c = agent === "omp" ? parseOmpPrompt(text, true) : agent ? parseChoices(text, { full: true }) : parseChoices(text, { full: true }) || parseOmpPrompt(text, true);
11836
+ return identity(c ? { question: c.question, options: c.options.map(({ label, hint, n, free }) => ({ label, hint, n, free })), detail: c.detail, multi: c.multi, tabs: c.tabs } : null);
11837
+ }
11838
+ function menuIdentity(menu, target2 = menu.cursor === null ? void 0 : menu.items[menu.cursor]) {
11839
+ return identity({ title: menu.title, target: target2 ? { label: target2.label, hint: target2.hint, header: target2.header } : null, actions: menu.actions });
11840
+ }
11841
+ function waitIdentity(screen) {
11842
+ return identity({ kind: screen.kind, title: screen.title, lines: screen.lines, actions: screen.actions });
11843
+ }
11747
11844
  function screenChoices(text, agent, asked = []) {
11748
- if (agent === "omp") return parseOmpPrompt(text);
11749
- const c = parseChoices(text) || parseChoices(text, { strict: true });
11845
+ const c = agent === "omp" ? parseOmpPrompt(text) : parseChoices(text) || parseChoices(text, { strict: true });
11846
+ if (c) c.identity = promptIdentity(text, agent);
11750
11847
  return c && agent === "claude" ? completeClaudeAsk(c, asked) : c;
11751
11848
  }
11752
11849
  function panelOpen(text, agent) {
@@ -12610,7 +12707,7 @@ const OMP_BUILTIN = [
12610
12707
  ["quit", "Quit the application"]
12611
12708
  ];
12612
12709
 
12613
- const TTL$2 = 5 * 60 * 1e3;
12710
+ const TTL$2 = 20 * 1e3;
12614
12711
  const cache$3 = /* @__PURE__ */ new Map();
12615
12712
  function frontmatter(text) {
12616
12713
  const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
@@ -12634,6 +12731,13 @@ async function ls$1(fs, d) {
12634
12731
  return [];
12635
12732
  }
12636
12733
  }
12734
+ async function lsRoot(fs, d) {
12735
+ try {
12736
+ return await fs.readdir(d);
12737
+ } catch (err) {
12738
+ return dirDeniedFromError(err) === "macos" ? "denied" : [];
12739
+ }
12740
+ }
12637
12741
  async function read(fs, f) {
12638
12742
  try {
12639
12743
  return await fs.readFile(f);
@@ -12644,14 +12748,26 @@ async function read(fs, f) {
12644
12748
  const HEAD = 16384;
12645
12749
  async function collectLocal(fs, roots) {
12646
12750
  const out = [];
12751
+ const denied = [];
12647
12752
  for (let i = 0; i < roots.length; i++) {
12648
12753
  const r = roots[i];
12754
+ if (r.kind === "exists") {
12755
+ if (await fs.stat(r.dir).then(() => true, () => false)) out.push({ root: i, rel: "", text: "" });
12756
+ continue;
12757
+ }
12649
12758
  if (r.kind === "file") {
12650
12759
  const text = await read(fs, r.dir);
12651
12760
  if (text !== null) out.push({ root: i, rel: "", text });
12652
- } else if (r.kind === "skills") {
12761
+ continue;
12762
+ }
12763
+ const top = await lsRoot(fs, r.dir);
12764
+ if (top === "denied") {
12765
+ denied.push(i);
12766
+ continue;
12767
+ }
12768
+ if (r.kind === "skills") {
12653
12769
  const dirs = [];
12654
- for (const a of await ls$1(fs, r.dir)) {
12770
+ for (const a of top) {
12655
12771
  dirs.push(a);
12656
12772
  for (const b of await ls$1(fs, path$1.join(r.dir, a))) {
12657
12773
  if (b === "SKILL.md") continue;
@@ -12669,7 +12785,7 @@ async function collectLocal(fs, roots) {
12669
12785
  } else {
12670
12786
  const walk = async (rel, depth) => {
12671
12787
  var _a;
12672
- for (const n of await ls$1(fs, path$1.join(r.dir, rel))) {
12788
+ for (const n of rel ? await ls$1(fs, path$1.join(r.dir, rel)) : top) {
12673
12789
  const f = rel ? path$1.join(rel, n) : n;
12674
12790
  if (n.endsWith(".md")) {
12675
12791
  const text = await read(fs, path$1.join(r.dir, f));
@@ -12680,15 +12796,20 @@ async function collectLocal(fs, roots) {
12680
12796
  await walk("", 0);
12681
12797
  }
12682
12798
  }
12683
- return out;
12799
+ return { files: out, denied };
12684
12800
  }
12685
12801
  const SLASH_SCRIPT = `i=0
12802
+ os=$(uname -s)
12686
12803
  while [ $# -ge 2 ]; do
12687
12804
  k=$1; d=$2; shift 2
12688
12805
  case $k in
12806
+ exists) if [ -e "$d" ]; then printf '\\036%s\\037\\037' "$i"; fi ;;
12689
12807
  file) if [ -f "$d" ]; then printf '\\036%s\\037\\037' "$i"; head -c ${HEAD} "$d"; fi ;;
12690
12808
  skills|commands*)
12691
12809
  if [ "$k" = skills ]; then lo=2; hi=4; name=SKILL.md; else lo=1; hi=$((\${k#commands} + 1)); name='*.md'; fi
12810
+ case $(LC_ALL=C ls -A "$d" 2>&1 >/dev/null) in
12811
+ *"not permitted"*) [ "$os" = Darwin ] && printf '\\036D\\037%s\\037' "$i" ;;
12812
+ esac
12692
12813
  if [ -d "$d" ]; then
12693
12814
  find -L "$d" -mindepth $lo -maxdepth $hi -name "$name" -type f 2>/dev/null | sort | while IFS= read -r f; do
12694
12815
  printf '\\036%s\\037%s\\037' "$i" "\${f#"$d"/}"; head -c ${HEAD} "$f"
@@ -12700,13 +12821,15 @@ done
12700
12821
  exit 0`;
12701
12822
  function parseSlashFiles(out) {
12702
12823
  const files = [];
12824
+ const denied = [];
12703
12825
  for (const rec of out.split("")) {
12704
12826
  const a = rec.indexOf("");
12705
12827
  const b = a < 0 ? -1 : rec.indexOf("", a + 1);
12706
12828
  if (b < 0) continue;
12707
- files.push({ root: Number(rec.slice(0, a)), rel: rec.slice(a + 1, b), text: rec.slice(b + 1) });
12829
+ if (rec.slice(0, a) === "D") denied.push(Number(rec.slice(a + 1, b)));
12830
+ else files.push({ root: Number(rec.slice(0, a)), rel: rec.slice(a + 1, b), text: rec.slice(b + 1) });
12708
12831
  }
12709
- return files;
12832
+ return { files, denied };
12710
12833
  }
12711
12834
  async function collectRemote(exec, roots) {
12712
12835
  const args = roots.flatMap((r) => {
@@ -12732,7 +12855,7 @@ function commandsOf(roots, files) {
12732
12855
  const sorted = [...files].sort((a, b) => a.root - b.root || (a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0));
12733
12856
  for (const f of sorted) {
12734
12857
  const r = roots[f.root];
12735
- if (!r || r.kind === "file") continue;
12858
+ if (!r || r.kind === "file" || r.kind === "exists") continue;
12736
12859
  const parts = f.rel.split("/");
12737
12860
  const fm = frontmatter(f.text);
12738
12861
  const hint = fm["argument-hint"] || void 0;
@@ -12789,21 +12912,45 @@ function mergeCommands(builtin, extra) {
12789
12912
  function builtinCommands(kind) {
12790
12913
  return mergeCommands(kind === "claude" ? CLAUDE_BUILTIN : kind === "codex" ? CODEX_BUILTIN : kind === "omp" ? OMP_BUILTIN : [], []);
12791
12914
  }
12915
+ function claudeProjectDirs(cwd, home) {
12916
+ if (!cwd) return [];
12917
+ const stop = path$1.resolve(home);
12918
+ const out = [];
12919
+ for (let d = path$1.resolve(cwd); d !== stop; d = path$1.dirname(d)) {
12920
+ out.push(d);
12921
+ if (path$1.dirname(d) === d) break;
12922
+ }
12923
+ return out;
12924
+ }
12925
+ async function claudeCommands(collect, home, cwd) {
12926
+ const dirs = claudeProjectDirs(cwd, home);
12927
+ const roots = dirs.flatMap((d) => [
12928
+ { dir: path$1.join(d, ".git"), kind: "exists" },
12929
+ { dir: path$1.join(d, ".claude/skills"), kind: "skills" },
12930
+ { dir: path$1.join(d, ".claude/commands"), kind: "commands" }
12931
+ ]);
12932
+ roots.push({ dir: path$1.join(home, ".claude/skills"), kind: "skills" }, { dir: path$1.join(home, ".claude/commands"), kind: "commands" });
12933
+ const { files, denied } = await collect(roots);
12934
+ const git = files.filter((f) => roots[f.root].kind === "exists").map((f) => f.root / 3);
12935
+ const last = git.length ? Math.min(...git) : Infinity;
12936
+ const kept = (root) => root >= dirs.length * 3 || Math.floor(root / 3) <= last;
12937
+ return { commands: commandsOf(roots, files.filter((f) => kept(f.root))), denied: denied.some(kept) };
12938
+ }
12792
12939
  async function slashCommands(opts) {
12793
12940
  const { fs, exec, home, kind, cwd } = opts;
12794
12941
  const id = `${opts.key}|${kind}|${cwd || ""}`;
12795
12942
  const hit = cache$3.get(id);
12796
- if (hit && Date.now() - hit.at < TTL$2) return hit.list;
12943
+ if (hit && Date.now() - hit.at < TTL$2) return hit.result;
12797
12944
  const collect = (roots2) => exec ? collectRemote(exec, roots2) : collectLocal(fs, roots2);
12798
- const project = cwd && cwd !== home ? cwd : null;
12799
12945
  let roots = [];
12800
12946
  let builtin = [];
12801
12947
  const extra = [];
12948
+ let denied = false;
12802
12949
  if (kind === "claude") {
12803
12950
  builtin = CLAUDE_BUILTIN;
12804
- for (const b of project ? [project, home] : [home]) {
12805
- roots.push({ dir: path$1.join(b, ".claude/skills"), kind: "skills" }, { dir: path$1.join(b, ".claude/commands"), kind: "commands" });
12806
- }
12951
+ const r = await claudeCommands(collect, home, cwd);
12952
+ extra.push(...r.commands);
12953
+ denied = r.denied;
12807
12954
  } else if (kind === "codex") {
12808
12955
  builtin = CODEX_BUILTIN;
12809
12956
  roots = [{ dir: path$1.join(home, ".codex/prompts"), kind: "commands", depth: 0, prefix: "prompts:" }];
@@ -12812,21 +12959,21 @@ async function slashCommands(opts) {
12812
12959
  const dirs = ompConfigDirs(home, cwd);
12813
12960
  const config = { dir: path$1.join(home, ".omp/agent/config.yml"), kind: "file" };
12814
12961
  roots = [...dirs.map((d) => ({ dir: path$1.join(d, "commands"), kind: "commands" })), config, ...dirs.map((d) => ({ dir: path$1.join(d, "skills"), kind: "skills", prefix: "skill:" }))];
12815
- const files = await collect(roots);
12962
+ const { files } = await collect(roots);
12816
12963
  const cfg = files.find((f) => roots[f.root] === config);
12817
12964
  const more = cfg ? ompSkillDirs(cfg.text, home).map((d) => ({ dir: d, kind: "skills", prefix: "skill:" })) : [];
12818
12965
  const all = [...roots, ...more];
12819
- const found = more.length ? [...files, ...(await collect(more)).map((f) => ({ ...f, root: f.root + roots.length }))] : files;
12966
+ const found = more.length ? [...files, ...(await collect(more)).files.map((f) => ({ ...f, root: f.root + roots.length }))] : files;
12820
12967
  const cmds = commandsOf(all, found);
12821
12968
  const firstSkill = cmds.findIndex((c) => c.source === "skill");
12822
12969
  cmds.splice(firstSkill < 0 ? cmds.length : firstSkill, 0, { name: "init", desc: "Generate AGENTS.md for current codebase", source: "command" });
12823
12970
  extra.push(...cmds);
12824
12971
  roots = [];
12825
12972
  }
12826
- if (roots.length) extra.push(...commandsOf(roots, await collect(roots)));
12827
- const list = mergeCommands(builtin, extra);
12828
- cache$3.set(id, { at: Date.now(), list });
12829
- return list;
12973
+ if (roots.length) extra.push(...commandsOf(roots, (await collect(roots)).files));
12974
+ const result = { commands: mergeCommands(builtin, extra), ...denied ? { denied: "macos" } : {} };
12975
+ cache$3.set(id, { at: Date.now(), result });
12976
+ return result;
12830
12977
  }
12831
12978
  function ompConfigDirs(home, cwd) {
12832
12979
  const bases = [...cwd && cwd !== home ? [cwd] : [], home];
@@ -12855,8 +13002,86 @@ const isLongPaste = (s) => {
12855
13002
  const BLOCK = /<pasted_content(?:\s[^>]*)?>\n?([\s\S]*?)\n?<\/pasted_content(?:\s[^>]*)?>/g;
12856
13003
  function pastedBlocks(raw) {
12857
13004
  if (!raw.includes("<pasted_content")) return [];
13005
+ if (!raw.replace(BLOCK, "").replace(/\[Image #\d+[^\]]*\]/g, "").trim()) return [];
12858
13006
  return [...raw.matchAll(BLOCK)].map((m) => m[1].trim()).filter(isLongPaste);
12859
13007
  }
13008
+ const QUEUED_CHARS = 4e3;
13009
+ const cutShort = (text) => text.endsWith("\u2026") || text.length === QUEUED_CHARS;
13010
+ function cut(text, block, open) {
13011
+ const body = open ? text.replace(/…$/, "") : null;
13012
+ let at = text.indexOf(block);
13013
+ let end = at + block.length;
13014
+ let part = block;
13015
+ if (at < 0) {
13016
+ if (body === null) return null;
13017
+ at = body.indexOf(block.slice(0, 200));
13018
+ if (at < 0 || !block.startsWith(body.slice(at))) return null;
13019
+ part = body.slice(at).trimEnd();
13020
+ if (!isLongPaste(part)) return null;
13021
+ end = text.length;
13022
+ }
13023
+ const short = body !== null && end >= body.trimEnd().length;
13024
+ if (short) end = text.length;
13025
+ return { rest: (text.slice(0, at).replace(/\s+$/, "") + "\n" + text.slice(end).replace(/^\s+/, "")).trim(), part, short };
13026
+ }
13027
+ function splitPasted(text, listed = [], known = [], whole = false) {
13028
+ let rest = text;
13029
+ const pastes = [];
13030
+ const longKnown = known.filter(isLongPaste).sort((a, b) => b.length - a.length);
13031
+ let open = cutShort(text);
13032
+ const take = (block) => {
13033
+ const r = cut(rest, block, open);
13034
+ if (r === null) return;
13035
+ rest = r.rest;
13036
+ if (r.short) open = false;
13037
+ const sent = whole && r.short ? longKnown.filter((k) => k.startsWith(r.part)) : [];
13038
+ pastes.push(sent.length === 1 ? sent[0] : r.part);
13039
+ };
13040
+ for (const b of listed) {
13041
+ if (longKnown.some((k) => k !== b && b.includes(k))) continue;
13042
+ take(b);
13043
+ }
13044
+ for (const k of longKnown) take(k);
13045
+ if (!pastes.length) return { text, pastes };
13046
+ pastes.sort((a, b) => text.indexOf(a.slice(0, 200)) - text.indexOf(b.slice(0, 200)));
13047
+ return { text: rest, pastes };
13048
+ }
13049
+
13050
+ function parseIntegrationStatus(text) {
13051
+ const out = {};
13052
+ for (const line of String(text || "").split("\n")) {
13053
+ const m = /^\s*([a-z][\w-]*):\s+(.+?)\s+\((?:\/|~|[A-Z]:\\)[^()]*\)\s*$/i.exec(line);
13054
+ if (!m) continue;
13055
+ const state = m[2].toLowerCase();
13056
+ out[m[1].toLowerCase()] = state.startsWith("not installed") ? "missing" : state.startsWith("current") ? "installed" : "outdated";
13057
+ }
13058
+ return out;
13059
+ }
13060
+ const integrationCommand = (agent) => `herdr integration install ${agent}`;
13061
+ const ACTIVE = /* @__PURE__ */ new Set(["working", "blocked", "done"]);
13062
+ const activeStatus = (status) => ACTIVE.has(String(status || ""));
13063
+ function missingIntegration(p, status, wasActive) {
13064
+ if (!p.agent || p.agentSession || !status) return false;
13065
+ if (status[p.agent] !== "missing") return false;
13066
+ return wasActive || !p.bornAt;
13067
+ }
13068
+ function createActivity() {
13069
+ const active = /* @__PURE__ */ new Map();
13070
+ return {
13071
+ observe(p) {
13072
+ if (!p.agent) {
13073
+ active.delete(p.id);
13074
+ return;
13075
+ }
13076
+ if (active.get(p.id) !== p.agent) active.delete(p.id);
13077
+ if (activeStatus(p.status)) active.set(p.id, p.agent);
13078
+ },
13079
+ was: (id, agent) => Boolean(agent) && active.get(id) === agent,
13080
+ prune(keep) {
13081
+ for (const id of active.keys()) if (!keep(id)) active.delete(id);
13082
+ }
13083
+ };
13084
+ }
12860
13085
 
12861
13086
  const WINDOW_BYTES = 2 * 1024 * 1024;
12862
13087
  const MAX_READ_BYTES = 24 * 1024 * 1024;
@@ -12876,8 +13101,8 @@ function humanText(t) {
12876
13101
  if (u !== s) return u;
12877
13102
  return isNoise(s) ? null : s;
12878
13103
  }
12879
- const pastedOf = (raw) => {
12880
- const b = pastedBlocks(raw).map((s) => clip(s));
13104
+ const pastedOf = (...parts) => {
13105
+ const b = parts.flatMap(pastedBlocks).map((s) => clip(s));
12881
13106
  return b.length ? { pasted: b } : {};
12882
13107
  };
12883
13108
  const normMsg = (t) => stripImageTags(t).replace(/\s+/g, " ").trim().toLowerCase();
@@ -13057,11 +13282,11 @@ function parseClaude(lines, home = "") {
13057
13282
  const ts = d.timestamp || null;
13058
13283
  if (d.type === "attachment" && d.attachment && d.attachment.type === "queued_command" && d.attachment.commandMode === "prompt" && (d.attachment.origin || {}).kind === "human") {
13059
13284
  const parts = Array.isArray(d.attachment.prompt) ? d.attachment.prompt : [{ type: "text", text: String(d.attachment.prompt || "") }];
13060
- const raw = parts.filter((p) => p.type === "text").map((p) => p.text).join("\n");
13061
- const text = stripImageTags(unwrapPasted(raw));
13285
+ const texts = parts.filter((p) => p.type === "text").map((p) => String(p.text || ""));
13286
+ const text = stripImageTags(unwrapPasted(texts.join("\n")));
13062
13287
  const images = parts.filter((p) => p.type === "image").length;
13063
13288
  if (text || images) {
13064
- items.push({ role: "user", text: clip(text), images, ref: images ? ref : void 0, ts: d.attachment.timestamp || ts, ...pastedOf(raw) });
13289
+ items.push({ role: "user", text: clip(text), images, ref: images ? ref : void 0, ts: d.attachment.timestamp || ts, ...pastedOf(...texts) });
13065
13290
  pendingCmd = null;
13066
13291
  said(text, d.attachment.timestamp || ts, images);
13067
13292
  }
@@ -13122,7 +13347,7 @@ function parseClaude(lines, home = "") {
13122
13347
  }
13123
13348
  if (!Array.isArray(content)) continue;
13124
13349
  let text = "";
13125
- let raw = "";
13350
+ const raw = [];
13126
13351
  let images = 0;
13127
13352
  let toolImages = content.filter((p) => p && p.type === "image").length;
13128
13353
  for (const part of content) {
@@ -13140,13 +13365,13 @@ function parseClaude(lines, home = "") {
13140
13365
  if (special(String(part.text || ""), ts)) continue;
13141
13366
  const t = humanText(part.text);
13142
13367
  if (t === null) continue;
13143
- raw += "\n" + String(part.text || "");
13368
+ raw.push(String(part.text || ""));
13144
13369
  if (/^\[Request interrupted/.test(t)) items.push({ role: "system", text: "Interrupted", ts });
13145
13370
  else text += (text ? "\n" : "") + unwrapPasted(t.replace(/\[Image #\d+\]\s*/g, ""));
13146
13371
  } else if (part.type === "image") images++;
13147
13372
  }
13148
13373
  if (text.trim() || images) {
13149
- items.push({ role: "user", text: clip(text.trim()), images, ref: images ? ref : void 0, ts, ...pastedOf(raw) });
13374
+ items.push({ role: "user", text: clip(text.trim()), images, ref: images ? ref : void 0, ts, ...pastedOf(...raw) });
13150
13375
  pendingCmd = null;
13151
13376
  said(text, ts, images);
13152
13377
  noteSaid(d);
@@ -13189,6 +13414,7 @@ function codexCommand(input) {
13189
13414
  return firstLine(s);
13190
13415
  }
13191
13416
  function parseCodex(lines) {
13417
+ var _a;
13192
13418
  const items = [];
13193
13419
  const calls = /* @__PURE__ */ new Map();
13194
13420
  for (let li = 0; li < lines.length; li++) {
@@ -13201,6 +13427,10 @@ function parseCodex(lines) {
13201
13427
  } catch {
13202
13428
  continue;
13203
13429
  }
13430
+ if (d.type === "event_msg" && ((_a = d.payload) == null ? void 0 : _a.type) === "turn_aborted") {
13431
+ if (d.payload.reason === "interrupted") items.push({ role: "system", text: "Interrupted", ts: d.timestamp || null });
13432
+ continue;
13433
+ }
13204
13434
  if (d.type !== "response_item" || !d.payload) continue;
13205
13435
  const p = d.payload;
13206
13436
  const ts = d.timestamp || null;
@@ -13570,9 +13800,14 @@ function createTranscripts({ home, herdr: herdr2, fs = localFs }) {
13570
13800
  return best && { file: best.file, session: best.id, guessed: true };
13571
13801
  }
13572
13802
  const codexPeers = /* @__PURE__ */ new Map();
13803
+ const activity = createActivity();
13573
13804
  function observe(panes) {
13805
+ var _a;
13574
13806
  codexPeers.clear();
13575
13807
  for (const p of panes) if (p.agent === "codex") codexPeers.set(p.id, p);
13808
+ const live = new Set(panes.map((p) => p.id));
13809
+ activity.prune((id) => live.has(id));
13810
+ for (const p of panes) activity.observe({ id: p.id, agent: p.agent, status: (_a = p.status) != null ? _a : null });
13576
13811
  }
13577
13812
  const bySession = /* @__PURE__ */ new Map();
13578
13813
  async function findSessionFile(kind, id) {
@@ -13681,7 +13916,7 @@ function createTranscripts({ home, herdr: herdr2, fs = localFs }) {
13681
13916
  return { start, items, queue: queue || [] };
13682
13917
  }
13683
13918
  async function tail(file, kind, size, from) {
13684
- const key = `${file}|${from}`;
13919
+ const key = `${file}|${kind}|${from}`;
13685
13920
  const c = parseCache.get(key);
13686
13921
  if (c && c.size === size) return c.r;
13687
13922
  let r;
@@ -13718,15 +13953,16 @@ function createTranscripts({ home, herdr: herdr2, fs = localFs }) {
13718
13953
  }
13719
13954
  const fileId = path$1.basename(loc.file);
13720
13955
  const base = { available: true, file: fileId, session: loc.session, guessed: Boolean(loc.guessed) };
13721
- if (pane.agent === "omp") await refreshOmpTemplates();
13956
+ const kind = transcriptKind(loc.file) || pane.agent;
13957
+ if (kind === "omp") await refreshOmpTemplates();
13722
13958
  if (opts.before !== null && opts.before !== void 0) {
13723
- const r2 = await readBackwards(loc.file, Math.min(opts.before, st.size), pane.agent);
13959
+ const r2 = await readBackwards(loc.file, Math.min(opts.before, st.size), kind);
13724
13960
  return { ...base, older: true, items: r2.items, start: r2.start };
13725
13961
  }
13726
13962
  const from = opts.from === void 0 ? null : opts.from;
13727
13963
  const token = `${fileId}:${st.size}:${from}`;
13728
13964
  if (opts.since && opts.since === token) return { ...base, unchanged: true, token };
13729
- const r = await tail(loc.file, pane.agent, st.size, from);
13965
+ const r = await tail(loc.file, kind, st.size, from);
13730
13966
  return { ...base, token, items: r.items, start: r.start, queue: r.queue || [] };
13731
13967
  }
13732
13968
  async function preview(pane) {
@@ -13894,7 +14130,7 @@ function createTranscripts({ home, herdr: herdr2, fs = localFs }) {
13894
14130
  askCache.delete(paneId);
13895
14131
  claudeAskCache.delete(paneId);
13896
14132
  }
13897
- return { chat, preview, image, forget, locate, model, observe, search, pendingTool, pendingAsk, pendingClaudeQuestions };
14133
+ return { chat, preview, image, forget, locate, model, observe, wasActive: activity.was, search, pendingTool, pendingAsk, pendingClaudeQuestions };
13898
14134
  }
13899
14135
 
13900
14136
  const ATTACH_LIMITS = {
@@ -13989,9 +14225,9 @@ function closeTrailingMention(text) {
13989
14225
  return /(^|\n)@\S+$/.test(text) ? `${text} ` : text;
13990
14226
  }
13991
14227
 
13992
- var __defProp$3 = Object.defineProperty;
13993
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13994
- var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
14228
+ var __defProp$4 = Object.defineProperty;
14229
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14230
+ var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
13995
14231
  const fsp$3 = fs.promises;
13996
14232
  const LOCAL_LABEL_FILE = path$1.join(DATA_DIR, "machine-label.txt");
13997
14233
  function renamedLabel() {
@@ -14094,43 +14330,43 @@ function runFile(bin, args, timeoutMs) {
14094
14330
  const lastLine = (s) => String(s || "").trim().split("\n").filter(Boolean).pop() || "";
14095
14331
  class RemoteMachine {
14096
14332
  constructor(p, onChange) {
14097
- __publicField$3(this, "key");
14098
- __publicField$3(this, "baseKey");
14099
- __publicField$3(this, "profileId");
14100
- __publicField$3(this, "label");
14101
- __publicField$3(this, "target");
14102
- __publicField$3(this, "profileSession");
14103
- __publicField$3(this, "local", false);
14104
- __publicField$3(this, "status", "connecting");
14105
- __publicField$3(this, "error", null);
14106
- __publicField$3(this, "home", "");
14107
- __publicField$3(this, "os", "");
14108
- __publicField$3(this, "bin", "");
14109
- __publicField$3(this, "remoteSock", "");
14110
- __publicField$3(this, "ctl");
14111
- __publicField$3(this, "fwd");
14112
- __publicField$3(this, "fwdClient");
14113
- __publicField$3(this, "clientFwd", false);
14114
- __publicField$3(this, "fs");
14115
- __publicField$3(this, "transcripts");
14116
- __publicField$3(this, "exec");
14117
- __publicField$3(this, "master", null);
14118
- __publicField$3(this, "masterErr", []);
14119
- __publicField$3(this, "fails", 0);
14120
- __publicField$3(this, "timer", null);
14121
- __publicField$3(this, "purgeTimer", null);
14122
- __publicField$3(this, "stopped", false);
14123
- __publicField$3(this, "connecting", false);
14124
- __publicField$3(this, "pollFails", 0);
14333
+ __publicField$4(this, "key");
14334
+ __publicField$4(this, "baseKey");
14335
+ __publicField$4(this, "profileId");
14336
+ __publicField$4(this, "label");
14337
+ __publicField$4(this, "target");
14338
+ __publicField$4(this, "profileSession");
14339
+ __publicField$4(this, "local", false);
14340
+ __publicField$4(this, "status", "connecting");
14341
+ __publicField$4(this, "error", null);
14342
+ __publicField$4(this, "home", "");
14343
+ __publicField$4(this, "os", "");
14344
+ __publicField$4(this, "bin", "");
14345
+ __publicField$4(this, "remoteSock", "");
14346
+ __publicField$4(this, "ctl");
14347
+ __publicField$4(this, "fwd");
14348
+ __publicField$4(this, "fwdClient");
14349
+ __publicField$4(this, "clientFwd", false);
14350
+ __publicField$4(this, "fs");
14351
+ __publicField$4(this, "transcripts");
14352
+ __publicField$4(this, "exec");
14353
+ __publicField$4(this, "master", null);
14354
+ __publicField$4(this, "masterErr", []);
14355
+ __publicField$4(this, "fails", 0);
14356
+ __publicField$4(this, "timer", null);
14357
+ __publicField$4(this, "purgeTimer", null);
14358
+ __publicField$4(this, "stopped", false);
14359
+ __publicField$4(this, "connecting", false);
14360
+ __publicField$4(this, "pollFails", 0);
14125
14361
  // Identity seen at connection (host name + remote socket): duplicates.
14126
- __publicField$3(this, "ident", "");
14127
- __publicField$3(this, "onChange");
14128
- __publicField$3(this, "onSkip", () => {
14362
+ __publicField$4(this, "ident", "");
14363
+ __publicField$4(this, "onChange");
14364
+ __publicField$4(this, "onSkip", () => {
14129
14365
  });
14130
- __publicField$3(this, "onOnline", () => {
14366
+ __publicField$4(this, "onOnline", () => {
14131
14367
  });
14132
14368
  // Session budget of the shared connection (sshd MaxSessions).
14133
- __publicField$3(this, "gate", new SessionGate({
14369
+ __publicField$4(this, "gate", new SessionGate({
14134
14370
  onRefused: (s, attempt) => log(`machine ${this.label}: SSH session refused (attempt ${attempt}; open: ${s.execs} commands + ${s.streams} streams, ${s.queued} queued, peak ${s.peak})`)
14135
14371
  }));
14136
14372
  this.key = p.key;
@@ -14209,7 +14445,7 @@ ${cmd}`;
14209
14445
  child.stdin.end(opts.input || void 0);
14210
14446
  });
14211
14447
  }
14212
- // Long-lived session (terminal, mirror): counted in the budget, never queued.
14448
+ // Long-lived session (terminal): counted in the budget, never queued.
14213
14449
  spawnHerdr(args) {
14214
14450
  const sess = this.session && this.session !== "default" ? ["--session", this.session] : [];
14215
14451
  const cmd = `exec ${[this.bin || "herdr", ...sess, ...args].map(shq).join(" ")}`;
@@ -14434,6 +14670,12 @@ const remoteMachines = () => [...remotes.values()];
14434
14670
  const getMachine = (key) => !key ? localMachine : remotes.get(key) || sessions.get(key);
14435
14671
  const machineOfPane = (id) => getMachine(splitId(String(id || "")).machine);
14436
14672
  const multiMachine = () => remotes.size > 0 || sessions.size > 0;
14673
+ async function runHerdrCli(m, args, timeoutMs = 1e4) {
14674
+ if (m.local) return runFile(HERDR_BIN, args, timeoutMs);
14675
+ const remote = m;
14676
+ if (remote.status !== "online" || !remote.bin) throw new HerdrError("unreachable", fmt("{machine} is unreachable", { machine: m.label }));
14677
+ return remote.exec('b="$1"; shift; "$b" "$@"', [remote.bin, ...args], { timeoutMs });
14678
+ }
14437
14679
  async function listSessions(baseKey) {
14438
14680
  const m = baseMachines().find((x) => x.key === baseKey);
14439
14681
  if (!m) throw new HerdrError("bad_machine", "unknown machine");
@@ -14698,16 +14940,6 @@ function splitPath(id) {
14698
14940
  }
14699
14941
  const PANE_DIRECTIONS = ["left", "right", "up", "down"];
14700
14942
 
14701
- function mirrorSize(o) {
14702
- var _a, _b;
14703
- const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, Math.round(v)));
14704
- const longest = Math.max(0, ...String(o.text || "").split("\n").map((l) => [...l.replace(/\s+$/, "")].length));
14705
- return {
14706
- cols: clamp(Math.max(longest, ((_a = o.rect) == null ? void 0 : _a.width) || 0, 20), 20, 300),
14707
- rows: clamp(o.rows || ((_b = o.rect) == null ? void 0 : _b.height) || 24, 5, 200)
14708
- };
14709
- }
14710
-
14711
14943
  const SLUG$1 = /^[a-z0-9][a-z0-9._-]*$/i;
14712
14944
  const validProject = (v) => typeof v === "string" && SLUG$1.test(v.trim()) ? v.trim() : void 0;
14713
14945
  function projectToken(tokens) {
@@ -14730,6 +14962,16 @@ function projectOf(p) {
14730
14962
  function isCoordinator(p) {
14731
14963
  return Boolean(p.agent && projectOf(p) && !isProjectThread(p));
14732
14964
  }
14965
+ function pickCoordinator(panes, slug, machine) {
14966
+ const key = slug.toLowerCase();
14967
+ const rank = (p) => (0) + (norm$4(p.cwd).toLowerCase().endsWith(`/.herdr-projects/${key}`) ? 0 : 1);
14968
+ let best = null;
14969
+ for (const p of panes) {
14970
+ if (!isCoordinator(p) || projectOf(p).toLowerCase() !== key) continue;
14971
+ if (!best || rank(p) < rank(best)) best = p;
14972
+ }
14973
+ return best;
14974
+ }
14733
14975
 
14734
14976
  function cleanLabel(label) {
14735
14977
  return (label != null ? label : "").replace(/[\u200B-\u200D\u2060\uFEFF]/g, "").replace(/[\u2800\s]+/g, " ").trim();
@@ -14871,11 +15113,53 @@ function foregroundCommand(info) {
14871
15113
  return [name, ...argv.slice(1)].join(" ").replace(/\s+/g, " ").trim().slice(0, 60);
14872
15114
  }
14873
15115
 
15116
+ var __defProp$3 = Object.defineProperty;
15117
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
15118
+ var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
14874
15119
  const SCREEN_MS$1 = 3e3;
14875
- function keepReading(c, rev, strict, watch, now) {
14876
- if (!c || c.rev !== rev || c.strict !== strict) return false;
14877
- const live = watch || !strict || Boolean(c.choices || c.screen || c.menu);
14878
- return !(live && now - c.at >= SCREEN_MS$1);
15120
+ const CHOICE_MS = 1e3;
15121
+ function keepReading(c, rev, strict, watch, now, viewed = false) {
15122
+ if (!c || c.unavailable || c.rev !== rev || c.strict !== strict) return false;
15123
+ const live = watch || !strict && !c.usageLimit || Boolean(c.choices || c.screen || c.menu || c.interaction === "terminal");
15124
+ return !(live && now - c.at >= (c.choices && viewed ? CHOICE_MS : SCREEN_MS$1));
15125
+ }
15126
+ class ScreenCache extends Map {
15127
+ constructor() {
15128
+ super(...arguments);
15129
+ // Retained only for disabled display after invalidation; never a cache hit.
15130
+ __publicField$3(this, "retained", /* @__PURE__ */ new Map());
15131
+ __publicField$3(this, "sequence", 0);
15132
+ __publicField$3(this, "versions", /* @__PURE__ */ new Map());
15133
+ }
15134
+ version(id) {
15135
+ if (!this.versions.has(id)) this.versions.set(id, ++this.sequence);
15136
+ return this.versions.get(id);
15137
+ }
15138
+ invalidate(id) {
15139
+ this.versions.set(id, ++this.sequence);
15140
+ }
15141
+ previous(id) {
15142
+ return this.get(id) || this.retained.get(id);
15143
+ }
15144
+ ids() {
15145
+ return /* @__PURE__ */ new Set([...this.keys(), ...this.versions.keys()]);
15146
+ }
15147
+ delete(id) {
15148
+ const previous = this.get(id);
15149
+ if (previous !== void 0) this.retained.set(id, previous);
15150
+ if (this.versions.has(id)) this.invalidate(id);
15151
+ return super.delete(id);
15152
+ }
15153
+ clear() {
15154
+ this.retained.clear();
15155
+ this.versions.clear();
15156
+ super.clear();
15157
+ }
15158
+ forget(id) {
15159
+ this.retained.delete(id);
15160
+ this.versions.delete(id);
15161
+ super.delete(id);
15162
+ }
14879
15163
  }
14880
15164
 
14881
15165
  const KEY_NAMES = { enter: "enter", return: "enter", esc: "esc", escape: "esc", tab: "tab" };
@@ -14978,6 +15262,16 @@ function settingsTabs(text) {
14978
15262
  const i = settingsRowIndex(lines);
14979
15263
  return i < 0 ? null : tabsOfRow(lines[i]);
14980
15264
  }
15265
+ function settingsFocus(text) {
15266
+ const rows = text.split("\n");
15267
+ const index = settingsRowIndex(rows);
15268
+ if (index < 0) return null;
15269
+ const lines = rows.slice(index + 1).map((l) => l.trim());
15270
+ if (lines.some((l) => /^←\/→\/tab to switch · ↓ to return · Esc to close$/.test(l))) return "tabs";
15271
+ if (lines.some((l) => /^Type to filter · Enter\/↓ to select · ↑ to tabs · Esc to clear$/.test(l))) return "filter";
15272
+ if (lines.some((l) => /^(?:Enter\/Space to change · )?\/ to search · Esc to close$/.test(l))) return "list";
15273
+ return null;
15274
+ }
14981
15275
 
14982
15276
  const SGR$1 = /\x1b\[([0-9;]*)m/g;
14983
15277
  const OTHER_ESC = /\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g;
@@ -15243,6 +15537,66 @@ function clickMovesOnly(menu) {
15243
15537
  return Boolean(enter && !/^(?:select|confirm|choose|open|resume|continue)$/i.test(enter.label.trim()));
15244
15538
  }
15245
15539
 
15540
+ function parseUsageLimit(text, agent) {
15541
+ var _a, _b;
15542
+ if (agent !== "claude") return null;
15543
+ const lines = text.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]|\r/g, "").split("\n");
15544
+ const field = lines.findLastIndex((l, i) => /^\s*❯(?:\s|$)/.test(l) && /^\s*─{3,}/.test(lines[i - 1] || ""));
15545
+ if (field < 0) return null;
15546
+ const rule = lines.findIndex((l, i) => i > field && /^\s*─{3,}/.test(l));
15547
+ if (rule < 0) return null;
15548
+ const tail = lines.slice(rule + 1);
15549
+ if (tail.length > 10 || tail.some((l) => /[╭┌]─|\benter to (?:select|confirm)\b|^\s*[❯›]\s*\d+\./i.test(l))) return null;
15550
+ const footer = tail.join("\n");
15551
+ const limit = footer.match(/^\s*(?:⚠\s*)?Usage limit reached(?:\s*·\s*limit resets ([^\n]+))?\s*$/m);
15552
+ if (!limit) return null;
15553
+ const resume = footer.match(/^\s*Continuing automatically (.+?)\s*·\s*esc to cancel\b/im);
15554
+ return {
15555
+ resets: ((_a = limit[1]) == null ? void 0 : _a.trim()) || ((_b = resume == null ? void 0 : resume[1]) == null ? void 0 : _b.trim()) || null,
15556
+ automatic: Boolean(resume),
15557
+ credits: /\/usage-credits to continue now\b/.test(footer),
15558
+ resetLink: /Use your limit reset to reset it now: clau\.de\/reset\b/.test(lines.slice(Math.max(0, field - 16), field).join("\n"))
15559
+ };
15560
+ }
15561
+
15562
+ function terminalException(text) {
15563
+ var _a, _b;
15564
+ const lines = text.trimEnd().split("\n");
15565
+ const at = lines.findLastIndex((l) => /^\s*(?:Agent Command Center|Usage)\s*$/.test(l));
15566
+ if (at < 0) return false;
15567
+ const body = lines.slice(at + 1).filter((l) => l.trim());
15568
+ if (lines[at].trim() === "Usage" && ((_a = body[0]) == null ? void 0 : _a.trim()) === "Account usage and resets.") body.shift();
15569
+ const legend = (_b = body.pop()) == null ? void 0 : _b.trim();
15570
+ if (lines[at].trim() === "Agent Command Center") {
15571
+ return legend === "Use arrows to navigate, Enter to open, Escape to return." && body.some((l) => /^\s*›\s+\S/.test(l)) && body.every((l) => /^(?:›\s+)?\S.* {2,}\S/.test(l.trim()));
15572
+ }
15573
+ return legend === "enter open \xB7 esc back" && body.length === 2 && /^[ \t›]*1\. View analytics {2,}Usage history[ \t]*$/.test(body[0]) && /^[ \t›]*2\. Redeem reset {2,}Check availability[ \t]*$/.test(body[1]);
15574
+ }
15575
+ function usesTerminalException(o) {
15576
+ return o.agent === "codex" && o.status !== "unknown" && o.status !== "working" && terminalException(o.text);
15577
+ }
15578
+ function confirmedInput(text) {
15579
+ const lines = text.trimEnd().split("\n");
15580
+ const at = lines.findLastIndex((l) => /^\s*[❯›](?:\s|$)/.test(l) || /^!(?:\s|$)/.test(l) || /^╰─(?:\s|$)/.test(l));
15581
+ if (at < 0) return false;
15582
+ const line = lines[at];
15583
+ const below = lines.slice(at + 1).join("\n");
15584
+ if (/\b(?:enter|esc|escape)\s+(?:to\s+)?(?:select|open|back|cancel|confirm|close)\b/i.test(below)) return false;
15585
+ if (/^\s*[❯›]\s+\d{1,2}\.\s/.test(line)) return false;
15586
+ if (/^╰─(?:\s|$)/.test(line)) return true;
15587
+ if (/^\s*›(?:\s|$)/.test(line)) return /for shortcuts|context left|\b(?:gpt-[\w.-]+|o[1-9](?:-[\w.-]+)?)\b.*·/i.test(below);
15588
+ return /^\s*─{3,}/.test(lines[at - 1] || "");
15589
+ }
15590
+ function classifyScreen(o) {
15591
+ if (o.status === "working") return "working";
15592
+ if (usesTerminalException(o)) return "terminal";
15593
+ if (o.status !== "unknown" && parseUsageLimit(o.text, o.agent)) return "native";
15594
+ if (o.choices || o.menu || o.screen || o.settings) return "native";
15595
+ if (o.status === "unknown" || !hasTranscript(o.agent) || !o.text.trim()) return "unknown";
15596
+ if (confirmedInput(o.text)) return "input";
15597
+ return "terminal";
15598
+ }
15599
+
15246
15600
  const GLYPHS = "\xB7\u2722\u2733\u2736\u273B\u273D\u273A\u2739\u2737\u2738*\u2217";
15247
15601
  const LINE_RE = new RegExp(`^([${GLYPHS}])\\s+(\\p{L}[\\p{L}'\u2019\\-]*(?: \\p{L}[\\p{L}'\u2019\\-]*){0,3})(?:\u2026|\\.\\.\\.)(?:\\s+\\((.*)\\))?\\s*$`, "u");
15248
15602
  const RULE_RE$1 = /^\s*[─━]{8,}\s*$/;
@@ -15475,20 +15829,28 @@ function checkQueue(list, status, now, menu = true) {
15475
15829
  }
15476
15830
  return changed;
15477
15831
  }
15832
+ function giveBackHeld(list) {
15833
+ for (const q of list || []) if (q.held) {
15834
+ q.failed = true;
15835
+ q.back = true;
15836
+ }
15837
+ }
15838
+ const leftForGood = (p, before) => !p.agent && !p.leaving && Boolean(before == null ? void 0 : before.leaving);
15478
15839
  const publicEntry = (q) => ({
15479
15840
  id: q.id,
15480
15841
  text: q.text,
15481
15842
  at: q.at,
15482
15843
  ...q.held && !q.failed ? { state: "held" } : {},
15483
15844
  ...q.failed ? { state: "failed" } : {},
15484
- ...(q.held || q.failed) && q.busy ? { reason: "busy" } : q.failed && q.noInput ? { reason: "no_input" } : {}
15845
+ ...(q.held || q.failed) && q.busy ? { reason: "busy" } : q.failed && q.noInput ? { reason: "no_input" } : {},
15846
+ ...q.back ? { back: true } : {}
15485
15847
  });
15486
15848
  function loadQueued(raw, now) {
15487
15849
  if (!raw || typeof raw !== "object") return [];
15488
15850
  const out = [];
15489
15851
  for (const [pane, list] of Object.entries(raw)) {
15490
15852
  if (!Array.isArray(list)) continue;
15491
- const ok = list.filter((q) => Boolean(q) && typeof q.id === "string" && typeof q.text === "string" && typeof q.at === "number" && now - q.at < QUEUED_TTL_MS).map((q) => ({ id: q.id, text: q.text, at: q.at, ...q.held ? { held: true } : {}, ...q.failed ? { failed: true } : {}, ...q.busy ? { busy: true } : {} }));
15853
+ const ok = list.filter((q) => Boolean(q) && typeof q.id === "string" && typeof q.text === "string" && typeof q.at === "number" && now - q.at < QUEUED_TTL_MS).map((q) => ({ id: q.id, text: q.text, at: q.at, ...q.held ? { held: true } : {}, ...q.failed ? { failed: true } : {}, ...q.busy ? { busy: true } : {}, ...q.back ? { back: true } : {} }));
15492
15854
  if (ok.length) out.push([pane, ok]);
15493
15855
  }
15494
15856
  return out;
@@ -15575,6 +15937,41 @@ function inputBox(ansi) {
15575
15937
  if (!bash && PLACEHOLDER_HINT.test(box) && !COLOR_SGR.test(ansi)) box = "";
15576
15938
  return bash ? `!${box && " "}${box}` : box;
15577
15939
  }
15940
+ const CODEX_FIELD = /^›(?: |$)/;
15941
+ function codexFieldLine(ansi) {
15942
+ const lines = String(ansi || "").split("\n").map((l) => l.replace(/\r$/, ""));
15943
+ let at = -1;
15944
+ for (let i = lines.length - 1; i >= 0 && at < 0; i--) if (CODEX_FIELD.test(lines[i].replace(SGR, ""))) at = i;
15945
+ if (at < 0) return null;
15946
+ const line = lines[at];
15947
+ const mark = sgrState(line.slice(0, line.indexOf("\u203A")));
15948
+ if (mark.dim || mark.reverse) return null;
15949
+ for (const below of lines.slice(at + 1)) {
15950
+ const plain = below.replace(SGR, "");
15951
+ if (plain.trim() && !plain.startsWith(" ")) return null;
15952
+ }
15953
+ return undimmed(line).replace(/^›\s?/, "").replace(/\u00a0/g, " ").trim();
15954
+ }
15955
+ function sgrState(prefix) {
15956
+ let dim = false;
15957
+ let reverse = false;
15958
+ for (const m of prefix.matchAll(SGR)) {
15959
+ if (!m[0].endsWith("m")) continue;
15960
+ const codes = m[0].slice(2, -1).split(";");
15961
+ for (let i = 0; i < codes.length; i++) {
15962
+ const c = Number(codes[i] || 0);
15963
+ if (c === 0) {
15964
+ dim = false;
15965
+ reverse = false;
15966
+ } else if (c === 2) dim = true;
15967
+ else if (c === 22) dim = false;
15968
+ else if (c === 7) reverse = true;
15969
+ else if (c === 27) reverse = false;
15970
+ else if (c === 38 || c === 48 || c === 58) i += codes[i + 1] === "5" ? 2 : codes[i + 1] === "2" ? 4 : 0;
15971
+ }
15972
+ }
15973
+ return { dim, reverse };
15974
+ }
15578
15975
  function clearKeys(lines) {
15579
15976
  const keys = [];
15580
15977
  for (let i = 0; i < Math.min(Math.max(lines, 1) + 2, 200); i++) keys.push("ctrl+u", "backspace");
@@ -15801,6 +16198,114 @@ async function interruptAgent(d, p) {
15801
16198
  return res;
15802
16199
  }
15803
16200
 
16201
+ const PASTES_MAX = 100;
16202
+ const PASTES_MAX_CHARS = 2e6;
16203
+ const PASTES_TTL_MS = 30 * 864e5;
16204
+ const live = (p, now) => now - p.at < PASTES_TTL_MS;
16205
+ const PER_MESSAGE = 20;
16206
+ function pastesAt(text, ranges) {
16207
+ if (!Array.isArray(ranges)) return [];
16208
+ const out = [];
16209
+ for (const r of ranges.slice(0, PER_MESSAGE)) {
16210
+ if (!Array.isArray(r)) continue;
16211
+ const [at, len] = r;
16212
+ if (typeof at !== "number" || typeof len !== "number" || !Number.isInteger(at) || !Number.isInteger(len)) continue;
16213
+ if (at < 0 || len <= 0 || at + len > text.length) continue;
16214
+ const b = text.slice(at, at + len).trim();
16215
+ if (isLongPaste(b) && !out.includes(b)) out.push(b);
16216
+ }
16217
+ return out;
16218
+ }
16219
+ function addPastes(list, blocks, now) {
16220
+ if (!blocks.length) return list;
16221
+ let total = 0;
16222
+ return [...blocks.map((text) => ({ text, at: now })), ...list.filter((p) => !blocks.includes(p.text) && live(p, now))].slice(0, PASTES_MAX).filter((p) => {
16223
+ total += p.text.length;
16224
+ return total <= PASTES_MAX_CHARS;
16225
+ });
16226
+ }
16227
+ function loadPastes(raw, now) {
16228
+ if (!Array.isArray(raw)) return [];
16229
+ const out = [];
16230
+ let total = 0;
16231
+ for (const r of raw) {
16232
+ const p = typeof r === "string" ? { text: r, at: now } : r;
16233
+ if (!p || typeof p.text !== "string" || typeof p.at !== "number" || !Number.isFinite(p.at)) continue;
16234
+ if (!isLongPaste(p.text) || !live(p, now) || out.some((o) => o.text === p.text)) continue;
16235
+ if (out.length >= PASTES_MAX || (total += p.text.length) > PASTES_MAX_CHARS) break;
16236
+ out.push({ text: p.text, at: Math.min(p.at, now) });
16237
+ }
16238
+ return out;
16239
+ }
16240
+ function pastedIn(list, text, listed = []) {
16241
+ if (!list.length || !isLongPaste(text)) return listed;
16242
+ const known = list.filter((b) => !listed.includes(b)).sort((a, b) => b.length - a.length);
16243
+ return splitPasted(text, listed, known).pastes;
16244
+ }
16245
+ function withPasted(items, list) {
16246
+ if (!list.length) return items;
16247
+ return items.map((i) => {
16248
+ if (i.role !== "user") return i;
16249
+ const pasted = pastedIn(list, i.text, i.pasted);
16250
+ return pasted.length && pasted !== i.pasted ? { ...i, pasted } : i;
16251
+ });
16252
+ }
16253
+ function withQueuedPasted(q, list) {
16254
+ const pasted = pastedIn(list, q.text);
16255
+ return pasted.length ? { ...q, pasted } : q;
16256
+ }
16257
+ const PASTES_FILE = path$1.join(DATA_DIR, "pastes.json");
16258
+ let kept = null;
16259
+ let saved = null;
16260
+ let texts = null;
16261
+ function pastes() {
16262
+ if (kept) return kept;
16263
+ kept = [];
16264
+ saved = kept;
16265
+ try {
16266
+ const raw = fs.readFileSync(PASTES_FILE, "utf8");
16267
+ kept = loadPastes(JSON.parse(raw), Date.now());
16268
+ saved = JSON.stringify(kept) + "\n" === raw ? kept : null;
16269
+ } catch {
16270
+ }
16271
+ return kept;
16272
+ }
16273
+ function keptTexts() {
16274
+ const list = pastes();
16275
+ if ((texts == null ? void 0 : texts.of) !== list) texts = { of: list, list: list.map((p) => p.text) };
16276
+ return texts.list;
16277
+ }
16278
+ let writing = Promise.resolve();
16279
+ function save() {
16280
+ writing = writing.then(async () => {
16281
+ const list = kept;
16282
+ if (!list || list === saved) return;
16283
+ const temp = `${PASTES_FILE}.${randomUUID$1()}.tmp`;
16284
+ try {
16285
+ await fs$1.mkdir(DATA_DIR, { recursive: true });
16286
+ await fs$1.writeFile(temp, JSON.stringify(list) + "\n", { mode: 384 });
16287
+ await fs$1.rename(temp, PASTES_FILE);
16288
+ saved = list;
16289
+ } catch {
16290
+ await fs$1.rm(temp, { force: true }).catch(() => {
16291
+ });
16292
+ }
16293
+ });
16294
+ }
16295
+ function keepPastes(text, ranges) {
16296
+ const next = addPastes(pastes(), pastesAt(text, ranges), Date.now());
16297
+ if (next === kept) return;
16298
+ kept = next;
16299
+ save();
16300
+ }
16301
+ function purgePastes(now = Date.now()) {
16302
+ const list = pastes();
16303
+ if (list.some((p) => !live(p, now))) kept = list.filter((p) => live(p, now));
16304
+ if (kept !== saved) save();
16305
+ }
16306
+ const chatPasted = (items) => withPasted(items, keptTexts());
16307
+ const queuedPasted = (q) => withQueuedPasted(q, keptTexts());
16308
+
15804
16309
  const DEFAULTS = { freeWaitMs: 2e3, quietMs: 400, showWaitMs: 4e3, submitWaitMs: 4e3, pollMs: 50 };
15805
16310
  const RECORD_MS = 600;
15806
16311
  const MAX_ATTEMPTS = 3;
@@ -15811,6 +16316,7 @@ const compact = (s) => s.replace(/\s+/g, "");
15811
16316
  const BASH_EMPTY = "!";
15812
16317
  const isFree = (box) => !box || box === BASH_EMPTY;
15813
16318
  const tidy = (s) => s.replace(/\s+/g, " ").trim();
16319
+ const submittable = (text) => text.endsWith("\\") ? `${text} ` : text;
15814
16320
  function classifyBox(box, ours) {
15815
16321
  const b = compact(box);
15816
16322
  const o = compact(ours);
@@ -15915,7 +16421,7 @@ async function sendOne(d, text, o, foreign) {
15915
16421
  };
15916
16422
  field = await waitFree(d, o);
15917
16423
  for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
15918
- await d.type(await bashReady(d, o, text, field));
16424
+ await d.type(submittable(await bashReady(d, o, text, field)));
15919
16425
  let state = { kind: "empty" };
15920
16426
  let box = "";
15921
16427
  const typed = now();
@@ -15950,6 +16456,7 @@ async function sendOne(d, text, o, foreign) {
15950
16456
  if (!same) {
15951
16457
  after = state.kind === "unknown" ? { kind: "unknown" } : classifyBox(box, text);
15952
16458
  if (after.kind === "glued") break;
16459
+ if (after.kind === "partial") continue;
15953
16460
  return;
15954
16461
  }
15955
16462
  if (!again && now() - entered >= o.submitWaitMs / 3) {
@@ -16311,23 +16818,30 @@ async function listDirs(p, machine = "") {
16311
16818
  const home = m.home;
16312
16819
  const dir = underHome(p || home, home);
16313
16820
  if (!dir) throw new HerdrError("bad_path", fmt("Outside {home}", { home }));
16821
+ const remote = m instanceof RemoteMachine;
16822
+ const parent = dir === home ? null : px.dirname(dir);
16314
16823
  let raw;
16824
+ let denied = null;
16315
16825
  if (m instanceof RemoteMachine) {
16316
16826
  const r = await m.exec(LIST_DIRS_SCRIPT, [dir], { timeoutMs: 15e3 });
16317
- if (r.code !== 0) throw new HerdrError("bad_path", fmt("Folder unreadable: {path}", { path: dir }));
16827
+ denied = dirDeniedFromCode(r.code);
16828
+ if (r.code !== 0 && !denied) throw new HerdrError("bad_path", fmt("Folder unreadable: {path}", { path: dir }));
16318
16829
  raw = parseDirList(r.stdout.toString("utf8"));
16319
16830
  } else {
16320
16831
  try {
16321
16832
  raw = await listDirsLocal(dir);
16322
- } catch {
16323
- throw new HerdrError("bad_path", fmt("Folder unreadable: {path}", { path: dir }));
16833
+ } catch (err) {
16834
+ denied = dirDeniedFromError(err);
16835
+ if (!denied) throw new HerdrError("bad_path", fmt("Folder unreadable: {path}", { path: dir }));
16836
+ raw = [];
16324
16837
  }
16325
16838
  }
16839
+ if (denied) return { path: dir, parent, home, dirs: [], denied, ...remote ? { remote } : {} };
16326
16840
  const out = raw.map((e) => ({ name: e.name, path: px.join(dir, e.name), git: e.git }));
16327
16841
  out.sort((a, b) => Number(b.git) - Number(a.git) || a.name.localeCompare(b.name));
16328
16842
  const kinds = await projectFolderKinds(m, [dir, ...out.map((e) => e.path)]);
16329
16843
  for (const e of out) if (kinds[e.path]) e.project = kinds[e.path];
16330
- return { path: dir, parent: dir === home ? null : px.dirname(dir), home, dirs: out, ...kinds[dir] ? { project: kinds[dir] } : {} };
16844
+ return { path: dir, parent, home, dirs: out, ...kinds[dir] ? { project: kinds[dir] } : {} };
16331
16845
  }
16332
16846
  async function closePanel(paneId) {
16333
16847
  const p = findPane(paneId);
@@ -16489,6 +17003,35 @@ function cleanSavedSizes(raw, isPane) {
16489
17003
  return out;
16490
17004
  }
16491
17005
 
17006
+ const SCROLL_MS = 75;
17007
+ const MAX_LINES = 500;
17008
+ function createScrollThrottle(send2, { intervalMs = SCROLL_MS, now = Date.now, setTimer = setTimeout, clearTimer = clearTimeout } = {}) {
17009
+ let net = 0;
17010
+ let last = -Infinity;
17011
+ let timer = null;
17012
+ const flush = () => {
17013
+ timer = null;
17014
+ if (!net) return;
17015
+ send2(net > 0 ? "up" : "down", Math.min(Math.abs(net), MAX_LINES));
17016
+ net = 0;
17017
+ last = now();
17018
+ };
17019
+ return {
17020
+ push(direction, lines) {
17021
+ net += direction === "up" ? lines : -lines;
17022
+ if (timer) return;
17023
+ const wait = last + intervalMs - now();
17024
+ if (wait <= 0) flush();
17025
+ else timer = setTimer(flush, wait);
17026
+ },
17027
+ dispose() {
17028
+ if (timer) clearTimer(timer);
17029
+ timer = null;
17030
+ net = 0;
17031
+ }
17032
+ };
17033
+ }
17034
+
16492
17035
  const clampInt = (v, lo, hi, dflt) => {
16493
17036
  const n = parseInt(String(v), 10);
16494
17037
  return Number.isFinite(n) ? Math.min(hi, Math.max(lo, n)) : dflt;
@@ -16613,6 +17156,7 @@ function openTerm(ws, url) {
16613
17156
  });
16614
17157
  for (const m of early.splice(0)) toChild(m);
16615
17158
  }
17159
+ const scroll = createScrollThrottle((direction, lines) => toChild({ type: "terminal.scroll", direction, lines }));
16616
17160
  paneSizes().hold(pane).then((h) => {
16617
17161
  if (closed) return h.release(true);
16618
17162
  hold = h;
@@ -16639,7 +17183,7 @@ function openTerm(ws, url) {
16639
17183
  }
16640
17184
  case "terminal.scroll":
16641
17185
  if (m.direction === "up" || m.direction === "down") {
16642
- toChild({ type: "terminal.scroll", direction: m.direction, lines: clampInt(m.lines, 1, 500, 3) });
17186
+ scroll.push(m.direction, clampInt(m.lines, 1, 500, 3));
16643
17187
  }
16644
17188
  break;
16645
17189
  case "keys":
@@ -16662,6 +17206,7 @@ function openTerm(ws, url) {
16662
17206
  },
16663
17207
  onClose(clean = false) {
16664
17208
  closed = true;
17209
+ scroll.dispose();
16665
17210
  termSessions.delete(sess);
16666
17211
  const c = child;
16667
17212
  if (c) {
@@ -16806,7 +17351,8 @@ const listKey = (paneId, agent) => {
16806
17351
  var _a;
16807
17352
  return `${((_a = machineOfPane(paneId)) == null ? void 0 : _a.key) || ""}|${agent}`;
16808
17353
  };
16809
- const busy = /* @__PURE__ */ new Set();
17354
+ const busy$1 = /* @__PURE__ */ new Set();
17355
+ const modelControlBusy = (paneId) => busy$1.has(paneId);
16810
17356
  async function withPane(paneId, fn) {
16811
17357
  const p = findPane(paneId);
16812
17358
  if (!p) throw new HerdrError("bad_pane", "Pane not found");
@@ -16814,12 +17360,12 @@ async function withPane(paneId, fn) {
16814
17360
  if (!READY.has(p.status || "")) {
16815
17361
  throw new HerdrError("busy", p.status === "blocked" ? "The agent is waiting for an answer \u2014 reply first." : "The agent is working \u2014 change the model once it\u2019s done.");
16816
17362
  }
16817
- if (busy.has(paneId)) throw new HerdrError("busy", "Model change already in progress");
16818
- busy.add(paneId);
17363
+ if (busy$1.has(paneId)) throw new HerdrError("busy", "Model change already in progress");
17364
+ busy$1.add(paneId);
16819
17365
  try {
16820
17366
  return await fn(p);
16821
17367
  } finally {
16822
- busy.delete(paneId);
17368
+ busy$1.delete(paneId);
16823
17369
  }
16824
17370
  }
16825
17371
  const screen = async (paneId) => {
@@ -18116,6 +18662,494 @@ async function installClaudeStatusline(m) {
18116
18662
  return last(r.stdout.toString("utf8"));
18117
18663
  }
18118
18664
 
18665
+ const CLAUDE = {
18666
+ keep: {
18667
+ "--model": 1,
18668
+ "--effort": 1,
18669
+ "--permission-mode": 1,
18670
+ "--fallback-model": 1,
18671
+ "--agent": 1,
18672
+ "--agents": 1,
18673
+ "--settings": 1,
18674
+ "--setting-sources": 1,
18675
+ "--system-prompt": 1,
18676
+ "--append-system-prompt": 1,
18677
+ "--autocompact": 1,
18678
+ "-n": 1,
18679
+ "--name": 1,
18680
+ "--debug-file": 1,
18681
+ "--add-dir": "*",
18682
+ "--mcp-config": "*",
18683
+ "--plugin-dir": "*",
18684
+ "--allowedTools": "*",
18685
+ "--allowed-tools": "*",
18686
+ "--disallowedTools": "*",
18687
+ "--disallowed-tools": "*",
18688
+ "--tools": "*",
18689
+ "--betas": "*",
18690
+ "--dangerously-skip-permissions": 0,
18691
+ "--allow-dangerously-skip-permissions": 0,
18692
+ "--verbose": 0,
18693
+ "--ide": 0,
18694
+ "--chrome": 0,
18695
+ "--no-chrome": 0,
18696
+ "--strict-mcp-config": 0,
18697
+ "--bare": 0,
18698
+ "--brief": 0,
18699
+ "--disable-slash-commands": 0,
18700
+ "--safe-mode": 0,
18701
+ "--restricted": 0
18702
+ },
18703
+ // Conversation choice, one-off launch or already done (worktree created).
18704
+ drop: {
18705
+ "-c": 0,
18706
+ "--continue": 0,
18707
+ "-r": "?",
18708
+ "--resume": "?",
18709
+ "--session-id": 1,
18710
+ "--fork-session": 0,
18711
+ "-w": "?",
18712
+ "--worktree": "?",
18713
+ "--tmux": 0,
18714
+ "--from-pr": "?",
18715
+ "--teleport": "?",
18716
+ "-p": 0,
18717
+ "--print": 0,
18718
+ "--bg": 0,
18719
+ "--background": 0,
18720
+ "--remote-control": "?",
18721
+ "--cloud": "?",
18722
+ "--file": "*",
18723
+ "-d": "?",
18724
+ "--debug": "?"
18725
+ }
18726
+ };
18727
+ const CODEX = {
18728
+ keep: {
18729
+ "-c": 1,
18730
+ "--config": 1,
18731
+ "--enable": 1,
18732
+ "--disable": 1,
18733
+ "-m": 1,
18734
+ "--model": 1,
18735
+ "--local-provider": 1,
18736
+ "-p": 1,
18737
+ "--profile": 1,
18738
+ "-s": 1,
18739
+ "--sandbox": 1,
18740
+ "-C": 1,
18741
+ "--cd": 1,
18742
+ "--add-dir": 1,
18743
+ "-a": 1,
18744
+ "--ask-for-approval": 1,
18745
+ "--remote": 1,
18746
+ "--remote-auth-token-env": 1,
18747
+ "--oss": 0,
18748
+ "--search": 0,
18749
+ "--no-alt-screen": 0,
18750
+ "--no-daemon": 0,
18751
+ "--full-auto": 0,
18752
+ "--dangerously-bypass-approvals-and-sandbox": 0,
18753
+ "--yolo": 0,
18754
+ "--approve-for-me": 0,
18755
+ "--strict-config": 0,
18756
+ "--dangerously-bypass-hook-trust": 0
18757
+ },
18758
+ drop: { "--last": 0, "--all": 0, "--include-non-interactive": 0, "-i": "*", "--image": "*", "--worktree": 0 }
18759
+ };
18760
+ const OMP = {
18761
+ keep: {
18762
+ "--model": 1,
18763
+ "--smol": 1,
18764
+ "--slow": 1,
18765
+ "--plan": 1,
18766
+ "--prewalk-into": 1,
18767
+ "--plan-yolo-into": 1,
18768
+ "--provider": 1,
18769
+ "--system-prompt": 1,
18770
+ "--system-prompt-template": 1,
18771
+ "--append-system-prompt": 1,
18772
+ "--profile": 1,
18773
+ "--cwd": 1,
18774
+ "--config": 1,
18775
+ "--add-dir": 1,
18776
+ "--session-dir": 1,
18777
+ "--models": 1,
18778
+ "--tools": 1,
18779
+ "--thinking": 1,
18780
+ "--service-tier": 1,
18781
+ "--hook": 1,
18782
+ "-e": 1,
18783
+ "--extension": 1,
18784
+ "--skills": 1,
18785
+ "--approval-mode": 1,
18786
+ "--plugin-dir": 1,
18787
+ "--allow-home": 0,
18788
+ "--prewalk": 0,
18789
+ "--no-prewalk": 0,
18790
+ "--no-tools": 0,
18791
+ "--no-lsp": 0,
18792
+ "--no-pty": 0,
18793
+ "--hide-thinking": 0,
18794
+ "--advisor": 0,
18795
+ "--external-thinking": 0,
18796
+ "--no-extensions": 0,
18797
+ "--no-skills": 0,
18798
+ "--no-rules": 0,
18799
+ "--no-title": 0,
18800
+ "--auto-approve": 0
18801
+ },
18802
+ // Conversation choice, one-off launch; the API key is never replayed
18803
+ // (it would show in the confirmation).
18804
+ drop: {
18805
+ "-c": 0,
18806
+ "--continue": 0,
18807
+ "-r": "?",
18808
+ "--resume": "?",
18809
+ "-p": 0,
18810
+ "--print": 0,
18811
+ "--plan-yolo": 0,
18812
+ "--from-claude": 0,
18813
+ "--from-codex": 0,
18814
+ "--no-session": 0,
18815
+ "--export": 1,
18816
+ "--mode": 1,
18817
+ "--max-time": 1,
18818
+ "--alias": 1,
18819
+ "--api-key": 1,
18820
+ "--no-ui": 0,
18821
+ "--print-thoughts": 0
18822
+ }
18823
+ };
18824
+ const SILENT = /* @__PURE__ */ new Set(["-c", "--continue", "-r", "--resume", "--session-id", "--fork-session", "--last", "--all"]);
18825
+ const SPECS = { claude: CLAUDE, codex: CODEX, omp: OMP };
18826
+ const RESTARTABLE = new Set(Object.keys(SPECS));
18827
+ const base$1 = (s) => s.replace(/^.*\//, "").replace(/\.(c?js|mjs)$/, "");
18828
+ function launchOptions(kind, argv) {
18829
+ const spec = SPECS[kind];
18830
+ const kept = [];
18831
+ const dropped = [];
18832
+ if (!spec) return { kept, dropped };
18833
+ let i = argv.findIndex((a) => base$1(a) === kind);
18834
+ i = i < 0 ? 1 : i + 1;
18835
+ for (; i < argv.length; i++) {
18836
+ const a = argv[i];
18837
+ if (a === "--") break;
18838
+ if (!a.startsWith("-") || a === "-") continue;
18839
+ const eq = a.indexOf("=");
18840
+ const flag = eq > 0 ? a.slice(0, eq) : a;
18841
+ const keep = flag in spec.keep;
18842
+ const arity = keep ? spec.keep[flag] : spec.drop[flag];
18843
+ const out = [a];
18844
+ if (keep) kept.push(out);
18845
+ else if (!SILENT.has(flag)) dropped.push(out);
18846
+ if (arity === void 0) {
18847
+ if (eq < 0 && argv[i + 1] !== void 0 && !argv[i + 1].startsWith("-")) out.push(argv[++i]);
18848
+ continue;
18849
+ }
18850
+ if (eq > 0 || arity === 0) continue;
18851
+ if (arity === 1) {
18852
+ if (argv[i + 1] !== void 0) out.push(argv[++i]);
18853
+ continue;
18854
+ }
18855
+ while (argv[i + 1] !== void 0 && !argv[i + 1].startsWith("-")) {
18856
+ out.push(argv[++i]);
18857
+ if (arity === "?") break;
18858
+ }
18859
+ }
18860
+ return { kept, dropped };
18861
+ }
18862
+ const EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
18863
+ function planRestart(o) {
18864
+ const opts = o.argv ? launchOptions(o.kind, o.argv) : { kept: [], dropped: [] };
18865
+ const mode = o.session ? "resume" : o.hadSession ? "fresh" : "continue";
18866
+ let groups = opts.kept;
18867
+ const without = (...flags) => {
18868
+ groups = groups.filter((g) => !flags.includes(g[0].split("=")[0]));
18869
+ };
18870
+ if (o.kind === "omp" && mode === "resume") without("--model", "--thinking");
18871
+ if (o.kind === "claude") {
18872
+ const cur = o.current || {};
18873
+ if (mode === "resume") without("--model");
18874
+ const effort = String(cur.effort || "").toLowerCase();
18875
+ if (EFFORTS.has(effort)) {
18876
+ without("--effort");
18877
+ groups.push(["--effort", effort]);
18878
+ }
18879
+ if (cur.permissionMode) {
18880
+ without("--permission-mode");
18881
+ if (cur.permissionMode !== "default") groups.push(["--permission-mode", cur.permissionMode]);
18882
+ }
18883
+ }
18884
+ const kept = groups.flat();
18885
+ const dropped = opts.dropped.flat();
18886
+ let args;
18887
+ if (o.kind === "codex") {
18888
+ args = mode === "fresh" ? kept : ["resume", ...kept, mode === "resume" ? o.session : "--last"];
18889
+ } else {
18890
+ args = mode === "resume" ? [...kept, "--resume", o.session] : mode === "continue" ? [...kept, "--continue"] : kept;
18891
+ }
18892
+ return { args, mode, kept, dropped, unknownArgs: !o.argv };
18893
+ }
18894
+ const FOOTER_MODES = [
18895
+ [/\bplan mode on\b/i, "plan"],
18896
+ [/\baccept edits on\b/i, "acceptEdits"],
18897
+ [/\bauto mode on\b/i, "auto"],
18898
+ [/\bbypass permissions on\b/i, "bypassPermissions"],
18899
+ [/\bdon'?t ask (?:mode )?on\b/i, "dontAsk"]
18900
+ ];
18901
+ function claudeFooterMode(text) {
18902
+ const lines = String(text || "").split("\n");
18903
+ let rule = -1;
18904
+ for (let i = lines.length - 1; i >= 0 && rule < 0; i--) if (/^\s*─{20,}\s*$/.test(lines[i])) rule = i;
18905
+ if (rule < 1 || !lines.slice(Math.max(0, rule - 6), rule).some((l) => /^\s*❯/.test(l))) return null;
18906
+ for (const l of lines.slice(rule + 1)) {
18907
+ for (const [re, mode] of FOOTER_MODES) if (re.test(l)) return mode;
18908
+ }
18909
+ return "default";
18910
+ }
18911
+
18912
+ function updateShellSignature(text) {
18913
+ const lines = text.replace(/\r/g, "").trimEnd().split("\n");
18914
+ const end = lines.findLastIndex((l) => /^\s*(?:🎉\s*)?Update ran successfully! Please restart Codex\.\s*$/.test(l));
18915
+ if (end < 0 || !lines.slice(Math.max(0, end - 4), end).some((l) => /^\s*Codex CLI \S+ installed successfully\.\s*$/.test(l))) return null;
18916
+ const tail = lines.slice(end + 1).filter((l) => l.trim());
18917
+ if (!tail.length || tail.length > 2) return null;
18918
+ const last = tail.at(-1);
18919
+ if (!/^\s*(?:[\w@./~:-]+(?: [\w@./~:-]+){0,2} )?[$%#❯]\s*$/.test(last)) return null;
18920
+ if (tail.length === 2 && (!/^\s*[\w./~:-]+ on [\w./:-]+\s*$/.test(tail[0]) || !/^\s*❯\s*$/.test(last))) return null;
18921
+ return tail.join("\n");
18922
+ }
18923
+ function updateChoices(launch) {
18924
+ return launch.conversation === "empty" && launch.argv && !launch.argv.some((a) => a === "resume" || a === "fork") ? ["restart"] : ["resume", "fresh"];
18925
+ }
18926
+ const UPDATE_LABELS = {
18927
+ restart: "Restart Codex",
18928
+ resume: "Resume conversation",
18929
+ fresh: "Start fresh"
18930
+ };
18931
+ function updatePrompt(launch) {
18932
+ return {
18933
+ kind: "self-update",
18934
+ question: "Codex updated itself and stopped",
18935
+ cursor: -1,
18936
+ options: updateChoices(launch).map((c) => ({ label: UPDATE_LABELS[c], hint: c === "resume" && !launch.session ? "Choose a conversation in Codex" : null }))
18937
+ };
18938
+ }
18939
+ function updateRestartPlan(launch, choice) {
18940
+ const kept = launch.argv ? launchOptions("codex", launch.argv).kept.flat() : [];
18941
+ let args = choice === "resume" ? ["resume", ...kept, ...launch.session ? [launch.session] : []] : kept;
18942
+ if (choice === "restart" && launch.argv) {
18943
+ const i = launch.argv.findIndex((a) => /(?:^|\/)codex(?:\.[cm]?js)?$/.test(a));
18944
+ if (i >= 0) args = launch.argv.slice(i + 1);
18945
+ }
18946
+ return { args, mode: choice === "resume" ? "resume" : "fresh", kept, dropped: [], unknownArgs: !launch.argv };
18947
+ }
18948
+
18949
+ const base = (s) => s.replace(/^.*\//, "").replace(/\.(c?js|mjs)$/, "");
18950
+ async function paneForeground(d, paneId, kind) {
18951
+ const r = await d.call("pane.process_info", { pane_id: paneId }, 4e3);
18952
+ const info = r && r.process_info || {};
18953
+ const procs = info.foreground_processes || [];
18954
+ const agent = procs.find((p) => p.name === kind || (p.argv || []).some((a) => base(a) === kind)) || null;
18955
+ const atShell = !agent && Boolean(info.shell_pid) && info.foreground_process_group_id === info.shell_pid;
18956
+ const sh = procs.find((p) => info.shell_pid && p.pid === info.shell_pid);
18957
+ const shell = { pid: Number(info.shell_pid) || null, name: sh ? String(sh.name || (sh.argv || [])[0] || "") || null : null };
18958
+ return { agent, atShell, shell, argv: agent && Array.isArray(agent.argv) ? agent.argv.map(String) : null };
18959
+ }
18960
+ async function waitFor(d, ms, test) {
18961
+ const end = d.now() + ms;
18962
+ while (d.now() < end) {
18963
+ await d.sleep(500);
18964
+ try {
18965
+ if (await test()) return true;
18966
+ } catch {
18967
+ }
18968
+ }
18969
+ return false;
18970
+ }
18971
+ const waitShell = (d, paneId, kind, ms) => waitFor(d, ms, async () => (await paneForeground(d, paneId, kind)).atShell);
18972
+ const busy = async (d, paneId) => {
18973
+ const r = await d.call("pane.get", { pane_id: paneId }, 4e3);
18974
+ const s = r && r.pane && r.pane.agent_status;
18975
+ return s === "working" || s === "blocked";
18976
+ };
18977
+ async function stopAgent(d, p) {
18978
+ const kind = p.agent;
18979
+ const key = (k) => d.call("pane.send_input", { pane_id: p.id, keys: [k] });
18980
+ if (p.status === "working" || p.status === "blocked") {
18981
+ for (let i = 0; i < 2; i++) {
18982
+ await key("esc");
18983
+ if (await waitFor(d, 3e3, async () => !await busy(d, p.id))) break;
18984
+ }
18985
+ }
18986
+ await d.call("pane.send_input", { pane_id: p.id, text: "/exit" });
18987
+ await d.sleep(300);
18988
+ await key("enter");
18989
+ if (await waitShell(d, p.id, kind, 8e3)) return "exit";
18990
+ await key("ctrl+c");
18991
+ await d.sleep(400);
18992
+ await key("ctrl+c");
18993
+ if (await waitShell(d, p.id, kind, 6e3)) return "ctrl-c";
18994
+ throw new HerdrError("restart_stop", "the agent did not stop");
18995
+ }
18996
+ async function startAgent(d, p, plan) {
18997
+ const name = p.name || `${p.agent}-${crypto.randomBytes(2).toString("hex")}`;
18998
+ let last = null;
18999
+ for (let i = 0; i < 6; i++) {
19000
+ try {
19001
+ await d.call("agent.start", { name, kind: p.agent, pane_id: p.id, timeout_ms: 6e4, ...plan.args.length ? { args: plan.args } : {} }, 75e3);
19002
+ return;
19003
+ } catch (e) {
19004
+ last = e;
19005
+ if (last.code === "agent_not_ready") return;
19006
+ if (last.code === "timeout" || last.code === "unreachable") break;
19007
+ await d.sleep(500);
19008
+ }
19009
+ }
19010
+ throw last || new HerdrError("restart_start", "the agent did not restart");
19011
+ }
19012
+
19013
+ const AT_SAVE_MS = 60 * 1e3;
19014
+ const OUTAGE_MS = 15e3;
19015
+ function createSelfUpdates(d, saved = []) {
19016
+ const records = new Map(saved);
19017
+ const restored = new Set(records.keys());
19018
+ const stable = () => JSON.stringify([...records].map(([id, r]) => [id, { ...r, at: 0 }]));
19019
+ const times = () => [...records.values()].map((r) => r.at).join();
19020
+ let written = stable();
19021
+ let writtenTimes = times();
19022
+ let writtenAt = d.now();
19023
+ const persist = () => {
19024
+ var _a;
19025
+ const s = stable();
19026
+ if (s === written && (d.now() - writtenAt < AT_SAVE_MS || times() === writtenTimes)) return;
19027
+ written = s;
19028
+ writtenTimes = times();
19029
+ writtenAt = d.now();
19030
+ (_a = d.save) == null ? void 0 : _a.call(d, [...records]);
19031
+ };
19032
+ const read = async (id) => {
19033
+ var _a, _b;
19034
+ return String(((_b = (_a = await d.call("pane.read", { pane_id: id, source: "recent_unwrapped", lines: 80 }, 4e3)) == null ? void 0 : _a.read) == null ? void 0 : _b.text) || "");
19035
+ };
19036
+ return {
19037
+ get: (id) => records.get(id),
19038
+ clear(id) {
19039
+ records.delete(id);
19040
+ persist();
19041
+ },
19042
+ // Service stopping: keep the exact time Codex was last seen alive, so a
19043
+ // quick restart still tells a short outage from a long one.
19044
+ flush() {
19045
+ var _a;
19046
+ if (records.size) (_a = d.save) == null ? void 0 : _a.call(d, [...records], true);
19047
+ },
19048
+ prune(ids, belongs) {
19049
+ let changed = false;
19050
+ for (const id of records.keys()) if (belongs(id) && !ids.has(id)) {
19051
+ records.delete(id);
19052
+ changed = true;
19053
+ }
19054
+ if (changed) persist();
19055
+ },
19056
+ async observe(p, owned) {
19057
+ var _a, _b, _c, _d;
19058
+ if (owned) return false;
19059
+ let last = records.get(p.id);
19060
+ if (p.agent === "codex") {
19061
+ const fg = await paneForeground(d, p.id, "codex");
19062
+ if (!fg.agent) return false;
19063
+ restored.delete(p.id);
19064
+ const pid = Number(fg.agent.pid);
19065
+ if (last && last.pid === pid && !last.gone && d.now() - last.at < 5e3 && p.agentSession === last.pane.agentSession && p.cwd === last.pane.cwd && p.bornAt === last.pane.bornAt) {
19066
+ last.argv = fg.argv || last.argv;
19067
+ persist();
19068
+ return false;
19069
+ }
19070
+ if (!last || last.pid !== pid || last.gone) {
19071
+ last = { pid, pane: { ...p }, at: d.now(), argv: fg.argv, session: null, conversation: "unknown" };
19072
+ records.set(p.id, last);
19073
+ }
19074
+ last.at = d.now();
19075
+ last.argv = fg.argv || last.argv;
19076
+ last.pane = { id: p.id, workspace: p.workspace, agent: p.agent, agentSession: p.agentSession, bornAt: p.bornAt, cwd: p.cwd, name: p.name, title: p.title };
19077
+ const screen = await read(p.id);
19078
+ const chat = await d.chat(p).catch(() => null);
19079
+ if (chat && (chat.guessed || chat.session && chat.session !== last.session)) {
19080
+ if (chat.session !== last.session) last.conversation = "unknown";
19081
+ last.session = null;
19082
+ }
19083
+ if ((chat == null ? void 0 : chat.available) && !chat.guessed && chat.session) {
19084
+ if (last.session && last.session !== chat.session) last.conversation = "unknown";
19085
+ last.session = chat.session;
19086
+ }
19087
+ if ((_a = chat == null ? void 0 : chat.items) == null ? void 0 : _a.some((i) => i.role === "user" || i.role === "assistant")) {
19088
+ last.conversation = "existing";
19089
+ if (!chat.guessed && chat.session) last.session = chat.session;
19090
+ } else if (chat && last.conversation !== "existing") {
19091
+ const startup = /(?:✨\s*)?Update available!|^Updating Codex via /m.test(screen);
19092
+ const witnessedBirth = Boolean(p.bornAt) && !((_b = fg.argv) == null ? void 0 : _b.some((a) => a === "resume" || a === "fork"));
19093
+ if (chat.available && !chat.guessed && !chat.start && !((_c = chat.items) == null ? void 0 : _c.length) || !p.agentSession && !chat.available && (startup || witnessedBirth)) last.conversation = "empty";
19094
+ }
19095
+ last.oldOutput = Boolean(updateShellSignature(screen));
19096
+ persist();
19097
+ return false;
19098
+ }
19099
+ if (!last) return false;
19100
+ if (p.agent) {
19101
+ records.delete(p.id);
19102
+ persist();
19103
+ return false;
19104
+ }
19105
+ if (!last.gone) {
19106
+ if (d.now() - last.at > OUTAGE_MS + (restored.has(p.id) ? AT_SAVE_MS : 0)) last.checked = true;
19107
+ last.gone = d.now();
19108
+ persist();
19109
+ }
19110
+ if (!last.checked) {
19111
+ if (d.now() - last.gone < 3e3) {
19112
+ p.leaving = true;
19113
+ return false;
19114
+ }
19115
+ last.checked = true;
19116
+ if (d.now() - last.gone < 15e3 && !last.oldOutput && (await paneForeground(d, p.id, "codex")).atShell) {
19117
+ last.signature = updateShellSignature(await read(p.id)) || void 0;
19118
+ if (last.signature) {
19119
+ const chat = await d.chat(last.pane).catch(() => null);
19120
+ if (!chat || chat.guessed || !chat.available && last.session) {
19121
+ if (last.conversation === "empty") last.conversation = "unknown";
19122
+ }
19123
+ if (chat && (chat.guessed || chat.session && chat.session !== last.session)) last.session = null;
19124
+ if ((chat == null ? void 0 : chat.available) && !chat.guessed && chat.session) last.session = chat.session;
19125
+ if ((_d = chat == null ? void 0 : chat.items) == null ? void 0 : _d.some((i) => i.role === "user" || i.role === "assistant")) {
19126
+ last.conversation = "existing";
19127
+ if (!chat.guessed && chat.session) last.session = chat.session;
19128
+ else if (chat.session !== last.session) last.session = null;
19129
+ }
19130
+ }
19131
+ }
19132
+ persist();
19133
+ }
19134
+ if (!last.signature) return false;
19135
+ p.agent = "codex";
19136
+ p.name = last.pane.name;
19137
+ p.title = last.pane.title;
19138
+ p.agentSession = last.session;
19139
+ p.bornAt = last.pane.bornAt;
19140
+ p.status = "blocked";
19141
+ p.stopped = { reason: "update" };
19142
+ p.prompt = updatePrompt(last);
19143
+ return true;
19144
+ },
19145
+ async check(id) {
19146
+ const last = records.get(id);
19147
+ if (!(last == null ? void 0 : last.signature) || !(await paneForeground(d, id, "codex")).atShell) return null;
19148
+ return updateShellSignature(await read(id)) === last.signature ? last : null;
19149
+ }
19150
+ };
19151
+ }
19152
+
18119
19153
  var _a, _b;
18120
19154
  const fsp$1 = fs.promises;
18121
19155
  function trFor(p) {
@@ -18162,21 +19196,54 @@ function watchScreen(paneId, ms = 6e4) {
18162
19196
  screenWatch.set(paneId, Date.now() + ms);
18163
19197
  choicesCache.delete(paneId);
18164
19198
  }
18165
- const choicesCache = /* @__PURE__ */ new Map();
19199
+ const choicesCache = new ScreenCache();
18166
19200
  const askChecks = /* @__PURE__ */ new Map();
19201
+ const choicesPending = /* @__PURE__ */ new Map();
18167
19202
  async function choicesFor(p, rev, strict, watch = false) {
19203
+ const key = JSON.stringify([rev, strict, p.agent, p.agentSession]);
19204
+ const active = choicesPending.get(p.id);
19205
+ if ((active == null ? void 0 : active.key) === key && active.generation === choicesCache.version(p.id)) return active.reading;
19206
+ const reading = readChoices(p, rev, strict, watch);
19207
+ const entry = { key, reading, generation: choicesCache.version(p.id) };
19208
+ choicesPending.set(p.id, entry);
19209
+ try {
19210
+ return await reading;
19211
+ } finally {
19212
+ if (choicesPending.get(p.id) === entry) choicesPending.delete(p.id);
19213
+ }
19214
+ }
19215
+ async function readChoices(p, rev, strict, watch = false) {
19216
+ if (modelControlBusy(p.id)) {
19217
+ choicesCache.delete(p.id);
19218
+ return { choices: null, screen: null, menu: null, interaction: "managed" };
19219
+ }
18168
19220
  const c = choicesCache.get(p.id);
18169
19221
  const watched = (screenWatch.get(p.id) || 0) > Date.now();
18170
19222
  if (!watched) screenWatch.delete(p.id);
18171
- if (c && keepReading(c, rev, strict, watch || watched, Date.now())) return c;
19223
+ if (c && !(p.status === "unknown" && c.interaction === "terminal") && keepReading(c, rev, strict, watch || watched, Date.now(), isViewed(p.id))) return c;
19224
+ choicesCache.invalidate(p.id);
19225
+ const generation = choicesCache.version(p.id);
19226
+ const unavailable = (previous = choicesCache.previous(p.id)) => previous ? {
19227
+ ...previous,
19228
+ unavailable: true,
19229
+ choices: previous.choices ? { ...previous.choices, unavailable: true } : null,
19230
+ screen: previous.screen ? { ...previous.screen, unavailable: true } : null,
19231
+ menu: previous.menu ? { ...previous.menu, unavailable: true } : null
19232
+ } : { choices: null, screen: null, menu: null, interaction: "unknown", unavailable: true };
18172
19233
  let out;
18173
19234
  try {
18174
19235
  const r = await herdr("pane.read", { pane_id: p.id, source: "detection" }, 4e3);
18175
19236
  const text = r.read && r.read.text;
18176
19237
  const framed = String(text || "").split("\n").some((l) => TOP.test(l));
18177
- let choices = p.agent === "omp" ? parseOmpPrompt(text) : parseChoices(text, { strict });
18178
- const menu = p.agent !== "omp" && framed && (strict || !choices || !parseChoices(text, { strict: true })) ? await readMenu(p.id) : null;
18179
- if (menu) choices = null;
19238
+ const usageLimit = p.status === "unknown" ? null : parseUsageLimit(String(text || ""), p.agent);
19239
+ let choices = usageLimit ? null : p.agent === "omp" ? parseOmpPrompt(text) : parseChoices(text, { strict });
19240
+ if (choices) choices.identity = promptIdentity(text, p.agent);
19241
+ const menu = !usageLimit && p.agent !== "omp" && framed && (strict || !choices || !parseChoices(text, { strict: true })) ? await readMenu(p.id) : null;
19242
+ if (menu) {
19243
+ menu.identity = menuIdentity(menu);
19244
+ for (const item of menu.items) item.identity = menuIdentity(menu, item);
19245
+ choices = null;
19246
+ }
18180
19247
  if (choices && p.agent === "omp" && !choices.detail) choices = await withOmpTab(p.id, completeOmpAsk(choices, await transcripts.pendingAsk(p).catch(() => [])));
18181
19248
  if (choices && p.agent === "claude") {
18182
19249
  const checks = askChecks.get(p.id) || /* @__PURE__ */ new Map();
@@ -18184,7 +19251,10 @@ async function choicesFor(p, rev, strict, watch = false) {
18184
19251
  choices = completeClaudeAsk(choices, await transcripts.pendingClaudeQuestions(p).catch(() => []), checks);
18185
19252
  } else if (!choices) askChecks.delete(p.id);
18186
19253
  const settings = p.agent === "claude" && settingsTabs(text) !== null;
18187
- out = { choices, screen: menu || settings ? null : parseWaitScreen(text, { choices: Boolean(choices) }), menu };
19254
+ const screen = menu || settings ? null : parseWaitScreen(text, { choices: Boolean(choices) });
19255
+ if (screen) screen.identity = waitIdentity(screen);
19256
+ const interaction = classifyScreen({ text: String(text || ""), agent: p.agent, choices, menu, screen, settings, status: p.status });
19257
+ out = interaction === "terminal" ? { choices: null, screen: null, menu: null, interaction } : { choices, screen: usageLimit ? null : screen, menu, interaction, ...usageLimit ? { usageLimit } : {} };
18188
19258
  noteScreen(p.id, p.agent, text);
18189
19259
  if (choices && (choices.detail || isPermissionQuestion(choices.question))) {
18190
19260
  const named = p.agent === "omp" && choices.detail && choices.detail.tool !== "tool" ? choices.detail.tool : null;
@@ -18194,7 +19264,10 @@ async function choicesFor(p, rev, strict, watch = false) {
18194
19264
  if (p.agent === "omp" && !choices.question && tr) choices.question = `Allow tool: ${tr.tool}`;
18195
19265
  }
18196
19266
  } catch {
18197
- out = { choices: c ? c.choices : null, screen: c ? c.screen : null, menu: c ? c.menu : null };
19267
+ out = unavailable(c || choicesCache.previous(p.id));
19268
+ }
19269
+ if (choicesCache.version(p.id) !== generation) {
19270
+ return choicesCache.get(p.id) || unavailable();
18198
19271
  }
18199
19272
  choicesCache.set(p.id, { rev, strict, at: Date.now(), ...out });
18200
19273
  return out;
@@ -18235,6 +19308,18 @@ function refreshActivity(p) {
18235
19308
  if (((_d = old2 == null ? void 0 : old2.notice) != null ? _d : null) !== notice || ((_e = old2 == null ? void 0 : old2.suggestion) != null ? _e : null) !== (working ? null : suggestion)) setTimeout(poll, 0);
18236
19309
  }).finally(() => activityBusy.delete(p.id));
18237
19310
  }
19311
+ const codexFields = /* @__PURE__ */ new Map();
19312
+ const codexFieldBusy = /* @__PURE__ */ new Set();
19313
+ function refreshCodexField(p) {
19314
+ if (codexFieldBusy.has(p.id)) return;
19315
+ codexFieldBusy.add(p.id);
19316
+ herdr("pane.read", { pane_id: p.id, source: "visible", format: "ansi" }, 4e3).then((r) => codexFieldLine(String(r.read && r.read.text || "")) || "", () => "").then((text) => {
19317
+ const old = codexFields.get(p.id);
19318
+ const seen2 = text && (old == null ? void 0 : old.text) === text ? old.seen + 1 : 1;
19319
+ codexFields.set(p.id, { text, seen: seen2, at: Date.now() });
19320
+ if ((old && old.seen > 1 ? old.text : "") !== (seen2 > 1 ? text : "")) setTimeout(poll, 0);
19321
+ }).finally(() => codexFieldBusy.delete(p.id));
19322
+ }
18238
19323
  const OMP_STATUS_MS = 3e3;
18239
19324
  const ompStatuses = /* @__PURE__ */ new Map();
18240
19325
  const ompStatusBusy = /* @__PURE__ */ new Set();
@@ -18345,7 +19430,7 @@ function addQueued(paneId, text, opts = {}) {
18345
19430
  };
18346
19431
  queued.set(paneId, [...list, e]);
18347
19432
  sent.set(paneId, addSent(sent.get(paneId) || [], e.text, e.at));
18348
- return publicEntry(e);
19433
+ return queuedPasted(publicEntry(e));
18349
19434
  }
18350
19435
  const sent = /* @__PURE__ */ new Map();
18351
19436
  const sentText = (paneId, entry, taken = []) => {
@@ -18366,9 +19451,14 @@ const restarting = (paneId) => {
18366
19451
  return Boolean(r && r.phase !== "failed");
18367
19452
  };
18368
19453
  const GUARD_STATES = /* @__PURE__ */ new Set(["idle", "done", "working"]);
19454
+ const typedFor = (p, text) => p.agent === "claude" ? submittable(text) : text;
18369
19455
  function sendPrompt(p, text) {
18370
19456
  return withPaneLock(p.id, async () => {
18371
- if (p.agent !== "claude" || !GUARD_STATES.has(p.status || "") || isSlashCommand(text)) return agentPrompt(p.id, text);
19457
+ const now = findPane(p.id);
19458
+ if ((now == null ? void 0 : now.stopped) || (now == null ? void 0 : now.leaving)) {
19459
+ throw new HerdrError(isSlashCommand(text) ? "stale" : "no_input", "Restart Codex before sending a command.");
19460
+ }
19461
+ if (p.agent !== "claude" || !GUARD_STATES.has(p.status || "") || isSlashCommand(text) && !p.usageLimit) return agentPrompt(p.id, typedFor(p, text));
18372
19462
  const keep = (texts) => {
18373
19463
  for (const t of texts || []) {
18374
19464
  addQueued(p.id, t, { held: true });
@@ -18405,7 +19495,7 @@ const isBusyError = (e) => e instanceof HerdrError && (e.code === "input_busy" |
18405
19495
  const deliverBusy = /* @__PURE__ */ new Set();
18406
19496
  function deliverHeld(p) {
18407
19497
  const q = nextHeld(queued.get(p.id) || []);
18408
- if (!q || deliverBusy.has(p.id) || !p.agent || !INPUT_STATES.has(p.status || "") || restarting(p.id)) return;
19498
+ if (!q || deliverBusy.has(p.id) || !p.agent || p.stopped || !INPUT_STATES.has(p.status || "") || restarting(p.id)) return;
18409
19499
  deliverBusy.add(p.id);
18410
19500
  herdr("pane.read", { pane_id: p.id, source: "detection" }, 4e3).then(async (r) => {
18411
19501
  if (!inputVisible(r.read && r.read.text) || !q.held || q.failed) return;
@@ -18476,13 +19566,14 @@ function retryQueued(paneId, id) {
18476
19566
  q.failed = false;
18477
19567
  q.held = true;
18478
19568
  q.at = Date.now();
19569
+ delete q.back;
18479
19570
  delete q.busy;
18480
19571
  delete q.readySince;
18481
19572
  delete q.turnSeen;
18482
19573
  delete q.stuckSince;
18483
19574
  delete q.noInput;
18484
19575
  setTimeout(poll, 50);
18485
- return publicEntry(q);
19576
+ return queuedPasted(publicEntry(q));
18486
19577
  }
18487
19578
  const reconcileBusy = /* @__PURE__ */ new Set();
18488
19579
  function reconcileQueued(p) {
@@ -18502,7 +19593,7 @@ async function deliveryDone(paneId) {
18502
19593
  }
18503
19594
  async function cancelQueued(paneId, text, id) {
18504
19595
  const p = findPane(paneId);
18505
- if (!p || !p.agent) throw new HerdrError("not_found", "agent not found");
19596
+ if (!p) throw new HerdrError("not_found", "agent not found");
18506
19597
  let mine = findQueued(queued.get(p.id) || [], text, id);
18507
19598
  if (mine && (mine.held || mine.failed) && deliverBusy.has(p.id)) {
18508
19599
  await deliveryDone(p.id);
@@ -18518,6 +19609,7 @@ async function cancelQueued(paneId, text, id) {
18518
19609
  setTimeout(poll, 50);
18519
19610
  return { text: mine.text };
18520
19611
  }
19612
+ if (!p.agent) throw new HerdrError("not_found", "agent not found");
18521
19613
  const pend = pendingPrompts.get(p.id);
18522
19614
  if (pend && !pendingBusy.has(p.id) && sameMsg(msgText(pend.text), msgText(text))) {
18523
19615
  pendingPrompts.delete(p.id);
@@ -18543,7 +19635,7 @@ async function cancelQueued(paneId, text, id) {
18543
19635
  const r2 = await transcripts.chat(p, {});
18544
19636
  return { queue: r2.queue || [], items: r2.items || [] };
18545
19637
  },
18546
- prompt: (t) => agentPrompt(p.id, t),
19638
+ prompt: (t) => agentPrompt(p.id, submittable(t)),
18547
19639
  sleep: sleep$1,
18548
19640
  original: (e) => {
18549
19641
  var _a2, _b2;
@@ -18576,6 +19668,41 @@ const pendingBusy = /* @__PURE__ */ new Set();
18576
19668
  const READY = /* @__PURE__ */ new Set(["done", "idle"]);
18577
19669
  const TURN = /* @__PURE__ */ new Set(["working", "blocked"]);
18578
19670
  const restarts = /* @__PURE__ */ new Map();
19671
+ const LAST_AGENTS_FILE = path$1.join(DATA_DIR, "last-agents.json");
19672
+ let lastAgentsWrite = Promise.resolve();
19673
+ const selfUpdates = createSelfUpdates({
19674
+ call: herdr,
19675
+ sleep: sleep$1,
19676
+ now: Date.now,
19677
+ chat: (p) => transcripts.chat(p, { fresh: true }),
19678
+ // Only called when a record changed (see agentSelfUpdate.ts).
19679
+ save: (records, sync) => {
19680
+ const s = JSON.stringify(records) + "\n";
19681
+ if (sync) {
19682
+ try {
19683
+ fs.mkdirSync(DATA_DIR, { recursive: true });
19684
+ fs.writeFileSync(LAST_AGENTS_FILE, s, { mode: 384 });
19685
+ } catch {
19686
+ }
19687
+ return;
19688
+ }
19689
+ lastAgentsWrite = lastAgentsWrite.then(async () => {
19690
+ await fsp$1.mkdir(DATA_DIR, { recursive: true });
19691
+ await fsp$1.writeFile(LAST_AGENTS_FILE, s, { mode: 384 });
19692
+ }).catch(() => {
19693
+ });
19694
+ }
19695
+ }, (() => {
19696
+ try {
19697
+ return JSON.parse(fs.readFileSync(LAST_AGENTS_FILE, "utf8"));
19698
+ } catch {
19699
+ return [];
19700
+ }
19701
+ })());
19702
+ function dismissStopped(paneId) {
19703
+ selfUpdates.clear(paneId);
19704
+ giveBackHeld(queued.get(paneId));
19705
+ }
18579
19706
  function flushPending(p) {
18580
19707
  const pend = pendingPrompts.get(p.id);
18581
19708
  if (!pend || pendingBusy.has(p.id)) return;
@@ -18586,7 +19713,7 @@ function flushPending(p) {
18586
19713
  }
18587
19714
  if (!p.agent || !READY.has(p.status || "")) return;
18588
19715
  pendingBusy.add(p.id);
18589
- withPaneLock(p.id, () => agentPrompt(p.id, pend.text)).then(() => {
19716
+ withPaneLock(p.id, () => agentPrompt(p.id, typedFor(p, pend.text))).then(() => {
18590
19717
  pendingPrompts.delete(p.id);
18591
19718
  log(`initial prompt ${p.id} sent`);
18592
19719
  }).catch((e) => {
@@ -18672,11 +19799,12 @@ function paneCommand(id) {
18672
19799
  }
18673
19800
  return (c == null ? void 0 : c.cmd) || "";
18674
19801
  }
18675
- async function enrich(next, snap, machine) {
18676
- var _a2, _b2, _c;
19802
+ async function enrich(next, snap, machine, publish) {
19803
+ var _a2, _b2;
18677
19804
  const firstSnapshot = !seenMachines.has(machine);
18678
19805
  const prevStatus = new Map((((_a2 = mstates.get(machine)) == null ? void 0 : _a2.panes) || []).map((p) => [p.id, p.status || void 0]));
18679
19806
  const live = new Set(next.panes.map((p) => p.id));
19807
+ selfUpdates.prune(live, (id) => machineOf(id) === machine);
18680
19808
  for (const id of commands.keys()) if (machineOf(id) === machine && !live.has(id)) commands.delete(id);
18681
19809
  for (const p of next.panes) {
18682
19810
  const b = agentBorn.get(p.id);
@@ -18701,7 +19829,15 @@ async function enrich(next, snap, machine) {
18701
19829
  seenMachines.add(machine);
18702
19830
  (_b2 = getMachine(machine)) == null ? void 0 : _b2.transcripts.observe(next.panes);
18703
19831
  const revs = new Map((snap.panes || []).map((p) => [joinId(machine, p.pane_id), p.revision]));
18704
- for (const p of next.panes) {
19832
+ const exited = await Promise.all(next.panes.map((p) => selfUpdates.observe(p, restarts.has(p.id)).catch(() => false)));
19833
+ await mapScreenPanes(next.panes, machine, async (p, i) => {
19834
+ var _a3;
19835
+ if (exited[i]) {
19836
+ p.interaction = "managed";
19837
+ if (queued.has(p.id)) p.queued = queued.get(p.id).map((q) => queuedPasted(publicEntry(q)));
19838
+ return;
19839
+ }
19840
+ if (leftForGood(p, findPane(p.id))) giveBackHeld(queued.get(p.id));
18705
19841
  if (pendingPrompts.has(p.id)) {
18706
19842
  p.pendingPrompt = true;
18707
19843
  flushPending(p);
@@ -18709,20 +19845,20 @@ async function enrich(next, snap, machine) {
18709
19845
  if (queued.has(p.id)) {
18710
19846
  reconcileQueued(p);
18711
19847
  const before = findPane(p.id);
18712
- const run = p.agent === "omp" ? (_c = ompStatuses.get(p.id)) == null ? void 0 : _c.shell : null;
19848
+ const run = p.agent === "omp" ? (_a3 = ompStatuses.get(p.id)) == null ? void 0 : _a3.shell : null;
18713
19849
  if (run) {
18714
19850
  const left = queued.get(p.id).filter((q) => q.held || q.failed || !ompRunShown(p.agent, q.text, run));
18715
19851
  if (left.length) queued.set(p.id, left);
18716
19852
  else queued.delete(p.id);
18717
19853
  }
18718
19854
  const list = queued.get(p.id);
18719
- const menu = Boolean(before && (before.menu || before.prompt || before.screen)) || restarting(p.id);
19855
+ const menu = Boolean(before && (before.menu || before.prompt || before.screen || before.interaction === "terminal")) || restarting(p.id);
18720
19856
  if (list && TURN.has(p.status || "")) {
18721
19857
  for (const q of list) if (!q.held && !q.failed) q.turnSeen = true;
18722
19858
  }
18723
19859
  if (list && checkQueue(list, (before == null ? void 0 : before.ompShell) ? "working" : p.status, Date.now(), menu)) log(`message not sent on ${p.id}`);
18724
19860
  if (list) deliverHeld(p);
18725
- if (list && list.length) p.queued = list.map(publicEntry);
19861
+ if (list && list.length) p.queued = list.map((q) => queuedPasted(publicEntry(q)));
18726
19862
  }
18727
19863
  const rs = restarts.get(p.id);
18728
19864
  if (rs && rs.phase === "failed" && (p.agent && rs.stopped || Date.now() - rs.at > 6e5)) restarts.delete(p.id);
@@ -18733,17 +19869,24 @@ async function enrich(next, snap, machine) {
18733
19869
  p.agent = rs.agent;
18734
19870
  p.agentSession = rs.session || null;
18735
19871
  p.status = "unknown";
18736
- continue;
19872
+ return;
18737
19873
  }
18738
19874
  }
18739
- if (!p.agent) continue;
19875
+ if (!p.agent) return;
18740
19876
  if (p.status !== "working") {
18741
19877
  const young = !p.agentSession || p.bornAt && Date.now() - p.bornAt < 12e4;
18742
19878
  const c = await choicesFor(p, revs.get(p.id), p.status !== "blocked", Boolean(young));
19879
+ screenVersions.set(p, choicesCache.version(p.id));
19880
+ p.interaction = c.interaction;
19881
+ if (c.usageLimit) {
19882
+ p.usageLimit = c.usageLimit;
19883
+ p.status = "idle";
19884
+ }
18743
19885
  if (c.choices) p.prompt = c.choices;
18744
19886
  if (c.screen) p.screen = c.screen;
18745
19887
  if (c.menu) p.menu = c.menu;
18746
19888
  } else {
19889
+ p.interaction = "working";
18747
19890
  choicesCache.delete(p.id);
18748
19891
  askChecks.delete(p.id);
18749
19892
  }
@@ -18775,9 +19918,14 @@ async function enrich(next, snap, machine) {
18775
19918
  const c = codexStatus.statusOf(p);
18776
19919
  if (c) p.codexStatus = c;
18777
19920
  } else codexStatus.forget(p.id);
18778
- }
19921
+ if (p.agent === "codex" && isViewed(p.id) && (p.status === "idle" || p.status === "done") && !p.prompt && !p.menu && !p.restart) {
19922
+ const f = codexFields.get(p.id);
19923
+ if (!f || Date.now() - f.at >= NOTICE_MS) refreshCodexField(p);
19924
+ if (f && f.text && f.seen > 1) p.codexField = f.text;
19925
+ } else codexFields.delete(p.id);
19926
+ }, (p) => isViewed(p.id), publish);
18779
19927
  const alive = (id) => machineOf(id) !== machine || next.panes.some((p) => p.id === id);
18780
- for (const id of choicesCache.keys()) if (!alive(id)) choicesCache.delete(id);
19928
+ for (const id of choicesCache.ids()) if (!alive(id)) choicesCache.forget(id);
18781
19929
  for (const id of askChecks.keys()) if (!alive(id)) askChecks.delete(id);
18782
19930
  for (const id of pendingPrompts.keys()) if (!alive(id)) pendingPrompts.delete(id);
18783
19931
  for (const id of queued.keys()) if (!alive(id)) queued.delete(id);
@@ -18803,6 +19951,7 @@ async function enrich(next, snap, machine) {
18803
19951
  forgetModel(id);
18804
19952
  }
18805
19953
  for (const id of activities.keys()) if (!alive(id)) activities.delete(id);
19954
+ for (const id of codexFields.keys()) if (!alive(id)) codexFields.delete(id);
18806
19955
  }
18807
19956
  const stateListeners = /* @__PURE__ */ new Set();
18808
19957
  function onStateChange(fn) {
@@ -18867,19 +20016,83 @@ function isReady() {
18867
20016
  return ready;
18868
20017
  }
18869
20018
  (_b = (_a = setTimeout(rebuild, READY_MAX_MS + 100)).unref) == null ? void 0 : _b.call(_a);
20019
+ const screenVersions = /* @__PURE__ */ new WeakMap();
20020
+ const viewedBusy = /* @__PURE__ */ new Set();
20021
+ function nativeViewed(p) {
20022
+ return Boolean(p.agent && !p.stopped && !p.leaving && p.status !== "working" && isViewed(p.id) && (p.prompt || p.screen || p.menu || p.interaction === "terminal" || p.status === "blocked" && !p.usageLimit));
20023
+ }
20024
+ function screenMachine(key) {
20025
+ const m = getMachine(key);
20026
+ return Boolean(m && (m.local || m.status === "online"));
20027
+ }
20028
+ function focusScreenGate() {
20029
+ screenRpcGate.priority = (machine, pane) => typeof pane === "string" && isViewed(joinId(machine, pane));
20030
+ screenRpcGate.reserved = (machine) => [...mstates].some(([key, s]) => (machine === void 0 || key === machine) && screenMachine(key) && s.ok && s.panes.some(nativeViewed));
20031
+ }
20032
+ function screenFields(p) {
20033
+ return { prompt: p.prompt, screen: p.screen, menu: p.menu, interaction: p.interaction, usageLimit: p.usageLimit };
20034
+ }
20035
+ function refreshNativeScreen(pane) {
20036
+ choicesCache.delete(pane);
20037
+ viewedBusy.delete(pane);
20038
+ pollViewed();
20039
+ }
20040
+ function pollViewed() {
20041
+ for (const [machine, s] of mstates) for (const p of s.panes) {
20042
+ const cached = choicesCache.previous(p.id);
20043
+ if (!screenMachine(machine) || !s.ok || !nativeViewed(p) || viewedBusy.has(p.id) || !cached || choicesCache.has(p.id) && keepReading(cached, cached.rev, cached.strict, false, Date.now(), true)) continue;
20044
+ viewedBusy.add(p.id);
20045
+ const reading = choicesFor(p, cached.rev, cached.strict);
20046
+ const generation = choicesCache.version(p.id);
20047
+ void reading.then((c) => {
20048
+ const current = mstates.get(machine);
20049
+ const latest = current == null ? void 0 : current.panes.find((x) => x.id === p.id);
20050
+ if (stopped || !screenMachine(machine) || !(current == null ? void 0 : current.ok) || !latest || !nativeViewed(latest) || latest.agent !== p.agent || latest.agentSession !== p.agentSession || choicesCache.version(p.id) !== generation) return;
20051
+ choicesCache.invalidate(p.id);
20052
+ const fresh = {
20053
+ ...latest,
20054
+ prompt: c.choices || void 0,
20055
+ screen: c.screen || void 0,
20056
+ menu: c.menu || void 0,
20057
+ interaction: c.interaction,
20058
+ usageLimit: c.usageLimit
20059
+ };
20060
+ if (c.usageLimit) fresh.status = "idle";
20061
+ mstates.set(machine, { ...current, panes: current.panes.map((x) => x.id === p.id ? fresh : x) });
20062
+ rebuild();
20063
+ }).catch(() => {
20064
+ }).finally(() => {
20065
+ var _a2, _b2;
20066
+ (_b2 = (_a2 = setTimeout(() => viewedBusy.delete(p.id), CHOICE_MS)).unref) == null ? void 0 : _b2.call(_a2);
20067
+ });
20068
+ }
20069
+ }
18870
20070
  async function pollMachine(m) {
20071
+ var _a2;
18871
20072
  const prev = mstates.get(m.key);
18872
20073
  let next;
18873
20074
  try {
18874
20075
  const r = await herdrOn(m.key, "session.snapshot", {}, 5e3);
18875
20076
  const snap = r.snapshot || r;
18876
20077
  next = reduceSnapshot(snap, m.key, HERDR_SESSION || "default");
18877
- await enrich(next, snap, m.key);
20078
+ await enrich(next, snap, m.key, (pane) => {
20079
+ var _a3;
20080
+ if (!getMachine(m.key)) return;
20081
+ const published = new Map((_a3 = mstates.get(m.key)) == null ? void 0 : _a3.panes.map((p) => [p.id, p]));
20082
+ mstates.set(m.key, { ...next, panes: next.panes.map((p) => p.id === pane.id ? { ...pane } : published.get(p.id) || { ...p }) });
20083
+ rebuild();
20084
+ });
20085
+ const current = new Map((_a2 = mstates.get(m.key)) == null ? void 0 : _a2.panes.map((p) => [p.id, p]));
20086
+ for (const p of next.panes) {
20087
+ const latest = current.get(p.id);
20088
+ if (latest && screenVersions.has(p) && screenVersions.get(p) !== choicesCache.version(p.id) && latest.agent === p.agent && latest.agentSession === p.agentSession && p.status !== "working") Object.assign(p, screenFields(latest), latest.usageLimit ? { status: "idle" } : {});
20089
+ }
18878
20090
  if (m instanceof RemoteMachine) m.reportPoll(true);
18879
20091
  } catch (e) {
18880
20092
  const error = e.message;
18881
20093
  if (m instanceof RemoteMachine) m.reportPoll(false, error);
18882
- next = m.local || !prev ? { ok: false, error, workspaces: [], panes: [] } : { ...prev, ok: false, error };
20094
+ const latest = mstates.get(m.key);
20095
+ next = m.local || !latest ? { ok: false, error, workspaces: [], panes: [] } : { ...latest, ok: false, error };
18883
20096
  }
18884
20097
  if (!getMachine(m.key)) return;
18885
20098
  mstates.set(m.key, next);
@@ -18913,8 +20126,17 @@ async function poll() {
18913
20126
  }
18914
20127
  let pollTimer = null;
18915
20128
  let stopped = false;
20129
+ let viewedTimer = null;
18916
20130
  function startPolling() {
18917
20131
  stopped = false;
20132
+ focusScreenGate();
20133
+ if (viewedTimer) clearTimeout(viewedTimer);
20134
+ const views = () => {
20135
+ if (stopped) return;
20136
+ pollViewed();
20137
+ viewedTimer = setTimeout(views, 250);
20138
+ };
20139
+ views();
18918
20140
  const loop = () => {
18919
20141
  const ms = allMachines();
18920
20142
  for (const m of ms) if (m.key !== LOCAL && m.status === "online" && !inflight.has(m.key)) pollOne(m);
@@ -18928,14 +20150,18 @@ const localMachineOf = (ms) => ms.find((m) => m.local);
18928
20150
  function stopPolling() {
18929
20151
  stopped = true;
18930
20152
  if (pollTimer) clearTimeout(pollTimer);
20153
+ if (viewedTimer) clearTimeout(viewedTimer);
20154
+ selfUpdates.flush();
18931
20155
  }
18932
20156
  const notifyTimers = /* @__PURE__ */ new Map();
18933
20157
  function watchTransitions(prev, next) {
20158
+ var _a2;
18934
20159
  const before = new Map(prev.panes.map((p) => [p.id, p.status]));
18935
20160
  for (const p of next.panes) {
18936
20161
  const was = before.get(p.id);
18937
- if (!p.agent || was === p.status) continue;
18938
- if (was === "working" && (p.status === "blocked" || READY.has(p.status || ""))) {
20162
+ const updated = p.stopped && !((_a2 = prev.panes.find((x) => x.id === p.id)) == null ? void 0 : _a2.stopped);
20163
+ if (!p.agent || was === p.status && !updated) continue;
20164
+ if (updated || was === "working" && (p.status === "blocked" || READY.has(p.status || ""))) {
18939
20165
  clearTimeout(notifyTimers.get(p.id));
18940
20166
  const target = p.status;
18941
20167
  notifyTimers.set(p.id, setTimeout(() => {
@@ -19737,13 +20963,25 @@ function hostAllowed(host, names = allowedHosts()) {
19737
20963
  function hostRefusalIsHtml(path, accept) {
19738
20964
  return !path.startsWith("/api/") && /\btext\/html\b/i.test(Array.isArray(accept) ? accept.join(",") : accept || "");
19739
20965
  }
19740
- function phoneFixCommand(install = process.env.WHERDR_INSTALL || "") {
19741
- if (install === "brew" || install === "npm-global") return "wherdr phone";
20966
+ const CLI_DEFAULT_PORT = "7683";
20967
+ function phoneFixCommand(install = process.env.WHERDR_INSTALL || "", port = process.env.NITRO_PORT || process.env.PORT || "") {
19742
20968
  if (install === "docker" || install === "docker-build" || install === "plugin") return "curl -fsSL https://wherdr.dev/install | sh";
19743
- return "npx wherdr phone";
20969
+ const command = install === "brew" || install === "npm-global" ? "wherdr phone" : "npx wherdr phone";
20970
+ return /^\d+$/.test(port) && port !== CLI_DEFAULT_PORT ? `${command} --port ${port}` : command;
19744
20971
  }
19745
- function hostRefusedPage(install) {
19746
- const command = phoneFixCommand(install);
20972
+ function tailnetName(host) {
20973
+ return /\.ts\.net$/.test(hostname(host || "") || "");
20974
+ }
20975
+ function hostRefusedPage(install, host, port) {
20976
+ var _a;
20977
+ const kind = (_a = process.env.WHERDR_INSTALL) != null ? _a : "";
20978
+ const command = phoneFixCommand(kind, port);
20979
+ const docker = kind === "docker" || kind === "docker-build";
20980
+ const where = docker ? "in the container's environment" : "in <code>~/wherdr/wherdr.env</code>";
20981
+ const whereFr = docker ? "dans l\u2019environnement du conteneur" : "dans <code>~/wherdr/wherdr.env</code>";
20982
+ const other = !tailnetName(host);
20983
+ const serve = other ? "If you reach wherdr through <code>tailscale serve</code>, wherdr enables that address by itself." : "wherdr enables by itself the address <code>tailscale serve</code> publishes for it.";
20984
+ const serveFr = other ? "Si tu passes par <code>tailscale serve</code>, wherdr active cette adresse tout seul." : "wherdr active tout seul l\u2019adresse que <code>tailscale serve</code> publie pour lui.";
19747
20985
  return `<!doctype html>
19748
20986
  <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
19749
20987
  <meta name="robots" content="noindex"><title>wherdr \xB7 address not enabled</title>
@@ -19753,18 +20991,20 @@ body{margin:0;min-height:100vh;display:grid;place-items:center;background:#0d0f1
19753
20991
  main{max-width:480px;border:1px solid #3a3f47;padding:24px}
19754
20992
  .tag{font:11px/1 "JetBrains Mono",ui-monospace,monospace;letter-spacing:.08em;text-transform:uppercase;color:#9aa0a8;margin:0 0 16px}
19755
20993
  h1{font:600 20px/1.25 Archivo,system-ui,sans-serif;margin:0 0 8px}
19756
- p{margin:0 0 12px}hr{border:0;border-top:1px solid #3a3f47;margin:20px 0}
19757
- code{font:13px/1.45 "JetBrains Mono",ui-monospace,monospace}
20994
+ p{margin:0 0 12px}pre+p{margin-top:16px}p:last-child{margin-bottom:0}hr{border:0;border-top:1px solid #3a3f47;margin:20px 0}
20995
+ code{font:13px/1.45 "JetBrains Mono",ui-monospace,monospace;overflow-wrap:anywhere}
19758
20996
  pre{margin:0;padding:10px 12px;border:1px solid #3a3f47;background:#15181d;white-space:pre-wrap;overflow-wrap:anywhere;user-select:all;-webkit-user-select:all}
19759
20997
  </style></head><body><main>
19760
20998
  <p class="tag">wherdr \xB7 403</p>
19761
20999
  <h1>This address isn't enabled yet.</h1>
19762
- <p>wherdr enables by itself the address <code>tailscale serve</code> publishes for it. On the machine that runs wherdr, run this, then reload:</p>
19763
- <pre><code>${command}</code></pre>
21000
+ <p>${serve} On the machine that runs wherdr, run this, then reload:</p>
21001
+ <pre><code>${command}</code></pre>${other ? `
21002
+ <p>For any other private name or IP address, add it to <code>HERDR_WEB_ALLOWED_HOSTS</code> (comma-separated) ${where}, then restart wherdr.</p>` : ""}
19764
21003
  <hr>
19765
21004
  <h1 lang="fr">Cette adresse n\u2019est pas encore activ\xE9e.</h1>
19766
- <p lang="fr">wherdr active tout seul l\u2019adresse que <code>tailscale serve</code> publie pour lui. Sur la machine qui fait tourner wherdr, lance ceci, puis recharge :</p>
19767
- <pre><code>${command}</code></pre>
21005
+ <p lang="fr">${serveFr} Sur la machine qui fait tourner wherdr, lance ceci, puis recharge :</p>
21006
+ <pre><code>${command}</code></pre>${other ? `
21007
+ <p lang="fr">Pour tout autre nom priv\xE9 ou adresse IP, ajoute-le \xE0 <code>HERDR_WEB_ALLOWED_HOSTS</code> (s\xE9par\xE9s par des virgules) ${whereFr}, puis red\xE9marre wherdr.</p>` : ""}
19768
21008
  </main></body></html>
19769
21009
  `;
19770
21010
  }
@@ -19776,6 +21016,7 @@ function crossSiteRequest(headers) {
19776
21016
  const MAX_SESSION_DAYS = [1, 7, 30, 90, 365];
19777
21017
  const DEFAULT_MAX_SESSION_DAYS = 7;
19778
21018
  const DAY_MS = 24 * 3600 * 1e3;
21019
+ const OVERRUN_MS = 12 * 3600 * 1e3;
19779
21020
  function isMaxSessionDays(v) {
19780
21021
  return MAX_SESSION_DAYS.includes(v);
19781
21022
  }
@@ -19783,8 +21024,8 @@ function isMaxSessionDays(v) {
19783
21024
  var __defProp = Object.defineProperty;
19784
21025
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
19785
21026
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
19786
- const SESSION_MS = 12 * 3600 * 1e3;
19787
- const RENEW_MS = 10 * 60 * 1e3;
21027
+ const COOKIE_MS = Math.max(...MAX_SESSION_DAYS) * DAY_MS + OVERRUN_MS;
21028
+ const LEGACY_SLIDE_MS = 12 * 3600 * 1e3;
19788
21029
  const CHALLENGE_MS = 5 * 60 * 1e3;
19789
21030
  const AUTH_COOKIE = "hw_session";
19790
21031
  const CHALLENGE_COOKIE = "hw_challenge";
@@ -19842,6 +21083,10 @@ function createAuth({ dataDir, log: log2 = () => {
19842
21083
  var _a;
19843
21084
  return ((_a = db.maxSessionDays) != null ? _a : DEFAULT_MAX_SESSION_DAYS) * DAY_MS;
19844
21085
  };
21086
+ const cutAt = (since) => {
21087
+ var _a;
21088
+ return Math.max(since + maxSessionMs(), (_a = db.maxSessionChangedAt) != null ? _a : 0) + OVERRUN_MS;
21089
+ };
19845
21090
  function session(req, now = Date.now()) {
19846
21091
  const v = readCookie(req);
19847
21092
  if (!v) return null;
@@ -19850,9 +21095,9 @@ function createAuth({ dataDir, log: log2 = () => {
19850
21095
  const mac = parts.pop();
19851
21096
  if (!mac || parts[1] !== String(db.generation) || !safeEq(mac, sign(parts.join(".")))) return null;
19852
21097
  const exp = Number(parts[0]);
19853
- const since = parts.length === 3 ? Number(parts[2]) : exp - SESSION_MS;
21098
+ const since = parts.length === 3 ? Number(parts[2]) : exp - LEGACY_SLIDE_MS;
19854
21099
  if (!(exp >= now) || !Number.isFinite(since)) return null;
19855
- if (now > since + maxSessionMs() + SESSION_MS) return null;
21100
+ if (now > cutAt(since)) return null;
19856
21101
  return { exp, since };
19857
21102
  }
19858
21103
  function isUnlocked(req) {
@@ -19860,16 +21105,16 @@ function createAuth({ dataDir, log: log2 = () => {
19860
21105
  }
19861
21106
  const secure = (req) => req.headers["x-forwarded-proto"] === "https" || String(req.headers.origin || "").startsWith("https://") ? "; Secure" : "";
19862
21107
  function sessionCookie(req, now = Date.now(), since = now) {
19863
- const exp = now + SESSION_MS;
21108
+ const exp = since + COOKIE_MS;
19864
21109
  const payload = `${exp}.${db.generation}.${since}`;
19865
- return `${AUTH_COOKIE}=${payload}.${sign(payload)}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${SESSION_MS / 1e3}${secure(req)}`;
21110
+ return `${AUTH_COOKIE}=${payload}.${sign(payload)}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${Math.max(0, Math.floor((exp - now) / 1e3))}${secure(req)}`;
19866
21111
  }
19867
21112
  const clearCookie = (req) => `${AUTH_COOKIE}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0${secure(req)}`;
19868
21113
  function renew(req, now = Date.now()) {
19869
21114
  if (!enabled()) return null;
19870
21115
  const s = session(req, now);
19871
- if (s === null || s.exp - now > SESSION_MS - RENEW_MS) return null;
19872
- return { cookie: sessionCookie(req, now, s.since), expiresAt: now + SESSION_MS };
21116
+ if (s === null || s.exp >= s.since + COOKIE_MS) return null;
21117
+ return { cookie: sessionCookie(req, now, s.since) };
19873
21118
  }
19874
21119
  function relying(req) {
19875
21120
  const origin = String(req.headers.origin || "");
@@ -19974,15 +21219,17 @@ function createAuth({ dataDir, log: log2 = () => {
19974
21219
  log2("lock: all devices locked");
19975
21220
  return { ok: true, __cookie: clearCookie(req) };
19976
21221
  }
19977
- function setMaxSession(req, days) {
21222
+ function setMaxSession(req, days, now = Date.now()) {
21223
+ var _a;
19978
21224
  if (!enabled() || !isUnlocked(req)) throw new AuthError("locked", "Unlock first");
19979
21225
  if (!isMaxSessionDays(days)) throw new AuthError("invalid", "Invalid duration");
21226
+ if (days !== ((_a = db.maxSessionDays) != null ? _a : DEFAULT_MAX_SESSION_DAYS)) db.maxSessionChangedAt = now;
19980
21227
  db.maxSessionDays = days;
19981
21228
  save();
19982
21229
  return { ok: true, maxSessionDays: days };
19983
21230
  }
19984
21231
  function status(req, { resume = false, now = Date.now() } = {}) {
19985
- var _a, _b;
21232
+ var _a;
19986
21233
  const devices = db.credentials.map((c) => ({ name: c.name, createdAt: c.createdAt, lastUsed: c.lastUsed || null }));
19987
21234
  if (!enabled()) return { enabled: false, unlocked: true, devices };
19988
21235
  const s = session(req, now);
@@ -19994,10 +21241,10 @@ function createAuth({ dataDir, log: log2 = () => {
19994
21241
  return {
19995
21242
  enabled: true,
19996
21243
  unlocked: true,
19997
- expiresAt: (_a = renewed == null ? void 0 : renewed.expiresAt) != null ? _a : s.exp,
21244
+ expiresAt: cutAt(s.since),
19998
21245
  deadline,
19999
21246
  now,
20000
- maxSessionDays: (_b = db.maxSessionDays) != null ? _b : DEFAULT_MAX_SESSION_DAYS,
21247
+ maxSessionDays: (_a = db.maxSessionDays) != null ? _a : DEFAULT_MAX_SESSION_DAYS,
20001
21248
  devices,
20002
21249
  ...renewed ? { __cookie: renewed.cookie } : {}
20003
21250
  };
@@ -20356,9 +21603,11 @@ const _mZt23IdRC2vLuqDtWT6mb7m9BgHXq3U5QrnQ7Z5Hc4c = defineNitroPlugin((nitroApp
20356
21603
  startTailnetWatch();
20357
21604
  cleanUploads();
20358
21605
  cleanAttachments();
21606
+ purgePastes();
20359
21607
  const purge = setInterval(() => {
20360
21608
  cleanUploads();
20361
21609
  cleanAttachments();
21610
+ purgePastes();
20362
21611
  }, 6 * 3600 * 1e3);
20363
21612
  log(`herdr-web \u2014 socket ${HERDR_SOCK}${HERDR_SESSION ? ` (session ${HERDR_SESSION})` : ""}`);
20364
21613
  nitroApp.hooks.hook("close", () => {
@@ -20380,394 +21629,422 @@ const assets = {
20380
21629
  "/manifest-en.webmanifest": {
20381
21630
  "type": "application/manifest+json",
20382
21631
  "etag": "\"260-q1JnCK0/ecdKwgeTve6N4I6/mWI\"",
20383
- "mtime": "2026-10-10T00:24:14.956Z",
21632
+ "mtime": "2026-10-17T18:43:41.588Z",
20384
21633
  "size": 608,
20385
21634
  "path": "../public/manifest-en.webmanifest"
20386
21635
  },
20387
21636
  "/manifest.webmanifest": {
20388
21637
  "type": "application/manifest+json",
20389
21638
  "etag": "\"26e-ykoYuj4V8la457yChW3oQTur8RU\"",
20390
- "mtime": "2026-10-10T00:24:14.956Z",
21639
+ "mtime": "2026-10-17T18:43:41.588Z",
20391
21640
  "size": 622,
20392
21641
  "path": "../public/manifest.webmanifest"
20393
21642
  },
20394
21643
  "/sw.js": {
20395
21644
  "type": "text/javascript; charset=utf-8",
20396
- "etag": "\"1b1d-wHdIux7mWagbphlmnadZ+jdW3jQ\"",
20397
- "mtime": "2026-10-10T00:24:15.363Z",
20398
- "size": 6941,
21645
+ "etag": "\"1b75-Ur5BTmn18dE1NVPKM1rpbCIqr9I\"",
21646
+ "mtime": "2026-10-17T18:43:41.990Z",
21647
+ "size": 7029,
20399
21648
  "path": "../public/sw.js"
20400
21649
  },
20401
- "/_nuxt/AgentView.C4YOwvZG.css": {
21650
+ "/_nuxt/AgentView.DzFWBd2A.css": {
20402
21651
  "type": "text/css; charset=utf-8",
20403
- "etag": "\"15c8-yoJUdtWy2mP7U+kxJ717a6Bzxgg\"",
20404
- "mtime": "2026-10-10T00:24:14.946Z",
20405
- "size": 5576,
20406
- "path": "../public/_nuxt/AgentView.C4YOwvZG.css"
21652
+ "etag": "\"16c2-oz6EmjJDgIf6r38fC9pJHsZoJww\"",
21653
+ "mtime": "2026-10-17T18:43:41.582Z",
21654
+ "size": 5826,
21655
+ "path": "../public/_nuxt/AgentView.DzFWBd2A.css"
20407
21656
  },
20408
- "/_nuxt/B7QP1TFs.js": {
21657
+ "/_nuxt/BEJHMUrj.js": {
20409
21658
  "type": "text/javascript; charset=utf-8",
20410
- "etag": "\"1118a-Gc+7ipGEaJc4tPQJbl761DHnbVc\"",
20411
- "mtime": "2026-10-10T00:24:14.946Z",
20412
- "size": 70026,
20413
- "path": "../public/_nuxt/B7QP1TFs.js"
21659
+ "etag": "\"238-y+VfpUOV4FM6ecp7mfl4o0RJzdU\"",
21660
+ "mtime": "2026-10-17T18:43:41.582Z",
21661
+ "size": 568,
21662
+ "path": "../public/_nuxt/BEJHMUrj.js"
21663
+ },
21664
+ "/_nuxt/BOtcEDnA.js": {
21665
+ "type": "text/javascript; charset=utf-8",
21666
+ "etag": "\"1422a-8atYpyuVmn2+Q0/CCOp/ro0wWUY\"",
21667
+ "mtime": "2026-10-17T18:43:41.582Z",
21668
+ "size": 82474,
21669
+ "path": "../public/_nuxt/BOtcEDnA.js"
20414
21670
  },
20415
- "/_nuxt/BDNMzG2s.js": {
21671
+ "/_nuxt/BUaYhQ2r.js": {
20416
21672
  "type": "text/javascript; charset=utf-8",
20417
- "etag": "\"54-MasMfSk/A98C3Gn9uIOxtFxkWNw\"",
20418
- "mtime": "2026-10-10T00:24:14.946Z",
20419
- "size": 84,
20420
- "path": "../public/_nuxt/BDNMzG2s.js"
21673
+ "etag": "\"17edf-GsMnATHB0A2Zdo/vxDga5VMHeKY\"",
21674
+ "mtime": "2026-10-17T18:43:41.582Z",
21675
+ "size": 98015,
21676
+ "path": "../public/_nuxt/BUaYhQ2r.js"
20421
21677
  },
20422
21678
  "/_nuxt/Bd17z0YL.js": {
20423
21679
  "type": "text/javascript; charset=utf-8",
20424
21680
  "etag": "\"1615-CPDn06/EO3pj6KudXz5uMZ0FkhI\"",
20425
- "mtime": "2026-10-10T00:24:14.946Z",
21681
+ "mtime": "2026-10-17T18:43:41.582Z",
20426
21682
  "size": 5653,
20427
21683
  "path": "../public/_nuxt/Bd17z0YL.js"
20428
21684
  },
20429
- "/_nuxt/BOpBIziZ.js": {
21685
+ "/_nuxt/Bpoxvzh6.js": {
20430
21686
  "type": "text/javascript; charset=utf-8",
20431
- "etag": "\"17047-w7HRRR9UP7E4j/0+gMWSMH60Me4\"",
20432
- "mtime": "2026-10-10T00:24:14.946Z",
20433
- "size": 94279,
20434
- "path": "../public/_nuxt/BOpBIziZ.js"
21687
+ "etag": "\"1c49-bXAEhdP8o69g6PbBI2Q4c1IQs2I\"",
21688
+ "mtime": "2026-10-17T18:43:41.582Z",
21689
+ "size": 7241,
21690
+ "path": "../public/_nuxt/Bpoxvzh6.js"
20435
21691
  },
20436
- "/_nuxt/CWwyK2XK.js": {
21692
+ "/_nuxt/C25ROUa9.js": {
20437
21693
  "type": "text/javascript; charset=utf-8",
20438
- "etag": "\"7e5e-4BG2J9cvS3sx6WQ360LFqNaThyA\"",
20439
- "mtime": "2026-10-10T00:24:14.947Z",
20440
- "size": 32350,
20441
- "path": "../public/_nuxt/CWwyK2XK.js"
21694
+ "etag": "\"176b5-t7ykke36hXndVVgSfWGMLAcfqiU\"",
21695
+ "mtime": "2026-10-17T18:43:41.582Z",
21696
+ "size": 95925,
21697
+ "path": "../public/_nuxt/C25ROUa9.js"
20442
21698
  },
20443
- "/_nuxt/CXG-cOdh.js": {
21699
+ "/_nuxt/CJKsMzIp.js": {
20444
21700
  "type": "text/javascript; charset=utf-8",
20445
- "etag": "\"d4e-hM6T4bjr/qfJVvSNRqFH3ePHBQY\"",
20446
- "mtime": "2026-10-10T00:24:14.947Z",
20447
- "size": 3406,
20448
- "path": "../public/_nuxt/CXG-cOdh.js"
21701
+ "etag": "\"10a-RP2xlxe7tKtrIpq0vhVbLQ+p3Ms\"",
21702
+ "mtime": "2026-10-17T18:43:41.582Z",
21703
+ "size": 266,
21704
+ "path": "../public/_nuxt/CJKsMzIp.js"
20449
21705
  },
20450
- "/_nuxt/BWXdFfeg.js": {
21706
+ "/_nuxt/CDWjMk9C.js": {
20451
21707
  "type": "text/javascript; charset=utf-8",
20452
- "etag": "\"39363-ZuVw+u9xjhW/x3aFJmung4q3Pdg\"",
20453
- "mtime": "2026-10-10T00:24:14.946Z",
20454
- "size": 234339,
20455
- "path": "../public/_nuxt/BWXdFfeg.js"
21708
+ "etag": "\"7e5c-4oH4bzjszPo3bZwQbTcPqcxL7Q8\"",
21709
+ "mtime": "2026-10-17T18:43:41.582Z",
21710
+ "size": 32348,
21711
+ "path": "../public/_nuxt/CDWjMk9C.js"
20456
21712
  },
20457
- "/_nuxt/Cd8j9O5w.js": {
21713
+ "/_nuxt/COCvtdHN.js": {
20458
21714
  "type": "text/javascript; charset=utf-8",
20459
- "etag": "\"238-VLnqq4ND3a28No8coqBgt+ad3DA\"",
20460
- "mtime": "2026-10-10T00:24:14.947Z",
20461
- "size": 568,
20462
- "path": "../public/_nuxt/Cd8j9O5w.js"
21715
+ "etag": "\"1bbdd-7o2VS8llXeUhLkFYDucYoVrbDvA\"",
21716
+ "mtime": "2026-10-17T18:43:41.582Z",
21717
+ "size": 113629,
21718
+ "path": "../public/_nuxt/COCvtdHN.js"
20463
21719
  },
20464
- "/_nuxt/COFCNFpG.js": {
21720
+ "/_nuxt/CJNhn9sA.js": {
20465
21721
  "type": "text/javascript; charset=utf-8",
20466
- "etag": "\"16ee4-rnyLLYmsFymH3XyCdaXwcJEEGuQ\"",
20467
- "mtime": "2026-10-10T00:24:14.947Z",
20468
- "size": 93924,
20469
- "path": "../public/_nuxt/COFCNFpG.js"
21722
+ "etag": "\"5bb9e-3d7Nv/IqQ7+jDnfQdGsgkcNQUug\"",
21723
+ "mtime": "2026-10-17T18:43:41.582Z",
21724
+ "size": 375710,
21725
+ "path": "../public/_nuxt/CJNhn9sA.js"
20470
21726
  },
20471
- "/_nuxt/Ci8N4mWR.js": {
21727
+ "/_nuxt/CXJnLmWv.js": {
20472
21728
  "type": "text/javascript; charset=utf-8",
20473
- "etag": "\"2426-fCrTYUyhtdHnTmu6ZJeEttvxVMo\"",
20474
- "mtime": "2026-10-10T00:24:14.947Z",
21729
+ "etag": "\"2426-wVRk+id72MiZ5Jk+fsnfLyJbNcM\"",
21730
+ "mtime": "2026-10-17T18:43:41.582Z",
20475
21731
  "size": 9254,
20476
- "path": "../public/_nuxt/Ci8N4mWR.js"
21732
+ "path": "../public/_nuxt/CXJnLmWv.js"
20477
21733
  },
20478
- "/_nuxt/CkZ8t6uB.js": {
21734
+ "/_nuxt/Cl45J6_Q.js": {
20479
21735
  "type": "text/javascript; charset=utf-8",
20480
- "etag": "\"3743-91mhngVNRfpvaYKVJ/QoYV6yh1A\"",
20481
- "mtime": "2026-10-10T00:24:14.947Z",
20482
- "size": 14147,
20483
- "path": "../public/_nuxt/CkZ8t6uB.js"
21736
+ "etag": "\"d34-0CEgeEL4LpfF/Ngxkc3X1qxVE0Q\"",
21737
+ "mtime": "2026-10-17T18:43:41.583Z",
21738
+ "size": 3380,
21739
+ "path": "../public/_nuxt/Cl45J6_Q.js"
20484
21740
  },
20485
- "/_nuxt/D7sxNXx1.js": {
21741
+ "/_nuxt/CndPDbMI.js": {
20486
21742
  "type": "text/javascript; charset=utf-8",
20487
- "etag": "\"13f-Neu4hxK7KXpqJx1TOH9mlMOz1nI\"",
20488
- "mtime": "2026-10-10T00:24:14.947Z",
20489
- "size": 319,
20490
- "path": "../public/_nuxt/D7sxNXx1.js"
21743
+ "etag": "\"91a2-smpfKh6goGkDUo+YVNYbS5+u/8I\"",
21744
+ "mtime": "2026-10-17T18:43:41.583Z",
21745
+ "size": 37282,
21746
+ "path": "../public/_nuxt/CndPDbMI.js"
20491
21747
  },
20492
- "/_nuxt/DViwOclv.js": {
21748
+ "/_nuxt/Ctbx58Um.js": {
20493
21749
  "type": "text/javascript; charset=utf-8",
20494
- "etag": "\"10a-+H4vdCMSTz83KYVa6X+gWZCDDow\"",
20495
- "mtime": "2026-10-10T00:24:14.947Z",
20496
- "size": 266,
20497
- "path": "../public/_nuxt/DViwOclv.js"
21750
+ "etag": "\"12607-L6r1fjUsRQANn1N6WahQDaJtUHg\"",
21751
+ "mtime": "2026-10-17T18:43:41.583Z",
21752
+ "size": 75271,
21753
+ "path": "../public/_nuxt/Ctbx58Um.js"
20498
21754
  },
20499
- "/_nuxt/DyBZDSCV.js": {
21755
+ "/_nuxt/Dl1PHLOB.js": {
20500
21756
  "type": "text/javascript; charset=utf-8",
20501
- "etag": "\"1f34c-1/LEO6HIPrMJPOnrvbeL2tadMf4\"",
20502
- "mtime": "2026-10-10T00:24:14.947Z",
20503
- "size": 127820,
20504
- "path": "../public/_nuxt/DyBZDSCV.js"
21757
+ "etag": "\"3779-fKEF4Ee4ZpPd5wR0QFWCwmhNG5Q\"",
21758
+ "mtime": "2026-10-17T18:43:41.583Z",
21759
+ "size": 14201,
21760
+ "path": "../public/_nuxt/Dl1PHLOB.js"
20505
21761
  },
20506
- "/_nuxt/DoD7Qb5P.js": {
21762
+ "/_nuxt/Nhex3_iH.js": {
20507
21763
  "type": "text/javascript; charset=utf-8",
20508
- "etag": "\"4c573-s0WTgDKba5SDqDXhmDa67SGcDHk\"",
20509
- "mtime": "2026-10-10T00:24:14.947Z",
20510
- "size": 312691,
20511
- "path": "../public/_nuxt/DoD7Qb5P.js"
20512
- },
20513
- "/_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2": {
20514
- "type": "font/woff2",
20515
- "etag": "\"7f60-cwHN4xD2RhU0GVBfKzpzYZ7Al6U\"",
20516
- "mtime": "2026-10-10T00:24:14.947Z",
20517
- "size": 32608,
20518
- "path": "../public/_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2"
21764
+ "etag": "\"dd3-AX1srF/wSbPRrTQkPY3fqVPLQak\"",
21765
+ "mtime": "2026-10-17T18:43:41.583Z",
21766
+ "size": 3539,
21767
+ "path": "../public/_nuxt/Nhex3_iH.js"
20519
21768
  },
20520
21769
  "/_nuxt/archivo-latin-wght-normal.E0tuGl4L.woff2": {
20521
21770
  "type": "font/woff2",
20522
21771
  "etag": "\"8870-ZUSfFgU3jYpWYbszVY1rxpynehc\"",
20523
- "mtime": "2026-10-10T00:24:14.947Z",
21772
+ "mtime": "2026-10-17T18:43:41.583Z",
20524
21773
  "size": 34928,
20525
21774
  "path": "../public/_nuxt/archivo-latin-wght-normal.E0tuGl4L.woff2"
20526
21775
  },
21776
+ "/_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2": {
21777
+ "type": "font/woff2",
21778
+ "etag": "\"7f60-cwHN4xD2RhU0GVBfKzpzYZ7Al6U\"",
21779
+ "mtime": "2026-10-17T18:43:41.583Z",
21780
+ "size": 32608,
21781
+ "path": "../public/_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2"
21782
+ },
20527
21783
  "/_nuxt/archivo-vietnamese-wght-normal.XAtsl5Q_.woff2": {
20528
21784
  "type": "font/woff2",
20529
21785
  "etag": "\"33b8-4zjQHgOy7y9EDRZs7TDAFDM4Ams\"",
20530
- "mtime": "2026-10-10T00:24:14.947Z",
21786
+ "mtime": "2026-10-17T18:43:41.583Z",
20531
21787
  "size": 13240,
20532
21788
  "path": "../public/_nuxt/archivo-vietnamese-wght-normal.XAtsl5Q_.woff2"
20533
21789
  },
20534
- "/_nuxt/SiL1FJ5s.js": {
20535
- "type": "text/javascript; charset=utf-8",
20536
- "etag": "\"176ad-/hlyeMkW67OV1A4G2nhIsYJX+vE\"",
20537
- "mtime": "2026-10-10T00:24:14.947Z",
20538
- "size": 95917,
20539
- "path": "../public/_nuxt/SiL1FJ5s.js"
20540
- },
20541
- "/_nuxt/D4Yz4rat.js": {
21790
+ "/_nuxt/OpWX45i7.js": {
20542
21791
  "type": "text/javascript; charset=utf-8",
20543
- "etag": "\"16234-4R0MEqvg4VFo319EzlQAELnsvis\"",
20544
- "mtime": "2026-10-10T00:24:14.947Z",
20545
- "size": 90676,
20546
- "path": "../public/_nuxt/D4Yz4rat.js"
21792
+ "etag": "\"47320-mmZKztzMUS0hWTUixNYds+GuxDc\"",
21793
+ "mtime": "2026-10-17T18:43:41.583Z",
21794
+ "size": 291616,
21795
+ "path": "../public/_nuxt/OpWX45i7.js"
20547
21796
  },
20548
- "/_nuxt/8ksjcuDu.js": {
21797
+ "/_nuxt/DMLmW6JM.js": {
20549
21798
  "type": "text/javascript; charset=utf-8",
20550
- "etag": "\"9d965-5D6213Qjb51iD9KHvuiyUPU3qew\"",
20551
- "mtime": "2026-10-10T00:24:14.946Z",
20552
- "size": 645477,
20553
- "path": "../public/_nuxt/8ksjcuDu.js"
21799
+ "etag": "\"a9c14-yjSMqVlge3ipwm5JBRYSl/+v9CU\"",
21800
+ "mtime": "2026-10-17T18:43:41.583Z",
21801
+ "size": 695316,
21802
+ "path": "../public/_nuxt/DMLmW6JM.js"
20554
21803
  },
20555
- "/_nuxt/bLP7Jj-b.js": {
21804
+ "/_nuxt/dTj21DMs.js": {
20556
21805
  "type": "text/javascript; charset=utf-8",
20557
- "etag": "\"eab-MDKLGS0aoyNdipefSjbM7x6w6Y8\"",
20558
- "mtime": "2026-10-10T00:24:14.948Z",
20559
- "size": 3755,
20560
- "path": "../public/_nuxt/bLP7Jj-b.js"
21806
+ "etag": "\"f35-iOGrl+zkV+NSGmABY4upNQrrgWA\"",
21807
+ "mtime": "2026-10-17T18:43:41.583Z",
21808
+ "size": 3893,
21809
+ "path": "../public/_nuxt/dTj21DMs.js"
20561
21810
  },
20562
21811
  "/_nuxt/error-404.Bb87HomL.css": {
20563
21812
  "type": "text/css; charset=utf-8",
20564
21813
  "etag": "\"97d-4h9VfBznldxjqagfMldh1hDncR0\"",
20565
- "mtime": "2026-10-10T00:24:14.948Z",
21814
+ "mtime": "2026-10-17T18:43:41.583Z",
20566
21815
  "size": 2429,
20567
21816
  "path": "../public/_nuxt/error-404.Bb87HomL.css"
20568
21817
  },
20569
21818
  "/_nuxt/error-500.Bwd7zAaE.css": {
20570
21819
  "type": "text/css; charset=utf-8",
20571
21820
  "etag": "\"772-nqXXACYtFiPK+D42BNu4uEECARA\"",
20572
- "mtime": "2026-10-10T00:24:14.948Z",
21821
+ "mtime": "2026-10-17T18:43:41.583Z",
20573
21822
  "size": 1906,
20574
21823
  "path": "../public/_nuxt/error-500.Bwd7zAaE.css"
20575
21824
  },
20576
21825
  "/_nuxt/hePW80VL.js": {
20577
21826
  "type": "text/javascript; charset=utf-8",
20578
21827
  "etag": "\"2cc-fA8td6k29UVF6JoPfhOPkceTK1M\"",
20579
- "mtime": "2026-10-10T00:24:14.948Z",
21828
+ "mtime": "2026-10-17T18:43:41.583Z",
20580
21829
  "size": 716,
20581
21830
  "path": "../public/_nuxt/hePW80VL.js"
20582
21831
  },
20583
- "/_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2": {
20584
- "type": "font/woff2",
20585
- "etag": "\"493c-n3Oy9D6jvzfMjpClqox+Zo7ERQQ\"",
20586
- "mtime": "2026-10-10T00:24:14.948Z",
20587
- "size": 18748,
20588
- "path": "../public/_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2"
20589
- },
20590
21832
  "/_nuxt/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2": {
20591
21833
  "type": "font/woff2",
20592
21834
  "etag": "\"6568-cF1iUGbboMFZ8TfnP5HiMgl9II0\"",
20593
- "mtime": "2026-10-10T00:24:14.948Z",
21835
+ "mtime": "2026-10-17T18:43:41.583Z",
20594
21836
  "size": 25960,
20595
21837
  "path": "../public/_nuxt/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2"
20596
21838
  },
21839
+ "/_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2": {
21840
+ "type": "font/woff2",
21841
+ "etag": "\"493c-n3Oy9D6jvzfMjpClqox+Zo7ERQQ\"",
21842
+ "mtime": "2026-10-17T18:43:41.583Z",
21843
+ "size": 18748,
21844
+ "path": "../public/_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2"
21845
+ },
20597
21846
  "/_nuxt/inter-greek-ext-wght-normal.DlzME5K_.woff2": {
20598
21847
  "type": "font/woff2",
20599
21848
  "etag": "\"2be0-BP5iTzJeB8nLqYAgKpWNi5o1Zm8\"",
20600
- "mtime": "2026-10-10T00:24:14.948Z",
21849
+ "mtime": "2026-10-17T18:43:41.583Z",
20601
21850
  "size": 11232,
20602
21851
  "path": "../public/_nuxt/inter-greek-ext-wght-normal.DlzME5K_.woff2"
20603
21852
  },
20604
- "/_nuxt/entry.Crt1r4l3.css": {
20605
- "type": "text/css; charset=utf-8",
20606
- "etag": "\"60b9f-TZJSjtJYwO9YgW0BvzvwELvXTcA\"",
20607
- "mtime": "2026-10-10T00:24:14.948Z",
20608
- "size": 396191,
20609
- "path": "../public/_nuxt/entry.Crt1r4l3.css"
20610
- },
20611
21853
  "/_nuxt/inter-greek-wght-normal.CkhJZR-_.woff2": {
20612
21854
  "type": "font/woff2",
20613
21855
  "etag": "\"4a34-xor/hj4YNqI52zFecXnUbzQ4Xs4\"",
20614
- "mtime": "2026-10-10T00:24:14.948Z",
21856
+ "mtime": "2026-10-17T18:43:41.583Z",
20615
21857
  "size": 18996,
20616
21858
  "path": "../public/_nuxt/inter-greek-wght-normal.CkhJZR-_.woff2"
20617
21859
  },
20618
- "/_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2": {
20619
- "type": "font/woff2",
20620
- "etag": "\"14c4c-zz61D7IQFMB9QxHvTAOk/Vh4ibQ\"",
20621
- "mtime": "2026-10-10T00:24:14.948Z",
20622
- "size": 85068,
20623
- "path": "../public/_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2"
21860
+ "/_nuxt/entry.BohTWE-n.css": {
21861
+ "type": "text/css; charset=utf-8",
21862
+ "etag": "\"69733-tHHaoNsUa1LrnLzsbMZLwgjFJCc\"",
21863
+ "mtime": "2026-10-17T18:43:41.583Z",
21864
+ "size": 431923,
21865
+ "path": "../public/_nuxt/entry.BohTWE-n.css"
20624
21866
  },
20625
21867
  "/_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2": {
20626
21868
  "type": "font/woff2",
20627
21869
  "etag": "\"bc80-8R1ym7Ck2DUNLqPQ/AYs9u8tUpg\"",
20628
- "mtime": "2026-10-10T00:24:14.948Z",
21870
+ "mtime": "2026-10-17T18:43:41.584Z",
20629
21871
  "size": 48256,
20630
21872
  "path": "../public/_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2"
20631
21873
  },
20632
21874
  "/_nuxt/inter-vietnamese-wght-normal.CBcvBZtf.woff2": {
20633
21875
  "type": "font/woff2",
20634
21876
  "etag": "\"280c-nBythjoDQ0+5wVAendJ6wU7Xz2M\"",
20635
- "mtime": "2026-10-10T00:24:14.948Z",
21877
+ "mtime": "2026-10-17T18:43:41.584Z",
20636
21878
  "size": 10252,
20637
21879
  "path": "../public/_nuxt/inter-vietnamese-wght-normal.CBcvBZtf.woff2"
20638
21880
  },
21881
+ "/_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2": {
21882
+ "type": "font/woff2",
21883
+ "etag": "\"14c4c-zz61D7IQFMB9QxHvTAOk/Vh4ibQ\"",
21884
+ "mtime": "2026-10-17T18:43:41.584Z",
21885
+ "size": 85068,
21886
+ "path": "../public/_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2"
21887
+ },
20639
21888
  "/_nuxt/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2": {
20640
21889
  "type": "font/woff2",
20641
21890
  "etag": "\"2f4c-WiAGfn140d4QND3ayQWaCHF8rbE\"",
20642
- "mtime": "2026-10-10T00:24:14.948Z",
21891
+ "mtime": "2026-10-17T18:43:41.584Z",
20643
21892
  "size": 12108,
20644
21893
  "path": "../public/_nuxt/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2"
20645
21894
  },
20646
21895
  "/_nuxt/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2": {
20647
21896
  "type": "font/woff2",
20648
21897
  "etag": "\"232c-Dnz9DhH4c266e6TziU1pxRkV6FY\"",
20649
- "mtime": "2026-10-10T00:24:14.948Z",
21898
+ "mtime": "2026-10-17T18:43:41.584Z",
20650
21899
  "size": 9004,
20651
21900
  "path": "../public/_nuxt/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2"
20652
21901
  },
20653
- "/_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2": {
20654
- "type": "font/woff2",
20655
- "etag": "\"3b5c-HLF7Wvs2Z1IA1cPRs6jnor8OUQ4\"",
20656
- "mtime": "2026-10-10T00:24:14.949Z",
20657
- "size": 15196,
20658
- "path": "../public/_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2"
20659
- },
20660
21902
  "/_nuxt/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2": {
20661
21903
  "type": "font/woff2",
20662
21904
  "etag": "\"9dd4-5yd+cUUhzrXxdMyYebUeD0qml1M\"",
20663
- "mtime": "2026-10-10T00:24:14.949Z",
21905
+ "mtime": "2026-10-17T18:43:41.584Z",
20664
21906
  "size": 40404,
20665
21907
  "path": "../public/_nuxt/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2"
20666
21908
  },
20667
- "/_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2": {
20668
- "type": "font/woff2",
20669
- "etag": "\"d9b0-kmO/x6KCTFRlVipOvl+5XcArGUw\"",
20670
- "mtime": "2026-10-10T00:24:14.949Z",
20671
- "size": 55728,
20672
- "path": "../public/_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2"
20673
- },
20674
21909
  "/_nuxt/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2": {
20675
21910
  "type": "font/woff2",
20676
21911
  "etag": "\"1d50-/Re0MyD6BV8h81wBPVijGZH5GBs\"",
20677
- "mtime": "2026-10-10T00:24:14.949Z",
21912
+ "mtime": "2026-10-17T18:43:41.584Z",
20678
21913
  "size": 7504,
20679
21914
  "path": "../public/_nuxt/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2"
20680
21915
  },
21916
+ "/_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2": {
21917
+ "type": "font/woff2",
21918
+ "etag": "\"3b5c-HLF7Wvs2Z1IA1cPRs6jnor8OUQ4\"",
21919
+ "mtime": "2026-10-17T18:43:41.584Z",
21920
+ "size": 15196,
21921
+ "path": "../public/_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2"
21922
+ },
21923
+ "/_nuxt/kwSoIiM7.js": {
21924
+ "type": "text/javascript; charset=utf-8",
21925
+ "etag": "\"e91-CnzsResp84INY2sxWs3arWnxgM8\"",
21926
+ "mtime": "2026-10-17T18:43:41.584Z",
21927
+ "size": 3729,
21928
+ "path": "../public/_nuxt/kwSoIiM7.js"
21929
+ },
21930
+ "/_nuxt/mkEwYka4.js": {
21931
+ "type": "text/javascript; charset=utf-8",
21932
+ "etag": "\"2e6a-zaC4Yf5z6GyCsrKnM1W6O4SIIIE\"",
21933
+ "mtime": "2026-10-17T18:43:41.584Z",
21934
+ "size": 11882,
21935
+ "path": "../public/_nuxt/mkEwYka4.js"
21936
+ },
21937
+ "/_nuxt/w7Rm7unj.js": {
21938
+ "type": "text/javascript; charset=utf-8",
21939
+ "etag": "\"13f-TquOUnLU+9UXN0EfzoVFvVrGpqg\"",
21940
+ "mtime": "2026-10-17T18:43:41.584Z",
21941
+ "size": 319,
21942
+ "path": "../public/_nuxt/w7Rm7unj.js"
21943
+ },
20681
21944
  "/_nuxt/wherdr-nerd-awesome.DQ3_iAfa.woff2": {
20682
21945
  "type": "font/woff2",
20683
21946
  "etag": "\"30178-02mpQKEDb74Ec8LtlhKceB1vHO8\"",
20684
- "mtime": "2026-10-10T00:24:14.949Z",
21947
+ "mtime": "2026-10-17T18:43:41.584Z",
20685
21948
  "size": 196984,
20686
21949
  "path": "../public/_nuxt/wherdr-nerd-awesome.DQ3_iAfa.woff2"
20687
21950
  },
21951
+ "/_nuxt/pdf.min.t82Z80JU.mjs": {
21952
+ "type": "text/javascript; charset=utf-8",
21953
+ "etag": "\"678c7-U+W9TWPlwH5JFSPFTsPGlAkMVJc\"",
21954
+ "mtime": "2026-10-17T18:43:41.584Z",
21955
+ "size": 424135,
21956
+ "path": "../public/_nuxt/pdf.min.t82Z80JU.mjs"
21957
+ },
21958
+ "/_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2": {
21959
+ "type": "font/woff2",
21960
+ "etag": "\"d9b0-kmO/x6KCTFRlVipOvl+5XcArGUw\"",
21961
+ "mtime": "2026-10-17T18:43:41.584Z",
21962
+ "size": 55728,
21963
+ "path": "../public/_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2"
21964
+ },
21965
+ "/_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2": {
21966
+ "type": "font/woff2",
21967
+ "etag": "\"30f78-2RuGTMLnbTBdhlI9ExApyiUeD8c\"",
21968
+ "mtime": "2026-10-17T18:43:41.584Z",
21969
+ "size": 200568,
21970
+ "path": "../public/_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2"
21971
+ },
21972
+ "/_nuxt/pdf.worker.min.wgc6bjNh.mjs": {
21973
+ "type": "text/javascript; charset=utf-8",
21974
+ "etag": "\"107554-apJIGjXrCPcbKwmHzZKIYl5kc4c\"",
21975
+ "mtime": "2026-10-17T18:43:41.584Z",
21976
+ "size": 1078612,
21977
+ "path": "../public/_nuxt/pdf.worker.min.wgc6bjNh.mjs"
21978
+ },
20688
21979
  "/_nuxt/wherdr-nerd-extension.Dai_ky39.woff2": {
20689
21980
  "type": "font/woff2",
20690
21981
  "etag": "\"f76c-CjERGtjtOrkpSXy7JyZNl1CAu0U\"",
20691
- "mtime": "2026-10-10T00:24:14.949Z",
21982
+ "mtime": "2026-10-17T18:43:41.584Z",
20692
21983
  "size": 63340,
20693
21984
  "path": "../public/_nuxt/wherdr-nerd-extension.Dai_ky39.woff2"
20694
21985
  },
20695
21986
  "/_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2": {
20696
21987
  "type": "font/woff2",
20697
21988
  "etag": "\"1e130-1GKpbVoJoRf3AxaKTZS8FjxkOd4\"",
20698
- "mtime": "2026-10-10T00:24:14.949Z",
21989
+ "mtime": "2026-10-17T18:43:41.584Z",
20699
21990
  "size": 123184,
20700
21991
  "path": "../public/_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2"
20701
21992
  },
20702
- "/_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2": {
20703
- "type": "font/woff2",
20704
- "etag": "\"30f78-2RuGTMLnbTBdhlI9ExApyiUeD8c\"",
20705
- "mtime": "2026-10-10T00:24:14.949Z",
20706
- "size": 200568,
20707
- "path": "../public/_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2"
20708
- },
20709
21993
  "/_nuxt/wherdr-nerd-material-2.C_flbBWO.woff2": {
20710
21994
  "type": "font/woff2",
20711
21995
  "etag": "\"1f95c-q6dAP964z2dgEvWzAYjTAzBtzBc\"",
20712
- "mtime": "2026-10-10T00:24:14.949Z",
21996
+ "mtime": "2026-10-17T18:43:41.585Z",
20713
21997
  "size": 129372,
20714
21998
  "path": "../public/_nuxt/wherdr-nerd-material-2.C_flbBWO.woff2"
20715
21999
  },
20716
22000
  "/_nuxt/wherdr-nerd-material-3.8xz7iX-Y.woff2": {
20717
22001
  "type": "font/woff2",
20718
22002
  "etag": "\"2248c-3GBJ1KjkT+xYPhza9V/DKaILa7Y\"",
20719
- "mtime": "2026-10-10T00:24:14.949Z",
22003
+ "mtime": "2026-10-17T18:43:41.585Z",
20720
22004
  "size": 140428,
20721
22005
  "path": "../public/_nuxt/wherdr-nerd-material-3.8xz7iX-Y.woff2"
20722
22006
  },
22007
+ "/_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2": {
22008
+ "type": "font/woff2",
22009
+ "etag": "\"1bc0-iXm39wQwNbm2VjpVBOn72grfku0\"",
22010
+ "mtime": "2026-10-17T18:43:41.585Z",
22011
+ "size": 7104,
22012
+ "path": "../public/_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2"
22013
+ },
20723
22014
  "/_nuxt/wherdr-nerd-material-4.CO_PudDR.woff2": {
20724
22015
  "type": "font/woff2",
20725
22016
  "etag": "\"1fa80-YcJvpFD/M3vTC4y6SMmp7s8a9gw\"",
20726
- "mtime": "2026-10-10T00:24:14.949Z",
22017
+ "mtime": "2026-10-17T18:43:41.585Z",
20727
22018
  "size": 129664,
20728
22019
  "path": "../public/_nuxt/wherdr-nerd-material-4.CO_PudDR.woff2"
20729
22020
  },
20730
22021
  "/_nuxt/wherdr-nerd-octicons.Hl4VEx8m.woff2": {
20731
22022
  "type": "font/woff2",
20732
22023
  "etag": "\"f890-FkAsW3iqENK+lU5UlSze0yqnE2s\"",
20733
- "mtime": "2026-10-10T00:24:14.949Z",
22024
+ "mtime": "2026-10-17T18:43:41.585Z",
20734
22025
  "size": 63632,
20735
22026
  "path": "../public/_nuxt/wherdr-nerd-octicons.Hl4VEx8m.woff2"
20736
22027
  },
20737
- "/_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2": {
20738
- "type": "font/woff2",
20739
- "etag": "\"1bc0-iXm39wQwNbm2VjpVBOn72grfku0\"",
20740
- "mtime": "2026-10-10T00:24:14.950Z",
20741
- "size": 7104,
20742
- "path": "../public/_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2"
20743
- },
20744
22028
  "/_nuxt/wherdr-symbols.C1LsPKmg.woff2": {
20745
22029
  "type": "font/woff2",
20746
22030
  "etag": "\"1304-Lwyr1XiDl3FK38nmS/6Pk9wfiWc\"",
20747
- "mtime": "2026-10-10T00:24:14.950Z",
22031
+ "mtime": "2026-10-17T18:43:41.585Z",
20748
22032
  "size": 4868,
20749
22033
  "path": "../public/_nuxt/wherdr-symbols.C1LsPKmg.woff2"
20750
22034
  },
20751
- "/_nuxt/yzABg5xl.js": {
20752
- "type": "text/javascript; charset=utf-8",
20753
- "etag": "\"1c49-W7I7waHyF8BfftITNIl1xCbNFQw\"",
20754
- "mtime": "2026-10-10T00:24:14.950Z",
20755
- "size": 7241,
20756
- "path": "../public/_nuxt/yzABg5xl.js"
20757
- },
20758
22035
  "/_nuxt/builds/latest.json": {
20759
22036
  "type": "application/json",
20760
- "etag": "\"47-gUq0w2mhEU+I4n1/G1rUjuC+PWE\"",
20761
- "mtime": "2026-10-10T00:24:14.921Z",
22037
+ "etag": "\"47-Ij38vrZ4+IXs2yqcXQmMWk9jWY4\"",
22038
+ "mtime": "2026-10-17T18:43:41.560Z",
20762
22039
  "size": 71,
20763
22040
  "path": "../public/_nuxt/builds/latest.json"
20764
22041
  },
20765
- "/_nuxt/builds/meta/7afbf062-5369-4002-b20d-7a582ff6e0f1.json": {
22042
+ "/_nuxt/builds/meta/4994f3a4-4126-4f57-a9e5-c7ebb25850bc.json": {
20766
22043
  "type": "application/json",
20767
- "etag": "\"58-LQMKUB4Jlz4hjuTcu/d4TGQA1Kc\"",
20768
- "mtime": "2026-10-10T00:24:14.916Z",
22044
+ "etag": "\"58-2ODqXvSPWOTvTj4cYdtTa6J4LS0\"",
22045
+ "mtime": "2026-10-17T18:43:41.550Z",
20769
22046
  "size": 88,
20770
- "path": "../public/_nuxt/builds/meta/7afbf062-5369-4002-b20d-7a582ff6e0f1.json"
22047
+ "path": "../public/_nuxt/builds/meta/4994f3a4-4126-4f57-a9e5-c7ebb25850bc.json"
20771
22048
  }
20772
22049
  };
20773
22050
 
@@ -20987,7 +22264,7 @@ const _M8hgLp = defineEventHandler(async (event) => {
20987
22264
  setResponseStatus(event, 403);
20988
22265
  setResponseHeader(event, "content-type", "text/html; charset=utf-8");
20989
22266
  setResponseHeader(event, "cache-control", "no-store");
20990
- return hostRefusedPage();
22267
+ return hostRefusedPage(void 0, event.node.req.headers.host);
20991
22268
  }
20992
22269
  return sendError(event, 403, { error: "Host not allowed", code: "host" });
20993
22270
  }
@@ -21019,6 +22296,7 @@ const _lazy_4__oTm = () => import('../routes/api/auth/max-session.post.mjs');
21019
22296
  const _lazy_7O3TsZ = () => import('../routes/api/auth/register/options.post.mjs');
21020
22297
  const _lazy_fQByfS = () => import('../routes/api/auth/register/verify.post.mjs');
21021
22298
  const _lazy_jcfnWB = () => import('../routes/api/auth/status.get.mjs');
22299
+ const _lazy_DwN9dC = () => import('../routes/api/board.get.mjs');
21022
22300
  const _lazy_WhNb61 = () => import('../routes/api/changes.get.mjs');
21023
22301
  const _lazy_hdSKYJ = () => import('../routes/api/chat.get.mjs');
21024
22302
  const _lazy_WoSEa6 = () => import('../routes/api/chat/image.get.mjs');
@@ -21030,10 +22308,14 @@ const _lazy_GF2Rhb = () => import('../routes/api/codex-update.post.mjs');
21030
22308
  const _lazy_onTn85 = () => import('../routes/api/commands.get.mjs');
21031
22309
  const _lazy_XuUgLO = () => import('../routes/api/config.get.mjs');
21032
22310
  const _lazy_y_su18 = () => import('../routes/api/dirs.get.mjs');
22311
+ const _lazy_l7QdCS = () => import('../routes/api/dismiss-stopped.post.mjs');
21033
22312
  const _lazy_Z6oqjB = () => import('../routes/api/dismiss.post.mjs');
21034
22313
  const _lazy_2uy6Z9 = () => import('../routes/api/effort.post.mjs');
21035
22314
  const _lazy_7FhJOq = () => import('../routes/api/efforts.get.mjs');
21036
22315
  const _lazy_Wg_MPT = () => import('../routes/api/file.post.mjs');
22316
+ const _lazy_vy5jzJ = () => import('../routes/api/files.get.mjs');
22317
+ const _lazy_iD5EkU = () => import('../routes/api/files/download.get.mjs');
22318
+ const _lazy_TecKdl = () => import('../routes/api/files/read.get.mjs');
21037
22319
  const _lazy_kEWyNy = () => import('../routes/api/gitroot.get.mjs');
21038
22320
  const _lazy_1Vqvr9 = () => import('../routes/api/health.get.mjs');
21039
22321
  const _lazy_U4OEhz = () => import('../routes/api/input.post.mjs');
@@ -21059,8 +22341,15 @@ const _lazy_mhIdo4 = () => import('../routes/api/plugins/projects.get.mjs');
21059
22341
  const _lazy_zH9tge = () => import('../routes/api/plugins/projects.post.mjs');
21060
22342
  const _lazy_qE4HMW = () => import('../routes/api/plugins/thread-limits.get.mjs');
21061
22343
  const _lazy_ByJj04 = () => import('../routes/api/plugins/thread-limits.post.mjs');
22344
+ const _lazy_VZ7yeT = () => import('../routes/api/project/inbox.get.mjs');
22345
+ const _lazy_wq4Jn3 = () => import('../routes/api/project/inbox.post.mjs');
21062
22346
  const _lazy_WLg2Uu = () => import('../routes/api/index.get.mjs');
22347
+ const _lazy_LkLunk = () => import('../routes/api/project/memory.get.mjs');
21063
22348
  const _lazy_sQe2ZF = () => import('../routes/api/project/report.get.mjs');
22349
+ const _lazy_jP59VB = () => import('../routes/api/project/routines.get.mjs');
22350
+ const _lazy_do1380 = () => import('../routes/api/project/settings.get.mjs');
22351
+ const _lazy_6EuDYh = () => import('../routes/api/project/thread.get.mjs');
22352
+ const _lazy_qZGRKl = () => import('../routes/api/project/thread.post.mjs');
21064
22353
  const _lazy_wxPObX = () => import('../routes/api/prompt.post.mjs');
21065
22354
  const _lazy_gHqHgE = () => import('../routes/api/push/quiet.post.mjs');
21066
22355
  const _lazy_vXOoN7 = () => import('../routes/api/push/subscribe.post.mjs');
@@ -21078,6 +22367,7 @@ const _lazy_K8ukU6 = () => import('../routes/api/search.get.mjs');
21078
22367
  const _lazy_NXLBIE = () => import('../routes/api/seen.post.mjs');
21079
22368
  const _lazy_GOSQuW = () => import('../routes/api/sessions.get.mjs');
21080
22369
  const _lazy_3y86mR = () => import('../routes/api/sessions.post.mjs');
22370
+ const _lazy_tLoqXq = () => import('../routes/api/settings-tab.post.mjs');
21081
22371
  const _lazy_TqhtLZ = () => import('../routes/api/space.post.mjs');
21082
22372
  const _lazy_oeuOKk = () => import('../routes/api/state.get.mjs');
21083
22373
  const _lazy_ecbrXA = () => import('../routes/api/unqueue.post.mjs');
@@ -21092,7 +22382,6 @@ const _lazy_2a3aHZ = () => import('../routes/icons/_name_.get.mjs');
21092
22382
  const _lazy_MpH2Yl = () => import('../routes/uploads/_...name_.get.mjs');
21093
22383
  const _lazy_hSqSXW = () => import('../routes/ws/_..._.mjs');
21094
22384
  const _lazy_N9wZe_ = () => import('../routes/ws/events.mjs');
21095
- const _lazy_CXgyQE = () => import('../routes/ws/mirror.mjs');
21096
22385
  const _lazy_Stovcz = () => import('../routes/ws/term.mjs');
21097
22386
  const _lazy_9gHabX = () => import('../routes/renderer.mjs');
21098
22387
 
@@ -21112,6 +22401,7 @@ const handlers = [
21112
22401
  { route: '/api/auth/register/options', handler: _lazy_7O3TsZ, lazy: true, middleware: false, method: "post" },
21113
22402
  { route: '/api/auth/register/verify', handler: _lazy_fQByfS, lazy: true, middleware: false, method: "post" },
21114
22403
  { route: '/api/auth/status', handler: _lazy_jcfnWB, lazy: true, middleware: false, method: "get" },
22404
+ { route: '/api/board', handler: _lazy_DwN9dC, lazy: true, middleware: false, method: "get" },
21115
22405
  { route: '/api/changes', handler: _lazy_WhNb61, lazy: true, middleware: false, method: "get" },
21116
22406
  { route: '/api/chat', handler: _lazy_hdSKYJ, lazy: true, middleware: false, method: "get" },
21117
22407
  { route: '/api/chat/image', handler: _lazy_WoSEa6, lazy: true, middleware: false, method: "get" },
@@ -21123,10 +22413,14 @@ const handlers = [
21123
22413
  { route: '/api/commands', handler: _lazy_onTn85, lazy: true, middleware: false, method: "get" },
21124
22414
  { route: '/api/config', handler: _lazy_XuUgLO, lazy: true, middleware: false, method: "get" },
21125
22415
  { route: '/api/dirs', handler: _lazy_y_su18, lazy: true, middleware: false, method: "get" },
22416
+ { route: '/api/dismiss-stopped', handler: _lazy_l7QdCS, lazy: true, middleware: false, method: "post" },
21126
22417
  { route: '/api/dismiss', handler: _lazy_Z6oqjB, lazy: true, middleware: false, method: "post" },
21127
22418
  { route: '/api/effort', handler: _lazy_2uy6Z9, lazy: true, middleware: false, method: "post" },
21128
22419
  { route: '/api/efforts', handler: _lazy_7FhJOq, lazy: true, middleware: false, method: "get" },
21129
22420
  { route: '/api/file', handler: _lazy_Wg_MPT, lazy: true, middleware: false, method: "post" },
22421
+ { route: '/api/files', handler: _lazy_vy5jzJ, lazy: true, middleware: false, method: "get" },
22422
+ { route: '/api/files/download', handler: _lazy_iD5EkU, lazy: true, middleware: false, method: "get" },
22423
+ { route: '/api/files/read', handler: _lazy_TecKdl, lazy: true, middleware: false, method: "get" },
21130
22424
  { route: '/api/gitroot', handler: _lazy_kEWyNy, lazy: true, middleware: false, method: "get" },
21131
22425
  { route: '/api/health', handler: _lazy_1Vqvr9, lazy: true, middleware: false, method: "get" },
21132
22426
  { route: '/api/input', handler: _lazy_U4OEhz, lazy: true, middleware: false, method: "post" },
@@ -21152,8 +22446,15 @@ const handlers = [
21152
22446
  { route: '/api/plugins/projects', handler: _lazy_zH9tge, lazy: true, middleware: false, method: "post" },
21153
22447
  { route: '/api/plugins/thread-limits', handler: _lazy_qE4HMW, lazy: true, middleware: false, method: "get" },
21154
22448
  { route: '/api/plugins/thread-limits', handler: _lazy_ByJj04, lazy: true, middleware: false, method: "post" },
22449
+ { route: '/api/project/inbox', handler: _lazy_VZ7yeT, lazy: true, middleware: false, method: "get" },
22450
+ { route: '/api/project/inbox', handler: _lazy_wq4Jn3, lazy: true, middleware: false, method: "post" },
21155
22451
  { route: '/api/project', handler: _lazy_WLg2Uu, lazy: true, middleware: false, method: "get" },
22452
+ { route: '/api/project/memory', handler: _lazy_LkLunk, lazy: true, middleware: false, method: "get" },
21156
22453
  { route: '/api/project/report', handler: _lazy_sQe2ZF, lazy: true, middleware: false, method: "get" },
22454
+ { route: '/api/project/routines', handler: _lazy_jP59VB, lazy: true, middleware: false, method: "get" },
22455
+ { route: '/api/project/settings', handler: _lazy_do1380, lazy: true, middleware: false, method: "get" },
22456
+ { route: '/api/project/thread', handler: _lazy_6EuDYh, lazy: true, middleware: false, method: "get" },
22457
+ { route: '/api/project/thread', handler: _lazy_qZGRKl, lazy: true, middleware: false, method: "post" },
21157
22458
  { route: '/api/prompt', handler: _lazy_wxPObX, lazy: true, middleware: false, method: "post" },
21158
22459
  { route: '/api/push/quiet', handler: _lazy_gHqHgE, lazy: true, middleware: false, method: "post" },
21159
22460
  { route: '/api/push/subscribe', handler: _lazy_vXOoN7, lazy: true, middleware: false, method: "post" },
@@ -21171,6 +22472,7 @@ const handlers = [
21171
22472
  { route: '/api/seen', handler: _lazy_NXLBIE, lazy: true, middleware: false, method: "post" },
21172
22473
  { route: '/api/sessions', handler: _lazy_GOSQuW, lazy: true, middleware: false, method: "get" },
21173
22474
  { route: '/api/sessions', handler: _lazy_3y86mR, lazy: true, middleware: false, method: "post" },
22475
+ { route: '/api/settings-tab', handler: _lazy_tLoqXq, lazy: true, middleware: false, method: "post" },
21174
22476
  { route: '/api/space', handler: _lazy_TqhtLZ, lazy: true, middleware: false, method: "post" },
21175
22477
  { route: '/api/state', handler: _lazy_oeuOKk, lazy: true, middleware: false, method: "get" },
21176
22478
  { route: '/api/unqueue', handler: _lazy_ecbrXA, lazy: true, middleware: false, method: "post" },
@@ -21185,7 +22487,6 @@ const handlers = [
21185
22487
  { route: '/uploads/**:name', handler: _lazy_MpH2Yl, lazy: true, middleware: false, method: "get" },
21186
22488
  { route: '/ws/**', handler: _lazy_hSqSXW, lazy: true, middleware: false, method: undefined },
21187
22489
  { route: '/ws/events', handler: _lazy_N9wZe_, lazy: true, middleware: false, method: undefined },
21188
- { route: '/ws/mirror', handler: _lazy_CXgyQE, lazy: true, middleware: false, method: undefined },
21189
22490
  { route: '/ws/term', handler: _lazy_Stovcz, lazy: true, middleware: false, method: undefined },
21190
22491
  { route: '/__nuxt_error', handler: _lazy_9gHabX, lazy: true, middleware: false, method: undefined },
21191
22492
  { route: '/__nuxt_island/**', handler: _SxA8c9, lazy: false, middleware: false, method: undefined },
@@ -21648,5 +22949,5 @@ setupGracefulShutdown(listener, nitroApp);
21648
22949
  }
21649
22950
  const nodeServer = {};
21650
22951
 
21651
- export { recentDirsWithKinds as $, ATTACH_MAX as A, keysFor as B, parseChoices as C, parseOmpField as D, sameQuestion as E, sleep$1 as F, getMachine as G, HerdrError as H, installClaudeStatusline as I, codexStatus as J, codexMenuOpen as K, terminalUpdateLine as L, MACHINE_KEY_RE as M, terminalUpdateDone as N, restarts as O, PANE_RE as P, log as Q, withPaneLock as R, builtinCommands as S, slashCommands as T, UPLOAD_DIR as U, HOME as V, localMachine as W, readSubs as X, vapidPublicKey as Y, pushReady as Z, machineConfigs as _, defineApi as a, readGlobalQuiet as a$, installedAgentKinds as a0, IN_DOCKER as a1, HOST_OPEN_TARGET as a2, HOST_OPEN_KEY as a3, PANE_RE$1 as a4, splitId as a5, HOST_OPEN_USER as a6, listDirs as a7, closePanel as a8, setEffort as a9, herdrOn as aA, getState as aB, HERDR_CHILD_ENV as aC, HERDR_BIN as aD, currentMachineSlots as aE, paneBaseMachine as aF, projectOf as aG, isProjectThread as aH, limitMachineKeys as aI, validLimit as aJ, readThreadLimits as aK, writeThreadLimits as aL, closeTrailingMention as aM, restarting as aN, hasHeld as aO, INPUT_STATES as aP, inputVisible as aQ, shouldHold as aR, sendPrompt as aS, agentPrompt as aT, isBusyError as aU, HOLD_AGENTS as aV, pendingPrompts as aW, parseQuiet as aX, writeGlobalQuiet as aY, writeSubs as aZ, quietActive as a_, refreshModel as aa, listEfforts as ab, saveUpload as ac, underHome as ad, isSlashCommand as ae, addQueued as af, interruptAgent as ag, takeBackFromClaude as ah, takeBack as ai, isGitRepo as aj, projectFolderKinds as ak, baseMachines as al, DATA_DIR as am, renameMachine as an, readMenu as ao, searchKeys as ap, findEntry as aq, stepToward as ar, clickMovesOnly as as, setModel as at, listModels as au, TOP as av, HOST_LABEL as aw, phoneAccess as ax, phoneStatus as ay, phoneAction as az, screenChoices as b, validPushSubscription as b0, replaceSubscription as b1, pushSend as b2, readQuotas as b3, retryQueued as b4, parseWaitScreen as b5, settingsTabs as b6, tabsOfRow as b7, hasTranscript as b8, SEARCH_DEADLINE_MS as b9, useRuntimeConfig as bA, encodePath as bB, joinRelativeURL as bC, defineRenderHandler as bD, createError$1 as bE, destr as bF, getRouteRules as bG, relative as bH, joinURL as bI, getResponseStatusText as bJ, getResponseStatus as bK, useNitroApp as bL, nodeServer as bM, SEARCH_MAX_RESULTS as ba, spaceTitle as bb, markSeen as bc, listSessions as bd, openSession as be, PANE_DIRECTIONS as bf, cancelQueued as bg, installMode as bh, oneTapMode as bi, updateCommand as bj, compareVersions as bk, updateRunning as bl, allMachines as bm, recentDirs as bn, joinId as bo, useStorage as bp, setResponseHeader as bq, getRouterParam as br, readUpload as bs, defineWebSocketHandler as bt, eventClients as bu, getStateJson as bv, hostAllowed as bw, sameOrigin as bx, mirrorSize as by, openTerm as bz, createAgent as c, defineEventHandler as d, watchScreen as e, findPane as f, choicesCache as g, herdr as h, getQuery as i, saveAttachment as j, auth as k, localMachineLabel as l, machineFor as m, machineOfPane as n, fmt as o, poll as p, transcripts as q, reqOf as r, sendError as s, takenBackOf as t, uploadNames as u, withoutTakenBack as v, withOmpTab as w, withSentText as x, currentModel as y, sendImage as z };
22952
+ export { UPDATE_LABELS as $, ATTACH_MAX as A, isProjectThread as B, uploadNames as C, runHerdrCli as D, parseIntegrationStatus as E, machineOfPane as F, fmt as G, HerdrError as H, takenBackOf as I, transcripts as J, missingIntegration as K, multiMachine as L, integrationCommand as M, chatPasted as N, withoutTakenBack as O, PANE_RE as P, withSentText as Q, currentModel as R, sendImage as S, keysFor as T, UPLOAD_DIR as U, parseChoices as V, parseOmpField as W, withPaneLock as X, selfUpdates as Y, restarting as Z, updateChoices as _, defineApi as a, refreshNativeScreen as a$, updateRestartPlan as a0, restarts as a1, usesTerminalException as a2, sameQuestion as a3, sleep$1 as a4, MACHINE_KEY_RE as a5, getMachine as a6, installClaudeStatusline as a7, codexStatus as a8, paneForeground as a9, listDirs as aA, dismissStopped as aB, closePanel as aC, setEffort as aD, refreshModel as aE, listEfforts as aF, saveUpload as aG, setResponseHeader as aH, underHome as aI, isSlashCommand as aJ, addQueued as aK, interruptAgent as aL, takeBackFromClaude as aM, takeBack as aN, isGitRepo as aO, projectFolderKinds as aP, baseMachines as aQ, DATA_DIR as aR, renameMachine as aS, readMenu as aT, findEntry as aU, menuIdentity as aV, searchKeys as aW, stepToward as aX, clickMovesOnly as aY, setModel as aZ, listModels as a_, codexMenuOpen as aa, stopAgent as ab, terminalUpdateLine as ac, waitFor as ad, terminalUpdateDone as ae, startAgent as af, log as ag, RESTARTABLE as ah, claudeFooterMode as ai, planRestart as aj, builtinCommands as ak, slashCommands as al, HOME as am, localMachine as an, readSubs as ao, vapidPublicKey as ap, pushReady as aq, machineConfigs as ar, recentDirsWithKinds as as, installedAgentKinds as at, IN_DOCKER as au, HOST_OPEN_TARGET as av, HOST_OPEN_KEY as aw, PANE_RE$1 as ax, splitId as ay, HOST_OPEN_USER as az, screenChoices as b, useRuntimeConfig as b$, TOP as b0, HOST_LABEL as b1, phoneAccess as b2, phoneStatus as b3, phoneAction as b4, limitMachineKeys as b5, validLimit as b6, readThreadLimits as b7, writeThreadLimits as b8, closeTrailingMention as b9, hasTranscript as bA, SEARCH_DEADLINE_MS as bB, SEARCH_MAX_RESULTS as bC, spaceTitle as bD, markSeen as bE, listSessions as bF, openSession as bG, settingsFocus as bH, PANE_DIRECTIONS as bI, cancelQueued as bJ, installMode as bK, oneTapMode as bL, updateCommand as bM, compareVersions as bN, updateRunning as bO, allMachines as bP, recentDirs as bQ, joinId as bR, useStorage as bS, getRouterParam as bT, readUpload as bU, defineWebSocketHandler as bV, eventClients as bW, getStateJson as bX, hostAllowed as bY, sameOrigin as bZ, openTerm as b_, keepPastes as ba, hasHeld as bb, INPUT_STATES as bc, inputVisible as bd, shouldHold as be, sendPrompt as bf, agentPrompt as bg, isBusyError as bh, HOLD_AGENTS as bi, pendingPrompts as bj, parseQuiet as bk, writeGlobalQuiet as bl, writeSubs as bm, quietActive as bn, readGlobalQuiet as bo, validPushSubscription as bp, replaceSubscription as bq, pushSend as br, readQuotas as bs, retryQueued as bt, parseWaitScreen as bu, waitIdentity as bv, settingsTabs as bw, tabsOfRow as bx, classifyScreen as by, parseMenu as bz, createAgent as c, encodePath as c0, joinRelativeURL as c1, defineRenderHandler as c2, createError$1 as c3, destr as c4, getRouteRules as c5, relative as c6, joinURL as c7, getResponseStatusText as c8, getResponseStatus as c9, useNitroApp as ca, nodeServer as cb, defineEventHandler as d, watchScreen as e, findPane as f, choicesCache as g, herdr as h, getQuery as i, saveAttachment as j, auth as k, localMachineLabel as l, getState as m, projectOf as n, isCoordinator as o, poll as p, paneBaseMachine as q, reqOf as r, sendError as s, pickCoordinator as t, currentMachineSlots as u, machineFor as v, withOmpTab as w, herdrOn as x, HERDR_CHILD_ENV as y, HERDR_BIN as z };
21652
22953
  //# sourceMappingURL=nitro.mjs.map