@weavecode/weave 0.1.0 → 0.1.2

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 (300) hide show
  1. package/node_modules/@weavecode/cli/dist/cli.js +3 -3
  2. package/node_modules/@weavecode/cli/dist/commands/daemon.d.ts +7 -0
  3. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  4. package/node_modules/@weavecode/cli/dist/commands/dashboard.d.ts +0 -2
  5. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -1
  6. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  7. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  8. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  9. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  10. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  11. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +6 -12
  12. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +44 -2
  13. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +6 -12
  14. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.d.ts +2 -3
  15. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +4 -4
  16. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  17. package/node_modules/@weavecode/cli/dist/init/git-commit.js +1 -1
  18. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  19. package/node_modules/@weavecode/cli/dist/init/harnesses/zcode.d.ts +29 -0
  20. package/node_modules/@weavecode/cli/dist/init/harnesses/zcode.js +1 -0
  21. package/node_modules/@weavecode/cli/dist/init/helpers-gen.d.ts +4 -0
  22. package/node_modules/@weavecode/cli/dist/init/helpers-gen.js +1 -20
  23. package/node_modules/@weavecode/cli/dist/init/mcp-gen.d.ts +3 -20
  24. package/node_modules/@weavecode/cli/dist/init/mcp-gen.js +1 -1
  25. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  26. package/node_modules/@weavecode/cli/dist/init/settings-gen.d.ts +3 -30
  27. package/node_modules/@weavecode/cli/dist/init/settings-gen.js +1 -1
  28. package/node_modules/@weavecode/cli/package.json +5 -5
  29. package/node_modules/@weavecode/core/dist/harness.d.ts +45 -2
  30. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  31. package/node_modules/@weavecode/core/dist/index.d.ts +2 -2
  32. package/node_modules/@weavecode/core/dist/index.js +1 -1
  33. package/node_modules/@weavecode/core/dist/terminal.d.ts +28 -4
  34. package/node_modules/@weavecode/core/dist/terminal.js +1 -1
  35. package/node_modules/@weavecode/core/dist/types.d.ts +188 -19
  36. package/node_modules/@weavecode/core/dist/types.js +1 -1
  37. package/node_modules/@weavecode/core/package.json +1 -1
  38. package/node_modules/@weavecode/harness/dist/claude/assets.d.ts +10 -0
  39. package/node_modules/@weavecode/harness/dist/claude/assets.js +4 -1
  40. package/node_modules/@weavecode/harness/dist/claude/capture.d.ts +15 -3
  41. package/node_modules/@weavecode/harness/dist/claude/capture.js +15 -9
  42. package/node_modules/@weavecode/harness/dist/claude/event-source.d.ts +1 -1
  43. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  44. package/node_modules/@weavecode/harness/dist/claude/helpers-gen.d.ts +5 -0
  45. package/node_modules/@weavecode/harness/dist/claude/helpers-gen.js +20 -0
  46. package/node_modules/@weavecode/harness/dist/claude/index.d.ts +10 -1
  47. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  48. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.d.ts +22 -0
  49. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -0
  50. package/node_modules/@weavecode/harness/dist/claude/messaging.d.ts +11 -2
  51. package/node_modules/@weavecode/harness/dist/claude/messaging.js +4 -1
  52. package/node_modules/@weavecode/harness/dist/claude/model-aliases.d.ts +39 -0
  53. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -0
  54. package/node_modules/@weavecode/harness/dist/claude/plan.d.ts +2 -0
  55. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -0
  56. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -1
  57. package/node_modules/@weavecode/harness/dist/claude/settings-gen.d.ts +32 -0
  58. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -0
  59. package/node_modules/@weavecode/harness/dist/claude/side-question.d.ts +12 -0
  60. package/node_modules/@weavecode/harness/dist/claude/side-question.js +1 -0
  61. package/node_modules/@weavecode/harness/dist/claude/statusline/config.d.ts +200 -0
  62. package/node_modules/@weavecode/harness/dist/claude/statusline/config.js +1 -0
  63. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.d.ts +12 -0
  64. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +745 -0
  65. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.d.ts +10 -0
  66. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -0
  67. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.d.ts +20 -0
  68. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -0
  69. package/node_modules/@weavecode/harness/dist/claude/transcript.d.ts +16 -0
  70. package/node_modules/@weavecode/harness/dist/claude/transcript.js +4 -2
  71. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  72. package/node_modules/@weavecode/harness/dist/codex/index.d.ts +1 -0
  73. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  74. package/node_modules/@weavecode/harness/dist/codex/mcp.d.ts +30 -0
  75. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -0
  76. package/node_modules/@weavecode/harness/dist/codex/messaging.js +1 -1
  77. package/node_modules/@weavecode/harness/dist/driver.d.ts +168 -3
  78. package/node_modules/@weavecode/harness/dist/index.d.ts +1 -0
  79. package/node_modules/@weavecode/harness/dist/index.js +1 -1
  80. package/node_modules/@weavecode/harness/dist/init/generated.d.ts +37 -0
  81. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -0
  82. package/node_modules/@weavecode/harness/dist/registry-wiring.d.ts +3 -1
  83. package/node_modules/@weavecode/harness/dist/zcode/assets.d.ts +8 -0
  84. package/node_modules/@weavecode/harness/dist/zcode/assets.js +1 -0
  85. package/node_modules/@weavecode/harness/dist/zcode/capture.d.ts +36 -0
  86. package/node_modules/@weavecode/harness/dist/zcode/capture.js +3 -0
  87. package/node_modules/@weavecode/harness/dist/zcode/detect.d.ts +2 -0
  88. package/node_modules/@weavecode/harness/dist/zcode/detect.js +1 -0
  89. package/node_modules/@weavecode/harness/dist/zcode/event-source.d.ts +8 -0
  90. package/node_modules/@weavecode/harness/dist/zcode/event-source.js +1 -0
  91. package/node_modules/@weavecode/harness/dist/zcode/index.d.ts +13 -0
  92. package/node_modules/@weavecode/harness/dist/zcode/index.js +1 -0
  93. package/node_modules/@weavecode/harness/dist/zcode/mcp.d.ts +6 -0
  94. package/node_modules/@weavecode/harness/dist/zcode/mcp.js +2 -0
  95. package/node_modules/@weavecode/harness/dist/zcode/messaging.d.ts +13 -0
  96. package/node_modules/@weavecode/harness/dist/zcode/messaging.js +1 -0
  97. package/node_modules/@weavecode/harness/dist/zcode/resume.d.ts +7 -0
  98. package/node_modules/@weavecode/harness/dist/zcode/resume.js +1 -0
  99. package/node_modules/@weavecode/harness/package.json +2 -2
  100. package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
  101. package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
  102. package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
  103. package/node_modules/@weavecode/server/dist/daemon/api-log.d.ts +48 -0
  104. package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -0
  105. package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
  106. package/node_modules/@weavecode/server/dist/daemon/auto-start.js +6 -6
  107. package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
  108. package/node_modules/@weavecode/server/dist/daemon/claude-liveness.js +1 -1
  109. package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
  110. package/node_modules/@weavecode/server/dist/daemon/data-bus.js +1 -1
  111. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  112. package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
  113. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.d.ts +13 -1
  114. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
  115. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  116. package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
  117. package/node_modules/@weavecode/server/dist/daemon/opener.d.ts +102 -19
  118. package/node_modules/@weavecode/server/dist/daemon/opener.js +97 -7
  119. package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
  120. package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
  121. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.d.ts +4 -3
  122. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
  123. package/node_modules/@weavecode/server/dist/daemon/server.d.ts +15 -0
  124. package/node_modules/@weavecode/server/dist/daemon/server.js +8 -6
  125. package/node_modules/@weavecode/server/dist/daemon/session-probe.d.ts +72 -2
  126. package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
  127. package/node_modules/@weavecode/server/dist/daemon/settings.d.ts +10 -0
  128. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  129. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.d.ts +7 -1
  130. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.js +1 -1
  131. package/node_modules/@weavecode/server/dist/daemon/sse-hub.d.ts +40 -0
  132. package/node_modules/@weavecode/server/dist/daemon/sse-hub.js +1 -0
  133. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  134. package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
  135. package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
  136. package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.d.ts +4 -1
  137. package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
  138. package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
  139. package/node_modules/@weavecode/server/dist/db/db.js +38 -2
  140. package/node_modules/@weavecode/server/dist/db/paths.d.ts +4 -0
  141. package/node_modules/@weavecode/server/dist/db/paths.js +1 -1
  142. package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
  143. package/node_modules/@weavecode/server/dist/hooks/bus.d.ts +5 -0
  144. package/node_modules/@weavecode/server/dist/hooks/bus.js +1 -1
  145. package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
  146. package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
  147. package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
  148. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.d.ts +17 -4
  149. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -1
  150. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.d.ts +27 -6
  151. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
  152. package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
  153. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.d.ts +200 -13
  154. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +3 -2
  155. package/node_modules/@weavecode/server/dist/hooks/mirror.d.ts +9 -4
  156. package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
  157. package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
  158. package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
  159. package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
  160. package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
  161. package/node_modules/@weavecode/server/dist/hooks/promptbox.d.ts +13 -0
  162. package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
  163. package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
  164. package/node_modules/@weavecode/server/dist/hooks/question-tracker.d.ts +6 -4
  165. package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
  166. package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
  167. package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
  168. package/node_modules/@weavecode/server/dist/hooks/sequence-engine.js +1 -1
  169. package/node_modules/@weavecode/server/dist/hooks/session-purge.d.ts +7 -0
  170. package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
  171. package/node_modules/@weavecode/server/dist/hooks/session-sweeper.d.ts +5 -8
  172. package/node_modules/@weavecode/server/dist/hooks/session-sweeper.js +1 -1
  173. package/node_modules/@weavecode/server/dist/hooks/side-questions.d.ts +41 -0
  174. package/node_modules/@weavecode/server/dist/hooks/side-questions.js +1 -0
  175. package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
  176. package/node_modules/@weavecode/server/dist/hooks/toolkit.d.ts +8 -0
  177. package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
  178. package/node_modules/@weavecode/server/dist/hooks/watch-engine.d.ts +7 -0
  179. package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
  180. package/node_modules/@weavecode/server/dist/index.d.ts +1 -1
  181. package/node_modules/@weavecode/server/dist/install/apply-update.d.ts +1 -1
  182. package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
  183. package/node_modules/@weavecode/server/dist/install/capabilities.d.ts +10 -0
  184. package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
  185. package/node_modules/@weavecode/server/dist/install/codex-toml.d.ts +8 -26
  186. package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
  187. package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
  188. package/node_modules/@weavecode/server/dist/install/fingerprint.d.ts +5 -1
  189. package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
  190. package/node_modules/@weavecode/server/dist/install/git-classify.d.ts +30 -0
  191. package/node_modules/@weavecode/server/dist/install/git-classify.js +1 -0
  192. package/node_modules/@weavecode/server/dist/install/global-config.d.ts +2 -4
  193. package/node_modules/@weavecode/server/dist/install/global-config.js +1 -2
  194. package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
  195. package/node_modules/@weavecode/server/dist/install/init-files.d.ts +46 -0
  196. package/node_modules/@weavecode/server/dist/install/init-files.js +2 -0
  197. package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
  198. package/node_modules/@weavecode/server/dist/install/installer.d.ts +3 -5
  199. package/node_modules/@weavecode/server/dist/install/installer.js +1 -3
  200. package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
  201. package/node_modules/@weavecode/server/dist/install/mcp-rows.d.ts +5 -5
  202. package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
  203. package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
  204. package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
  205. package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
  206. package/node_modules/@weavecode/server/dist/install/project-config.d.ts +0 -2
  207. package/node_modules/@weavecode/server/dist/install/project-config.js +2 -2
  208. package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
  209. package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
  210. package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
  211. package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
  212. package/node_modules/@weavecode/server/dist/install/updates.d.ts +17 -5
  213. package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
  214. package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
  215. package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
  216. package/node_modules/@weavecode/server/dist/market/import.js +2 -2
  217. package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
  218. package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
  219. package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
  220. package/node_modules/@weavecode/server/dist/registry.js +2 -2
  221. package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +5 -5
  222. package/node_modules/@weavecode/server/dist/repositories/hook-events.d.ts +7 -0
  223. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +2 -2
  224. package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
  225. package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
  226. package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
  227. package/node_modules/@weavecode/server/dist/repositories/projects.d.ts +7 -0
  228. package/node_modules/@weavecode/server/dist/repositories/projects.js +2 -2
  229. package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
  230. package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
  231. package/node_modules/@weavecode/server/dist/repositories/sessions.d.ts +32 -8
  232. package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
  233. package/node_modules/@weavecode/server/dist/repositories/side-questions.d.ts +50 -0
  234. package/node_modules/@weavecode/server/dist/repositories/side-questions.js +6 -0
  235. package/node_modules/@weavecode/server/dist/repositories/uploads.d.ts +66 -0
  236. package/node_modules/@weavecode/server/dist/repositories/uploads.js +7 -0
  237. package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
  238. package/node_modules/@weavecode/server/dist/statusline/config.d.ts +4 -198
  239. package/node_modules/@weavecode/server/dist/statusline/config.js +1 -1
  240. package/node_modules/@weavecode/server/dist/statusline/generator.d.ts +5 -0
  241. package/node_modules/@weavecode/server/dist/statusline/generator.js +1 -676
  242. package/node_modules/@weavecode/server/dist/statusline/manager.d.ts +7 -5
  243. package/node_modules/@weavecode/server/dist/statusline/manager.js +3 -4
  244. package/node_modules/@weavecode/server/dist/surfaces.d.ts +11 -1
  245. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  246. package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
  247. package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
  248. package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
  249. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.d.ts +8 -4
  250. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
  251. package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
  252. package/node_modules/@weavecode/server/package.json +4 -4
  253. package/node_modules/@weavecode/server/web/dist/assets/index-CHWbLAje.js +594 -0
  254. package/node_modules/@weavecode/server/web/dist/assets/index-D0s5v8QS.css +11 -0
  255. package/node_modules/@weavecode/server/web/dist/index.html +14 -2
  256. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-plugin-creator/skills/weave-plugin-creator/SKILL.md +2 -2
  257. package/node_modules/@weavecode/templates/package.json +2 -2
  258. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/README.md +50 -32
  259. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.d.ts +86 -40
  260. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.es.js +860 -353
  261. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.js +860 -353
  262. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/package.json +20 -17
  263. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/README.md +50 -32
  264. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.d.ts +86 -40
  265. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.es.js +860 -353
  266. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.js +860 -353
  267. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/package.json +20 -17
  268. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/README.md +50 -32
  269. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.d.ts +86 -40
  270. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.es.js +860 -353
  271. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.js +860 -353
  272. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/package.json +20 -17
  273. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/README.md +50 -32
  274. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.d.ts +86 -40
  275. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.es.js +860 -353
  276. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.js +860 -353
  277. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/package.json +20 -17
  278. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/README.md +50 -32
  279. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.d.ts +86 -40
  280. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.es.js +860 -353
  281. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.js +860 -353
  282. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/package.json +20 -17
  283. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/README.md +50 -32
  284. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.d.ts +86 -40
  285. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.es.js +860 -353
  286. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.js +860 -353
  287. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/package.json +20 -17
  288. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/README.md +50 -32
  289. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.d.ts +86 -40
  290. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.es.js +860 -353
  291. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.js +860 -353
  292. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/package.json +20 -17
  293. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/README.md +50 -32
  294. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.d.ts +86 -40
  295. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.es.js +860 -353
  296. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.js +860 -353
  297. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/package.json +20 -17
  298. package/package.json +6 -6
  299. package/node_modules/@weavecode/server/web/dist/assets/index-BOzaRlQE.js +0 -560
  300. package/node_modules/@weavecode/server/web/dist/assets/index-ChX8G8cT.css +0 -11
@@ -59,7 +59,7 @@ export declare abstract class TerminalBackend {
59
59
  * default_prog,且 mux 在时会挂死出无窗僵尸而 trySpawn 假成功)。
60
60
  */
61
61
  run(dir: string, argv: string[]): Promise<void>;
62
- /** 每目录已开窗口数;不支持的 preset 走这里(空表 = 角标不显示,不谎报)。 */
62
+ /** 每目录已开终端数(单位 = 本后端的可见屏幕);不支持的 preset 走这里(空表 = 角标不显示,不谎报)。 */
63
63
  countWindows(_dirs: readonly string[]): Promise<Map<string, number>>;
64
64
  /** 可附加目标(窗口内的 tab);不支持的 preset 走这里。 */
65
65
  listTargets(_dir: string): Promise<AttachTarget[]>;
@@ -69,21 +69,61 @@ export declare abstract class TerminalBackend {
69
69
  listPromptPanes(): Promise<PromptPaneTarget[]>;
70
70
  /** 层② 定位:pane env → pane id;无定位能力的后端 null(回落标题+cwd,不猜)。 */
71
71
  locatePane(_env: Record<string, string>): Promise<string | null>;
72
+ /** 这个 pane id 是不是本后端发的(id 表示法归本后端);默认不是,不抢别人的 id。 */
73
+ ownsPaneId(_paneId: string): boolean;
72
74
  /** 会话 → 所在可见屏幕(会话列表分块);无枚举能力的后端空表(不分组,不猜)。 */
73
75
  locateScreens(_envs: Record<string, Record<string, string>>): Promise<Record<string, SessionTerminal | null>>;
74
76
  /** prompt 层② 兜底:向枚举所得 pane 注入 prompt 原文并提交;无通道的后端明确拒绝。 */
75
77
  sendPromptText(_paneId: string, _text: string): Promise<void>;
76
78
  /** 阻塞问答作答:裸键序注入(模态框只吃键盘,不吃粘贴文本);无通道的后端明确拒绝。 */
77
79
  sendKeys(_paneId: string, _keys: string): Promise<void>;
80
+ /** 关掉这个 pane(会话生命周期收尾 / 项目关终端共用);无通道的后端明确拒绝。 */
81
+ closePane(_paneId: string): Promise<void>;
78
82
  /** 按候选顺序起一个;全失败抛真相(含试过哪些命令)。 */
79
83
  protected spawnFirst(candidates: TerminalLaunch[], emptyReason: string): Promise<void>;
80
84
  }
85
+ /** wt 的 pane id ↔ 会话进程号;坏 id → null。 */
86
+ export declare function parseWtPaneId(id: string): number | null;
87
+ /**
88
+ * 上报的 pane env → wt 要打键的那个 pid;不是 wt 会话(缺世界标记或 pid)→ null。
89
+ * 纯函数:环境判定与取值一处写,投递路径只做存在性校验。
90
+ */
91
+ export declare function wtPanePidFromEnv(env: Record<string, string>): number | null;
92
+ /** PowerShell 脚本(base64/UTF-16,`-EncodedCommand` 免引号转义);纯函数,单测覆盖。 */
93
+ export declare function wtInjectEncodedScript(): string;
94
+ /** Konsole 的 pane id ↔ (D-Bus 服务名, 会话路径);坏 id → null。 */
95
+ export declare function parseKonsolePaneId(id: string): {
96
+ service: string;
97
+ session: string;
98
+ } | null;
99
+ /** 上报的 pane env → Konsole 的 pane id;不是 Konsole 会话(缺键)→ null。 */
100
+ export declare function konsolePaneFromEnv(env: Record<string, string>): string | null;
101
+ /** 字符 → Qt 键值:控制键给真值,其余用码位(ASCII 与 Qt::Key 一致)。 */
102
+ export declare function qtKeyOf(ch: string): number;
103
+ /** iTerm2 的 pane id ↔ 会话 unique id;坏 id → null。 */
104
+ export declare function parseItermPaneId(paneId: string): string | null;
105
+ /** 上报的 pane env → iTerm2 的 pane id;不是 iTerm 会话(缺键)→ null。 */
106
+ export declare function itermPaneFromEnv(env: Record<string, string>): string | null;
107
+ /** AppleScript 字符串字面量转义(反斜杠先转,免把引号转义再转一遍)。 */
108
+ export declare function applescriptString(text: string): string;
81
109
  /** settings → 后端(未知 preset 回落 auto,与旧的 switch default 一致)。 */
82
110
  export declare function terminalBackendFor(terminal: TerminalSettings, platform?: NodeJS.Platform): TerminalBackend;
83
111
  /**
84
- * prompt 层② 兜底通道适配(MessageDeliverer 的 PromptTerminal 形状):settings
85
- * 每次调用重新取后端(preset 运行期可改),`textAddressable` 即「层② 可用」的
86
- * 诚实声明——能力矩阵与投递裁决都经 available() 取用,不支持的 preset 不谎报。
112
+ * 上报的 pane env 属于哪个终端 preset——**每组键齐了才算认得**(缺键 = 不是那个
113
+ * 终端的会话)。表来自 core 的定位键表(preset 名不散写),故「会话活在哪个终端」
114
+ * 只有一个事实源。
115
+ */
116
+ export declare function locatorPresetOf(env: Record<string, string>): TerminalPreset | null;
117
+ /**
118
+ * prompt 层② 兜底通道适配(MessageDeliverer 的 PromptTerminal 形状)。
119
+ *
120
+ * 取后端分两处,因为「开窗」与「对话」是两个问题:
121
+ * - `settings.terminal` 答「weave 该往哪个终端开窗」——`listPanes`(标题+cwd
122
+ * 启发式回落的枚举面)用它,没有 env 的会话只在用户指明过的终端世界里猜;
123
+ * - 会话**自己上报的 pane env** 答「这个会话此刻在哪个终端里」——定位按它反查
124
+ * preset、击键按 **pane id 认领后端**。故换 preset 是纯开窗偏好,已开会话的
125
+ * 停止/作答照旧(唯一实现文本通道的 wezterm 也不是硬编码回落,而是 `ownsPaneId`
126
+ * 自然认领;将来别的终端实现这组方法即自动接入)。
87
127
  */
88
128
  export declare function promptTerminalChannel(settings: () => TerminalSettings): {
89
129
  available(): boolean;
@@ -92,6 +132,7 @@ export declare function promptTerminalChannel(settings: () => TerminalSettings):
92
132
  locateScreens(envs: Record<string, Record<string, string>>): Promise<Record<string, SessionTerminal | null>>;
93
133
  sendText(paneId: string, text: string): Promise<void>;
94
134
  sendKeys(paneId: string, keys: string): Promise<void>;
135
+ closePane(paneId: string): Promise<void>;
95
136
  };
96
137
  /**
97
138
  * Resolve the spawn candidates that would open a terminal at `dir`. 兼容入口:
@@ -135,15 +176,18 @@ export interface WeztermSplitTarget {
135
176
  export declare function parseWeztermPanes(jsonText: string | null): WeztermPaneInfo[];
136
177
  /** file:/// URL/本地路径 → 规范比较键:统一斜杠、去尾斜杠,win 下压大小写。 */
137
178
  export declare function normalizeDirKey(raw: string | null, platform: NodeJS.Platform): string | null;
138
- /** 跨 mux 摊平的 pane 行:计数只需 (mux 判别键, windowId, cwd)。 */
179
+ /** 跨 mux 摊平的 pane 行:计数只需 (mux 判别键, windowId, tabId, cwd)。 */
139
180
  export interface WeztermMuxPane {
140
181
  muxKey: string;
141
182
  windowId: number;
183
+ /** tab 号(可见屏幕);不给 = 该后端没有 tab 概念,按窗口计。 */
184
+ tabId?: number;
142
185
  cwd: string | null;
143
186
  }
144
187
  /**
145
- * 已打开终端窗口计数(窗口级口径:distinct (mux, windowId)、任一 pane cwd 命中
146
- * 即计——不是分屏 pane 数、也不是会话数)。同一窗口多个 pane 同属一目录只计 1。
188
+ * 已打开终端计数,单位 = 各后端的**可见屏幕**(与会话终端选择弹窗的选项同一
189
+ * 口径):distinct (mux, windowId, tabId)、任一 pane cwd 命中即计——不是分屏
190
+ * pane 数、也不是会话数。同一屏多个 pane 同属一目录只计 1。
147
191
  */
148
192
  export declare function countWindowsByDir(dirs: readonly string[], panes: readonly WeztermMuxPane[], platform?: NodeJS.Platform): Map<string, number>;
149
193
  /**
@@ -187,7 +231,11 @@ export interface AttachTarget {
187
231
  /** 这个可见屏幕已长满(pane 数到上限):前端置灰,后端定点附加明确拒绝。 */
188
232
  full: boolean;
189
233
  }
190
- /** mux socket → 不透明短标识(不回传本机路径)。 */
234
+ /**
235
+ * mux socket → 不透明短标识(不回传本机路径)。**按比较键取哈希**:同一 socket
236
+ * 有两种形态(wezterm 注进 pane env 的是混合分隔符,目录拼出来的是全反斜杠),
237
+ * 裸串哈希会给同一实例发两个 id,投递时按 id 反查就落空。
238
+ */
191
239
  export declare function weztermMuxKey(socket: string): string;
192
240
  /**
193
241
  * 层② 定位(纯函数):hook 上报的 pane env × 活 mux 表 → prompt pane id。
@@ -211,13 +259,20 @@ export interface SessionTerminal {
211
259
  tabsInWindow: number;
212
260
  }
213
261
  /**
214
- * 会话 → 可见屏幕(纯函数):hook 上报的 pane env × 活 mux 表。键缺、socket 对
215
- * 不上活 mux、pane 号已不在 = null(该会话不分组,不猜)。
262
+ * 会话 → 可见屏幕(纯函数):hook 上报的 pane env × 活 mux 表 × 这轮的候选清单。
263
+ * 三态各司其职——屏幕 = 反查到了;`null` = **确认不在了**(pane 已关 / 换了 mux /
264
+ * 整个 GUI 没了);**缺键 = 这轮没探到但实例还活着**(探活闸跳过、冷却、超时),
265
+ * web 据此保留上次分块。探活闸的冷却窗与偶发失败都会让 mux 短暂不在枚举表里,
266
+ * 把它们写成 null 就是「同一个终端的会话莫名掉出分块」的成因——分不清「没查」
267
+ * 与「查了没有」。
216
268
  */
217
269
  export declare function sessionScreensFromEnvs(envs: Record<string, Record<string, string>>, muxes: readonly {
218
270
  socket: string;
219
271
  panes: readonly WeztermPaneInfo[];
220
- }[], platform?: NodeJS.Platform): Record<string, SessionTerminal | null>;
272
+ }[],
273
+ /** 这轮认定还活着的 socket(`weztermSocketCandidates` 口径 = 枚举成功 ∪ 探活
274
+ * 失败/被闸跳过):不在枚举表里却在这里面 = 只是这轮没探到。 */
275
+ candidates: readonly string[], platform?: NodeJS.Platform): Record<string, SessionTerminal | null>;
221
276
  /** 目标 id ↔ (mux, window, tab) 解码;坏 id → null。 */
222
277
  export declare function parseAttachTargetId(id: string): {
223
278
  muxKey: string;
@@ -242,25 +297,28 @@ export declare function attachTargetsFromMuxes(dir: string, muxes: readonly {
242
297
  export declare function listAttachTargets(dir: string, platform?: NodeJS.Platform): Promise<AttachTarget[]>;
243
298
  /** list-clients JSON → 最近活跃(idle 最小)client 的 workspace;坏输入 null。 */
244
299
  export declare function weztermActiveWorkspaceOf(jsonText: string | null): string | null;
300
+ /** cli 子命令参数 → 补上 `--no-auto-start`(须落在 `cli` 与子命令之间)。 */
301
+ export declare function weztermCliArgs(args: readonly string[]): string[];
245
302
  /**
246
303
  * 候选 mux socket:进程 env 显式指定的最优先(daemon 一般没有,pane 内才有),
247
304
  * 其次存活 GUI 的 gui-sock-*(新的在前 ≈ 最近开的 wezterm 实例)。
248
- * 跳过裸 `sock`:指向死 mux-server 时 cli 会原地拉起一个无人看的幽灵 server
249
- * 还 rc=0 返回空世界,会造成新一轮假成功。
305
+ * 跳过裸 `sock`:默认 socket 不按 GUI pid 命名、判活无据——历史教训是 cli 对它
306
+ * 原地拉起幽灵 server 后 rc=0 返回空世界、假成功一轮接一轮(见 DECISIONS);
307
+ * wezterm 注进 pane env 的恒是 gui-sock-<pid>,跳过它不丢发现面。
250
308
  */
251
309
  export declare function weztermSocketCandidates(platform: NodeJS.Platform): string[];
252
310
  /**
253
311
  * 探活失败的 socket 记忆——避免对已知坏 socket 反复 spawn `wezterm cli`。
254
312
  *
255
313
  * 为什么需要:陈旧的 `gui-sock-<pid>` 不会自己消失(wezterm 退出不清理,实测
256
- * 攒到过 48 个),而对着死 socket 跑 `wezterm cli` 会**原地拉起幽灵 mux-server,
257
- * 甚至挂死**——实测一次探活 >250s 不返回,且代码里 5s 超时后的 kill「对卡死
258
- * 进程可能无效」,于是每次枚举都再堆一个。
314
+ * 攒到过 48 个),对它们反复 spawn 纯属浪费(`--no-auto-start` 后死 socket
315
+ * 是快速 rc≠0,不再是当年「原地拉起幽灵 mux-server、探活 >250s 不返回」的
316
+ * 自伤——复盘见 docs/DECISIONS.md)。
259
317
  *
260
318
  * 判据的分寸:socket 路径与 GUI 的 pid 绑定,**进程死则该路径永久失效**(新 GUI
261
- * 必然是新 pid → 新路径),所以「干净的非零退出」可以永久记住;而**超时/起不来
262
- * 只算可疑**(本机 GUI 常年在 4~6 核,5s 内答不上来是可能的),只短期回避,
263
- * 免得把活着的 GUI 误判死。
319
+ * 必然是新 pid → 新路径),所以「干净的非零退出 + 这个 GUI 进程真没了」可以永久
320
+ * 记住;而**超时/起不来/进程还活着却答不上来只算可疑**(本机 GUI 常年在 4~6 核,
321
+ * 5s 内答不上来是可能的),只短期回避,免得把活着的 GUI 误判死。
264
322
  */
265
323
  export declare class SocketProbeGate {
266
324
  private readonly dead;
@@ -289,6 +347,27 @@ export declare function runInWeztermAt(dir: string, argv: string[], targetId: st
289
347
  * 一律 0(角标不显示,不谎报)。
290
348
  */
291
349
  export declare function countOpenTerminals(dirs: string[], terminal: TerminalSettings): Promise<Map<string, number>>;
350
+ /**
351
+ * cwd **恰为** `dir` 的 pane = 这个项目的终端(关终端的命中判据,与
352
+ * `countWindowsByDir` 同一条:精确相等、不含子目录)。关错一个就是杀掉用户
353
+ * 顺手开着的别的活,故判据单点在此。
354
+ */
355
+ export declare function panesAtDir(panes: readonly PromptPaneTarget[], dir: string, platform?: NodeJS.Platform): PromptPaneTarget[];
356
+ /**
357
+ * `dir` 名下可关的 pane(项目关终端多选弹窗的数据面):`panesAtDir` 命中的那些。
358
+ *
359
+ * 枚举不到 pane 而计数说有 = 这个后端有窗口却关不了(wt 只数不关)——如实抛,
360
+ * 不返回空表让弹窗装作「没有终端」。
361
+ */
362
+ export declare function listProjectPanes(dir: string, terminal: TerminalSettings, platform?: NodeJS.Platform): Promise<PromptPaneTarget[]>;
363
+ /**
364
+ * 关掉 `dir` 的已开终端(项目卡「关闭终端」):只关清单里的那些 pane——清单来自
365
+ * 用户在弹窗里的多选,**不提供「一口气全关」**(那是这次要去掉的误触面)。
366
+ * 窗口里别的 cwd 的 pane 不动(不替用户关掉顺手开着的别的活),只剩它一个时整窗
367
+ * 随 pane 一起没。返回关掉的 pane 数;清单里的 pane 一个都没命中 = 目标已经没了,
368
+ * 如实返回 0。
369
+ */
370
+ export declare function closeTerminalsIn(dir: string, terminal: TerminalSettings, paneIds: readonly string[], platform?: NodeJS.Platform): Promise<number>;
292
371
  /**
293
372
  * 每项目窗口数(projectId → 窗口数):/terminals/counts 路由与隐藏刷新器共用
294
373
  * 同一口径,免得两处各自拼 settings/opener 后漂移。
@@ -376,6 +455,10 @@ export interface ProjectOpener {
376
455
  runInTerminal(dir: string, argv: string[], terminal: TerminalSettings): Promise<void>;
377
456
  /** 已打开终端窗口计数(可选:不实现的 spy 由路由回落到默认实现)。 */
378
457
  countTerminals?(dirs: string[], terminal: TerminalSettings): Promise<Map<string, number>>;
458
+ /** 关掉本目录的已开终端(可选):只关清单里的 pane,回关掉几个。 */
459
+ closeTerminals?(dir: string, terminal: TerminalSettings, paneIds: readonly string[]): Promise<number>;
460
+ /** 本目录名下可关的 pane(可选):关终端多选弹窗的数据面。 */
461
+ listPanes?(dir: string, terminal: TerminalSettings): Promise<PromptPaneTarget[]>;
379
462
  /** 可附加终端目标列表(可选):多终端选择弹窗的数据面。 */
380
463
  listTerminals?(dir: string, terminal: TerminalSettings): Promise<AttachTarget[]>;
381
464
  /** 定点附加到指定目标 tab(可选):会话终端选择后的落点。 */
@@ -1,7 +1,97 @@
1
- import{spawn as M}from"node:child_process";import{createHash as N}from"node:crypto";import{readdirSync as V}from"node:fs";import{basename as b,join as E}from"node:path";import{TERMINAL_LOCATOR_ENV as S}from"@weavecode/core";import{readDaemonSettings as q}from"./settings.js";export function quotePath(n,t){return t==="win32"?`"${n}"`:`'${n.replace(/'/g,"'\\''")}'`}function J(n,t){return t==="win32"?n!==""&&!/[\s"&|<>^%]/.test(n)?n:`"${n.replace(/"/g,'\\"')}"`:/^[A-Za-z0-9_@%+=:,./-]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}function f(n,t){return n.map(e=>J(e,t)).join(" ")}function v(n,t){return!t||!n||n.length===0?n:["cmd.exe","/k",f(n,"win32")]}function z(n,t,e){const r=`cd ${quotePath(t,"darwin")} && ${f(e,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return n==="Terminal"?["-e",`tell application "Terminal" to do script "${r}"`,"-e",'tell application "Terminal" to activate']:["-e",'tell application "iTerm" to create window with default profile',"-e",`tell application "iTerm" to tell current window to write text "${r}"`]}export function parsePromptPaneId(n){const t=/^([0-9a-f]{8}):(\d+)$/.exec(n);return t?{muxKey:t[1],paneId:Number(t[2])}:null}export class TerminalBackend{preset;enumerable;platform;textAddressable;constructor(t,e,r=process.platform,o=!1){this.preset=t,this.enumerable=e,this.platform=r,this.textAddressable=o}async open(t){await this.spawnFirst(this.candidates(t),`Terminal preset "${this.preset}" is unavailable on this platform`)}async run(t,e){await this.spawnFirst(this.candidates(t,e),`Terminal preset "${this.preset}" cannot run a command here \u2014 pick another preset in settings`)}async countWindows(t){return new Map}async listTargets(t){return[]}async runAt(t,e,r){throw new Error(`Terminal preset "${this.preset}" cannot attach to a chosen pane \u2014 pick wezterm, wt or Terminal.app in settings`)}async listPromptPanes(){return[]}async locatePane(t){return null}async locateScreens(t){return{}}async sendPromptText(t,e){throw new Error(`Terminal preset "${this.preset}" cannot send text into an open pane \u2014 pick wezterm in settings`)}async sendKeys(t,e){throw new Error(`Terminal preset "${this.preset}" cannot send keys to an open pane \u2014 pick wezterm in settings`)}async spawnFirst(t,e){for(const r of t)if(await O(r))return;throw new Error(t.length===0?e:"No usable terminal found (tried: "+t.map(r=>r.command).join(", ")+")")}}class I extends TerminalBackend{make;constructor(t,e,r){super(t,!1,e),this.make=r}candidates(t,e){return this.make(t,e,this.platform)}}const w={wt:(n,t,e)=>e==="win32"?[{command:"wt.exe",args:["-w",wtWindowSlug(n),"-d",n,...v(t,!0)??[]]}]:[],powershell:(n,t,e)=>e==="win32"?[t?{command:"powershell.exe",args:["-NoExit","-Command",f(t,"win32")],cwd:n}:{command:"powershell.exe",args:["-NoExit"],cwd:n}]:[],cmd:(n,t,e)=>e==="win32"?[t?{command:"cmd.exe",args:["/K",f(t,"win32")],cwd:n}:{command:"cmd.exe",args:["/K"],cwd:n}]:[],terminal:(n,t,e)=>e!=="darwin"?[]:t?[{command:"osascript",args:z("Terminal",n,t)}]:[{command:"open",args:["-a","Terminal",n]}],iterm:(n,t,e)=>e!=="darwin"?[]:t?[{command:"osascript",args:z("iTerm",n,t)}]:[{command:"open",args:["-a","iTerm",n]}],gnome:(n,t)=>[{command:"gnome-terminal",args:[`--working-directory=${n}`,...t?["--",...t]:[]]}],konsole:(n,t)=>[{command:"konsole",args:["--workdir",n,...t?["-e",...t]:[]]}],ghostty:(n,t,e)=>e==="win32"?[]:e==="darwin"?t?[]:[{command:"open",args:["-a","Ghostty",n]}]:[{command:"ghostty",args:[`--working-directory=${n}`,...t?["-e",...t]:[]]}]};class Q extends TerminalBackend{terminal;constructor(t,e){super("custom",!1,e),this.terminal=t}candidates(t,e){const r=this.terminal.customCommand.trim();if(!r)return[];let o=r.replace(/\{path\}/g,quotePath(t,this.platform));const a=e?f(e,this.platform):"";return o=o.includes("{command}")?o.replace(/\{command\}/g,a):e?`${o} ${a}`:o,[{command:o,args:[],shell:!0}]}}class Y extends TerminalBackend{constructor(t){super("ghostty",!1,t)}candidates(t,e){return w.ghostty(t,e,this.platform)}async openViaIpcThenStandalone(t,e){if(this.platform==="linux"){const r=["+new-window",`--working-directory=${t}`,...e.length>0?["-e",...e]:[]];if((await h("ghostty",r))?.ok)return}await this.spawnFirst(this.candidates(t,e.length>0?e:void 0),`Terminal preset "${this.preset}" is unavailable on this platform`)}open(t){return this.openViaIpcThenStandalone(t,[])}run(t,e){return this.openViaIpcThenStandalone(t,e)}}class A extends TerminalBackend{constructor(t){super("wt",t==="win32",t)}candidates(t,e){return w.wt(t,e,this.platform)}async countWindows(t){if(t.length===0||this.platform!=="win32")return new Map(t.map(r=>[r,0]));const e=await H();return e.length===0?new Map(t.map(r=>[r,0])):countWindowsByDir(t,G(e))}async listTargets(t){if(this.platform!=="win32")return[];const e=await H(),r=countWindowsByDir([t],G(e)).get(t)??0;return r===0?[]:[{id:`wt:${wtWindowSlug(t)}`,windowId:0,tabId:0,title:b(t),matchCount:r,paneCount:r,active:!1,full:!1}]}async runAt(t,e,r){if(this.platform!=="win32")throw new Error(`Terminal preset "${this.preset}" is unavailable on this platform`);if(!parseWtTargetId(r))throw new Error(`Invalid terminal target "${r}"`);await this.spawnFirst([{command:"wt.exe",args:["-w",wtWindowSlug(t),"split-pane","-d",t,...v(e,!0)??[]]}],`Terminal preset "${this.preset}" is unavailable on this platform`)}}class C extends TerminalBackend{constructor(t){super("terminal",t==="darwin",t)}candidates(t,e){return w.terminal(t,e,this.platform)}async run(t,e){if(this.platform==="darwin"){const r=await listTerminalAppSurfaces(this.platform),o=pickTerminalAppWindow(r,t,this.platform);if(o&&await L(t,e,o.windowId))return}await this.spawnFirst(this.candidates(t,e),`Terminal preset "${this.preset}" is unavailable on this platform`)}async countWindows(t){if(t.length===0||this.platform!=="darwin")return new Map(t.map(r=>[r,0]));const e=await ct(this.platform);return e.length===0?new Map(t.map(r=>[r,0])):countWindowsByDir(t,e.flatMap(r=>r.cwd?[{muxKey:"terminal.app",windowId:r.windowId,cwd:r.cwd}]:[]))}listTargets(t){return dt(t,this.platform)}async runAt(t,e,r){const o=parseTerminalAppTargetId(r);if(!o)throw new Error(`Invalid terminal target "${r}"`);if(!await L(t,e,o.windowId))throw new Error("Terminal window is gone \u2014 pick a terminal again")}}class _ extends TerminalBackend{constructor(t){super("wezterm",!0,t,!0)}candidates(t,e){return[{command:"wezterm",args:["start","--cwd",t,...v(e,this.platform==="win32")??[]]}]}async open(t){await at(t)||await super.open(t)}async run(t,e){await st(t,e)}async countWindows(t){if(t.length===0)return new Map;const e=await U();return e.length===0?new Map(t.map(r=>[r,0])):countWindowsByDir(t,e.flatMap(r=>r.panes.map(o=>({muxKey:r.socket,windowId:o.windowId,cwd:o.cwd}))))}listTargets(t){return listAttachTargets(t,this.platform)}runAt(t,e,r){return runInWeztermAt(t,e,r,this.platform)}async listPromptPanes(){const{muxes:t}=await m();return t.flatMap(e=>e.panes.map(r=>({id:`${weztermMuxKey(e.socket)}:${r.paneId}`,title:r.title,cwd:r.cwd})))}async locatePane(t){const{muxes:e}=await m();return weztermPaneFromEnv(t,e,this.platform)}async locateScreens(t){return Object.keys(t).length===0?{}:sessionScreensFromEnvs(t,await U(),this.platform)}async sendPromptText(t,e){const r=parsePromptPaneId(t);if(!r)throw new Error(`Invalid prompt pane "${t}"`);const{muxes:o}=await m(),a=o.find(c=>weztermMuxKey(c.socket)===r.muxKey);if(!a)throw new Error("wezterm instance is gone \u2014 cannot deliver prompt");const s=String(r.paneId);if(e){const c=await g(["cli","send-text","--pane-id",s,e],a.socket);if(!c?.ok)throw new Error(y(["cli","send-text","--pane-id",s,"<prompt text>"],a.socket,c))}const i=await g(["cli","send-text","--pane-id",s,"--no-paste","\r"],a.socket);if(!i?.ok)throw new Error(y(["cli","send-text","--pane-id",s,"--no-paste","<CR>"],a.socket,i))}async sendKeys(t,e){const r=parsePromptPaneId(t);if(!r)throw new Error(`Invalid prompt pane "${t}"`);const{muxes:o}=await m(),a=o.find(c=>weztermMuxKey(c.socket)===r.muxKey);if(!a)throw new Error("wezterm instance is gone \u2014 cannot send keys to the pane");const s=String(r.paneId),i=await g(["cli","send-text","--pane-id",s,"--no-paste",e],a.socket);if(!i?.ok)throw new Error(y(["cli","send-text","--pane-id",s,"--no-paste","<keys>"],a.socket,i))}}class tt extends TerminalBackend{parts;constructor(t){super("auto",!0,t,t!=="win32"&&t!=="darwin");const e={win32:["wt","powershell","cmd"],darwin:["terminal","iterm"]}[t]??["gnome","konsole"];this.parts=e.map(r=>new I(r,t,w[r]))}candidates(t,e){return this.parts.flatMap(r=>e&&r.preset==="iterm"?[]:r.candidates(t,e))}attachBackend(){return this.platform==="darwin"?new C(this.platform):this.platform==="win32"?new A(this.platform):new _(this.platform)}countWindows(t){return this.attachBackend().countWindows(t)}listTargets(t){return this.attachBackend().listTargets(t)}runAt(t,e,r){return this.attachBackend().runAt(t,e,r)}listPromptPanes(){return this.attachBackend().listPromptPanes()}locatePane(t){return this.attachBackend().locatePane(t)}locateScreens(t){return this.attachBackend().locateScreens(t)}sendPromptText(t,e){return this.attachBackend().sendPromptText(t,e)}sendKeys(t,e){return this.attachBackend().sendKeys(t,e)}}const W={auto:(n,t)=>new tt(t),wt:(n,t)=>new A(t),powershell:(n,t)=>new I("powershell",t,w.powershell),cmd:(n,t)=>new I("cmd",t,w.cmd),terminal:(n,t)=>new C(t),iterm:(n,t)=>new I("iterm",t,w.iterm),gnome:(n,t)=>new I("gnome",t,w.gnome),konsole:(n,t)=>new I("konsole",t,w.konsole),ghostty:(n,t)=>new Y(t),wezterm:(n,t)=>new _(t),custom:(n,t)=>new Q(n,t)};export function terminalBackendFor(n,t=process.platform){return(W[n.preset]??W.auto)(n,t)}export function promptTerminalChannel(n){const t=()=>terminalBackendFor(n());return{available:()=>t().textAddressable,listPanes:async()=>{const e=t();return e.textAddressable?await e.listPromptPanes():[]},locatePane:async e=>{const r=t();return r.textAddressable?await r.locatePane(e):null},locateScreens:async e=>{const r=t();return r.textAddressable?await r.locateScreens(e):{}},sendText:async(e,r)=>{const o=t();if(!o.textAddressable)throw new Error(`Terminal preset "${o.preset}" cannot send text into an open pane \u2014 pick wezterm in settings`);await o.sendPromptText(e,r)},sendKeys:async(e,r)=>{const o=t();if(!o.textAddressable)throw new Error(`Terminal preset "${o.preset}" cannot send keys to an open pane \u2014 pick wezterm in settings`);await o.sendKeys(e,r)}}}export function resolveTerminalLaunch(n,t,e=process.platform,r){return terminalBackendFor(t,e).candidates(n,r)}export function resolveExplorerLaunch(n,t=process.platform){return t==="win32"?{command:"explorer.exe",args:[n]}:t==="darwin"?{command:"open",args:[n]}:{command:"xdg-open",args:[n]}}function O(n){return new Promise(t=>{let e;try{e=M(n.command,n.args,{cwd:n.cwd,shell:n.shell,detached:!0,stdio:"ignore"})}catch{t(!1);return}e.on("error",()=>t(!1)),e.on("spawn",()=>{e.unref(),t(!0)})})}export async function openInExplorer(n){const t=resolveExplorerLaunch(n);if(!await O(t))throw new Error(`Failed to open file manager (${t.command})`)}export async function openInTerminal(n,t){await terminalBackendFor(t).open(n)}export async function runInTerminal(n,t,e){await terminalBackendFor(e).run(n,t)}export function parseWeztermPanes(n){if(!n)return[];let t;try{t=JSON.parse(n)}catch{return[]}if(!Array.isArray(t))return[];const e=[];for(const r of t){const o=r;typeof o?.pane_id!="number"||typeof o?.tab_id!="number"||e.push({windowId:typeof o.window_id=="number"?o.window_id:0,tabId:o.tab_id,paneId:o.pane_id,cwd:typeof o.cwd=="string"?o.cwd:null,left:typeof o.left_col=="number"?o.left_col:0,top:typeof o.top_row=="number"?o.top_row:0,isActive:o.is_active===!0,title:typeof o.title=="string"&&o.title?o.title:null})}return e}export function normalizeDirKey(n,t){if(!n)return null;let e=n;if(e.startsWith("file://")){e=e.slice(7);try{e=decodeURIComponent(e)}catch{return null}t==="win32"&&(e=e.replace(/^\//,""))}return e=e.replace(/\\/g,"/").replace(/\/+$/,""),e?t==="win32"?e.toLowerCase():e:null}export function countWindowsByDir(n,t,e=process.platform){const r=n.map(a=>normalizeDirKey(a,e)),o=n.map(()=>new Set);for(const a of t){const s=normalizeDirKey(a.cwd,e);if(s)for(let i=0;i<n.length;i++)r[i]!==null&&r[i]===s&&o[i].add(`${a.muxKey}#${a.windowId}`)}return new Map(n.map((a,s)=>[a,o[s].size]))}export const MAX_PANES_PER_SCREEN=6;function et(n,t,e){const r=new Map,o=new Map;for(const i of t)o.set(i.tabId,(o.get(i.tabId)??0)+1),normalizeDirKey(i.cwd,e)===n&&r.set(i.tabId,(r.get(i.tabId)??0)+1);let a=null,s=0;for(const[i,c]of r)(o.get(i)??0)>=MAX_PANES_PER_SCREEN||(a===null||c>s||c===s&&i<a)&&(a=i,s=c);return a}export function planWeztermGrid(n){if(n.length===0||n.length>=MAX_PANES_PER_SCREEN)return null;if(n.length===1)return{paneId:n[0].paneId,direction:"right"};const t=new Map;for(const o of n){const a=t.get(o.left)??[];a.push(o),t.set(o.left,a)}const e=[...t.entries()].sort(([o],[a])=>o-a).map(([,o])=>[...o].sort((a,s)=>s.top-a.top));if(e.length===1)return{paneId:e[0][0].paneId,direction:"right"};let r=e[0];for(const o of e)o.length<r.length&&(r=o);return{paneId:r[0].paneId,direction:"bottom"}}export function planWeztermReuse(n,t,e=process.platform){const r=normalizeDirKey(n,e);if(!r)return null;const o=et(r,t,e);return o===null?null:planWeztermGrid(t.filter(a=>a.tabId===o))}export function planWeztermNewWindow(n,t){const e=["cli","spawn","--new-window","--cwd",n];return t&&e.push("--workspace",t),e}export function weztermMuxKey(n){return N("sha256").update(n).digest("hex").slice(0,8)}export function weztermPaneFromEnv(n,t,e){const[r,o]=S.wezterm,a=n[r],s=n[o];if(!a||!s)return null;const i=normalizeDirKey(s,e),c=t.find(l=>normalizeDirKey(l.socket,e)===i);return!c||!c.panes.some(l=>String(l.paneId)===a)?null:`${weztermMuxKey(c.socket)}:${a}`}export function sessionScreensFromEnvs(n,t,e=process.platform){const[r,o]=S.wezterm,a={};for(const[s,i]of Object.entries(n)){const c=i[r],l=i[o],p=l?t.find(u=>normalizeDirKey(u.socket,e)===normalizeDirKey(l,e)):void 0,d=p?.panes.find(u=>String(u.paneId)===c);if(!p||!d){a[s]=null;continue}a[s]={id:`${weztermMuxKey(p.socket)}:${d.windowId}:${d.tabId}`,windowId:d.windowId,tabId:d.tabId,tabsInWindow:new Set(p.panes.filter(u=>u.windowId===d.windowId).map(u=>u.tabId)).size}}return a}export function parseAttachTargetId(n){const t=/^([0-9a-f]{8}):(\d+):(\d+)$/.exec(n);return t?{muxKey:t[1],windowId:Number(t[2]),tabId:Number(t[3])}:null}export function attachTargetsFromMuxes(n,t,e=process.platform){const r=normalizeDirKey(n,e);if(!r)return[];const o=[];for(const a of[...t].sort((s,i)=>s.idleMs-i.idleMs)){const s=new Map;for(const c of a.panes){const l=`${c.windowId}:${c.tabId}`,p=s.get(l)??[];p.push(c),s.set(l,p)}const i=[];for(const[c,l]of s){const p=l.filter(x=>normalizeDirKey(x.cwd,e)===r).length;if(p===0)continue;const d=Number(c.slice(0,c.indexOf(":"))),u=Number(c.slice(c.indexOf(":")+1)),X=l.find(x=>x.isActive)??l[0];i.push({id:`${weztermMuxKey(a.socket)}:${d}:${u}`,windowId:d,tabId:u,title:X.title,matchCount:p,paneCount:l.length,active:l.some(x=>x.isActive),full:l.length>=MAX_PANES_PER_SCREEN})}i.sort((c,l)=>Number(l.active)-Number(c.active)||l.tabId-c.tabId),o.push(...i)}return o}export async function listAttachTargets(n,t=process.platform){const{muxes:e}=await m();return attachTargetsFromMuxes(n,e,t)}function R(n){if(!n)return null;let t;try{t=JSON.parse(n)}catch{return null}if(!Array.isArray(t))return null;let e=null;for(const r of t){const o=r;if(typeof o?.workspace!="string"||!o.workspace)continue;const a=o.idle_time,s=(typeof a?.secs=="number"?a.secs*1e3:0)+(typeof a?.nanos=="number"?a.nanos/1e6:0);(e===null||s<e.idleMs)&&(e={workspace:o.workspace,idleMs:s})}return e}export function weztermActiveWorkspaceOf(n){return R(n)?.workspace??null}const D=5e3;function h(n,t,e,r=D){return new Promise(o=>{let a;try{a=M(n,t,{windowsHide:!0,env:e??process.env})}catch{o(null);return}let s="",i="",c=!1;const l=d=>{c||(c=!0,clearTimeout(p),o(d))};a.stdout.on("data",d=>{s+=d.toString()}),a.stderr?.on("data",d=>{i+=d.toString()});const p=setTimeout(()=>{a.stdout.destroy(),a.stderr?.destroy(),a.unref(),a.kill(),l({ok:!1,out:s,err:i.trim(),timedOut:!0})},r);p.unref(),a.on("error",()=>l(null)),a.on("close",d=>{l({ok:d===0,out:s,err:i.trim(),timedOut:!1})})})}function g(n,t){return h("wezterm",n,{...process.env,WEZTERM_UNIX_SOCKET:t})}function y(n,t,e){const r=`wezterm[${b(t)}] ${n.join(" ")}`;return e===null?`${r}: executable not found`:e.timedOut?`${r}: timed out after ${D}ms`:e.err?`${r}: ${e.err}`:`${r}: exited with failure`}function nt(n){try{return process.kill(n,0),!0}catch{return!1}}function K(n){let t;try{t=V(n)}catch{return[]}const e=[];for(const r of t){const o=/^gui-sock-(\d+)$/.exec(r);if(!o)continue;const a=Number(o[1]);nt(a)&&e.push({path:E(n,r),pid:a})}return e.sort((r,o)=>o.pid-r.pid).map(r=>r.path)}function rt(n,t){const e=n.replace(/\\/g,"/");return t==="win32"?e.toLowerCase():e}export function weztermSocketCandidates(n){const t=[],e=new Set,r=a=>{const s=rt(a,n);e.has(s)||(e.add(s),t.push(a))};process.env.WEZTERM_UNIX_SOCKET&&r(process.env.WEZTERM_UNIX_SOCKET);const o=n==="win32"?process.env.USERPROFILE:process.env.HOME;return o&&K(E(o,".local","share","wezterm")).forEach(r),n!=="win32"&&process.env.XDG_RUNTIME_DIR&&K(E(process.env.XDG_RUNTIME_DIR,"wezterm")).forEach(r),t}const ot=6e4;export class SocketProbeGate{dead=new Set;cooling=new Map;shouldProbe(t,e=Date.now()){if(this.dead.has(t))return!1;const r=this.cooling.get(t);return r===void 0||e>=r}succeeded(t){this.cooling.delete(t)}failed(t){this.dead.add(t),this.cooling.delete(t)}cooledDown(t,e=Date.now()){this.dead.has(t)||this.cooling.set(t,e+ot)}}const P=new SocketProbeGate;async function m(n=!1){const t=weztermSocketCandidates(process.platform);return{muxes:(await Promise.all(t.map(async e=>{if(!P.shouldProbe(e))return null;const r=await g(["cli","list","--format","json"],e);if(!r?.ok)return r&&!r.timedOut?P.failed(e):P.cooledDown(e),null;P.succeeded(e);const o=parseWeztermPanes(r.out);if(n)return{socket:e,panes:o,workspace:null,idleMs:Number.POSITIVE_INFINITY};const a=await g(["cli","list-clients","--format","json"],e),s=R(a?.ok?a.out:null);return{socket:e,panes:o,workspace:s?.workspace??null,idleMs:s?.idleMs??Number.POSITIVE_INFINITY}}))).filter(e=>e!==null),candidates:t}}async function at(n){const{muxes:t}=await m();if(t.length===0)return!1;const e=t.reduce((r,o)=>o.idleMs<r.idleMs?o:r);return await B(e.socket,n,null,e.workspace),!0}async function st(n,t){const e=process.platform,{muxes:r,candidates:o}=await m();if(r.length===0)throw new Error(o.length===0?`wezterm mux undiscoverable: ${process.env.WEZTERM_UNIX_SOCKET?"WEZTERM_UNIX_SOCKET set but dead":"WEZTERM_UNIX_SOCKET unset"} and no living gui-sock under socket dirs (USERPROFILE=${process.env.USERPROFILE??"?"} HOME=${process.env.HOME??"?"}) \u2014 is wezterm running?`:`wezterm mux sockets all unreachable: ${o.map(i=>b(i)).join(", ")} \u2014 wezterm may be wedged, restart it`);let a=null,s=null;for(const i of r){const c=planWeztermReuse(n,i.panes,e);c&&(a===null||i.idleMs<a.idleMs)&&(a=i,s=c)}a??=r.reduce((i,c)=>c.idleMs<i.idleMs?c:i),await F(a.socket,n,t,s,a.workspace)}async function B(n,t,e,r){const o=e?["cli","split-pane","--pane-id",String(e.paneId),`--${e.direction}`,"--cwd",t]:planWeztermNewWindow(t,r),a=await g(o,n);if(!a?.ok)throw new Error(y(o,n,a));const s=a.out.trim();if(!/^\d+$/.test(s))throw new Error(`wezterm[${b(n)}] ${o.join(" ")}: unexpected pane id "${s}"`);return s}async function F(n,t,e,r,o,a=process.platform){const s=["cli","send-text","--pane-id",await B(n,t,r,o),"--no-paste",`${f(e,a)}\r`],i=await g(s,n);if(!i?.ok)throw new Error(y(s,n,i))}export async function runInWeztermAt(n,t,e,r=process.platform){const o=parseAttachTargetId(e);if(!o)throw new Error(`Invalid terminal target "${e}"`);const{muxes:a}=await m(),s=a.find(c=>weztermMuxKey(c.socket)===o.muxKey);if(!s)throw new Error("wezterm instance is gone \u2014 pick a terminal again");const i=s.panes.filter(c=>c.windowId===o.windowId&&c.tabId===o.tabId);if(i.length===0)throw new Error("terminal tab is gone \u2014 pick a terminal again");if(i.length>=MAX_PANES_PER_SCREEN)throw new Error(`terminal is full (${MAX_PANES_PER_SCREEN} panes) \u2014 pick another terminal or open a new one`);await F(s.socket,n,t,planWeztermGrid(i),s.workspace,r)}export async function countOpenTerminals(n,t){return terminalBackendFor(t).countWindows(n)}export async function readTerminalCounts(n,t=defaultProjectOpener){const e=await q(),r=await(t.countTerminals??countOpenTerminals)(n.map(o=>o.path),e.terminal);return Object.fromEntries(n.map(o=>[o.id,r.get(o.path)??0]))}let k=null;async function U(){if(k&&Date.now()-k.at<1e4)return k.muxes;const{muxes:n}=await m(!0);return k={at:Date.now(),muxes:n},n}const it=['if application "Terminal" is not running then return ""','tell application "Terminal"',' set out to ""'," repeat with w in windows"," set wid to id of w"," set fm to frontmost of w as text"," repeat with t in tabs of w",' set out to out & wid & "\\t" & (index of t) & "\\t" & tty of t & "\\t" & (selected of t as text) & "\\t" & fm & linefeed'," end repeat"," end repeat"," return out","end tell"].join(`
2
- `);export function parseTerminalAppDump(n){const t=[];for(const e of n.split(`
3
- `)){const r=e.trim().split(" ");if(r.length!==5)continue;const o=Number(r[0]),a=Number(r[1]);!Number.isInteger(o)||!Number.isInteger(a)||t.push({windowId:o,tabIndex:a,tty:r[2],selected:r[3]==="true",frontmost:r[4]==="true"})}return t}export function parsePsRootPids(n){const t=new Map,e=new Map;for(const o of n.split(`
4
- `)){const a=/^\s*(\d+)\s+(\d+)\s+(\S+)/.exec(o);if(!a)continue;const s=Number(a[1]),i=a[3];if(i==="??")continue;const c=t.get(i)??new Set;c.add(s),t.set(i,c),e.set(s,Number(a[2]))}const r=new Map;for(const[o,a]of t)for(const s of a)if(!a.has(e.get(s)??-1)){r.set(o,s);break}return r}export function parseLsofCwds(n){const t=new Map;let e=-1;for(const r of n.split(`
5
- `))r.startsWith("p")&&/^\d+$/.test(r.slice(1))?e=Number(r.slice(1)):r.startsWith("n")&&e!==-1&&(t.set(e,r.slice(1)),e=-1);return t}export async function listTerminalAppSurfaces(n){if(n!=="darwin")return[];const t=await h("osascript",["-e",it]);if(!t?.ok)return[];const e=parseTerminalAppDump(t.out);if(e.length===0)return[];const r=await h("ps",["-axo","pid=,ppid=,tty="]);if(!r?.ok)return e.map(c=>({...c,cwd:null}));const o=parsePsRootPids(r.out),a=[...new Set(e.map(c=>o.get(c.tty.replace(/^\/dev\//,""))??-1))].filter(c=>c!==-1),s=a.length>0?await h("lsof",["-a","-p",a.join(","),"-d","cwd","-Fn"]):null,i=parseLsofCwds(s?.out??"");return e.map(c=>({...c,cwd:i.get(o.get(c.tty.replace(/^\/dev\//,""))??-1)??null}))}let $=null;async function ct(n){if($&&Date.now()-$.at<1e4)return $.surfaces;const t=await listTerminalAppSurfaces(n);return $={at:Date.now(),surfaces:t},t}function lt(n,t){return`terminal:${n}:${t}`}export function parseTerminalAppTargetId(n){const t=/^terminal:(\d+):(\d+)$/.exec(n);return t?{windowId:Number(t[1]),tabIndex:Number(t[2])}:null}function j(n,t,e){const r=normalizeDirKey(t,e);return r?n.filter(o=>o.cwd!==null&&normalizeDirKey(o.cwd,e)===r):[]}export function terminalAppTargets(n,t,e=process.platform){const r=j(t,n,e);return r.sort((o,a)=>Number(a.frontmost)-Number(o.frontmost)||Number(a.selected)-Number(o.selected)||a.tabIndex-o.tabIndex),r.map(o=>({id:lt(o.windowId,o.tabIndex),windowId:o.windowId,tabId:o.tabIndex,title:null,matchCount:1,paneCount:1,active:o.frontmost&&o.selected,full:!1}))}export function pickTerminalAppWindow(n,t,e=process.platform){const r=j(n,t,e);return r.length===0?null:(r.sort((o,a)=>Number(a.frontmost)-Number(o.frontmost)||a.windowId-o.windowId),{windowId:r[0].windowId,tabIndex:r[0].tabIndex})}async function dt(n,t){return terminalAppTargets(n,await listTerminalAppSurfaces(t),t)}async function L(n,t,e){const r=`cd ${quotePath(n,"darwin")} && ${f(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return(await h("osascript",["-e",`tell application "Terminal" to do script "${r}" in window id ${e}`]))?.ok===!0}const pt=["$ErrorActionPreference = 'SilentlyContinue'","$src = @'","using System; using System.Runtime.InteropServices;","public class WeaveWtCwd {",' [DllImport("ntdll.dll")] static extern int NtQueryInformationProcess(IntPtr h, int c, ref PBI pbi, int size, out int rl);',' [DllImport("kernel32.dll")] static extern IntPtr OpenProcess(int a, bool inh, int pid);',' [DllImport("kernel32.dll")] static extern bool ReadProcessMemory(IntPtr h, IntPtr addr, byte[] buf, int size, out IntPtr read);',' [DllImport("kernel32.dll")] static extern bool CloseHandle(IntPtr h);'," [StructLayout(LayoutKind.Sequential)] struct PBI { public IntPtr r1; public IntPtr Peb; public IntPtr r2; public IntPtr r3; public IntPtr Pid; public IntPtr r4; }"," static IntPtr ReadPtr(IntPtr h, IntPtr addr) { var b = new byte[8]; IntPtr r; if (!ReadProcessMemory(h, addr, b, 8, out r)) return IntPtr.Zero; long v = BitConverter.ToInt64(b, 0); return v == 0 ? IntPtr.Zero : (IntPtr)v; }"," static ushort ReadU16(IntPtr h, IntPtr addr) { var b = new byte[2]; IntPtr r; if (!ReadProcessMemory(h, addr, b, 2, out r)) return 0; return BitConverter.ToUInt16(b, 0); }"," public static string GetCwd(int pid) {"," var h = OpenProcess(0x0410, false, pid);"," if (h == IntPtr.Zero) return null;"," try {"," var pbi = new PBI(); int rl;"," if (NtQueryInformationProcess(h, 0, ref pbi, Marshal.SizeOf(typeof(PBI)), out rl) != 0) return null;"," var pp = ReadPtr(h, (IntPtr)((long)pbi.Peb + 0x20));"," if (pp == IntPtr.Zero) return null;"," ushort len = ReadU16(h, (IntPtr)((long)pp + 0x38));"," var buf = ReadPtr(h, (IntPtr)((long)pp + 0x40));"," if (buf == IntPtr.Zero || len == 0 || len > 2048) return null;"," var b = new byte[len]; IntPtr r;"," if (!ReadProcessMemory(h, buf, b, len, out r)) return null;"," return System.Text.Encoding.Unicode.GetString(b).TrimEnd('\\0');"," } finally { CloseHandle(h); }"," }","}","'@","Add-Type -TypeDefinition $src","foreach ($p in Get-CimInstance Win32_Process) {"," $cwd = [WeaveWtCwd]::GetCwd($p.ProcessId)"," if ($null -ne $cwd -or $p.Name -eq 'WindowsTerminal.exe' -or $p.Name -eq 'OpenConsole.exe') {"," $created = if ($p.CreationDate) { $p.CreationDate.ToString('yyyyMMddHHmmss') } else { '' }"," '{0}|{1}|{2}|{3}|{4}' -f $p.ProcessId, $p.ParentProcessId, $p.Name, $created, $cwd"," }","}"].join(`
6
- `),ut=15e3;export function parseWtProcDump(n){const t=[];for(const e of n.split(`
7
- `)){const r=e.trimEnd().split("|");if(r.length!==5)continue;const o=Number(r[0]),a=Number(r[1]);!Number.isInteger(o)||!Number.isInteger(a)||o<=0||a<0||r[2]&&t.push({pid:o,parentPid:a,name:r[2].toLowerCase(),created:r[3],cwd:r[4]===""?null:r[4]})}return t}const Z=new Set(["bash.exe","zsh.exe","sh.exe","fish.exe","pwsh.exe","powershell.exe","cmd.exe"]);export function wtPanes(n){const t=new Set(n.filter(o=>o.name==="windowsterminal.exe").map(o=>o.pid));if(t.size===0)return[];const e=new Map;for(const o of n){if(o.parentPid===o.pid)continue;const a=e.get(o.parentPid)??[];a.push(o),e.set(o.parentPid,a)}const r=[];for(const o of n){if(!t.has(o.parentPid)||o.name==="openconsole.exe")continue;let a=o;for(;Z.has(a.name);){const s=(e.get(a.pid)??[]).filter(i=>Z.has(i.name));if(s.length===0)break;a=s.reduce((i,c)=>c.created>i.created||c.created===i.created&&c.pid>i.pid?c:i)}r.push({pid:o.pid,cwd:a.cwd})}return r}function G(n){return n.map(t=>({muxKey:`wt:${t.pid}`,windowId:t.pid,cwd:t.cwd}))}async function wt(){if(process.platform!=="win32")return[];const n=await h("powershell.exe",["-NoProfile","-Command",pt],void 0,ut);return n?.ok?wtPanes(parseWtProcDump(n.out)):[]}let T=null;async function H(){if(T&&Date.now()-T.at<1e4)return T.panes;const n=await wt();return T={at:Date.now(),panes:n},n}export function wtWindowSlug(n){const t=normalizeDirKey(n,"win32")??"root",e=t.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),r=N("sha1").update(t).digest("hex").slice(0,8);return`weave-${e.slice(0,48)||"root"}-${r}`}export function parseWtTargetId(n){const t=/^wt:(weave-[a-z0-9-]+)$/.exec(n);return t?t[1]:null}export const defaultProjectOpener={openExplorer:openInExplorer,openTerminal:openInTerminal,runInTerminal,countTerminals:countOpenTerminals,listTerminals:(n,t)=>terminalBackendFor(t).listTargets(n),runInTerminalAt:(n,t,e,r)=>terminalBackendFor(r).runAt(n,t,e)};
1
+ import{spawn as A}from"node:child_process";import{createHash as K}from"node:crypto";import{readdirSync as ee}from"node:fs";import{basename as S,join as C}from"node:path";import{TERMINAL_LOCATOR_ENV as y}from"@weavecode/core";import{pidAlive as te}from"./claude-liveness.js";import{readDaemonSettings as ne}from"./settings.js";export function quotePath(n,e){return e==="win32"?`"${n}"`:`'${n.replace(/'/g,"'\\''")}'`}function re(n,e){return e==="win32"?n!==""&&!/[\s"&|<>^%]/.test(n)?n:`"${n.replace(/"/g,'\\"')}"`:/^[A-Za-z0-9_@%+=:,./-]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}function g(n,e){return n.map(t=>re(t,e)).join(" ")}function _(n,e){return!e||!n||n.length===0?n:["cmd.exe","/k",g(n,"win32")]}function W(n,e,t){const o=`cd ${quotePath(e,"darwin")} && ${g(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return n==="Terminal"?["-e",`tell application "Terminal" to do script "${o}"`,"-e",'tell application "Terminal" to activate']:["-e",'tell application "iTerm" to create window with default profile',"-e",`tell application "iTerm" to tell current window to write text "${o}"`]}export function parsePromptPaneId(n){const e=/^([0-9a-f]{8}):(\d+)$/.exec(n);return e?{muxKey:e[1],paneId:Number(e[2])}:null}export class TerminalBackend{preset;enumerable;platform;textAddressable;constructor(e,t,r=process.platform,o=!1){this.preset=e,this.enumerable=t,this.platform=r,this.textAddressable=o}async open(e){await this.spawnFirst(this.candidates(e),`Terminal preset "${this.preset}" is unavailable on this platform`)}async run(e,t){await this.spawnFirst(this.candidates(e,t),`Terminal preset "${this.preset}" cannot run a command here \u2014 pick another preset in settings`)}async countWindows(e){return new Map}async listTargets(e){return[]}async runAt(e,t,r){throw new Error(`Terminal preset "${this.preset}" cannot attach to a chosen pane \u2014 pick wezterm, wt or Terminal.app in settings`)}async listPromptPanes(){return[]}async locatePane(e){return null}ownsPaneId(e){return!1}async locateScreens(e){return{}}async sendPromptText(e,t){throw new Error(`Terminal preset "${this.preset}" cannot send text into an open pane \u2014 pick wezterm in settings`)}async sendKeys(e,t){throw new Error(`Terminal preset "${this.preset}" cannot send keys to an open pane \u2014 pick wezterm in settings`)}async closePane(e){throw new Error(`Terminal preset "${this.preset}" cannot close an open pane \u2014 pick wezterm in settings`)}async spawnFirst(e,t){for(const r of e)if(await F(r))return;throw new Error(e.length===0?t:"No usable terminal found (tried: "+e.map(r=>r.command).join(", ")+")")}}class k extends TerminalBackend{make;constructor(e,t,r){super(e,!1,t),this.make=r}candidates(e,t){return this.make(e,t,this.platform)}}const h={wt:(n,e,t)=>t==="win32"?[{command:"wt.exe",args:["-w",wtWindowSlug(n),"-d",n,..._(e,!0)??[]]}]:[],powershell:(n,e,t)=>t==="win32"?[e?{command:"powershell.exe",args:["-NoExit","-Command",g(e,"win32")],cwd:n}:{command:"powershell.exe",args:["-NoExit"],cwd:n}]:[],cmd:(n,e,t)=>t==="win32"?[e?{command:"cmd.exe",args:["/K",g(e,"win32")],cwd:n}:{command:"cmd.exe",args:["/K"],cwd:n}]:[],terminal:(n,e,t)=>t!=="darwin"?[]:e?[{command:"osascript",args:W("Terminal",n,e)}]:[{command:"open",args:["-a","Terminal",n]}],iterm:(n,e,t)=>t!=="darwin"?[]:e?[{command:"osascript",args:W("iTerm",n,e)}]:[{command:"open",args:["-a","iTerm",n]}],gnome:(n,e)=>[{command:"gnome-terminal",args:[`--working-directory=${n}`,...e?["--",...e]:[]]}],konsole:(n,e)=>[{command:"konsole",args:["--workdir",n,...e?["-e",...e]:[]]}],ghostty:(n,e,t)=>t==="win32"?[]:t==="darwin"?e?[]:[{command:"open",args:["-a","Ghostty",n]}]:[{command:"ghostty",args:[`--working-directory=${n}`,...e?["-e",...e]:[]]}]};class oe extends TerminalBackend{terminal;constructor(e,t){super("custom",!1,t),this.terminal=e}candidates(e,t){const r=this.terminal.customCommand.trim();if(!r)return[];let o=r.replace(/\{path\}/g,quotePath(e,this.platform));const s=t?g(t,this.platform):"";return o=o.includes("{command}")?o.replace(/\{command\}/g,s):t?`${o} ${s}`:o,[{command:o,args:[],shell:!0}]}}class se extends TerminalBackend{constructor(e){super("ghostty",!1,e)}candidates(e,t){return h.ghostty(e,t,this.platform)}async openViaIpcThenStandalone(e,t){if(this.platform==="linux"){const r=["+new-window",`--working-directory=${e}`,...t.length>0?["-e",...t]:[]];if((await f("ghostty",r))?.ok)return}await this.spawnFirst(this.candidates(e,t.length>0?t:void 0),`Terminal preset "${this.preset}" is unavailable on this platform`)}open(e){return this.openViaIpcThenStandalone(e,[])}run(e,t){return this.openViaIpcThenStandalone(e,t)}}class M extends TerminalBackend{constructor(e){super("wt",e==="win32",e,e==="win32")}candidates(e,t){return h.wt(e,t,this.platform)}async countWindows(e){if(e.length===0||this.platform!=="win32")return new Map(e.map(r=>[r,0]));const t=await J();return t.length===0?new Map(e.map(r=>[r,0])):countWindowsByDir(e,Q(t))}async listTargets(e){if(this.platform!=="win32")return[];const t=await J(),r=countWindowsByDir([e],Q(t)).get(e)??0;return r===0?[]:[{id:`wt:${wtWindowSlug(e)}`,windowId:0,tabId:0,title:S(e),matchCount:r,paneCount:r,active:!1,full:!1}]}async runAt(e,t,r){if(this.platform!=="win32")throw new Error(`Terminal preset "${this.preset}" is unavailable on this platform`);if(!parseWtTargetId(r))throw new Error(`Invalid terminal target "${r}"`);await this.spawnFirst([{command:"wt.exe",args:["-w",wtWindowSlug(e),"split-pane","-d",e,..._(t,!0)??[]]}],`Terminal preset "${this.preset}" is unavailable on this platform`)}async locatePane(e){const t=wtPanePidFromEnv(e);return t==null||!te(t)?null:`wt:${t}`}ownsPaneId(e){return parseWtPaneId(e)!==null}async sendPromptText(e,t){const r=parseWtPaneId(e);if(r==null)throw new Error(`Invalid prompt pane "${e}"`);await O(r,`${ie}${t}${ae}\r`)}async sendKeys(e,t){const r=parseWtPaneId(e);if(r==null)throw new Error(`Invalid prompt pane "${e}"`);await O(r,t)}}export function parseWtPaneId(n){const e=/^wt:(\d+)$/.exec(n);if(!e)return null;const t=Number(e[1]);return Number.isInteger(t)&&t>0?t:null}export function wtPanePidFromEnv(n){const[e,t]=y.wt;if(!n[e])return null;const r=n[t];if(!r||!/^\d+$/.test(r))return null;const o=Number(r);return o>0?o:null}const ie="\x1B[200~",ae="\x1B[201~";async function O(n,e){const t=await f("powershell",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-EncodedCommand",wtInjectEncodedScript()],{...process.env,WEAVE_WT_PID:String(n),WEAVE_WT_KEYS:Buffer.from(e,"utf8").toString("base64")},15e3);if(!t)throw new Error("powershell is unavailable \u2014 cannot send keys into Windows Terminal");if(!t.ok)throw t.timedOut?new Error("Windows Terminal key injection timed out"):new Error(`Windows Terminal key injection failed: ${t.err||t.out||"unknown error"}`)}export function wtInjectEncodedScript(){const n=`$ErrorActionPreference = 'Stop'
2
+ Add-Type -TypeDefinition @'
3
+ ${ce}
4
+ '@
5
+ $keys = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($env:WEAVE_WT_KEYS))
6
+ $r = [WeaveWtKeys]::Send([uint32]$env:WEAVE_WT_PID, $keys)
7
+ if (-not $r.StartsWith('ok:')) { [Console]::Error.WriteLine($r); exit 3 }
8
+ `;return Buffer.from(n,"utf16le").toString("base64")}const ce=`using System;
9
+ using System.Runtime.InteropServices;
10
+
11
+ [StructLayout(LayoutKind.Sequential)]
12
+ public struct KEY_EVENT_RECORD
13
+ {
14
+ [MarshalAs(UnmanagedType.Bool)] public bool bKeyDown;
15
+ public ushort wRepeatCount;
16
+ public ushort wVirtualKeyCode;
17
+ public ushort wVirtualScanCode;
18
+ public char UnicodeChar;
19
+ public uint dwControlKeyState;
20
+ }
21
+
22
+ [StructLayout(LayoutKind.Explicit)]
23
+ public struct INPUT_RECORD
24
+ {
25
+ [FieldOffset(0)] public ushort EventType;
26
+ [FieldOffset(4)] public KEY_EVENT_RECORD KeyEvent;
27
+ }
28
+
29
+ public static class WeaveWtKeys
30
+ {
31
+ [DllImport("kernel32.dll", SetLastError = true)]
32
+ static extern bool AttachConsole(uint pid);
33
+ [DllImport("kernel32.dll", SetLastError = true)]
34
+ static extern bool FreeConsole();
35
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
36
+ static extern IntPtr CreateFileW(string name, uint access, uint share, IntPtr sec, uint disp, uint flags, IntPtr tmpl);
37
+ [DllImport("kernel32.dll", SetLastError = true)]
38
+ static extern bool WriteConsoleInputW(IntPtr h, INPUT_RECORD[] recs, uint len, out uint written);
39
+ [DllImport("kernel32.dll", SetLastError = true)]
40
+ static extern bool CloseHandle(IntPtr h);
41
+
42
+ static ushort VkOf(char c)
43
+ {
44
+ if (c == '\\x1b') return 0x1B;
45
+ if (c == '\\r') return 0x0D;
46
+ if (c == '\\t') return 0x09;
47
+ if (c == '\\b') return 0x08;
48
+ return 0;
49
+ }
50
+
51
+ public static string Send(uint pid, string keys)
52
+ {
53
+ FreeConsole();
54
+ if (!AttachConsole(pid)) return "attach:" + Marshal.GetLastWin32Error();
55
+ IntPtr h = CreateFileW("CONIN$", 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);
56
+ if (h == new IntPtr(-1))
57
+ {
58
+ int e = Marshal.GetLastWin32Error();
59
+ FreeConsole();
60
+ return "conin:" + e;
61
+ }
62
+ INPUT_RECORD[] recs = new INPUT_RECORD[keys.Length * 2];
63
+ for (int i = 0; i < keys.Length; i++)
64
+ {
65
+ char c = keys[i];
66
+ ushort vk = VkOf(c);
67
+ recs[i * 2].EventType = 1;
68
+ recs[i * 2].KeyEvent = new KEY_EVENT_RECORD { bKeyDown = true, wRepeatCount = 1, wVirtualKeyCode = vk, wVirtualScanCode = 0, UnicodeChar = c, dwControlKeyState = 0 };
69
+ recs[i * 2 + 1].EventType = 1;
70
+ recs[i * 2 + 1].KeyEvent = new KEY_EVENT_RECORD { bKeyDown = false, wRepeatCount = 1, wVirtualKeyCode = vk, wVirtualScanCode = 0, UnicodeChar = c, dwControlKeyState = 0 };
71
+ }
72
+ uint written;
73
+ bool ok = WriteConsoleInputW(h, recs, (uint)recs.Length, out written);
74
+ int err = Marshal.GetLastWin32Error();
75
+ CloseHandle(h);
76
+ FreeConsole();
77
+ return ok ? "ok:" + written : "write:" + err;
78
+ }
79
+ }`;class le extends TerminalBackend{constructor(e){super("konsole",!1,e,e==="linux")}candidates(e,t){return h.konsole(e,t,this.platform)}async locatePane(e){return konsolePaneFromEnv(e)}ownsPaneId(e){return parseKonsolePaneId(e)!==null}async sendPromptText(e,t){const r=parseKonsolePaneId(e);if(!r)throw new Error(`Invalid prompt pane "${e}"`);t&&await v(r,"sendText",t),await v(r,"sendKey",String(R))}async sendKeys(e,t){const r=parseKonsolePaneId(e);if(!r)throw new Error(`Invalid prompt pane "${e}"`);for(const o of t)await v(r,"sendKey",String(qtKeyOf(o)))}}export function parseKonsolePaneId(n){const e=/^konsole:([\w.:-]+)\|(\/[\w/]+)$/.exec(n);return e?{service:e[1],session:e[2]}:null}export function konsolePaneFromEnv(n){const[e,t]=y.konsole,r=n[e],o=n[t];if(!r||!o)return null;const s=`konsole:${r}|${o}`;return parseKonsolePaneId(s)?s:null}const R=16777220;export function qtKeyOf(n){switch(n){case"\x1B":return 16777216;case"\r":case`
80
+ `:return R;case" ":return 16777217;case"\b":return 16777219;default:return n.codePointAt(0)??0}}async function v(n,e,t){const r=[...["qdbus6","qdbus5","qdbus"].map(i=>({command:i,args:[n.service,n.session,e,t]})),{command:"dbus-send",args:["--session","--type=method_call",`--dest=${n.service}`,n.session,`org.kde.konsole.Session.${e}`,`string:${t}`]}];let o=null;for(const i of r){const a=await f(i.command,i.args,void 0,5e3);if(a?.ok)return;o=a}const s=o?o.err||o.out||"unknown error":"no qdbus / dbus-send on PATH";throw new Error(`Konsole D-Bus call "${e}" failed: ${s}`)}class ue extends TerminalBackend{constructor(e){super("iterm",!1,e,e==="darwin")}candidates(e,t){return h.iterm(e,t,this.platform)}async locatePane(e){return itermPaneFromEnv(e)}ownsPaneId(e){return parseItermPaneId(e)!==null}async sendPromptText(e,t){const r=parseItermPaneId(e);if(!r)throw new Error(`Invalid prompt pane "${e}"`);await de(r,t)}}export function parseItermPaneId(n){const e=/^iterm:(w\d+t\d+p\d+:[0-9A-Fa-f-]+)$/.exec(n);return e?e[1]:null}export function itermPaneFromEnv(n){const[e]=y.iterm,t=n[e];if(!t)return null;const r=`iterm:${t}`;return parseItermPaneId(r)?r:null}export function applescriptString(n){return n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}async function de(n,e){const t=`tell application "iTerm2"
81
+ repeat with w in windows
82
+ repeat with t in tabs of w
83
+ repeat with s in sessions of t
84
+ if unique id of s is "${n}" then
85
+ tell s to write text "${applescriptString(e)}"
86
+ return "ok"
87
+ end if
88
+ end repeat
89
+ end repeat
90
+ end repeat
91
+ end tell`,r=await f("osascript",["-e",t],void 0,8e3);if(!r)throw new Error("osascript is unavailable \u2014 cannot send text into iTerm2");if(!r.ok||!r.out.includes("ok"))throw new Error(`iTerm2 write text failed: ${r.err||r.out||"unknown error"}`)}class D extends TerminalBackend{constructor(e){super("terminal",e==="darwin",e)}candidates(e,t){return h.terminal(e,t,this.platform)}async run(e,t){if(this.platform==="darwin"){const r=await listTerminalAppSurfaces(this.platform),o=pickTerminalAppWindow(r,e,this.platform);if(o&&await Y(e,t,o.windowId))return}await this.spawnFirst(this.candidates(e,t),`Terminal preset "${this.preset}" is unavailable on this platform`)}async countWindows(e){if(e.length===0||this.platform!=="darwin")return new Map(e.map(r=>[r,0]));const t=await ge(this.platform);return t.length===0?new Map(e.map(r=>[r,0])):countWindowsByDir(e,t.flatMap(r=>r.cwd?[{muxKey:"terminal.app",windowId:r.windowId,tabId:r.tabIndex,cwd:r.cwd}]:[]))}listTargets(e){return Pe(e,this.platform)}async runAt(e,t,r){const o=parseTerminalAppTargetId(r);if(!o)throw new Error(`Invalid terminal target "${r}"`);if(!await Y(e,t,o.windowId))throw new Error("Terminal window is gone \u2014 pick a terminal again")}}class z extends TerminalBackend{constructor(e){super("wezterm",!0,e,!0)}candidates(e,t){return[{command:"wezterm",args:["start","--cwd",e,..._(t,this.platform==="win32")??[]]}]}async open(e){await ye(e)||await super.open(e)}async run(e,t){await Ie(e,t)||await super.run(e,t)}async countWindows(e){if(e.length===0)return new Map;const{muxes:t}=await H();return t.length===0?new Map(e.map(r=>[r,0])):countWindowsByDir(e,t.flatMap(r=>r.panes.map(o=>({muxKey:r.socket,windowId:o.windowId,tabId:o.tabId,cwd:o.cwd}))))}listTargets(e){return listAttachTargets(e,this.platform)}runAt(e,t,r){return runInWeztermAt(e,t,r,this.platform)}async listPromptPanes(){const{muxes:e}=await x();return e.flatMap(t=>t.panes.map(r=>({id:`${weztermMuxKey(t.socket)}:${r.paneId}`,title:r.title,cwd:r.cwd})))}async locatePane(e){const[t,r]=y.wezterm,o=e[r];if(!e[t]||!o)return null;const{muxes:s}=await x(!0,o);return weztermPaneFromEnv(e,s,this.platform)}ownsPaneId(e){return parsePromptPaneId(e)!==null}async locateScreens(e){if(Object.keys(e).length===0)return{};const{muxes:t,candidates:r}=await H();return sessionScreensFromEnvs(e,t,r,this.platform)}async sendPromptText(e,t){const r=parsePromptPaneId(e);if(!r)throw new Error(`Invalid prompt pane "${e}"`);const o=await N(r.muxKey);if(!o)throw new Error("wezterm instance is gone \u2014 cannot deliver prompt");const s=String(r.paneId);if(t){const a=await I(["cli","send-text","--pane-id",s,t],o.socket);if(!a?.ok)throw new Error(b(["cli","send-text","--pane-id",s,"<prompt text>"],o.socket,a))}const i=await I(["cli","send-text","--pane-id",s,"--no-paste","\r"],o.socket);if(!i?.ok)throw new Error(b(["cli","send-text","--pane-id",s,"--no-paste","<CR>"],o.socket,i))}async sendKeys(e,t){const r=parsePromptPaneId(e);if(!r)throw new Error(`Invalid prompt pane "${e}"`);const o=await N(r.muxKey);if(!o)throw new Error("wezterm instance is gone \u2014 cannot send keys to the pane");const s=String(r.paneId),i=await I(["cli","send-text","--pane-id",s,"--no-paste",t],o.socket);if(!i?.ok)throw new Error(b(["cli","send-text","--pane-id",s,"--no-paste","<keys>"],o.socket,i))}async closePane(e){const t=parsePromptPaneId(e);if(!t)throw new Error(`Invalid prompt pane "${e}"`);const r=await N(t.muxKey);if(!r)throw new Error("wezterm instance is gone \u2014 cannot close the pane");const o=String(t.paneId),s=await I(["cli","kill-pane","--pane-id",o],r.socket);if(!s?.ok)throw new Error(b(["cli","kill-pane","--pane-id",o],r.socket,s))}}class pe extends TerminalBackend{parts;constructor(e){super("auto",!0,e,e!=="win32"&&e!=="darwin");const r={win32:["wt","powershell","cmd"],darwin:["terminal","iterm"]}[e]??["gnome","konsole"];this.parts=r.map(o=>new k(o,e,h[o]))}candidates(e,t){return this.parts.flatMap(r=>t&&r.preset==="iterm"?[]:r.candidates(e,t))}attachBackend(){return this.platform==="darwin"?new D(this.platform):this.platform==="win32"?new M(this.platform):new z(this.platform)}countWindows(e){return this.attachBackend().countWindows(e)}listTargets(e){return this.attachBackend().listTargets(e)}runAt(e,t,r){return this.attachBackend().runAt(e,t,r)}listPromptPanes(){return this.attachBackend().listPromptPanes()}locatePane(e){return this.attachBackend().locatePane(e)}locateScreens(e){return this.attachBackend().locateScreens(e)}sendPromptText(e,t){return this.attachBackend().sendPromptText(e,t)}sendKeys(e,t){return this.attachBackend().sendKeys(e,t)}closePane(e){return this.attachBackend().closePane(e)}}const B={auto:(n,e)=>new pe(e),wt:(n,e)=>new M(e),powershell:(n,e)=>new k("powershell",e,h.powershell),cmd:(n,e)=>new k("cmd",e,h.cmd),terminal:(n,e)=>new D(e),iterm:(n,e)=>new ue(e),gnome:(n,e)=>new k("gnome",e,h.gnome),konsole:(n,e)=>new le(e),ghostty:(n,e)=>new se(e),wezterm:(n,e)=>new z(e),custom:(n,e)=>new oe(n,e)};export function terminalBackendFor(n,e=process.platform){return(B[n.preset]??B.auto)(n,e)}export function locatorPresetOf(n){for(const[e,t]of Object.entries(y))if(t.every(r=>n[r]))return e;return null}export function promptTerminalChannel(n){const e=i=>terminalBackendFor({...n(),preset:i}),t=()=>e(n().preset),r=()=>Object.keys(y).map(i=>e(i)),o=i=>{const a=locatorPresetOf(i);return a?e(a):null},s=i=>r().find(a=>a.ownsPaneId(i))??null;return{available:()=>r().some(i=>i.textAddressable),listPanes:async()=>{const i=t();return i.textAddressable?await i.listPromptPanes():[]},locatePane:async i=>await o(i)?.locatePane(i)??null,locateScreens:async i=>{const a={},c=new Map;for(const[l,d]of Object.entries(i)){const u=locatorPresetOf(d);if(!u){a[l]=null;continue}const w=c.get(u)??{};w[l]=d,c.set(u,w)}for(const[l,d]of c){const u=e(l);if(!u.locateScreens){for(const m of Object.keys(d))a[m]=null;continue}const w=await u.locateScreens(d);for(const[m,p]of Object.entries(w))a[m]=p}return a},sendText:async(i,a)=>{const c=s(i);if(!c)throw new Error(`Invalid prompt pane "${i}"`);await c.sendPromptText(i,a)},sendKeys:async(i,a)=>{const c=s(i);if(!c)throw new Error(`Invalid prompt pane "${i}"`);await c.sendKeys(i,a)},closePane:async i=>{const a=s(i);if(!a)throw new Error(`Invalid prompt pane "${i}"`);await a.closePane(i)}}}export function resolveTerminalLaunch(n,e,t=process.platform,r){return terminalBackendFor(e,t).candidates(n,r)}export function resolveExplorerLaunch(n,e=process.platform){return e==="win32"?{command:"explorer.exe",args:[n]}:e==="darwin"?{command:"open",args:[n]}:{command:"xdg-open",args:[n]}}function F(n){return new Promise(e=>{let t;try{t=A(n.command,n.args,{cwd:n.cwd,shell:n.shell,detached:!0,stdio:"ignore"})}catch{e(!1);return}t.on("error",()=>e(!1)),t.on("spawn",()=>{t.unref(),e(!0)})})}export async function openInExplorer(n){const e=resolveExplorerLaunch(n);if(!await F(e))throw new Error(`Failed to open file manager (${e.command})`)}export async function openInTerminal(n,e){await terminalBackendFor(e).open(n)}export async function runInTerminal(n,e,t){await terminalBackendFor(t).run(n,e)}export function parseWeztermPanes(n){if(!n)return[];let e;try{e=JSON.parse(n)}catch{return[]}if(!Array.isArray(e))return[];const t=[];for(const r of e){const o=r;typeof o?.pane_id!="number"||typeof o?.tab_id!="number"||t.push({windowId:typeof o.window_id=="number"?o.window_id:0,tabId:o.tab_id,paneId:o.pane_id,cwd:typeof o.cwd=="string"?o.cwd:null,left:typeof o.left_col=="number"?o.left_col:0,top:typeof o.top_row=="number"?o.top_row:0,isActive:o.is_active===!0,title:typeof o.title=="string"&&o.title?o.title:null})}return t}export function normalizeDirKey(n,e){if(!n)return null;let t=n;if(t.startsWith("file://")){t=t.slice(7);try{t=decodeURIComponent(t)}catch{return null}e==="win32"&&(t=t.replace(/^\//,""))}return t=t.replace(/\\/g,"/").replace(/\/+$/,""),t?e==="win32"?t.toLowerCase():t:null}export function countWindowsByDir(n,e,t=process.platform){const r=n.map(s=>normalizeDirKey(s,t)),o=n.map(()=>new Set);for(const s of e){const i=normalizeDirKey(s.cwd,t);if(!i)continue;const a=s.tabId==null?`${s.muxKey}#${s.windowId}`:`${s.muxKey}#${s.windowId}#${s.tabId}`;for(let c=0;c<n.length;c++)r[c]!==null&&r[c]===i&&o[c].add(a)}return new Map(n.map((s,i)=>[s,o[i].size]))}export const MAX_PANES_PER_SCREEN=6;function we(n,e,t){const r=new Map,o=new Map;for(const a of e)o.set(a.tabId,(o.get(a.tabId)??0)+1),normalizeDirKey(a.cwd,t)===n&&r.set(a.tabId,(r.get(a.tabId)??0)+1);let s=null,i=0;for(const[a,c]of r)(o.get(a)??0)>=MAX_PANES_PER_SCREEN||(s===null||c>i||c===i&&a<s)&&(s=a,i=c);return s}export function planWeztermGrid(n){if(n.length===0||n.length>=MAX_PANES_PER_SCREEN)return null;if(n.length===1)return{paneId:n[0].paneId,direction:"right"};const e=new Map;for(const o of n){const s=e.get(o.left)??[];s.push(o),e.set(o.left,s)}const t=[...e.entries()].sort(([o],[s])=>o-s).map(([,o])=>[...o].sort((s,i)=>i.top-s.top));if(t.length===1)return{paneId:t[0][0].paneId,direction:"right"};let r=t[0];for(const o of t)o.length<r.length&&(r=o);return{paneId:r[0].paneId,direction:"bottom"}}export function planWeztermReuse(n,e,t=process.platform){const r=normalizeDirKey(n,t);if(!r)return null;const o=we(r,e,t);return o===null?null:planWeztermGrid(e.filter(s=>s.tabId===o))}export function planWeztermNewWindow(n,e){const t=["cli","spawn","--new-window","--cwd",n];return e&&t.push("--workspace",e),t}export function weztermMuxKey(n){return K("sha256").update(normalizeDirKey(n,process.platform)??n).digest("hex").slice(0,8)}export function weztermPaneFromEnv(n,e,t){const[r,o]=y.wezterm,s=n[r],i=n[o];if(!s||!i)return null;const a=normalizeDirKey(i,t),c=e.find(l=>normalizeDirKey(l.socket,t)===a);return!c||!c.panes.some(l=>String(l.paneId)===s)?null:`${weztermMuxKey(c.socket)}:${s}`}export function sessionScreensFromEnvs(n,e,t,r=process.platform){const[o,s]=y.wezterm,i=new Set(t.map(c=>normalizeDirKey(c,r))),a={};for(const[c,l]of Object.entries(n)){const d=l[o],u=l[s],w=u?e.find(p=>normalizeDirKey(p.socket,r)===normalizeDirKey(u,r)):void 0,m=w?.panes.find(p=>String(p.paneId)===d);if(w){a[c]=m?{id:`${weztermMuxKey(w.socket)}:${m.windowId}:${m.tabId}`,windowId:m.windowId,tabId:m.tabId,tabsInWindow:new Set(w.panes.filter(p=>p.windowId===m.windowId).map(p=>p.tabId)).size}:null;continue}u&&i.has(normalizeDirKey(u,r))||(a[c]=null)}return a}export function parseAttachTargetId(n){const e=/^([0-9a-f]{8}):(\d+):(\d+)$/.exec(n);return e?{muxKey:e[1],windowId:Number(e[2]),tabId:Number(e[3])}:null}export function attachTargetsFromMuxes(n,e,t=process.platform){const r=normalizeDirKey(n,t);if(!r)return[];const o=[];for(const s of[...e].sort((i,a)=>i.idleMs-a.idleMs)){const i=new Map;for(const c of s.panes){const l=`${c.windowId}:${c.tabId}`,d=i.get(l)??[];d.push(c),i.set(l,d)}const a=[];for(const[c,l]of i){const d=l.filter(p=>normalizeDirKey(p.cwd,t)===r).length;if(d===0)continue;const u=Number(c.slice(0,c.indexOf(":"))),w=Number(c.slice(c.indexOf(":")+1)),m=l.find(p=>p.isActive)??l[0];a.push({id:`${weztermMuxKey(s.socket)}:${u}:${w}`,windowId:u,tabId:w,title:m.title,matchCount:d,paneCount:l.length,active:l.some(p=>p.isActive),full:l.length>=MAX_PANES_PER_SCREEN})}a.sort((c,l)=>Number(l.active)-Number(c.active)||l.tabId-c.tabId),o.push(...a)}return o}export async function listAttachTargets(n,e=process.platform){const{muxes:t}=await x();return attachTargetsFromMuxes(n,t,e)}function L(n){if(!n)return null;let e;try{e=JSON.parse(n)}catch{return null}if(!Array.isArray(e))return null;let t=null;for(const r of e){const o=r;if(typeof o?.workspace!="string"||!o.workspace)continue;const s=o.idle_time,i=(typeof s?.secs=="number"?s.secs*1e3:0)+(typeof s?.nanos=="number"?s.nanos/1e6:0);(t===null||i<t.idleMs)&&(t={workspace:o.workspace,idleMs:i})}return t}export function weztermActiveWorkspaceOf(n){return L(n)?.workspace??null}const U=5e3;function f(n,e,t,r=U){return new Promise(o=>{let s;try{s=A(n,e,{windowsHide:!0,env:t??process.env})}catch{o(null);return}let i="",a="",c=!1;const l=u=>{c||(c=!0,clearTimeout(d),o(u))};s.stdout.on("data",u=>{i+=u.toString()}),s.stderr?.on("data",u=>{a+=u.toString()});const d=setTimeout(()=>{s.stdout.destroy(),s.stderr?.destroy(),s.unref(),s.kill(),l({ok:!1,out:i,err:a.trim(),timedOut:!0})},r);d.unref(),s.on("error",()=>l(null)),s.on("close",u=>{l({ok:u===0,out:i,err:a.trim(),timedOut:!1})})})}function I(n,e){return f("wezterm",weztermCliArgs(n),{...process.env,WEZTERM_UNIX_SOCKET:e})}export function weztermCliArgs(n){return n[0]==="cli"?["cli","--no-auto-start",...n.slice(1)]:[...n]}function b(n,e,t){const r=`wezterm[${S(e)}] ${n.join(" ")}`;return t===null?`${r}: executable not found`:t.timedOut?`${r}: timed out after ${U}ms`:t.err?`${r}: ${t.err}`:`${r}: exited with failure`}function V(n){try{return process.kill(n,0),!0}catch{return!1}}function me(n){const e=/gui-sock-(\d+)$/.exec(n.replace(/\\/g,"/"));return e?Number(e[1]):null}function j(n){let e;try{e=ee(n)}catch{return[]}const t=[];for(const r of e){const o=/^gui-sock-(\d+)$/.exec(r);if(!o)continue;const s=Number(o[1]);V(s)&&t.push({path:C(n,r),pid:s})}return t.sort((r,o)=>o.pid-r.pid).map(r=>r.path)}function fe(n,e){const t=n.replace(/\\/g,"/");return e==="win32"?t.toLowerCase():t}export function weztermSocketCandidates(n){const e=[],t=new Set,r=s=>{const i=fe(s,n);t.has(i)||(t.add(i),e.push(s))};process.env.WEZTERM_UNIX_SOCKET&&r(process.env.WEZTERM_UNIX_SOCKET);const o=n==="win32"?process.env.USERPROFILE:process.env.HOME;return o&&j(C(o,".local","share","wezterm")).forEach(r),n!=="win32"&&process.env.XDG_RUNTIME_DIR&&j(C(process.env.XDG_RUNTIME_DIR,"wezterm")).forEach(r),e}const he=6e4;export class SocketProbeGate{dead=new Set;cooling=new Map;shouldProbe(e,t=Date.now()){if(this.dead.has(e))return!1;const r=this.cooling.get(e);return r===void 0||t>=r}succeeded(e){this.cooling.delete(e)}failed(e){this.dead.add(e),this.cooling.delete(e)}cooledDown(e,t=Date.now()){this.dead.has(e)||this.cooling.set(e,t+he)}}const E=new SocketProbeGate;async function x(n=!1,e=null){const t=e?[e]:weztermSocketCandidates(process.platform);return{muxes:(await Promise.all(t.map(async o=>{if(!e&&!E.shouldProbe(o))return null;const s=await I(["cli","list","--format","json"],o);if(!s?.ok){const l=me(o);return s&&!s.timedOut&&l!==null&&!V(l)?E.failed(o):E.cooledDown(o),null}E.succeeded(o);const i=parseWeztermPanes(s.out);if(n)return{socket:o,panes:i,workspace:null,idleMs:Number.POSITIVE_INFINITY};const a=await I(["cli","list-clients","--format","json"],o),c=L(a?.ok?a.out:null);return{socket:o,panes:i,workspace:c?.workspace??null,idleMs:c?.idleMs??Number.POSITIVE_INFINITY}}))).filter(o=>o!==null),candidates:t}}async function N(n){const e=weztermSocketCandidates(process.platform).find(r=>weztermMuxKey(r)===n);if(!e)return null;const{muxes:t}=await x(!0,e);return t.find(r=>weztermMuxKey(r.socket)===n)??null}async function ye(n){const{muxes:e}=await x();if(e.length===0)return!1;const t=e.reduce((r,o)=>o.idleMs<r.idleMs?o:r);return await G(t.socket,n,null,t.workspace),!0}async function Ie(n,e){const t=process.platform,{muxes:r}=await x();if(r.length===0)return!1;let o=null,s=null;for(const i of r){const a=planWeztermReuse(n,i.panes,t);a&&(o===null||i.idleMs<o.idleMs)&&(o=i,s=a)}return o??=r.reduce((i,a)=>a.idleMs<i.idleMs?a:i),await q(o.socket,n,e,s,o.workspace),!0}async function G(n,e,t,r){const o=t?["cli","split-pane","--pane-id",String(t.paneId),`--${t.direction}`,"--cwd",e]:planWeztermNewWindow(e,r),s=await I(o,n);if(!s?.ok)throw new Error(b(o,n,s));const i=s.out.trim();if(!/^\d+$/.test(i))throw new Error(`wezterm[${S(n)}] ${o.join(" ")}: unexpected pane id "${i}"`);return i}async function q(n,e,t,r,o,s=process.platform){const a=["cli","send-text","--pane-id",await G(n,e,r,o),"--no-paste",`${g(t,s)}\r`],c=await I(a,n);if(!c?.ok)throw new Error(b(a,n,c))}export async function runInWeztermAt(n,e,t,r=process.platform){const o=parseAttachTargetId(t);if(!o)throw new Error(`Invalid terminal target "${t}"`);const{muxes:s}=await x(),i=s.find(c=>weztermMuxKey(c.socket)===o.muxKey);if(!i)throw new Error("wezterm instance is gone \u2014 pick a terminal again");const a=i.panes.filter(c=>c.windowId===o.windowId&&c.tabId===o.tabId);if(a.length===0)throw new Error("terminal tab is gone \u2014 pick a terminal again");if(a.length>=MAX_PANES_PER_SCREEN)throw new Error(`terminal is full (${MAX_PANES_PER_SCREEN} panes) \u2014 pick another terminal or open a new one`);await q(i.socket,n,e,planWeztermGrid(a),i.workspace,r)}export async function countOpenTerminals(n,e){return terminalBackendFor(e).countWindows(n)}export function panesAtDir(n,e,t=process.platform){const r=normalizeDirKey(e,t);return n.filter(o=>o.cwd!=null&&normalizeDirKey(o.cwd,t)===r)}export async function listProjectPanes(n,e,t=process.platform){const r=terminalBackendFor(e,t),o=panesAtDir(await r.listPromptPanes(),n,t);if(o.length===0&&((await r.countWindows([n])).get(n)??0)>0)throw new Error(`Terminal preset "${r.preset}" cannot close open panes remotely \u2014 pick wezterm in settings`);return o}export async function closeTerminalsIn(n,e,t,r=process.platform){const o=terminalBackendFor(e,r),s=new Set(t),i=(await listProjectPanes(n,e,r)).filter(a=>s.has(a.id));for(const a of i)await o.closePane(a.id);return i.length}export async function readTerminalCounts(n,e=defaultProjectOpener){const t=await ne(),o=await(e.countTerminals??countOpenTerminals)(n.map(s=>s.path),t.terminal);return Object.fromEntries(n.map(s=>[s.id,o.get(s.path)??0]))}let P=null;async function H(){if(P&&Date.now()-P.at<1e4)return P;const{muxes:n,candidates:e}=await x(!0);return P={at:Date.now(),muxes:n,candidates:e},P}const xe=['if application "Terminal" is not running then return ""','tell application "Terminal"',' set out to ""'," repeat with w in windows"," set wid to id of w"," set fm to frontmost of w as text"," repeat with t in tabs of w",' set out to out & wid & "\\t" & (index of t) & "\\t" & tty of t & "\\t" & (selected of t as text) & "\\t" & fm & linefeed'," end repeat"," end repeat"," return out","end tell"].join(`
92
+ `);export function parseTerminalAppDump(n){const e=[];for(const t of n.split(`
93
+ `)){const r=t.trim().split(" ");if(r.length!==5)continue;const o=Number(r[0]),s=Number(r[1]);!Number.isInteger(o)||!Number.isInteger(s)||e.push({windowId:o,tabIndex:s,tty:r[2],selected:r[3]==="true",frontmost:r[4]==="true"})}return e}export function parsePsRootPids(n){const e=new Map,t=new Map;for(const o of n.split(`
94
+ `)){const s=/^\s*(\d+)\s+(\d+)\s+(\S+)/.exec(o);if(!s)continue;const i=Number(s[1]),a=s[3];if(a==="??")continue;const c=e.get(a)??new Set;c.add(i),e.set(a,c),t.set(i,Number(s[2]))}const r=new Map;for(const[o,s]of e)for(const i of s)if(!s.has(t.get(i)??-1)){r.set(o,i);break}return r}export function parseLsofCwds(n){const e=new Map;let t=-1;for(const r of n.split(`
95
+ `))r.startsWith("p")&&/^\d+$/.test(r.slice(1))?t=Number(r.slice(1)):r.startsWith("n")&&t!==-1&&(e.set(t,r.slice(1)),t=-1);return e}export async function listTerminalAppSurfaces(n){if(n!=="darwin")return[];const e=await f("osascript",["-e",xe]);if(!e?.ok)return[];const t=parseTerminalAppDump(e.out);if(t.length===0)return[];const r=await f("ps",["-axo","pid=,ppid=,tty="]);if(!r?.ok)return t.map(c=>({...c,cwd:null}));const o=parsePsRootPids(r.out),s=[...new Set(t.map(c=>o.get(c.tty.replace(/^\/dev\//,""))??-1))].filter(c=>c!==-1),i=s.length>0?await f("lsof",["-a","-p",s.join(","),"-d","cwd","-Fn"]):null,a=parseLsofCwds(i?.out??"");return t.map(c=>({...c,cwd:a.get(o.get(c.tty.replace(/^\/dev\//,""))??-1)??null}))}let T=null;async function ge(n){if(T&&Date.now()-T.at<1e4)return T.surfaces;const e=await listTerminalAppSurfaces(n);return T={at:Date.now(),surfaces:e},e}function be(n,e){return`terminal:${n}:${e}`}export function parseTerminalAppTargetId(n){const e=/^terminal:(\d+):(\d+)$/.exec(n);return e?{windowId:Number(e[1]),tabIndex:Number(e[2])}:null}function Z(n,e,t){const r=normalizeDirKey(e,t);return r?n.filter(o=>o.cwd!==null&&normalizeDirKey(o.cwd,t)===r):[]}export function terminalAppTargets(n,e,t=process.platform){const r=Z(e,n,t);return r.sort((o,s)=>Number(s.frontmost)-Number(o.frontmost)||Number(s.selected)-Number(o.selected)||s.tabIndex-o.tabIndex),r.map(o=>({id:be(o.windowId,o.tabIndex),windowId:o.windowId,tabId:o.tabIndex,title:null,matchCount:1,paneCount:1,active:o.frontmost&&o.selected,full:!1}))}export function pickTerminalAppWindow(n,e,t=process.platform){const r=Z(n,e,t);return r.length===0?null:(r.sort((o,s)=>Number(s.frontmost)-Number(o.frontmost)||s.windowId-o.windowId),{windowId:r[0].windowId,tabIndex:r[0].tabIndex})}async function Pe(n,e){return terminalAppTargets(n,await listTerminalAppSurfaces(e),e)}async function Y(n,e,t){const o=`cd ${quotePath(n,"darwin")} && ${g(e,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return(await f("osascript",["-e",`tell application "Terminal" to do script "${o}" in window id ${t}`]))?.ok===!0}const ke=["$ErrorActionPreference = 'SilentlyContinue'","$src = @'","using System; using System.Runtime.InteropServices;","public class WeaveWtCwd {",' [DllImport("ntdll.dll")] static extern int NtQueryInformationProcess(IntPtr h, int c, ref PBI pbi, int size, out int rl);',' [DllImport("kernel32.dll")] static extern IntPtr OpenProcess(int a, bool inh, int pid);',' [DllImport("kernel32.dll")] static extern bool ReadProcessMemory(IntPtr h, IntPtr addr, byte[] buf, int size, out IntPtr read);',' [DllImport("kernel32.dll")] static extern bool CloseHandle(IntPtr h);'," [StructLayout(LayoutKind.Sequential)] struct PBI { public IntPtr r1; public IntPtr Peb; public IntPtr r2; public IntPtr r3; public IntPtr Pid; public IntPtr r4; }"," static IntPtr ReadPtr(IntPtr h, IntPtr addr) { var b = new byte[8]; IntPtr r; if (!ReadProcessMemory(h, addr, b, 8, out r)) return IntPtr.Zero; long v = BitConverter.ToInt64(b, 0); return v == 0 ? IntPtr.Zero : (IntPtr)v; }"," static ushort ReadU16(IntPtr h, IntPtr addr) { var b = new byte[2]; IntPtr r; if (!ReadProcessMemory(h, addr, b, 2, out r)) return 0; return BitConverter.ToUInt16(b, 0); }"," public static string GetCwd(int pid) {"," var h = OpenProcess(0x0410, false, pid);"," if (h == IntPtr.Zero) return null;"," try {"," var pbi = new PBI(); int rl;"," if (NtQueryInformationProcess(h, 0, ref pbi, Marshal.SizeOf(typeof(PBI)), out rl) != 0) return null;"," var pp = ReadPtr(h, (IntPtr)((long)pbi.Peb + 0x20));"," if (pp == IntPtr.Zero) return null;"," ushort len = ReadU16(h, (IntPtr)((long)pp + 0x38));"," var buf = ReadPtr(h, (IntPtr)((long)pp + 0x40));"," if (buf == IntPtr.Zero || len == 0 || len > 2048) return null;"," var b = new byte[len]; IntPtr r;"," if (!ReadProcessMemory(h, buf, b, len, out r)) return null;"," return System.Text.Encoding.Unicode.GetString(b).TrimEnd('\\0');"," } finally { CloseHandle(h); }"," }","}","'@","Add-Type -TypeDefinition $src","foreach ($p in Get-CimInstance Win32_Process) {"," $cwd = [WeaveWtCwd]::GetCwd($p.ProcessId)"," if ($null -ne $cwd -or $p.Name -eq 'WindowsTerminal.exe' -or $p.Name -eq 'OpenConsole.exe') {"," $created = if ($p.CreationDate) { $p.CreationDate.ToString('yyyyMMddHHmmss') } else { '' }"," '{0}|{1}|{2}|{3}|{4}' -f $p.ProcessId, $p.ParentProcessId, $p.Name, $created, $cwd"," }","}"].join(`
96
+ `),Ee=15e3;export function parseWtProcDump(n){const e=[];for(const t of n.split(`
97
+ `)){const r=t.trimEnd().split("|");if(r.length!==5)continue;const o=Number(r[0]),s=Number(r[1]);!Number.isInteger(o)||!Number.isInteger(s)||o<=0||s<0||r[2]&&e.push({pid:o,parentPid:s,name:r[2].toLowerCase(),created:r[3],cwd:r[4]===""?null:r[4]})}return e}const X=new Set(["bash.exe","zsh.exe","sh.exe","fish.exe","pwsh.exe","powershell.exe","cmd.exe"]);export function wtPanes(n){const e=new Set(n.filter(o=>o.name==="windowsterminal.exe").map(o=>o.pid));if(e.size===0)return[];const t=new Map;for(const o of n){if(o.parentPid===o.pid)continue;const s=t.get(o.parentPid)??[];s.push(o),t.set(o.parentPid,s)}const r=[];for(const o of n){if(!e.has(o.parentPid)||o.name==="openconsole.exe")continue;let s=o;for(;X.has(s.name);){const i=(t.get(s.pid)??[]).filter(a=>X.has(a.name));if(i.length===0)break;s=i.reduce((a,c)=>c.created>a.created||c.created===a.created&&c.pid>a.pid?c:a)}r.push({pid:o.pid,cwd:s.cwd})}return r}function Q(n){return n.map(e=>({muxKey:`wt:${e.pid}`,windowId:e.pid,cwd:e.cwd}))}async function Te(){if(process.platform!=="win32")return[];const n=await f("powershell.exe",["-NoProfile","-Command",ke],void 0,Ee);return n?.ok?wtPanes(parseWtProcDump(n.out)):[]}let $=null;async function J(){if($&&Date.now()-$.at<1e4)return $.panes;const n=await Te();return $={at:Date.now(),panes:n},n}export function wtWindowSlug(n){const e=normalizeDirKey(n,"win32")??"root",t=e.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),r=K("sha1").update(e).digest("hex").slice(0,8);return`weave-${t.slice(0,48)||"root"}-${r}`}export function parseWtTargetId(n){const e=/^wt:(weave-[a-z0-9-]+)$/.exec(n);return e?e[1]:null}export const defaultProjectOpener={openExplorer:openInExplorer,openTerminal:openInTerminal,runInTerminal,countTerminals:countOpenTerminals,closeTerminals:(n,e,t)=>closeTerminalsIn(n,e,t),listPanes:(n,e)=>listProjectPanes(n,e),listTerminals:(n,e)=>terminalBackendFor(e).listTargets(n),runInTerminalAt:(n,e,t,r)=>terminalBackendFor(r).runAt(n,e,t)};
@@ -1 +1 @@
1
- import t from"node:net";export const DEFAULT_PORT=6420,DAEMON_HOST="127.0.0.1",DEFAULT_BIND_HOST="0.0.0.0";export function isPortFree(r,n=DAEMON_HOST){return new Promise(e=>{const o=t.createServer();o.once("error",()=>e(!1)),o.once("listening",()=>o.close(()=>e(!0))),o.listen(r,n)})}export async function findFreePort(r,n=100){for(let e=r;e<r+n;e++)if(await isPortFree(e))return e;throw new Error(`No free port found in range ${r}-${r+n-1}`)}
1
+ import t from"node:net";export const DEFAULT_PORT=6420,DAEMON_HOST="127.0.0.1",DEFAULT_BIND_HOST="0.0.0.0";export function isPortFree(r,o=DAEMON_HOST){return new Promise(e=>{const n=t.createServer();n.once("error",()=>e(!1)),n.once("listening",()=>n.close(()=>e(!0))),n.listen(r,o)})}export async function findFreePort(r,o=100){for(let e=r;e<r+o;e++)if(await isPortFree(e))return e;throw new Error(`No free port found in range ${r}-${r+o-1}`)}
@@ -1,2 +1,2 @@
1
- import{readFile as i}from"node:fs/promises";import o from"node:path";import{HARNESS_KEYS as c,isHarness as f}from"@weavecode/core";async function m(s){const r=[c[0]];let t;try{t=await i(o.join(s,".weave","config.yaml"),"utf-8")}catch{return r}const e=t.split(`
2
- `).find(a=>a.startsWith("harnesses:"));if(!e)return r;try{const a=JSON.parse(e.slice(e.indexOf(":")+1).trim()),n=Array.isArray(a)?a.filter(f):[];return n.length>0?n:r}catch{return r}}export async function projectHarnesses(s,r){return(await m(s)).map(t=>({id:t,canStartSession:!!r?.get(t)?.resume?.bin}))}export async function withProjectHarnesses(s,r){return Promise.all(s.map(async t=>({...t,harnesses:await projectHarnesses(t.path,r)})))}
1
+ import{readFile as i}from"node:fs/promises";import o from"node:path";import{HARNESS_KEYS as c,isHarness as f}from"@weavecode/core";async function l(e){const r=[c[0]];let t;try{t=await i(o.join(e,".weave","config.yaml"),"utf-8")}catch{return r}const s=t.split(`
2
+ `).find(a=>a.startsWith("harnesses:"));if(!s)return r;try{const a=JSON.parse(s.slice(s.indexOf(":")+1).trim()),n=Array.isArray(a)?a.filter(f):[];return n.length>0?n:r}catch{return r}}export async function projectHarnesses(e,r){return(await l(e)).map(t=>({id:t,canStartSession:!!r?.get(t)?.resume?.bin}))}export async function withProjectHarnesses(e,r){return Promise.all(e.map(async t=>({...t,harnesses:await projectHarnesses(t.path,r)})))}
@@ -1,5 +1,6 @@
1
1
  import type { DataBus } from './data-bus.js';
2
2
  import type { HookEventBus } from '../hooks/bus.js';
3
+ import type { ProjectUpdateSummary } from '../install/updates.js';
3
4
  /**
4
5
  * ProjectUpdatesRefresher — 项目行「有更新待同步」角标的数据面(SSE 推送)。
5
6
  *
@@ -10,7 +11,7 @@ import type { HookEventBus } from '../hooks/bus.js';
10
11
  * 自我校正;`GET /projects/:id/updates` 仍是权威检测面(hover 兜底同源同算)。
11
12
  */
12
13
  export declare class ProjectUpdatesRefresher {
13
- /** 现算一份每项目待同步数(projectId → 条数,含 0);失败应 throw,由本类吞掉。 */
14
+ /** 现算一份每项目更新摘要(含 0/false);失败应 throw,由本类吞掉。 */
14
15
  private readonly snapshot;
15
16
  private readonly bus;
16
17
  /** 是否值得重算(一般为「有 SSE 客户端」)。缺省恒真(测试用)。 */
@@ -22,8 +23,8 @@ export declare class ProjectUpdatesRefresher {
22
23
  /** 重算要读盘/算指纹,防重入(并发重算会让快照乱序到达)。 */
23
24
  private running;
24
25
  constructor(
25
- /** 现算一份每项目待同步数(projectId → 条数,含 0);失败应 throw,由本类吞掉。 */
26
- snapshot: () => Promise<Record<number, number>>, bus: DataBus, hookBus: HookEventBus,
26
+ /** 现算一份每项目更新摘要(含 0/false);失败应 throw,由本类吞掉。 */
27
+ snapshot: () => Promise<Record<number, ProjectUpdateSummary>>, bus: DataBus, hookBus: HookEventBus,
27
28
  /** 是否值得重算(一般为「有 SSE 客户端」)。缺省恒真(测试用)。 */
28
29
  shouldRun?: () => boolean);
29
30
  /** 显式对账(用户动作/同步落地):无视「没人看」判定,仍只在值变化时推。 */
@@ -1 +1 @@
1
- export class ProjectUpdatesRefresher{snapshot;bus;shouldRun;lastCounts=null;lastFingerprint=null;running=!1;constructor(n,s,t,i=()=>!0){this.snapshot=n,this.bus=s,this.shouldRun=i,t.subscribe(r=>{r.kind==="plugin.reloaded"&&this.refreshNow()})}async refreshNow(n=!1){if(!this.running&&!(!n&&!this.shouldRun())){this.running=!0;try{const s=await this.snapshot();this.lastCounts=s;const t=JSON.stringify(s);if(t===this.lastFingerprint)return;this.lastFingerprint=t,this.bus.emit({key:"updates",payload:{counts:s}})}catch{}finally{this.running=!1}}}onSubscriberJoin(){this.lastCounts!==null&&(this.lastFingerprint=JSON.stringify(this.lastCounts),this.bus.emit({key:"updates",payload:{counts:this.lastCounts}})),this.refreshNow(!0)}}
1
+ export class ProjectUpdatesRefresher{snapshot;bus;shouldRun;lastCounts=null;lastFingerprint=null;running=!1;constructor(i,s,t,n=()=>!0){this.snapshot=i,this.bus=s,this.shouldRun=n,t.subscribe(r=>{r.kind==="plugin.reloaded"&&this.refreshNow()})}async refreshNow(i=!1){if(!this.running&&!(!i&&!this.shouldRun())){this.running=!0;try{const s=await this.snapshot();this.lastCounts=s;const t=JSON.stringify(s);if(t===this.lastFingerprint)return;this.lastFingerprint=t,this.bus.emit({key:"updates",payload:{counts:s}})}catch{}finally{this.running=!1}}}onSubscriberJoin(){this.lastCounts!==null&&(this.lastFingerprint=JSON.stringify(this.lastCounts),this.bus.emit({key:"updates",payload:{counts:this.lastCounts}})),this.refreshNow(!0)}}
@@ -10,6 +10,7 @@ import { type MirrorWriter } from '../hooks/mirror.js';
10
10
  import type { HookDispatcher } from '../hooks/dispatcher.js';
11
11
  import type { HookEventBus } from '../hooks/bus.js';
12
12
  import type { DataBus } from './data-bus.js';
13
+ import { SseHub } from './sse-hub.js';
13
14
  import type { TerminalTopologyRefresher } from './terminal-topology-refresher.js';
14
15
  import type { InflightCountsRefresher } from './inflight-counts-refresher.js';
15
16
  import type { SnapshotRefresher } from './snapshot-refresher.js';
@@ -18,6 +19,7 @@ import type { ProjectUpdatesRefresher } from './project-updates-refresher.js';
18
19
  import type { ResumeRunner } from '../hooks/resume-runner.js';
19
20
  import type { MessageDeliverer } from '../hooks/message-deliverer.js';
20
21
  import type { QuestionTracker } from '../hooks/question-tracker.js';
22
+ import type { SideQuestionDeps } from '../hooks/side-questions.js';
21
23
  import type { WatchEngine } from '../hooks/watch-engine.js';
22
24
  import type { SessionWatchRepository } from '../repositories/session-watches.js';
23
25
  import type { PushSubscriptionRepository } from '../repositories/push-subscriptions.js';
@@ -26,8 +28,10 @@ import type { SessionSequenceRepository } from '../repositories/session-sequence
26
28
  import type { SequenceEngine } from '../hooks/sequence-engine.js';
27
29
  import type { PluginManager } from '../hooks/plugin-loader.js';
28
30
  import type { PluginStateRepository } from '../repositories/plugin-states.js';
31
+ import type { UploadRepository } from '../repositories/uploads.js';
29
32
  import type { WatchService } from '../watch/watch-service.js';
30
33
  import { FingerprintCache } from '../install/fingerprint.js';
34
+ import { ApiLogger } from './api-log.js';
31
35
  import { type ToolkitService } from '../hooks/toolkit.js';
32
36
  import { type ProjectOpener } from './opener.js';
33
37
  import type { AuthService } from './dashboard-auth.js';
@@ -52,6 +56,8 @@ export interface WeaveServerDeps {
52
56
  libraries?: LibraryRepository;
53
57
  /** Content-fingerprint cache for update detection; created if absent. */
54
58
  fingerprintCache?: FingerprintCache;
59
+ /** 接口日志(出入参 + 耗时按小时 JSONL;GET /api-logs 查询);缺省 <dataDir>/logs/api。 */
60
+ apiLog?: ApiLogger;
55
61
  /** Directory of the built SPA to statically host; optional. */
56
62
  staticDir?: string;
57
63
  /** Directory-opening backend for the project context menu; spied in tests. */
@@ -68,10 +74,14 @@ export interface WeaveServerDeps {
68
74
  hookBus?: HookEventBus;
69
75
  /** 数据变更帧总线(SSE 第三订阅源:载荷推送 / 失效键)。 */
70
76
  dataBus?: DataBus;
77
+ /** 事件流中枢(编号 + 环形缓冲 + 扇出):weaveRequestHandler 建一份,两监听共享。 */
78
+ sseHub?: SseHub;
71
79
  /** 终端世界(角标计数 + 会话所在屏幕)的后端隐藏刷新器;缺省则该角标只能靠前端自拉(兼容旧装配)。 */
72
80
  terminalRefresher?: TerminalTopologyRefresher;
73
81
  /** 会话中断态快照刷新器(ESC 打断后多数连 Stop 都不发):中断成功后即时补一拍。 */
74
82
  interruptRefresher?: SnapshotRefresher;
83
+ /** 会话判活快照刷新器(关 pane 后进程死掉同样无 hook 事件):关完即时补一拍。 */
84
+ livenessRefresher?: SnapshotRefresher;
75
85
  /** 会话转录探测(中断态判据):GET /sessions 逐行现算;缺省不带该字段。 */
76
86
  sessionProbe?: SessionProbe;
77
87
  /** 在途消息角标(会话行)的推送器:新 SSE 客户端接入时补一份首帧快照。 */
@@ -84,8 +94,13 @@ export interface WeaveServerDeps {
84
94
  hookRunner?: ResumeRunner;
85
95
  /** 消息域投递器(消息域重塑:纯管道裁决 + prompt 三层);/sessions/:id/messages 依赖它。 */
86
96
  messageDeliverer?: MessageDeliverer;
97
+ /** 会话图片上传件(内容寻址落盘 + event_images 指针);/uploads 与 /images/:id 依赖它。 */
98
+ uploads?: UploadRepository;
87
99
  /** 阻塞问答跟踪器(AskUserQuestion / 计划与权限确认);/messaging/questions 与 /sessions/:id/answer 依赖它。 */
88
100
  questionTracker?: QuestionTracker;
101
+ /** 旁路会话历史(claude = /btw):问句只有 weave 自己发过才知道,故得自己记;
102
+ * `/sessions/:id/side-question(s)` 与删会话级联依赖它。 */
103
+ sideQuestions?: SideQuestionDeps;
89
104
  /** 空闲订阅存储(批 2);POST/DELETE /sessions/:id/watch 与 GET /messaging/watches 依赖它。 */
90
105
  sessionWatches?: SessionWatchRepository;
91
106
  /** Web Push 订阅存储;POST /messaging/push/(un)subscribe 依赖它。 */