wherdr 1.3.2 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) 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/B4Yk2tB1.js +23 -0
  4. package/.output/public/_nuxt/BBw_0a4M.js +6 -0
  5. package/.output/public/_nuxt/{D7sxNXx1.js → BSy6OCIY.js} +1 -1
  6. package/.output/public/_nuxt/BX5PM2JQ.js +1 -0
  7. package/.output/public/_nuxt/BgPDnf2S.js +1 -0
  8. package/.output/public/_nuxt/BkOxQzbS.js +2 -0
  9. package/.output/public/_nuxt/{8ksjcuDu.js → CKhgznq4.js} +45 -56
  10. package/.output/public/_nuxt/{Cd8j9O5w.js → CP8o925U.js} +1 -1
  11. package/.output/public/_nuxt/CkbmecwS.js +1 -0
  12. package/.output/public/_nuxt/Cr3SrGky.js +1 -0
  13. package/.output/public/_nuxt/DAg9fiVh.js +89 -0
  14. package/.output/public/_nuxt/DT8qZ0Wv.js +1 -0
  15. package/.output/public/_nuxt/DaaJIRB3.js +1 -0
  16. package/.output/public/_nuxt/{DViwOclv.js → DcJi16XA.js} +1 -1
  17. package/.output/public/_nuxt/VpjCgSXu.js +36 -0
  18. package/.output/public/_nuxt/builds/latest.json +1 -1
  19. package/.output/public/_nuxt/builds/meta/c735b6c0-1bd0-47d7-a208-d310f0a06287.json +1 -0
  20. package/.output/public/_nuxt/dPxB2L94.js +89 -0
  21. package/.output/public/_nuxt/{entry.Crt1r4l3.css → entry.CGWKmYU3.css} +1 -1
  22. package/.output/public/_nuxt/xYX85SPI.js +1 -0
  23. package/.output/public/sw.js +1 -1
  24. package/.output/server/chunks/_/branding.mjs +1 -1
  25. package/.output/server/chunks/_/filePaths.mjs +25 -0
  26. package/.output/server/chunks/_/files.mjs +204 -0
  27. package/.output/server/chunks/_/machineOrder.mjs +1 -1
  28. package/.output/server/chunks/_/onboarding.mjs +1 -1
  29. package/.output/server/chunks/_/package.mjs +3 -2
  30. package/.output/server/chunks/_/pluginPolicy.mjs +93 -0
  31. package/.output/server/chunks/_/plugins.mjs +4 -94
  32. package/.output/server/chunks/_/projectBoard.mjs +120 -29
  33. package/.output/server/chunks/_/projectDocs.mjs +106 -0
  34. package/.output/server/chunks/_/projectInbox.mjs +135 -0
  35. package/.output/server/chunks/_/projectThreads.mjs +46 -0
  36. package/.output/server/chunks/_/projectThreads2.mjs +61 -0
  37. package/.output/server/chunks/_/projectsActions.mjs +1 -1
  38. package/.output/server/chunks/_/projectsPlugin.mjs +1 -1
  39. package/.output/server/chunks/_/restart.mjs +2 -312
  40. package/.output/server/chunks/_/reveal.mjs +2 -24
  41. package/.output/server/chunks/_/selfupdate.mjs +3 -2
  42. package/.output/server/chunks/_/updates.mjs +51 -10
  43. package/.output/server/chunks/_/worktrees.mjs +1 -1
  44. package/.output/server/chunks/_/ws.mjs +1 -1
  45. package/.output/server/chunks/nitro/nitro.mjs +1096 -268
  46. package/.output/server/chunks/raw/bump-homebrew.mjs +1 -1
  47. package/.output/server/chunks/raw/herdr-plugin.mjs +1 -1
  48. package/.output/server/chunks/raw/release-ready.mjs +5 -0
  49. package/.output/server/chunks/routes/api/_..._.mjs +1 -1
  50. package/.output/server/chunks/routes/api/agents.post.mjs +1 -1
  51. package/.output/server/chunks/routes/api/ask-tab.post.mjs +1 -1
  52. package/.output/server/chunks/routes/api/attach.post.mjs +1 -1
  53. package/.output/server/chunks/routes/api/auth/disable.post.mjs +1 -1
  54. package/.output/server/chunks/routes/api/auth/lock-all.post.mjs +1 -1
  55. package/.output/server/chunks/routes/api/auth/lock.post.mjs +1 -1
  56. package/.output/server/chunks/routes/api/auth/login/options.post.mjs +1 -1
  57. package/.output/server/chunks/routes/api/auth/login/verify.post.mjs +1 -1
  58. package/.output/server/chunks/routes/api/auth/max-session.post.mjs +1 -1
  59. package/.output/server/chunks/routes/api/auth/register/options.post.mjs +1 -1
  60. package/.output/server/chunks/routes/api/auth/register/verify.post.mjs +1 -1
  61. package/.output/server/chunks/routes/api/auth/status.get.mjs +1 -1
  62. package/.output/server/chunks/routes/api/board.get.mjs +147 -0
  63. package/.output/server/chunks/routes/api/changes.get.mjs +2 -2
  64. package/.output/server/chunks/routes/api/chat/image.get.mjs +2 -2
  65. package/.output/server/chunks/routes/api/chat.get.mjs +2 -2
  66. package/.output/server/chunks/routes/api/choose.post.mjs +29 -3
  67. package/.output/server/chunks/routes/api/claude-statusline.post.mjs +2 -2
  68. package/.output/server/chunks/routes/api/close/status.get.mjs +2 -2
  69. package/.output/server/chunks/routes/api/close.post.mjs +1 -1
  70. package/.output/server/chunks/routes/api/codex-update.post.mjs +2 -2
  71. package/.output/server/chunks/routes/api/commands.get.mjs +2 -2
  72. package/.output/server/chunks/routes/api/config.get.mjs +3 -2
  73. package/.output/server/chunks/routes/api/dirs.get.mjs +2 -2
  74. package/.output/server/chunks/routes/api/dismiss-stopped.post.mjs +43 -0
  75. package/.output/server/chunks/routes/api/dismiss.post.mjs +2 -2
  76. package/.output/server/chunks/routes/api/effort.post.mjs +2 -2
  77. package/.output/server/chunks/routes/api/efforts.get.mjs +2 -2
  78. package/.output/server/chunks/routes/api/file.post.mjs +2 -2
  79. package/.output/server/chunks/routes/api/files/download.get.mjs +53 -0
  80. package/.output/server/chunks/routes/api/files/read.get.mjs +45 -0
  81. package/.output/server/chunks/routes/api/files.get.mjs +44 -0
  82. package/.output/server/chunks/routes/api/gitroot.get.mjs +2 -2
  83. package/.output/server/chunks/routes/api/health.get.mjs +1 -1
  84. package/.output/server/chunks/routes/api/index.get.mjs +1 -1
  85. package/.output/server/chunks/routes/api/input.post.mjs +13 -3
  86. package/.output/server/chunks/routes/api/interrupt.post.mjs +2 -2
  87. package/.output/server/chunks/routes/api/isgit.get.mjs +2 -2
  88. package/.output/server/chunks/routes/api/machine/awake.get.mjs +2 -2
  89. package/.output/server/chunks/routes/api/machine/awake.post.mjs +2 -2
  90. package/.output/server/chunks/routes/api/machine/order.get.mjs +1 -1
  91. package/.output/server/chunks/routes/api/machine/order.post.mjs +1 -1
  92. package/.output/server/chunks/routes/api/machine/rename.post.mjs +2 -2
  93. package/.output/server/chunks/routes/api/menu.post.mjs +2 -2
  94. package/.output/server/chunks/routes/api/model.post.mjs +2 -2
  95. package/.output/server/chunks/routes/api/models.get.mjs +2 -2
  96. package/.output/server/chunks/routes/api/nav.post.mjs +5 -4
  97. package/.output/server/chunks/routes/api/onboarding.get.mjs +1 -1
  98. package/.output/server/chunks/routes/api/onboarding.post.mjs +1 -1
  99. package/.output/server/chunks/routes/api/phone.get.mjs +2 -2
  100. package/.output/server/chunks/routes/api/phone.post.mjs +2 -2
  101. package/.output/server/chunks/routes/api/plugins/actions.get.mjs +2 -1
  102. package/.output/server/chunks/routes/api/plugins/invoke.post.mjs +2 -1
  103. package/.output/server/chunks/routes/api/plugins/profiles.get.mjs +2 -1
  104. package/.output/server/chunks/routes/api/plugins/projects.get.mjs +2 -2
  105. package/.output/server/chunks/routes/api/plugins/projects.post.mjs +2 -2
  106. package/.output/server/chunks/routes/api/plugins/thread-limits.get.mjs +2 -2
  107. package/.output/server/chunks/routes/api/plugins/thread-limits.post.mjs +2 -2
  108. package/.output/server/chunks/routes/api/project/inbox.get.mjs +43 -0
  109. package/.output/server/chunks/routes/api/project/inbox.post.mjs +43 -0
  110. package/.output/server/chunks/routes/api/project/memory.get.mjs +42 -0
  111. package/.output/server/chunks/routes/api/project/report.get.mjs +2 -2
  112. package/.output/server/chunks/routes/api/project/routines.get.mjs +43 -0
  113. package/.output/server/chunks/routes/api/project/settings.get.mjs +41 -0
  114. package/.output/server/chunks/routes/api/project/thread.get.mjs +44 -0
  115. package/.output/server/chunks/routes/api/project/thread.post.mjs +45 -0
  116. package/.output/server/chunks/routes/api/prompt.post.mjs +21 -3
  117. package/.output/server/chunks/routes/api/push/quiet.post.mjs +2 -2
  118. package/.output/server/chunks/routes/api/push/subscribe.post.mjs +2 -2
  119. package/.output/server/chunks/routes/api/push/test.post.mjs +2 -2
  120. package/.output/server/chunks/routes/api/push/unsubscribe.post.mjs +2 -2
  121. package/.output/server/chunks/routes/api/quotas.get.mjs +2 -2
  122. package/.output/server/chunks/routes/api/rename.post.mjs +1 -1
  123. package/.output/server/chunks/routes/api/requeue.post.mjs +2 -2
  124. package/.output/server/chunks/routes/api/restart.get.mjs +1 -1
  125. package/.output/server/chunks/routes/api/restart.post.mjs +1 -1
  126. package/.output/server/chunks/routes/api/reveal.post.mjs +2 -1
  127. package/.output/server/chunks/routes/api/screen-key.post.mjs +2 -2
  128. package/.output/server/chunks/routes/api/screen.get.mjs +5 -3
  129. package/.output/server/chunks/routes/api/search.get.mjs +2 -2
  130. package/.output/server/chunks/routes/api/seen.post.mjs +2 -2
  131. package/.output/server/chunks/routes/api/sessions.get.mjs +2 -2
  132. package/.output/server/chunks/routes/api/sessions.post.mjs +2 -2
  133. package/.output/server/chunks/routes/api/space.post.mjs +14 -14
  134. package/.output/server/chunks/routes/api/state.get.mjs +2 -2
  135. package/.output/server/chunks/routes/api/unqueue.post.mjs +2 -2
  136. package/.output/server/chunks/routes/api/update/status.get.mjs +1 -1
  137. package/.output/server/chunks/routes/api/update.get.mjs +2 -2
  138. package/.output/server/chunks/routes/api/update.post.mjs +2 -2
  139. package/.output/server/chunks/routes/api/upload.post.mjs +2 -2
  140. package/.output/server/chunks/routes/api/worktrees/remove.post.mjs +1 -1
  141. package/.output/server/chunks/routes/api/worktrees.get.mjs +1 -1
  142. package/.output/server/chunks/routes/favicon.ico.get.mjs +1 -1
  143. package/.output/server/chunks/routes/icons/_name_.get.mjs +2 -2
  144. package/.output/server/chunks/routes/renderer.mjs +3 -3
  145. package/.output/server/chunks/routes/uploads/_...name_.get.mjs +2 -2
  146. package/.output/server/chunks/routes/ws/_..._.mjs +2 -2
  147. package/.output/server/chunks/routes/ws/events.mjs +2 -2
  148. package/.output/server/chunks/routes/ws/term.mjs +2 -2
  149. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  150. package/.output/server/index.mjs +2 -2
  151. package/.output/server/package.json +1 -1
  152. package/README.md +332 -25
  153. package/bin/install-docker-skill.sh +20 -0
  154. package/bin/lib/commands.mjs +5 -1
  155. package/bin/lib/core.mjs +1 -0
  156. package/bin/lib/install-skill.sh +100 -0
  157. package/bin/lib/skill.mjs +16 -0
  158. package/bin/lib/updater.mjs +65 -12
  159. package/bin/lib/verify-release.mjs +20 -0
  160. package/package.json +3 -2
  161. package/skills/wherdr/SKILL.md +180 -0
  162. package/.output/public/_nuxt/B7QP1TFs.js +0 -23
  163. package/.output/public/_nuxt/BDNMzG2s.js +0 -1
  164. package/.output/public/_nuxt/BOpBIziZ.js +0 -6
  165. package/.output/public/_nuxt/BWXdFfeg.js +0 -17
  166. package/.output/public/_nuxt/COFCNFpG.js +0 -83
  167. package/.output/public/_nuxt/CXG-cOdh.js +0 -1
  168. package/.output/public/_nuxt/CkZ8t6uB.js +0 -1
  169. package/.output/public/_nuxt/D4Yz4rat.js +0 -65
  170. package/.output/public/_nuxt/DoD7Qb5P.js +0 -30
  171. package/.output/public/_nuxt/DyBZDSCV.js +0 -2
  172. package/.output/public/_nuxt/bLP7Jj-b.js +0 -1
  173. package/.output/public/_nuxt/builds/meta/7afbf062-5369-4002-b20d-7a582ff6e0f1.json +0 -1
  174. 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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.115Z"}
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-12T02:42:41.120Z"}
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-12T02:42:41.120Z"}
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-12T02:42:41.120Z"}
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-12T02:42:41.120Z"}
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-12T02:42:41.120Z"}
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-12T02:42:41.120Z"}
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-12T02:42:41.120Z"}
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-12T02:42:41.120Z"}
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": "c735b6c0-1bd0-47d7-a208-d310f0a06287",
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);
@@ -10552,17 +10556,17 @@ function herdrSock(path, method, params = {}, timeoutMs = 15e3) {
10552
10556
  sock.on("close", () => finish(new HerdrError("closed", "Herdr connection closed without a response")));
10553
10557
  });
10554
10558
  }
10555
- async function agentPrompt(target, text) {
10559
+ async function agentPrompt(target2, text) {
10556
10560
  try {
10557
- await herdr("agent.prompt", { target, text });
10561
+ await herdr("agent.prompt", { target: target2, text });
10558
10562
  } catch (e) {
10559
10563
  if (!(e instanceof HerdrError) || e.code !== "agent_not_ready") throw e;
10560
10564
  try {
10561
- await herdr("agent.get", { target });
10565
+ await herdr("agent.get", { target: target2 });
10562
10566
  } catch {
10563
10567
  throw e;
10564
10568
  }
10565
- await herdr("agent.prompt", { target, text });
10569
+ await herdr("agent.prompt", { target: target2, text });
10566
10570
  }
10567
10571
  }
10568
10572
  const sleep$1 = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -10717,7 +10721,7 @@ class SessionGate {
10717
10721
  stats() {
10718
10722
  return { execs: this.execs, streams: this.streams, queued: this.waiting.length, peak: this.peak, refusals: this.refusals };
10719
10723
  }
10720
- // A long-lived session (terminal, mirror) opens; call the result when it closes.
10724
+ // A long-lived session (terminal) opens; call the result when it closes.
10721
10725
  openStream() {
10722
10726
  this.streams++;
10723
10727
  this.track();
@@ -12855,8 +12859,50 @@ const isLongPaste = (s) => {
12855
12859
  const BLOCK = /<pasted_content(?:\s[^>]*)?>\n?([\s\S]*?)\n?<\/pasted_content(?:\s[^>]*)?>/g;
12856
12860
  function pastedBlocks(raw) {
12857
12861
  if (!raw.includes("<pasted_content")) return [];
12862
+ if (!raw.replace(BLOCK, "").replace(/\[Image #\d+[^\]]*\]/g, "").trim()) return [];
12858
12863
  return [...raw.matchAll(BLOCK)].map((m) => m[1].trim()).filter(isLongPaste);
12859
12864
  }
12865
+ const QUEUED_CHARS = 4e3;
12866
+ const cutShort = (text) => text.endsWith("\u2026") || text.length === QUEUED_CHARS;
12867
+ function cut(text, block, open) {
12868
+ const body = open ? text.replace(/…$/, "") : null;
12869
+ let at = text.indexOf(block);
12870
+ let end = at + block.length;
12871
+ let part = block;
12872
+ if (at < 0) {
12873
+ if (body === null) return null;
12874
+ at = body.indexOf(block.slice(0, 200));
12875
+ if (at < 0 || !block.startsWith(body.slice(at))) return null;
12876
+ part = body.slice(at).trimEnd();
12877
+ if (!isLongPaste(part)) return null;
12878
+ end = text.length;
12879
+ }
12880
+ const short = body !== null && end >= body.trimEnd().length;
12881
+ if (short) end = text.length;
12882
+ return { rest: (text.slice(0, at).replace(/\s+$/, "") + "\n" + text.slice(end).replace(/^\s+/, "")).trim(), part, short };
12883
+ }
12884
+ function splitPasted(text, listed = [], known = [], whole = false) {
12885
+ let rest = text;
12886
+ const pastes = [];
12887
+ const longKnown = known.filter(isLongPaste).sort((a, b) => b.length - a.length);
12888
+ let open = cutShort(text);
12889
+ const take = (block) => {
12890
+ const r = cut(rest, block, open);
12891
+ if (r === null) return;
12892
+ rest = r.rest;
12893
+ if (r.short) open = false;
12894
+ const sent = whole && r.short ? longKnown.filter((k) => k.startsWith(r.part)) : [];
12895
+ pastes.push(sent.length === 1 ? sent[0] : r.part);
12896
+ };
12897
+ for (const b of listed) {
12898
+ if (longKnown.some((k) => k !== b && b.includes(k))) continue;
12899
+ take(b);
12900
+ }
12901
+ for (const k of longKnown) take(k);
12902
+ if (!pastes.length) return { text, pastes };
12903
+ pastes.sort((a, b) => text.indexOf(a.slice(0, 200)) - text.indexOf(b.slice(0, 200)));
12904
+ return { text: rest, pastes };
12905
+ }
12860
12906
 
12861
12907
  const WINDOW_BYTES = 2 * 1024 * 1024;
12862
12908
  const MAX_READ_BYTES = 24 * 1024 * 1024;
@@ -12876,8 +12922,8 @@ function humanText(t) {
12876
12922
  if (u !== s) return u;
12877
12923
  return isNoise(s) ? null : s;
12878
12924
  }
12879
- const pastedOf = (raw) => {
12880
- const b = pastedBlocks(raw).map((s) => clip(s));
12925
+ const pastedOf = (...parts) => {
12926
+ const b = parts.flatMap(pastedBlocks).map((s) => clip(s));
12881
12927
  return b.length ? { pasted: b } : {};
12882
12928
  };
12883
12929
  const normMsg = (t) => stripImageTags(t).replace(/\s+/g, " ").trim().toLowerCase();
@@ -13057,11 +13103,11 @@ function parseClaude(lines, home = "") {
13057
13103
  const ts = d.timestamp || null;
13058
13104
  if (d.type === "attachment" && d.attachment && d.attachment.type === "queued_command" && d.attachment.commandMode === "prompt" && (d.attachment.origin || {}).kind === "human") {
13059
13105
  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));
13106
+ const texts = parts.filter((p) => p.type === "text").map((p) => String(p.text || ""));
13107
+ const text = stripImageTags(unwrapPasted(texts.join("\n")));
13062
13108
  const images = parts.filter((p) => p.type === "image").length;
13063
13109
  if (text || images) {
13064
- items.push({ role: "user", text: clip(text), images, ref: images ? ref : void 0, ts: d.attachment.timestamp || ts, ...pastedOf(raw) });
13110
+ items.push({ role: "user", text: clip(text), images, ref: images ? ref : void 0, ts: d.attachment.timestamp || ts, ...pastedOf(...texts) });
13065
13111
  pendingCmd = null;
13066
13112
  said(text, d.attachment.timestamp || ts, images);
13067
13113
  }
@@ -13122,7 +13168,7 @@ function parseClaude(lines, home = "") {
13122
13168
  }
13123
13169
  if (!Array.isArray(content)) continue;
13124
13170
  let text = "";
13125
- let raw = "";
13171
+ const raw = [];
13126
13172
  let images = 0;
13127
13173
  let toolImages = content.filter((p) => p && p.type === "image").length;
13128
13174
  for (const part of content) {
@@ -13140,13 +13186,13 @@ function parseClaude(lines, home = "") {
13140
13186
  if (special(String(part.text || ""), ts)) continue;
13141
13187
  const t = humanText(part.text);
13142
13188
  if (t === null) continue;
13143
- raw += "\n" + String(part.text || "");
13189
+ raw.push(String(part.text || ""));
13144
13190
  if (/^\[Request interrupted/.test(t)) items.push({ role: "system", text: "Interrupted", ts });
13145
13191
  else text += (text ? "\n" : "") + unwrapPasted(t.replace(/\[Image #\d+\]\s*/g, ""));
13146
13192
  } else if (part.type === "image") images++;
13147
13193
  }
13148
13194
  if (text.trim() || images) {
13149
- items.push({ role: "user", text: clip(text.trim()), images, ref: images ? ref : void 0, ts, ...pastedOf(raw) });
13195
+ items.push({ role: "user", text: clip(text.trim()), images, ref: images ? ref : void 0, ts, ...pastedOf(...raw) });
13150
13196
  pendingCmd = null;
13151
13197
  said(text, ts, images);
13152
13198
  noteSaid(d);
@@ -13681,7 +13727,7 @@ function createTranscripts({ home, herdr: herdr2, fs = localFs }) {
13681
13727
  return { start, items, queue: queue || [] };
13682
13728
  }
13683
13729
  async function tail(file, kind, size, from) {
13684
- const key = `${file}|${from}`;
13730
+ const key = `${file}|${kind}|${from}`;
13685
13731
  const c = parseCache.get(key);
13686
13732
  if (c && c.size === size) return c.r;
13687
13733
  let r;
@@ -13718,15 +13764,16 @@ function createTranscripts({ home, herdr: herdr2, fs = localFs }) {
13718
13764
  }
13719
13765
  const fileId = path$1.basename(loc.file);
13720
13766
  const base = { available: true, file: fileId, session: loc.session, guessed: Boolean(loc.guessed) };
13721
- if (pane.agent === "omp") await refreshOmpTemplates();
13767
+ const kind = transcriptKind(loc.file) || pane.agent;
13768
+ if (kind === "omp") await refreshOmpTemplates();
13722
13769
  if (opts.before !== null && opts.before !== void 0) {
13723
- const r2 = await readBackwards(loc.file, Math.min(opts.before, st.size), pane.agent);
13770
+ const r2 = await readBackwards(loc.file, Math.min(opts.before, st.size), kind);
13724
13771
  return { ...base, older: true, items: r2.items, start: r2.start };
13725
13772
  }
13726
13773
  const from = opts.from === void 0 ? null : opts.from;
13727
13774
  const token = `${fileId}:${st.size}:${from}`;
13728
13775
  if (opts.since && opts.since === token) return { ...base, unchanged: true, token };
13729
- const r = await tail(loc.file, pane.agent, st.size, from);
13776
+ const r = await tail(loc.file, kind, st.size, from);
13730
13777
  return { ...base, token, items: r.items, start: r.start, queue: r.queue || [] };
13731
13778
  }
13732
13779
  async function preview(pane) {
@@ -14209,7 +14256,7 @@ ${cmd}`;
14209
14256
  child.stdin.end(opts.input || void 0);
14210
14257
  });
14211
14258
  }
14212
- // Long-lived session (terminal, mirror): counted in the budget, never queued.
14259
+ // Long-lived session (terminal): counted in the budget, never queued.
14213
14260
  spawnHerdr(args) {
14214
14261
  const sess = this.session && this.session !== "default" ? ["--session", this.session] : [];
14215
14262
  const cmd = `exec ${[this.bin || "herdr", ...sess, ...args].map(shq).join(" ")}`;
@@ -14698,16 +14745,6 @@ function splitPath(id) {
14698
14745
  }
14699
14746
  const PANE_DIRECTIONS = ["left", "right", "up", "down"];
14700
14747
 
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
14748
  const SLUG$1 = /^[a-z0-9][a-z0-9._-]*$/i;
14712
14749
  const validProject = (v) => typeof v === "string" && SLUG$1.test(v.trim()) ? v.trim() : void 0;
14713
14750
  function projectToken(tokens) {
@@ -14730,6 +14767,16 @@ function projectOf(p) {
14730
14767
  function isCoordinator(p) {
14731
14768
  return Boolean(p.agent && projectOf(p) && !isProjectThread(p));
14732
14769
  }
14770
+ function pickCoordinator(panes, slug, machine) {
14771
+ const key = slug.toLowerCase();
14772
+ const rank = (p) => (0) + (norm$4(p.cwd).toLowerCase().endsWith(`/.herdr-projects/${key}`) ? 0 : 1);
14773
+ let best = null;
14774
+ for (const p of panes) {
14775
+ if (!isCoordinator(p) || projectOf(p).toLowerCase() !== key) continue;
14776
+ if (!best || rank(p) < rank(best)) best = p;
14777
+ }
14778
+ return best;
14779
+ }
14733
14780
 
14734
14781
  function cleanLabel(label) {
14735
14782
  return (label != null ? label : "").replace(/[\u200B-\u200D\u2060\uFEFF]/g, "").replace(/[\u2800\s]+/g, " ").trim();
@@ -14874,7 +14921,7 @@ function foregroundCommand(info) {
14874
14921
  const SCREEN_MS$1 = 3e3;
14875
14922
  function keepReading(c, rev, strict, watch, now) {
14876
14923
  if (!c || c.rev !== rev || c.strict !== strict) return false;
14877
- const live = watch || !strict || Boolean(c.choices || c.screen || c.menu);
14924
+ const live = watch || !strict && !c.usageLimit || Boolean(c.choices || c.screen || c.menu || c.interaction === "terminal");
14878
14925
  return !(live && now - c.at >= SCREEN_MS$1);
14879
14926
  }
14880
14927
 
@@ -15243,6 +15290,65 @@ function clickMovesOnly(menu) {
15243
15290
  return Boolean(enter && !/^(?:select|confirm|choose|open|resume|continue)$/i.test(enter.label.trim()));
15244
15291
  }
15245
15292
 
15293
+ function parseUsageLimit(text, agent) {
15294
+ var _a, _b;
15295
+ if (agent !== "claude") return null;
15296
+ const lines = text.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]|\r/g, "").split("\n");
15297
+ const field = lines.findLastIndex((l, i) => /^\s*❯(?:\s|$)/.test(l) && /^\s*─{3,}/.test(lines[i - 1] || ""));
15298
+ if (field < 0) return null;
15299
+ const rule = lines.findIndex((l, i) => i > field && /^\s*─{3,}/.test(l));
15300
+ if (rule < 0) return null;
15301
+ const tail = lines.slice(rule + 1);
15302
+ if (tail.length > 10 || tail.some((l) => /[╭┌]─|\benter to (?:select|confirm)\b|^\s*[❯›]\s*\d+\./i.test(l))) return null;
15303
+ const footer = tail.join("\n");
15304
+ const limit = footer.match(/^\s*(?:⚠\s*)?Usage limit reached(?:\s*·\s*limit resets ([^\n]+))?\s*$/m);
15305
+ if (!limit) return null;
15306
+ const resume = footer.match(/^\s*Continuing automatically (.+?)\s*·\s*esc to cancel\b/im);
15307
+ return {
15308
+ resets: ((_a = limit[1]) == null ? void 0 : _a.trim()) || ((_b = resume == null ? void 0 : resume[1]) == null ? void 0 : _b.trim()) || null,
15309
+ automatic: Boolean(resume),
15310
+ credits: /\/usage-credits to continue now\b/.test(footer),
15311
+ resetLink: /Use your limit reset to reset it now: clau\.de\/reset\b/.test(lines.slice(Math.max(0, field - 16), field).join("\n"))
15312
+ };
15313
+ }
15314
+
15315
+ function terminalException(text) {
15316
+ var _a;
15317
+ const lines = text.trimEnd().split("\n");
15318
+ const at = lines.findLastIndex((l) => /^\s*(?:Agent Command Center|Usage)\s*$/.test(l));
15319
+ if (at < 0) return false;
15320
+ const body = lines.slice(at + 1).filter((l) => l.trim());
15321
+ const legend = (_a = body.pop()) == null ? void 0 : _a.trim();
15322
+ if (lines[at].trim() === "Agent Command Center") {
15323
+ 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()));
15324
+ }
15325
+ 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]);
15326
+ }
15327
+ function usesTerminalException(o) {
15328
+ return o.agent === "codex" && o.status !== "unknown" && o.status !== "working" && terminalException(o.text);
15329
+ }
15330
+ function confirmedInput(text) {
15331
+ const lines = text.trimEnd().split("\n");
15332
+ const at = lines.findLastIndex((l) => /^\s*[❯›](?:\s|$)/.test(l) || /^!(?:\s|$)/.test(l) || /^╰─(?:\s|$)/.test(l));
15333
+ if (at < 0) return false;
15334
+ const line = lines[at];
15335
+ const below = lines.slice(at + 1).join("\n");
15336
+ if (/\b(?:enter|esc|escape)\s+(?:to\s+)?(?:select|open|back|cancel|confirm|close)\b/i.test(below)) return false;
15337
+ if (/^\s*[❯›]\s+\d{1,2}\.\s/.test(line)) return false;
15338
+ if (/^╰─(?:\s|$)/.test(line)) return true;
15339
+ if (/^\s*›(?:\s|$)/.test(line)) return /for shortcuts|context left|\b(?:gpt-[\w.-]+|o[1-9](?:-[\w.-]+)?)\b.*·/i.test(below);
15340
+ return /^\s*─{3,}/.test(lines[at - 1] || "");
15341
+ }
15342
+ function classifyScreen(o) {
15343
+ if (o.status === "working") return "working";
15344
+ if (usesTerminalException(o)) return "terminal";
15345
+ if (o.status !== "unknown" && parseUsageLimit(o.text, o.agent)) return "native";
15346
+ if (o.choices || o.menu || o.screen || o.settings) return "native";
15347
+ if (o.status === "unknown" || !hasTranscript(o.agent) || !o.text.trim()) return "unknown";
15348
+ if (confirmedInput(o.text)) return "input";
15349
+ return "terminal";
15350
+ }
15351
+
15246
15352
  const GLYPHS = "\xB7\u2722\u2733\u2736\u273B\u273D\u273A\u2739\u2737\u2738*\u2217";
15247
15353
  const LINE_RE = new RegExp(`^([${GLYPHS}])\\s+(\\p{L}[\\p{L}'\u2019\\-]*(?: \\p{L}[\\p{L}'\u2019\\-]*){0,3})(?:\u2026|\\.\\.\\.)(?:\\s+\\((.*)\\))?\\s*$`, "u");
15248
15354
  const RULE_RE$1 = /^\s*[─━]{8,}\s*$/;
@@ -15475,20 +15581,28 @@ function checkQueue(list, status, now, menu = true) {
15475
15581
  }
15476
15582
  return changed;
15477
15583
  }
15584
+ function giveBackHeld(list) {
15585
+ for (const q of list || []) if (q.held) {
15586
+ q.failed = true;
15587
+ q.back = true;
15588
+ }
15589
+ }
15590
+ const leftForGood = (p, before) => !p.agent && !p.leaving && Boolean(before == null ? void 0 : before.leaving);
15478
15591
  const publicEntry = (q) => ({
15479
15592
  id: q.id,
15480
15593
  text: q.text,
15481
15594
  at: q.at,
15482
15595
  ...q.held && !q.failed ? { state: "held" } : {},
15483
15596
  ...q.failed ? { state: "failed" } : {},
15484
- ...(q.held || q.failed) && q.busy ? { reason: "busy" } : q.failed && q.noInput ? { reason: "no_input" } : {}
15597
+ ...(q.held || q.failed) && q.busy ? { reason: "busy" } : q.failed && q.noInput ? { reason: "no_input" } : {},
15598
+ ...q.back ? { back: true } : {}
15485
15599
  });
15486
15600
  function loadQueued(raw, now) {
15487
15601
  if (!raw || typeof raw !== "object") return [];
15488
15602
  const out = [];
15489
15603
  for (const [pane, list] of Object.entries(raw)) {
15490
15604
  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 } : {} }));
15605
+ 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
15606
  if (ok.length) out.push([pane, ok]);
15493
15607
  }
15494
15608
  return out;
@@ -15801,6 +15915,114 @@ async function interruptAgent(d, p) {
15801
15915
  return res;
15802
15916
  }
15803
15917
 
15918
+ const PASTES_MAX = 100;
15919
+ const PASTES_MAX_CHARS = 2e6;
15920
+ const PASTES_TTL_MS = 30 * 864e5;
15921
+ const live = (p, now) => now - p.at < PASTES_TTL_MS;
15922
+ const PER_MESSAGE = 20;
15923
+ function pastesAt(text, ranges) {
15924
+ if (!Array.isArray(ranges)) return [];
15925
+ const out = [];
15926
+ for (const r of ranges.slice(0, PER_MESSAGE)) {
15927
+ if (!Array.isArray(r)) continue;
15928
+ const [at, len] = r;
15929
+ if (typeof at !== "number" || typeof len !== "number" || !Number.isInteger(at) || !Number.isInteger(len)) continue;
15930
+ if (at < 0 || len <= 0 || at + len > text.length) continue;
15931
+ const b = text.slice(at, at + len).trim();
15932
+ if (isLongPaste(b) && !out.includes(b)) out.push(b);
15933
+ }
15934
+ return out;
15935
+ }
15936
+ function addPastes(list, blocks, now) {
15937
+ if (!blocks.length) return list;
15938
+ let total = 0;
15939
+ return [...blocks.map((text) => ({ text, at: now })), ...list.filter((p) => !blocks.includes(p.text) && live(p, now))].slice(0, PASTES_MAX).filter((p) => {
15940
+ total += p.text.length;
15941
+ return total <= PASTES_MAX_CHARS;
15942
+ });
15943
+ }
15944
+ function loadPastes(raw, now) {
15945
+ if (!Array.isArray(raw)) return [];
15946
+ const out = [];
15947
+ let total = 0;
15948
+ for (const r of raw) {
15949
+ const p = typeof r === "string" ? { text: r, at: now } : r;
15950
+ if (!p || typeof p.text !== "string" || typeof p.at !== "number" || !Number.isFinite(p.at)) continue;
15951
+ if (!isLongPaste(p.text) || !live(p, now) || out.some((o) => o.text === p.text)) continue;
15952
+ if (out.length >= PASTES_MAX || (total += p.text.length) > PASTES_MAX_CHARS) break;
15953
+ out.push({ text: p.text, at: Math.min(p.at, now) });
15954
+ }
15955
+ return out;
15956
+ }
15957
+ function pastedIn(list, text, listed = []) {
15958
+ if (!list.length || !isLongPaste(text)) return listed;
15959
+ const known = list.filter((b) => !listed.includes(b)).sort((a, b) => b.length - a.length);
15960
+ return splitPasted(text, listed, known).pastes;
15961
+ }
15962
+ function withPasted(items, list) {
15963
+ if (!list.length) return items;
15964
+ return items.map((i) => {
15965
+ if (i.role !== "user") return i;
15966
+ const pasted = pastedIn(list, i.text, i.pasted);
15967
+ return pasted.length && pasted !== i.pasted ? { ...i, pasted } : i;
15968
+ });
15969
+ }
15970
+ function withQueuedPasted(q, list) {
15971
+ const pasted = pastedIn(list, q.text);
15972
+ return pasted.length ? { ...q, pasted } : q;
15973
+ }
15974
+ const PASTES_FILE = path$1.join(DATA_DIR, "pastes.json");
15975
+ let kept = null;
15976
+ let saved = null;
15977
+ let texts = null;
15978
+ function pastes() {
15979
+ if (kept) return kept;
15980
+ kept = [];
15981
+ saved = kept;
15982
+ try {
15983
+ const raw = fs.readFileSync(PASTES_FILE, "utf8");
15984
+ kept = loadPastes(JSON.parse(raw), Date.now());
15985
+ saved = JSON.stringify(kept) + "\n" === raw ? kept : null;
15986
+ } catch {
15987
+ }
15988
+ return kept;
15989
+ }
15990
+ function keptTexts() {
15991
+ const list = pastes();
15992
+ if ((texts == null ? void 0 : texts.of) !== list) texts = { of: list, list: list.map((p) => p.text) };
15993
+ return texts.list;
15994
+ }
15995
+ let writing = Promise.resolve();
15996
+ function save() {
15997
+ writing = writing.then(async () => {
15998
+ const list = kept;
15999
+ if (!list || list === saved) return;
16000
+ const temp = `${PASTES_FILE}.${randomUUID$1()}.tmp`;
16001
+ try {
16002
+ await fs$1.mkdir(DATA_DIR, { recursive: true });
16003
+ await fs$1.writeFile(temp, JSON.stringify(list) + "\n", { mode: 384 });
16004
+ await fs$1.rename(temp, PASTES_FILE);
16005
+ saved = list;
16006
+ } catch {
16007
+ await fs$1.rm(temp, { force: true }).catch(() => {
16008
+ });
16009
+ }
16010
+ });
16011
+ }
16012
+ function keepPastes(text, ranges) {
16013
+ const next = addPastes(pastes(), pastesAt(text, ranges), Date.now());
16014
+ if (next === kept) return;
16015
+ kept = next;
16016
+ save();
16017
+ }
16018
+ function purgePastes(now = Date.now()) {
16019
+ const list = pastes();
16020
+ if (list.some((p) => !live(p, now))) kept = list.filter((p) => live(p, now));
16021
+ if (kept !== saved) save();
16022
+ }
16023
+ const chatPasted = (items) => withPasted(items, keptTexts());
16024
+ const queuedPasted = (q) => withQueuedPasted(q, keptTexts());
16025
+
15804
16026
  const DEFAULTS = { freeWaitMs: 2e3, quietMs: 400, showWaitMs: 4e3, submitWaitMs: 4e3, pollMs: 50 };
15805
16027
  const RECORD_MS = 600;
15806
16028
  const MAX_ATTEMPTS = 3;
@@ -16806,7 +17028,8 @@ const listKey = (paneId, agent) => {
16806
17028
  var _a;
16807
17029
  return `${((_a = machineOfPane(paneId)) == null ? void 0 : _a.key) || ""}|${agent}`;
16808
17030
  };
16809
- const busy = /* @__PURE__ */ new Set();
17031
+ const busy$1 = /* @__PURE__ */ new Set();
17032
+ const modelControlBusy = (paneId) => busy$1.has(paneId);
16810
17033
  async function withPane(paneId, fn) {
16811
17034
  const p = findPane(paneId);
16812
17035
  if (!p) throw new HerdrError("bad_pane", "Pane not found");
@@ -16814,12 +17037,12 @@ async function withPane(paneId, fn) {
16814
17037
  if (!READY.has(p.status || "")) {
16815
17038
  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
17039
  }
16817
- if (busy.has(paneId)) throw new HerdrError("busy", "Model change already in progress");
16818
- busy.add(paneId);
17040
+ if (busy$1.has(paneId)) throw new HerdrError("busy", "Model change already in progress");
17041
+ busy$1.add(paneId);
16819
17042
  try {
16820
17043
  return await fn(p);
16821
17044
  } finally {
16822
- busy.delete(paneId);
17045
+ busy$1.delete(paneId);
16823
17046
  }
16824
17047
  }
16825
17048
  const screen = async (paneId) => {
@@ -18116,6 +18339,494 @@ async function installClaudeStatusline(m) {
18116
18339
  return last(r.stdout.toString("utf8"));
18117
18340
  }
18118
18341
 
18342
+ const CLAUDE = {
18343
+ keep: {
18344
+ "--model": 1,
18345
+ "--effort": 1,
18346
+ "--permission-mode": 1,
18347
+ "--fallback-model": 1,
18348
+ "--agent": 1,
18349
+ "--agents": 1,
18350
+ "--settings": 1,
18351
+ "--setting-sources": 1,
18352
+ "--system-prompt": 1,
18353
+ "--append-system-prompt": 1,
18354
+ "--autocompact": 1,
18355
+ "-n": 1,
18356
+ "--name": 1,
18357
+ "--debug-file": 1,
18358
+ "--add-dir": "*",
18359
+ "--mcp-config": "*",
18360
+ "--plugin-dir": "*",
18361
+ "--allowedTools": "*",
18362
+ "--allowed-tools": "*",
18363
+ "--disallowedTools": "*",
18364
+ "--disallowed-tools": "*",
18365
+ "--tools": "*",
18366
+ "--betas": "*",
18367
+ "--dangerously-skip-permissions": 0,
18368
+ "--allow-dangerously-skip-permissions": 0,
18369
+ "--verbose": 0,
18370
+ "--ide": 0,
18371
+ "--chrome": 0,
18372
+ "--no-chrome": 0,
18373
+ "--strict-mcp-config": 0,
18374
+ "--bare": 0,
18375
+ "--brief": 0,
18376
+ "--disable-slash-commands": 0,
18377
+ "--safe-mode": 0,
18378
+ "--restricted": 0
18379
+ },
18380
+ // Conversation choice, one-off launch or already done (worktree created).
18381
+ drop: {
18382
+ "-c": 0,
18383
+ "--continue": 0,
18384
+ "-r": "?",
18385
+ "--resume": "?",
18386
+ "--session-id": 1,
18387
+ "--fork-session": 0,
18388
+ "-w": "?",
18389
+ "--worktree": "?",
18390
+ "--tmux": 0,
18391
+ "--from-pr": "?",
18392
+ "--teleport": "?",
18393
+ "-p": 0,
18394
+ "--print": 0,
18395
+ "--bg": 0,
18396
+ "--background": 0,
18397
+ "--remote-control": "?",
18398
+ "--cloud": "?",
18399
+ "--file": "*",
18400
+ "-d": "?",
18401
+ "--debug": "?"
18402
+ }
18403
+ };
18404
+ const CODEX = {
18405
+ keep: {
18406
+ "-c": 1,
18407
+ "--config": 1,
18408
+ "--enable": 1,
18409
+ "--disable": 1,
18410
+ "-m": 1,
18411
+ "--model": 1,
18412
+ "--local-provider": 1,
18413
+ "-p": 1,
18414
+ "--profile": 1,
18415
+ "-s": 1,
18416
+ "--sandbox": 1,
18417
+ "-C": 1,
18418
+ "--cd": 1,
18419
+ "--add-dir": 1,
18420
+ "-a": 1,
18421
+ "--ask-for-approval": 1,
18422
+ "--remote": 1,
18423
+ "--remote-auth-token-env": 1,
18424
+ "--oss": 0,
18425
+ "--search": 0,
18426
+ "--no-alt-screen": 0,
18427
+ "--no-daemon": 0,
18428
+ "--full-auto": 0,
18429
+ "--dangerously-bypass-approvals-and-sandbox": 0,
18430
+ "--yolo": 0,
18431
+ "--approve-for-me": 0,
18432
+ "--strict-config": 0,
18433
+ "--dangerously-bypass-hook-trust": 0
18434
+ },
18435
+ drop: { "--last": 0, "--all": 0, "--include-non-interactive": 0, "-i": "*", "--image": "*", "--worktree": 0 }
18436
+ };
18437
+ const OMP = {
18438
+ keep: {
18439
+ "--model": 1,
18440
+ "--smol": 1,
18441
+ "--slow": 1,
18442
+ "--plan": 1,
18443
+ "--prewalk-into": 1,
18444
+ "--plan-yolo-into": 1,
18445
+ "--provider": 1,
18446
+ "--system-prompt": 1,
18447
+ "--system-prompt-template": 1,
18448
+ "--append-system-prompt": 1,
18449
+ "--profile": 1,
18450
+ "--cwd": 1,
18451
+ "--config": 1,
18452
+ "--add-dir": 1,
18453
+ "--session-dir": 1,
18454
+ "--models": 1,
18455
+ "--tools": 1,
18456
+ "--thinking": 1,
18457
+ "--service-tier": 1,
18458
+ "--hook": 1,
18459
+ "-e": 1,
18460
+ "--extension": 1,
18461
+ "--skills": 1,
18462
+ "--approval-mode": 1,
18463
+ "--plugin-dir": 1,
18464
+ "--allow-home": 0,
18465
+ "--prewalk": 0,
18466
+ "--no-prewalk": 0,
18467
+ "--no-tools": 0,
18468
+ "--no-lsp": 0,
18469
+ "--no-pty": 0,
18470
+ "--hide-thinking": 0,
18471
+ "--advisor": 0,
18472
+ "--external-thinking": 0,
18473
+ "--no-extensions": 0,
18474
+ "--no-skills": 0,
18475
+ "--no-rules": 0,
18476
+ "--no-title": 0,
18477
+ "--auto-approve": 0
18478
+ },
18479
+ // Conversation choice, one-off launch; the API key is never replayed
18480
+ // (it would show in the confirmation).
18481
+ drop: {
18482
+ "-c": 0,
18483
+ "--continue": 0,
18484
+ "-r": "?",
18485
+ "--resume": "?",
18486
+ "-p": 0,
18487
+ "--print": 0,
18488
+ "--plan-yolo": 0,
18489
+ "--from-claude": 0,
18490
+ "--from-codex": 0,
18491
+ "--no-session": 0,
18492
+ "--export": 1,
18493
+ "--mode": 1,
18494
+ "--max-time": 1,
18495
+ "--alias": 1,
18496
+ "--api-key": 1,
18497
+ "--no-ui": 0,
18498
+ "--print-thoughts": 0
18499
+ }
18500
+ };
18501
+ const SILENT = /* @__PURE__ */ new Set(["-c", "--continue", "-r", "--resume", "--session-id", "--fork-session", "--last", "--all"]);
18502
+ const SPECS = { claude: CLAUDE, codex: CODEX, omp: OMP };
18503
+ const RESTARTABLE = new Set(Object.keys(SPECS));
18504
+ const base$1 = (s) => s.replace(/^.*\//, "").replace(/\.(c?js|mjs)$/, "");
18505
+ function launchOptions(kind, argv) {
18506
+ const spec = SPECS[kind];
18507
+ const kept = [];
18508
+ const dropped = [];
18509
+ if (!spec) return { kept, dropped };
18510
+ let i = argv.findIndex((a) => base$1(a) === kind);
18511
+ i = i < 0 ? 1 : i + 1;
18512
+ for (; i < argv.length; i++) {
18513
+ const a = argv[i];
18514
+ if (a === "--") break;
18515
+ if (!a.startsWith("-") || a === "-") continue;
18516
+ const eq = a.indexOf("=");
18517
+ const flag = eq > 0 ? a.slice(0, eq) : a;
18518
+ const keep = flag in spec.keep;
18519
+ const arity = keep ? spec.keep[flag] : spec.drop[flag];
18520
+ const out = [a];
18521
+ if (keep) kept.push(out);
18522
+ else if (!SILENT.has(flag)) dropped.push(out);
18523
+ if (arity === void 0) {
18524
+ if (eq < 0 && argv[i + 1] !== void 0 && !argv[i + 1].startsWith("-")) out.push(argv[++i]);
18525
+ continue;
18526
+ }
18527
+ if (eq > 0 || arity === 0) continue;
18528
+ if (arity === 1) {
18529
+ if (argv[i + 1] !== void 0) out.push(argv[++i]);
18530
+ continue;
18531
+ }
18532
+ while (argv[i + 1] !== void 0 && !argv[i + 1].startsWith("-")) {
18533
+ out.push(argv[++i]);
18534
+ if (arity === "?") break;
18535
+ }
18536
+ }
18537
+ return { kept, dropped };
18538
+ }
18539
+ const EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
18540
+ function planRestart(o) {
18541
+ const opts = o.argv ? launchOptions(o.kind, o.argv) : { kept: [], dropped: [] };
18542
+ const mode = o.session ? "resume" : o.hadSession ? "fresh" : "continue";
18543
+ let groups = opts.kept;
18544
+ const without = (...flags) => {
18545
+ groups = groups.filter((g) => !flags.includes(g[0].split("=")[0]));
18546
+ };
18547
+ if (o.kind === "omp" && mode === "resume") without("--model", "--thinking");
18548
+ if (o.kind === "claude") {
18549
+ const cur = o.current || {};
18550
+ if (mode === "resume") without("--model");
18551
+ const effort = String(cur.effort || "").toLowerCase();
18552
+ if (EFFORTS.has(effort)) {
18553
+ without("--effort");
18554
+ groups.push(["--effort", effort]);
18555
+ }
18556
+ if (cur.permissionMode) {
18557
+ without("--permission-mode");
18558
+ if (cur.permissionMode !== "default") groups.push(["--permission-mode", cur.permissionMode]);
18559
+ }
18560
+ }
18561
+ const kept = groups.flat();
18562
+ const dropped = opts.dropped.flat();
18563
+ let args;
18564
+ if (o.kind === "codex") {
18565
+ args = mode === "fresh" ? kept : ["resume", ...kept, mode === "resume" ? o.session : "--last"];
18566
+ } else {
18567
+ args = mode === "resume" ? [...kept, "--resume", o.session] : mode === "continue" ? [...kept, "--continue"] : kept;
18568
+ }
18569
+ return { args, mode, kept, dropped, unknownArgs: !o.argv };
18570
+ }
18571
+ const FOOTER_MODES = [
18572
+ [/\bplan mode on\b/i, "plan"],
18573
+ [/\baccept edits on\b/i, "acceptEdits"],
18574
+ [/\bauto mode on\b/i, "auto"],
18575
+ [/\bbypass permissions on\b/i, "bypassPermissions"],
18576
+ [/\bdon'?t ask (?:mode )?on\b/i, "dontAsk"]
18577
+ ];
18578
+ function claudeFooterMode(text) {
18579
+ const lines = String(text || "").split("\n");
18580
+ let rule = -1;
18581
+ for (let i = lines.length - 1; i >= 0 && rule < 0; i--) if (/^\s*─{20,}\s*$/.test(lines[i])) rule = i;
18582
+ if (rule < 1 || !lines.slice(Math.max(0, rule - 6), rule).some((l) => /^\s*❯/.test(l))) return null;
18583
+ for (const l of lines.slice(rule + 1)) {
18584
+ for (const [re, mode] of FOOTER_MODES) if (re.test(l)) return mode;
18585
+ }
18586
+ return "default";
18587
+ }
18588
+
18589
+ function updateShellSignature(text) {
18590
+ const lines = text.replace(/\r/g, "").trimEnd().split("\n");
18591
+ const end = lines.findLastIndex((l) => /^\s*(?:🎉\s*)?Update ran successfully! Please restart Codex\.\s*$/.test(l));
18592
+ if (end < 0 || !lines.slice(Math.max(0, end - 4), end).some((l) => /^\s*Codex CLI \S+ installed successfully\.\s*$/.test(l))) return null;
18593
+ const tail = lines.slice(end + 1).filter((l) => l.trim());
18594
+ if (!tail.length || tail.length > 2) return null;
18595
+ const last = tail.at(-1);
18596
+ if (!/^\s*(?:[\w@./~:-]+(?: [\w@./~:-]+){0,2} )?[$%#❯]\s*$/.test(last)) return null;
18597
+ if (tail.length === 2 && (!/^\s*[\w./~:-]+ on [\w./:-]+\s*$/.test(tail[0]) || !/^\s*❯\s*$/.test(last))) return null;
18598
+ return tail.join("\n");
18599
+ }
18600
+ function updateChoices(launch) {
18601
+ return launch.conversation === "empty" && launch.argv && !launch.argv.some((a) => a === "resume" || a === "fork") ? ["restart"] : ["resume", "fresh"];
18602
+ }
18603
+ const UPDATE_LABELS = {
18604
+ restart: "Restart Codex",
18605
+ resume: "Resume conversation",
18606
+ fresh: "Start fresh"
18607
+ };
18608
+ function updatePrompt(launch) {
18609
+ return {
18610
+ kind: "self-update",
18611
+ question: "Codex updated itself and stopped",
18612
+ cursor: -1,
18613
+ options: updateChoices(launch).map((c) => ({ label: UPDATE_LABELS[c], hint: c === "resume" && !launch.session ? "Choose a conversation in Codex" : null }))
18614
+ };
18615
+ }
18616
+ function updateRestartPlan(launch, choice) {
18617
+ const kept = launch.argv ? launchOptions("codex", launch.argv).kept.flat() : [];
18618
+ let args = choice === "resume" ? ["resume", ...kept, ...launch.session ? [launch.session] : []] : kept;
18619
+ if (choice === "restart" && launch.argv) {
18620
+ const i = launch.argv.findIndex((a) => /(?:^|\/)codex(?:\.[cm]?js)?$/.test(a));
18621
+ if (i >= 0) args = launch.argv.slice(i + 1);
18622
+ }
18623
+ return { args, mode: choice === "resume" ? "resume" : "fresh", kept, dropped: [], unknownArgs: !launch.argv };
18624
+ }
18625
+
18626
+ const base = (s) => s.replace(/^.*\//, "").replace(/\.(c?js|mjs)$/, "");
18627
+ async function paneForeground(d, paneId, kind) {
18628
+ const r = await d.call("pane.process_info", { pane_id: paneId }, 4e3);
18629
+ const info = r && r.process_info || {};
18630
+ const procs = info.foreground_processes || [];
18631
+ const agent = procs.find((p) => p.name === kind || (p.argv || []).some((a) => base(a) === kind)) || null;
18632
+ const atShell = !agent && Boolean(info.shell_pid) && info.foreground_process_group_id === info.shell_pid;
18633
+ const sh = procs.find((p) => info.shell_pid && p.pid === info.shell_pid);
18634
+ const shell = { pid: Number(info.shell_pid) || null, name: sh ? String(sh.name || (sh.argv || [])[0] || "") || null : null };
18635
+ return { agent, atShell, shell, argv: agent && Array.isArray(agent.argv) ? agent.argv.map(String) : null };
18636
+ }
18637
+ async function waitFor(d, ms, test) {
18638
+ const end = d.now() + ms;
18639
+ while (d.now() < end) {
18640
+ await d.sleep(500);
18641
+ try {
18642
+ if (await test()) return true;
18643
+ } catch {
18644
+ }
18645
+ }
18646
+ return false;
18647
+ }
18648
+ const waitShell = (d, paneId, kind, ms) => waitFor(d, ms, async () => (await paneForeground(d, paneId, kind)).atShell);
18649
+ const busy = async (d, paneId) => {
18650
+ const r = await d.call("pane.get", { pane_id: paneId }, 4e3);
18651
+ const s = r && r.pane && r.pane.agent_status;
18652
+ return s === "working" || s === "blocked";
18653
+ };
18654
+ async function stopAgent(d, p) {
18655
+ const kind = p.agent;
18656
+ const key = (k) => d.call("pane.send_input", { pane_id: p.id, keys: [k] });
18657
+ if (p.status === "working" || p.status === "blocked") {
18658
+ for (let i = 0; i < 2; i++) {
18659
+ await key("esc");
18660
+ if (await waitFor(d, 3e3, async () => !await busy(d, p.id))) break;
18661
+ }
18662
+ }
18663
+ await d.call("pane.send_input", { pane_id: p.id, text: "/exit" });
18664
+ await d.sleep(300);
18665
+ await key("enter");
18666
+ if (await waitShell(d, p.id, kind, 8e3)) return "exit";
18667
+ await key("ctrl+c");
18668
+ await d.sleep(400);
18669
+ await key("ctrl+c");
18670
+ if (await waitShell(d, p.id, kind, 6e3)) return "ctrl-c";
18671
+ throw new HerdrError("restart_stop", "the agent did not stop");
18672
+ }
18673
+ async function startAgent(d, p, plan) {
18674
+ const name = p.name || `${p.agent}-${crypto.randomBytes(2).toString("hex")}`;
18675
+ let last = null;
18676
+ for (let i = 0; i < 6; i++) {
18677
+ try {
18678
+ await d.call("agent.start", { name, kind: p.agent, pane_id: p.id, timeout_ms: 6e4, ...plan.args.length ? { args: plan.args } : {} }, 75e3);
18679
+ return;
18680
+ } catch (e) {
18681
+ last = e;
18682
+ if (last.code === "agent_not_ready") return;
18683
+ if (last.code === "timeout" || last.code === "unreachable") break;
18684
+ await d.sleep(500);
18685
+ }
18686
+ }
18687
+ throw last || new HerdrError("restart_start", "the agent did not restart");
18688
+ }
18689
+
18690
+ const AT_SAVE_MS = 60 * 1e3;
18691
+ const OUTAGE_MS = 15e3;
18692
+ function createSelfUpdates(d, saved = []) {
18693
+ const records = new Map(saved);
18694
+ const restored = new Set(records.keys());
18695
+ const stable = () => JSON.stringify([...records].map(([id, r]) => [id, { ...r, at: 0 }]));
18696
+ const times = () => [...records.values()].map((r) => r.at).join();
18697
+ let written = stable();
18698
+ let writtenTimes = times();
18699
+ let writtenAt = d.now();
18700
+ const persist = () => {
18701
+ var _a;
18702
+ const s = stable();
18703
+ if (s === written && (d.now() - writtenAt < AT_SAVE_MS || times() === writtenTimes)) return;
18704
+ written = s;
18705
+ writtenTimes = times();
18706
+ writtenAt = d.now();
18707
+ (_a = d.save) == null ? void 0 : _a.call(d, [...records]);
18708
+ };
18709
+ const read = async (id) => {
18710
+ var _a, _b;
18711
+ 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) || "");
18712
+ };
18713
+ return {
18714
+ get: (id) => records.get(id),
18715
+ clear(id) {
18716
+ records.delete(id);
18717
+ persist();
18718
+ },
18719
+ // Service stopping: keep the exact time Codex was last seen alive, so a
18720
+ // quick restart still tells a short outage from a long one.
18721
+ flush() {
18722
+ var _a;
18723
+ if (records.size) (_a = d.save) == null ? void 0 : _a.call(d, [...records], true);
18724
+ },
18725
+ prune(ids, belongs) {
18726
+ let changed = false;
18727
+ for (const id of records.keys()) if (belongs(id) && !ids.has(id)) {
18728
+ records.delete(id);
18729
+ changed = true;
18730
+ }
18731
+ if (changed) persist();
18732
+ },
18733
+ async observe(p, owned) {
18734
+ var _a, _b, _c, _d;
18735
+ if (owned) return false;
18736
+ let last = records.get(p.id);
18737
+ if (p.agent === "codex") {
18738
+ const fg = await paneForeground(d, p.id, "codex");
18739
+ if (!fg.agent) return false;
18740
+ restored.delete(p.id);
18741
+ const pid = Number(fg.agent.pid);
18742
+ 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) {
18743
+ last.argv = fg.argv || last.argv;
18744
+ persist();
18745
+ return false;
18746
+ }
18747
+ if (!last || last.pid !== pid || last.gone) {
18748
+ last = { pid, pane: { ...p }, at: d.now(), argv: fg.argv, session: null, conversation: "unknown" };
18749
+ records.set(p.id, last);
18750
+ }
18751
+ last.at = d.now();
18752
+ last.argv = fg.argv || last.argv;
18753
+ 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 };
18754
+ const screen = await read(p.id);
18755
+ const chat = await d.chat(p).catch(() => null);
18756
+ if (chat && (chat.guessed || chat.session && chat.session !== last.session)) {
18757
+ if (chat.session !== last.session) last.conversation = "unknown";
18758
+ last.session = null;
18759
+ }
18760
+ if ((chat == null ? void 0 : chat.available) && !chat.guessed && chat.session) {
18761
+ if (last.session && last.session !== chat.session) last.conversation = "unknown";
18762
+ last.session = chat.session;
18763
+ }
18764
+ if ((_a = chat == null ? void 0 : chat.items) == null ? void 0 : _a.some((i) => i.role === "user" || i.role === "assistant")) {
18765
+ last.conversation = "existing";
18766
+ if (!chat.guessed && chat.session) last.session = chat.session;
18767
+ } else if (chat && last.conversation !== "existing") {
18768
+ const startup = /(?:✨\s*)?Update available!|^Updating Codex via /m.test(screen);
18769
+ const witnessedBirth = Boolean(p.bornAt) && !((_b = fg.argv) == null ? void 0 : _b.some((a) => a === "resume" || a === "fork"));
18770
+ if (chat.available && !chat.guessed && !chat.start && !((_c = chat.items) == null ? void 0 : _c.length) || !p.agentSession && !chat.available && (startup || witnessedBirth)) last.conversation = "empty";
18771
+ }
18772
+ last.oldOutput = Boolean(updateShellSignature(screen));
18773
+ persist();
18774
+ return false;
18775
+ }
18776
+ if (!last) return false;
18777
+ if (p.agent) {
18778
+ records.delete(p.id);
18779
+ persist();
18780
+ return false;
18781
+ }
18782
+ if (!last.gone) {
18783
+ if (d.now() - last.at > OUTAGE_MS + (restored.has(p.id) ? AT_SAVE_MS : 0)) last.checked = true;
18784
+ last.gone = d.now();
18785
+ persist();
18786
+ }
18787
+ if (!last.checked) {
18788
+ if (d.now() - last.gone < 3e3) {
18789
+ p.leaving = true;
18790
+ return false;
18791
+ }
18792
+ last.checked = true;
18793
+ if (d.now() - last.gone < 15e3 && !last.oldOutput && (await paneForeground(d, p.id, "codex")).atShell) {
18794
+ last.signature = updateShellSignature(await read(p.id)) || void 0;
18795
+ if (last.signature) {
18796
+ const chat = await d.chat(last.pane).catch(() => null);
18797
+ if (!chat || chat.guessed || !chat.available && last.session) {
18798
+ if (last.conversation === "empty") last.conversation = "unknown";
18799
+ }
18800
+ if (chat && (chat.guessed || chat.session && chat.session !== last.session)) last.session = null;
18801
+ if ((chat == null ? void 0 : chat.available) && !chat.guessed && chat.session) last.session = chat.session;
18802
+ if ((_d = chat == null ? void 0 : chat.items) == null ? void 0 : _d.some((i) => i.role === "user" || i.role === "assistant")) {
18803
+ last.conversation = "existing";
18804
+ if (!chat.guessed && chat.session) last.session = chat.session;
18805
+ else if (chat.session !== last.session) last.session = null;
18806
+ }
18807
+ }
18808
+ }
18809
+ persist();
18810
+ }
18811
+ if (!last.signature) return false;
18812
+ p.agent = "codex";
18813
+ p.name = last.pane.name;
18814
+ p.title = last.pane.title;
18815
+ p.agentSession = last.session;
18816
+ p.bornAt = last.pane.bornAt;
18817
+ p.status = "blocked";
18818
+ p.stopped = { reason: "update" };
18819
+ p.prompt = updatePrompt(last);
18820
+ return true;
18821
+ },
18822
+ async check(id) {
18823
+ const last = records.get(id);
18824
+ if (!(last == null ? void 0 : last.signature) || !(await paneForeground(d, id, "codex")).atShell) return null;
18825
+ return updateShellSignature(await read(id)) === last.signature ? last : null;
18826
+ }
18827
+ };
18828
+ }
18829
+
18119
18830
  var _a, _b;
18120
18831
  const fsp$1 = fs.promises;
18121
18832
  function trFor(p) {
@@ -18165,17 +18876,22 @@ function watchScreen(paneId, ms = 6e4) {
18165
18876
  const choicesCache = /* @__PURE__ */ new Map();
18166
18877
  const askChecks = /* @__PURE__ */ new Map();
18167
18878
  async function choicesFor(p, rev, strict, watch = false) {
18879
+ if (modelControlBusy(p.id)) {
18880
+ choicesCache.delete(p.id);
18881
+ return { choices: null, screen: null, menu: null, interaction: "managed" };
18882
+ }
18168
18883
  const c = choicesCache.get(p.id);
18169
18884
  const watched = (screenWatch.get(p.id) || 0) > Date.now();
18170
18885
  if (!watched) screenWatch.delete(p.id);
18171
- if (c && keepReading(c, rev, strict, watch || watched, Date.now())) return c;
18886
+ if (c && !(p.status === "unknown" && c.interaction === "terminal") && keepReading(c, rev, strict, watch || watched, Date.now())) return c;
18172
18887
  let out;
18173
18888
  try {
18174
18889
  const r = await herdr("pane.read", { pane_id: p.id, source: "detection" }, 4e3);
18175
18890
  const text = r.read && r.read.text;
18176
18891
  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;
18892
+ const usageLimit = p.status === "unknown" ? null : parseUsageLimit(String(text || ""), p.agent);
18893
+ let choices = usageLimit ? null : p.agent === "omp" ? parseOmpPrompt(text) : parseChoices(text, { strict });
18894
+ const menu = !usageLimit && p.agent !== "omp" && framed && (strict || !choices || !parseChoices(text, { strict: true })) ? await readMenu(p.id) : null;
18179
18895
  if (menu) choices = null;
18180
18896
  if (choices && p.agent === "omp" && !choices.detail) choices = await withOmpTab(p.id, completeOmpAsk(choices, await transcripts.pendingAsk(p).catch(() => [])));
18181
18897
  if (choices && p.agent === "claude") {
@@ -18184,7 +18900,9 @@ async function choicesFor(p, rev, strict, watch = false) {
18184
18900
  choices = completeClaudeAsk(choices, await transcripts.pendingClaudeQuestions(p).catch(() => []), checks);
18185
18901
  } else if (!choices) askChecks.delete(p.id);
18186
18902
  const settings = p.agent === "claude" && settingsTabs(text) !== null;
18187
- out = { choices, screen: menu || settings ? null : parseWaitScreen(text, { choices: Boolean(choices) }), menu };
18903
+ const screen = menu || settings ? null : parseWaitScreen(text, { choices: Boolean(choices) });
18904
+ const interaction = classifyScreen({ text: String(text || ""), agent: p.agent, choices, menu, screen, settings, status: p.status });
18905
+ out = interaction === "terminal" ? { choices: null, screen: null, menu: null, interaction } : { choices, screen: usageLimit ? null : screen, menu, interaction, ...usageLimit ? { usageLimit } : {} };
18188
18906
  noteScreen(p.id, p.agent, text);
18189
18907
  if (choices && (choices.detail || isPermissionQuestion(choices.question))) {
18190
18908
  const named = p.agent === "omp" && choices.detail && choices.detail.tool !== "tool" ? choices.detail.tool : null;
@@ -18194,7 +18912,7 @@ async function choicesFor(p, rev, strict, watch = false) {
18194
18912
  if (p.agent === "omp" && !choices.question && tr) choices.question = `Allow tool: ${tr.tool}`;
18195
18913
  }
18196
18914
  } catch {
18197
- out = { choices: c ? c.choices : null, screen: c ? c.screen : null, menu: c ? c.menu : null };
18915
+ out = { choices: c ? c.choices : null, screen: c ? c.screen : null, menu: c ? c.menu : null, interaction: (c == null ? void 0 : c.interaction) || "unknown", ...(c == null ? void 0 : c.usageLimit) ? { usageLimit: c.usageLimit } : {} };
18198
18916
  }
18199
18917
  choicesCache.set(p.id, { rev, strict, at: Date.now(), ...out });
18200
18918
  return out;
@@ -18345,7 +19063,7 @@ function addQueued(paneId, text, opts = {}) {
18345
19063
  };
18346
19064
  queued.set(paneId, [...list, e]);
18347
19065
  sent.set(paneId, addSent(sent.get(paneId) || [], e.text, e.at));
18348
- return publicEntry(e);
19066
+ return queuedPasted(publicEntry(e));
18349
19067
  }
18350
19068
  const sent = /* @__PURE__ */ new Map();
18351
19069
  const sentText = (paneId, entry, taken = []) => {
@@ -18368,7 +19086,11 @@ const restarting = (paneId) => {
18368
19086
  const GUARD_STATES = /* @__PURE__ */ new Set(["idle", "done", "working"]);
18369
19087
  function sendPrompt(p, text) {
18370
19088
  return withPaneLock(p.id, async () => {
18371
- if (p.agent !== "claude" || !GUARD_STATES.has(p.status || "") || isSlashCommand(text)) return agentPrompt(p.id, text);
19089
+ const now = findPane(p.id);
19090
+ if ((now == null ? void 0 : now.stopped) || (now == null ? void 0 : now.leaving)) {
19091
+ throw new HerdrError(isSlashCommand(text) ? "stale" : "no_input", "Restart Codex before sending a command.");
19092
+ }
19093
+ if (p.agent !== "claude" || !GUARD_STATES.has(p.status || "") || isSlashCommand(text) && !p.usageLimit) return agentPrompt(p.id, text);
18372
19094
  const keep = (texts) => {
18373
19095
  for (const t of texts || []) {
18374
19096
  addQueued(p.id, t, { held: true });
@@ -18405,7 +19127,7 @@ const isBusyError = (e) => e instanceof HerdrError && (e.code === "input_busy" |
18405
19127
  const deliverBusy = /* @__PURE__ */ new Set();
18406
19128
  function deliverHeld(p) {
18407
19129
  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;
19130
+ if (!q || deliverBusy.has(p.id) || !p.agent || p.stopped || !INPUT_STATES.has(p.status || "") || restarting(p.id)) return;
18409
19131
  deliverBusy.add(p.id);
18410
19132
  herdr("pane.read", { pane_id: p.id, source: "detection" }, 4e3).then(async (r) => {
18411
19133
  if (!inputVisible(r.read && r.read.text) || !q.held || q.failed) return;
@@ -18476,13 +19198,14 @@ function retryQueued(paneId, id) {
18476
19198
  q.failed = false;
18477
19199
  q.held = true;
18478
19200
  q.at = Date.now();
19201
+ delete q.back;
18479
19202
  delete q.busy;
18480
19203
  delete q.readySince;
18481
19204
  delete q.turnSeen;
18482
19205
  delete q.stuckSince;
18483
19206
  delete q.noInput;
18484
19207
  setTimeout(poll, 50);
18485
- return publicEntry(q);
19208
+ return queuedPasted(publicEntry(q));
18486
19209
  }
18487
19210
  const reconcileBusy = /* @__PURE__ */ new Set();
18488
19211
  function reconcileQueued(p) {
@@ -18502,7 +19225,7 @@ async function deliveryDone(paneId) {
18502
19225
  }
18503
19226
  async function cancelQueued(paneId, text, id) {
18504
19227
  const p = findPane(paneId);
18505
- if (!p || !p.agent) throw new HerdrError("not_found", "agent not found");
19228
+ if (!p) throw new HerdrError("not_found", "agent not found");
18506
19229
  let mine = findQueued(queued.get(p.id) || [], text, id);
18507
19230
  if (mine && (mine.held || mine.failed) && deliverBusy.has(p.id)) {
18508
19231
  await deliveryDone(p.id);
@@ -18518,6 +19241,7 @@ async function cancelQueued(paneId, text, id) {
18518
19241
  setTimeout(poll, 50);
18519
19242
  return { text: mine.text };
18520
19243
  }
19244
+ if (!p.agent) throw new HerdrError("not_found", "agent not found");
18521
19245
  const pend = pendingPrompts.get(p.id);
18522
19246
  if (pend && !pendingBusy.has(p.id) && sameMsg(msgText(pend.text), msgText(text))) {
18523
19247
  pendingPrompts.delete(p.id);
@@ -18576,6 +19300,41 @@ const pendingBusy = /* @__PURE__ */ new Set();
18576
19300
  const READY = /* @__PURE__ */ new Set(["done", "idle"]);
18577
19301
  const TURN = /* @__PURE__ */ new Set(["working", "blocked"]);
18578
19302
  const restarts = /* @__PURE__ */ new Map();
19303
+ const LAST_AGENTS_FILE = path$1.join(DATA_DIR, "last-agents.json");
19304
+ let lastAgentsWrite = Promise.resolve();
19305
+ const selfUpdates = createSelfUpdates({
19306
+ call: herdr,
19307
+ sleep: sleep$1,
19308
+ now: Date.now,
19309
+ chat: (p) => transcripts.chat(p, { fresh: true }),
19310
+ // Only called when a record changed (see agentSelfUpdate.ts).
19311
+ save: (records, sync) => {
19312
+ const s = JSON.stringify(records) + "\n";
19313
+ if (sync) {
19314
+ try {
19315
+ fs.mkdirSync(DATA_DIR, { recursive: true });
19316
+ fs.writeFileSync(LAST_AGENTS_FILE, s, { mode: 384 });
19317
+ } catch {
19318
+ }
19319
+ return;
19320
+ }
19321
+ lastAgentsWrite = lastAgentsWrite.then(async () => {
19322
+ await fsp$1.mkdir(DATA_DIR, { recursive: true });
19323
+ await fsp$1.writeFile(LAST_AGENTS_FILE, s, { mode: 384 });
19324
+ }).catch(() => {
19325
+ });
19326
+ }
19327
+ }, (() => {
19328
+ try {
19329
+ return JSON.parse(fs.readFileSync(LAST_AGENTS_FILE, "utf8"));
19330
+ } catch {
19331
+ return [];
19332
+ }
19333
+ })());
19334
+ function dismissStopped(paneId) {
19335
+ selfUpdates.clear(paneId);
19336
+ giveBackHeld(queued.get(paneId));
19337
+ }
18579
19338
  function flushPending(p) {
18580
19339
  const pend = pendingPrompts.get(p.id);
18581
19340
  if (!pend || pendingBusy.has(p.id)) return;
@@ -18677,6 +19436,7 @@ async function enrich(next, snap, machine) {
18677
19436
  const firstSnapshot = !seenMachines.has(machine);
18678
19437
  const prevStatus = new Map((((_a2 = mstates.get(machine)) == null ? void 0 : _a2.panes) || []).map((p) => [p.id, p.status || void 0]));
18679
19438
  const live = new Set(next.panes.map((p) => p.id));
19439
+ selfUpdates.prune(live, (id) => machineOf(id) === machine);
18680
19440
  for (const id of commands.keys()) if (machineOf(id) === machine && !live.has(id)) commands.delete(id);
18681
19441
  for (const p of next.panes) {
18682
19442
  const b = agentBorn.get(p.id);
@@ -18701,7 +19461,14 @@ async function enrich(next, snap, machine) {
18701
19461
  seenMachines.add(machine);
18702
19462
  (_b2 = getMachine(machine)) == null ? void 0 : _b2.transcripts.observe(next.panes);
18703
19463
  const revs = new Map((snap.panes || []).map((p) => [joinId(machine, p.pane_id), p.revision]));
18704
- for (const p of next.panes) {
19464
+ const exited = await Promise.all(next.panes.map((p) => selfUpdates.observe(p, restarts.has(p.id)).catch(() => false)));
19465
+ for (const [i, p] of next.panes.entries()) {
19466
+ if (exited[i]) {
19467
+ p.interaction = "managed";
19468
+ if (queued.has(p.id)) p.queued = queued.get(p.id).map((q) => queuedPasted(publicEntry(q)));
19469
+ continue;
19470
+ }
19471
+ if (leftForGood(p, findPane(p.id))) giveBackHeld(queued.get(p.id));
18705
19472
  if (pendingPrompts.has(p.id)) {
18706
19473
  p.pendingPrompt = true;
18707
19474
  flushPending(p);
@@ -18716,13 +19483,13 @@ async function enrich(next, snap, machine) {
18716
19483
  else queued.delete(p.id);
18717
19484
  }
18718
19485
  const list = queued.get(p.id);
18719
- const menu = Boolean(before && (before.menu || before.prompt || before.screen)) || restarting(p.id);
19486
+ const menu = Boolean(before && (before.menu || before.prompt || before.screen || before.interaction === "terminal")) || restarting(p.id);
18720
19487
  if (list && TURN.has(p.status || "")) {
18721
19488
  for (const q of list) if (!q.held && !q.failed) q.turnSeen = true;
18722
19489
  }
18723
19490
  if (list && checkQueue(list, (before == null ? void 0 : before.ompShell) ? "working" : p.status, Date.now(), menu)) log(`message not sent on ${p.id}`);
18724
19491
  if (list) deliverHeld(p);
18725
- if (list && list.length) p.queued = list.map(publicEntry);
19492
+ if (list && list.length) p.queued = list.map((q) => queuedPasted(publicEntry(q)));
18726
19493
  }
18727
19494
  const rs = restarts.get(p.id);
18728
19495
  if (rs && rs.phase === "failed" && (p.agent && rs.stopped || Date.now() - rs.at > 6e5)) restarts.delete(p.id);
@@ -18740,10 +19507,16 @@ async function enrich(next, snap, machine) {
18740
19507
  if (p.status !== "working") {
18741
19508
  const young = !p.agentSession || p.bornAt && Date.now() - p.bornAt < 12e4;
18742
19509
  const c = await choicesFor(p, revs.get(p.id), p.status !== "blocked", Boolean(young));
19510
+ p.interaction = c.interaction;
19511
+ if (c.usageLimit) {
19512
+ p.usageLimit = c.usageLimit;
19513
+ p.status = "idle";
19514
+ }
18743
19515
  if (c.choices) p.prompt = c.choices;
18744
19516
  if (c.screen) p.screen = c.screen;
18745
19517
  if (c.menu) p.menu = c.menu;
18746
19518
  } else {
19519
+ p.interaction = "working";
18747
19520
  choicesCache.delete(p.id);
18748
19521
  askChecks.delete(p.id);
18749
19522
  }
@@ -18928,14 +19701,17 @@ const localMachineOf = (ms) => ms.find((m) => m.local);
18928
19701
  function stopPolling() {
18929
19702
  stopped = true;
18930
19703
  if (pollTimer) clearTimeout(pollTimer);
19704
+ selfUpdates.flush();
18931
19705
  }
18932
19706
  const notifyTimers = /* @__PURE__ */ new Map();
18933
19707
  function watchTransitions(prev, next) {
19708
+ var _a2;
18934
19709
  const before = new Map(prev.panes.map((p) => [p.id, p.status]));
18935
19710
  for (const p of next.panes) {
18936
19711
  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 || ""))) {
19712
+ const updated = p.stopped && !((_a2 = prev.panes.find((x) => x.id === p.id)) == null ? void 0 : _a2.stopped);
19713
+ if (!p.agent || was === p.status && !updated) continue;
19714
+ if (updated || was === "working" && (p.status === "blocked" || READY.has(p.status || ""))) {
18939
19715
  clearTimeout(notifyTimers.get(p.id));
18940
19716
  const target = p.status;
18941
19717
  notifyTimers.set(p.id, setTimeout(() => {
@@ -19737,13 +20513,25 @@ function hostAllowed(host, names = allowedHosts()) {
19737
20513
  function hostRefusalIsHtml(path, accept) {
19738
20514
  return !path.startsWith("/api/") && /\btext\/html\b/i.test(Array.isArray(accept) ? accept.join(",") : accept || "");
19739
20515
  }
19740
- function phoneFixCommand(install = process.env.WHERDR_INSTALL || "") {
19741
- if (install === "brew" || install === "npm-global") return "wherdr phone";
20516
+ const CLI_DEFAULT_PORT = "7683";
20517
+ function phoneFixCommand(install = process.env.WHERDR_INSTALL || "", port = process.env.NITRO_PORT || process.env.PORT || "") {
19742
20518
  if (install === "docker" || install === "docker-build" || install === "plugin") return "curl -fsSL https://wherdr.dev/install | sh";
19743
- return "npx wherdr phone";
20519
+ const command = install === "brew" || install === "npm-global" ? "wherdr phone" : "npx wherdr phone";
20520
+ return /^\d+$/.test(port) && port !== CLI_DEFAULT_PORT ? `${command} --port ${port}` : command;
19744
20521
  }
19745
- function hostRefusedPage(install) {
19746
- const command = phoneFixCommand(install);
20522
+ function tailnetName(host) {
20523
+ return /\.ts\.net$/.test(hostname(host || "") || "");
20524
+ }
20525
+ function hostRefusedPage(install, host, port) {
20526
+ var _a;
20527
+ const kind = (_a = process.env.WHERDR_INSTALL) != null ? _a : "";
20528
+ const command = phoneFixCommand(kind, port);
20529
+ const docker = kind === "docker" || kind === "docker-build";
20530
+ const where = docker ? "in the container's environment" : "in <code>~/wherdr/wherdr.env</code>";
20531
+ const whereFr = docker ? "dans l\u2019environnement du conteneur" : "dans <code>~/wherdr/wherdr.env</code>";
20532
+ const other = !tailnetName(host);
20533
+ 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.";
20534
+ 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
20535
  return `<!doctype html>
19748
20536
  <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
19749
20537
  <meta name="robots" content="noindex"><title>wherdr \xB7 address not enabled</title>
@@ -19753,18 +20541,20 @@ body{margin:0;min-height:100vh;display:grid;place-items:center;background:#0d0f1
19753
20541
  main{max-width:480px;border:1px solid #3a3f47;padding:24px}
19754
20542
  .tag{font:11px/1 "JetBrains Mono",ui-monospace,monospace;letter-spacing:.08em;text-transform:uppercase;color:#9aa0a8;margin:0 0 16px}
19755
20543
  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}
20544
+ 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}
20545
+ code{font:13px/1.45 "JetBrains Mono",ui-monospace,monospace;overflow-wrap:anywhere}
19758
20546
  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
20547
  </style></head><body><main>
19760
20548
  <p class="tag">wherdr \xB7 403</p>
19761
20549
  <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>
20550
+ <p>${serve} On the machine that runs wherdr, run this, then reload:</p>
20551
+ <pre><code>${command}</code></pre>${other ? `
20552
+ <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
20553
  <hr>
19765
20554
  <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>
20555
+ <p lang="fr">${serveFr} Sur la machine qui fait tourner wherdr, lance ceci, puis recharge :</p>
20556
+ <pre><code>${command}</code></pre>${other ? `
20557
+ <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
20558
  </main></body></html>
19769
20559
  `;
19770
20560
  }
@@ -20356,9 +21146,11 @@ const _mZt23IdRC2vLuqDtWT6mb7m9BgHXq3U5QrnQ7Z5Hc4c = defineNitroPlugin((nitroApp
20356
21146
  startTailnetWatch();
20357
21147
  cleanUploads();
20358
21148
  cleanAttachments();
21149
+ purgePastes();
20359
21150
  const purge = setInterval(() => {
20360
21151
  cleanUploads();
20361
21152
  cleanAttachments();
21153
+ purgePastes();
20362
21154
  }, 6 * 3600 * 1e3);
20363
21155
  log(`herdr-web \u2014 socket ${HERDR_SOCK}${HERDR_SESSION ? ` (session ${HERDR_SESSION})` : ""}`);
20364
21156
  nitroApp.hooks.hook("close", () => {
@@ -20380,394 +21172,408 @@ const assets = {
20380
21172
  "/manifest-en.webmanifest": {
20381
21173
  "type": "application/manifest+json",
20382
21174
  "etag": "\"260-q1JnCK0/ecdKwgeTve6N4I6/mWI\"",
20383
- "mtime": "2026-10-10T00:24:14.956Z",
21175
+ "mtime": "2026-10-12T02:43:06.055Z",
20384
21176
  "size": 608,
20385
21177
  "path": "../public/manifest-en.webmanifest"
20386
21178
  },
20387
21179
  "/manifest.webmanifest": {
20388
21180
  "type": "application/manifest+json",
20389
21181
  "etag": "\"26e-ykoYuj4V8la457yChW3oQTur8RU\"",
20390
- "mtime": "2026-10-10T00:24:14.956Z",
21182
+ "mtime": "2026-10-12T02:43:06.055Z",
20391
21183
  "size": 622,
20392
21184
  "path": "../public/manifest.webmanifest"
20393
21185
  },
20394
21186
  "/sw.js": {
20395
21187
  "type": "text/javascript; charset=utf-8",
20396
- "etag": "\"1b1d-wHdIux7mWagbphlmnadZ+jdW3jQ\"",
20397
- "mtime": "2026-10-10T00:24:15.363Z",
20398
- "size": 6941,
21188
+ "etag": "\"1b75-QHSGlFHPf7wCrgMEz9tF99j/HQQ\"",
21189
+ "mtime": "2026-10-12T02:43:06.452Z",
21190
+ "size": 7029,
20399
21191
  "path": "../public/sw.js"
20400
21192
  },
20401
- "/_nuxt/AgentView.C4YOwvZG.css": {
21193
+ "/_nuxt/AgentView.DzFWBd2A.css": {
20402
21194
  "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"
21195
+ "etag": "\"16c2-oz6EmjJDgIf6r38fC9pJHsZoJww\"",
21196
+ "mtime": "2026-10-12T02:43:06.045Z",
21197
+ "size": 5826,
21198
+ "path": "../public/_nuxt/AgentView.DzFWBd2A.css"
21199
+ },
21200
+ "/_nuxt/B4Yk2tB1.js": {
21201
+ "type": "text/javascript; charset=utf-8",
21202
+ "etag": "\"1176f-Op3w8R2G8EFcEwxudNsoKLq8Fl8\"",
21203
+ "mtime": "2026-10-12T02:43:06.045Z",
21204
+ "size": 71535,
21205
+ "path": "../public/_nuxt/B4Yk2tB1.js"
21206
+ },
21207
+ "/_nuxt/BBw_0a4M.js": {
21208
+ "type": "text/javascript; charset=utf-8",
21209
+ "etag": "\"17b75-3R2VJP1Oq7OKRMe/1iHRMGe6l3o\"",
21210
+ "mtime": "2026-10-12T02:43:06.045Z",
21211
+ "size": 97141,
21212
+ "path": "../public/_nuxt/BBw_0a4M.js"
20407
21213
  },
20408
- "/_nuxt/B7QP1TFs.js": {
21214
+ "/_nuxt/BSy6OCIY.js": {
20409
21215
  "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"
21216
+ "etag": "\"13f-1QDhbXhMYI+YPIbMXZLiVqG81SU\"",
21217
+ "mtime": "2026-10-12T02:43:06.045Z",
21218
+ "size": 319,
21219
+ "path": "../public/_nuxt/BSy6OCIY.js"
20414
21220
  },
20415
- "/_nuxt/BDNMzG2s.js": {
21221
+ "/_nuxt/BX5PM2JQ.js": {
20416
21222
  "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"
21223
+ "etag": "\"2905-uwamdHajAQRD2qCUB0gaMXs5+Hs\"",
21224
+ "mtime": "2026-10-12T02:43:06.045Z",
21225
+ "size": 10501,
21226
+ "path": "../public/_nuxt/BX5PM2JQ.js"
20421
21227
  },
20422
21228
  "/_nuxt/Bd17z0YL.js": {
20423
21229
  "type": "text/javascript; charset=utf-8",
20424
21230
  "etag": "\"1615-CPDn06/EO3pj6KudXz5uMZ0FkhI\"",
20425
- "mtime": "2026-10-10T00:24:14.946Z",
21231
+ "mtime": "2026-10-12T02:43:06.045Z",
20426
21232
  "size": 5653,
20427
21233
  "path": "../public/_nuxt/Bd17z0YL.js"
20428
21234
  },
20429
- "/_nuxt/BOpBIziZ.js": {
20430
- "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"
20435
- },
20436
- "/_nuxt/CWwyK2XK.js": {
21235
+ "/_nuxt/BgPDnf2S.js": {
20437
21236
  "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"
21237
+ "etag": "\"14010-9tQrbfc74ogfocj+ZMU5WrK9qEM\"",
21238
+ "mtime": "2026-10-12T02:43:06.045Z",
21239
+ "size": 81936,
21240
+ "path": "../public/_nuxt/BgPDnf2S.js"
20442
21241
  },
20443
- "/_nuxt/CXG-cOdh.js": {
21242
+ "/_nuxt/BkOxQzbS.js": {
20444
21243
  "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"
21244
+ "etag": "\"91a1-Cc5iImaS93KRPJgLU4sZS6Cewjk\"",
21245
+ "mtime": "2026-10-12T02:43:06.045Z",
21246
+ "size": 37281,
21247
+ "path": "../public/_nuxt/BkOxQzbS.js"
20449
21248
  },
20450
- "/_nuxt/BWXdFfeg.js": {
21249
+ "/_nuxt/CP8o925U.js": {
20451
21250
  "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"
21251
+ "etag": "\"238-L5f/T9nwmMze/S7MlkAtOw2Agko\"",
21252
+ "mtime": "2026-10-12T02:43:06.045Z",
21253
+ "size": 568,
21254
+ "path": "../public/_nuxt/CP8o925U.js"
20456
21255
  },
20457
- "/_nuxt/Cd8j9O5w.js": {
21256
+ "/_nuxt/CWwyK2XK.js": {
20458
21257
  "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"
21258
+ "etag": "\"7e5e-4BG2J9cvS3sx6WQ360LFqNaThyA\"",
21259
+ "mtime": "2026-10-12T02:43:06.045Z",
21260
+ "size": 32350,
21261
+ "path": "../public/_nuxt/CWwyK2XK.js"
20463
21262
  },
20464
- "/_nuxt/COFCNFpG.js": {
21263
+ "/_nuxt/CkbmecwS.js": {
20465
21264
  "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"
21265
+ "etag": "\"f35-4fKoqAhIJbV/rJjyeg24lmHsFBg\"",
21266
+ "mtime": "2026-10-12T02:43:06.046Z",
21267
+ "size": 3893,
21268
+ "path": "../public/_nuxt/CkbmecwS.js"
20470
21269
  },
20471
21270
  "/_nuxt/Ci8N4mWR.js": {
20472
21271
  "type": "text/javascript; charset=utf-8",
20473
21272
  "etag": "\"2426-fCrTYUyhtdHnTmu6ZJeEttvxVMo\"",
20474
- "mtime": "2026-10-10T00:24:14.947Z",
21273
+ "mtime": "2026-10-12T02:43:06.045Z",
20475
21274
  "size": 9254,
20476
21275
  "path": "../public/_nuxt/Ci8N4mWR.js"
20477
21276
  },
20478
- "/_nuxt/CkZ8t6uB.js": {
21277
+ "/_nuxt/Cr3SrGky.js": {
20479
21278
  "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"
21279
+ "etag": "\"e91-L57+rnkmURnrnbQ2ojMRXvZSac4\"",
21280
+ "mtime": "2026-10-12T02:43:06.046Z",
21281
+ "size": 3729,
21282
+ "path": "../public/_nuxt/Cr3SrGky.js"
20484
21283
  },
20485
- "/_nuxt/D7sxNXx1.js": {
21284
+ "/_nuxt/DT8qZ0Wv.js": {
20486
21285
  "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"
21286
+ "etag": "\"d34-pCkp/XrEPhSiS8s2YPYsI/DZ69I\"",
21287
+ "mtime": "2026-10-12T02:43:06.046Z",
21288
+ "size": 3380,
21289
+ "path": "../public/_nuxt/DT8qZ0Wv.js"
21290
+ },
21291
+ "/_nuxt/DAg9fiVh.js": {
21292
+ "type": "text/javascript; charset=utf-8",
21293
+ "etag": "\"1b244-sPLH9gYhaVJ89ISuFCDsYuNF9Vs\"",
21294
+ "mtime": "2026-10-12T02:43:06.046Z",
21295
+ "size": 111172,
21296
+ "path": "../public/_nuxt/DAg9fiVh.js"
20491
21297
  },
20492
- "/_nuxt/DViwOclv.js": {
21298
+ "/_nuxt/DaaJIRB3.js": {
20493
21299
  "type": "text/javascript; charset=utf-8",
20494
- "etag": "\"10a-+H4vdCMSTz83KYVa6X+gWZCDDow\"",
20495
- "mtime": "2026-10-10T00:24:14.947Z",
21300
+ "etag": "\"dd3-CbFoaT3rUHg6B+v1747rxTekQNQ\"",
21301
+ "mtime": "2026-10-12T02:43:06.046Z",
21302
+ "size": 3539,
21303
+ "path": "../public/_nuxt/DaaJIRB3.js"
21304
+ },
21305
+ "/_nuxt/DcJi16XA.js": {
21306
+ "type": "text/javascript; charset=utf-8",
21307
+ "etag": "\"10a-fvmuAmno7y+Lve3V9/nvXuQHotk\"",
21308
+ "mtime": "2026-10-12T02:43:06.046Z",
20496
21309
  "size": 266,
20497
- "path": "../public/_nuxt/DViwOclv.js"
21310
+ "path": "../public/_nuxt/DcJi16XA.js"
20498
21311
  },
20499
- "/_nuxt/DyBZDSCV.js": {
21312
+ "/_nuxt/SiL1FJ5s.js": {
20500
21313
  "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"
21314
+ "etag": "\"176ad-/hlyeMkW67OV1A4G2nhIsYJX+vE\"",
21315
+ "mtime": "2026-10-12T02:43:06.046Z",
21316
+ "size": 95917,
21317
+ "path": "../public/_nuxt/SiL1FJ5s.js"
20505
21318
  },
20506
- "/_nuxt/DoD7Qb5P.js": {
21319
+ "/_nuxt/VpjCgSXu.js": {
20507
21320
  "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"
21321
+ "etag": "\"5b489-LoKHy0L+KBvwlf0JAvODFbMFL2o\"",
21322
+ "mtime": "2026-10-12T02:43:06.046Z",
21323
+ "size": 373897,
21324
+ "path": "../public/_nuxt/VpjCgSXu.js"
20512
21325
  },
20513
21326
  "/_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2": {
20514
21327
  "type": "font/woff2",
20515
21328
  "etag": "\"7f60-cwHN4xD2RhU0GVBfKzpzYZ7Al6U\"",
20516
- "mtime": "2026-10-10T00:24:14.947Z",
21329
+ "mtime": "2026-10-12T02:43:06.046Z",
20517
21330
  "size": 32608,
20518
21331
  "path": "../public/_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2"
20519
21332
  },
20520
21333
  "/_nuxt/archivo-latin-wght-normal.E0tuGl4L.woff2": {
20521
21334
  "type": "font/woff2",
20522
21335
  "etag": "\"8870-ZUSfFgU3jYpWYbszVY1rxpynehc\"",
20523
- "mtime": "2026-10-10T00:24:14.947Z",
21336
+ "mtime": "2026-10-12T02:43:06.046Z",
20524
21337
  "size": 34928,
20525
21338
  "path": "../public/_nuxt/archivo-latin-wght-normal.E0tuGl4L.woff2"
20526
21339
  },
21340
+ "/_nuxt/CKhgznq4.js": {
21341
+ "type": "text/javascript; charset=utf-8",
21342
+ "etag": "\"a7330-Q9O7D5hd37aKtqvr2vkiACwyZzM\"",
21343
+ "mtime": "2026-10-12T02:43:06.046Z",
21344
+ "size": 684848,
21345
+ "path": "../public/_nuxt/CKhgznq4.js"
21346
+ },
20527
21347
  "/_nuxt/archivo-vietnamese-wght-normal.XAtsl5Q_.woff2": {
20528
21348
  "type": "font/woff2",
20529
21349
  "etag": "\"33b8-4zjQHgOy7y9EDRZs7TDAFDM4Ams\"",
20530
- "mtime": "2026-10-10T00:24:14.947Z",
21350
+ "mtime": "2026-10-12T02:43:06.046Z",
20531
21351
  "size": 13240,
20532
21352
  "path": "../public/_nuxt/archivo-vietnamese-wght-normal.XAtsl5Q_.woff2"
20533
21353
  },
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": {
20542
- "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"
20547
- },
20548
- "/_nuxt/8ksjcuDu.js": {
21354
+ "/_nuxt/dPxB2L94.js": {
20549
21355
  "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"
21356
+ "etag": "\"471ad-4Pu+hTmytPNTQQ7hdBgH0D/hZVE\"",
21357
+ "mtime": "2026-10-12T02:43:06.046Z",
21358
+ "size": 291245,
21359
+ "path": "../public/_nuxt/dPxB2L94.js"
20554
21360
  },
20555
- "/_nuxt/bLP7Jj-b.js": {
20556
- "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"
21361
+ "/_nuxt/error-500.Bwd7zAaE.css": {
21362
+ "type": "text/css; charset=utf-8",
21363
+ "etag": "\"772-nqXXACYtFiPK+D42BNu4uEECARA\"",
21364
+ "mtime": "2026-10-12T02:43:06.046Z",
21365
+ "size": 1906,
21366
+ "path": "../public/_nuxt/error-500.Bwd7zAaE.css"
20561
21367
  },
20562
21368
  "/_nuxt/error-404.Bb87HomL.css": {
20563
21369
  "type": "text/css; charset=utf-8",
20564
21370
  "etag": "\"97d-4h9VfBznldxjqagfMldh1hDncR0\"",
20565
- "mtime": "2026-10-10T00:24:14.948Z",
21371
+ "mtime": "2026-10-12T02:43:06.046Z",
20566
21372
  "size": 2429,
20567
21373
  "path": "../public/_nuxt/error-404.Bb87HomL.css"
20568
21374
  },
20569
- "/_nuxt/error-500.Bwd7zAaE.css": {
20570
- "type": "text/css; charset=utf-8",
20571
- "etag": "\"772-nqXXACYtFiPK+D42BNu4uEECARA\"",
20572
- "mtime": "2026-10-10T00:24:14.948Z",
20573
- "size": 1906,
20574
- "path": "../public/_nuxt/error-500.Bwd7zAaE.css"
20575
- },
20576
21375
  "/_nuxt/hePW80VL.js": {
20577
21376
  "type": "text/javascript; charset=utf-8",
20578
21377
  "etag": "\"2cc-fA8td6k29UVF6JoPfhOPkceTK1M\"",
20579
- "mtime": "2026-10-10T00:24:14.948Z",
21378
+ "mtime": "2026-10-12T02:43:06.047Z",
20580
21379
  "size": 716,
20581
21380
  "path": "../public/_nuxt/hePW80VL.js"
20582
21381
  },
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
21382
  "/_nuxt/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2": {
20591
21383
  "type": "font/woff2",
20592
21384
  "etag": "\"6568-cF1iUGbboMFZ8TfnP5HiMgl9II0\"",
20593
- "mtime": "2026-10-10T00:24:14.948Z",
21385
+ "mtime": "2026-10-12T02:43:06.047Z",
20594
21386
  "size": 25960,
20595
21387
  "path": "../public/_nuxt/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2"
20596
21388
  },
21389
+ "/_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2": {
21390
+ "type": "font/woff2",
21391
+ "etag": "\"493c-n3Oy9D6jvzfMjpClqox+Zo7ERQQ\"",
21392
+ "mtime": "2026-10-12T02:43:06.047Z",
21393
+ "size": 18748,
21394
+ "path": "../public/_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2"
21395
+ },
20597
21396
  "/_nuxt/inter-greek-ext-wght-normal.DlzME5K_.woff2": {
20598
21397
  "type": "font/woff2",
20599
21398
  "etag": "\"2be0-BP5iTzJeB8nLqYAgKpWNi5o1Zm8\"",
20600
- "mtime": "2026-10-10T00:24:14.948Z",
21399
+ "mtime": "2026-10-12T02:43:06.047Z",
20601
21400
  "size": 11232,
20602
21401
  "path": "../public/_nuxt/inter-greek-ext-wght-normal.DlzME5K_.woff2"
20603
21402
  },
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
21403
  "/_nuxt/inter-greek-wght-normal.CkhJZR-_.woff2": {
20612
21404
  "type": "font/woff2",
20613
21405
  "etag": "\"4a34-xor/hj4YNqI52zFecXnUbzQ4Xs4\"",
20614
- "mtime": "2026-10-10T00:24:14.948Z",
21406
+ "mtime": "2026-10-12T02:43:06.047Z",
20615
21407
  "size": 18996,
20616
21408
  "path": "../public/_nuxt/inter-greek-wght-normal.CkhJZR-_.woff2"
20617
21409
  },
20618
21410
  "/_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2": {
20619
21411
  "type": "font/woff2",
20620
21412
  "etag": "\"14c4c-zz61D7IQFMB9QxHvTAOk/Vh4ibQ\"",
20621
- "mtime": "2026-10-10T00:24:14.948Z",
21413
+ "mtime": "2026-10-12T02:43:06.047Z",
20622
21414
  "size": 85068,
20623
21415
  "path": "../public/_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2"
20624
21416
  },
20625
- "/_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2": {
20626
- "type": "font/woff2",
20627
- "etag": "\"bc80-8R1ym7Ck2DUNLqPQ/AYs9u8tUpg\"",
20628
- "mtime": "2026-10-10T00:24:14.948Z",
20629
- "size": 48256,
20630
- "path": "../public/_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2"
20631
- },
20632
21417
  "/_nuxt/inter-vietnamese-wght-normal.CBcvBZtf.woff2": {
20633
21418
  "type": "font/woff2",
20634
21419
  "etag": "\"280c-nBythjoDQ0+5wVAendJ6wU7Xz2M\"",
20635
- "mtime": "2026-10-10T00:24:14.948Z",
21420
+ "mtime": "2026-10-12T02:43:06.047Z",
20636
21421
  "size": 10252,
20637
21422
  "path": "../public/_nuxt/inter-vietnamese-wght-normal.CBcvBZtf.woff2"
20638
21423
  },
21424
+ "/_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2": {
21425
+ "type": "font/woff2",
21426
+ "etag": "\"bc80-8R1ym7Ck2DUNLqPQ/AYs9u8tUpg\"",
21427
+ "mtime": "2026-10-12T02:43:06.047Z",
21428
+ "size": 48256,
21429
+ "path": "../public/_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2"
21430
+ },
20639
21431
  "/_nuxt/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2": {
20640
21432
  "type": "font/woff2",
20641
21433
  "etag": "\"2f4c-WiAGfn140d4QND3ayQWaCHF8rbE\"",
20642
- "mtime": "2026-10-10T00:24:14.948Z",
21434
+ "mtime": "2026-10-12T02:43:06.047Z",
20643
21435
  "size": 12108,
20644
21436
  "path": "../public/_nuxt/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2"
20645
21437
  },
21438
+ "/_nuxt/entry.CGWKmYU3.css": {
21439
+ "type": "text/css; charset=utf-8",
21440
+ "etag": "\"68db2-q6wQXFOalVzn1yh9EoP09Ru8lNs\"",
21441
+ "mtime": "2026-10-12T02:43:06.046Z",
21442
+ "size": 429490,
21443
+ "path": "../public/_nuxt/entry.CGWKmYU3.css"
21444
+ },
20646
21445
  "/_nuxt/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2": {
20647
21446
  "type": "font/woff2",
20648
21447
  "etag": "\"232c-Dnz9DhH4c266e6TziU1pxRkV6FY\"",
20649
- "mtime": "2026-10-10T00:24:14.948Z",
21448
+ "mtime": "2026-10-12T02:43:06.047Z",
20650
21449
  "size": 9004,
20651
21450
  "path": "../public/_nuxt/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2"
20652
21451
  },
20653
21452
  "/_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2": {
20654
21453
  "type": "font/woff2",
20655
21454
  "etag": "\"3b5c-HLF7Wvs2Z1IA1cPRs6jnor8OUQ4\"",
20656
- "mtime": "2026-10-10T00:24:14.949Z",
21455
+ "mtime": "2026-10-12T02:43:06.047Z",
20657
21456
  "size": 15196,
20658
21457
  "path": "../public/_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2"
20659
21458
  },
20660
21459
  "/_nuxt/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2": {
20661
21460
  "type": "font/woff2",
20662
21461
  "etag": "\"9dd4-5yd+cUUhzrXxdMyYebUeD0qml1M\"",
20663
- "mtime": "2026-10-10T00:24:14.949Z",
21462
+ "mtime": "2026-10-12T02:43:06.047Z",
20664
21463
  "size": 40404,
20665
21464
  "path": "../public/_nuxt/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2"
20666
21465
  },
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
21466
  "/_nuxt/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2": {
20675
21467
  "type": "font/woff2",
20676
21468
  "etag": "\"1d50-/Re0MyD6BV8h81wBPVijGZH5GBs\"",
20677
- "mtime": "2026-10-10T00:24:14.949Z",
21469
+ "mtime": "2026-10-12T02:43:06.047Z",
20678
21470
  "size": 7504,
20679
21471
  "path": "../public/_nuxt/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2"
20680
21472
  },
20681
21473
  "/_nuxt/wherdr-nerd-awesome.DQ3_iAfa.woff2": {
20682
21474
  "type": "font/woff2",
20683
21475
  "etag": "\"30178-02mpQKEDb74Ec8LtlhKceB1vHO8\"",
20684
- "mtime": "2026-10-10T00:24:14.949Z",
21476
+ "mtime": "2026-10-12T02:43:06.047Z",
20685
21477
  "size": 196984,
20686
21478
  "path": "../public/_nuxt/wherdr-nerd-awesome.DQ3_iAfa.woff2"
20687
21479
  },
21480
+ "/_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2": {
21481
+ "type": "font/woff2",
21482
+ "etag": "\"d9b0-kmO/x6KCTFRlVipOvl+5XcArGUw\"",
21483
+ "mtime": "2026-10-12T02:43:06.047Z",
21484
+ "size": 55728,
21485
+ "path": "../public/_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2"
21486
+ },
20688
21487
  "/_nuxt/wherdr-nerd-extension.Dai_ky39.woff2": {
20689
21488
  "type": "font/woff2",
20690
21489
  "etag": "\"f76c-CjERGtjtOrkpSXy7JyZNl1CAu0U\"",
20691
- "mtime": "2026-10-10T00:24:14.949Z",
21490
+ "mtime": "2026-10-12T02:43:06.047Z",
20692
21491
  "size": 63340,
20693
21492
  "path": "../public/_nuxt/wherdr-nerd-extension.Dai_ky39.woff2"
20694
21493
  },
20695
- "/_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2": {
20696
- "type": "font/woff2",
20697
- "etag": "\"1e130-1GKpbVoJoRf3AxaKTZS8FjxkOd4\"",
20698
- "mtime": "2026-10-10T00:24:14.949Z",
20699
- "size": 123184,
20700
- "path": "../public/_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2"
20701
- },
20702
21494
  "/_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2": {
20703
21495
  "type": "font/woff2",
20704
21496
  "etag": "\"30f78-2RuGTMLnbTBdhlI9ExApyiUeD8c\"",
20705
- "mtime": "2026-10-10T00:24:14.949Z",
21497
+ "mtime": "2026-10-12T02:43:06.047Z",
20706
21498
  "size": 200568,
20707
21499
  "path": "../public/_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2"
20708
21500
  },
21501
+ "/_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2": {
21502
+ "type": "font/woff2",
21503
+ "etag": "\"1e130-1GKpbVoJoRf3AxaKTZS8FjxkOd4\"",
21504
+ "mtime": "2026-10-12T02:43:06.047Z",
21505
+ "size": 123184,
21506
+ "path": "../public/_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2"
21507
+ },
20709
21508
  "/_nuxt/wherdr-nerd-material-2.C_flbBWO.woff2": {
20710
21509
  "type": "font/woff2",
20711
21510
  "etag": "\"1f95c-q6dAP964z2dgEvWzAYjTAzBtzBc\"",
20712
- "mtime": "2026-10-10T00:24:14.949Z",
21511
+ "mtime": "2026-10-12T02:43:06.047Z",
20713
21512
  "size": 129372,
20714
21513
  "path": "../public/_nuxt/wherdr-nerd-material-2.C_flbBWO.woff2"
20715
21514
  },
20716
21515
  "/_nuxt/wherdr-nerd-material-3.8xz7iX-Y.woff2": {
20717
21516
  "type": "font/woff2",
20718
21517
  "etag": "\"2248c-3GBJ1KjkT+xYPhza9V/DKaILa7Y\"",
20719
- "mtime": "2026-10-10T00:24:14.949Z",
21518
+ "mtime": "2026-10-12T02:43:06.047Z",
20720
21519
  "size": 140428,
20721
21520
  "path": "../public/_nuxt/wherdr-nerd-material-3.8xz7iX-Y.woff2"
20722
21521
  },
20723
21522
  "/_nuxt/wherdr-nerd-material-4.CO_PudDR.woff2": {
20724
21523
  "type": "font/woff2",
20725
21524
  "etag": "\"1fa80-YcJvpFD/M3vTC4y6SMmp7s8a9gw\"",
20726
- "mtime": "2026-10-10T00:24:14.949Z",
21525
+ "mtime": "2026-10-12T02:43:06.047Z",
20727
21526
  "size": 129664,
20728
21527
  "path": "../public/_nuxt/wherdr-nerd-material-4.CO_PudDR.woff2"
20729
21528
  },
20730
21529
  "/_nuxt/wherdr-nerd-octicons.Hl4VEx8m.woff2": {
20731
21530
  "type": "font/woff2",
20732
21531
  "etag": "\"f890-FkAsW3iqENK+lU5UlSze0yqnE2s\"",
20733
- "mtime": "2026-10-10T00:24:14.949Z",
21532
+ "mtime": "2026-10-12T02:43:06.047Z",
20734
21533
  "size": 63632,
20735
21534
  "path": "../public/_nuxt/wherdr-nerd-octicons.Hl4VEx8m.woff2"
20736
21535
  },
20737
21536
  "/_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2": {
20738
21537
  "type": "font/woff2",
20739
21538
  "etag": "\"1bc0-iXm39wQwNbm2VjpVBOn72grfku0\"",
20740
- "mtime": "2026-10-10T00:24:14.950Z",
21539
+ "mtime": "2026-10-12T02:43:06.047Z",
20741
21540
  "size": 7104,
20742
21541
  "path": "../public/_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2"
20743
21542
  },
20744
21543
  "/_nuxt/wherdr-symbols.C1LsPKmg.woff2": {
20745
21544
  "type": "font/woff2",
20746
21545
  "etag": "\"1304-Lwyr1XiDl3FK38nmS/6Pk9wfiWc\"",
20747
- "mtime": "2026-10-10T00:24:14.950Z",
21546
+ "mtime": "2026-10-12T02:43:06.048Z",
20748
21547
  "size": 4868,
20749
21548
  "path": "../public/_nuxt/wherdr-symbols.C1LsPKmg.woff2"
20750
21549
  },
20751
21550
  "/_nuxt/yzABg5xl.js": {
20752
21551
  "type": "text/javascript; charset=utf-8",
20753
21552
  "etag": "\"1c49-W7I7waHyF8BfftITNIl1xCbNFQw\"",
20754
- "mtime": "2026-10-10T00:24:14.950Z",
21553
+ "mtime": "2026-10-12T02:43:06.048Z",
20755
21554
  "size": 7241,
20756
21555
  "path": "../public/_nuxt/yzABg5xl.js"
20757
21556
  },
21557
+ "/_nuxt/xYX85SPI.js": {
21558
+ "type": "text/javascript; charset=utf-8",
21559
+ "etag": "\"374e-AaaIqO4sGKcceUeLatrSWJTAfAU\"",
21560
+ "mtime": "2026-10-12T02:43:06.048Z",
21561
+ "size": 14158,
21562
+ "path": "../public/_nuxt/xYX85SPI.js"
21563
+ },
21564
+ "/_nuxt/builds/meta/c735b6c0-1bd0-47d7-a208-d310f0a06287.json": {
21565
+ "type": "application/json",
21566
+ "etag": "\"58-d/XzFsF7fGOYu7cBbS83s+45DOk\"",
21567
+ "mtime": "2026-10-12T02:43:06.021Z",
21568
+ "size": 88,
21569
+ "path": "../public/_nuxt/builds/meta/c735b6c0-1bd0-47d7-a208-d310f0a06287.json"
21570
+ },
20758
21571
  "/_nuxt/builds/latest.json": {
20759
21572
  "type": "application/json",
20760
- "etag": "\"47-gUq0w2mhEU+I4n1/G1rUjuC+PWE\"",
20761
- "mtime": "2026-10-10T00:24:14.921Z",
21573
+ "etag": "\"47-tXRY9adXBmru9/K9a4qadfDPmmc\"",
21574
+ "mtime": "2026-10-12T02:43:06.026Z",
20762
21575
  "size": 71,
20763
21576
  "path": "../public/_nuxt/builds/latest.json"
20764
- },
20765
- "/_nuxt/builds/meta/7afbf062-5369-4002-b20d-7a582ff6e0f1.json": {
20766
- "type": "application/json",
20767
- "etag": "\"58-LQMKUB4Jlz4hjuTcu/d4TGQA1Kc\"",
20768
- "mtime": "2026-10-10T00:24:14.916Z",
20769
- "size": 88,
20770
- "path": "../public/_nuxt/builds/meta/7afbf062-5369-4002-b20d-7a582ff6e0f1.json"
20771
21577
  }
20772
21578
  };
20773
21579
 
@@ -20987,7 +21793,7 @@ const _M8hgLp = defineEventHandler(async (event) => {
20987
21793
  setResponseStatus(event, 403);
20988
21794
  setResponseHeader(event, "content-type", "text/html; charset=utf-8");
20989
21795
  setResponseHeader(event, "cache-control", "no-store");
20990
- return hostRefusedPage();
21796
+ return hostRefusedPage(void 0, event.node.req.headers.host);
20991
21797
  }
20992
21798
  return sendError(event, 403, { error: "Host not allowed", code: "host" });
20993
21799
  }
@@ -21019,6 +21825,7 @@ const _lazy_4__oTm = () => import('../routes/api/auth/max-session.post.mjs');
21019
21825
  const _lazy_7O3TsZ = () => import('../routes/api/auth/register/options.post.mjs');
21020
21826
  const _lazy_fQByfS = () => import('../routes/api/auth/register/verify.post.mjs');
21021
21827
  const _lazy_jcfnWB = () => import('../routes/api/auth/status.get.mjs');
21828
+ const _lazy_DwN9dC = () => import('../routes/api/board.get.mjs');
21022
21829
  const _lazy_WhNb61 = () => import('../routes/api/changes.get.mjs');
21023
21830
  const _lazy_hdSKYJ = () => import('../routes/api/chat.get.mjs');
21024
21831
  const _lazy_WoSEa6 = () => import('../routes/api/chat/image.get.mjs');
@@ -21030,10 +21837,14 @@ const _lazy_GF2Rhb = () => import('../routes/api/codex-update.post.mjs');
21030
21837
  const _lazy_onTn85 = () => import('../routes/api/commands.get.mjs');
21031
21838
  const _lazy_XuUgLO = () => import('../routes/api/config.get.mjs');
21032
21839
  const _lazy_y_su18 = () => import('../routes/api/dirs.get.mjs');
21840
+ const _lazy_l7QdCS = () => import('../routes/api/dismiss-stopped.post.mjs');
21033
21841
  const _lazy_Z6oqjB = () => import('../routes/api/dismiss.post.mjs');
21034
21842
  const _lazy_2uy6Z9 = () => import('../routes/api/effort.post.mjs');
21035
21843
  const _lazy_7FhJOq = () => import('../routes/api/efforts.get.mjs');
21036
21844
  const _lazy_Wg_MPT = () => import('../routes/api/file.post.mjs');
21845
+ const _lazy_vy5jzJ = () => import('../routes/api/files.get.mjs');
21846
+ const _lazy_iD5EkU = () => import('../routes/api/files/download.get.mjs');
21847
+ const _lazy_TecKdl = () => import('../routes/api/files/read.get.mjs');
21037
21848
  const _lazy_kEWyNy = () => import('../routes/api/gitroot.get.mjs');
21038
21849
  const _lazy_1Vqvr9 = () => import('../routes/api/health.get.mjs');
21039
21850
  const _lazy_U4OEhz = () => import('../routes/api/input.post.mjs');
@@ -21059,8 +21870,15 @@ const _lazy_mhIdo4 = () => import('../routes/api/plugins/projects.get.mjs');
21059
21870
  const _lazy_zH9tge = () => import('../routes/api/plugins/projects.post.mjs');
21060
21871
  const _lazy_qE4HMW = () => import('../routes/api/plugins/thread-limits.get.mjs');
21061
21872
  const _lazy_ByJj04 = () => import('../routes/api/plugins/thread-limits.post.mjs');
21873
+ const _lazy_VZ7yeT = () => import('../routes/api/project/inbox.get.mjs');
21874
+ const _lazy_wq4Jn3 = () => import('../routes/api/project/inbox.post.mjs');
21062
21875
  const _lazy_WLg2Uu = () => import('../routes/api/index.get.mjs');
21876
+ const _lazy_LkLunk = () => import('../routes/api/project/memory.get.mjs');
21063
21877
  const _lazy_sQe2ZF = () => import('../routes/api/project/report.get.mjs');
21878
+ const _lazy_jP59VB = () => import('../routes/api/project/routines.get.mjs');
21879
+ const _lazy_do1380 = () => import('../routes/api/project/settings.get.mjs');
21880
+ const _lazy_6EuDYh = () => import('../routes/api/project/thread.get.mjs');
21881
+ const _lazy_qZGRKl = () => import('../routes/api/project/thread.post.mjs');
21064
21882
  const _lazy_wxPObX = () => import('../routes/api/prompt.post.mjs');
21065
21883
  const _lazy_gHqHgE = () => import('../routes/api/push/quiet.post.mjs');
21066
21884
  const _lazy_vXOoN7 = () => import('../routes/api/push/subscribe.post.mjs');
@@ -21092,7 +21910,6 @@ const _lazy_2a3aHZ = () => import('../routes/icons/_name_.get.mjs');
21092
21910
  const _lazy_MpH2Yl = () => import('../routes/uploads/_...name_.get.mjs');
21093
21911
  const _lazy_hSqSXW = () => import('../routes/ws/_..._.mjs');
21094
21912
  const _lazy_N9wZe_ = () => import('../routes/ws/events.mjs');
21095
- const _lazy_CXgyQE = () => import('../routes/ws/mirror.mjs');
21096
21913
  const _lazy_Stovcz = () => import('../routes/ws/term.mjs');
21097
21914
  const _lazy_9gHabX = () => import('../routes/renderer.mjs');
21098
21915
 
@@ -21112,6 +21929,7 @@ const handlers = [
21112
21929
  { route: '/api/auth/register/options', handler: _lazy_7O3TsZ, lazy: true, middleware: false, method: "post" },
21113
21930
  { route: '/api/auth/register/verify', handler: _lazy_fQByfS, lazy: true, middleware: false, method: "post" },
21114
21931
  { route: '/api/auth/status', handler: _lazy_jcfnWB, lazy: true, middleware: false, method: "get" },
21932
+ { route: '/api/board', handler: _lazy_DwN9dC, lazy: true, middleware: false, method: "get" },
21115
21933
  { route: '/api/changes', handler: _lazy_WhNb61, lazy: true, middleware: false, method: "get" },
21116
21934
  { route: '/api/chat', handler: _lazy_hdSKYJ, lazy: true, middleware: false, method: "get" },
21117
21935
  { route: '/api/chat/image', handler: _lazy_WoSEa6, lazy: true, middleware: false, method: "get" },
@@ -21123,10 +21941,14 @@ const handlers = [
21123
21941
  { route: '/api/commands', handler: _lazy_onTn85, lazy: true, middleware: false, method: "get" },
21124
21942
  { route: '/api/config', handler: _lazy_XuUgLO, lazy: true, middleware: false, method: "get" },
21125
21943
  { route: '/api/dirs', handler: _lazy_y_su18, lazy: true, middleware: false, method: "get" },
21944
+ { route: '/api/dismiss-stopped', handler: _lazy_l7QdCS, lazy: true, middleware: false, method: "post" },
21126
21945
  { route: '/api/dismiss', handler: _lazy_Z6oqjB, lazy: true, middleware: false, method: "post" },
21127
21946
  { route: '/api/effort', handler: _lazy_2uy6Z9, lazy: true, middleware: false, method: "post" },
21128
21947
  { route: '/api/efforts', handler: _lazy_7FhJOq, lazy: true, middleware: false, method: "get" },
21129
21948
  { route: '/api/file', handler: _lazy_Wg_MPT, lazy: true, middleware: false, method: "post" },
21949
+ { route: '/api/files', handler: _lazy_vy5jzJ, lazy: true, middleware: false, method: "get" },
21950
+ { route: '/api/files/download', handler: _lazy_iD5EkU, lazy: true, middleware: false, method: "get" },
21951
+ { route: '/api/files/read', handler: _lazy_TecKdl, lazy: true, middleware: false, method: "get" },
21130
21952
  { route: '/api/gitroot', handler: _lazy_kEWyNy, lazy: true, middleware: false, method: "get" },
21131
21953
  { route: '/api/health', handler: _lazy_1Vqvr9, lazy: true, middleware: false, method: "get" },
21132
21954
  { route: '/api/input', handler: _lazy_U4OEhz, lazy: true, middleware: false, method: "post" },
@@ -21152,8 +21974,15 @@ const handlers = [
21152
21974
  { route: '/api/plugins/projects', handler: _lazy_zH9tge, lazy: true, middleware: false, method: "post" },
21153
21975
  { route: '/api/plugins/thread-limits', handler: _lazy_qE4HMW, lazy: true, middleware: false, method: "get" },
21154
21976
  { route: '/api/plugins/thread-limits', handler: _lazy_ByJj04, lazy: true, middleware: false, method: "post" },
21977
+ { route: '/api/project/inbox', handler: _lazy_VZ7yeT, lazy: true, middleware: false, method: "get" },
21978
+ { route: '/api/project/inbox', handler: _lazy_wq4Jn3, lazy: true, middleware: false, method: "post" },
21155
21979
  { route: '/api/project', handler: _lazy_WLg2Uu, lazy: true, middleware: false, method: "get" },
21980
+ { route: '/api/project/memory', handler: _lazy_LkLunk, lazy: true, middleware: false, method: "get" },
21156
21981
  { route: '/api/project/report', handler: _lazy_sQe2ZF, lazy: true, middleware: false, method: "get" },
21982
+ { route: '/api/project/routines', handler: _lazy_jP59VB, lazy: true, middleware: false, method: "get" },
21983
+ { route: '/api/project/settings', handler: _lazy_do1380, lazy: true, middleware: false, method: "get" },
21984
+ { route: '/api/project/thread', handler: _lazy_6EuDYh, lazy: true, middleware: false, method: "get" },
21985
+ { route: '/api/project/thread', handler: _lazy_qZGRKl, lazy: true, middleware: false, method: "post" },
21157
21986
  { route: '/api/prompt', handler: _lazy_wxPObX, lazy: true, middleware: false, method: "post" },
21158
21987
  { route: '/api/push/quiet', handler: _lazy_gHqHgE, lazy: true, middleware: false, method: "post" },
21159
21988
  { route: '/api/push/subscribe', handler: _lazy_vXOoN7, lazy: true, middleware: false, method: "post" },
@@ -21185,7 +22014,6 @@ const handlers = [
21185
22014
  { route: '/uploads/**:name', handler: _lazy_MpH2Yl, lazy: true, middleware: false, method: "get" },
21186
22015
  { route: '/ws/**', handler: _lazy_hSqSXW, lazy: true, middleware: false, method: undefined },
21187
22016
  { 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
22017
  { route: '/ws/term', handler: _lazy_Stovcz, lazy: true, middleware: false, method: undefined },
21190
22018
  { route: '/__nuxt_error', handler: _lazy_9gHabX, lazy: true, middleware: false, method: undefined },
21191
22019
  { route: '/__nuxt_island/**', handler: _SxA8c9, lazy: false, middleware: false, method: undefined },
@@ -21648,5 +22476,5 @@ setupGracefulShutdown(listener, nitroApp);
21648
22476
  }
21649
22477
  const nodeServer = {};
21650
22478
 
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 };
22479
+ export { sleep$1 as $, ATTACH_MAX as A, isProjectThread as B, uploadNames as C, machineOfPane as D, fmt as E, takenBackOf as F, transcripts as G, HerdrError as H, chatPasted as I, withoutTakenBack as J, withSentText as K, currentModel as L, sendImage as M, keysFor as N, parseChoices as O, PANE_RE as P, parseOmpField as Q, withPaneLock as R, selfUpdates as S, restarting as T, UPLOAD_DIR as U, updateChoices as V, UPDATE_LABELS as W, updateRestartPlan as X, restarts as Y, usesTerminalException as Z, sameQuestion as _, defineApi as a, validLimit as a$, MACHINE_KEY_RE as a0, getMachine as a1, installClaudeStatusline as a2, codexStatus as a3, paneForeground as a4, codexMenuOpen as a5, stopAgent as a6, terminalUpdateLine as a7, waitFor as a8, terminalUpdateDone as a9, listEfforts as aA, saveUpload as aB, setResponseHeader 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, limitMachineKeys as a_, startAgent as aa, log as ab, RESTARTABLE as ac, claudeFooterMode as ad, planRestart as ae, builtinCommands as af, slashCommands as ag, HOME as ah, localMachine as ai, readSubs as aj, vapidPublicKey as ak, pushReady as al, machineConfigs as am, recentDirsWithKinds as an, installedAgentKinds as ao, IN_DOCKER as ap, HOST_OPEN_TARGET as aq, HOST_OPEN_KEY as ar, PANE_RE$1 as as, splitId as at, HOST_OPEN_USER as au, listDirs as av, dismissStopped as aw, closePanel as ax, setEffort as ay, refreshModel as az, screenChoices as b, getResponseStatusText as b$, readThreadLimits as b0, writeThreadLimits as b1, closeTrailingMention as b2, keepPastes as b3, hasHeld as b4, INPUT_STATES as b5, inputVisible as b6, shouldHold as b7, sendPrompt as b8, agentPrompt as b9, cancelQueued as bA, installMode as bB, oneTapMode as bC, updateCommand as bD, compareVersions as bE, updateRunning as bF, allMachines as bG, recentDirs as bH, joinId as bI, useStorage as bJ, getRouterParam as bK, readUpload as bL, defineWebSocketHandler as bM, eventClients as bN, getStateJson as bO, hostAllowed as bP, sameOrigin as bQ, openTerm as bR, useRuntimeConfig as bS, encodePath as bT, joinRelativeURL as bU, defineRenderHandler as bV, createError$1 as bW, destr as bX, getRouteRules as bY, relative as bZ, joinURL as b_, isBusyError as ba, HOLD_AGENTS as bb, pendingPrompts as bc, parseQuiet as bd, writeGlobalQuiet as be, writeSubs as bf, quietActive as bg, readGlobalQuiet as bh, validPushSubscription as bi, replaceSubscription as bj, pushSend as bk, readQuotas as bl, retryQueued as bm, parseWaitScreen as bn, settingsTabs as bo, tabsOfRow as bp, classifyScreen as bq, parseMenu as br, hasTranscript as bs, SEARCH_DEADLINE_MS as bt, SEARCH_MAX_RESULTS as bu, spaceTitle as bv, markSeen as bw, listSessions as bx, openSession as by, PANE_DIRECTIONS as bz, createAgent as c, getResponseStatus as c0, useNitroApp as c1, nodeServer as c2, 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
22480
  //# sourceMappingURL=nitro.mjs.map