wherdr 1.3.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/BDNMzG2s.js +1 -0
  3. package/.output/public/_nuxt/BETID3_E.js +1 -0
  4. package/.output/public/_nuxt/BHenDMeH.js +1 -0
  5. package/.output/public/_nuxt/{CJKsMzIp.js → BYZVrreW.js} +1 -1
  6. package/.output/public/_nuxt/BhgehRdJ.js +1 -0
  7. package/.output/public/_nuxt/BtH82ZuZ.js +9 -0
  8. package/.output/public/_nuxt/C3Bkn4ac.js +62 -0
  9. package/.output/public/_nuxt/CuUQ4mEf.js +1 -0
  10. package/.output/public/_nuxt/DFGEl0v2.js +23 -0
  11. package/.output/public/_nuxt/{DMLmW6JM.js → DFmgQVme.js} +41 -42
  12. package/.output/public/_nuxt/DZGKxROq.js +6 -0
  13. package/.output/public/_nuxt/DmkWvmnE.js +2 -0
  14. package/.output/public/_nuxt/DrKKeFFE.js +31 -0
  15. package/.output/public/_nuxt/DyfFwwGq.js +1 -0
  16. package/.output/public/_nuxt/FaNto0ga.js +105 -0
  17. package/.output/public/_nuxt/NIF0VwHk.js +25 -0
  18. package/.output/public/_nuxt/{w7Rm7unj.js → R0Y4VoeX.js} +1 -1
  19. package/.output/public/_nuxt/board.CEEcFc6M.css +1 -0
  20. package/.output/public/_nuxt/builds/latest.json +1 -1
  21. package/.output/public/_nuxt/builds/meta/0b28b3e9-664e-4347-a35b-afb0a711d5c5.json +1 -0
  22. package/.output/public/_nuxt/entry.CKoXcwRa.css +2 -0
  23. package/.output/public/_nuxt/settings.Cdb21nNw.css +1 -0
  24. package/.output/public/sw.js +1 -1
  25. package/.output/server/chunks/_/branding.mjs +1 -1
  26. package/.output/server/chunks/_/changes.mjs +4 -4
  27. package/.output/server/chunks/_/fileDownload.mjs +278 -0
  28. package/.output/server/chunks/_/files.mjs +44 -17
  29. package/.output/server/chunks/_/machineOrder.mjs +1 -1
  30. package/.output/server/chunks/_/onboarding.mjs +1 -1
  31. package/.output/server/chunks/_/package.mjs +9 -3
  32. package/.output/server/chunks/_/plugins.mjs +92 -125
  33. package/.output/server/chunks/_/restart.mjs +1 -1
  34. package/.output/server/chunks/_/selfupdate.mjs +1 -1
  35. package/.output/server/chunks/_/updates.mjs +1 -1
  36. package/.output/server/chunks/_/worktrees.mjs +1 -1
  37. package/.output/server/chunks/_/ws.mjs +43 -6
  38. package/.output/server/chunks/nitro/nitro.mjs +14033 -10618
  39. package/.output/server/chunks/raw/check-doc-links.mjs +5 -0
  40. package/.output/server/chunks/raw/check-leaks.mjs +1 -1
  41. package/.output/server/chunks/raw/check-release-notes.mjs +5 -0
  42. package/.output/server/chunks/raw/herdr-plugin.mjs +1 -1
  43. package/.output/server/chunks/raw/install-claude-statusline.mjs +1 -1
  44. package/.output/server/chunks/raw/prerelease-summary.mjs +5 -0
  45. package/.output/server/chunks/raw/prerelease.mjs +7 -0
  46. package/.output/server/chunks/raw/reveal.mjs +1 -1
  47. package/.output/server/chunks/raw/test-affected.mjs +5 -0
  48. package/.output/server/chunks/routes/api/_..._.mjs +6 -5
  49. package/.output/server/chunks/routes/api/agents.post.mjs +6 -5
  50. package/.output/server/chunks/routes/api/ask-tab.post.mjs +6 -5
  51. package/.output/server/chunks/routes/api/attach.post.mjs +6 -5
  52. package/.output/server/chunks/routes/api/auth/disable.post.mjs +6 -5
  53. package/.output/server/chunks/routes/api/auth/lock-all.post.mjs +6 -5
  54. package/.output/server/chunks/routes/api/auth/lock.post.mjs +6 -5
  55. package/.output/server/chunks/routes/api/auth/login/options.post.mjs +6 -5
  56. package/.output/server/chunks/routes/api/auth/login/verify.post.mjs +6 -5
  57. package/.output/server/chunks/routes/api/auth/max-session.post.mjs +6 -5
  58. package/.output/server/chunks/routes/api/auth/register/options.post.mjs +6 -5
  59. package/.output/server/chunks/routes/api/auth/register/verify.post.mjs +6 -5
  60. package/.output/server/chunks/routes/api/auth/status.get.mjs +6 -5
  61. package/.output/server/chunks/routes/api/changes.get.mjs +7 -6
  62. package/.output/server/chunks/routes/api/chat/image.get.mjs +7 -6
  63. package/.output/server/chunks/routes/api/chat.get.mjs +20 -7
  64. package/.output/server/chunks/routes/api/choose.post.mjs +31 -17
  65. package/.output/server/chunks/routes/api/claude-setup.post.mjs +42 -0
  66. package/.output/server/chunks/routes/api/claude-statusline.post.mjs +7 -6
  67. package/.output/server/chunks/routes/api/clear-queued-input.post.mjs +42 -0
  68. package/.output/server/chunks/routes/api/close/status.get.mjs +7 -6
  69. package/.output/server/chunks/routes/api/close.post.mjs +6 -5
  70. package/.output/server/chunks/routes/api/codex-update.post.mjs +7 -6
  71. package/.output/server/chunks/routes/api/commands.get.mjs +7 -6
  72. package/.output/server/chunks/routes/api/config.get.mjs +10 -13
  73. package/.output/server/chunks/routes/api/dirs.get.mjs +7 -6
  74. package/.output/server/chunks/routes/api/dismiss-stopped.post.mjs +7 -6
  75. package/.output/server/chunks/routes/api/dismiss.post.mjs +7 -6
  76. package/.output/server/chunks/routes/api/effort.post.mjs +7 -6
  77. package/.output/server/chunks/routes/api/efforts.get.mjs +7 -6
  78. package/.output/server/chunks/routes/api/file.post.mjs +7 -6
  79. package/.output/server/chunks/routes/api/files/download.get.mjs +12 -31
  80. package/.output/server/chunks/routes/api/files/download.head.mjs +41 -0
  81. package/.output/server/chunks/routes/api/files/read.get.mjs +8 -7
  82. package/.output/server/chunks/routes/api/files.get.mjs +7 -6
  83. package/.output/server/chunks/routes/api/health.get.mjs +6 -5
  84. package/.output/server/chunks/routes/api/input.post.mjs +7 -6
  85. package/.output/server/chunks/routes/api/interrupt.post.mjs +24 -21
  86. package/.output/server/chunks/routes/api/isgit.get.mjs +8 -8
  87. package/.output/server/chunks/routes/api/machine/awake.get.mjs +7 -6
  88. package/.output/server/chunks/routes/api/machine/awake.post.mjs +7 -6
  89. package/.output/server/chunks/routes/api/machine/order.get.mjs +6 -5
  90. package/.output/server/chunks/routes/api/machine/order.post.mjs +6 -5
  91. package/.output/server/chunks/routes/api/machine/reconnect.post.mjs +40 -0
  92. package/.output/server/chunks/routes/api/machine/rename.post.mjs +7 -6
  93. package/.output/server/chunks/routes/api/machine/status.post.mjs +39 -0
  94. package/.output/server/chunks/routes/api/menu-left.post.mjs +40 -0
  95. package/.output/server/chunks/routes/api/menu.post.mjs +7 -6
  96. package/.output/server/chunks/routes/api/model.post.mjs +7 -6
  97. package/.output/server/chunks/routes/api/models.get.mjs +7 -6
  98. package/.output/server/chunks/routes/api/nav.post.mjs +7 -6
  99. package/.output/server/chunks/routes/api/onboarding.get.mjs +6 -5
  100. package/.output/server/chunks/routes/api/onboarding.post.mjs +6 -5
  101. package/.output/server/chunks/routes/api/phone.get.mjs +8 -10
  102. package/.output/server/chunks/routes/api/phone.post.mjs +8 -10
  103. package/.output/server/chunks/routes/api/plugins/actions.get.mjs +6 -10
  104. package/.output/server/chunks/routes/api/plugins/invoke.post.mjs +6 -10
  105. package/.output/server/chunks/routes/api/plugins/projects.get.mjs +10 -9
  106. package/.output/server/chunks/routes/api/plugins/projects.post.mjs +11 -8
  107. package/.output/server/chunks/routes/api/prompt.post.mjs +22 -13
  108. package/.output/server/chunks/routes/api/push/quiet.post.mjs +7 -6
  109. package/.output/server/chunks/routes/api/push/subscribe.post.mjs +7 -7
  110. package/.output/server/chunks/routes/api/push/test.post.mjs +7 -6
  111. package/.output/server/chunks/routes/api/push/unsubscribe.post.mjs +7 -6
  112. package/.output/server/chunks/routes/api/quotas.get.mjs +7 -6
  113. package/.output/server/chunks/routes/api/rename.post.mjs +6 -5
  114. package/.output/server/chunks/routes/api/requeue.post.mjs +7 -6
  115. package/.output/server/chunks/routes/api/restart.get.mjs +6 -5
  116. package/.output/server/chunks/routes/api/restart.post.mjs +6 -5
  117. package/.output/server/chunks/routes/api/reveal.post.mjs +91 -8
  118. package/.output/server/chunks/routes/api/screen-key.post.mjs +7 -6
  119. package/.output/server/chunks/routes/api/screen.get.mjs +7 -6
  120. package/.output/server/chunks/routes/api/search.get.mjs +7 -6
  121. package/.output/server/chunks/routes/api/seen.post.mjs +7 -6
  122. package/.output/server/chunks/routes/api/sessions.get.mjs +7 -6
  123. package/.output/server/chunks/routes/api/sessions.post.mjs +7 -6
  124. package/.output/server/chunks/routes/api/settings-tab.post.mjs +7 -6
  125. package/.output/server/chunks/routes/api/{plugins/thread-limits.get.mjs → settings.get.mjs} +10 -9
  126. package/.output/server/chunks/routes/api/settings.post.mjs +40 -0
  127. package/.output/server/chunks/routes/api/space.post.mjs +34 -18
  128. package/.output/server/chunks/routes/api/state.get.mjs +7 -6
  129. package/.output/server/chunks/routes/api/tasks/action.post.mjs +39 -0
  130. package/.output/server/chunks/routes/api/{plugins/profiles.get.mjs → tasks/add.post.mjs} +12 -16
  131. package/.output/server/chunks/routes/api/tasks/after.post.mjs +39 -0
  132. package/.output/server/chunks/routes/api/tasks/approve.post.mjs +39 -0
  133. package/.output/server/chunks/routes/api/{project/report.get.mjs → tasks/archived.get.mjs} +12 -14
  134. package/.output/server/chunks/routes/api/{index.get.mjs → tasks/autopilot.get.mjs} +13 -14
  135. package/.output/server/chunks/routes/api/tasks/autopilot.post.mjs +39 -0
  136. package/.output/server/chunks/routes/api/{gitroot.get.mjs → tasks/board-settings.get.mjs} +12 -14
  137. package/.output/server/chunks/routes/api/tasks/board-settings.post.mjs +39 -0
  138. package/.output/server/chunks/routes/api/tasks/coordinator.get.mjs +40 -0
  139. package/.output/server/chunks/routes/api/tasks/coordinator.post.mjs +39 -0
  140. package/.output/server/chunks/routes/api/tasks/details.get.mjs +40 -0
  141. package/.output/server/chunks/routes/api/tasks/limit.post.mjs +39 -0
  142. package/.output/server/chunks/routes/api/tasks/links.get.mjs +39 -0
  143. package/.output/server/chunks/routes/api/tasks/models.get.mjs +40 -0
  144. package/.output/server/chunks/routes/api/tasks/pick.post.mjs +39 -0
  145. package/.output/server/chunks/routes/api/tasks/question.post.mjs +39 -0
  146. package/.output/server/chunks/routes/api/tasks/scheduled.get.mjs +40 -0
  147. package/.output/server/chunks/routes/api/{project → tasks}/settings.get.mjs +10 -12
  148. package/.output/server/chunks/routes/api/tasks/start.get.mjs +40 -0
  149. package/.output/server/chunks/routes/api/tasks/tell.post.mjs +39 -0
  150. package/.output/server/chunks/routes/api/tasks.get.mjs +39 -0
  151. package/.output/server/chunks/routes/api/unqueue.post.mjs +7 -6
  152. package/.output/server/chunks/routes/api/update/status.get.mjs +6 -5
  153. package/.output/server/chunks/routes/api/update.get.mjs +8 -10
  154. package/.output/server/chunks/routes/api/update.post.mjs +8 -10
  155. package/.output/server/chunks/routes/api/upload.post.mjs +7 -6
  156. package/.output/server/chunks/routes/api/worktrees/remove.post.mjs +6 -5
  157. package/.output/server/chunks/routes/api/worktrees.get.mjs +6 -5
  158. package/.output/server/chunks/routes/favicon.ico.get.mjs +6 -5
  159. package/.output/server/chunks/routes/icons/_name_.get.mjs +7 -6
  160. package/.output/server/chunks/routes/renderer.mjs +8 -7
  161. package/.output/server/chunks/routes/uploads/_...name_.get.mjs +7 -6
  162. package/.output/server/chunks/routes/ws/_..._.mjs +7 -6
  163. package/.output/server/chunks/routes/ws/events.mjs +9 -7
  164. package/.output/server/chunks/routes/ws/term.mjs +7 -6
  165. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  166. package/.output/server/index.mjs +7 -6
  167. package/.output/server/package.json +1 -1
  168. package/README.md +44 -1445
  169. package/bin/lib/commands.mjs +44 -9
  170. package/bin/lib/panel.mjs +3 -11
  171. package/bin/lib/service.mjs +41 -2
  172. package/bin/lib/skill.mjs +1 -1
  173. package/bin/lib/tailnet.d.mts +6 -3
  174. package/bin/lib/tailnet.mjs +70 -32
  175. package/bin/lib/userpath.d.mts +14 -0
  176. package/bin/lib/userpath.mjs +142 -0
  177. package/docs/README.md +58 -0
  178. package/docs/RELEASING.md +174 -0
  179. package/docs/board.md +164 -0
  180. package/docs/command.md +58 -0
  181. package/docs/configuration.md +39 -0
  182. package/docs/conversation.md +132 -0
  183. package/docs/development.md +38 -0
  184. package/docs/devices.md +58 -0
  185. package/docs/files.md +29 -0
  186. package/docs/herdr-projects-1x.md +278 -0
  187. package/docs/home.md +52 -0
  188. package/docs/installation.md +174 -0
  189. package/docs/machines.md +69 -0
  190. package/docs/migrate-from-1.x-docker.md +160 -0
  191. package/docs/networks.md +154 -0
  192. package/docs/notifications.md +83 -0
  193. package/docs/overview.md +71 -0
  194. package/docs/phone.md +26 -0
  195. package/docs/plugins.md +109 -0
  196. package/docs/quick-start.md +89 -0
  197. package/docs/quotas.md +65 -0
  198. package/docs/release-notes-2.0.0.md +84 -0
  199. package/docs/security.md +117 -0
  200. package/docs/terminal.md +15 -0
  201. package/docs/troubleshooting.md +45 -0
  202. package/package.json +9 -3
  203. package/skills/wherdr/SKILL.md +24 -173
  204. package/.output/public/_nuxt/BEJHMUrj.js +0 -1
  205. package/.output/public/_nuxt/BOtcEDnA.js +0 -1
  206. package/.output/public/_nuxt/BUaYhQ2r.js +0 -6
  207. package/.output/public/_nuxt/CJNhn9sA.js +0 -36
  208. package/.output/public/_nuxt/COCvtdHN.js +0 -89
  209. package/.output/public/_nuxt/Cl45J6_Q.js +0 -1
  210. package/.output/public/_nuxt/CndPDbMI.js +0 -2
  211. package/.output/public/_nuxt/Ctbx58Um.js +0 -23
  212. package/.output/public/_nuxt/Dl1PHLOB.js +0 -1
  213. package/.output/public/_nuxt/Nhex3_iH.js +0 -1
  214. package/.output/public/_nuxt/OpWX45i7.js +0 -89
  215. package/.output/public/_nuxt/builds/meta/4994f3a4-4126-4f57-a9e5-c7ebb25850bc.json +0 -1
  216. package/.output/public/_nuxt/dTj21DMs.js +0 -1
  217. package/.output/public/_nuxt/entry.BohTWE-n.css +0 -2
  218. package/.output/public/_nuxt/kwSoIiM7.js +0 -1
  219. package/.output/public/_nuxt/mkEwYka4.js +0 -1
  220. package/.output/server/chunks/_/pluginPolicy.mjs +0 -93
  221. package/.output/server/chunks/_/projectBoard.mjs +0 -363
  222. package/.output/server/chunks/_/projectDocs.mjs +0 -106
  223. package/.output/server/chunks/_/projectInbox.mjs +0 -135
  224. package/.output/server/chunks/_/projectThreads.mjs +0 -46
  225. package/.output/server/chunks/_/projectThreads2.mjs +0 -61
  226. package/.output/server/chunks/_/projectsActions.mjs +0 -143
  227. package/.output/server/chunks/_/projectsPlugin.mjs +0 -30
  228. package/.output/server/chunks/_/projectsPlugin2.mjs +0 -57
  229. package/.output/server/chunks/_/reveal.mjs +0 -115
  230. package/.output/server/chunks/raw/dev.wherdr.open.mjs +0 -7
  231. package/.output/server/chunks/raw/docker-entrypoint.mjs +0 -7
  232. package/.output/server/chunks/raw/install-host-open.mjs +0 -7
  233. package/.output/server/chunks/raw/wherdr-open.mjs +0 -7
  234. package/.output/server/chunks/routes/api/board.get.mjs +0 -148
  235. package/.output/server/chunks/routes/api/plugins/thread-limits.post.mjs +0 -45
  236. package/.output/server/chunks/routes/api/project/inbox.get.mjs +0 -44
  237. package/.output/server/chunks/routes/api/project/inbox.post.mjs +0 -44
  238. package/.output/server/chunks/routes/api/project/memory.get.mjs +0 -43
  239. package/.output/server/chunks/routes/api/project/routines.get.mjs +0 -44
  240. package/.output/server/chunks/routes/api/project/thread.get.mjs +0 -45
  241. package/.output/server/chunks/routes/api/project/thread.post.mjs +0 -47
  242. package/bin/install-docker-skill.sh +0 -20
@@ -0,0 +1 @@
1
+ .notification-level[data-v-aa9b4e30]{flex-direction:column;gap:6px;min-width:0;display:flex}.notification-level select[data-v-aa9b4e30]{border:1px solid var(--line);background:var(--bg);max-width:100%;min-height:44px;color:var(--text);font:inherit;border-radius:0;padding:8px}.notification-level-hint[data-v-aa9b4e30]{color:var(--muted);font-size:12px}.notification-customize summary[data-v-aa9b4e30]{cursor:pointer;min-height:36px;color:var(--muted);align-items:center;gap:4px;font-size:13px;list-style:none;display:flex}.notification-customize summary[data-v-aa9b4e30]::-webkit-details-marker{display:none}.notification-chev[data-v-aa9b4e30]{transition:transform .15s}.notification-customize[open] .notification-chev[data-v-aa9b4e30]{transform:rotate(90deg)}.notification-events[data-v-aa9b4e30]{flex-wrap:wrap;gap:4px 18px;display:flex}.notification-events label[data-v-aa9b4e30]{align-items:center;gap:6px;min-height:44px;display:flex}.notification-events input[data-v-aa9b4e30]{accent-color:var(--accent)}.notification-rules .settings-toggle[data-v-aeafb17e]{gap:16px}.notification-rules .settings-toggle>span[data-v-aeafb17e]{flex:1;min-width:0}.notification-default[data-v-aeafb17e]>.notification-level{margin-bottom:8px}.notification-help[data-v-aeafb17e]{margin:8px 0 0;font-size:12px}.notification-rule[data-v-aeafb17e]{border:1px solid var(--line);flex-direction:column;gap:10px;min-width:0;margin:12px 0;padding:14px;display:flex}.notification-rule-head b[data-v-aeafb17e],.notification-rule-head small[data-v-aeafb17e]{overflow-wrap:anywhere;display:block}.notification-rule-head small[data-v-aeafb17e]{color:var(--muted);font:11px var(--mono);margin-bottom:4px}.notification-rule-head .notification-diff[data-v-aeafb17e]{font:12px var(--sans,inherit);margin:4px 0 0}.notification-rule .settings-action small[data-v-aeafb17e]{margin-left:auto;padding-left:8px;font-size:11px}.notification-add[data-v-aeafb17e]{margin-top:12px}.notification-picker[data-v-aeafb17e]{border:1px solid var(--line);flex-direction:column;gap:12px;margin-top:8px;padding:12px;display:flex}.notification-picker-group[data-v-aeafb17e]{flex-direction:column;gap:4px;display:flex}.notification-picker-group>small[data-v-aeafb17e]{color:var(--muted);font:11px var(--mono)}.notification-reset[data-v-aeafb17e]{margin-top:16px}
@@ -15,7 +15,7 @@
15
15
  var sw = self;
16
16
  var CACHE = "wherdr-v1";
17
17
  var NETWORK_WAIT_MS = 3e3;
18
- var PRECACHE = ["/", ...[{"revision":"e6a852ba6e2a724d2255af526cb04083","url":"manifest.webmanifest"},{"revision":"b1a14fab8c06784649bf26c636747a86","url":"manifest-en.webmanifest"},{"revision":null,"url":"_nuxt/wherdr-symbols.C1LsPKmg.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-octicons.Hl4VEx8m.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-4.CO_PudDR.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-3.8xz7iX-Y.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-2.C_flbBWO.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-extension.Dai_ky39.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-awesome.DQ3_iAfa.woff2"},{"revision":null,"url":"_nuxt/w7Rm7unj.js"},{"revision":null,"url":"_nuxt/mkEwYka4.js"},{"revision":null,"url":"_nuxt/kwSoIiM7.js"},{"revision":null,"url":"_nuxt/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2"},{"revision":null,"url":"_nuxt/inter-vietnamese-wght-normal.CBcvBZtf.woff2"},{"revision":null,"url":"_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2"},{"revision":null,"url":"_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2"},{"revision":null,"url":"_nuxt/inter-greek-wght-normal.CkhJZR-_.woff2"},{"revision":null,"url":"_nuxt/inter-greek-ext-wght-normal.DlzME5K_.woff2"},{"revision":null,"url":"_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2"},{"revision":null,"url":"_nuxt/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2"},{"revision":null,"url":"_nuxt/hePW80VL.js"},{"revision":null,"url":"_nuxt/error-500.Bwd7zAaE.css"},{"revision":null,"url":"_nuxt/error-404.Bb87HomL.css"},{"revision":null,"url":"_nuxt/entry.BohTWE-n.css"},{"revision":null,"url":"_nuxt/dTj21DMs.js"},{"revision":null,"url":"_nuxt/archivo-vietnamese-wght-normal.XAtsl5Q_.woff2"},{"revision":null,"url":"_nuxt/archivo-latin-wght-normal.E0tuGl4L.woff2"},{"revision":null,"url":"_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2"},{"revision":null,"url":"_nuxt/OpWX45i7.js"},{"revision":null,"url":"_nuxt/Nhex3_iH.js"},{"revision":null,"url":"_nuxt/Dl1PHLOB.js"},{"revision":null,"url":"_nuxt/DMLmW6JM.js"},{"revision":null,"url":"_nuxt/Ctbx58Um.js"},{"revision":null,"url":"_nuxt/CndPDbMI.js"},{"revision":null,"url":"_nuxt/Cl45J6_Q.js"},{"revision":null,"url":"_nuxt/CXJnLmWv.js"},{"revision":null,"url":"_nuxt/COCvtdHN.js"},{"revision":null,"url":"_nuxt/CJNhn9sA.js"},{"revision":null,"url":"_nuxt/CJKsMzIp.js"},{"revision":null,"url":"_nuxt/CDWjMk9C.js"},{"revision":null,"url":"_nuxt/C25ROUa9.js"},{"revision":null,"url":"_nuxt/Bpoxvzh6.js"},{"revision":null,"url":"_nuxt/Bd17z0YL.js"},{"revision":null,"url":"_nuxt/BUaYhQ2r.js"},{"revision":null,"url":"_nuxt/BOtcEDnA.js"},{"revision":null,"url":"_nuxt/BEJHMUrj.js"},{"revision":null,"url":"_nuxt/AgentView.DzFWBd2A.css"},{"revision":"d1c26c8c001b83b0e7cbd1084ff810f1","url":"_nuxt/builds/latest.json"},{"revision":null,"url":"_nuxt/builds/meta/4994f3a4-4126-4f57-a9e5-c7ebb25850bc.json"}].map((e) => "/" + (typeof e === "string" ? e : e.url).replace(/^\//, ""))];
18
+ var PRECACHE = ["/", ...[{"revision":"e6a852ba6e2a724d2255af526cb04083","url":"manifest.webmanifest"},{"revision":"b1a14fab8c06784649bf26c636747a86","url":"manifest-en.webmanifest"},{"revision":null,"url":"_nuxt/wherdr-symbols.C1LsPKmg.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-powerline.B_kAMxXr.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-octicons.Hl4VEx8m.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-4.CO_PudDR.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-3.8xz7iX-Y.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-2.C_flbBWO.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-material-1.BdvqkCqW.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-extension.Dai_ky39.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-devicons.ZMSFX1sW.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-codicons.CtEsfSAf.woff2"},{"revision":null,"url":"_nuxt/wherdr-nerd-awesome.DQ3_iAfa.woff2"},{"revision":null,"url":"_nuxt/settings.Cdb21nNw.css"},{"revision":null,"url":"_nuxt/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2"},{"revision":null,"url":"_nuxt/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2"},{"revision":null,"url":"_nuxt/inter-vietnamese-wght-normal.CBcvBZtf.woff2"},{"revision":null,"url":"_nuxt/inter-latin-wght-normal.Dx4kXJAl.woff2"},{"revision":null,"url":"_nuxt/inter-latin-ext-wght-normal.DO1Apj_S.woff2"},{"revision":null,"url":"_nuxt/inter-greek-wght-normal.CkhJZR-_.woff2"},{"revision":null,"url":"_nuxt/inter-greek-ext-wght-normal.DlzME5K_.woff2"},{"revision":null,"url":"_nuxt/inter-cyrillic-wght-normal.DqGufNeO.woff2"},{"revision":null,"url":"_nuxt/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2"},{"revision":null,"url":"_nuxt/hePW80VL.js"},{"revision":null,"url":"_nuxt/error-500.Bwd7zAaE.css"},{"revision":null,"url":"_nuxt/error-404.Bb87HomL.css"},{"revision":null,"url":"_nuxt/entry.CKoXcwRa.css"},{"revision":null,"url":"_nuxt/board.CEEcFc6M.css"},{"revision":null,"url":"_nuxt/archivo-vietnamese-wght-normal.XAtsl5Q_.woff2"},{"revision":null,"url":"_nuxt/archivo-latin-wght-normal.E0tuGl4L.woff2"},{"revision":null,"url":"_nuxt/archivo-latin-ext-wght-normal.C4zznr8T.woff2"},{"revision":null,"url":"_nuxt/R0Y4VoeX.js"},{"revision":null,"url":"_nuxt/NIF0VwHk.js"},{"revision":null,"url":"_nuxt/FaNto0ga.js"},{"revision":null,"url":"_nuxt/DyfFwwGq.js"},{"revision":null,"url":"_nuxt/DrKKeFFE.js"},{"revision":null,"url":"_nuxt/DmkWvmnE.js"},{"revision":null,"url":"_nuxt/DZGKxROq.js"},{"revision":null,"url":"_nuxt/DFmgQVme.js"},{"revision":null,"url":"_nuxt/DFGEl0v2.js"},{"revision":null,"url":"_nuxt/CuUQ4mEf.js"},{"revision":null,"url":"_nuxt/CXJnLmWv.js"},{"revision":null,"url":"_nuxt/CDWjMk9C.js"},{"revision":null,"url":"_nuxt/C3Bkn4ac.js"},{"revision":null,"url":"_nuxt/C25ROUa9.js"},{"revision":null,"url":"_nuxt/BtH82ZuZ.js"},{"revision":null,"url":"_nuxt/Bpoxvzh6.js"},{"revision":null,"url":"_nuxt/BhgehRdJ.js"},{"revision":null,"url":"_nuxt/Bd17z0YL.js"},{"revision":null,"url":"_nuxt/BYZVrreW.js"},{"revision":null,"url":"_nuxt/BHenDMeH.js"},{"revision":null,"url":"_nuxt/BETID3_E.js"},{"revision":null,"url":"_nuxt/BDNMzG2s.js"},{"revision":null,"url":"_nuxt/AgentView.DzFWBd2A.css"},{"revision":"cd669ad19a6e6aac95c99782fbde9967","url":"_nuxt/builds/latest.json"},{"revision":null,"url":"_nuxt/builds/meta/0b28b3e9-664e-4347-a35b-afb0a711d5c5.json"}].map((e) => "/" + (typeof e === "string" ? e : e.url).replace(/^\//, ""))];
19
19
  sw.addEventListener("install", (e) => {
20
20
  e.waitUntil((async () => {
21
21
  const c = await caches.open(CACHE);
@@ -1,4 +1,4 @@
1
- import { s as sendError, bS as useStorage, aH as setResponseHeader } from '../nitro/nitro.mjs';
1
+ import { s as sendError, cd as useStorage, aw as setResponseHeader } from '../nitro/nitro.mjs';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
 
@@ -55,7 +55,7 @@ function parseNumstat(raw) {
55
55
  }
56
56
  return stats;
57
57
  }
58
- function runner(m) {
58
+ function runner(m, signal) {
59
59
  const remoteExec = m.exec;
60
60
  if (remoteExec) return async (script, args, timeout = 12e3) => {
61
61
  const r = await remoteExec(script, args, { timeoutMs: timeout });
@@ -63,7 +63,7 @@ function runner(m) {
63
63
  return r.stdout;
64
64
  };
65
65
  return (script, args, timeout = 12e3) => new Promise((resolve, reject) => {
66
- execFile("sh", ["-c", script, "sh", ...args], { timeout, encoding: "buffer", maxBuffer: 512 * 1024 }, (err, out, stderr) => {
66
+ execFile("sh", ["-c", script, "sh", ...args], { timeout, encoding: "buffer", maxBuffer: 512 * 1024, signal }, (err, out, stderr) => {
67
67
  if (err) reject(new Error(String(stderr || err.message).trim()));
68
68
  else resolve(out);
69
69
  });
@@ -72,8 +72,8 @@ function runner(m) {
72
72
  const git = "git --no-optional-locks -c core.fsmonitor=false -c core.hooksPath=/dev/null -c core.quotePath=false -c diff.external=";
73
73
  const generated = /(^|\/)(?:dist|build|generated|coverage|node_modules|\.nuxt)\/|(^|\/)(?:package-lock\.json|pnpm-lock\.yaml|yarn\.lock|Cargo\.lock|composer\.lock|Gemfile\.lock|.*\.min\.(?:js|css)|.*\.map|.*\.generated\.[^/]+)$/i;
74
74
  const emptySet = () => ({ files: [], truncated: false, count: 0 });
75
- async function gitToplevel(m, cwd) {
76
- const out = await runner(m)(`cd "$1" 2>/dev/null && ${git} rev-parse --show-toplevel 2>/dev/null || true`, [cwd]).catch(() => Buffer.alloc(0));
75
+ async function gitToplevel(m, cwd, signal) {
76
+ const out = await runner(m, signal)(`cd "$1" 2>/dev/null && ${git} rev-parse --show-toplevel 2>/dev/null || true`, [cwd]).catch(() => Buffer.alloc(0));
77
77
  return out.toString("utf8").trim();
78
78
  }
79
79
  async function readChangeStatus(m, cwd) {
@@ -0,0 +1,278 @@
1
+ import { H as HerdrError, a as defineApi, i as getQuery, f as findPane, m as machineFor, aw as setResponseHeader, ax as getRequestHeader, ay as setResponseStatus } from '../nitro/nitro.mjs';
2
+ import { w as writtenTarget, c as cleanRelative, r as rootOf, i as isVideo, O as OPEN_FILE, V as VIDEO_HEAD, s as shellError, v as videoType, a as readWrittenBytes, b as readFileBytes, d as isPdf, e as attachmentHeader } from './files.mjs';
3
+ import { spawn } from 'node:child_process';
4
+ import crypto from 'node:crypto';
5
+ import path from 'node:path';
6
+ import { Readable } from 'node:stream';
7
+
8
+ const VIDEO_BLOCK = 64 * 1024;
9
+ const OPEN_TIMEOUT_MS = 15e3;
10
+ const STREAM_SCRIPT = `${OPEN_FILE}
11
+ m=$(meta) || exit 4
12
+ echo "$(date +%s) $m"
13
+ dd bs=${VIDEO_HEAD} count=1 <&3 2>/dev/null
14
+ read skip count || exit 0
15
+ [ "$count" -gt 0 ] 2>/dev/null || exit 0
16
+ exec dd bs=${VIDEO_BLOCK} skip="$skip" count="$count" <&3 2>/dev/null`;
17
+ function parseRange(header, size) {
18
+ var _a;
19
+ if (header === void 0) return { kind: "full" };
20
+ const m = /^bytes[ \t]*=[ \t]*(.*)$/i.exec(header.trim());
21
+ if (!m) return { kind: "full" };
22
+ const specs = m[1].split(",").map((x) => x.trim()).filter(Boolean);
23
+ if (!specs.length) return { kind: "full" };
24
+ const parsed = [];
25
+ for (const spec of specs) {
26
+ const r = /^(\d*)-(\d*)$/.exec(spec);
27
+ if (!r || !r[1] && !r[2]) return { kind: "full" };
28
+ if (!r[1]) parsed.push({ suffix: Number(r[2]) });
29
+ else {
30
+ const first = Number(r[1]);
31
+ const last = r[2] ? Number(r[2]) : void 0;
32
+ if (last !== void 0 && last < first) return { kind: "full" };
33
+ parsed.push({ first, last });
34
+ }
35
+ }
36
+ for (const p of parsed) {
37
+ if (p.suffix !== void 0) {
38
+ if (p.suffix > 0 && size > 0) return { kind: "part", start: Math.max(0, size - p.suffix), end: size - 1 };
39
+ } else if (p.first < size) {
40
+ return { kind: "part", start: p.first, end: Math.min((_a = p.last) != null ? _a : size - 1, size - 1) };
41
+ }
42
+ }
43
+ return { kind: "none" };
44
+ }
45
+ function answer(v, req) {
46
+ let range = req.method === "HEAD" ? void 0 : req.range;
47
+ if (range !== void 0 && req.ifRange !== void 0 && (req.ifRange.trim() !== v.etag || v.etag.startsWith("W/"))) range = void 0;
48
+ const r = parseRange(range, v.size);
49
+ if (r.kind === "none") return { status: 416, start: 0, len: 0, contentRange: `bytes */${v.size}` };
50
+ if (r.kind === "full") return { status: 200, start: 0, len: v.size };
51
+ return { status: 206, start: r.start, len: r.end - r.start + 1, contentRange: `bytes ${r.start}-${r.end}/${v.size}` };
52
+ }
53
+ function videoEtag(meta) {
54
+ var _a;
55
+ const frac = ((_a = /\.(\d+)/.exec(meta.version)) == null ? void 0 : _a[1]) || "";
56
+ const strong = /[1-9]/.test(frac) && meta.now - meta.mtime >= 2;
57
+ const hash = crypto.createHash("sha1").update(`${meta.ino}|${meta.size}|${meta.version}`).digest("hex").slice(0, 20);
58
+ return `${strong ? "" : "W/"}"${hash}"`;
59
+ }
60
+ function cutOnError(res, body) {
61
+ body.once("error", () => res.destroy());
62
+ return body;
63
+ }
64
+ function readPlan(start, len, head) {
65
+ const fromHead = start < head ? Math.min(len, head - start) : 0;
66
+ const rest = len - fromHead;
67
+ if (rest <= 0) return { fromHead, skip: 0, count: 0, drop: 0 };
68
+ const at = start + fromHead - head;
69
+ const skip = Math.floor(at / VIDEO_BLOCK);
70
+ const drop = at - skip * VIDEO_BLOCK;
71
+ return { fromHead, skip, count: Math.ceil((drop + rest) / VIDEO_BLOCK), drop };
72
+ }
73
+ function spawnScript(m, args) {
74
+ var _a;
75
+ if (!m.exec) {
76
+ return spawn("sh", ["-c", STREAM_SCRIPT, "sh", ...args], { stdio: ["pipe", "pipe", "pipe"], detached: true });
77
+ }
78
+ const child = (_a = m.spawnShell) == null ? void 0 : _a.call(m, STREAM_SCRIPT, args);
79
+ if (!child) throw new HerdrError("unreachable", "Machine unreachable");
80
+ return child;
81
+ }
82
+ function kill(child, local) {
83
+ if (child.exitCode !== null || child.signalCode !== null) return;
84
+ try {
85
+ if (local && child.pid) process.kill(-child.pid, "SIGKILL");
86
+ else child.kill("SIGKILL");
87
+ } catch {
88
+ }
89
+ }
90
+ const closedError = () => new HerdrError("closed", "Request closed");
91
+ async function openAt(m, root, rel, signal) {
92
+ if (signal == null ? void 0 : signal.aborted) throw closedError();
93
+ const child = spawnScript(m, [root, rel]);
94
+ const done = new Promise((resolve) => {
95
+ child.on("close", () => resolve());
96
+ child.on("error", () => resolve());
97
+ });
98
+ const local = !m.exec;
99
+ const close = () => kill(child, local);
100
+ child.stdin.on("error", () => {
101
+ });
102
+ let buf = Buffer.alloc(0);
103
+ let stderr = "";
104
+ child.stderr.on("data", (b) => {
105
+ if (stderr.length < 4e3) stderr += b.toString("utf8");
106
+ });
107
+ const opened = await new Promise((resolve, reject) => {
108
+ const timer = setTimeout(() => {
109
+ close();
110
+ reject(new HerdrError("timeout", "The folder took too long to read"));
111
+ }, OPEN_TIMEOUT_MS);
112
+ const onAbort = () => done2(() => {
113
+ close();
114
+ reject(closedError());
115
+ });
116
+ signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
117
+ const done2 = (f) => {
118
+ clearTimeout(timer);
119
+ signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
120
+ child.stdout.off("data", onData);
121
+ child.off("close", onClose);
122
+ child.off("error", onError);
123
+ f();
124
+ };
125
+ const onData = (b) => {
126
+ buf = Buffer.concat([buf, b]);
127
+ const nl = buf.indexOf(10);
128
+ if (nl < 0) return;
129
+ const [now = "0", ino = "0", size = "0", mtime = "0", ...version] = buf.subarray(0, nl).toString("utf8").trim().split(/\s+/);
130
+ const n = Number(size) || 0;
131
+ const headLen = Math.min(VIDEO_HEAD, n);
132
+ if (buf.length - nl - 1 < headLen) return;
133
+ child.stdout.pause();
134
+ const head = buf.subarray(nl + 1, nl + 1 + headLen);
135
+ done2(() => resolve({ now: Number(now) || 0, ino, size: n, mtime: Number(mtime) || 0, version: version.join(" "), head }));
136
+ };
137
+ const onClose = (code) => done2(() => reject(code === 0 ? new HerdrError("not_found", "File not found") : shellError(m, code, stderr)));
138
+ const onError = () => done2(() => reject(new HerdrError("unreachable", "Machine unreachable")));
139
+ child.stdout.on("data", onData);
140
+ child.on("close", onClose);
141
+ child.on("error", onError);
142
+ });
143
+ const name = path.posix.basename(rel);
144
+ if (!isVideo(name, opened.head)) {
145
+ close();
146
+ throw new HerdrError("not_video", "Not a video");
147
+ }
148
+ let reading = false;
149
+ return {
150
+ name,
151
+ size: opened.size,
152
+ mtime: opened.mtime,
153
+ etag: videoEtag(opened),
154
+ close,
155
+ done,
156
+ read(start, len) {
157
+ if (reading) throw new Error("read once");
158
+ reading = true;
159
+ const plan = readPlan(start, len, opened.head.length);
160
+ child.stdin.end(`${plan.skip} ${plan.count}
161
+ `);
162
+ const out = child.stdout;
163
+ async function* bytes() {
164
+ let left = len;
165
+ try {
166
+ if (plan.fromHead) {
167
+ yield opened.head.subarray(start, start + plan.fromHead);
168
+ left -= plan.fromHead;
169
+ }
170
+ let drop = plan.drop;
171
+ for await (const chunk of out) {
172
+ if (left <= 0) break;
173
+ let c = chunk;
174
+ if (drop) {
175
+ const n = Math.min(drop, c.length);
176
+ c = c.subarray(n);
177
+ drop -= n;
178
+ }
179
+ if (!c.length) continue;
180
+ if (c.length > left) c = c.subarray(0, left);
181
+ left -= c.length;
182
+ yield c;
183
+ if (left <= 0) break;
184
+ }
185
+ if (left > 0) throw new HerdrError("truncated", "The file shrank while being read");
186
+ } finally {
187
+ close();
188
+ }
189
+ }
190
+ return Readable.from(bytes(), { objectMode: false });
191
+ }
192
+ };
193
+ }
194
+ function untilClosed(p, signal) {
195
+ if (!signal) return p;
196
+ if (signal.aborted) return Promise.reject(closedError());
197
+ return new Promise((resolve, reject) => {
198
+ const onAbort = () => reject(closedError());
199
+ signal.addEventListener("abort", onAbort, { once: true });
200
+ p.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
201
+ });
202
+ }
203
+ async function openVideo(m, cwd, rel, signal) {
204
+ if (signal == null ? void 0 : signal.aborted) throw closedError();
205
+ const p = cleanRelative(rel);
206
+ if (!p) throw new HerdrError("not_file", "Not a file");
207
+ const root = await untilClosed(rootOf(m, cwd, signal), signal);
208
+ if (signal == null ? void 0 : signal.aborted) throw closedError();
209
+ return openAt(m, root, p, signal);
210
+ }
211
+ async function openWrittenVideo(m, cwd, written, signal) {
212
+ const t = writtenTarget(m, cwd, written);
213
+ return openAt(m, t.root, t.rel, signal);
214
+ }
215
+
216
+ async function serveVideo(event, p, q, type) {
217
+ const m = machineFor(p.machine);
218
+ const res = event.node.res;
219
+ const closed = new AbortController();
220
+ res.once("close", () => closed.abort());
221
+ if (res.destroyed) closed.abort();
222
+ const v = q.from === "chat" ? await openWrittenVideo(m, p.cwd, q.path, closed.signal) : await openVideo(m, p.cwd, q.path, closed.signal);
223
+ if (closed.signal.aborted) {
224
+ v.close();
225
+ return "";
226
+ }
227
+ closed.signal.addEventListener("abort", v.close, { once: true });
228
+ try {
229
+ setResponseHeader(event, "x-content-type-options", "nosniff");
230
+ setResponseHeader(event, "accept-ranges", "bytes");
231
+ setResponseHeader(event, "content-security-policy", "default-src 'none'; media-src 'self'; frame-ancestors 'self'");
232
+ setResponseHeader(event, "etag", v.etag);
233
+ setResponseHeader(event, "last-modified", new Date(v.mtime * 1e3).toUTCString());
234
+ const a = answer(v, { method: event.method, range: getRequestHeader(event, "range"), ifRange: getRequestHeader(event, "if-range") });
235
+ setResponseStatus(event, a.status);
236
+ if (a.contentRange) setResponseHeader(event, "content-range", a.contentRange);
237
+ if (a.status === 416) {
238
+ v.close();
239
+ setResponseHeader(event, "content-type", "text/plain");
240
+ return "";
241
+ }
242
+ setResponseHeader(event, "content-type", type);
243
+ setResponseHeader(event, "content-disposition", attachmentHeader(v.name, "inline"));
244
+ setResponseHeader(event, "content-length", a.len);
245
+ if (event.method === "HEAD" || !a.len) {
246
+ v.close();
247
+ return "";
248
+ }
249
+ return cutOnError(res, v.read(a.start, a.len));
250
+ } catch (e) {
251
+ v.close();
252
+ throw e;
253
+ }
254
+ }
255
+ const fileDownload = defineApi(async (event) => {
256
+ const q = getQuery(event);
257
+ const p = findPane(String(q.pane || ""));
258
+ if (!p) throw new HerdrError("bad_pane", "Pane not found");
259
+ if (q.from !== "chat" && !p.cwd) throw new HerdrError("bad_cwd", "This agent\u2019s folder is unknown");
260
+ const video = q.inline === "1" ? videoType(String(q.path || "")) : void 0;
261
+ if (video) return serveVideo(event, p, q, video);
262
+ const f = q.from === "chat" ? await readWrittenBytes(machineFor(p.machine), p.cwd, q.path) : await readFileBytes(machineFor(p.machine), p.cwd, q.path);
263
+ setResponseHeader(event, "x-content-type-options", "nosniff");
264
+ if (q.inline === "1" && isPdf(f.name, f.body)) {
265
+ setResponseHeader(event, "content-type", "application/pdf");
266
+ setResponseHeader(event, "content-disposition", attachmentHeader(f.name, "inline"));
267
+ setResponseHeader(event, "content-security-policy", "default-src 'none'; object-src 'self'; frame-ancestors 'self'");
268
+ setResponseHeader(event, "cache-control", "private, no-store");
269
+ return f.body;
270
+ }
271
+ setResponseHeader(event, "content-type", "application/octet-stream");
272
+ setResponseHeader(event, "content-disposition", attachmentHeader(f.name));
273
+ setResponseHeader(event, "content-security-policy", "default-src 'none'; sandbox");
274
+ return f.body;
275
+ });
276
+
277
+ export { fileDownload as f };
278
+ //# sourceMappingURL=fileDownload.mjs.map
@@ -21,6 +21,16 @@ const IMAGE_TYPES = {
21
21
  };
22
22
  const PDF_HEAD = 1024;
23
23
  const isPdf = (name, head) => path.posix.extname(name).toLowerCase() === ".pdf" && head.subarray(0, PDF_HEAD).includes("%PDF-");
24
+ const VIDEO_TYPES = { mp4: "video/mp4", m4v: "video/mp4", mov: "video/quicktime", webm: "video/webm" };
25
+ const VIDEO_HEAD = 12;
26
+ const MP4_BOXES = /* @__PURE__ */ new Set(["ftyp", "moov", "mdat", "wide", "free", "skip", "pnot"]);
27
+ const videoType = (name) => VIDEO_TYPES[path.posix.extname(name).slice(1).toLowerCase()];
28
+ function isVideo(name, head) {
29
+ const type = videoType(name);
30
+ if (!type || head.length < 8) return false;
31
+ if (type === "video/webm") return head.readUInt32BE(0) === 440786851;
32
+ return MP4_BOXES.has(head.subarray(4, 8).toString("latin1"));
33
+ }
24
34
  const RESOLVE = `root=$(cd "$1" 2>/dev/null && pwd -P) || { echo "folder not found" >&2; exit 3; }
25
35
  under() { case "$1/" in "\${root%/}/"*) return 0 ;; esac; return 1; }`;
26
36
  const LIST_SCRIPT = `${RESOLVE}
@@ -52,7 +62,7 @@ printf '=\\0'
52
62
  [ "$#" -gt 0 ] || exit 0
53
63
  if stat -f %z / >/dev/null 2>&1; then stat -f %z -- "$@"; else stat -c %s -- "$@"; fi 2>/dev/null
54
64
  exit 0`;
55
- const READ_SCRIPT = `${RESOLVE}
65
+ const OPEN_FILE = `${RESOLVE}
56
66
  case "$2" in */*) d=\${2%/*} ;; *) d=. ;; esac
57
67
  b=\${2##*/}
58
68
  dir=$(cd "$root" && cd -- "./$d" 2>/dev/null && pwd -P) || { echo "not found" >&2; exit 4; }
@@ -69,10 +79,21 @@ done
69
79
  under "$f" || { echo "outside" >&2; exit 5; }
70
80
  [ -f "$f" ] || { echo "not a file" >&2; exit 6; }
71
81
  [ -r "$f" ] || { echo "permission denied" >&2; exit 7; }
72
- s=$(wc -c < "$f") || exit 4
82
+ command exec 3< "$f" || { echo "permission denied" >&2; exit 7; }
83
+ # "<inode> <size> <mtime> <version>" of the opened file, from its metadata:
84
+ # never a read (BusyBox's wc -c reads every byte). <version>: modification
85
+ # and change times to the nanosecond (GNU/BusyBox, then BSD). Without the
86
+ # descriptor's metadata, the path's, with no <version>: never a strong ETag.
87
+ meta() {
88
+ stat -L -c '%i %s %Y %y %z' /dev/fd/3 2>/dev/null || stat -L -f '%i %z %m %Fm %Fc' /dev/fd/3 2>/dev/null ||
89
+ stat -L -c '%i %s %Y' "$f" 2>/dev/null || stat -L -f '%i %z %m' "$f" 2>/dev/null || echo "0 $(wc -c < "$f") 0"
90
+ }`;
91
+ const READ_SCRIPT = `${OPEN_FILE}
92
+ m=$(meta) || exit 4
93
+ s=\${m#* }; s=$((\${s%% *}))
73
94
  echo $s
74
- [ -n "$4" ] && [ $(($s)) -ge "$3" ] && exit 0
75
- head -c "$3" < "$f"`;
95
+ [ -n "$4" ] && [ "$s" -ge "$3" ] && exit 0
96
+ head -c "$3" <&3`;
76
97
  const MACOS_SSH_DENIED = "macOS blocks access to this folder. On the Mac: System Settings \u203A General \u203A Sharing \u203A Remote Login \u24D8 \u203A \u201CAllow full disk access for remote users\u201D.";
77
98
  const MACOS_LOCAL_DENIED = "macOS blocks access to this folder. Allow the app that runs wherdr in System Settings \u203A Privacy & Security \u203A Full Disk Access.";
78
99
  function executor(m, { timeoutMs = 15e3, maxBytes = IMAGE_BYTES } = {}) {
@@ -89,15 +110,19 @@ function executor(m, { timeoutMs = 15e3, maxBytes = IMAGE_BYTES } = {}) {
89
110
  async function run(m, script, args, opts) {
90
111
  const r = await executor(m, opts)(script, args);
91
112
  if (r.code === 0) return r.stdout;
92
- if (r.code === 3) throw new HerdrError("bad_cwd", "This agent\u2019s folder is unknown");
93
- if (r.code === 4) throw new HerdrError("not_found", "File not found");
94
- if (r.code === 5) throw new HerdrError("outside", "Outside the project folder");
95
- if (r.code === 6) throw new HerdrError("not_file", "Not a file");
96
- if (r.code === 7) throw new HerdrError("denied", "Permission denied");
97
- if (r.code === 8) throw new HerdrError("denied", m.exec ? MACOS_SSH_DENIED : MACOS_LOCAL_DENIED);
98
- if (r.code === 124) throw new HerdrError("timeout", "The folder took too long to read");
99
- if (r.code === 255 || r.code === null) throw new HerdrError("unreachable", "Machine unreachable");
100
- throw new HerdrError("remote", r.stderr.trim().split("\n").pop() || `code ${r.code}`);
113
+ throw shellError(m, r.code, r.stderr);
114
+ }
115
+ function shellError(m, code, stderr) {
116
+ const r = { code, stderr };
117
+ if (r.code === 3) return new HerdrError("bad_cwd", "This agent\u2019s folder is unknown");
118
+ if (r.code === 4) return new HerdrError("not_found", "File not found");
119
+ if (r.code === 5) return new HerdrError("outside", "Outside the project folder");
120
+ if (r.code === 6) return new HerdrError("not_file", "Not a file");
121
+ if (r.code === 7) return new HerdrError("denied", "Permission denied");
122
+ if (r.code === 8) return new HerdrError("denied", m.exec ? MACOS_SSH_DENIED : MACOS_LOCAL_DENIED);
123
+ if (r.code === 124) return new HerdrError("timeout", "The folder took too long to read");
124
+ if (r.code === 255 || r.code === null) return new HerdrError("unreachable", "Machine unreachable");
125
+ return new HerdrError("remote", r.stderr.trim().split("\n").pop() || `code ${r.code}`);
101
126
  }
102
127
  function cleanRelative(p) {
103
128
  const raw = String(p != null ? p : "").replace(/\\/g, "/");
@@ -134,8 +159,8 @@ function parseListing(raw) {
134
159
  entries.sort((a, b) => Number(b.kind === "dir") - Number(a.kind === "dir") || a.name.localeCompare(b.name, void 0, { numeric: true, sensitivity: "base" }));
135
160
  return { root, dir, entries, truncated };
136
161
  }
137
- async function rootOf(m, cwd) {
138
- return await gitToplevel(m, cwd) || cwd;
162
+ async function rootOf(m, cwd, signal) {
163
+ return await gitToplevel(m, cwd, signal) || cwd;
139
164
  }
140
165
  async function listFiles(m, cwd, rel, opts = {}) {
141
166
  var _a, _b;
@@ -170,7 +195,9 @@ async function readHead(m, root, rel, max, opts) {
170
195
  async function previewAt(m, root, rel, shown) {
171
196
  const ext = path.posix.extname(rel).slice(1).toLowerCase();
172
197
  const mime = IMAGE_TYPES[ext];
173
- const { size, body } = await readHead(m, root, rel, mime ? IMAGE_BYTES + 1 : ext === "pdf" ? PDF_HEAD : TEXT_BYTES + 1);
198
+ const video = VIDEO_TYPES[ext];
199
+ const { size, body } = await readHead(m, root, rel, mime ? IMAGE_BYTES + 1 : ext === "pdf" ? PDF_HEAD : video ? VIDEO_HEAD : TEXT_BYTES + 1);
200
+ if (video) return { path: shown, size, kind: isVideo(rel, body) ? "video" : "binary", truncated: false };
174
201
  if (ext === "pdf") {
175
202
  if (!isPdf(rel, body)) return { path: shown, size, kind: "binary", truncated: false };
176
203
  return { path: shown, size, kind: size > DOWNLOAD_BYTES ? "large" : "pdf", truncated: false };
@@ -213,5 +240,5 @@ function attachmentHeader(name, type = "attachment") {
213
240
  return `${type}; filename="${ascii}"; filename*=UTF-8''${utf8}`;
214
241
  }
215
242
 
216
- export { readFileBytes as a, attachmentHeader as b, readWrittenPreview as c, readFilePreview as d, isPdf as i, listFiles as l, readWrittenBytes as r };
243
+ export { OPEN_FILE as O, VIDEO_HEAD as V, readWrittenBytes as a, readFileBytes as b, cleanRelative as c, isPdf as d, attachmentHeader as e, readWrittenPreview as f, readFilePreview as g, isVideo as i, listFiles as l, rootOf as r, shellError as s, videoType as v, writtenTarget as w };
217
244
  //# sourceMappingURL=files.mjs.map
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { randomUUID } from 'node:crypto';
4
- import { aQ as baseMachines, aR as DATA_DIR } from '../nitro/nitro.mjs';
4
+ import { aG as baseMachines, aH as DATA_DIR } from '../nitro/nitro.mjs';
5
5
 
6
6
  function cleanMachineOrder(value, known) {
7
7
  if (!Array.isArray(value)) return [];
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { b1 as HOST_LABEL, aR as DATA_DIR } from '../nitro/nitro.mjs';
3
+ import { aW as HOST_LABEL, aH as DATA_DIR } from '../nitro/nitro.mjs';
4
4
 
5
5
  const ONBOARDING_FILE = path.join(DATA_DIR, "onboarding.json");
6
6
  function readOnboarding(file = ONBOARDING_FILE, host = HOST_LABEL) {
@@ -1,5 +1,5 @@
1
1
  var name = "wherdr";
2
- var version = "1.3.4";
2
+ var version = "2.0.0";
3
3
  var license = "MIT";
4
4
  var type = "module";
5
5
  var description = "Unofficial mobile web client (PWA) to drive the coding agents running in Herdr";
@@ -25,7 +25,8 @@ var files = [
25
25
  ".output",
26
26
  "!.output/**/*.map",
27
27
  "bin",
28
- "skills/wherdr"
28
+ "skills/wherdr",
29
+ "docs/*.md"
29
30
  ];
30
31
  var engines = {
31
32
  node: ">=22"
@@ -38,10 +39,15 @@ var scripts = {
38
39
  typecheck: "nuxt typecheck",
39
40
  test: "vitest run",
40
41
  "test:e2e": "playwright test",
42
+ "shots:readme": "node tools/readme-shots/capture.mjs",
43
+ "test:e2e:shots": "SHOTS=${SHOTS:-.shots} playwright test tests/e2e/question-reply.spec.ts --grep screenshot:",
44
+ "test:e2e:stability": "playwright test menu-responsiveness codex-self-update quote-mode onboarding-tailnet --grep \"MCP arrow paints|a new Codex restarts|the former per-device values|a quoted question keeps|#/setup[?]step=security opens|a direct Security link\"",
41
45
  prepare: "nuxt prepare",
42
46
  prepack: "nuxt build && node scripts/pack-output.mjs",
47
+ "check:docs": "node scripts/check-doc-links.mjs",
43
48
  "check:leaks": "node scripts/check-leaks.mjs",
44
- "hooks:install": "git config core.hooksPath .githooks"
49
+ "hooks:install": "git config core.hooksPath .githooks",
50
+ "test:affected": "node scripts/test-affected.mjs"
45
51
  };
46
52
  var dependencies = {
47
53
  "qrcode-terminal": "^0.12.0"