@weavecode/weave 0.1.4 → 0.1.6

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 (362) hide show
  1. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/encodeurl/README.md +14 -0
  2. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/encodeurl/index.js +5 -10
  3. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/encodeurl/package.json +10 -6
  4. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/CHANGELOG.md +42 -0
  5. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/README.md +38 -10
  6. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/dist/qs.js +18 -18
  7. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/lib/parse.js +16 -4
  8. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/lib/utils.js +13 -2
  9. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/package.json +1 -1
  10. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.cjs +6 -2
  11. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.mjs +6 -2
  12. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/package.json +10 -10
  13. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/decrypt.d.ts +3 -0
  14. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/unsecured.d.ts +2 -0
  15. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/verify.d.ts +3 -0
  16. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/types.d.ts +8 -0
  17. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/util/decode_jwt.d.ts +1 -0
  18. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/remote.js +1 -1
  19. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/package.json +1 -1
  20. package/node_modules/@weavecode/cli/dist/cli.js +4 -4
  21. package/node_modules/@weavecode/cli/dist/commands/chpass.js +1 -1
  22. package/node_modules/@weavecode/cli/dist/commands/daemon-auth.js +1 -1
  23. package/node_modules/@weavecode/cli/dist/commands/daemon.d.ts +2 -0
  24. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  25. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -2
  26. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  27. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  28. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  29. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  30. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  31. package/node_modules/@weavecode/cli/dist/commands/uninstall.js +1 -1
  32. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +4 -4
  33. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +5 -1
  34. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +5 -5
  35. package/node_modules/@weavecode/cli/dist/i18n/index.js +1 -1
  36. package/node_modules/@weavecode/cli/dist/i18n/t.js +1 -1
  37. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +3 -3
  38. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  39. package/node_modules/@weavecode/cli/dist/init/git-commit.js +2 -2
  40. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  41. package/node_modules/@weavecode/cli/dist/init/harnesses/codex.js +1 -1
  42. package/node_modules/@weavecode/cli/dist/init/instruction-link.js +1 -1
  43. package/node_modules/@weavecode/cli/dist/init/plugin-templates.js +1 -1
  44. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  45. package/node_modules/@weavecode/cli/dist/init/provision.js +1 -1
  46. package/node_modules/@weavecode/cli/dist/init/uninstall.js +6 -6
  47. package/node_modules/@weavecode/cli/dist/init/wiring.js +1 -1
  48. package/node_modules/@weavecode/cli/dist/parser.js +1 -1
  49. package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
  50. package/node_modules/@weavecode/cli/dist/statusline/mock-input.js +1 -1
  51. package/node_modules/@weavecode/cli/dist/statusline/preview.js +2 -2
  52. package/node_modules/@weavecode/cli/package.json +5 -5
  53. package/node_modules/@weavecode/core/dist/harness-checks.js +1 -1
  54. package/node_modules/@weavecode/core/dist/harness.d.ts +14 -0
  55. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  56. package/node_modules/@weavecode/core/dist/index.d.ts +1 -1
  57. package/node_modules/@weavecode/core/dist/index.js +1 -1
  58. package/node_modules/@weavecode/core/dist/platform.js +1 -1
  59. package/node_modules/@weavecode/core/dist/types.js +1 -1
  60. package/node_modules/@weavecode/core/dist/utils/fs.js +1 -1
  61. package/node_modules/@weavecode/core/dist/utils/logger.js +1 -1
  62. package/node_modules/@weavecode/core/package.json +1 -1
  63. package/node_modules/@weavecode/harness/dist/claude/assets.js +4 -4
  64. package/node_modules/@weavecode/harness/dist/claude/capture.js +9 -9
  65. package/node_modules/@weavecode/harness/dist/claude/commands.d.ts +3 -0
  66. package/node_modules/@weavecode/harness/dist/claude/commands.js +2 -3
  67. package/node_modules/@weavecode/harness/dist/claude/config.js +2 -2
  68. package/node_modules/@weavecode/harness/dist/claude/detect.js +1 -1
  69. package/node_modules/@weavecode/harness/dist/claude/edits.js +1 -1
  70. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  71. package/node_modules/@weavecode/harness/dist/claude/images.js +2 -2
  72. package/node_modules/@weavecode/harness/dist/claude/index.d.ts +1 -0
  73. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  74. package/node_modules/@weavecode/harness/dist/claude/liveness.js +1 -1
  75. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -1
  76. package/node_modules/@weavecode/harness/dist/claude/messaging.js +2 -2
  77. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -1
  78. package/node_modules/@weavecode/harness/dist/claude/narration.d.ts +0 -11
  79. package/node_modules/@weavecode/harness/dist/claude/narration.js +1 -1
  80. package/node_modules/@weavecode/harness/dist/claude/peers.js +1 -1
  81. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -1
  82. package/node_modules/@weavecode/harness/dist/claude/plugins.js +4 -4
  83. package/node_modules/@weavecode/harness/dist/claude/prompt-inbox.js +1 -1
  84. package/node_modules/@weavecode/harness/dist/claude/prompt.js +3 -3
  85. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -2
  86. package/node_modules/@weavecode/harness/dist/claude/resume.js +1 -1
  87. package/node_modules/@weavecode/harness/dist/claude/rewind.d.ts +8 -0
  88. package/node_modules/@weavecode/harness/dist/claude/rewind.js +1 -0
  89. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -1
  90. package/node_modules/@weavecode/harness/dist/claude/side-question.js +2 -2
  91. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +39 -18
  92. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -1
  93. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -2
  94. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.d.ts +26 -0
  95. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.js +2 -0
  96. package/node_modules/@weavecode/harness/dist/claude/transcript.js +7 -7
  97. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  98. package/node_modules/@weavecode/harness/dist/codex/capture.js +2 -2
  99. package/node_modules/@weavecode/harness/dist/codex/commands.js +4 -4
  100. package/node_modules/@weavecode/harness/dist/codex/config.js +2 -2
  101. package/node_modules/@weavecode/harness/dist/codex/detect.js +1 -1
  102. package/node_modules/@weavecode/harness/dist/codex/event-source.js +2 -2
  103. package/node_modules/@weavecode/harness/dist/codex/images.js +1 -1
  104. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  105. package/node_modules/@weavecode/harness/dist/codex/liveness.js +1 -1
  106. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -1
  107. package/node_modules/@weavecode/harness/dist/codex/messaging.js +2 -2
  108. package/node_modules/@weavecode/harness/dist/codex/narration.js +1 -1
  109. package/node_modules/@weavecode/harness/dist/codex/plugin-state.js +1 -1
  110. package/node_modules/@weavecode/harness/dist/codex/plugins.js +3 -3
  111. package/node_modules/@weavecode/harness/dist/codex/provision.js +1 -1
  112. package/node_modules/@weavecode/harness/dist/codex/questions.js +2 -2
  113. package/node_modules/@weavecode/harness/dist/codex/rollout.js +5 -5
  114. package/node_modules/@weavecode/harness/dist/codex/side-question.js +4 -4
  115. package/node_modules/@weavecode/harness/dist/codex/titles.js +4 -4
  116. package/node_modules/@weavecode/harness/dist/codex/toml.js +13 -13
  117. package/node_modules/@weavecode/harness/dist/codex/transcript.js +2 -2
  118. package/node_modules/@weavecode/harness/dist/driver.d.ts +49 -1
  119. package/node_modules/@weavecode/harness/dist/driver.js +1 -1
  120. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -2
  121. package/node_modules/@weavecode/harness/dist/init/pipeline.js +1 -1
  122. package/node_modules/@weavecode/harness/dist/registry-wiring.js +1 -1
  123. package/node_modules/@weavecode/harness/dist/shared/install-link.js +1 -1
  124. package/node_modules/@weavecode/harness/dist/shared/json-cap.js +1 -1
  125. package/node_modules/@weavecode/harness/package.json +2 -2
  126. package/node_modules/@weavecode/server/dist/config/dotted.js +1 -1
  127. package/node_modules/@weavecode/server/dist/config/profiles.d.ts +19 -13
  128. package/node_modules/@weavecode/server/dist/config/profiles.js +2 -2
  129. package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
  130. package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
  131. package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
  132. package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -3
  133. package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
  134. package/node_modules/@weavecode/server/dist/daemon/auto-start.js +6 -6
  135. package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
  136. package/node_modules/@weavecode/server/dist/daemon/config-routes.js +1 -1
  137. package/node_modules/@weavecode/server/dist/daemon/cron.js +1 -1
  138. package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
  139. package/node_modules/@weavecode/server/dist/daemon/dashboard-pusher.js +1 -1
  140. package/node_modules/@weavecode/server/dist/daemon/data-bus.js +1 -1
  141. package/node_modules/@weavecode/server/dist/daemon/decision-config.js +2 -2
  142. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  143. package/node_modules/@weavecode/server/dist/daemon/entry.js +7 -1
  144. package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
  145. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
  146. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  147. package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
  148. package/node_modules/@weavecode/server/dist/daemon/liveness.js +1 -1
  149. package/node_modules/@weavecode/server/dist/daemon/mcp-orchestration.js +1 -1
  150. package/node_modules/@weavecode/server/dist/daemon/narration-watcher.js +2 -2
  151. package/node_modules/@weavecode/server/dist/daemon/opener/backend-ghostty.js +1 -1
  152. package/node_modules/@weavecode/server/dist/daemon/opener/backend-iterm.js +1 -1
  153. package/node_modules/@weavecode/server/dist/daemon/opener/backend-konsole.js +2 -2
  154. package/node_modules/@weavecode/server/dist/daemon/opener/backend-terminal-app.js +1 -1
  155. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wezterm.js +1 -1
  156. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wt.js +1 -1
  157. package/node_modules/@weavecode/server/dist/daemon/opener/backend.js +1 -1
  158. package/node_modules/@weavecode/server/dist/daemon/opener/launch.js +1 -1
  159. package/node_modules/@weavecode/server/dist/daemon/opener/pty-terminals.js +4 -4
  160. package/node_modules/@weavecode/server/dist/daemon/opener/shared.js +1 -1
  161. package/node_modules/@weavecode/server/dist/daemon/opener/wezterm-mux.js +1 -1
  162. package/node_modules/@weavecode/server/dist/daemon/opener/wt.js +3 -3
  163. package/node_modules/@weavecode/server/dist/daemon/opener.d.ts +2 -0
  164. package/node_modules/@weavecode/server/dist/daemon/opener.js +1 -1
  165. package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
  166. package/node_modules/@weavecode/server/dist/daemon/project-files.d.ts +12 -6
  167. package/node_modules/@weavecode/server/dist/daemon/project-files.js +2 -2
  168. package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
  169. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
  170. package/node_modules/@weavecode/server/dist/daemon/prompt-images.js +1 -1
  171. package/node_modules/@weavecode/server/dist/daemon/routes/hooks-admin.js +1 -1
  172. package/node_modules/@weavecode/server/dist/daemon/routes/market.js +1 -1
  173. package/node_modules/@weavecode/server/dist/daemon/routes/orchestration.js +1 -1
  174. package/node_modules/@weavecode/server/dist/daemon/routes/path-refs.js +1 -1
  175. package/node_modules/@weavecode/server/dist/daemon/routes/project-files.js +1 -1
  176. package/node_modules/@weavecode/server/dist/daemon/routes/projects.js +1 -1
  177. package/node_modules/@weavecode/server/dist/daemon/routes/search.js +1 -1
  178. package/node_modules/@weavecode/server/dist/daemon/routes/session-control.js +1 -1
  179. package/node_modules/@weavecode/server/dist/daemon/routes/session-insights.js +1 -1
  180. package/node_modules/@weavecode/server/dist/daemon/routes/settings-statusline.js +1 -1
  181. package/node_modules/@weavecode/server/dist/daemon/routes/uploads.js +1 -1
  182. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.d.ts +3 -0
  183. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.js +1 -0
  184. package/node_modules/@weavecode/server/dist/daemon/routes/watches.js +1 -1
  185. package/node_modules/@weavecode/server/dist/daemon/server.js +8 -8
  186. package/node_modules/@weavecode/server/dist/daemon/session-open.js +1 -1
  187. package/node_modules/@weavecode/server/dist/daemon/session-probe.d.ts +5 -4
  188. package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
  189. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  190. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.js +1 -1
  191. package/node_modules/@weavecode/server/dist/daemon/sse-hub.js +1 -1
  192. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  193. package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
  194. package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
  195. package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.js +1 -1
  196. package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
  197. package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
  198. package/node_modules/@weavecode/server/dist/daemon/upload-sessions.js +1 -1
  199. package/node_modules/@weavecode/server/dist/db/db.js +6 -2
  200. package/node_modules/@weavecode/server/dist/db/layout.js +1 -1
  201. package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
  202. package/node_modules/@weavecode/server/dist/hooks/bus.d.ts +3 -1
  203. package/node_modules/@weavecode/server/dist/hooks/bus.js +1 -1
  204. package/node_modules/@weavecode/server/dist/hooks/dashboard-rate.js +1 -1
  205. package/node_modules/@weavecode/server/dist/hooks/decision-judge.js +1 -1
  206. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.d.ts +12 -6
  207. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.js +1 -1
  208. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.d.ts +3 -3
  209. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.js +1 -1
  210. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.d.ts +19 -9
  211. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.js +1 -1
  212. package/node_modules/@weavecode/server/dist/hooks/delivery/queue.js +1 -1
  213. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.d.ts +2 -2
  214. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.js +1 -1
  215. package/node_modules/@weavecode/server/dist/hooks/delivery/send.js +2 -2
  216. package/node_modules/@weavecode/server/dist/hooks/delivery/views.d.ts +3 -1
  217. package/node_modules/@weavecode/server/dist/hooks/delivery/views.js +1 -1
  218. package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
  219. package/node_modules/@weavecode/server/dist/hooks/edge-extract.js +1 -1
  220. package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
  221. package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
  222. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -2
  223. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
  224. package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
  225. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.d.ts +45 -38
  226. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +5 -3
  227. package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
  228. package/node_modules/@weavecode/server/dist/hooks/orchestration-engine.js +7 -7
  229. package/node_modules/@weavecode/server/dist/hooks/orchestration-graph.js +1 -1
  230. package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
  231. package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
  232. package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
  233. package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
  234. package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
  235. package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
  236. package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
  237. package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
  238. package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
  239. package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
  240. package/node_modules/@weavecode/server/dist/hooks/side-questions.js +1 -1
  241. package/node_modules/@weavecode/server/dist/hooks/synthetic-sessions.js +1 -1
  242. package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
  243. package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
  244. package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
  245. package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
  246. package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
  247. package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
  248. package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
  249. package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
  250. package/node_modules/@weavecode/server/dist/install/global-config.js +1 -1
  251. package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
  252. package/node_modules/@weavecode/server/dist/install/init-files.js +2 -2
  253. package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
  254. package/node_modules/@weavecode/server/dist/install/installer.js +1 -1
  255. package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
  256. package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
  257. package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
  258. package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
  259. package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
  260. package/node_modules/@weavecode/server/dist/install/project-config.js +1 -1
  261. package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
  262. package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
  263. package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
  264. package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
  265. package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
  266. package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
  267. package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
  268. package/node_modules/@weavecode/server/dist/market/import.js +2 -2
  269. package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
  270. package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
  271. package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
  272. package/node_modules/@weavecode/server/dist/registry.js +2 -2
  273. package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +5 -5
  274. package/node_modules/@weavecode/server/dist/repositories/hook-events.d.ts +1 -1
  275. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +5 -5
  276. package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
  277. package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
  278. package/node_modules/@weavecode/server/dist/repositories/orchestrations.js +7 -7
  279. package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
  280. package/node_modules/@weavecode/server/dist/repositories/projects.js +2 -2
  281. package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
  282. package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
  283. package/node_modules/@weavecode/server/dist/repositories/sessions.d.ts +11 -1
  284. package/node_modules/@weavecode/server/dist/repositories/sessions.js +4 -2
  285. package/node_modules/@weavecode/server/dist/repositories/uploads.d.ts +14 -4
  286. package/node_modules/@weavecode/server/dist/repositories/uploads.js +11 -11
  287. package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
  288. package/node_modules/@weavecode/server/dist/statusline/generator.js +1 -1
  289. package/node_modules/@weavecode/server/dist/statusline/manager.js +3 -3
  290. package/node_modules/@weavecode/server/dist/surfaces.d.ts +3 -1
  291. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  292. package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
  293. package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
  294. package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
  295. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
  296. package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
  297. package/node_modules/@weavecode/server/package.json +4 -4
  298. package/node_modules/@weavecode/server/web/dist/assets/{abnfDiagram-WEYOIA3C-DA-K085F.js → abnfDiagram-WEYOIA3C-CbIFQh0R.js} +1 -1
  299. package/node_modules/@weavecode/server/web/dist/assets/{arc-BI1jnmdZ.js → arc-DH8-rYAa.js} +1 -1
  300. package/node_modules/@weavecode/server/web/dist/assets/{architectureDiagram-ZHVYKT53-DbdBgric.js → architectureDiagram-ZHVYKT53-qnv6S0sc.js} +1 -1
  301. package/node_modules/@weavecode/server/web/dist/assets/{blockDiagram-RJAE7QA3-BPRBmzb-.js → blockDiagram-RJAE7QA3-pT5eO-cB.js} +1 -1
  302. package/node_modules/@weavecode/server/web/dist/assets/{c4Diagram-XDPPPE54-C4D5sRs1.js → c4Diagram-XDPPPE54-DHDBDMb1.js} +1 -1
  303. package/node_modules/@weavecode/server/web/dist/assets/channel-BHPeeuzN.js +1 -0
  304. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2E7WHVMD-9ZSKiNU3.js → chunk-2E7WHVMD-CT951PH5.js} +1 -1
  305. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2Q5K7J3B-i0AOjw_8.js → chunk-2Q5K7J3B-E5AD7_ZY.js} +1 -1
  306. package/node_modules/@weavecode/server/web/dist/assets/{chunk-4EMNKR2T-DTpLfX1H.js → chunk-4EMNKR2T-DWz9qkcy.js} +1 -1
  307. package/node_modules/@weavecode/server/web/dist/assets/{chunk-55XCU76K-COQYRD4q.js → chunk-55XCU76K-D-SgWD8w.js} +1 -1
  308. package/node_modules/@weavecode/server/web/dist/assets/{chunk-5VM5RSS4-VsftEbvo.js → chunk-5VM5RSS4-ci6YzbO5.js} +1 -1
  309. package/node_modules/@weavecode/server/web/dist/assets/{chunk-JWPE2WC7-DonektJN.js → chunk-JWPE2WC7-CY4mr2f4.js} +1 -1
  310. package/node_modules/@weavecode/server/web/dist/assets/{chunk-VQ5W62QI-CaKUwuul.js → chunk-VQ5W62QI-CON8zyg8.js} +1 -1
  311. package/node_modules/@weavecode/server/web/dist/assets/{chunk-XXDRQBXY-DXH3D_MT.js → chunk-XXDRQBXY-DXXXZ4pW.js} +1 -1
  312. package/node_modules/@weavecode/server/web/dist/assets/{chunk-ZCHMQSOR-COwyAuGn.js → chunk-ZCHMQSOR-CukvPvkM.js} +2 -2
  313. package/node_modules/@weavecode/server/web/dist/assets/{classDiagram-v2-4MYWR3UA-DEvMZ6mX.js → classDiagram-v2-4MYWR3UA-GiWZ9xtF.js} +1 -1
  314. package/node_modules/@weavecode/server/web/dist/assets/{cose-bilkent-JH36ORCC-6JBJHfH6.js → cose-bilkent-JH36ORCC-D7aJ-akq.js} +1 -1
  315. package/node_modules/@weavecode/server/web/dist/assets/{cynefin-EF2NZ3EQ-C4GM4sjT.js → cynefin-EF2NZ3EQ-9B__MaRM.js} +1 -1
  316. package/node_modules/@weavecode/server/web/dist/assets/{cynefinDiagram-WF24UDRP-Cqgi0MBP.js → cynefinDiagram-WF24UDRP-B2ujZh2k.js} +1 -1
  317. package/node_modules/@weavecode/server/web/dist/assets/{dagre-NK4GIZVX-CljrnkCY.js → dagre-NK4GIZVX-nHaB6IWf.js} +1 -1
  318. package/node_modules/@weavecode/server/web/dist/assets/{diagram-CBK3MWTC-C3PyOj5J.js → diagram-CBK3MWTC-xKfjDvgr.js} +1 -1
  319. package/node_modules/@weavecode/server/web/dist/assets/{diagram-I5XIIV2D-I5brQlaZ.js → diagram-I5XIIV2D-BHT2-5mY.js} +1 -1
  320. package/node_modules/@weavecode/server/web/dist/assets/{diagram-ODIL2UCW-BX9uFNbU.js → diagram-ODIL2UCW-CckywF4W.js} +1 -1
  321. package/node_modules/@weavecode/server/web/dist/assets/{diagram-PFBEJUXE-y7D-VmqJ.js → diagram-PFBEJUXE-Dpjlc7Wh.js} +1 -1
  322. package/node_modules/@weavecode/server/web/dist/assets/{diagram-RJA3I4VV-DLUL8W42.js → diagram-RJA3I4VV-M6WznOaW.js} +1 -1
  323. package/node_modules/@weavecode/server/web/dist/assets/{diagram-TYUNFSNR-DLCC3ILi.js → diagram-TYUNFSNR-DgRJ3zL1.js} +1 -1
  324. package/node_modules/@weavecode/server/web/dist/assets/{ebnfDiagram-V4P3TTPT-D7vALia7.js → ebnfDiagram-V4P3TTPT-BzzVN__a.js} +1 -1
  325. package/node_modules/@weavecode/server/web/dist/assets/{elk-QONTBCTQ-Ct2_hatz.js → elk-QONTBCTQ-Ch6Gs9G9.js} +1 -1
  326. package/node_modules/@weavecode/server/web/dist/assets/{erDiagram-KYQIGQAA-DxLai58T.js → erDiagram-KYQIGQAA-COxT-Pxb.js} +1 -1
  327. package/node_modules/@weavecode/server/web/dist/assets/{flowDiagram-IUGLLWBU-AWn2IHrF.js → flowDiagram-IUGLLWBU-CJVWnTBa.js} +1 -1
  328. package/node_modules/@weavecode/server/web/dist/assets/{ganttDiagram-R7GPNTJY-DmRHd4Wz.js → ganttDiagram-R7GPNTJY-BkRpWPUl.js} +1 -1
  329. package/node_modules/@weavecode/server/web/dist/assets/{gitGraphDiagram-PDYL7XHY-Ccj-t3zg.js → gitGraphDiagram-PDYL7XHY-Ba8BJcvZ.js} +1 -1
  330. package/node_modules/@weavecode/server/web/dist/assets/index-CtifxEiF.css +11 -0
  331. package/node_modules/@weavecode/server/web/dist/assets/index-FwH9INgS.js +1090 -0
  332. package/node_modules/@weavecode/server/web/dist/assets/{infoDiagram-MVDRKAX5-BHquFlQa.js → infoDiagram-MVDRKAX5-HTQ5FUNK.js} +1 -1
  333. package/node_modules/@weavecode/server/web/dist/assets/{ishikawaDiagram-HPEHV2GE-CVogEbdm.js → ishikawaDiagram-HPEHV2GE-BNjEDIZy.js} +1 -1
  334. package/node_modules/@weavecode/server/web/dist/assets/{journeyDiagram-BOSHW7O7-DC9XG9oh.js → journeyDiagram-BOSHW7O7-Cao6h91a.js} +1 -1
  335. package/node_modules/@weavecode/server/web/dist/assets/{kanban-definition-FNSA4HC5-C_eu7DC_.js → kanban-definition-FNSA4HC5-CXIx2CHQ.js} +1 -1
  336. package/node_modules/@weavecode/server/web/dist/assets/{linear-keTbWHJ-.js → linear-65WmlvQb.js} +1 -1
  337. package/node_modules/@weavecode/server/web/dist/assets/{mermaid.core-4sbg0MnY.js → mermaid.core-D39fi_iR.js} +4 -4
  338. package/node_modules/@weavecode/server/web/dist/assets/{mindmap-definition-6OY57UG3-kMQS0S2l.js → mindmap-definition-6OY57UG3-DHqpz_AK.js} +1 -1
  339. package/node_modules/@weavecode/server/web/dist/assets/{pegDiagram-ECIUJNBX-DcUFoEwP.js → pegDiagram-ECIUJNBX-Cpy1nsER.js} +1 -1
  340. package/node_modules/@weavecode/server/web/dist/assets/{pieDiagram-GNMPY74T-BQJ7WDCx.js → pieDiagram-GNMPY74T-B1IyNqzr.js} +1 -1
  341. package/node_modules/@weavecode/server/web/dist/assets/{quadrantDiagram-D57K4MC3-C7Oi1-sq.js → quadrantDiagram-D57K4MC3-zSM6o7mB.js} +1 -1
  342. package/node_modules/@weavecode/server/web/dist/assets/{railroadDiagram-Y72NRBL7-CEF2QbOF.js → railroadDiagram-Y72NRBL7-oM4XJIwA.js} +1 -1
  343. package/node_modules/@weavecode/server/web/dist/assets/{requirementDiagram-EQYSW5RA-CTjjFS7X.js → requirementDiagram-EQYSW5RA-CbCLBjHf.js} +1 -1
  344. package/node_modules/@weavecode/server/web/dist/assets/{sankeyDiagram-SY24JHO5-j0S5kubS.js → sankeyDiagram-SY24JHO5-BucVk6EP.js} +1 -1
  345. package/node_modules/@weavecode/server/web/dist/assets/{sequenceDiagram-BLEHNHQU-B76EsZp4.js → sequenceDiagram-BLEHNHQU-Dg8CYEnT.js} +1 -1
  346. package/node_modules/@weavecode/server/web/dist/assets/{sizeCapture-INFHLROL-r0DZuqAy.js → sizeCapture-INFHLROL-C51zb7Oc.js} +1 -1
  347. package/node_modules/@weavecode/server/web/dist/assets/{stateDiagram-v2-A6IESKWZ-B4DR9LHz.js → stateDiagram-v2-A6IESKWZ-BvK2l3is.js} +1 -1
  348. package/node_modules/@weavecode/server/web/dist/assets/{swimlanes-B3ENRKFQ-Dbcl85ro.js → swimlanes-B3ENRKFQ-Ds7QOfXW.js} +1 -1
  349. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-ByBF02UJ.js +8 -0
  350. package/node_modules/@weavecode/server/web/dist/assets/{timeline-definition-JXYKGLGB-BlBXXRNf.js → timeline-definition-JXYKGLGB-CadU4Qq4.js} +1 -1
  351. package/node_modules/@weavecode/server/web/dist/assets/{usecaseDiagram-WPOLBNNX-Ck1M0dpc.js → usecaseDiagram-WPOLBNNX-BYuZwTDZ.js} +1 -1
  352. package/node_modules/@weavecode/server/web/dist/assets/{vennDiagram-Q3Y3IDCW-N8B-ohWk.js → vennDiagram-Q3Y3IDCW-C7zgxe07.js} +1 -1
  353. package/node_modules/@weavecode/server/web/dist/assets/{wardleyDiagram-IVAIDKWA-DX-AMXq_.js → wardleyDiagram-IVAIDKWA-DA4Otf4s.js} +1 -1
  354. package/node_modules/@weavecode/server/web/dist/assets/{xychartDiagram-4URNHDU4-4fgL48Yl.js → xychartDiagram-4URNHDU4-Bs5YGwMU.js} +1 -1
  355. package/node_modules/@weavecode/server/web/dist/index.html +2 -2
  356. package/node_modules/@weavecode/server/web/dist/sw.js +14 -12
  357. package/node_modules/@weavecode/templates/package.json +2 -2
  358. package/package.json +6 -6
  359. package/node_modules/@weavecode/server/web/dist/assets/channel-DcCJrvon.js +0 -1
  360. package/node_modules/@weavecode/server/web/dist/assets/index-BSxzia7U.js +0 -1031
  361. package/node_modules/@weavecode/server/web/dist/assets/index-CEpJpR7P.css +0 -11
  362. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-CZ_6SSBd.js +0 -8
@@ -1 +1 @@
1
- import{claudeLivenessById as s}from"./claude-liveness.js";import{codexLivenessById as c}from"@weavecode/harness";const i=15e3;let o=new Map;async function a(n){try{o=await c(void 0,n)}catch{}}let e=null;function f(){e||(e=setInterval(()=>{a(Date.now())},i),e.unref())}export function combinedLivenessOf(){f();const n=s();for(const[t,r]of o)n.set(t,r);return n}export function resetCombinedLivenessForTest(){e&&(clearInterval(e),e=null),o=new Map}
1
+ import{claudeLivenessById as r}from"./claude-liveness.js";import{codexLivenessById as c}from"@weavecode/harness";const i=15e3;let t=new Map;async function a(n){try{t=await c(void 0,n)}catch{}}let e=null;function f(){e||(e=setInterval(()=>{a(Date.now())},i),e.unref())}export function combinedLivenessOf(){f();const n=r();for(const[o,s]of t)n.set(o,s);return n}export function resetCombinedLivenessForTest(){e&&(clearInterval(e),e=null),t=new Map}
@@ -1 +1 @@
1
- import{Server as b}from"@modelcontextprotocol/sdk/server/index.js";import{StreamableHTTPServerTransport as f}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as g,ListToolsRequestSchema as S}from"@modelcontextprotocol/sdk/types.js";import{readBody as j,sendJson as w}from"./http.js";async function a(t,n,e,o){const r=await fetch(`http://127.0.0.1:${t.port}/api${e}`,{method:n,headers:{...t.token?{"x-weave-local":t.token}:{},...o===void 0?{}:{"content-type":"application/json"}},...o===void 0?{}:{body:JSON.stringify(o)}}),s=await r.text(),p=(()=>{try{return JSON.parse(s)}catch{return{raw:s}}})();if(!r.ok){const l=p&&typeof p=="object"&&"error"in p?String(p.error):`HTTP ${r.status}`;throw new Error(l)}return p}const d=t=>{const n=new URLSearchParams;for(const[o,r]of Object.entries(t))r!==void 0&&r!==""&&n.set(o,String(r));const e=n.toString();return e?`?${e}`:""},u={type:"object",required:["id","kind"],properties:{id:{type:"string",description:'session id, or "w:<uuid>" for a webhook node'},kind:{type:"string",enum:["session","webhook"]},webhookToken:{type:"string"},url:{type:"string",description:"webhook exit: outbound URL"},secret:{type:"string",description:"webhook exit: optional HMAC secret"}}},m={type:"object",required:["id","from","to","text"],properties:{id:{type:"string"},from:{type:"string"},to:{type:"string"},text:{type:"string",description:"message body; {upstream}/{summary}/{session} are substituted"},extract:{type:"string",description:"optional extraction prompt for {summary}"}}},c={type:"object",additionalProperties:!0},h={type:"object",additionalProperties:!0},k=[{name:"list_orchestrations",description:"List orchestrations (optionally by project). Returns { orchestrations: OrchestrationRow[] }; each row has id/name/projectId/startText/nodes/edges/enabled/cron/nextRunAt.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{orchestrations:{type:"array",items:c}},required:["orchestrations"]}},{name:"get_orchestration",description:"Get one orchestration definition (nodes, edges, startText, cron, enabled). Returns { orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{orchestration:c},required:["orchestration"]}},{name:"create_orchestration",description:"Create an orchestration. enabled defaults to true, which makes the entry session auto-fire the graph on EVERY natural turn \u2014 pass enabled:false when the run should be triggered manually. Edges support {upstream}/{summary}/{session}; a cycle is rejected. Returns { ok, orchestration }.",inputSchema:{type:"object",required:["name","nodes","edges"],properties:{name:{type:"string"},startText:{type:"string",description:"first message for session entries (manual trigger)"},projectId:{type:"number",description:"webhook-only orchestrations"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"update_orchestration",description:"Update part of an orchestration (omit fields to keep them; changing the graph does not affect a run already in flight). Returns { ok, orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},name:{type:"string"},startText:{type:"string"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"delete_orchestration",description:"Delete a definition. Run history (orchestration_runs) is kept. Returns { ok, orchestrationId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestrationId:{type:"number"}},required:["ok","orchestrationId"]}},{name:"trigger_orchestration",description:"Start a run. Manual trigger works even when enabled=false. Optional text overrides startText; entries restricts which entry nodes run. Dead target sessions are opened automatically, and delivery waits for their SessionStart. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},text:{type:"string"},entries:{type:"array",items:{type:"string"}}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_runs",description:"List runs, newest first. Returns { runs: RunSummary[], nextBefore }. RunSummary has id/orchestrationId/name/status/deliveries/pendingCounts/createdAt.",inputSchema:{type:"object",properties:{orchestrationId:{type:"number"},projectId:{type:"number"},status:{type:"string"},limit:{type:"number"},before:{type:"number"}}},outputSchema:{type:"object",properties:{runs:{type:"array",items:h},nextBefore:{type:["number","null"]}},required:["runs"]}},{name:"get_run",description:'Get a run with state.events (deliveries and stage:"ensure" opens) and state.pending per session. Returns { run }. status becomes interrupted when the daemon restarts (runs are not resumed).',inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{run:h},required:["run"]}},{name:"cancel_run",description:"Cancel a running run. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_sessions",description:"List sessions for picking graph nodes; minimal fields only (sessionId/projectId/title/harness/lastSeenAt/turnOpen/pidAlive). Returns { sessions }.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{sessions:{type:"array",items:{type:"object",additionalProperties:!0}}},required:["sessions"]}}],i=t=>typeof t=="number"?t:void 0,y=t=>typeof t=="string"?t:void 0;async function I(t,n,e){switch(n){case"list_orchestrations":return a(t,"GET",`/messaging/orchestrations${d({projectId:i(e.projectId)})}`);case"get_orchestration":{const r=(await a(t,"GET","/messaging/orchestrations")).orchestrations.find(s=>s.id===i(e.id));if(!r)throw new Error(`Orchestration not found: ${String(e.id)}`);return{orchestration:r}}case"create_orchestration":return a(t,"POST","/messaging/orchestrations",{name:e.name,startText:e.startText,projectId:i(e.projectId),nodes:e.nodes,edges:e.edges,cron:e.cron??null,enabled:e.enabled});case"update_orchestration":{const o=i(e.id);return a(t,"PUT",`/messaging/orchestrations/${o}`,{...e.name===void 0?{}:{name:e.name},...e.startText===void 0?{}:{startText:e.startText},...e.nodes===void 0?{}:{nodes:e.nodes},...e.edges===void 0?{}:{edges:e.edges},...e.cron===void 0?{}:{cron:e.cron},...e.enabled===void 0?{}:{enabled:e.enabled}})}case"delete_orchestration":return a(t,"DELETE",`/messaging/orchestrations/${i(e.id)}`);case"trigger_orchestration":return a(t,"POST",`/messaging/orchestrations/${i(e.id)}/trigger`,{...y(e.text)?{text:e.text}:{},...Array.isArray(e.entries)?{entries:e.entries}:{}});case"list_runs":return a(t,"GET",`/messaging/orchestration-runs${d({orchestrationId:i(e.orchestrationId),projectId:i(e.projectId),status:y(e.status),limit:i(e.limit),before:i(e.before)})}`);case"get_run":return a(t,"GET",`/messaging/orchestration-runs/${i(e.id)}`);case"cancel_run":return a(t,"POST",`/messaging/orchestration-runs/${i(e.id)}/cancel`);case"list_sessions":return{sessions:(await a(t,"GET",`/sessions${d({projectId:i(e.projectId)})}`)).sessions.map(r=>({sessionId:r.sessionId,projectId:r.projectId,title:r.title,harness:r.harness,lastSeenAt:r.lastSeenAt,turnOpen:r.turnOpen,pidAlive:r.pidAlive}))};default:throw new Error(`Unknown tool: ${n}`)}}function T(t){const n=new b({name:"weave-orchestration",version:"0.1.0"},{capabilities:{tools:{}}});return n.setRequestHandler(S,async()=>({tools:k})),n.setRequestHandler(g,async e=>{const{name:o,arguments:r}=e.params;try{const s=await I(t,o,r??{});return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s}}catch(s){return{isError:!0,content:[{type:"text",text:s instanceof Error?s.message:String(s)}]}}}),n}export async function handleMcpRequest(t,n,e){const o=T(e),r=new f({sessionIdGenerator:void 0,enableJsonResponse:!0});n.on("close",()=>{r.close(),o.close()}),await o.connect(r);let s;if(t.method==="POST"){const p=await j(t);try{s=p.trim()?JSON.parse(p):void 0}catch{w(n,400,{error:"Invalid JSON body"});return}}await r.handleRequest(t,n,s)}
1
+ import{Server as g}from"@modelcontextprotocol/sdk/server/index.js";import{StreamableHTTPServerTransport as b}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as f,ListToolsRequestSchema as S}from"@modelcontextprotocol/sdk/types.js";import{readBody as j,sendJson as w}from"./http.js";async function a(t,s,e,r){const n=await fetch(`http://127.0.0.1:${t.port}/api${e}`,{method:s,headers:{...t.token?{"x-weave-local":t.token}:{},...r===void 0?{}:{"content-type":"application/json"}},...r===void 0?{}:{body:JSON.stringify(r)}}),i=await n.text(),p=(()=>{try{return JSON.parse(i)}catch{return{raw:i}}})();if(!n.ok){const l=p&&typeof p=="object"&&"error"in p?String(p.error):`HTTP ${n.status}`;throw new Error(l)}return p}const d=t=>{const s=new URLSearchParams;for(const[r,n]of Object.entries(t))n!==void 0&&n!==""&&s.set(r,String(n));const e=s.toString();return e?`?${e}`:""},u={type:"object",required:["id","kind"],properties:{id:{type:"string",description:'session id, or "w:<uuid>" for a webhook node'},kind:{type:"string",enum:["session","webhook"]},webhookToken:{type:"string"},url:{type:"string",description:"webhook exit: outbound URL"},secret:{type:"string",description:"webhook exit: optional HMAC secret"}}},m={type:"object",required:["id","from","to","text"],properties:{id:{type:"string"},from:{type:"string"},to:{type:"string"},text:{type:"string",description:"message body; {upstream}/{summary}/{session} are substituted"},extract:{type:"string",description:"optional extraction prompt for {summary}"}}},c={type:"object",additionalProperties:!0},y={type:"object",additionalProperties:!0},I=[{name:"list_orchestrations",description:"List orchestrations (optionally by project). Returns { orchestrations: OrchestrationRow[] }; each row has id/name/projectId/startText/nodes/edges/enabled/cron/nextRunAt.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{orchestrations:{type:"array",items:c}},required:["orchestrations"]}},{name:"get_orchestration",description:"Get one orchestration definition (nodes, edges, startText, cron, enabled). Returns { orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{orchestration:c},required:["orchestration"]}},{name:"create_orchestration",description:"Create an orchestration. enabled defaults to true, which makes the entry session auto-fire the graph on EVERY natural turn \u2014 pass enabled:false when the run should be triggered manually. Edges support {upstream}/{summary}/{session}; a cycle is rejected. Returns { ok, orchestration }.",inputSchema:{type:"object",required:["name","nodes","edges"],properties:{name:{type:"string"},startText:{type:"string",description:"first message for session entries (manual trigger)"},projectId:{type:"number",description:"webhook-only orchestrations"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"update_orchestration",description:"Update part of an orchestration (omit fields to keep them; changing the graph does not affect a run already in flight). Returns { ok, orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},name:{type:"string"},startText:{type:"string"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"delete_orchestration",description:"Delete a definition. Run history (orchestration_runs) is kept. Returns { ok, orchestrationId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestrationId:{type:"number"}},required:["ok","orchestrationId"]}},{name:"trigger_orchestration",description:"Start a run. Manual trigger works even when enabled=false. Optional text overrides startText; entries restricts which entry nodes run. Dead target sessions are opened automatically, and delivery waits for their SessionStart. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},text:{type:"string"},entries:{type:"array",items:{type:"string"}}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_runs",description:"List runs, newest first. Returns { runs: RunSummary[], nextBefore }. RunSummary has id/orchestrationId/name/status/deliveries/pendingCounts/createdAt.",inputSchema:{type:"object",properties:{orchestrationId:{type:"number"},projectId:{type:"number"},status:{type:"string"},limit:{type:"number"},before:{type:"number"}}},outputSchema:{type:"object",properties:{runs:{type:"array",items:y},nextBefore:{type:["number","null"]}},required:["runs"]}},{name:"get_run",description:'Get a run with state.events (deliveries and stage:"ensure" opens) and state.pending per session. Returns { run }. status becomes interrupted when the daemon restarts (runs are not resumed).',inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{run:y},required:["run"]}},{name:"cancel_run",description:"Cancel a running run. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_sessions",description:"List sessions for picking graph nodes; minimal fields only (sessionId/projectId/title/harness/lastSeenAt/turnOpen/pidAlive). Returns { sessions }.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{sessions:{type:"array",items:{type:"object",additionalProperties:!0}}},required:["sessions"]}}],o=t=>typeof t=="number"?t:void 0,h=t=>typeof t=="string"?t:void 0;async function k(t,s,e){switch(s){case"list_orchestrations":return a(t,"GET",`/messaging/orchestrations${d({projectId:o(e.projectId)})}`);case"get_orchestration":{const r=(await a(t,"GET","/messaging/orchestrations")).orchestrations.find(n=>n.id===o(e.id));if(!r)throw new Error(`Orchestration not found: ${String(e.id)}`);return{orchestration:r}}case"create_orchestration":return a(t,"POST","/messaging/orchestrations",{name:e.name,startText:e.startText,projectId:o(e.projectId),nodes:e.nodes,edges:e.edges,cron:e.cron??null,enabled:e.enabled});case"update_orchestration":{const r=o(e.id);return a(t,"PUT",`/messaging/orchestrations/${r}`,{...e.name===void 0?{}:{name:e.name},...e.startText===void 0?{}:{startText:e.startText},...e.nodes===void 0?{}:{nodes:e.nodes},...e.edges===void 0?{}:{edges:e.edges},...e.cron===void 0?{}:{cron:e.cron},...e.enabled===void 0?{}:{enabled:e.enabled}})}case"delete_orchestration":return a(t,"DELETE",`/messaging/orchestrations/${o(e.id)}`);case"trigger_orchestration":return a(t,"POST",`/messaging/orchestrations/${o(e.id)}/trigger`,{...h(e.text)?{text:e.text}:{},...Array.isArray(e.entries)?{entries:e.entries}:{}});case"list_runs":return a(t,"GET",`/messaging/orchestration-runs${d({orchestrationId:o(e.orchestrationId),projectId:o(e.projectId),status:h(e.status),limit:o(e.limit),before:o(e.before)})}`);case"get_run":return a(t,"GET",`/messaging/orchestration-runs/${o(e.id)}`);case"cancel_run":return a(t,"POST",`/messaging/orchestration-runs/${o(e.id)}/cancel`);case"list_sessions":return{sessions:(await a(t,"GET",`/sessions${d({projectId:o(e.projectId)})}`)).sessions.map(r=>({sessionId:r.sessionId,projectId:r.projectId,title:r.title,harness:r.harness,lastSeenAt:r.lastSeenAt,turnOpen:r.turnOpen,pidAlive:r.pidAlive}))};default:throw new Error(`Unknown tool: ${s}`)}}function x(t){const s=new g({name:"weave-orchestration",version:"0.1.0"},{capabilities:{tools:{}}});return s.setRequestHandler(S,async()=>({tools:I})),s.setRequestHandler(f,async e=>{const{name:r,arguments:n}=e.params;try{const i=await k(t,r,n??{});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],structuredContent:i}}catch(i){return{isError:!0,content:[{type:"text",text:i instanceof Error?i.message:String(i)}]}}}),s}export async function handleMcpRequest(t,s,e){const r=x(e),n=new b({sessionIdGenerator:void 0,enableJsonResponse:!0});s.on("close",()=>{n.close(),r.close()}),await r.connect(n);let i;if(t.method==="POST"){const p=await j(t);try{i=p.trim()?JSON.parse(p):void 0}catch{w(s,400,{error:"Invalid JSON body"});return}}await n.handleRequest(t,s,i)}
@@ -1,2 +1,2 @@
1
- import{openSync as p,readSync as m,closeSync as y,statSync as O}from"node:fs";const S=500;export class NarrationWatcher{bus;surfaceOf;pathOf;harnessOf;cursors=new Map;timers=new Map;off=null;constructor(t,e,o,n){this.bus=t,this.surfaceOf=e,this.pathOf=o,this.harnessOf=n}start(){this.off||(this.off=this.bus.subscribe(t=>{t.kind!=="event.ingested"||!t.sessionId||this.schedule(t.sessionId)}))}stop(){this.off?.(),this.off=null;for(const t of this.timers.values())clearTimeout(t);this.timers.clear()}schedule(t){this.timers.get(t)||this.timers.set(t,setTimeout(()=>{this.timers.delete(t),this.pump(t)},S))}pumpForTest(t="test"){return this.pump(t)}async pump(t){const e=this.harnessOf(t),n=(e?this.surfaceOf(e):null)?.lineParser,f=this.pathOf(t);if(!n||!f)return;let r;try{r=O(f).size}catch{this.cursors.delete(t);return}const s=this.cursors.get(t);if(!s||s.path!==f||r<s.offset){this.cursors.set(t,{offset:r,carry:"",path:f});return}if(r===s.offset)return;let h;const u=p(f,"r");try{const i=Buffer.alloc(r-s.offset);m(u,i,0,i.length,s.offset),h=i.toString("utf8")}catch{return}finally{y(u)}const a=(s.carry+h).split(`
2
- `);s.carry=a.pop()??"",s.offset=r;const c=[];for(const i of a){const l=n(i);l&&c.push(l)}c.length>0&&this.bus.emit({kind:"narration.updated",sessionId:t,segs:c,at:new Date().toISOString()})}}
1
+ import{openSync as l,readSync as p,closeSync as m,statSync as d}from"node:fs";const y=500;export class NarrationWatcher{bus;surfaceOf;pathOf;harnessOf;cursors=new Map;timers=new Map;off=null;constructor(s,n,o,e){this.bus=s,this.surfaceOf=n,this.pathOf=o,this.harnessOf=e}start(){this.off||(this.off=this.bus.subscribe(s=>{s.kind!=="event.ingested"||!s.sessionId||this.schedule(s.sessionId)}))}stop(){this.off?.(),this.off=null;for(const s of this.timers.values())clearTimeout(s);this.timers.clear()}schedule(s){this.timers.get(s)||this.timers.set(s,setTimeout(()=>{this.timers.delete(s),this.pump(s)},y))}pumpForTest(s="test"){return this.pump(s)}async pump(s){const n=this.harnessOf(s),o=(n?this.surfaceOf(n):null)?.lineParser,e=this.pathOf(s);if(!o||!e)return;let r;try{r=d(e).size}catch{this.cursors.delete(s);return}const t=this.cursors.get(s);if(!t||t.path!==e||r<t.offset){this.cursors.set(s,{offset:r,carry:"",path:e});return}if(r===t.offset)return;let a;const c=l(e,"r");try{const i=Buffer.alloc(r-t.offset);p(c,i,0,i.length,t.offset),a=i.toString("utf8")}catch{return}finally{m(c)}const h=(t.carry+a).split(`
2
+ `);t.carry=h.pop()??"",t.offset=r;const f=[];for(const i of h){const u=o(i);u&&f.push(u)}f.length>0&&this.bus.emit({kind:"narration.updated",sessionId:s,segs:f,at:new Date().toISOString()})}}
@@ -1 +1 @@
1
- import{captureCommand as a}from"./wezterm-mux.js";import{PRESET_CANDIDATES as s,TerminalBackend as i}from"./backend.js";export class GhosttyBackend extends i{constructor(t){super("ghostty",!1,t)}candidates(t,n){return s.ghostty(t,n,this.platform)}async openViaIpcThenStandalone(t,n){if(this.platform==="linux"){const e=["+new-window",`--working-directory=${t}`,...n.length>0?["-e",...n]:[]];if((await a("ghostty",e))?.ok)return}await this.spawnFirst(this.candidates(t,n.length>0?n:void 0),`Terminal preset "${this.preset}" is unavailable on this platform`)}open(t){return this.openViaIpcThenStandalone(t,[])}async run(t,n){return await this.openViaIpcThenStandalone(t,n),null}}
1
+ import{captureCommand as e}from"./wezterm-mux.js";import{PRESET_CANDIDATES as i,TerminalBackend as s}from"./backend.js";export class GhosttyBackend extends s{constructor(t){super("ghostty",!1,t)}candidates(t,a){return i.ghostty(t,a,this.platform)}async openViaIpcThenStandalone(t,a){if(this.platform==="linux"){const n=["+new-window",`--working-directory=${t}`,...a.length>0?["-e",...a]:[]];if((await e("ghostty",n))?.ok)return}await this.spawnFirst(this.candidates(t,a.length>0?a:void 0),`Terminal preset "${this.preset}" is unavailable on this platform`)}open(t){return this.openViaIpcThenStandalone(t,[])}async run(t,a){return await this.openViaIpcThenStandalone(t,a),null}}
@@ -1,4 +1,4 @@
1
- import{TERMINAL_LOCATOR_ENV as i}from"@weavecode/core";import{captureCommand as o}from"./wezterm-mux.js";import{PRESET_CANDIDATES as s,TerminalBackend as a}from"./backend.js";export class ItermBackend extends a{constructor(e){super("iterm",!1,e,e==="darwin")}candidates(e,n){return s.iterm(e,n,this.platform)}async locatePane(e){return itermPaneFromEnv(e)}ownsPaneId(e){return parseItermPaneId(e)!==null}async sendPromptText(e,n){const t=parseItermPaneId(e);if(!t)throw new Error(`Invalid prompt pane "${e}"`);await c(t,n)}}export function parseItermPaneId(r){const e=/^iterm:(w\d+t\d+p\d+:[0-9A-Fa-f-]+)$/.exec(r);return e?e[1]:null}export function itermPaneFromEnv(r){const[e]=i.iterm,n=r[e];if(!n)return null;const t=`iterm:${n}`;return parseItermPaneId(t)?t:null}export function applescriptString(r){return r.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}async function c(r,e){const n=`tell application "iTerm2"
1
+ import{TERMINAL_LOCATOR_ENV as i}from"@weavecode/core";import{captureCommand as o}from"./wezterm-mux.js";import{PRESET_CANDIDATES as a,TerminalBackend as s}from"./backend.js";export class ItermBackend extends s{constructor(e){super("iterm",!1,e,e==="darwin")}candidates(e,n){return a.iterm(e,n,this.platform)}async locatePane(e){return itermPaneFromEnv(e)}ownsPaneId(e){return parseItermPaneId(e)!==null}async sendPromptText(e,n){const t=parseItermPaneId(e);if(!t)throw new Error(`Invalid prompt pane "${e}"`);await p(t,n)}}export function parseItermPaneId(r){const e=/^iterm:(w\d+t\d+p\d+:[0-9A-Fa-f-]+)$/.exec(r);return e?e[1]:null}export function itermPaneFromEnv(r){const[e]=i.iterm,n=r[e];if(!n)return null;const t=`iterm:${n}`;return parseItermPaneId(t)?t:null}export function applescriptString(r){return r.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}async function p(r,e){const n=`tell application "iTerm2"
2
2
  repeat with w in windows
3
3
  repeat with t in tabs of w
4
4
  repeat with s in sessions of t
@@ -1,2 +1,2 @@
1
- import{TERMINAL_LOCATOR_ENV as u}from"@weavecode/core";import{captureCommand as d}from"./wezterm-mux.js";import{PRESET_CANDIDATES as f,TerminalBackend as m}from"./backend.js";export class KonsoleBackend extends m{constructor(n){super("konsole",!1,n,n==="linux")}candidates(n,s){return f.konsole(n,s,this.platform)}async locatePane(n){return konsolePaneFromEnv(n)}ownsPaneId(n){return parseKonsolePaneId(n)!==null}async sendPromptText(n,s){const o=parseKonsolePaneId(n);if(!o)throw new Error(`Invalid prompt pane "${n}"`);s&&await c(o,"sendText",s),await c(o,"sendKey",String(l))}async sendKeys(n,s){const o=parseKonsolePaneId(n);if(!o)throw new Error(`Invalid prompt pane "${n}"`);for(const r of s)await c(o,"sendKey",String(qtKeyOf(r)))}}export function parseKonsolePaneId(e){const n=/^konsole:([\w.:-]+)\|(\/[\w/]+)$/.exec(e);return n?{service:n[1],session:n[2]}:null}export function konsolePaneFromEnv(e){const[n,s]=u.konsole,o=e[n],r=e[s];if(!o||!r)return null;const t=`konsole:${o}|${r}`;return parseKonsolePaneId(t)?t:null}const l=16777220;export function qtKeyOf(e){switch(e){case"\x1B":return 16777216;case"\r":case`
2
- `:return l;case" ":return 16777217;case"\b":return 16777219;default:return e.codePointAt(0)??0}}async function c(e,n,s){const o=[...["qdbus6","qdbus5","qdbus"].map(a=>({command:a,args:[e.service,e.session,n,s]})),{command:"dbus-send",args:["--session","--type=method_call",`--dest=${e.service}`,e.session,`org.kde.konsole.Session.${n}`,`string:${s}`]}];let r=null;for(const a of o){const i=await d(a.command,a.args,void 0,5e3);if(i?.ok)return;r=i}const t=r?r.err||r.out||"unknown error":"no qdbus / dbus-send on PATH";throw new Error(`Konsole D-Bus call "${n}" failed: ${t}`)}
1
+ import{TERMINAL_LOCATOR_ENV as l}from"@weavecode/core";import{captureCommand as d}from"./wezterm-mux.js";import{PRESET_CANDIDATES as m,TerminalBackend as f}from"./backend.js";export class KonsoleBackend extends f{constructor(n){super("konsole",!1,n,n==="linux")}candidates(n,e){return m.konsole(n,e,this.platform)}async locatePane(n){return konsolePaneFromEnv(n)}ownsPaneId(n){return parseKonsolePaneId(n)!==null}async sendPromptText(n,e){const s=parseKonsolePaneId(n);if(!s)throw new Error(`Invalid prompt pane "${n}"`);e&&await c(s,"sendText",e),await c(s,"sendKey",String(u))}async sendKeys(n,e){const s=parseKonsolePaneId(n);if(!s)throw new Error(`Invalid prompt pane "${n}"`);for(const r of e)await c(s,"sendKey",String(qtKeyOf(r)))}}export function parseKonsolePaneId(o){const n=/^konsole:([\w.:-]+)\|(\/[\w/]+)$/.exec(o);return n?{service:n[1],session:n[2]}:null}export function konsolePaneFromEnv(o){const[n,e]=l.konsole,s=o[n],r=o[e];if(!s||!r)return null;const t=`konsole:${s}|${r}`;return parseKonsolePaneId(t)?t:null}const u=16777220;export function qtKeyOf(o){switch(o){case"\x1B":return 16777216;case"\r":case`
2
+ `:return u;case" ":return 16777217;case"\b":return 16777219;default:return o.codePointAt(0)??0}}async function c(o,n,e){const s=[...["qdbus6","qdbus5","qdbus"].map(a=>({command:a,args:[o.service,o.session,n,e]})),{command:"dbus-send",args:["--session","--type=method_call",`--dest=${o.service}`,o.session,`org.kde.konsole.Session.${n}`,`string:${e}`]}];let r=null;for(const a of s){const i=await d(a.command,a.args,void 0,5e3);if(i?.ok)return;r=i}const t=r?r.err||r.out||"unknown error":"no qdbus / dbus-send on PATH";throw new Error(`Konsole D-Bus call "${n}" failed: ${t}`)}
@@ -1 +1 @@
1
- import{doScriptInTerminalWindow as i,listTerminalAppSurfaces as e,listTerminalAppTargets as s,parseTerminalAppTargetId as p,pickTerminalAppWindow as l,terminalAppSurfacesCached as o}from"./pty-terminals.js";import{countWindowsByDir as w}from"./wezterm-mux.js";import{PRESET_CANDIDATES as m,TerminalBackend as c}from"./backend.js";export class TerminalAppBackend extends c{constructor(a){super("terminal",a==="darwin",a)}candidates(a,t){return m.terminal(a,t,this.platform)}async run(a,t){if(this.platform==="darwin"){const n=await e(this.platform),r=l(n,a,this.platform);if(r&&await i(a,t,r.windowId))return null}return await this.spawnFirst(this.candidates(a,t),`Terminal preset "${this.preset}" is unavailable on this platform`),null}async countWindows(a){if(a.length===0||this.platform!=="darwin")return new Map(a.map(n=>[n,0]));const t=await o(this.platform);return t.length===0?new Map(a.map(n=>[n,0])):w(a,t.flatMap(n=>n.cwd?[{muxKey:"terminal.app",windowId:n.windowId,tabId:n.tabIndex,cwd:n.cwd}]:[]))}listTargets(a){return s(a,this.platform)}async runAt(a,t,n){const r=p(n);if(!r)throw new Error(`Invalid terminal target "${n}"`);if(!await i(a,t,r.windowId))throw new Error("Terminal window is gone \u2014 pick a terminal again");return null}}
1
+ import{doScriptInTerminalWindow as n,listTerminalAppSurfaces as e,listTerminalAppTargets as s,parseTerminalAppTargetId as l,pickTerminalAppWindow as p,terminalAppSurfacesCached as o}from"./pty-terminals.js";import{countWindowsByDir as m}from"./wezterm-mux.js";import{PRESET_CANDIDATES as w,TerminalBackend as d}from"./backend.js";export class TerminalAppBackend extends d{constructor(a){super("terminal",a==="darwin",a)}candidates(a,t){return w.terminal(a,t,this.platform)}async run(a,t){if(this.platform==="darwin"){const r=await e(this.platform),i=p(r,a,this.platform);if(i&&await n(a,t,i.windowId))return null}return await this.spawnFirst(this.candidates(a,t),`Terminal preset "${this.preset}" is unavailable on this platform`),null}async countWindows(a){if(a.length===0||this.platform!=="darwin")return new Map(a.map(r=>[r,0]));const t=await o(this.platform);return t.length===0?new Map(a.map(r=>[r,0])):m(a,t.flatMap(r=>r.cwd?[{muxKey:"terminal.app",windowId:r.windowId,tabId:r.tabIndex,cwd:r.cwd}]:[]))}listTargets(a){return s(a,this.platform)}async runAt(a,t,r){const i=l(r);if(!i)throw new Error(`Invalid terminal target "${r}"`);if(!await n(a,t,i.windowId))throw new Error("Terminal window is gone \u2014 pick a terminal again");return null}}
@@ -1 +1 @@
1
- import{TERMINAL_LOCATOR_ENV as g}from"@weavecode/core";import{MAX_PANES_PER_SCREEN as f,countWindowsByDir as I,listAttachTargets as y,openInWezterm as E,parseAttachTargetId as h,planWeztermGrid as z,runInWezterm as P,weztermCli as p,weztermGuiPidOf as K,weztermLiveMuxes as u,weztermMuxForId as d,weztermMuxKey as x,weztermPaneFromEnv as b,sessionScreensFromEnvs as S,weztermSpawnAndSend as T,weztermStepError as m}from"./wezterm-mux.js";import{winRaiseTerminalWindow as M}from"./win-raise.js";import{throughCmd as A}from"./shared.js";import{TerminalBackend as $}from"./backend.js";let l=null;export async function weztermLiveMuxesCached(){if(l&&Date.now()-l.at<1e4)return l;const{muxes:w,candidates:e}=await u(!0);return l={at:Date.now(),muxes:w,candidates:e},l}export class WeztermBackend extends ${constructor(e){super("wezterm",!0,e,!0)}candidates(e,n){return[{command:"wezterm",args:["start","--cwd",e,...A(n,this.platform==="win32")??[]]}]}async open(e){await E(e)||await super.open(e)}async run(e,n){const t=await P(e,n);return t||super.run(e,n)}async countWindows(e){if(e.length===0)return new Map;const{muxes:n}=await weztermLiveMuxesCached();return n.length===0?new Map(e.map(t=>[t,0])):I(e,n.flatMap(t=>t.panes.map(r=>({muxKey:t.socket,windowId:r.windowId,tabId:r.tabId,cwd:r.cwd}))))}listTargets(e){return y(e,this.platform)}runAt(e,n,t){return runInWeztermAt(e,n,t,this.platform)}async focusTarget(e,n){const t=h(n);if(!t)throw new Error(`Invalid terminal target "${n}"`);const r=await d(t.muxKey);if(!r)throw new Error("wezterm instance is gone \u2014 cannot bring the terminal to the front");const a=r.panes.find(i=>i.windowId===t.windowId&&i.tabId===t.tabId);if(!a)throw new Error("That terminal is gone \u2014 reopen the list");const o=["cli","activate-pane","--pane-id",String(a.paneId)],s=await p(o,r.socket);if(!s?.ok)throw new Error(m(o,r.socket,s));if(this.platform!=="win32")return;const c=(await d(t.muxKey))?.panes??r.panes,k=[(c.find(i=>i.paneId===a.paneId)??a).title,...c.filter(i=>i.windowId===t.windowId).map(i=>i.title)].filter(i=>!!i);await M({guiPid:K(r.socket)??void 0,titles:k})}async listPromptPanes(){const{muxes:e}=await u();return e.flatMap(n=>n.panes.map(t=>({id:`${x(n.socket)}:${t.paneId}`,title:t.title,cwd:t.cwd})))}async locatePane(e){const[n,t]=g.wezterm,r=e[t];if(!e[n]||!r)return null;const{muxes:a}=await u(!0,r);return b(e,a,this.platform)}ownsPaneId(e){return parsePromptPaneId(e)!==null}async locateScreens(e){if(Object.keys(e).length===0)return{};const{muxes:n,candidates:t}=await weztermLiveMuxesCached();return S(e,n,t,this.platform)}async sendPromptText(e,n){const t=parsePromptPaneId(e);if(!t)throw new Error(`Invalid prompt pane "${e}"`);const r=await d(t.muxKey);if(!r)throw new Error("wezterm instance is gone \u2014 cannot deliver prompt");const a=String(t.paneId);if(n){const s=await p(["cli","send-text","--pane-id",a,n],r.socket);if(!s?.ok)throw new Error(m(["cli","send-text","--pane-id",a,"<prompt text>"],r.socket,s))}const o=await p(["cli","send-text","--pane-id",a,"--no-paste","\r"],r.socket);if(!o?.ok)throw new Error(m(["cli","send-text","--pane-id",a,"--no-paste","<CR>"],r.socket,o))}async sendKeys(e,n){const t=parsePromptPaneId(e);if(!t)throw new Error(`Invalid prompt pane "${e}"`);const r=await d(t.muxKey);if(!r)throw new Error("wezterm instance is gone \u2014 cannot send keys to the pane");const a=String(t.paneId),o=await p(["cli","send-text","--pane-id",a,"--no-paste",n],r.socket);if(!o?.ok)throw new Error(m(["cli","send-text","--pane-id",a,"--no-paste","<keys>"],r.socket,o))}async closePane(e){const n=parsePromptPaneId(e);if(!n)throw new Error(`Invalid prompt pane "${e}"`);const t=await d(n.muxKey);if(!t)throw new Error("wezterm instance is gone \u2014 cannot close the pane");const r=String(n.paneId),a=await p(["cli","kill-pane","--pane-id",r],t.socket);if(!a?.ok)throw new Error(m(["cli","kill-pane","--pane-id",r],t.socket,a))}async getPaneText(e){const n=parsePromptPaneId(e);if(!n)return null;const t=await d(n.muxKey);if(!t)return null;const r=await p(["cli","get-text","--pane-id",String(n.paneId)],t.socket);return r?.ok?r.out:null}}export async function runInWeztermAt(w,e,n,t=process.platform){const r=h(n);if(!r)throw new Error(`Invalid terminal target "${n}"`);const{muxes:a}=await u(),o=a.find(c=>x(c.socket)===r.muxKey);if(!o)throw new Error("wezterm instance is gone \u2014 pick a terminal again");const s=o.panes.filter(c=>c.windowId===r.windowId&&c.tabId===r.tabId);if(s.length===0)throw new Error("terminal tab is gone \u2014 pick a terminal again");if(s.length>=f)throw new Error(`terminal is full (${f} panes) \u2014 pick another terminal or open a new one`);return T(o.socket,w,e,z(s),o.workspace,t)}export function parsePromptPaneId(w){const e=/^([0-9a-f]{8}):(\d+)$/.exec(w);return e?{muxKey:e[1],paneId:Number(e[2])}:null}
1
+ import{TERMINAL_LOCATOR_ENV as k}from"@weavecode/core";import{MAX_PANES_PER_SCREEN as f,countWindowsByDir as g,listAttachTargets as y,openInWezterm as E,parseAttachTargetId as h,planWeztermGrid as z,runInWezterm as P,weztermCli as d,weztermGuiPidOf as S,weztermLiveMuxes as u,weztermMuxForId as p,weztermMuxKey as x,weztermPaneFromEnv as v,sessionScreensFromEnvs as K,weztermSpawnAndSend as T,weztermStepError as m}from"./wezterm-mux.js";import{winRaiseTerminalWindow as b}from"./win-raise.js";import{throughCmd as M}from"./shared.js";import{TerminalBackend as A}from"./backend.js";let l=null;export async function weztermLiveMuxesCached(){if(l&&Date.now()-l.at<1e4)return l;const{muxes:w,candidates:t}=await u(!0);return l={at:Date.now(),muxes:w,candidates:t},l}export class WeztermBackend extends A{constructor(t){super("wezterm",!0,t,!0)}candidates(t,n){return[{command:"wezterm",args:["start","--cwd",t,...M(n,this.platform==="win32")??[]]}]}async open(t){await E(t)||await super.open(t)}async run(t,n){return await P(t,n)||super.run(t,n)}async countWindows(t){if(t.length===0)return new Map;const{muxes:n}=await weztermLiveMuxesCached();return n.length===0?new Map(t.map(e=>[e,0])):g(t,n.flatMap(e=>e.panes.map(r=>({muxKey:e.socket,windowId:r.windowId,tabId:r.tabId,cwd:r.cwd}))))}listTargets(t){return y(t,this.platform)}runAt(t,n,e){return runInWeztermAt(t,n,e,this.platform)}async focusTarget(t,n){const e=h(n);if(!e)throw new Error(`Invalid terminal target "${n}"`);const r=await p(e.muxKey);if(!r)throw new Error("wezterm instance is gone \u2014 cannot bring the terminal to the front");const a=r.panes.find(s=>s.windowId===e.windowId&&s.tabId===e.tabId);if(!a)throw new Error("That terminal is gone \u2014 reopen the list");const o=["cli","activate-pane","--pane-id",String(a.paneId)],i=await d(o,r.socket);if(!i?.ok)throw new Error(m(o,r.socket,i));if(this.platform!=="win32")return;const c=(await p(e.muxKey))?.panes??r.panes,I=[(c.find(s=>s.paneId===a.paneId)??a).title,...c.filter(s=>s.windowId===e.windowId).map(s=>s.title)].filter(s=>!!s);await b({guiPid:S(r.socket)??void 0,titles:I})}async listPromptPanes(){const{muxes:t}=await u();return t.flatMap(n=>n.panes.map(e=>({id:`${x(n.socket)}:${e.paneId}`,title:e.title,cwd:e.cwd})))}async locatePane(t){const[n,e]=k.wezterm,r=t[e];if(!t[n]||!r)return null;const{muxes:a}=await u(!0,r);return v(t,a,this.platform)}ownsPaneId(t){return parsePromptPaneId(t)!==null}async locateScreens(t){if(Object.keys(t).length===0)return{};const{muxes:n,candidates:e}=await weztermLiveMuxesCached();return K(t,n,e,this.platform)}async sendPromptText(t,n){const e=parsePromptPaneId(t);if(!e)throw new Error(`Invalid prompt pane "${t}"`);const r=await p(e.muxKey);if(!r)throw new Error("wezterm instance is gone \u2014 cannot deliver prompt");const a=String(e.paneId);if(n){const i=await d(["cli","send-text","--pane-id",a,n],r.socket);if(!i?.ok)throw new Error(m(["cli","send-text","--pane-id",a,"<prompt text>"],r.socket,i))}const o=await d(["cli","send-text","--pane-id",a,"--no-paste","\r"],r.socket);if(!o?.ok)throw new Error(m(["cli","send-text","--pane-id",a,"--no-paste","<CR>"],r.socket,o))}async sendKeys(t,n){const e=parsePromptPaneId(t);if(!e)throw new Error(`Invalid prompt pane "${t}"`);const r=await p(e.muxKey);if(!r)throw new Error("wezterm instance is gone \u2014 cannot send keys to the pane");const a=String(e.paneId),o=await d(["cli","send-text","--pane-id",a,"--no-paste",n],r.socket);if(!o?.ok)throw new Error(m(["cli","send-text","--pane-id",a,"--no-paste","<keys>"],r.socket,o))}async closePane(t){const n=parsePromptPaneId(t);if(!n)throw new Error(`Invalid prompt pane "${t}"`);const e=await p(n.muxKey);if(!e)throw new Error("wezterm instance is gone \u2014 cannot close the pane");const r=String(n.paneId),a=await d(["cli","kill-pane","--pane-id",r],e.socket);if(!a?.ok)throw new Error(m(["cli","kill-pane","--pane-id",r],e.socket,a))}async getPaneText(t){const n=parsePromptPaneId(t);if(!n)return null;const e=await p(n.muxKey);if(!e)return null;const r=await d(["cli","get-text","--pane-id",String(n.paneId)],e.socket);return r?.ok?r.out:null}}export async function runInWeztermAt(w,t,n,e=process.platform){const r=h(n);if(!r)throw new Error(`Invalid terminal target "${n}"`);const{muxes:a}=await u(),o=a.find(c=>x(c.socket)===r.muxKey);if(!o)throw new Error("wezterm instance is gone \u2014 pick a terminal again");const i=o.panes.filter(c=>c.windowId===r.windowId&&c.tabId===r.tabId);if(i.length===0)throw new Error("terminal tab is gone \u2014 pick a terminal again");if(i.length>=f)throw new Error(`terminal is full (${f} panes) \u2014 pick another terminal or open a new one`);return T(o.socket,w,t,z(i),o.workspace,e)}export function parsePromptPaneId(w){const t=/^([0-9a-f]{8}):(\d+)$/.exec(w);return t?{muxKey:t[1],paneId:Number(t[2])}:null}
@@ -1 +1 @@
1
- import{basename as c}from"node:path";import{pidAlive as f}from"../claude-liveness.js";import{countWindowsByDir as s,normalizeDirKey as l}from"./wezterm-mux.js";import{BRACKETED_PASTE_END as d,BRACKETED_PASTE_START as h,parseWtPaneId as a,parseWtTargetId as w,wtInjectKeys as p,wtPanePidFromEnv as E,wtPanesAsWindows as m,wtPanesCached as i,wtWindowSlug as u}from"./wt.js";import{winRaiseTerminalWindow as T}from"./win-raise.js";import{throughCmd as y}from"./shared.js";import{PRESET_CANDIDATES as P,TerminalBackend as g}from"./backend.js";export class WtBackend extends g{constructor(t){super("wt",t==="win32",t,t==="win32")}candidates(t,n){return P.wt(t,n,this.platform)}async countWindows(t){if(t.length===0||this.platform!=="win32")return new Map(t.map(e=>[e,0]));const n=await i();return n.length===0?new Map(t.map(e=>[e,0])):s(t,m(n))}async listTargets(t){if(this.platform!=="win32")return[];const n=await i(),e=s([t],m(n)).get(t)??0;return e===0?[]:[{id:`wt:${u(t)}`,windowId:0,tabId:0,title:c(t),matchCount:e,paneCount:e,active:!1,full:!1}]}async runAt(t,n,e){if(this.platform!=="win32")throw new Error(`Terminal preset "${this.preset}" is unavailable on this platform`);if(!w(e))throw new Error(`Invalid terminal target "${e}"`);return await this.spawnFirst([{command:"wt.exe",args:["-w",u(t),"split-pane","-d",t,...y(n,!0)??[]]}],`Terminal preset "${this.preset}" is unavailable on this platform`),null}async focusTarget(t,n){if(!w(n))throw new Error(`Invalid terminal target "${n}"`);const e=l(t,this.platform),o=(await i()).filter(r=>e!==null&&l(r.cwd,this.platform)===e).map(r=>r.pid);if(!o.length)throw new Error("That terminal is gone \u2014 reopen the list");await T({panePids:o,exe:"windowsterminal.exe"})}async locatePane(t){const n=E(t);return n==null||!f(n)?null:`wt:${n}`}ownsPaneId(t){return a(t)!==null}async sendPromptText(t,n){const e=a(t);if(e==null)throw new Error(`Invalid prompt pane "${t}"`);await p(e,`${h}${n}${d}\r`)}async sendKeys(t,n){const e=a(t);if(e==null)throw new Error(`Invalid prompt pane "${t}"`);await p(e,n)}}
1
+ import{basename as c}from"node:path";import{pidAlive as u}from"../claude-liveness.js";import{countWindowsByDir as o,normalizeDirKey as l}from"./wezterm-mux.js";import{BRACKETED_PASTE_END as f,BRACKETED_PASTE_START as h,parseWtPaneId as e,parseWtTargetId as w,wtInjectKeys as m,wtPanePidFromEnv as E,wtPanesAsWindows as p,wtPanesCached as i,wtWindowSlug as d}from"./wt.js";import{winRaiseTerminalWindow as T}from"./win-raise.js";import{throughCmd as g}from"./shared.js";import{PRESET_CANDIDATES as P,TerminalBackend as y}from"./backend.js";export class WtBackend extends y{constructor(a){super("wt",a==="win32",a,a==="win32")}candidates(a,t){return P.wt(a,t,this.platform)}async countWindows(a){if(a.length===0||this.platform!=="win32")return new Map(a.map(n=>[n,0]));const t=await i();return t.length===0?new Map(a.map(n=>[n,0])):o(a,p(t))}async listTargets(a){if(this.platform!=="win32")return[];const t=await i(),n=o([a],p(t)).get(a)??0;return n===0?[]:[{id:`wt:${d(a)}`,windowId:0,tabId:0,title:c(a),matchCount:n,paneCount:n,active:!1,full:!1}]}async runAt(a,t,n){if(this.platform!=="win32")throw new Error(`Terminal preset "${this.preset}" is unavailable on this platform`);if(!w(n))throw new Error(`Invalid terminal target "${n}"`);return await this.spawnFirst([{command:"wt.exe",args:["-w",d(a),"split-pane","-d",a,...g(t,!0)??[]]}],`Terminal preset "${this.preset}" is unavailable on this platform`),null}async focusTarget(a,t){if(!w(t))throw new Error(`Invalid terminal target "${t}"`);const n=l(a,this.platform),s=(await i()).filter(r=>n!==null&&l(r.cwd,this.platform)===n).map(r=>r.pid);if(!s.length)throw new Error("That terminal is gone \u2014 reopen the list");await T({panePids:s,exe:"windowsterminal.exe"})}async locatePane(a){const t=E(a);return t==null||!u(t)?null:`wt:${t}`}ownsPaneId(a){return e(a)!==null}async sendPromptText(a,t){const n=e(a);if(n==null)throw new Error(`Invalid prompt pane "${a}"`);await m(n,`${h}${t}${f}\r`)}async sendKeys(a,t){const n=e(a);if(n==null)throw new Error(`Invalid prompt pane "${a}"`);await m(n,t)}}
@@ -1 +1 @@
1
- import{spawn as m}from"node:child_process";import{joinCmd as s,quotePath as i,throughCmd as l}from"./shared.js";import{wtWindowSlug as p}from"./wt.js";export class TerminalBackend{preset;enumerable;platform;textAddressable;constructor(e,t,r=process.platform,a=!1){this.preset=e,this.enumerable=t,this.platform=r,this.textAddressable=a}async open(e){await this.spawnFirst(this.candidates(e),`Terminal preset "${this.preset}" is unavailable on this platform`)}async run(e,t){return await this.spawnFirst(this.candidates(e,t),`Terminal preset "${this.preset}" cannot run a command here \u2014 pick another preset in settings`),null}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 focusTarget(e,t){throw new Error(`Terminal preset "${this.preset}" cannot bring an open terminal to the front \u2014 pick wezterm or wt 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 a preset with text injection in settings`)}async sendKeys(e,t){throw new Error(`Terminal preset "${this.preset}" cannot send keys to an open pane \u2014 pick a preset with key injection in settings`)}async getPaneText(e){return null}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 trySpawn(r))return;throw new Error(e.length===0?t:"No usable terminal found (tried: "+e.map(r=>r.command).join(", ")+")")}}export class CandidatesBackend extends TerminalBackend{make;constructor(e,t,r){super(e,!1,t),this.make=r}candidates(e,t){return this.make(e,t,this.platform)}}export const PRESET_CANDIDATES={wt:(n,e,t)=>t==="win32"?[{command:"wt.exe",args:["-w",p(n),"-d",n,...l(e,!0)??[]]}]:[],powershell:(n,e,t)=>t==="win32"?[e?{command:"powershell.exe",args:["-NoExit","-Command",s(e,"win32")],cwd:n}:{command:"powershell.exe",args:["-NoExit"],cwd:n}]:[],cmd:(n,e,t)=>t==="win32"?[e?{command:"cmd.exe",args:["/K",s(e,"win32")],cwd:n}:{command:"cmd.exe",args:["/K"],cwd:n}]:[],terminal:(n,e,t)=>t!=="darwin"?[]:e?[{command:"osascript",args:c("Terminal",n,e)}]:[{command:"open",args:["-a","Terminal",n]}],iterm:(n,e,t)=>t!=="darwin"?[]:e?[{command:"osascript",args:c("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]:[]]}]};function c(n,e,t){const a=`cd ${i(e,"darwin")} && ${s(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return n==="Terminal"?["-e",`tell application "Terminal" to do script "${a}"`,"-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 "${a}"`]}export class CustomBackend 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 a=r.replace(/\{path\}/g,i(e,this.platform));const o=t?s(t,this.platform):"";return a=a.includes("{command}")?a.replace(/\{command\}/g,o):t?`${a} ${o}`:a,[{command:a,args:[],shell:!0}]}}export function trySpawn(n){return new Promise(e=>{let t;try{t=m(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)})})}
1
+ import{spawn as m}from"node:child_process";import{joinCmd as s,quotePath as i,throughCmd as l}from"./shared.js";import{wtWindowSlug as p}from"./wt.js";export class TerminalBackend{preset;enumerable;platform;textAddressable;constructor(e,t,n=process.platform,a=!1){this.preset=e,this.enumerable=t,this.platform=n,this.textAddressable=a}async open(e){await this.spawnFirst(this.candidates(e),`Terminal preset "${this.preset}" is unavailable on this platform`)}async run(e,t){return await this.spawnFirst(this.candidates(e,t),`Terminal preset "${this.preset}" cannot run a command here \u2014 pick another preset in settings`),null}async countWindows(e){return new Map}async listTargets(e){return[]}async runAt(e,t,n){throw new Error(`Terminal preset "${this.preset}" cannot attach to a chosen pane \u2014 pick wezterm, wt or Terminal.app in settings`)}async focusTarget(e,t){throw new Error(`Terminal preset "${this.preset}" cannot bring an open terminal to the front \u2014 pick wezterm or wt 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 a preset with text injection in settings`)}async sendKeys(e,t){throw new Error(`Terminal preset "${this.preset}" cannot send keys to an open pane \u2014 pick a preset with key injection in settings`)}async getPaneText(e){return null}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 n of e)if(await trySpawn(n))return;throw new Error(e.length===0?t:"No usable terminal found (tried: "+e.map(n=>n.command).join(", ")+")")}}export class CandidatesBackend extends TerminalBackend{make;constructor(e,t,n){super(e,!1,t),this.make=n}candidates(e,t){return this.make(e,t,this.platform)}}export const PRESET_CANDIDATES={wt:(r,e,t)=>t==="win32"?[{command:"wt.exe",args:["-w",p(r),"-d",r,...l(e,!0)??[]]}]:[],powershell:(r,e,t)=>t==="win32"?[e?{command:"powershell.exe",args:["-NoExit","-Command",s(e,"win32")],cwd:r}:{command:"powershell.exe",args:["-NoExit"],cwd:r}]:[],cmd:(r,e,t)=>t==="win32"?[e?{command:"cmd.exe",args:["/K",s(e,"win32")],cwd:r}:{command:"cmd.exe",args:["/K"],cwd:r}]:[],terminal:(r,e,t)=>t!=="darwin"?[]:e?[{command:"osascript",args:c("Terminal",r,e)}]:[{command:"open",args:["-a","Terminal",r]}],iterm:(r,e,t)=>t!=="darwin"?[]:e?[{command:"osascript",args:c("iTerm",r,e)}]:[{command:"open",args:["-a","iTerm",r]}],gnome:(r,e)=>[{command:"gnome-terminal",args:[`--working-directory=${r}`,...e?["--",...e]:[]]}],konsole:(r,e)=>[{command:"konsole",args:["--workdir",r,...e?["-e",...e]:[]]}],ghostty:(r,e,t)=>t==="win32"?[]:t==="darwin"?e?[]:[{command:"open",args:["-a","Ghostty",r]}]:[{command:"ghostty",args:[`--working-directory=${r}`,...e?["-e",...e]:[]]}]};function c(r,e,t){const n=`cd ${i(e,"darwin")} && ${s(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return r==="Terminal"?["-e",`tell application "Terminal" to do script "${n}"`,"-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 "${n}"`]}export class CustomBackend extends TerminalBackend{terminal;constructor(e,t){super("custom",!1,t),this.terminal=e}candidates(e,t){const n=this.terminal.customCommand.trim();if(!n)return[];let a=n.replace(/\{path\}/g,i(e,this.platform));const o=t?s(t,this.platform):"";return a=a.includes("{command}")?a.replace(/\{command\}/g,o):t?`${a} ${o}`:a,[{command:a,args:[],shell:!0}]}}export function trySpawn(r){return new Promise(e=>{let t;try{t=m(r.command,r.args,{cwd:r.cwd,shell:r.shell,detached:!0,stdio:"ignore"})}catch{e(!1);return}t.on("error",()=>e(!1)),t.on("spawn",()=>{t.unref(),e(!0)})})}
@@ -1 +1 @@
1
- import{spawn as a}from"node:child_process";export function resolveTerminalLaunch(n,e,r=process.platform,o){return terminalBackendFor(e,r).candidates(n,o)}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]}}export function trySpawn(n){return new Promise(e=>{let r;try{r=a(n.command,n.args,{cwd:n.cwd,shell:n.shell,detached:!0,stdio:"ignore"})}catch{e(!1);return}r.on("error",()=>e(!1)),r.on("spawn",()=>{r.unref(),e(!0)})})}export async function openInExplorer(n){const e=resolveExplorerLaunch(n);if(!await trySpawn(e))throw new Error(`Failed to open file manager (${e.command})`)}export async function openInTerminal(n,e){await terminalBackendFor(e).open(n)}
1
+ import{spawn as a}from"node:child_process";export function resolveTerminalLaunch(r,e,n=process.platform,o){return terminalBackendFor(e,n).candidates(r,o)}export function resolveExplorerLaunch(r,e=process.platform){return e==="win32"?{command:"explorer.exe",args:[r]}:e==="darwin"?{command:"open",args:[r]}:{command:"xdg-open",args:[r]}}export function trySpawn(r){return new Promise(e=>{let n;try{n=a(r.command,r.args,{cwd:r.cwd,shell:r.shell,detached:!0,stdio:"ignore"})}catch{e(!1);return}n.on("error",()=>e(!1)),n.on("spawn",()=>{n.unref(),e(!0)})})}export async function openInExplorer(r){const e=resolveExplorerLaunch(r);if(!await trySpawn(e))throw new Error(`Failed to open file manager (${e.command})`)}export async function openInTerminal(r,e){await terminalBackendFor(e).open(r)}
@@ -1,5 +1,5 @@
1
1
  import{captureCommand as p,normalizeDirKey as d}from"./wezterm-mux.js";import{joinCmd as l,quotePath as f}from"./shared.js";const m=['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(o){const t=[];for(const r of o.split(`
3
- `)){const e=r.trim().split(" ");if(e.length!==5)continue;const n=Number(e[0]),i=Number(e[1]);!Number.isInteger(n)||!Number.isInteger(i)||t.push({windowId:n,tabIndex:i,tty:e[2],selected:e[3]==="true",frontmost:e[4]==="true"})}return t}export function parsePsRootPids(o){const t=new Map,r=new Map;for(const n of o.split(`
4
- `)){const i=/^\s*(\d+)\s+(\d+)\s+(\S+)/.exec(n);if(!i)continue;const a=Number(i[1]),c=i[3];if(c==="??")continue;const s=t.get(c)??new Set;s.add(a),t.set(c,s),r.set(a,Number(i[2]))}const e=new Map;for(const[n,i]of t)for(const a of i)if(!i.has(r.get(a)??-1)){e.set(n,a);break}return e}export function parseLsofCwds(o){const t=new Map;let r=-1;for(const e of o.split(`
5
- `))e.startsWith("p")&&/^\d+$/.test(e.slice(1))?r=Number(e.slice(1)):e.startsWith("n")&&r!==-1&&(t.set(r,e.slice(1)),r=-1);return t}export async function listTerminalAppSurfaces(o){if(o!=="darwin")return[];const t=await p("osascript",["-e",m]);if(!t?.ok)return[];const r=parseTerminalAppDump(t.out);if(r.length===0)return[];const e=await p("ps",["-axo","pid=,ppid=,tty="]);if(!e?.ok)return r.map(s=>({...s,cwd:null}));const n=parsePsRootPids(e.out),i=[...new Set(r.map(s=>n.get(s.tty.replace(/^\/dev\//,""))??-1))].filter(s=>s!==-1),a=i.length>0?await p("lsof",["-a","-p",i.join(","),"-d","cwd","-Fn"]):null,c=parseLsofCwds(a?.out??"");return r.map(s=>({...s,cwd:c.get(n.get(s.tty.replace(/^\/dev\//,""))??-1)??null}))}let u=null;export async function terminalAppSurfacesCached(o){if(u&&Date.now()-u.at<1e4)return u.surfaces;const t=await listTerminalAppSurfaces(o);return u={at:Date.now(),surfaces:t},t}export function terminalAppTargetId(o,t){return`terminal:${o}:${t}`}export function parseTerminalAppTargetId(o){const t=/^terminal:(\d+):(\d+)$/.exec(o);return t?{windowId:Number(t[1]),tabIndex:Number(t[2])}:null}export function terminalAppMatches(o,t,r){const e=d(t,r);return e?o.filter(n=>n.cwd!==null&&d(n.cwd,r)===e):[]}export function terminalAppTargets(o,t,r=process.platform){const e=terminalAppMatches(t,o,r);return e.sort((n,i)=>Number(i.frontmost)-Number(n.frontmost)||Number(i.selected)-Number(n.selected)||i.tabIndex-n.tabIndex),e.map(n=>({id:terminalAppTargetId(n.windowId,n.tabIndex),windowId:n.windowId,tabId:n.tabIndex,title:null,matchCount:1,paneCount:1,active:n.frontmost&&n.selected,full:!1}))}export function pickTerminalAppWindow(o,t,r=process.platform){const e=terminalAppMatches(o,t,r);return e.length===0?null:(e.sort((n,i)=>Number(i.frontmost)-Number(n.frontmost)||i.windowId-n.windowId),{windowId:e[0].windowId,tabIndex:e[0].tabIndex})}export async function listTerminalAppTargets(o,t){return terminalAppTargets(o,await listTerminalAppSurfaces(t),t)}export async function doScriptInTerminalWindow(o,t,r){const n=`cd ${f(o,"darwin")} && ${l(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return(await p("osascript",["-e",`tell application "Terminal" to do script "${n}" in window id ${r}`]))?.ok===!0}
2
+ `);export function parseTerminalAppDump(r){const t=[];for(const o of r.split(`
3
+ `)){const e=o.trim().split(" ");if(e.length!==5)continue;const n=Number(e[0]),i=Number(e[1]);!Number.isInteger(n)||!Number.isInteger(i)||t.push({windowId:n,tabIndex:i,tty:e[2],selected:e[3]==="true",frontmost:e[4]==="true"})}return t}export function parsePsRootPids(r){const t=new Map,o=new Map;for(const n of r.split(`
4
+ `)){const i=/^\s*(\d+)\s+(\d+)\s+(\S+)/.exec(n);if(!i)continue;const s=Number(i[1]),c=i[3];if(c==="??")continue;const a=t.get(c)??new Set;a.add(s),t.set(c,a),o.set(s,Number(i[2]))}const e=new Map;for(const[n,i]of t)for(const s of i)if(!i.has(o.get(s)??-1)){e.set(n,s);break}return e}export function parseLsofCwds(r){const t=new Map;let o=-1;for(const e of r.split(`
5
+ `))e.startsWith("p")&&/^\d+$/.test(e.slice(1))?o=Number(e.slice(1)):e.startsWith("n")&&o!==-1&&(t.set(o,e.slice(1)),o=-1);return t}export async function listTerminalAppSurfaces(r){if(r!=="darwin")return[];const t=await p("osascript",["-e",m]);if(!t?.ok)return[];const o=parseTerminalAppDump(t.out);if(o.length===0)return[];const e=await p("ps",["-axo","pid=,ppid=,tty="]);if(!e?.ok)return o.map(a=>({...a,cwd:null}));const n=parsePsRootPids(e.out),i=[...new Set(o.map(a=>n.get(a.tty.replace(/^\/dev\//,""))??-1))].filter(a=>a!==-1),s=i.length>0?await p("lsof",["-a","-p",i.join(","),"-d","cwd","-Fn"]):null,c=parseLsofCwds(s?.out??"");return o.map(a=>({...a,cwd:c.get(n.get(a.tty.replace(/^\/dev\//,""))??-1)??null}))}let u=null;export async function terminalAppSurfacesCached(r){if(u&&Date.now()-u.at<1e4)return u.surfaces;const t=await listTerminalAppSurfaces(r);return u={at:Date.now(),surfaces:t},t}export function terminalAppTargetId(r,t){return`terminal:${r}:${t}`}export function parseTerminalAppTargetId(r){const t=/^terminal:(\d+):(\d+)$/.exec(r);return t?{windowId:Number(t[1]),tabIndex:Number(t[2])}:null}export function terminalAppMatches(r,t,o){const e=d(t,o);return e?r.filter(n=>n.cwd!==null&&d(n.cwd,o)===e):[]}export function terminalAppTargets(r,t,o=process.platform){const e=terminalAppMatches(t,r,o);return e.sort((n,i)=>Number(i.frontmost)-Number(n.frontmost)||Number(i.selected)-Number(n.selected)||i.tabIndex-n.tabIndex),e.map(n=>({id:terminalAppTargetId(n.windowId,n.tabIndex),windowId:n.windowId,tabId:n.tabIndex,title:null,matchCount:1,paneCount:1,active:n.frontmost&&n.selected,full:!1}))}export function pickTerminalAppWindow(r,t,o=process.platform){const e=terminalAppMatches(r,t,o);return e.length===0?null:(e.sort((n,i)=>Number(i.frontmost)-Number(n.frontmost)||i.windowId-n.windowId),{windowId:e[0].windowId,tabIndex:e[0].tabIndex})}export async function listTerminalAppTargets(r,t){return terminalAppTargets(r,await listTerminalAppSurfaces(t),t)}export async function doScriptInTerminalWindow(r,t,o){const e=`cd ${f(r,"darwin")} && ${l(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return(await p("osascript",["-e",`tell application "Terminal" to do script "${e}" in window id ${o}`]))?.ok===!0}
@@ -1 +1 @@
1
- export function quotePath(e,t){return t==="win32"?`"${e}"`:`'${e.replace(/'/g,"'\\''")}'`}export function quoteArg(e,t){return t==="win32"?e!==""&&!/[\s"&|<>^%]/.test(e)?e:`"${e.replace(/"/g,'\\"')}"`:/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}export function joinCmd(e,t){return e.map(n=>quoteArg(n,t)).join(" ")}export function throughCmd(e,t){return!t||!e||e.length===0?e:["cmd.exe","/k",joinCmd(e,"win32")]}
1
+ export function quotePath(t,n){return n==="win32"?`"${t}"`:`'${t.replace(/'/g,"'\\''")}'`}export function quoteArg(t,n){return n==="win32"?t!==""&&!/[\s"&|<>^%]/.test(t)?t:`"${t.replace(/"/g,'\\"')}"`:/^[A-Za-z0-9_@%+=:,./-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}export function joinCmd(t,n){return t.map(r=>quoteArg(r,n)).join(" ")}export function throughCmd(t,n){return!n||!t||t.length===0?t:["cmd.exe","/k",joinCmd(t,"win32")]}
@@ -1 +1 @@
1
- import{spawn as $}from"node:child_process";import{createHash as z}from"node:crypto";import{readdirSync as M}from"node:fs";import{basename as y,join as I}from"node:path";import{TERMINAL_LOCATOR_ENV as h}from"@weavecode/core";import{joinCmd as k}from"./shared.js";export function parseWeztermPanes(t){if(!t)return[];let n;try{n=JSON.parse(t)}catch{return[]}if(!Array.isArray(n))return[];const r=[];for(const s of n){const e=s;typeof e?.pane_id!="number"||typeof e?.tab_id!="number"||r.push({windowId:typeof e.window_id=="number"?e.window_id:0,tabId:e.tab_id,paneId:e.pane_id,cwd:typeof e.cwd=="string"?e.cwd:null,left:typeof e.left_col=="number"?e.left_col:0,top:typeof e.top_row=="number"?e.top_row:0,isActive:e.is_active===!0,title:typeof e.title=="string"&&e.title?e.title:null})}return r}export function normalizeDirKey(t,n){if(!t)return null;let r=t;if(r.startsWith("file://")){r=r.slice(7);try{r=decodeURIComponent(r)}catch{return null}n==="win32"&&(r=r.replace(/^\//,""))}return r=r.replace(/\\/g,"/").replace(/\/+$/,""),r?n==="win32"?r.toLowerCase():r:null}export function countWindowsByDir(t,n,r=process.platform){const s=t.map(o=>normalizeDirKey(o,r)),e=t.map(()=>new Set);for(const o of n){const i=normalizeDirKey(o.cwd,r);if(!i)continue;const c=o.tabId==null?`${o.muxKey}#${o.windowId}`:`${o.muxKey}#${o.windowId}#${o.tabId}`;for(let u=0;u<t.length;u++)s[u]!==null&&s[u]===i&&e[u].add(c)}return new Map(t.map((o,i)=>[o,e[i].size]))}export const MAX_PANES_PER_SCREEN=6;function _(t,n,r){const s=new Map,e=new Map;for(const c of n)e.set(c.tabId,(e.get(c.tabId)??0)+1),normalizeDirKey(c.cwd,r)===t&&s.set(c.tabId,(s.get(c.tabId)??0)+1);let o=null,i=0;for(const[c,u]of s)(e.get(c)??0)>=MAX_PANES_PER_SCREEN||(o===null||u>i||u===i&&c<o)&&(o=c,i=u);return o}export function planWeztermGrid(t){if(t.length===0||t.length>=MAX_PANES_PER_SCREEN)return null;if(t.length===1)return{paneId:t[0].paneId,direction:"right"};const n=new Map;for(const e of t){const o=n.get(e.left)??[];o.push(e),n.set(e.left,o)}const r=[...n.entries()].sort(([e],[o])=>e-o).map(([,e])=>[...e].sort((o,i)=>i.top-o.top));if(r.length===1)return{paneId:r[0][0].paneId,direction:"right"};let s=r[0];for(const e of r)e.length<s.length&&(s=e);return{paneId:s[0].paneId,direction:"bottom"}}export function planWeztermReuse(t,n,r=process.platform){const s=normalizeDirKey(t,r);if(!s)return null;const e=_(s,n,r);return e===null?null:planWeztermGrid(n.filter(o=>o.tabId===e))}export function planWeztermNewWindow(t,n){const r=["cli","spawn","--new-window","--cwd",t];return n&&r.push("--workspace",n),r}export function weztermMuxKey(t){return z("sha256").update(normalizeDirKey(t,process.platform)??t).digest("hex").slice(0,8)}export function weztermPaneFromEnv(t,n,r){const[s,e]=h.wezterm,o=t[s],i=t[e];if(!o||!i)return null;const c=normalizeDirKey(i,r),u=n.find(l=>normalizeDirKey(l.socket,r)===c);return!u||!u.panes.some(l=>String(l.paneId)===o)?null:`${weztermMuxKey(u.socket)}:${o}`}export function sessionScreensFromEnvs(t,n,r,s=process.platform){const[e,o]=h.wezterm,i=new Set(r.map(u=>normalizeDirKey(u,s))),c={};for(const[u,l]of Object.entries(t)){const a=l[e],d=l[o],w=d?n.find(f=>normalizeDirKey(f.socket,s)===normalizeDirKey(d,s)):void 0,p=w?.panes.find(f=>String(f.paneId)===a);if(w){c[u]=p?{id:`${weztermMuxKey(w.socket)}:${p.windowId}:${p.tabId}`,windowId:p.windowId,tabId:p.tabId,tabsInWindow:new Set(w.panes.filter(f=>f.windowId===p.windowId).map(f=>f.tabId)).size}:null;continue}d&&i.has(normalizeDirKey(d,s))||(c[u]=null)}return c}export function parseAttachTargetId(t){const n=/^([0-9a-f]{8}):(\d+):(\d+)$/.exec(t);return n?{muxKey:n[1],windowId:Number(n[2]),tabId:Number(n[3])}:null}export function attachTargetsFromMuxes(t,n,r=process.platform){const s=normalizeDirKey(t,r);if(!s)return[];const e=[];for(const o of[...n].sort((i,c)=>i.idleMs-c.idleMs)){const i=weztermMuxKey(o.socket),c=new Map;for(const l of o.panes){const a=`${l.windowId}:${l.tabId}`,d=c.get(a)??[];d.push(l),c.set(a,d)}const u=[];for(const[l,a]of c){const d=a.filter(m=>normalizeDirKey(m.cwd,r)===s);if(d.length===0)continue;const w=Number(l.slice(0,l.indexOf(":"))),p=Number(l.slice(l.indexOf(":")+1)),f=a.find(m=>m.isActive)??a[0];u.push({id:`${i}:${w}:${p}`,windowId:w,tabId:p,title:f.title,matchCount:d.length,paneCount:a.length,active:a.some(m=>m.isActive),full:a.length>=MAX_PANES_PER_SCREEN,paneIds:d.map(m=>`${i}:${m.paneId}`)})}u.sort((l,a)=>Number(a.active)-Number(l.active)||a.tabId-l.tabId),e.push(...u)}return e}export async function listAttachTargets(t,n=process.platform){const{muxes:r}=await weztermLiveMuxes();return attachTargetsFromMuxes(t,r,n)}export function weztermActiveClient(t){if(!t)return null;let n;try{n=JSON.parse(t)}catch{return null}if(!Array.isArray(n))return null;let r=null;for(const s of n){const e=s;if(typeof e?.workspace!="string"||!e.workspace)continue;const o=e.idle_time,i=(typeof o?.secs=="number"?o.secs*1e3:0)+(typeof o?.nanos=="number"?o.nanos/1e6:0);(r===null||i<r.idleMs)&&(r={workspace:e.workspace,idleMs:i})}return r}export function weztermActiveWorkspaceOf(t){return weztermActiveClient(t)?.workspace??null}const g=5e3;export function captureCommand(t,n,r,s=g){return new Promise(e=>{let o;try{o=$(t,n,{windowsHide:!0,env:r??process.env})}catch{e(null);return}let i="",c="",u=!1;const l=d=>{u||(u=!0,clearTimeout(a),e(d))};o.stdout.on("data",d=>{i+=d.toString()}),o.stderr?.on("data",d=>{c+=d.toString()});const a=setTimeout(()=>{o.stdout.destroy(),o.stderr?.destroy(),o.unref(),o.kill(),l({ok:!1,out:i,err:c.trim(),timedOut:!0})},s);a.unref(),o.on("error",()=>l(null)),o.on("close",d=>{l({ok:d===0,out:i,err:c.trim(),timedOut:!1})})})}export function weztermCli(t,n){return captureCommand("wezterm",weztermCliArgs(t),{...process.env,WEZTERM_UNIX_SOCKET:n})}export function weztermCliArgs(t){return t[0]==="cli"?["cli","--no-auto-start",...t.slice(1)]:[...t]}export function weztermStepError(t,n,r){const s=`wezterm[${y(n)}] ${t.join(" ")}`;return r===null?`${s}: executable not found`:r.timedOut?`${s}: timed out after ${g}ms`:r.err?`${s}: ${r.err}`:`${s}: exited with failure`}function x(t){try{return process.kill(t,0),!0}catch{return!1}}export async function weztermGuiAlive(t){if(!x(t))return!1;if(process.platform!=="win32")return!0;const n=await captureCommand("tasklist",["/FI",`PID eq ${t}`,"/FO","CSV","/NH"],void 0,2e3);return n?.ok===!0&&/wezterm-gui\.exe/i.test(n.out)}export function weztermGuiPidOf(t){const n=/gui-sock-(\d+)$/.exec(t.replace(/\\/g,"/"));return n?Number(n[1]):null}function b(t){let n;try{n=M(t)}catch{return[]}const r=[];for(const s of n){const e=/^gui-sock-(\d+)$/.exec(s);if(!e)continue;const o=Number(e[1]);x(o)&&r.push({path:I(t,s),pid:o})}return r.sort((s,e)=>e.pid-s.pid).map(s=>s.path)}function S(t,n){const r=t.replace(/\\/g,"/");return n==="win32"?r.toLowerCase():r}export function weztermSocketCandidates(t){const n=[],r=new Set,s=i=>{const c=S(i,t);r.has(c)||(r.add(c),n.push(i))},e=process.env.WEZTERM_UNIX_SOCKET;if(e){const i=weztermGuiPidOf(e);(i===null||x(i))&&s(e)}const o=t==="win32"?process.env.USERPROFILE:process.env.HOME;return o&&b(I(o,".local","share","wezterm")).forEach(s),t!=="win32"&&process.env.XDG_RUNTIME_DIR&&b(I(process.env.XDG_RUNTIME_DIR,"wezterm")).forEach(s),n}const E=6e4;export class SocketProbeGate{dead=new Set;cooling=new Map;shouldProbe(n,r=Date.now()){if(this.dead.has(n))return!1;const s=this.cooling.get(n);return s===void 0||r>=s}succeeded(n){this.cooling.delete(n)}failed(n){this.dead.add(n),this.cooling.delete(n)}cooledDown(n,r=Date.now()){this.dead.has(n)||this.cooling.set(n,r+E)}}export const probeGate=new SocketProbeGate;export async function weztermLiveMuxes(t=!1,n=null){const r=n?[n]:weztermSocketCandidates(process.platform);return{muxes:(await Promise.all(r.map(async e=>{if(!n&&!probeGate.shouldProbe(e))return null;const o=await weztermCli(["cli","list","--format","json"],e);if(!o?.ok){const l=weztermGuiPidOf(e);return o&&!o.timedOut&&l!==null&&!await weztermGuiAlive(l)?probeGate.failed(e):probeGate.cooledDown(e),null}probeGate.succeeded(e);const i=parseWeztermPanes(o.out);if(t)return{socket:e,panes:i,workspace:null,idleMs:Number.POSITIVE_INFINITY};const c=await weztermCli(["cli","list-clients","--format","json"],e),u=weztermActiveClient(c?.ok?c.out:null);return{socket:e,panes:i,workspace:u?.workspace??null,idleMs:u?.idleMs??Number.POSITIVE_INFINITY}}))).filter(e=>e!==null),candidates:r}}export async function weztermMuxForId(t){const n=weztermSocketCandidates(process.platform).find(s=>weztermMuxKey(s)===t);if(!n)return null;const{muxes:r}=await weztermLiveMuxes(!0,n);return r.find(s=>weztermMuxKey(s.socket)===t)??null}export async function openInWezterm(t){const{muxes:n}=await weztermLiveMuxes();if(n.length===0)return!1;const r=n.reduce((s,e)=>e.idleMs<s.idleMs?e:s);return await weztermSpawnPane(r.socket,t,null,r.workspace),!0}export async function runInWezterm(t,n){const r=process.platform,{muxes:s}=await weztermLiveMuxes();if(s.length===0)return null;let e=null,o=null;for(const i of s){const c=planWeztermReuse(t,i.panes,r);c&&(e===null||i.idleMs<e.idleMs)&&(e=i,o=c)}return e??=s.reduce((i,c)=>c.idleMs<i.idleMs?c:i),weztermSpawnAndSend(e.socket,t,n,o,e.workspace)}export async function weztermSpawnPane(t,n,r,s){const e=r?["cli","split-pane","--pane-id",String(r.paneId),`--${r.direction}`,"--cwd",n]:planWeztermNewWindow(n,s),o=await weztermCli(e,t);if(!o?.ok)throw new Error(weztermStepError(e,t,o));const i=o.out.trim();if(!/^\d+$/.test(i))throw new Error(`wezterm[${y(t)}] ${e.join(" ")}: unexpected pane id "${i}"`);return i}export async function weztermSpawnAndSend(t,n,r,s,e,o=process.platform){const i=await weztermSpawnPane(t,n,s,e),c=["cli","send-text","--pane-id",i,"--no-paste",`${k(r,o)}\r`],u=await weztermCli(c,t);if(!u?.ok)throw new Error(weztermStepError(c,t,u));const[l,a]=h.wezterm;return{env:{[l]:i,[a]:t}}}
1
+ import{spawn as k}from"node:child_process";import{createHash as $}from"node:crypto";import{readdirSync as z}from"node:fs";import{basename as b,join as I}from"node:path";import{TERMINAL_LOCATOR_ENV as h}from"@weavecode/core";import{joinCmd as M}from"./shared.js";export function parseWeztermPanes(e){if(!e)return[];let t;try{t=JSON.parse(e)}catch{return[]}if(!Array.isArray(t))return[];const n=[];for(const r of t){const o=r;typeof o?.pane_id!="number"||typeof o?.tab_id!="number"||n.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 n}export function normalizeDirKey(e,t){if(!e)return null;let n=e;if(n.startsWith("file://")){n=n.slice(7);try{n=decodeURIComponent(n)}catch{return null}t==="win32"&&(n=n.replace(/^\//,""))}return n=n.replace(/\\/g,"/").replace(/\/+$/,""),n?t==="win32"?n.toLowerCase():n:null}export function countWindowsByDir(e,t,n=process.platform){const r=e.map(s=>normalizeDirKey(s,n)),o=e.map(()=>new Set);for(const s of t){const i=normalizeDirKey(s.cwd,n);if(!i)continue;const c=s.tabId==null?`${s.muxKey}#${s.windowId}`:`${s.muxKey}#${s.windowId}#${s.tabId}`;for(let a=0;a<e.length;a++)r[a]!==null&&r[a]===i&&o[a].add(c)}return new Map(e.map((s,i)=>[s,o[i].size]))}export const MAX_PANES_PER_SCREEN=6;function S(e,t,n){const r=new Map,o=new Map;for(const c of t)o.set(c.tabId,(o.get(c.tabId)??0)+1),normalizeDirKey(c.cwd,n)===e&&r.set(c.tabId,(r.get(c.tabId)??0)+1);let s=null,i=0;for(const[c,a]of r)(o.get(c)??0)>=MAX_PANES_PER_SCREEN||(s===null||a>i||a===i&&c<s)&&(s=c,i=a);return s}export function planWeztermGrid(e){if(e.length===0||e.length>=MAX_PANES_PER_SCREEN)return null;if(e.length===1)return{paneId:e[0].paneId,direction:"right"};const t=new Map;for(const o of e){const s=t.get(o.left)??[];s.push(o),t.set(o.left,s)}const n=[...t.entries()].sort(([o],[s])=>o-s).map(([,o])=>[...o].sort((s,i)=>i.top-s.top));if(n.length===1)return{paneId:n[0][0].paneId,direction:"right"};let r=n[0];for(const o of n)o.length<r.length&&(r=o);return{paneId:r[0].paneId,direction:"bottom"}}export function planWeztermReuse(e,t,n=process.platform){const r=normalizeDirKey(e,n);if(!r)return null;const o=S(r,t,n);return o===null?null:planWeztermGrid(t.filter(s=>s.tabId===o))}export function planWeztermNewWindow(e,t){const n=["cli","spawn","--new-window","--cwd",e];return t&&n.push("--workspace",t),n}export function weztermMuxKey(e){return $("sha256").update(normalizeDirKey(e,process.platform)??e).digest("hex").slice(0,8)}export function weztermPaneFromEnv(e,t,n){const[r,o]=h.wezterm,s=e[r],i=e[o];if(!s||!i)return null;const c=normalizeDirKey(i,n),a=t.find(u=>normalizeDirKey(u.socket,n)===c);return!a||!a.panes.some(u=>String(u.paneId)===s)?null:`${weztermMuxKey(a.socket)}:${s}`}export function sessionScreensFromEnvs(e,t,n,r=process.platform){const[o,s]=h.wezterm,i=new Set(n.map(a=>normalizeDirKey(a,r))),c={};for(const[a,u]of Object.entries(e)){const l=u[o],d=u[s],w=d?t.find(f=>normalizeDirKey(f.socket,r)===normalizeDirKey(d,r)):void 0,p=w?.panes.find(f=>String(f.paneId)===l);if(w){c[a]=p?{id:`${weztermMuxKey(w.socket)}:${p.windowId}:${p.tabId}`,windowId:p.windowId,tabId:p.tabId,tabsInWindow:new Set(w.panes.filter(f=>f.windowId===p.windowId).map(f=>f.tabId)).size}:null;continue}d&&i.has(normalizeDirKey(d,r))||(c[a]=null)}return c}export function parseAttachTargetId(e){const t=/^([0-9a-f]{8}):(\d+):(\d+)$/.exec(e);return t?{muxKey:t[1],windowId:Number(t[2]),tabId:Number(t[3])}:null}export function attachTargetsFromMuxes(e,t,n=process.platform){const r=normalizeDirKey(e,n);if(!r)return[];const o=[];for(const s of[...t].sort((i,c)=>i.idleMs-c.idleMs)){const i=weztermMuxKey(s.socket),c=new Map;for(const u of s.panes){const l=`${u.windowId}:${u.tabId}`,d=c.get(l)??[];d.push(u),c.set(l,d)}const a=[];for(const[u,l]of c){const d=l.filter(m=>normalizeDirKey(m.cwd,n)===r);if(d.length===0)continue;const w=Number(u.slice(0,u.indexOf(":"))),p=Number(u.slice(u.indexOf(":")+1)),f=l.find(m=>m.isActive)??l[0];a.push({id:`${i}:${w}:${p}`,windowId:w,tabId:p,title:f.title,matchCount:d.length,paneCount:l.length,active:l.some(m=>m.isActive),full:l.length>=MAX_PANES_PER_SCREEN,paneIds:d.map(m=>`${i}:${m.paneId}`)})}a.sort((u,l)=>Number(l.active)-Number(u.active)||l.tabId-u.tabId),o.push(...a)}return o}export async function listAttachTargets(e,t=process.platform){const{muxes:n}=await weztermLiveMuxes();return attachTargetsFromMuxes(e,n,t)}export function weztermActiveClient(e){if(!e)return null;let t;try{t=JSON.parse(e)}catch{return null}if(!Array.isArray(t))return null;let n=null;for(const r of t){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);(n===null||i<n.idleMs)&&(n={workspace:o.workspace,idleMs:i})}return n}export function weztermActiveWorkspaceOf(e){return weztermActiveClient(e)?.workspace??null}const g=5e3;export function captureCommand(e,t,n,r=g){return new Promise(o=>{let s;try{s=k(e,t,{windowsHide:!0,env:n??process.env})}catch{o(null);return}let i="",c="",a=!1;const u=d=>{a||(a=!0,clearTimeout(l),o(d))};s.stdout.on("data",d=>{i+=d.toString()}),s.stderr?.on("data",d=>{c+=d.toString()});const l=setTimeout(()=>{s.stdout.destroy(),s.stderr?.destroy(),s.unref(),s.kill(),u({ok:!1,out:i,err:c.trim(),timedOut:!0})},r);l.unref(),s.on("error",()=>u(null)),s.on("close",d=>{u({ok:d===0,out:i,err:c.trim(),timedOut:!1})})})}export function weztermCli(e,t){return captureCommand("wezterm",weztermCliArgs(e),{...process.env,WEZTERM_UNIX_SOCKET:t})}export function weztermCliArgs(e){return e[0]==="cli"?["cli","--no-auto-start",...e.slice(1)]:[...e]}export function weztermStepError(e,t,n){const r=`wezterm[${b(t)}] ${e.join(" ")}`;return n===null?`${r}: executable not found`:n.timedOut?`${r}: timed out after ${g}ms`:n.err?`${r}: ${n.err}`:`${r}: exited with failure`}function x(e){try{return process.kill(e,0),!0}catch{return!1}}export async function weztermGuiAlive(e){if(!x(e))return!1;if(process.platform!=="win32")return!0;const t=await captureCommand("tasklist",["/FI",`PID eq ${e}`,"/FO","CSV","/NH"],void 0,2e3);return t?.ok===!0&&/wezterm-gui\.exe/i.test(t.out)}export function weztermGuiPidOf(e){const t=/gui-sock-(\d+)$/.exec(e.replace(/\\/g,"/"));return t?Number(t[1]):null}function y(e){let t;try{t=z(e)}catch{return[]}const n=[];for(const r of t){const o=/^gui-sock-(\d+)$/.exec(r);if(!o)continue;const s=Number(o[1]);x(s)&&n.push({path:I(e,r),pid:s})}return n.sort((r,o)=>o.pid-r.pid).map(r=>r.path)}function E(e,t){const n=e.replace(/\\/g,"/");return t==="win32"?n.toLowerCase():n}export function weztermSocketCandidates(e){const t=[],n=new Set,r=i=>{const c=E(i,e);n.has(c)||(n.add(c),t.push(i))},o=process.env.WEZTERM_UNIX_SOCKET;if(o){const i=weztermGuiPidOf(o);(i===null||x(i))&&r(o)}const s=e==="win32"?process.env.USERPROFILE:process.env.HOME;return s&&y(I(s,".local","share","wezterm")).forEach(r),e!=="win32"&&process.env.XDG_RUNTIME_DIR&&y(I(process.env.XDG_RUNTIME_DIR,"wezterm")).forEach(r),t}const _=6e4;export class SocketProbeGate{dead=new Set;cooling=new Map;shouldProbe(t,n=Date.now()){if(this.dead.has(t))return!1;const r=this.cooling.get(t);return r===void 0||n>=r}succeeded(t){this.cooling.delete(t)}failed(t){this.dead.add(t),this.cooling.delete(t)}cooledDown(t,n=Date.now()){this.dead.has(t)||this.cooling.set(t,n+_)}}export const probeGate=new SocketProbeGate;export async function weztermLiveMuxes(e=!1,t=null){const n=t?[t]:weztermSocketCandidates(process.platform);return{muxes:(await Promise.all(n.map(async r=>{if(!t&&!probeGate.shouldProbe(r))return null;const o=await weztermCli(["cli","list","--format","json"],r);if(!o?.ok){const a=weztermGuiPidOf(r);return o&&!o.timedOut&&a!==null&&!await weztermGuiAlive(a)?probeGate.failed(r):probeGate.cooledDown(r),null}probeGate.succeeded(r);const s=parseWeztermPanes(o.out);if(e)return{socket:r,panes:s,workspace:null,idleMs:Number.POSITIVE_INFINITY};const i=await weztermCli(["cli","list-clients","--format","json"],r),c=weztermActiveClient(i?.ok?i.out:null);return{socket:r,panes:s,workspace:c?.workspace??null,idleMs:c?.idleMs??Number.POSITIVE_INFINITY}}))).filter(r=>r!==null),candidates:n}}export async function weztermMuxForId(e){const t=weztermSocketCandidates(process.platform).find(r=>weztermMuxKey(r)===e);if(!t)return null;const{muxes:n}=await weztermLiveMuxes(!0,t);return n.find(r=>weztermMuxKey(r.socket)===e)??null}export async function openInWezterm(e){const{muxes:t}=await weztermLiveMuxes();if(t.length===0)return!1;const n=t.reduce((r,o)=>o.idleMs<r.idleMs?o:r);return await weztermSpawnPane(n.socket,e,null,n.workspace),!0}export async function runInWezterm(e,t){const n=process.platform,{muxes:r}=await weztermLiveMuxes();if(r.length===0)return null;let o=null,s=null;for(const i of r){const c=planWeztermReuse(e,i.panes,n);c&&(o===null||i.idleMs<o.idleMs)&&(o=i,s=c)}return o??=r.reduce((i,c)=>c.idleMs<i.idleMs?c:i),weztermSpawnAndSend(o.socket,e,t,s,o.workspace)}export async function weztermSpawnPane(e,t,n,r){const o=n?["cli","split-pane","--pane-id",String(n.paneId),`--${n.direction}`,"--cwd",t]:planWeztermNewWindow(t,r),s=await weztermCli(o,e);if(!s?.ok)throw new Error(weztermStepError(o,e,s));const i=s.out.trim();if(!/^\d+$/.test(i))throw new Error(`wezterm[${b(e)}] ${o.join(" ")}: unexpected pane id "${i}"`);return i}export async function weztermSpawnAndSend(e,t,n,r,o,s=process.platform){const i=await weztermSpawnPane(e,t,r,o),c=["cli","send-text","--pane-id",i,"--no-paste",`${M(n,s)}\r`],a=await weztermCli(c,e);if(!a?.ok)throw new Error(weztermStepError(c,e,a));const[u,l]=h.wezterm;return{env:{[u]:i,[l]:e}}}
@@ -1,6 +1,6 @@
1
- import{createHash as p}from"node:crypto";import{TERMINAL_LOCATOR_ENV as f}from"@weavecode/core";import{captureCommand as u,normalizeDirKey as P}from"./wezterm-mux.js";const h=["$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(`
2
- `),I=15e3;export function parseWtProcDump(t){const e=[];for(const n of t.split(`
3
- `)){const o=n.trimEnd().split("|");if(o.length!==5)continue;const r=Number(o[0]),i=Number(o[1]);!Number.isInteger(r)||!Number.isInteger(i)||r<=0||i<0||o[2]&&e.push({pid:r,parentPid:i,name:o[2].toLowerCase(),created:o[3],cwd:o[4]===""?null:o[4]})}return e}const d=new Set(["bash.exe","zsh.exe","sh.exe","fish.exe","pwsh.exe","powershell.exe","cmd.exe"]);export function wtPanes(t){const e=new Set(t.filter(r=>r.name==="windowsterminal.exe").map(r=>r.pid));if(e.size===0)return[];const n=new Map;for(const r of t){if(r.parentPid===r.pid)continue;const i=n.get(r.parentPid)??[];i.push(r),n.set(r.parentPid,i)}const o=[];for(const r of t){if(!e.has(r.parentPid)||r.name==="openconsole.exe")continue;let i=r;for(;d.has(i.name);){const c=(n.get(i.pid)??[]).filter(s=>d.has(s.name));if(c.length===0)break;i=c.reduce((s,a)=>a.created>s.created||a.created===s.created&&a.pid>s.pid?a:s)}o.push({pid:r.pid,cwd:i.cwd})}return o}export function wtPanesAsWindows(t){return t.map(e=>({muxKey:`wt:${e.pid}`,windowId:e.pid,cwd:e.cwd}))}async function w(){if(process.platform!=="win32")return[];const t=await u("powershell.exe",["-NoProfile","-Command",h],void 0,I);return t?.ok?wtPanes(parseWtProcDump(t.out)):[]}let l=null;export async function wtPanesCached(){if(l&&Date.now()-l.at<1e4)return l.panes;const t=await w();return l={at:Date.now(),panes:t},t}export function wtWindowSlug(t){const e=P(t,"win32")??"root",n=e.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),o=p("sha1").update(e).digest("hex").slice(0,8);return`weave-${n.slice(0,48)||"root"}-${o}`}export function parseWtTargetId(t){const e=/^wt:(weave-[a-z0-9-]+)$/.exec(t);return e?e[1]:null}export function parseWtPaneId(t){const e=/^wt:(\d+)$/.exec(t);if(!e)return null;const n=Number(e[1]);return Number.isInteger(n)&&n>0?n:null}export function wtPanePidFromEnv(t){const[e,n]=f.wt;if(!t[e])return null;const o=t[n];if(!o||!/^\d+$/.test(o))return null;const r=Number(o);return r>0?r:null}export const BRACKETED_PASTE_START="\x1B[200~",BRACKETED_PASTE_END="\x1B[201~";export async function wtInjectKeys(t,e){const n=await u("powershell",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-EncodedCommand",wtInjectEncodedScript()],{...process.env,WEAVE_WT_PID:String(t),WEAVE_WT_KEYS:Buffer.from(e,"utf8").toString("base64")},15e3);if(!n)throw new Error("powershell is unavailable \u2014 cannot send keys into Windows Terminal");if(!n.ok)throw n.timedOut?new Error("Windows Terminal key injection timed out"):new Error(`Windows Terminal key injection failed: ${n.err||n.out||"unknown error"}`)}export function wtInjectEncodedScript(){const t=`$ErrorActionPreference = 'Stop'
1
+ import{createHash as p}from"node:crypto";import{TERMINAL_LOCATOR_ENV as f}from"@weavecode/core";import{captureCommand as c,normalizeDirKey as I}from"./wezterm-mux.js";const h=["$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(`
2
+ `),P=15e3;export function parseWtProcDump(t){const e=[];for(const n of t.split(`
3
+ `)){const o=n.trimEnd().split("|");if(o.length!==5)continue;const r=Number(o[0]),i=Number(o[1]);!Number.isInteger(r)||!Number.isInteger(i)||r<=0||i<0||o[2]&&e.push({pid:r,parentPid:i,name:o[2].toLowerCase(),created:o[3],cwd:o[4]===""?null:o[4]})}return e}const d=new Set(["bash.exe","zsh.exe","sh.exe","fish.exe","pwsh.exe","powershell.exe","cmd.exe"]);export function wtPanes(t){const e=new Set(t.filter(r=>r.name==="windowsterminal.exe").map(r=>r.pid));if(e.size===0)return[];const n=new Map;for(const r of t){if(r.parentPid===r.pid)continue;const i=n.get(r.parentPid)??[];i.push(r),n.set(r.parentPid,i)}const o=[];for(const r of t){if(!e.has(r.parentPid)||r.name==="openconsole.exe")continue;let i=r;for(;d.has(i.name);){const u=(n.get(i.pid)??[]).filter(a=>d.has(a.name));if(u.length===0)break;i=u.reduce((a,s)=>s.created>a.created||s.created===a.created&&s.pid>a.pid?s:a)}o.push({pid:r.pid,cwd:i.cwd})}return o}export function wtPanesAsWindows(t){return t.map(e=>({muxKey:`wt:${e.pid}`,windowId:e.pid,cwd:e.cwd}))}async function w(){if(process.platform!=="win32")return[];const t=await c("powershell.exe",["-NoProfile","-Command",h],void 0,P);return t?.ok?wtPanes(parseWtProcDump(t.out)):[]}let l=null;export async function wtPanesCached(){if(l&&Date.now()-l.at<1e4)return l.panes;const t=await w();return l={at:Date.now(),panes:t},t}export function wtWindowSlug(t){const e=I(t,"win32")??"root",n=e.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),o=p("sha1").update(e).digest("hex").slice(0,8);return`weave-${n.slice(0,48)||"root"}-${o}`}export function parseWtTargetId(t){const e=/^wt:(weave-[a-z0-9-]+)$/.exec(t);return e?e[1]:null}export function parseWtPaneId(t){const e=/^wt:(\d+)$/.exec(t);if(!e)return null;const n=Number(e[1]);return Number.isInteger(n)&&n>0?n:null}export function wtPanePidFromEnv(t){const[e,n]=f.wt;if(!t[e])return null;const o=t[n];if(!o||!/^\d+$/.test(o))return null;const r=Number(o);return r>0?r:null}export const BRACKETED_PASTE_START="\x1B[200~",BRACKETED_PASTE_END="\x1B[201~";export async function wtInjectKeys(t,e){const n=await c("powershell",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-EncodedCommand",wtInjectEncodedScript()],{...process.env,WEAVE_WT_PID:String(t),WEAVE_WT_KEYS:Buffer.from(e,"utf8").toString("base64")},15e3);if(!n)throw new Error("powershell is unavailable \u2014 cannot send keys into Windows Terminal");if(!n.ok)throw n.timedOut?new Error("Windows Terminal key injection timed out"):new Error(`Windows Terminal key injection failed: ${n.err||n.out||"unknown error"}`)}export function wtInjectEncodedScript(){const t=`$ErrorActionPreference = 'Stop'
4
4
  Add-Type -TypeDefinition @'
5
5
  ${m}
6
6
  '@
@@ -51,6 +51,8 @@ export declare function promptTerminalChannel(settings: () => TerminalSettings):
51
51
  locateScreens(envs: Record<string, Record<string, string>>): Promise<Record<string, SessionTerminal | null>>;
52
52
  sendText(paneId: string, text: string): Promise<void>;
53
53
  sendKeys(paneId: string, keys: string): Promise<void>;
54
+ /** 读 pane 可视屏(中断后的读屏确认:宿主吞掉 ESC 时才补打)。 */
55
+ getPaneText(paneId: string): Promise<string | null>;
54
56
  closePane(paneId: string): Promise<void>;
55
57
  };
56
58
  /**
@@ -1 +1 @@
1
- import{TERMINAL_LOCATOR_ENV as h}from"@weavecode/core";import{readDaemonSettings as B}from"./settings.js";import{normalizeDirKey as P}from"./opener/wezterm-mux.js";import{KonsoleBackend as E}from"./opener/backend-konsole.js";import{ItermBackend as A}from"./opener/backend-iterm.js";import{GhosttyBackend as I}from"./opener/backend-ghostty.js";import{TerminalAppBackend as k}from"./opener/backend-terminal-app.js";import{WtBackend as T}from"./opener/backend-wt.js";import{WeztermBackend as x}from"./opener/backend-wezterm.js";import{CandidatesBackend as u,CustomBackend as b,PRESET_CANDIDATES as w,TerminalBackend as S,trySpawn as W}from"./opener/backend.js";export{parseTerminalAppDump,parseTerminalAppTargetId,parsePsRootPids,parseLsofCwds,pickTerminalAppWindow,terminalAppTargets}from"./opener/pty-terminals.js";export{winRaiseEncodedScript}from"./opener/win-raise.js";export{parseWtPaneId,parseWtProcDump,parseWtTargetId,wtInjectEncodedScript,wtPanePidFromEnv,wtPanes,wtWindowSlug}from"./opener/wt.js";export{quotePath}from"./opener/shared.js";export{attachTargetsFromMuxes,countWindowsByDir,listAttachTargets,normalizeDirKey,parseAttachTargetId,parseWeztermPanes,planWeztermNewWindow,planWeztermReuse,sessionScreensFromEnvs,SocketProbeGate,weztermActiveWorkspaceOf,weztermCliArgs,weztermMuxKey,weztermPaneFromEnv,weztermSocketCandidates}from"./opener/wezterm-mux.js";export{planWeztermGrid}from"./opener/wezterm-mux.js";export{konsolePaneFromEnv,parseKonsolePaneId,qtKeyOf}from"./opener/backend-konsole.js";export{applescriptString,itermPaneFromEnv,parseItermPaneId}from"./opener/backend-iterm.js";export{parsePromptPaneId,runInWeztermAt}from"./opener/backend-wezterm.js";export{CandidatesBackend,CustomBackend,PRESET_CANDIDATES,TerminalBackend,trySpawn}from"./opener/backend.js";class z extends S{parts;constructor(e){super("auto",!0,e,e!=="win32"&&e!=="darwin");const a={win32:["wt","powershell","cmd"],darwin:["terminal","iterm"]}[e]??["gnome","konsole"];this.parts=a.map(s=>new u(s,e,w[s]))}candidates(e,n){return this.parts.flatMap(a=>n&&a.preset==="iterm"?[]:a.candidates(e,n))}attachBackend(){return this.platform==="darwin"?new k(this.platform):this.platform==="win32"?new T(this.platform):new x(this.platform)}countWindows(e){return this.attachBackend().countWindows(e)}listTargets(e){return this.attachBackend().listTargets(e)}runAt(e,n,a){return this.attachBackend().runAt(e,n,a)}focusTarget(e,n){return this.attachBackend().focusTarget(e,n)}listPromptPanes(){return this.attachBackend().listPromptPanes()}locatePane(e){return this.attachBackend().locatePane(e)}locateScreens(e){return this.attachBackend().locateScreens(e)}sendPromptText(e,n){return this.attachBackend().sendPromptText(e,n)}sendKeys(e,n){return this.attachBackend().sendKeys(e,n)}getPaneText(e){return this.attachBackend().getPaneText(e)}closePane(e){return this.attachBackend().closePane(e)}}const g={auto:(t,e)=>new z(e),wt:(t,e)=>new T(e),powershell:(t,e)=>new u("powershell",e,w.powershell),cmd:(t,e)=>new u("cmd",e,w.cmd),terminal:(t,e)=>new k(e),iterm:(t,e)=>new A(e),gnome:(t,e)=>new u("gnome",e,w.gnome),konsole:(t,e)=>new E(e),ghostty:(t,e)=>new I(e),wezterm:(t,e)=>new x(e),custom:(t,e)=>new b(t,e)};export function terminalBackendFor(t,e=process.platform){return(g[t.preset]??g.auto)(t,e)}export function locatorPresetOf(t){for(const[e,n]of Object.entries(h))if(n.every(a=>t[a]))return e;return null}export function promptTerminalChannel(t){const e=r=>terminalBackendFor({...t(),preset:r}),n=()=>e(t().preset),a=()=>Object.keys(h).map(r=>e(r)),s=r=>{const o=locatorPresetOf(r);return o?e(o):null},c=r=>a().find(o=>o.ownsPaneId(r))??null;return{available:()=>a().some(r=>r.textAddressable),listPanes:async()=>{const r=n();return r.textAddressable?await r.listPromptPanes():[]},locatePane:async r=>await s(r)?.locatePane(r)??null,locateScreens:async r=>{const o={},i=new Map;for(const[l,m]of Object.entries(r)){const p=locatorPresetOf(m);if(!p){o[l]=null;continue}const d=i.get(p)??{};d[l]=m,i.set(p,d)}for(const[l,m]of i){const p=e(l);if(!p.locateScreens){for(const f of Object.keys(m))o[f]=null;continue}const d=await p.locateScreens(m);for(const[f,y]of Object.entries(d))o[f]=y}return o},sendText:async(r,o)=>{const i=c(r);if(!i)throw new Error(`Invalid prompt pane "${r}"`);await i.sendPromptText(r,o)},sendKeys:async(r,o)=>{const i=c(r);if(!i)throw new Error(`Invalid prompt pane "${r}"`);await i.sendKeys(r,o)},closePane:async r=>{const o=c(r);if(!o)throw new Error(`Invalid prompt pane "${r}"`);await o.closePane(r)}}}export async function runInTerminal(t,e,n){return terminalBackendFor(n).run(t,e)}export async function countOpenTerminals(t,e){return terminalBackendFor(e).countWindows(t)}export function panesAtDir(t,e,n=process.platform){const a=P(e,n);return t.filter(s=>s.cwd!=null&&P(s.cwd,n)===a)}export async function listProjectPanes(t,e,n=process.platform){const a=terminalBackendFor(e,n),s=panesAtDir(await a.listPromptPanes(),t,n);if(s.length===0&&((await a.countWindows([t])).get(t)??0)>0)throw new Error(`Terminal preset "${a.preset}" cannot close open panes remotely \u2014 pick wezterm in settings`);return s}export async function closeTerminalsIn(t,e,n,a=process.platform){const s=terminalBackendFor(e,a),c=new Set(n),r=(await listProjectPanes(t,e,a)).filter(o=>c.has(o.id));for(const o of r)await s.closePane(o.id);return r.length}export async function readTerminalCounts(t,e=void 0){const n=await B(),s=await(e?.countTerminals??countOpenTerminals)(t.map(c=>c.path),n.terminal);return Object.fromEntries(t.map(c=>[c.id,s.get(c.path)??0]))}export function resolveTerminalLaunch(t,e,n=process.platform,a){return terminalBackendFor(e,n).candidates(t,a)}export function resolveExplorerLaunch(t,e=process.platform){return e==="win32"?{command:"explorer.exe",args:[t]}:e==="darwin"?{command:"open",args:[t]}:{command:"xdg-open",args:[t]}}export async function openInExplorer(t){const e=resolveExplorerLaunch(t);if(!await W(e))throw new Error(`Failed to open file manager (${e.command})`)}export async function openInTerminal(t,e){await terminalBackendFor(e).open(t)}export const defaultProjectOpener={openExplorer:openInExplorer,openTerminal:openInTerminal,runInTerminal,countTerminals:countOpenTerminals,closeTerminals:(t,e,n)=>closeTerminalsIn(t,e,n),listPanes:(t,e)=>listProjectPanes(t,e),listTerminals:(t,e)=>terminalBackendFor(e).listTargets(t),runInTerminalAt:(t,e,n,a)=>terminalBackendFor(a).runAt(t,e,n),focusTerminal:(t,e,n)=>terminalBackendFor(n).focusTarget(t,e)};
1
+ import{TERMINAL_LOCATOR_ENV as h}from"@weavecode/core";import{readDaemonSettings as B}from"./settings.js";import{normalizeDirKey as P}from"./opener/wezterm-mux.js";import{KonsoleBackend as E}from"./opener/backend-konsole.js";import{ItermBackend as I}from"./opener/backend-iterm.js";import{GhosttyBackend as A}from"./opener/backend-ghostty.js";import{TerminalAppBackend as T}from"./opener/backend-terminal-app.js";import{WtBackend as x}from"./opener/backend-wt.js";import{WeztermBackend as g}from"./opener/backend-wezterm.js";import{CandidatesBackend as u,CustomBackend as S,PRESET_CANDIDATES as w,TerminalBackend as W,trySpawn as v}from"./opener/backend.js";export{parseTerminalAppDump,parseTerminalAppTargetId,parsePsRootPids,parseLsofCwds,pickTerminalAppWindow,terminalAppTargets}from"./opener/pty-terminals.js";export{winRaiseEncodedScript}from"./opener/win-raise.js";export{parseWtPaneId,parseWtProcDump,parseWtTargetId,wtInjectEncodedScript,wtPanePidFromEnv,wtPanes,wtWindowSlug}from"./opener/wt.js";export{quotePath}from"./opener/shared.js";export{attachTargetsFromMuxes,countWindowsByDir,listAttachTargets,normalizeDirKey,parseAttachTargetId,parseWeztermPanes,planWeztermNewWindow,planWeztermReuse,sessionScreensFromEnvs,SocketProbeGate,weztermActiveWorkspaceOf,weztermCliArgs,weztermMuxKey,weztermPaneFromEnv,weztermSocketCandidates}from"./opener/wezterm-mux.js";export{planWeztermGrid}from"./opener/wezterm-mux.js";export{konsolePaneFromEnv,parseKonsolePaneId,qtKeyOf}from"./opener/backend-konsole.js";export{applescriptString,itermPaneFromEnv,parseItermPaneId}from"./opener/backend-iterm.js";export{parsePromptPaneId,runInWeztermAt}from"./opener/backend-wezterm.js";export{CandidatesBackend,CustomBackend,PRESET_CANDIDATES,TerminalBackend,trySpawn}from"./opener/backend.js";class z extends W{parts;constructor(e){super("auto",!0,e,e!=="win32"&&e!=="darwin");const n={win32:["wt","powershell","cmd"],darwin:["terminal","iterm"]}[e]??["gnome","konsole"];this.parts=n.map(a=>new u(a,e,w[a]))}candidates(e,n){return this.parts.flatMap(a=>n&&a.preset==="iterm"?[]:a.candidates(e,n))}attachBackend(){return this.platform==="darwin"?new T(this.platform):this.platform==="win32"?new x(this.platform):new g(this.platform)}countWindows(e){return this.attachBackend().countWindows(e)}listTargets(e){return this.attachBackend().listTargets(e)}runAt(e,n,a){return this.attachBackend().runAt(e,n,a)}focusTarget(e,n){return this.attachBackend().focusTarget(e,n)}listPromptPanes(){return this.attachBackend().listPromptPanes()}locatePane(e){return this.attachBackend().locatePane(e)}locateScreens(e){return this.attachBackend().locateScreens(e)}sendPromptText(e,n){return this.attachBackend().sendPromptText(e,n)}sendKeys(e,n){return this.attachBackend().sendKeys(e,n)}getPaneText(e){return this.attachBackend().getPaneText(e)}closePane(e){return this.attachBackend().closePane(e)}}const k={auto:(t,e)=>new z(e),wt:(t,e)=>new x(e),powershell:(t,e)=>new u("powershell",e,w.powershell),cmd:(t,e)=>new u("cmd",e,w.cmd),terminal:(t,e)=>new T(e),iterm:(t,e)=>new I(e),gnome:(t,e)=>new u("gnome",e,w.gnome),konsole:(t,e)=>new E(e),ghostty:(t,e)=>new A(e),wezterm:(t,e)=>new g(e),custom:(t,e)=>new S(t,e)};export function terminalBackendFor(t,e=process.platform){return(k[t.preset]??k.auto)(t,e)}export function locatorPresetOf(t){for(const[e,n]of Object.entries(h))if(n.every(a=>t[a]))return e;return null}export function promptTerminalChannel(t){const e=r=>terminalBackendFor({...t(),preset:r}),n=()=>e(t().preset),a=()=>Object.keys(h).map(r=>e(r)),s=r=>{const o=locatorPresetOf(r);return o?e(o):null},i=r=>a().find(o=>o.ownsPaneId(r))??null;return{available:()=>a().some(r=>r.textAddressable),listPanes:async()=>{const r=n();return r.textAddressable?await r.listPromptPanes():[]},locatePane:async r=>await s(r)?.locatePane(r)??null,locateScreens:async r=>{const o={},c=new Map;for(const[l,m]of Object.entries(r)){const p=locatorPresetOf(m);if(!p){o[l]=null;continue}const d=c.get(p)??{};d[l]=m,c.set(p,d)}for(const[l,m]of c){const p=e(l);if(!p.locateScreens){for(const f of Object.keys(m))o[f]=null;continue}const d=await p.locateScreens(m);for(const[f,y]of Object.entries(d))o[f]=y}return o},sendText:async(r,o)=>{const c=i(r);if(!c)throw new Error(`Invalid prompt pane "${r}"`);await c.sendPromptText(r,o)},sendKeys:async(r,o)=>{const c=i(r);if(!c)throw new Error(`Invalid prompt pane "${r}"`);await c.sendKeys(r,o)},getPaneText:async r=>{const o=i(r);if(!o)throw new Error(`Invalid prompt pane "${r}"`);return o.getPaneText(r)},closePane:async r=>{const o=i(r);if(!o)throw new Error(`Invalid prompt pane "${r}"`);await o.closePane(r)}}}export async function runInTerminal(t,e,n){return terminalBackendFor(n).run(t,e)}export async function countOpenTerminals(t,e){return terminalBackendFor(e).countWindows(t)}export function panesAtDir(t,e,n=process.platform){const a=P(e,n);return t.filter(s=>s.cwd!=null&&P(s.cwd,n)===a)}export async function listProjectPanes(t,e,n=process.platform){const a=terminalBackendFor(e,n),s=panesAtDir(await a.listPromptPanes(),t,n);if(s.length===0&&((await a.countWindows([t])).get(t)??0)>0)throw new Error(`Terminal preset "${a.preset}" cannot close open panes remotely \u2014 pick wezterm in settings`);return s}export async function closeTerminalsIn(t,e,n,a=process.platform){const s=terminalBackendFor(e,a),i=new Set(n),r=(await listProjectPanes(t,e,a)).filter(o=>i.has(o.id));for(const o of r)await s.closePane(o.id);return r.length}export async function readTerminalCounts(t,e=void 0){const n=await B(),a=await(e?.countTerminals??countOpenTerminals)(t.map(s=>s.path),n.terminal);return Object.fromEntries(t.map(s=>[s.id,a.get(s.path)??0]))}export function resolveTerminalLaunch(t,e,n=process.platform,a){return terminalBackendFor(e,n).candidates(t,a)}export function resolveExplorerLaunch(t,e=process.platform){return e==="win32"?{command:"explorer.exe",args:[t]}:e==="darwin"?{command:"open",args:[t]}:{command:"xdg-open",args:[t]}}export async function openInExplorer(t){const e=resolveExplorerLaunch(t);if(!await v(e))throw new Error(`Failed to open file manager (${e.command})`)}export async function openInTerminal(t,e){await terminalBackendFor(e).open(t)}export const defaultProjectOpener={openExplorer:openInExplorer,openTerminal:openInTerminal,runInTerminal,countTerminals:countOpenTerminals,closeTerminals:(t,e,n)=>closeTerminalsIn(t,e,n),listPanes:(t,e)=>listProjectPanes(t,e),listTerminals:(t,e)=>terminalBackendFor(e).listTargets(t),runInTerminalAt:(t,e,n,a)=>terminalBackendFor(a).runAt(t,e,n),focusTerminal:(t,e,n)=>terminalBackendFor(n).focusTarget(t,e)};
@@ -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,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
+ 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,7 +1,8 @@
1
1
  import type { PathRefKind } from '@weavecode/harness';
2
2
  /**
3
- * 项目文件索引:对话页的路径补全面。**不常驻、不 watch**——打开选择器即重建
4
- * (`?fresh=1`),开着的期间靠 git 指纹(`.git/index`)重验 + 硬窗兜底;**重建
3
+ * 项目文件索引:对话页的路径补全面。**不常驻、不 watch**——打开选择器那一拍
4
+ * (`?fresh=1`)先端核过指纹的旧账(毫秒级)、同时在后台重建,跟进的请求搭在飞
5
+ * 的车拿新账;开着的期间靠 git 指纹(`.git/index`)重验 + 硬窗兜底;**重建
5
6
  * 结果落盘**(`<dataDir>/cache/index/<projectId>.json`,可弃档)当下一次进程启动
6
7
  * 的 L2,省掉冷启动后第一次补全/粘贴认引用的整棵重建。
7
8
  * 理由:重建是事实、watch 是猜测(事件会漏,漏了就永远陈旧),而枚举一个项目
@@ -62,13 +63,18 @@ export declare function buildIndex(root: string): Promise<FileIndex>;
62
63
  /** 测试用:把落盘根改到临时目录(null = 回到生产口径)。 */
63
64
  export declare function setFileIndexRoot(dir: string | null): void;
64
65
  /**
65
- * 取项目索引:`fresh` = 打开选择器那一拍,无条件重建;否则在飞则共用一次构建
66
- * (同 `/toolkit` 的口径),命中缓存则**先核 git 指纹**——变了立刻重建,没变才复用
67
- * (一次 lstat + 一次 stat,比一个请求本身还便宜)。
66
+ * 取项目索引:命中缓存则**先核 git 指纹**——变了立刻重建,没变才复用(一次 lstat +
67
+ * 一次 stat,比一个请求本身还便宜);在飞则共用一次构建(同 `/toolkit` 的口径)。
68
68
  *
69
69
  * 内存里没有(daemon 刚起来)先看**盘上那份**:版本、根、git 指纹全对得上、年纪
70
70
  * 在 `INDEX_MAX_STALE_MS` 内就直接端出去,省掉整棵重建(粘贴认引用是每次粘贴都要
71
- * 走的路径)。`fresh` 仍然不许走后门——它就是「现在重建」。
71
+ * 走的路径)。
72
+ *
73
+ * `fresh`(打开选择器那一拍)**不阻塞在重建上**:手里有任何旧账(内存或盘上快照,
74
+ * 指纹变了也算——旧账好过白等)就先端出去,同时在后台发起重建;重建已在飞的
75
+ * fresh 请求(前端打开后静默补的那一发)搭车等新账。只有手里真没有(daemon 首启
76
+ * 且从未建过)才同步重建。这样「每次打开」都是毫秒级出画面,刚建的文件由后台
77
+ * 那一拍补上。
72
78
  */
73
79
  export declare function projectFileIndex(projectId: number, root: string, opts?: {
74
80
  fresh?: boolean;
@@ -1,2 +1,2 @@
1
- import{execFile as X}from"node:child_process";import{lstat as $,mkdir as P,readFile as x,readdir as V,realpath as D,rename as z,stat as A,writeFile as B}from"node:fs/promises";import{readdirSync as G,rmSync as J}from"node:fs";import f from"node:path";import{promisify as Y}from"node:util";import{getIndexDir as I}from"../db/paths.js";const K=Y(X);export const MAX_INDEX_FILES=3e5,INDEX_VERSION=2;const L=3e4,j=10*6e4,Q=3,U=new Set(["node_modules",".git","dist","build","out",".next","target","coverage",".turbo"]);async function b(t,n){try{const{stdout:e}=await K("git",["ls-files","-z",...n],{cwd:t,timeout:1e4,maxBuffer:67108864,windowsHide:!0});return e.split("\0").filter(Boolean)}catch{return null}}async function Z(t){const n=await b(t,["--stage"]);return n?n.filter(e=>e.startsWith("160000 ")).map(e=>e.slice(e.indexOf(" ")+1)):[]}async function q(t){const n=await b(t,["--stage"]);return n?n.filter(e=>e.startsWith("120000 ")).map(e=>e.slice(e.indexOf(" ")+1)):[]}function F(t){return $(f.join(t,".git")).then(()=>!0,()=>!1)}async function tt(t){try{let n=f.join(t,".git");if(!(await $(n)).isDirectory()){const s=/^gitdir:\s*(.+)$/m.exec(await x(n,"utf8"));if(!s)return null;n=f.resolve(t,s[1].trim())}const e=(await x(f.join(n,"HEAD"),"utf8")).trim(),i=e.startsWith("ref: ")?await(async()=>{const s=e.slice(5);try{return(await x(f.join(n,s),"utf8")).trim()}catch{const a=(await x(f.join(n,"packed-refs"),"utf8")).split(`
2
- `).find(c=>c.endsWith(` ${s}`));return a?a.slice(0,a.indexOf(" ")):null}})():e;return i!==null&&/^[0-9a-f]{40}$/i.test(i)?i.slice(0,7):null}catch{return null}}async function et(t){const n=await b(t,["--others","--ignored","--exclude-standard","--directory"]),e=[];for(const i of n??[]){if(!i.endsWith("/"))continue;const s=i.slice(0,-1);await F(f.join(t,s))&&e.push(s)}return e}async function M(t,n=""){const e=await b(t,["--cached","--others","--exclude-standard"]);if(!e)return null;const i=new Set;for(const o of await Z(t))i.add(o);for(const o of e)o.endsWith("/")&&i.add(o.slice(0,-1));for(const o of await et(t))i.add(o);const s=new Set;for(const o of await q(t))if(!i.has(o))try{(await A(f.join(t,o))).isDirectory()&&s.add(o)}catch{}const r=e.filter(o=>!o.endsWith("/")&&!i.has(o)&&!s.has(o)).map(o=>n+o),a=[...i,...s].map(o=>n+o),c={};for(const o of i){const d=f.join(t,o);if(!await F(d))continue;const w=await tt(d);w&&(c[`${n}${o}`]=w);const l=await M(d,`${n}${o}/`);l&&(r.push(...l.files),a.push(...l.links),Object.assign(c,l.heads))}const u=new Set([await D(t).catch(()=>t)]);for(const o of s){const d=f.join(t,o),w=await D(d).catch(()=>null);if(w===null||u.has(w))continue;u.add(w);const l=`${n}${o}/`;for(let m=r.length-1;m>=0;m--)r[m].startsWith(l)&&r.splice(m,1);const p=await M(d,l)??{files:await W(d),links:[],heads:{}};r.push(...p.files),a.push(...p.links),Object.assign(c,p.heads)}return{files:r,links:a,heads:c}}async function W(t){const n=[],e=new Set([await D(t).catch(()=>t)]),i=async s=>{if(n.length>=MAX_INDEX_FILES)return;let r;try{r=await V(f.join(t,s),{withFileTypes:!0})}catch{return}for(const a of r){if(n.length>=MAX_INDEX_FILES)return;const c=s?`${s}/${a.name}`:a.name;if(a.isDirectory()||a.isSymbolicLink()){if(U.has(a.name))continue;if(a.isSymbolicLink()){let u;try{u=(await A(f.join(t,c))).isDirectory()}catch{u=!1}if(!u){a.name!==".git"&&n.push(c);continue}const o=await D(f.join(t,c)).catch(()=>null);if(o===null||e.has(o))continue;e.add(o);try{await i(c)}finally{e.delete(o)}}else await i(c)}else a.isFile()&&a.name!==".git"&&n.push(c)}};return await i(""),n}function v(t){const n=new Set;for(const e of t){let i=e.lastIndexOf("/");for(;i>0;){const s=e.slice(0,i);if(n.has(s))break;n.add(s),i=s.lastIndexOf("/")}}return[...n].sort()}async function O(t){try{let n=f.join(t,".git");if(!(await $(n)).isDirectory()){const i=/^gitdir:\s*(.+)$/m.exec(await x(n,"utf8"));if(!i)return null;n=f.resolve(t,i[1].trim())}const e=await A(f.join(n,"index"));return`${e.mtimeMs}:${e.size}`}catch{return null}}async function nt(t){const n=await M(t),e=n?.files??await W(t),i=e.length>MAX_INDEX_FILES,s=i?e.slice(0,MAX_INDEX_FILES):e;s.sort();const r=n?.links??[],a=[...new Set([...v(s),...r,...v(r)])].sort();return{v:INDEX_VERSION,root:t,at:Date.now(),stamp:await O(t),truncated:i,files:s,dirs:a,...n&&Object.keys(n.heads).length>0?{submodules:n.heads}:{}}}export function hydrateIndex(t){const n=new Array(t.files.length);for(let r=0;r<t.files.length;r++)n[r]=t.files[r].toLowerCase();const e=new Array(t.dirs.length);for(let r=0;r<t.dirs.length;r++)e[r]=t.dirs[r].toLowerCase();const i=new Map,s=r=>{let a=i.get(r);return a||i.set(r,a={dirs:[],files:[],sorted:!1}),a};for(const r of t.dirs)s(r.slice(0,Math.max(0,r.lastIndexOf("/")))).dirs.push(r);for(const r of t.files)s(r.slice(0,Math.max(0,r.lastIndexOf("/")))).files.push(r);return{...t,lower:n,dirLower:e,children:i,submodules:t.submodules??{}}}export async function buildIndex(t){return hydrateIndex(await nt(t))}const h=new Map,_=new Map;let C=null;export function setFileIndexRoot(t){C=t}function N(t){return f.join(C??I(),`${t}.json`)}function it(t){return{v:t.v,root:t.root,at:t.at,stamp:t.stamp,truncated:t.truncated,files:t.files,dirs:t.dirs,...Object.keys(t.submodules).length>0?{submodules:{...t.submodules}}:{}}}async function st(t,n){const e=N(t),i=`${e}.tmp`;try{await P(f.dirname(e),{recursive:!0}),await B(i,JSON.stringify(it(n)),"utf8"),await z(i,e)}catch{}}async function H(t,n){try{const e=JSON.parse(await x(N(t),"utf8"));return e?.v!==INDEX_VERSION||e.root!==n||!Array.isArray(e.files)||!Array.isArray(e.dirs)?null:e}catch{return null}}function E(t,n){for(h.delete(t),h.set(t,n);h.size>Q;){const e=h.keys().next().value;if(e===void 0)break;h.delete(e)}}function rt(t,n){const e=_.get(t);if(e)return e;const i=buildIndex(n).then(r=>(E(t,r),st(t,r),r));_.set(t,i);const s=()=>{_.delete(t)};return i.then(s,s),i}export async function projectFileIndex(t,n,e={}){const i=h.get(t);if(i&&i.root===n&&!e.fresh){if(Date.now()-i.at<L&&await O(n)===i.stamp)return i;h.delete(t)}else i&&h.delete(t);const s=_.get(t);if(s)return s;if(!i&&!e.fresh){const r=await H(t,n);if(r&&Date.now()-r.at<j&&await O(n)===r.stamp){const a=hydrateIndex(r);return E(t,a),a}}return rt(t,n)}export async function peekCachedIndex(t,n,e={}){const i=h.get(t);if(i&&i.root===n)return Date.now()-i.at<L&&await O(n)===i.stamp?i:(h.delete(t),null);const s=e.maxStaleMs??j,r=await H(t,n);if(r&&Date.now()-r.at<s&&await O(n)===r.stamp){const a=hydrateIndex(r);return E(t,a),a}return null}export function clearFileIndexCache(){h.clear()}export function pruneFileIndexes(t){const n=C??I(),e=new Set(t.map(s=>`${s}.json`));let i;try{i=G(n)}catch{return}for(const s of i)if(!(!s.endsWith(".json")||e.has(s)))try{J(f.join(n,s))}catch{}}const R=new Intl.Collator(void 0,{numeric:!0});export function listDirOf(t,n){const e=t.children.get(n);if(!e)return[];e.sorted||(e.dirs.sort(R.compare),e.files.sort(R.compare),e.sorted=!0);const i=[];for(const s of e.dirs){const r=t.submodules[s];i.push(r?{path:s,kind:"dir",head:r}:{path:s,kind:"dir"})}for(const s of e.files)i.push({path:s,kind:"file"});return i}function at(t,n){return t.startsWith(n)?3:t.includes(n)?2:ot(t,n)?1:-1}function ot(t,n){let e=0;for(let i=0;i<t.length&&e<n.length;i++)t[i]===n[e]&&e++;return e===n.length}function ct(t,n,e){const i=t.lastIndexOf("/")+1,s=t.slice(i).toLowerCase();if(n===3||n===2){const c=s.indexOf(e);return c<0?[]:[[i+c,e.length]]}const r=[];let a=0;for(let c=0;c<s.length&&a<e.length;c++)s[c]===e[a]&&(r.push([i+c,1]),a++);return r}function T(t,n){return n.rank-t.rank||t.len-n.len||t.path.localeCompare(n.path)}const lt=8,ft=1024;function ut(t,n){if(!n)return 0;let e=0,i=t.length;for(;e<i;){const s=e+i>>1;t[s]<n?e=s+1:i=s}return e}export function startMatch(t,n,e,i=""){const s=n.trim().toLowerCase(),r=i?`${i}/`:"",a=[];let c=s&&e>0?"files":"done",u=0,o=0,d=!1;const w=(l,p)=>{const m=l.slice(l.lastIndexOf("/")+1).toLowerCase(),y=at(m,s);if(y<0)return;o++;const g={path:l,kind:p,rank:y,len:l.length};if(a.length===e&&T(g,a[e-1])>=0)return;const S=a.length===e;let k=S?e-1:a.length;for(S?a[e-1]=g:a.push(g);k>0&&T(g,a[k-1])<0;)a[k]=a[k-1],k--;a[k]=g};return{step(l){const p=Date.now()+l;let m=0;for(;c!=="done";){const y=c==="files"?t.files:t.dirs,g=c==="files"?"file":"dir";for(u===0&&(u=ut(y,r));u<y.length;){const S=y[u];if(r&&!S.startsWith(r))break;if(w(S,g),u++,a.length===e&&a[e-1].rank===3)return d=!0,c="done",!0;if((++m&ft-1)===0&&Date.now()>p)return!1}u=0,c=c==="files"?"dirs":"done"}return!0},result(){return{hits:a.map(l=>({path:l.path,kind:l.kind,ranges:ct(l.path,l.rank,s)})),total:d?a.length:o,capped:d}}}}export async function matchPaths(t,n,e,i=""){const s=startMatch(t,n,e,i);for(;!s.step(lt);)await new Promise(r=>setImmediate(r));return s.result()}
1
+ import{execFile as H}from"node:child_process";import{lstat as $,mkdir as J,readFile as k,readdir as R,realpath as O,rename as T,stat as D,writeFile as V}from"node:fs/promises";import{readdirSync as q,rmSync as G}from"node:fs";import f from"node:path";import{promisify as K}from"node:util";import{getIndexDir as L}from"../db/paths.js";const Q=K(H);export const MAX_INDEX_FILES=3e5,INDEX_VERSION=2;const M=3e4,A=10*6e4,U=3,Y=new Set(["node_modules",".git","dist","build","out",".next","target","coverage",".turbo"]);async function v(t,n){try{const{stdout:e}=await Q("git",["ls-files","-z",...n],{cwd:t,timeout:1e4,maxBuffer:67108864,windowsHide:!0});return e.split("\0").filter(Boolean)}catch{return null}}async function Z(t){const n=await v(t,["--stage"]),e=[],s=[];for(const i of n??[])i.startsWith("160000 ")?e.push(i.slice(i.indexOf(" ")+1)):i.startsWith("120000 ")&&s.push(i.slice(i.indexOf(" ")+1));return{links:e,symlinks:s}}function E(t){return $(f.join(t,".git")).then(()=>!0,()=>!1)}async function tt(t){try{let n=f.join(t,".git");if(!(await $(n)).isDirectory()){const i=/^gitdir:\s*(.+)$/m.exec(await k(n,"utf8"));if(!i)return null;n=f.resolve(t,i[1].trim())}const e=(await k(f.join(n,"HEAD"),"utf8")).trim(),s=e.startsWith("ref: ")?await(async()=>{const i=e.slice(5);try{return(await k(f.join(n,i),"utf8")).trim()}catch{const r=(await k(f.join(n,"packed-refs"),"utf8")).split(`
2
+ `).find(o=>o.endsWith(` ${i}`));return r?r.slice(0,r.indexOf(" ")):null}})():e;return s!==null&&/^[0-9a-f]{40}$/i.test(s)?s.slice(0,7):null}catch{return null}}async function nt(t){const n=await v(t,["--others","--ignored","--exclude-standard","--directory"]),e=[];for(const s of n??[]){if(!s.endsWith("/"))continue;const i=s.slice(0,-1);await E(f.join(t,i))&&e.push(i)}return e}async function W(t,n=""){const[e,s,i]=await Promise.all([v(t,["--cached","--others","--exclude-standard"]),Z(t),nt(t)]);if(!e)return null;const r=new Set;for(const c of s.links)r.add(c);for(const c of e)c.endsWith("/")&&r.add(c.slice(0,-1));for(const c of i)r.add(c);const o=new Set;for(const c of s.symlinks)if(!r.has(c))try{(await D(f.join(t,c))).isDirectory()&&o.add(c)}catch{}const a=e.filter(c=>!c.endsWith("/")&&!r.has(c)&&!o.has(c)).map(c=>n+c),u=[...r,...o].map(c=>n+c),d={};for(const c of r){const l=f.join(t,c);if(!await E(l))continue;const m=await tt(l);m&&(d[`${n}${c}`]=m);const p=await W(l,`${n}${c}/`);p&&(a.push(...p.files),u.push(...p.links),Object.assign(d,p.heads))}const g=new Set([await O(t).catch(()=>t)]);for(const c of o){const l=f.join(t,c),m=await O(l).catch(()=>null);if(m===null||g.has(m))continue;g.add(m);const p=`${n}${c}/`;for(let h=a.length-1;h>=0;h--)a[h].startsWith(p)&&a.splice(h,1);const y=await W(l,p)??{files:await N(l),links:[],heads:{}};a.push(...y.files),u.push(...y.links),Object.assign(d,y.heads)}return{files:a,links:u,heads:d}}async function N(t){const n=[],e=new Set([await O(t).catch(()=>t)]),s=async i=>{if(n.length>=MAX_INDEX_FILES)return;let r;try{r=await R(f.join(t,i),{withFileTypes:!0})}catch{return}for(const o of r){if(n.length>=MAX_INDEX_FILES)return;const a=i?`${i}/${o.name}`:o.name;if(o.isDirectory()||o.isSymbolicLink()){if(Y.has(o.name))continue;if(o.isSymbolicLink()){let u;try{u=(await D(f.join(t,a))).isDirectory()}catch{u=!1}if(!u){o.name!==".git"&&n.push(a);continue}const d=await O(f.join(t,a)).catch(()=>null);if(d===null||e.has(d))continue;e.add(d);try{await s(a)}finally{e.delete(d)}}else await s(a)}else o.isFile()&&o.name!==".git"&&n.push(a)}};return await s(""),n}function _(t){const n=new Set;for(const e of t){let s=e.lastIndexOf("/");for(;s>0;){const i=e.slice(0,s);if(n.has(i))break;n.add(i),s=i.lastIndexOf("/")}}return[...n].sort()}async function I(t){try{let n=f.join(t,".git");if(!(await $(n)).isDirectory()){const s=/^gitdir:\s*(.+)$/m.exec(await k(n,"utf8"));if(!s)return null;n=f.resolve(t,s[1].trim())}const e=await D(f.join(n,"index"));return`${e.mtimeMs}:${e.size}`}catch{return null}}async function et(t){const n=await W(t),e=n?.files??await N(t),s=e.length>MAX_INDEX_FILES,i=s?e.slice(0,MAX_INDEX_FILES):e;i.sort();const r=n?.links??[],o=[...new Set([..._(i),...r,..._(r)])].sort();return{v:INDEX_VERSION,root:t,at:Date.now(),stamp:await I(t),truncated:s,files:i,dirs:o,...n&&Object.keys(n.heads).length>0?{submodules:n.heads}:{}}}export function hydrateIndex(t){const n=new Array(t.files.length);for(let r=0;r<t.files.length;r++)n[r]=t.files[r].toLowerCase();const e=new Array(t.dirs.length);for(let r=0;r<t.dirs.length;r++)e[r]=t.dirs[r].toLowerCase();const s=new Map,i=r=>{let o=s.get(r);return o||s.set(r,o={dirs:[],files:[],sorted:!1}),o};for(const r of t.dirs)i(r.slice(0,Math.max(0,r.lastIndexOf("/")))).dirs.push(r);for(const r of t.files)i(r.slice(0,Math.max(0,r.lastIndexOf("/")))).files.push(r);return{...t,lower:n,dirLower:e,children:s,submodules:t.submodules??{}}}export async function buildIndex(t){return hydrateIndex(await et(t))}const w=new Map,b=new Map;let F=null;export function setFileIndexRoot(t){F=t}function z(t){return f.join(F??L(),`${t}.json`)}function st(t){return{v:t.v,root:t.root,at:t.at,stamp:t.stamp,truncated:t.truncated,files:t.files,dirs:t.dirs,...Object.keys(t.submodules).length>0?{submodules:{...t.submodules}}:{}}}async function it(t,n){const e=z(t),s=`${e}.tmp`;try{await J(f.dirname(e),{recursive:!0}),await V(s,JSON.stringify(st(n)),"utf8"),await T(s,e)}catch{}}async function P(t,n){try{const e=JSON.parse(await k(z(t),"utf8"));return e?.v!==INDEX_VERSION||e.root!==n||!Array.isArray(e.files)||!Array.isArray(e.dirs)?null:e}catch{return null}}function S(t,n){for(w.delete(t),w.set(t,n);w.size>U;){const e=w.keys().next().value;if(e===void 0)break;w.delete(e)}}function C(t,n){const e=b.get(t);if(e)return e;const s=buildIndex(n).then(r=>(S(t,r),it(t,r),r));b.set(t,s);const i=()=>{b.delete(t)};return s.then(i,i),s}export async function projectFileIndex(t,n,e={}){if(e.fresh){const o=b.get(t);if(o)return o}const s=w.get(t);s&&s.root!==n&&w.delete(t);const i=s&&s.root===n?s:null;if(i&&e.fresh)return C(t,n).catch(()=>{}),i;if(i&&await I(n)===i.stamp){if(Date.now()-i.at<M)return i;w.delete(t)}else i&&w.delete(t);const r=b.get(t);if(r)return r;if(!i){const o=await P(t,n);if(o&&Date.now()-o.at<A){const a=hydrateIndex(o);if(e.fresh)return S(t,a),C(t,n).catch(()=>{}),a;if(await I(n)===o.stamp)return S(t,a),a}}return C(t,n)}export async function peekCachedIndex(t,n,e={}){const s=w.get(t);if(s&&s.root===n)return Date.now()-s.at<M&&await I(n)===s.stamp?s:(w.delete(t),null);const i=e.maxStaleMs??A,r=await P(t,n);if(r&&Date.now()-r.at<i&&await I(n)===r.stamp){const o=hydrateIndex(r);return S(t,o),o}return null}export function clearFileIndexCache(){w.clear()}export function pruneFileIndexes(t){const n=F??L(),e=new Set(t.map(i=>`${i}.json`));let s;try{s=q(n)}catch{return}for(const i of s)if(!(!i.endsWith(".json")||e.has(i)))try{G(f.join(n,i))}catch{}}const X=new Intl.Collator(void 0,{numeric:!0});export function listDirOf(t,n){const e=t.children.get(n);if(!e)return[];e.sorted||(e.dirs.sort(X.compare),e.files.sort(X.compare),e.sorted=!0);const s=[];for(const i of e.dirs){const r=t.submodules[i];s.push(r?{path:i,kind:"dir",head:r}:{path:i,kind:"dir"})}for(const i of e.files)s.push({path:i,kind:"file"});return s}function rt(t,n){return t.startsWith(n)?3:t.includes(n)?2:ot(t,n)?1:-1}function ot(t,n){let e=0;for(let s=0;s<t.length&&e<n.length;s++)t[s]===n[e]&&e++;return e===n.length}function at(t,n,e){const s=t.lastIndexOf("/")+1,i=t.slice(s).toLowerCase();if(n===3||n===2){const a=i.indexOf(e);return a<0?[]:[[s+a,e.length]]}const r=[];let o=0;for(let a=0;a<i.length&&o<e.length;a++)i[a]===e[o]&&(r.push([s+a,1]),o++);return r}function B(t,n){return n.rank-t.rank||t.len-n.len||t.path.localeCompare(n.path)}const ct=8,lt=1024;function ft(t,n){if(!n)return 0;let e=0,s=t.length;for(;e<s;){const i=e+s>>1;t[i]<n?e=i+1:s=i}return e}export function startMatch(t,n,e,s=""){const i=n.trim().toLowerCase(),r=s?`${s}/`:"",o=[];let a=i&&e>0?"files":"done",u=0,d=0,g=!1;const c=(l,m)=>{const p=l.slice(l.lastIndexOf("/")+1).toLowerCase(),y=rt(p,i);if(y<0)return;d++;const h={path:l,kind:m,rank:y,len:l.length};if(o.length===e&&B(h,o[e-1])>=0)return;const j=o.length===e;let x=j?e-1:o.length;for(j?o[e-1]=h:o.push(h);x>0&&B(h,o[x-1])<0;)o[x]=o[x-1],x--;o[x]=h};return{step(l){const m=Date.now()+l;let p=0;for(;a!=="done";){const y=a==="files"?t.files:t.dirs,h=a==="files"?"file":"dir";for(u===0&&(u=ft(y,r));u<y.length;){const j=y[u];if(r&&!j.startsWith(r))break;if(c(j,h),u++,o.length===e&&o[e-1].rank===3)return g=!0,a="done",!0;if((++p&lt-1)===0&&Date.now()>m)return!1}u=0,a=a==="files"?"dirs":"done"}return!0},result(){return{hits:o.map(l=>({path:l.path,kind:l.kind,ranges:at(l.path,l.rank,i)})),total:g?o.length:d,capped:g}}}}export async function matchPaths(t,n,e,s=""){const i=startMatch(t,n,e,s);for(;!i.step(ct);)await new Promise(r=>setImmediate(r));return i.result()}
@@ -1,2 +1,2 @@
1
- import{spawn as c}from"node:child_process";import{readFile as m}from"node:fs/promises";import f from"node:path";import{HARNESS_KEYS as d,isHarness as w}from"@weavecode/core";import{isVersionAtLeast as h}from"../hooks/toolkit.js";export async function projectHarnessIds(n){const e=[d[0]];let s;try{s=await m(f.join(n,".weave","config.yaml"),"utf-8")}catch{return e}const t=s.split(`
2
- `).find(o=>o.startsWith("harnesses:"));if(!t)return e;try{const o=JSON.parse(t.slice(t.indexOf(":")+1).trim()),r=Array.isArray(o)?o.filter(w):[];return r.length>0?r:e}catch{return e}}const S=6e5,a=new Map;export function probeBinVersion(n){return new Promise(e=>{let s="";const t=process.platform==="win32"?c(`${n} --version`,{windowsHide:!0,shell:!0,stdio:["ignore","pipe","pipe"]}):c(n,["--version"],{windowsHide:!0,stdio:["ignore","pipe","pipe"]}),o=setTimeout(()=>{t.kill("SIGKILL"),e(null)},5e3);t.stdout?.on("data",r=>s+=r.toString()),t.on("error",()=>{clearTimeout(o),e(null)}),t.on("close",()=>{clearTimeout(o);const r=/(\d+\.\d+\.\d+)/.exec(s);e(r?r[1]:null)})})}function y(n){const e=a.get(n);if(e&&Date.now()-e.at<S)return e.value;const s=probeBinVersion(n).then(t=>(t===null&&a.delete(n),t));return a.set(n,{at:Date.now(),value:s}),s}export async function projectHarnesses(n,e,s=y){const t=await projectHarnessIds(n);return Promise.all(t.map(async o=>{const r=e?.get(o)?.resume;if(!r?.bin)return{id:o,canStartSession:!1};if(!r.minVersion)return{id:o,canStartSession:!0};const i=await s(r.bin),l=r.minVersion.split(".").map(p=>Number.parseInt(p,10)),u=i===null||h(i,l);return{id:o,canStartSession:u,version:i,minVersion:r.minVersion}}))}export async function withProjectHarnesses(n,e,s){return Promise.all(n.map(async t=>({...t,harnesses:await projectHarnesses(t.path,e,s)})))}
1
+ import{spawn as c}from"node:child_process";import{readFile as m}from"node:fs/promises";import f from"node:path";import{HARNESS_KEYS as d,isHarness as w}from"@weavecode/core";import{isVersionAtLeast as S}from"../hooks/toolkit.js";export async function projectHarnessIds(r){const e=[d[0]];let s;try{s=await m(f.join(r,".weave","config.yaml"),"utf-8")}catch{return e}const t=s.split(`
2
+ `).find(i=>i.startsWith("harnesses:"));if(!t)return e;try{const i=JSON.parse(t.slice(t.indexOf(":")+1).trim()),n=Array.isArray(i)?i.filter(w):[];return n.length>0?n:e}catch{return e}}const h=6e5,a=new Map;export function probeBinVersion(r){return new Promise(e=>{let s="";const t=process.platform==="win32"?c(`${r} --version`,{windowsHide:!0,shell:!0,stdio:["ignore","pipe","pipe"]}):c(r,["--version"],{windowsHide:!0,stdio:["ignore","pipe","pipe"]}),i=setTimeout(()=>{t.kill("SIGKILL"),e(null)},5e3);t.stdout?.on("data",n=>s+=n.toString()),t.on("error",()=>{clearTimeout(i),e(null)}),t.on("close",()=>{clearTimeout(i);const n=/(\d+\.\d+\.\d+)/.exec(s);e(n?n[1]:null)})})}function y(r){const e=a.get(r);if(e&&Date.now()-e.at<h)return e.value;const s=probeBinVersion(r).then(t=>(t===null&&a.delete(r),t));return a.set(r,{at:Date.now(),value:s}),s}export async function projectHarnesses(r,e,s=y){const t=await projectHarnessIds(r);return Promise.all(t.map(async i=>{const n=e?.get(i)?.resume;if(!n?.bin)return{id:i,canStartSession:!1};if(!n.minVersion)return{id:i,canStartSession:!0};const o=await s(n.bin),l=n.minVersion.split(".").map(u=>Number.parseInt(u,10)),p=o===null||S(o,l);return{id:i,canStartSession:p,version:o,minVersion:n.minVersion}}))}export async function withProjectHarnesses(r,e,s){return Promise.all(r.map(async t=>({...t,harnesses:await projectHarnesses(t.path,e,s)})))}
@@ -1 +1 @@
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)}}
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)}}