@weavecode/weave 0.1.8 → 0.1.9

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 (351) hide show
  1. package/node_modules/@modelcontextprotocol/sdk/node_modules/@hono/node-server/dist/index.cjs +31 -6
  2. package/node_modules/@modelcontextprotocol/sdk/node_modules/@hono/node-server/dist/index.mjs +31 -6
  3. package/node_modules/@modelcontextprotocol/sdk/node_modules/@hono/node-server/package.json +1 -1
  4. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.cjs +1 -1
  5. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.mjs +1 -1
  6. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/node_modules/ip-address/README.md +39 -39
  7. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/node_modules/ip-address/dist/ipv6.js +1 -1
  8. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/node_modules/ip-address/package.json +1 -1
  9. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/package.json +1 -1
  10. package/node_modules/@weavecode/cli/dist/cli.js +4 -4
  11. package/node_modules/@weavecode/cli/dist/commands/chpass.js +1 -1
  12. package/node_modules/@weavecode/cli/dist/commands/daemon-auth.js +1 -1
  13. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  14. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -2
  15. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  16. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  17. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  18. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  19. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  20. package/node_modules/@weavecode/cli/dist/commands/uninstall.js +1 -1
  21. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +2 -2
  22. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +7 -0
  23. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +3 -3
  24. package/node_modules/@weavecode/cli/dist/i18n/index.js +1 -1
  25. package/node_modules/@weavecode/cli/dist/i18n/t.js +1 -1
  26. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +5 -5
  27. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  28. package/node_modules/@weavecode/cli/dist/init/git-commit.js +2 -2
  29. package/node_modules/@weavecode/cli/dist/init/git-exclude.d.ts +20 -0
  30. package/node_modules/@weavecode/cli/dist/init/git-exclude.js +7 -0
  31. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  32. package/node_modules/@weavecode/cli/dist/init/harnesses/codex.js +1 -1
  33. package/node_modules/@weavecode/cli/dist/init/instruction-files.d.ts +14 -0
  34. package/node_modules/@weavecode/cli/dist/init/instruction-files.js +1 -0
  35. package/node_modules/@weavecode/cli/dist/init/instruction-link.js +1 -1
  36. package/node_modules/@weavecode/cli/dist/init/plugin-templates.js +1 -1
  37. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  38. package/node_modules/@weavecode/cli/dist/init/provision.js +1 -1
  39. package/node_modules/@weavecode/cli/dist/init/uninstall.js +6 -6
  40. package/node_modules/@weavecode/cli/dist/init/wiring.js +1 -1
  41. package/node_modules/@weavecode/cli/dist/parser.js +1 -1
  42. package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
  43. package/node_modules/@weavecode/cli/dist/statusline/mock-input.js +1 -1
  44. package/node_modules/@weavecode/cli/dist/statusline/preview.js +2 -2
  45. package/node_modules/@weavecode/cli/package.json +5 -5
  46. package/node_modules/@weavecode/core/dist/harness-checks.js +1 -1
  47. package/node_modules/@weavecode/core/dist/harness.d.ts +37 -0
  48. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  49. package/node_modules/@weavecode/core/dist/index.d.ts +1 -1
  50. package/node_modules/@weavecode/core/dist/index.js +1 -1
  51. package/node_modules/@weavecode/core/dist/platform.js +1 -1
  52. package/node_modules/@weavecode/core/dist/types.d.ts +4 -4
  53. package/node_modules/@weavecode/core/dist/types.js +1 -1
  54. package/node_modules/@weavecode/core/dist/utils/fs.js +1 -1
  55. package/node_modules/@weavecode/core/package.json +1 -1
  56. package/node_modules/@weavecode/harness/dist/claude/assets.js +3 -3
  57. package/node_modules/@weavecode/harness/dist/claude/capture.js +9 -9
  58. package/node_modules/@weavecode/harness/dist/claude/commands.js +3 -3
  59. package/node_modules/@weavecode/harness/dist/claude/config.js +2 -2
  60. package/node_modules/@weavecode/harness/dist/claude/detect.js +1 -1
  61. package/node_modules/@weavecode/harness/dist/claude/edits.js +1 -1
  62. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  63. package/node_modules/@weavecode/harness/dist/claude/images.js +2 -2
  64. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  65. package/node_modules/@weavecode/harness/dist/claude/liveness.js +1 -1
  66. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -1
  67. package/node_modules/@weavecode/harness/dist/claude/messaging.js +2 -2
  68. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -1
  69. package/node_modules/@weavecode/harness/dist/claude/narration.js +1 -1
  70. package/node_modules/@weavecode/harness/dist/claude/peers.js +1 -1
  71. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -1
  72. package/node_modules/@weavecode/harness/dist/claude/plugins.js +4 -4
  73. package/node_modules/@weavecode/harness/dist/claude/prompt-inbox.js +1 -1
  74. package/node_modules/@weavecode/harness/dist/claude/prompt.js +3 -3
  75. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -2
  76. package/node_modules/@weavecode/harness/dist/claude/resume.js +1 -1
  77. package/node_modules/@weavecode/harness/dist/claude/rewind.js +1 -1
  78. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -1
  79. package/node_modules/@weavecode/harness/dist/claude/side-question.js +2 -2
  80. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.d.ts +6 -0
  81. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +21 -14
  82. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -1
  83. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -2
  84. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.js +2 -2
  85. package/node_modules/@weavecode/harness/dist/claude/transcript.js +7 -7
  86. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  87. package/node_modules/@weavecode/harness/dist/codex/capture.js +2 -2
  88. package/node_modules/@weavecode/harness/dist/codex/commands.js +4 -4
  89. package/node_modules/@weavecode/harness/dist/codex/config.js +2 -2
  90. package/node_modules/@weavecode/harness/dist/codex/detect.js +1 -1
  91. package/node_modules/@weavecode/harness/dist/codex/event-source.js +2 -2
  92. package/node_modules/@weavecode/harness/dist/codex/images.js +1 -1
  93. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  94. package/node_modules/@weavecode/harness/dist/codex/liveness.js +1 -1
  95. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -1
  96. package/node_modules/@weavecode/harness/dist/codex/messaging.js +2 -2
  97. package/node_modules/@weavecode/harness/dist/codex/narration.js +1 -1
  98. package/node_modules/@weavecode/harness/dist/codex/plugin-state.js +1 -1
  99. package/node_modules/@weavecode/harness/dist/codex/plugins.js +3 -3
  100. package/node_modules/@weavecode/harness/dist/codex/provision.js +1 -1
  101. package/node_modules/@weavecode/harness/dist/codex/questions.js +2 -2
  102. package/node_modules/@weavecode/harness/dist/codex/rollout.js +5 -5
  103. package/node_modules/@weavecode/harness/dist/codex/side-question.js +4 -4
  104. package/node_modules/@weavecode/harness/dist/codex/titles.js +4 -4
  105. package/node_modules/@weavecode/harness/dist/codex/toml.js +13 -13
  106. package/node_modules/@weavecode/harness/dist/codex/transcript.js +2 -2
  107. package/node_modules/@weavecode/harness/dist/driver.js +1 -1
  108. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -2
  109. package/node_modules/@weavecode/harness/dist/init/pipeline.js +1 -1
  110. package/node_modules/@weavecode/harness/dist/registry-wiring.js +1 -1
  111. package/node_modules/@weavecode/harness/dist/shared/install-link.js +1 -1
  112. package/node_modules/@weavecode/harness/dist/shared/json-cap.js +1 -1
  113. package/node_modules/@weavecode/harness/dist/zcode/assets.js +1 -1
  114. package/node_modules/@weavecode/harness/dist/zcode/capture.js +3 -3
  115. package/node_modules/@weavecode/harness/dist/zcode/mcp.js +2 -2
  116. package/node_modules/@weavecode/harness/package.json +2 -2
  117. package/node_modules/@weavecode/server/dist/config/dotted.js +1 -1
  118. package/node_modules/@weavecode/server/dist/config/profiles.js +2 -2
  119. package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
  120. package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
  121. package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
  122. package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -3
  123. package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
  124. package/node_modules/@weavecode/server/dist/daemon/auto-start.js +3 -3
  125. package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
  126. package/node_modules/@weavecode/server/dist/daemon/config-routes.js +1 -1
  127. package/node_modules/@weavecode/server/dist/daemon/cron.js +1 -1
  128. package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
  129. package/node_modules/@weavecode/server/dist/daemon/dashboard-pusher.js +1 -1
  130. package/node_modules/@weavecode/server/dist/daemon/decision-config.js +2 -2
  131. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  132. package/node_modules/@weavecode/server/dist/daemon/entry.js +2 -2
  133. package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
  134. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
  135. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  136. package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
  137. package/node_modules/@weavecode/server/dist/daemon/liveness.js +1 -1
  138. package/node_modules/@weavecode/server/dist/daemon/mcp-orchestration.js +1 -1
  139. package/node_modules/@weavecode/server/dist/daemon/narration-watcher.js +2 -2
  140. package/node_modules/@weavecode/server/dist/daemon/opener/backend-ghostty.js +1 -1
  141. package/node_modules/@weavecode/server/dist/daemon/opener/backend-iterm.js +1 -1
  142. package/node_modules/@weavecode/server/dist/daemon/opener/backend-konsole.js +2 -2
  143. package/node_modules/@weavecode/server/dist/daemon/opener/backend-terminal-app.js +1 -1
  144. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wezterm.js +1 -1
  145. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wt.js +1 -1
  146. package/node_modules/@weavecode/server/dist/daemon/opener/backend.js +1 -1
  147. package/node_modules/@weavecode/server/dist/daemon/opener/launch.js +1 -1
  148. package/node_modules/@weavecode/server/dist/daemon/opener/pty-terminals.js +1 -1
  149. package/node_modules/@weavecode/server/dist/daemon/opener/shared.js +1 -1
  150. package/node_modules/@weavecode/server/dist/daemon/opener/wezterm-mux.js +1 -1
  151. package/node_modules/@weavecode/server/dist/daemon/opener/wt.js +3 -3
  152. package/node_modules/@weavecode/server/dist/daemon/opener.js +1 -1
  153. package/node_modules/@weavecode/server/dist/daemon/pet-seed.d.ts +4 -6
  154. package/node_modules/@weavecode/server/dist/daemon/pet-seed.js +2 -1
  155. package/node_modules/@weavecode/server/dist/daemon/pet-window.js +1 -1
  156. package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
  157. package/node_modules/@weavecode/server/dist/daemon/project-files.js +2 -2
  158. package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
  159. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
  160. package/node_modules/@weavecode/server/dist/daemon/prompt-images.js +1 -1
  161. package/node_modules/@weavecode/server/dist/daemon/routes/hooks-admin.js +1 -1
  162. package/node_modules/@weavecode/server/dist/daemon/routes/installations.d.ts +29 -0
  163. package/node_modules/@weavecode/server/dist/daemon/routes/installations.js +1 -0
  164. package/node_modules/@weavecode/server/dist/daemon/routes/market.js +1 -1
  165. package/node_modules/@weavecode/server/dist/daemon/routes/orchestration.js +1 -1
  166. package/node_modules/@weavecode/server/dist/daemon/routes/path-refs.js +1 -1
  167. package/node_modules/@weavecode/server/dist/daemon/routes/pets.js +1 -1
  168. package/node_modules/@weavecode/server/dist/daemon/routes/project-files.js +1 -1
  169. package/node_modules/@weavecode/server/dist/daemon/routes/projects.js +1 -1
  170. package/node_modules/@weavecode/server/dist/daemon/routes/search.js +1 -1
  171. package/node_modules/@weavecode/server/dist/daemon/routes/session-control.js +1 -1
  172. package/node_modules/@weavecode/server/dist/daemon/routes/session-insights.js +1 -1
  173. package/node_modules/@weavecode/server/dist/daemon/routes/settings-statusline.js +1 -1
  174. package/node_modules/@weavecode/server/dist/daemon/routes/uploads.js +1 -1
  175. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.js +2 -2
  176. package/node_modules/@weavecode/server/dist/daemon/routes/watches.js +1 -1
  177. package/node_modules/@weavecode/server/dist/daemon/server.d.ts +2 -0
  178. package/node_modules/@weavecode/server/dist/daemon/server.js +8 -8
  179. package/node_modules/@weavecode/server/dist/daemon/session-open.js +1 -1
  180. package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
  181. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  182. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.js +1 -1
  183. package/node_modules/@weavecode/server/dist/daemon/sse-hub.js +1 -1
  184. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  185. package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
  186. package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
  187. package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.js +1 -1
  188. package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
  189. package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
  190. package/node_modules/@weavecode/server/dist/daemon/upload-sessions.js +1 -1
  191. package/node_modules/@weavecode/server/dist/db/db.js +2 -2
  192. package/node_modules/@weavecode/server/dist/db/layout.d.ts +5 -0
  193. package/node_modules/@weavecode/server/dist/db/layout.js +2 -1
  194. package/node_modules/@weavecode/server/dist/db/paths.d.ts +5 -0
  195. package/node_modules/@weavecode/server/dist/db/paths.js +1 -1
  196. package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
  197. package/node_modules/@weavecode/server/dist/hooks/dashboard-rate.js +1 -1
  198. package/node_modules/@weavecode/server/dist/hooks/decision-judge.js +1 -1
  199. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.js +1 -1
  200. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.js +1 -1
  201. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.js +1 -1
  202. package/node_modules/@weavecode/server/dist/hooks/delivery/queue.js +1 -1
  203. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.js +1 -1
  204. package/node_modules/@weavecode/server/dist/hooks/delivery/send.js +2 -2
  205. package/node_modules/@weavecode/server/dist/hooks/delivery/views.js +1 -1
  206. package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
  207. package/node_modules/@weavecode/server/dist/hooks/edge-extract.js +1 -1
  208. package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
  209. package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
  210. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -2
  211. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
  212. package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
  213. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +5 -5
  214. package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
  215. package/node_modules/@weavecode/server/dist/hooks/orchestration-engine.js +7 -7
  216. package/node_modules/@weavecode/server/dist/hooks/orchestration-graph.js +1 -1
  217. package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
  218. package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
  219. package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
  220. package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
  221. package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
  222. package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
  223. package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
  224. package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
  225. package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
  226. package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
  227. package/node_modules/@weavecode/server/dist/hooks/side-questions.js +1 -1
  228. package/node_modules/@weavecode/server/dist/hooks/synthetic-sessions.js +1 -1
  229. package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
  230. package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
  231. package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
  232. package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
  233. package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
  234. package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
  235. package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
  236. package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
  237. package/node_modules/@weavecode/server/dist/install/global-config.js +1 -1
  238. package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
  239. package/node_modules/@weavecode/server/dist/install/init-files.d.ts +0 -9
  240. package/node_modules/@weavecode/server/dist/install/init-files.js +2 -2
  241. package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
  242. package/node_modules/@weavecode/server/dist/install/installer.js +1 -1
  243. package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
  244. package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
  245. package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
  246. package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
  247. package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
  248. package/node_modules/@weavecode/server/dist/install/project-config.js +1 -1
  249. package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
  250. package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
  251. package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
  252. package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
  253. package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
  254. package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
  255. package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
  256. package/node_modules/@weavecode/server/dist/market/import.js +2 -2
  257. package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
  258. package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
  259. package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
  260. package/node_modules/@weavecode/server/dist/registry.js +2 -2
  261. package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +4 -4
  262. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +6 -6
  263. package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
  264. package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
  265. package/node_modules/@weavecode/server/dist/repositories/orchestrations.js +7 -7
  266. package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
  267. package/node_modules/@weavecode/server/dist/repositories/projects.js +1 -1
  268. package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
  269. package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
  270. package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
  271. package/node_modules/@weavecode/server/dist/repositories/uploads.js +11 -11
  272. package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
  273. package/node_modules/@weavecode/server/dist/statusline/generator.js +1 -1
  274. package/node_modules/@weavecode/server/dist/statusline/manager.js +3 -3
  275. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  276. package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
  277. package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
  278. package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
  279. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
  280. package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
  281. package/node_modules/@weavecode/server/package.json +4 -4
  282. package/node_modules/@weavecode/server/web/dist/assets/{abnfDiagram-WEYOIA3C-t5OQjhuS.js → abnfDiagram-WEYOIA3C-S1lL1V_n.js} +1 -1
  283. package/node_modules/@weavecode/server/web/dist/assets/{arc-De-uH_Q9.js → arc-CoTNHyHV.js} +1 -1
  284. package/node_modules/@weavecode/server/web/dist/assets/{architectureDiagram-ZHVYKT53-ImPclD43.js → architectureDiagram-ZHVYKT53-C6ttfnzW.js} +1 -1
  285. package/node_modules/@weavecode/server/web/dist/assets/{blockDiagram-RJAE7QA3-B5xEQs6X.js → blockDiagram-RJAE7QA3-CYr3Cpu9.js} +1 -1
  286. package/node_modules/@weavecode/server/web/dist/assets/{c4Diagram-XDPPPE54-DP8MjIgJ.js → c4Diagram-XDPPPE54-BFS7PhLD.js} +1 -1
  287. package/node_modules/@weavecode/server/web/dist/assets/channel-DxQHp3Yc.js +1 -0
  288. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2E7WHVMD-C3UFIDyj.js → chunk-2E7WHVMD-DJ7X_Shu.js} +1 -1
  289. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2Q5K7J3B-Bgw-3YfG.js → chunk-2Q5K7J3B-B8nr2rdz.js} +1 -1
  290. package/node_modules/@weavecode/server/web/dist/assets/{chunk-4EMNKR2T-Dy_Wq9qn.js → chunk-4EMNKR2T-DmnZmUMU.js} +1 -1
  291. package/node_modules/@weavecode/server/web/dist/assets/{chunk-55XCU76K-D32C0DXX.js → chunk-55XCU76K-Xz9a8dmp.js} +1 -1
  292. package/node_modules/@weavecode/server/web/dist/assets/{chunk-5VM5RSS4-Dpmi-9Gi.js → chunk-5VM5RSS4-Dg9mg7pf.js} +1 -1
  293. package/node_modules/@weavecode/server/web/dist/assets/{chunk-JWPE2WC7-CEYXaZDX.js → chunk-JWPE2WC7-CmjTZO8o.js} +1 -1
  294. package/node_modules/@weavecode/server/web/dist/assets/{chunk-VQ5W62QI-A616Pgzo.js → chunk-VQ5W62QI-D3YDdJ3E.js} +1 -1
  295. package/node_modules/@weavecode/server/web/dist/assets/{chunk-XXDRQBXY-CnxFMLWV.js → chunk-XXDRQBXY-s1OG9sqW.js} +1 -1
  296. package/node_modules/@weavecode/server/web/dist/assets/{chunk-ZCHMQSOR-BhjCTig8.js → chunk-ZCHMQSOR-C3hINQU3.js} +2 -2
  297. package/node_modules/@weavecode/server/web/dist/assets/{classDiagram-v2-4MYWR3UA-rzlq5tPv.js → classDiagram-v2-4MYWR3UA-BTsbYrVl.js} +1 -1
  298. package/node_modules/@weavecode/server/web/dist/assets/{cose-bilkent-JH36ORCC-CxWQXzj8.js → cose-bilkent-JH36ORCC-C0W8Y-jI.js} +1 -1
  299. package/node_modules/@weavecode/server/web/dist/assets/{cynefin-EF2NZ3EQ-AFHjx2wU.js → cynefin-EF2NZ3EQ-stAu4Rh-.js} +1 -1
  300. package/node_modules/@weavecode/server/web/dist/assets/{cynefinDiagram-WF24UDRP-Bp_Oaf9U.js → cynefinDiagram-WF24UDRP-CqYibiiv.js} +1 -1
  301. package/node_modules/@weavecode/server/web/dist/assets/{dagre-NK4GIZVX-7oUPIU35.js → dagre-NK4GIZVX-qqcoJAqB.js} +1 -1
  302. package/node_modules/@weavecode/server/web/dist/assets/{diagram-CBK3MWTC-D_rS_rSY.js → diagram-CBK3MWTC-D0YTopb7.js} +1 -1
  303. package/node_modules/@weavecode/server/web/dist/assets/{diagram-I5XIIV2D-Duc_cKMb.js → diagram-I5XIIV2D-Csvw6aYr.js} +1 -1
  304. package/node_modules/@weavecode/server/web/dist/assets/{diagram-ODIL2UCW-DA0XFVXm.js → diagram-ODIL2UCW-Dl0tYLkF.js} +1 -1
  305. package/node_modules/@weavecode/server/web/dist/assets/{diagram-PFBEJUXE-D1U0Xhtt.js → diagram-PFBEJUXE-BCPSWZPe.js} +1 -1
  306. package/node_modules/@weavecode/server/web/dist/assets/{diagram-RJA3I4VV-CbDFY871.js → diagram-RJA3I4VV-ETg-BrAJ.js} +1 -1
  307. package/node_modules/@weavecode/server/web/dist/assets/{diagram-TYUNFSNR-jPg9AxQv.js → diagram-TYUNFSNR-_M6ZxBG7.js} +1 -1
  308. package/node_modules/@weavecode/server/web/dist/assets/{ebnfDiagram-V4P3TTPT-ZHfGTB0N.js → ebnfDiagram-V4P3TTPT-C-e_W7qx.js} +1 -1
  309. package/node_modules/@weavecode/server/web/dist/assets/{elk-QONTBCTQ-C-ESJrUi.js → elk-QONTBCTQ-B5TBharB.js} +1 -1
  310. package/node_modules/@weavecode/server/web/dist/assets/{erDiagram-KYQIGQAA-DGK7TeHj.js → erDiagram-KYQIGQAA-D08rj2pv.js} +1 -1
  311. package/node_modules/@weavecode/server/web/dist/assets/{flowDiagram-IUGLLWBU-CVV4rL8v.js → flowDiagram-IUGLLWBU-BALTxsKh.js} +1 -1
  312. package/node_modules/@weavecode/server/web/dist/assets/{ganttDiagram-R7GPNTJY-CuAwNvbm.js → ganttDiagram-R7GPNTJY-Cts193jT.js} +1 -1
  313. package/node_modules/@weavecode/server/web/dist/assets/{gitGraphDiagram-PDYL7XHY-D_15Wtf-.js → gitGraphDiagram-PDYL7XHY-L9qYUX0v.js} +1 -1
  314. package/node_modules/@weavecode/server/web/dist/assets/{infoDiagram-MVDRKAX5-ClqhbrCa.js → infoDiagram-MVDRKAX5-Bv47rgU0.js} +1 -1
  315. package/node_modules/@weavecode/server/web/dist/assets/{ishikawaDiagram-HPEHV2GE-CUJ891JX.js → ishikawaDiagram-HPEHV2GE-Da8_s6cs.js} +1 -1
  316. package/node_modules/@weavecode/server/web/dist/assets/{journeyDiagram-BOSHW7O7-B4skiMu-.js → journeyDiagram-BOSHW7O7-Bj3CjZOf.js} +1 -1
  317. package/node_modules/@weavecode/server/web/dist/assets/{kanban-definition-FNSA4HC5-UNGJR_y_.js → kanban-definition-FNSA4HC5-D1hicmMu.js} +1 -1
  318. package/node_modules/@weavecode/server/web/dist/assets/{linear-BEB-UwbR.js → linear-CWQg2iA1.js} +1 -1
  319. package/node_modules/@weavecode/server/web/dist/assets/main-XLn3EZFh.css +11 -0
  320. package/node_modules/@weavecode/server/web/dist/assets/main-bsb0lQoL.js +1096 -0
  321. package/node_modules/@weavecode/server/web/dist/assets/{mermaid.core-knGXJfjz.js → mermaid.core-C-wP0Zg2.js} +4 -4
  322. package/node_modules/@weavecode/server/web/dist/assets/{mindmap-definition-6OY57UG3-CEldbr3a.js → mindmap-definition-6OY57UG3-Dk0VKqre.js} +1 -1
  323. package/node_modules/@weavecode/server/web/dist/assets/{pegDiagram-ECIUJNBX-cNCkGLx3.js → pegDiagram-ECIUJNBX-Bp1K_F9z.js} +1 -1
  324. package/node_modules/@weavecode/server/web/dist/assets/pet-J6izA90s.js +1 -0
  325. package/node_modules/@weavecode/server/web/dist/assets/{pieDiagram-GNMPY74T-CfMEFiQD.js → pieDiagram-GNMPY74T-BZ4rGy3t.js} +1 -1
  326. package/node_modules/@weavecode/server/web/dist/assets/{quadrantDiagram-D57K4MC3-knmi2rwP.js → quadrantDiagram-D57K4MC3-B4N5KRsR.js} +1 -1
  327. package/node_modules/@weavecode/server/web/dist/assets/{railroadDiagram-Y72NRBL7-BJ7AzhEo.js → railroadDiagram-Y72NRBL7-C8nx8oHf.js} +1 -1
  328. package/node_modules/@weavecode/server/web/dist/assets/{requirementDiagram-EQYSW5RA-Dte2LGQM.js → requirementDiagram-EQYSW5RA-VSH57d0d.js} +1 -1
  329. package/node_modules/@weavecode/server/web/dist/assets/{sankeyDiagram-SY24JHO5-3noLaWgd.js → sankeyDiagram-SY24JHO5-jUb1hcya.js} +1 -1
  330. package/node_modules/@weavecode/server/web/dist/assets/{sequenceDiagram-BLEHNHQU-CclOWTTc.js → sequenceDiagram-BLEHNHQU-E2BioCNi.js} +1 -1
  331. package/node_modules/@weavecode/server/web/dist/assets/{sizeCapture-INFHLROL-B82sbLhA.js → sizeCapture-INFHLROL-BdKrbRmI.js} +1 -1
  332. package/node_modules/@weavecode/server/web/dist/assets/{stateDiagram-v2-A6IESKWZ-BXfVDwSN.js → stateDiagram-v2-A6IESKWZ-tFz7uNM7.js} +1 -1
  333. package/node_modules/@weavecode/server/web/dist/assets/{swimlanes-B3ENRKFQ-D4lKZaeV.js → swimlanes-B3ENRKFQ-B9BAPDWw.js} +1 -1
  334. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-DQ2NPLl9.js +8 -0
  335. package/node_modules/@weavecode/server/web/dist/assets/{timeline-definition-JXYKGLGB-D6H6zP5b.js → timeline-definition-JXYKGLGB-CofNnFTK.js} +1 -1
  336. package/node_modules/@weavecode/server/web/dist/assets/{usecaseDiagram-WPOLBNNX-D2J2bKo_.js → usecaseDiagram-WPOLBNNX-DOvjhJjJ.js} +1 -1
  337. package/node_modules/@weavecode/server/web/dist/assets/{vennDiagram-Q3Y3IDCW-pdRbIkpB.js → vennDiagram-Q3Y3IDCW-BcFHWnhS.js} +1 -1
  338. package/node_modules/@weavecode/server/web/dist/assets/{wardleyDiagram-IVAIDKWA-Cyd2QPMf.js → wardleyDiagram-IVAIDKWA-Bz2aqRAs.js} +1 -1
  339. package/node_modules/@weavecode/server/web/dist/assets/{xychartDiagram-4URNHDU4-Bd4BkwVM.js → xychartDiagram-4URNHDU4-DpNF6Vsq.js} +1 -1
  340. package/node_modules/@weavecode/server/web/dist/index.html +2 -2
  341. package/node_modules/@weavecode/server/web/dist/pet.html +80 -10
  342. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/pet.json +1 -1
  343. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/spritesheet.png +0 -0
  344. package/node_modules/@weavecode/templates/package.json +2 -2
  345. package/package.json +6 -6
  346. package/scripts/preinstall.mjs +60 -22
  347. package/node_modules/@weavecode/server/web/dist/assets/channel-C0RGiobt.js +0 -1
  348. package/node_modules/@weavecode/server/web/dist/assets/main-B_0jS_Gz.js +0 -1096
  349. package/node_modules/@weavecode/server/web/dist/assets/main-Czzlavi4.css +0 -11
  350. package/node_modules/@weavecode/server/web/dist/assets/pet-DJCpIDM5.js +0 -1
  351. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-DbdFh_d6.js +0 -8
@@ -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,n,e,r){const s=await fetch(`http://127.0.0.1:${t.port}/api${e}`,{method:n,headers:{...t.token?{"x-weave-local":t.token}:{},...r===void 0?{}:{"content-type":"application/json"}},...r===void 0?{}:{body:JSON.stringify(r)}}),i=await s.text(),p=(()=>{try{return JSON.parse(i)}catch{return{raw:i}}})();if(!s.ok){const l=p&&typeof p=="object"&&"error"in p?String(p.error):`HTTP ${s.status}`;throw new Error(l)}return p}const d=t=>{const n=new URLSearchParams;for(const[r,s]of Object.entries(t))s!==void 0&&s!==""&&n.set(r,String(s));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},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,n,e){switch(n){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(s=>s.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: ${n}`)}}function x(t){const n=new g({name:"weave-orchestration",version:"0.1.0"},{capabilities:{tools:{}}});return n.setRequestHandler(S,async()=>({tools:I})),n.setRequestHandler(f,async e=>{const{name:r,arguments:s}=e.params;try{const i=await k(t,r,s??{});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)}]}}}),n}export async function handleMcpRequest(t,n,e){const r=x(e),s=new b({sessionIdGenerator:void 0,enableJsonResponse:!0});n.on("close",()=>{s.close(),r.close()}),await r.connect(s);let i;if(t.method==="POST"){const p=await j(t);try{i=p.trim()?JSON.parse(p):void 0}catch{w(n,400,{error:"Invalid JSON body"});return}}await s.handleRequest(t,n,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(t,o,n,e){this.bus=t,this.surfaceOf=o,this.pathOf=n,this.harnessOf=e}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)},y))}pumpForTest(t="test"){return this.pump(t)}async pump(t){const o=this.harnessOf(t),n=(o?this.surfaceOf(o):null)?.lineParser,e=this.pathOf(t);if(!n||!e)return;let r;try{r=d(e).size}catch{this.cursors.delete(t);return}const s=this.cursors.get(t);if(!s||s.path!==e||r<s.offset){this.cursors.set(t,{offset:r,carry:"",path:e});return}if(r===s.offset)return;let a;const c=l(e,"r");try{const i=Buffer.alloc(r-s.offset);p(c,i,0,i.length,s.offset),a=i.toString("utf8")}catch{return}finally{m(c)}const h=(s.carry+a).split(`
2
+ `);s.carry=h.pop()??"",s.offset=r;const f=[];for(const i of h){const u=n(i);u&&f.push(u)}f.length>0&&this.bus.emit({kind:"narration.updated",sessionId:t,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 a}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,n){return i.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,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,s){return m.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(u))}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]=l.konsole,o=e[n],r=e[s];if(!o||!r)return null;const t=`konsole:${o}|${r}`;return parseKonsolePaneId(t)?t:null}const u=16777220;export function qtKeyOf(e){switch(e){case"\x1B":return 16777216;case"\r":case`
2
+ `:return u;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 +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 i,listTerminalAppSurfaces as e,listTerminalAppTargets as s,parseTerminalAppTargetId as l,pickTerminalAppWindow as p,terminalAppSurfacesCached as o}from"./pty-terminals.js";import{countWindowsByDir as d}from"./wezterm-mux.js";import{PRESET_CANDIDATES as m,TerminalBackend as w}from"./backend.js";export class TerminalAppBackend extends w{constructor(a){super("terminal",a==="darwin",a)}candidates(a,n){return m.terminal(a,n,this.platform)}async run(a,n){if(this.platform==="darwin"){const t=await e(this.platform),r=p(t,a,this.platform);if(r&&await i(a,n,r.windowId))return null}return await this.spawnFirst(this.candidates(a,n),`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(t=>[t,0]));const n=await o(this.platform);return n.length===0?new Map(a.map(t=>[t,0])):d(a,n.flatMap(t=>t.cwd?[{muxKey:"terminal.app",windowId:t.windowId,tabId:t.tabIndex,cwd:t.cwd}]:[]))}listTargets(a){return s(a,this.platform)}async runAt(a,n,t){const r=l(t);if(!r)throw new Error(`Invalid terminal target "${t}"`);if(!await i(a,n,r.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 v,weztermLiveMuxes as u,weztermMuxForId as p,weztermMuxKey as x,weztermPaneFromEnv as S,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:e}=await u(!0);return l={at:Date.now(),muxes:w,candidates:e},l}export class WeztermBackend extends A{constructor(e){super("wezterm",!0,e,!0)}candidates(e,n){return[{command:"wezterm",args:["start","--cwd",e,...M(n,this.platform==="win32")??[]]}]}async open(e){await E(e)||await super.open(e)}async run(e,n){return await P(e,n)||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])):g(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 p(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 d(o,r.socket);if(!s?.ok)throw new Error(m(o,r.socket,s));if(this.platform!=="win32")return;const c=(await p(t.muxKey))?.panes??r.panes,I=[(c.find(i=>i.paneId===a.paneId)??a).title,...c.filter(i=>i.windowId===t.windowId).map(i=>i.title)].filter(i=>!!i);await b({guiPid:v(r.socket)??void 0,titles:I})}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]=k.wezterm,r=e[t];if(!e[n]||!r)return null;const{muxes:a}=await u(!0,r);return S(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 K(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 p(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 d(["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 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(e,n){const t=parsePromptPaneId(e);if(!t)throw new Error(`Invalid prompt pane "${e}"`);const r=await p(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 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(e){const n=parsePromptPaneId(e);if(!n)throw new Error(`Invalid prompt pane "${e}"`);const t=await p(n.muxKey);if(!t)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],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 p(n.muxKey);if(!t)return null;const r=await d(["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 +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(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(r=>[r,0]));const n=await i();return n.length===0?new Map(t.map(r=>[r,0])):o(t,p(n))}async listTargets(t){if(this.platform!=="win32")return[];const n=await i(),r=o([t],p(n)).get(t)??0;return r===0?[]:[{id:`wt:${d(t)}`,windowId:0,tabId:0,title:c(t),matchCount:r,paneCount:r,active:!1,full:!1}]}async runAt(t,n,r){if(this.platform!=="win32")throw new Error(`Terminal preset "${this.preset}" is unavailable on this platform`);if(!w(r))throw new Error(`Invalid terminal target "${r}"`);return await this.spawnFirst([{command:"wt.exe",args:["-w",d(t),"split-pane","-d",t,...g(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 r=l(t,this.platform),s=(await i()).filter(a=>r!==null&&l(a.cwd,this.platform)===r).map(a=>a.pid);if(!s.length)throw new Error("That terminal is gone \u2014 reopen the list");await T({panePids:s,exe:"windowsterminal.exe"})}async locatePane(t){const n=E(t);return n==null||!u(n)?null:`wt:${n}`}ownsPaneId(t){return e(t)!==null}async sendPromptText(t,n){const r=e(t);if(r==null)throw new Error(`Invalid prompt pane "${t}"`);await m(r,`${h}${n}${f}\r`)}async sendKeys(t,n){const r=e(t);if(r==null)throw new Error(`Invalid prompt pane "${t}"`);await m(r,n)}}
@@ -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,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 r=`cd ${i(e,"darwin")} && ${s(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return n==="Terminal"?["-e",`tell application "Terminal" to do script "${r}"`,"-e",'tell application "Terminal" to activate']:["-e",'tell application "iTerm" to create window with default profile',"-e",`tell application "iTerm" to tell current window to write text "${r}"`]}export 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 +1 @@
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
+ 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)}
@@ -2,4 +2,4 @@ import{captureCommand as p,normalizeDirKey as d}from"./wezterm-mux.js";import{jo
2
2
  `);export function parseTerminalAppDump(o){const t=[];for(const r of o.split(`
3
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
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}
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 e=`cd ${f(o,"darwin")} && ${l(t,"darwin")}`.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return(await p("osascript",["-e",`tell application "Terminal" to do script "${e}" in window id ${r}`]))?.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(e,n){return n==="win32"?`"${e}"`:`'${e.replace(/'/g,"'\\''")}'`}export function quoteArg(e,n){return n==="win32"?e!==""&&!/[\s"&|<>^%]/.test(e)?e:`"${e.replace(/"/g,'\\"')}"`:/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}export function joinCmd(e,n){return e.map(r=>quoteArg(r,n)).join(" ")}export function throughCmd(e,n){return!n||!e||e.length===0?e:["cmd.exe","/k",joinCmd(e,"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(t){if(!t)return[];let e;try{e=JSON.parse(t)}catch{return[]}if(!Array.isArray(e))return[];const n=[];for(const r of e){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(t,e){if(!t)return null;let n=t;if(n.startsWith("file://")){n=n.slice(7);try{n=decodeURIComponent(n)}catch{return null}e==="win32"&&(n=n.replace(/^\//,""))}return n=n.replace(/\\/g,"/").replace(/\/+$/,""),n?e==="win32"?n.toLowerCase():n:null}export function countWindowsByDir(t,e,n=process.platform){const r=t.map(s=>normalizeDirKey(s,n)),o=t.map(()=>new Set);for(const s of e){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<t.length;a++)r[a]!==null&&r[a]===i&&o[a].add(c)}return new Map(t.map((s,i)=>[s,o[i].size]))}export const MAX_PANES_PER_SCREEN=6;function S(t,e,n){const r=new Map,o=new Map;for(const c of e)o.set(c.tabId,(o.get(c.tabId)??0)+1),normalizeDirKey(c.cwd,n)===t&&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(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 e=new Map;for(const o of t){const s=e.get(o.left)??[];s.push(o),e.set(o.left,s)}const n=[...e.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(t,e,n=process.platform){const r=normalizeDirKey(t,n);if(!r)return null;const o=S(r,e,n);return o===null?null:planWeztermGrid(e.filter(s=>s.tabId===o))}export function planWeztermNewWindow(t,e){const n=["cli","spawn","--new-window","--cwd",t];return e&&n.push("--workspace",e),n}export function weztermMuxKey(t){return $("sha256").update(normalizeDirKey(t,process.platform)??t).digest("hex").slice(0,8)}export function weztermPaneFromEnv(t,e,n){const[r,o]=h.wezterm,s=t[r],i=t[o];if(!s||!i)return null;const c=normalizeDirKey(i,n),a=e.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(t,e,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(t)){const l=u[o],d=u[s],w=d?e.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(t){const e=/^([0-9a-f]{8}):(\d+):(\d+)$/.exec(t);return e?{muxKey:e[1],windowId:Number(e[2]),tabId:Number(e[3])}:null}export function attachTargetsFromMuxes(t,e,n=process.platform){const r=normalizeDirKey(t,n);if(!r)return[];const o=[];for(const s of[...e].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(t,e=process.platform){const{muxes:n}=await weztermLiveMuxes();return attachTargetsFromMuxes(t,n,e)}export function weztermActiveClient(t){if(!t)return null;let e;try{e=JSON.parse(t)}catch{return null}if(!Array.isArray(e))return null;let n=null;for(const r of e){const o=r;if(typeof o?.workspace!="string"||!o.workspace)continue;const s=o.idle_time,i=(typeof s?.secs=="number"?s.secs*1e3:0)+(typeof s?.nanos=="number"?s.nanos/1e6:0);(n===null||i<n.idleMs)&&(n={workspace:o.workspace,idleMs:i})}return n}export function weztermActiveWorkspaceOf(t){return weztermActiveClient(t)?.workspace??null}const g=5e3;export function captureCommand(t,e,n,r=g){return new Promise(o=>{let s;try{s=k(t,e,{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(t,e){return captureCommand("wezterm",weztermCliArgs(t),{...process.env,WEZTERM_UNIX_SOCKET:e})}export function weztermCliArgs(t){return t[0]==="cli"?["cli","--no-auto-start",...t.slice(1)]:[...t]}export function weztermStepError(t,e,n){const r=`wezterm[${b(e)}] ${t.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(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 e=await captureCommand("tasklist",["/FI",`PID eq ${t}`,"/FO","CSV","/NH"],void 0,2e3);return e?.ok===!0&&/wezterm-gui\.exe/i.test(e.out)}export function weztermGuiPidOf(t){const e=/gui-sock-(\d+)$/.exec(t.replace(/\\/g,"/"));return e?Number(e[1]):null}function y(t){let e;try{e=z(t)}catch{return[]}const n=[];for(const r of e){const o=/^gui-sock-(\d+)$/.exec(r);if(!o)continue;const s=Number(o[1]);x(s)&&n.push({path:I(t,r),pid:s})}return n.sort((r,o)=>o.pid-r.pid).map(r=>r.path)}function E(t,e){const n=t.replace(/\\/g,"/");return e==="win32"?n.toLowerCase():n}export function weztermSocketCandidates(t){const e=[],n=new Set,r=i=>{const c=E(i,t);n.has(c)||(n.add(c),e.push(i))},o=process.env.WEZTERM_UNIX_SOCKET;if(o){const i=weztermGuiPidOf(o);(i===null||x(i))&&r(o)}const s=t==="win32"?process.env.USERPROFILE:process.env.HOME;return s&&y(I(s,".local","share","wezterm")).forEach(r),t!=="win32"&&process.env.XDG_RUNTIME_DIR&&y(I(process.env.XDG_RUNTIME_DIR,"wezterm")).forEach(r),e}const _=6e4;export class SocketProbeGate{dead=new Set;cooling=new Map;shouldProbe(e,n=Date.now()){if(this.dead.has(e))return!1;const r=this.cooling.get(e);return r===void 0||n>=r}succeeded(e){this.cooling.delete(e)}failed(e){this.dead.add(e),this.cooling.delete(e)}cooledDown(e,n=Date.now()){this.dead.has(e)||this.cooling.set(e,n+_)}}export const probeGate=new SocketProbeGate;export async function weztermLiveMuxes(t=!1,e=null){const n=e?[e]:weztermSocketCandidates(process.platform);return{muxes:(await Promise.all(n.map(async r=>{if(!e&&!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(t)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(t){const e=weztermSocketCandidates(process.platform).find(r=>weztermMuxKey(r)===t);if(!e)return null;const{muxes:n}=await weztermLiveMuxes(!0,e);return n.find(r=>weztermMuxKey(r.socket)===t)??null}export async function openInWezterm(t){const{muxes:e}=await weztermLiveMuxes();if(e.length===0)return!1;const n=e.reduce((r,o)=>o.idleMs<r.idleMs?o:r);return await weztermSpawnPane(n.socket,t,null,n.workspace),!0}export async function runInWezterm(t,e){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(t,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,t,e,s,o.workspace)}export async function weztermSpawnPane(t,e,n,r){const o=n?["cli","split-pane","--pane-id",String(n.paneId),`--${n.direction}`,"--cwd",e]:planWeztermNewWindow(e,r),s=await weztermCli(o,t);if(!s?.ok)throw new Error(weztermStepError(o,t,s));const i=s.out.trim();if(!/^\d+$/.test(i))throw new Error(`wezterm[${b(t)}] ${o.join(" ")}: unexpected pane id "${i}"`);return i}export async function weztermSpawnAndSend(t,e,n,r,o,s=process.platform){const i=await weztermSpawnPane(t,e,r,o),c=["cli","send-text","--pane-id",i,"--no-paste",`${M(n,s)}\r`],a=await weztermCli(c,t);if(!a?.ok)throw new Error(weztermStepError(c,t,a));const[u,l]=h.wezterm;return{env:{[u]:i,[l]:t}}}
@@ -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
  '@
@@ -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 b}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 I,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 v 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,r){return this.parts.flatMap(a=>r&&a.preset==="iterm"?[]:a.candidates(e,r))}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,r,a){return this.attachBackend().runAt(e,r,a)}focusTarget(e,r){return this.attachBackend().focusTarget(e,r)}listPromptPanes(){return this.attachBackend().listPromptPanes()}locatePane(e){return this.attachBackend().locatePane(e)}locateScreens(e){return this.attachBackend().locateScreens(e)}sendPromptText(e,r){return this.attachBackend().sendPromptText(e,r)}sendKeys(e,r){return this.attachBackend().sendKeys(e,r)}getPaneText(e){return this.attachBackend().getPaneText(e)}closePane(e){return this.attachBackend().closePane(e)}}const g={auto:(t,e)=>new v(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 b(e),wezterm:(t,e)=>new x(e),custom:(t,e)=>new I(t,e)};export function terminalBackendFor(t,e=process.platform){return(g[t.preset]??g.auto)(t,e)}export function locatorPresetOf(t){for(const[e,r]of Object.entries(h))if(r.every(a=>t[a]))return e;return null}export function promptTerminalChannel(t){const e=n=>terminalBackendFor({...t(),preset:n}),r=()=>e(t().preset),a=()=>Object.keys(h).map(n=>e(n)),s=n=>{const o=locatorPresetOf(n);return o?e(o):null},c=n=>a().find(o=>o.ownsPaneId(n))??null;return{available:()=>a().some(n=>n.textAddressable),listPanes:async()=>{const n=r();return n.textAddressable?await n.listPromptPanes():[]},locatePane:async n=>await s(n)?.locatePane(n)??null,locateScreens:async n=>{const o={},i=new Map;for(const[l,m]of Object.entries(n)){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(n,o)=>{const i=c(n);if(!i)throw new Error(`Invalid prompt pane "${n}"`);await i.sendPromptText(n,o)},sendKeys:async(n,o)=>{const i=c(n);if(!i)throw new Error(`Invalid prompt pane "${n}"`);await i.sendKeys(n,o)},getPaneText:async n=>{const o=c(n);if(!o)throw new Error(`Invalid prompt pane "${n}"`);return o.getPaneText(n)},closePane:async n=>{const o=c(n);if(!o)throw new Error(`Invalid prompt pane "${n}"`);await o.closePane(n)}}}export async function runInTerminal(t,e,r){return terminalBackendFor(r).run(t,e)}export async function countOpenTerminals(t,e){return terminalBackendFor(e).countWindows(t)}export function panesAtDir(t,e,r=process.platform){const a=P(e,r);return t.filter(s=>s.cwd!=null&&P(s.cwd,r)===a)}export async function listProjectPanes(t,e,r=process.platform){const a=terminalBackendFor(e,r),s=panesAtDir(await a.listPromptPanes(),t,r);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,r,a=process.platform){const s=terminalBackendFor(e,a),c=new Set(r),n=(await listProjectPanes(t,e,a)).filter(o=>c.has(o.id));for(const o of n)await s.closePane(o.id);return n.length}export async function readTerminalCounts(t,e=void 0){const r=await B(),s=await(e?.countTerminals??countOpenTerminals)(t.map(c=>c.path),r.terminal);return Object.fromEntries(t.map(c=>[c.id,s.get(c.path)??0]))}export function resolveTerminalLaunch(t,e,r=process.platform,a){return terminalBackendFor(e,r).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,r)=>closeTerminalsIn(t,e,r),listPanes:(t,e)=>listProjectPanes(t,e),listTerminals:(t,e)=>terminalBackendFor(e).listTargets(t),runInTerminalAt:(t,e,r,a)=>terminalBackendFor(a).runAt(t,e,r),focusTerminal:(t,e,r)=>terminalBackendFor(r).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,6 +1,4 @@
1
- /**
2
- * 内置默认宠播种:`@weavecode/templates` 随包发货的 `resources/pets/` 落到
3
- * `<data>/pets/<id>/`。**缺失才拷**(mtime+size 指纹对不上也不覆盖——用户改过
4
- * 的资产是数据,不是包内容);目录已存在即视为用户领地,跳过。
5
- */
6
- export declare function seedBuiltinPets(): Promise<void>;
1
+ export declare function seedBuiltinPets(opts?: {
2
+ builtinRoot?: string;
3
+ dataDir?: string;
4
+ }): Promise<void>;
@@ -1 +1,2 @@
1
- import{cp as c,mkdir as a,readdir as s,stat as u}from"node:fs/promises";import e from"node:path";import{builtinPetsRoot as n}from"@weavecode/templates";import{getPetsDir as m}from"../db/paths.js";export async function seedBuiltinPets(){let t;try{t=await s(n())}catch{return}const i=m();await a(i,{recursive:!0});for(const r of t){const o=e.join(i,r);(await u(o).catch(()=>null))?.isDirectory()||await c(e.join(n(),r),o,{recursive:!0}).catch(()=>{})}}
1
+ import{createHash as h}from"node:crypto";import{cp as w,mkdir as b,readFile as m,readdir as d,stat as p,writeFile as j}from"node:fs/promises";import a from"node:path";import{builtinPetsRoot as g}from"@weavecode/templates";import{getPetsDir as x}from"../db/paths.js";const e=".weave-builtin";async function v(c){const n=[];for(const i of(await d(c)).sort()){if(i===e)continue;const o=a.join(c,i);(await p(o)).isFile()&&n.push(`${i}:${h("sha256").update(await m(o)).digest("hex")}`)}return h("sha256").update(n.join(`
2
+ `)).digest("hex")}export async function seedBuiltinPets(c={}){const n=c.builtinRoot??g();let i;try{i=await d(n)}catch{return}const o=x(c.dataDir);await b(o,{recursive:!0});for(const u of i){const r=a.join(n,u),t=a.join(o,u),s=await v(r).catch(()=>null);if(!(await p(t).catch(()=>null))?.isDirectory()){await w(r,t,{recursive:!0}).catch(()=>{}),s&&await j(a.join(t,e),s).catch(()=>{});continue}const l=await m(a.join(t,e),"utf8").catch(()=>null);if(!l||!s)continue;const f=await v(t).catch(()=>null);f!==l.trim()||f===s||(await w(r,t,{recursive:!0}).catch(()=>{}),await j(a.join(t,e),s).catch(()=>{}))}}
@@ -1,2 +1,2 @@
1
- import{spawn as f}from"node:child_process";import{existsSync as d}from"node:fs";import s from"node:path";import{fileURLToPath as h}from"node:url";import{PET_SIZE_PRESETS as a,readDaemonSettingsSync as p}from"./settings.js";const m=s.join(s.dirname(h(import.meta.url)),"../../res/pet-window"),w=3e4,t={proc:null,lastCrashAt:null};export function petWindowExePath(){return s.join(m,"weave-pet-window.exe")}export function canOpenPetWindow(){return process.platform==="win32"&&d(petWindowExePath())}export function openPetWindow(e){if(!canOpenPetWindow()||t.proc)return!1;const o=p().pet;if(!o?.enabled)return!1;const i=a[o.size]??a.small,r=o.pos,l=[`${e.baseUrl}/pet.html`,"--size",`${i.width}x${i.height}`,...r?["--pos",`${r.x},${r.y}`]:[],...e.auth?["--cookie",e.auth.issueSession()]:[]];let n;try{n=f(petWindowExePath(),l,{detached:!1,stdio:["pipe","ignore","ignore"],windowsHide:!0})}catch{return!1}return t.proc=n,n.on("exit",()=>{const u=t.proc===n;if(t.proc=null,!u)return;const c=Date.now();t.lastCrashAt!==null&&c-t.lastCrashAt<w||(t.lastCrashAt=c,setTimeout(()=>{p().pet?.enabled&&openPetWindow(e)},1e3).unref())}),!0}export function closePetWindow(){const e=t.proc;if(e){t.proc=null;try{e.stdin?.end(`close
1
+ import{spawn as d}from"node:child_process";import{existsSync as m}from"node:fs";import i from"node:path";import{fileURLToPath as f}from"node:url";import{PET_SIZE_PRESETS as p,readDaemonSettingsSync as c}from"./settings.js";const w=i.join(i.dirname(f(import.meta.url)),"../../res/pet-window"),h=3e4,t={proc:null,lastCrashAt:null};export function petWindowExePath(){return i.join(w,"weave-pet-window.exe")}export function canOpenPetWindow(){return process.platform==="win32"&&m(petWindowExePath())}export function openPetWindow(e){if(!canOpenPetWindow()||t.proc)return!1;const n=c().pet;if(!n?.enabled)return!1;const s=p[n.size]??p.small,r=n.pos,l=[`${e.baseUrl}/pet.html`,"--size",`${s.width}x${s.height}`,...r?["--pos",`${r.x},${r.y}`]:[],...e.auth?["--cookie",e.auth.issueSession()]:[]];let o;try{o=d(petWindowExePath(),l,{detached:!1,stdio:["pipe","ignore","ignore"],windowsHide:!0})}catch{return!1}return t.proc=o,o.on("exit",()=>{const u=t.proc===o;if(t.proc=null,!u)return;const a=Date.now();t.lastCrashAt!==null&&a-t.lastCrashAt<h||(t.lastCrashAt=a,setTimeout(()=>{c().pet?.enabled&&openPetWindow(e)},1e3).unref())}),!0}export function closePetWindow(){const e=t.proc;if(e){t.proc=null;try{e.stdin?.end(`close
2
2
  `)}catch{e.kill()}}}export function shutdownPetWindow(){closePetWindow()}
@@ -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 n 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 t=n.createServer();t.once("error",()=>e(!1)),t.once("listening",()=>t.close(()=>e(!0))),t.listen(r,o)})}export async function findFreePort(r,o=100){for(let e=r;e<r+o;e++)if(await isPortFree(e))return e;throw new Error(`No free port found in range ${r}-${r+o-1}`)}
@@ -1,2 +1,2 @@
1
- import{execFile as z}from"node:child_process";import{lstat as b,mkdir as B,readFile as x,readdir as J,realpath as _,rename as Y,stat as $,writeFile as K}from"node:fs/promises";import{readdirSync as Q,rmSync as U}from"node:fs";import{homedir as Z}from"node:os";import l from"node:path";import{promisify as q}from"node:util";import{getIndexDir as L}from"../db/paths.js";const v=q(z);export const MAX_INDEX_FILES=3e5,INDEX_VERSION=3;const W=3e4,j=10*6e4,tt=3,et=new Set(["node_modules",".git","dist","build","out",".next","target","coverage",".turbo"]);async function C(t,e){try{const{stdout:n}=await v("git",["ls-files","-z",...e],{cwd:t,timeout:1e4,maxBuffer:67108864,windowsHide:!0});return n.split("\0").filter(Boolean)}catch{return null}}async function nt(t){const e=async i=>await b(i).then(()=>!0,()=>!1)?i:null;try{const{stdout:i}=await v("git",["config","--get","--path","core.excludesFile"],{cwd:t,timeout:5e3,windowsHide:!0}),s=i.trim();if(s)return e(l.resolve(t,s))}catch{}const n=process.env.XDG_CONFIG_HOME||l.join(Z(),".config");return e(l.join(n,"git","ignore"))}async function it(t){const e=["--exclude-per-directory=.gitignore"],n=await nt(t);return n&&e.push(`--exclude-from=${n}`),e}const I=new Map;async function H(t){let e=I.get(t);return e||(e=await it(t),I.set(t,e)),e}async function st(t){const e=await C(t,["--stage"]),n=[],i=[];for(const s of e??[])s.startsWith("160000 ")?n.push(s.slice(s.indexOf(" ")+1)):s.startsWith("120000 ")&&i.push(s.slice(s.indexOf(" ")+1));return{links:n,symlinks:i}}function N(t){return b(l.join(t,".git")).then(()=>!0,()=>!1)}async function rt(t){try{let e=l.join(t,".git");if(!(await b(e)).isDirectory()){const s=/^gitdir:\s*(.+)$/m.exec(await x(e,"utf8"));if(!s)return null;e=l.resolve(t,s[1].trim())}const n=(await x(l.join(e,"HEAD"),"utf8")).trim(),i=n.startsWith("ref: ")?await(async()=>{const s=n.slice(5);try{return(await x(l.join(e,s),"utf8")).trim()}catch{const r=(await x(l.join(e,"packed-refs"),"utf8")).split(`
2
- `).find(c=>c.endsWith(` ${s}`));return r?r.slice(0,r.indexOf(" ")):null}})():n;return i!==null&&/^[0-9a-f]{40}$/i.test(i)?i.slice(0,7):null}catch{return null}}async function at(t){const e=await C(t,["--others","--ignored",...await H(t),"--directory"]),n=[];for(const i of e??[]){if(!i.endsWith("/"))continue;const s=i.slice(0,-1);await N(l.join(t,s))&&n.push(s)}return n}async function A(t,e="",n=[]){const[i,s,a]=await Promise.all([(async()=>{const o=["--cached","--others",...n.length?n:await H(t)];return C(t,o)})(),st(t),at(t)]);if(!i)return null;const r=new Set;for(const o of s.links)r.add(o);for(const o of i)o.endsWith("/")&&r.add(o.slice(0,-1));for(const o of a)r.add(o);const c=new Set;for(const o of s.symlinks)if(!r.has(o))try{(await $(l.join(t,o))).isDirectory()&&c.add(o)}catch{}const f=i.filter(o=>!o.endsWith("/")&&!r.has(o)&&!c.has(o)).map(o=>e+o),d=[...r,...c].map(o=>e+o),y={};for(const o of r){const w=l.join(t,o);if(!await N(w))continue;const g=await rt(w);g&&(y[`${e}${o}`]=g);const u=await A(w,`${e}${o}/`,n);u&&(f.push(...u.files),d.push(...u.links),Object.assign(y,u.heads))}const D=new Set([await _(t).catch(()=>t)]);for(const o of c){const w=l.join(t,o),g=await _(w).catch(()=>null);if(g===null||D.has(g))continue;D.add(g);const u=`${e}${o}/`;for(let p=f.length-1;p>=0;p--)f[p].startsWith(u)&&f.splice(p,1);const m=await A(w,u,n)??{files:await X(w),links:[],heads:{}};f.push(...m.files),d.push(...m.links),Object.assign(y,m.heads)}return{files:f,links:d,heads:y}}async function X(t){const e=[],n=new Set([await _(t).catch(()=>t)]),i=async s=>{if(e.length>=MAX_INDEX_FILES)return;let a;try{a=await J(l.join(t,s),{withFileTypes:!0})}catch{return}for(const r of a){if(e.length>=MAX_INDEX_FILES)return;const c=s?`${s}/${r.name}`:r.name;if(r.isDirectory()||r.isSymbolicLink()){if(et.has(r.name))continue;if(r.isSymbolicLink()){let f;try{f=(await $(l.join(t,c))).isDirectory()}catch{f=!1}if(!f){r.name!==".git"&&e.push(c);continue}const d=await _(l.join(t,c)).catch(()=>null);if(d===null||n.has(d))continue;n.add(d);try{await i(c)}finally{n.delete(d)}}else await i(c)}else r.isFile()&&r.name!==".git"&&e.push(c)}};return await i(""),e}function P(t){const e=new Set;for(const n of t){let i=n.lastIndexOf("/");for(;i>0;){const s=n.slice(0,i);if(e.has(s))break;e.add(s),i=s.lastIndexOf("/")}}return[...e].sort()}async function O(t){try{let e=l.join(t,".git");if(!(await b(e)).isDirectory()){const i=/^gitdir:\s*(.+)$/m.exec(await x(e,"utf8"));if(!i)return null;e=l.resolve(t,i[1].trim())}const n=await $(l.join(e,"index"));return`${n.mtimeMs}:${n.size}`}catch{return null}}async function ot(t){const e=await A(t),n=e?.files??await X(t),i=n.length>MAX_INDEX_FILES,s=i?n.slice(0,MAX_INDEX_FILES):n;s.sort();const a=e?.links??[],r=[...new Set([...P(s),...a,...P(a)])].sort();return{v:INDEX_VERSION,root:t,at:Date.now(),stamp:await O(t),truncated:i,files:s,dirs:r,...e&&Object.keys(e.heads).length>0?{submodules:e.heads}:{}}}export function hydrateIndex(t){const e=new Array(t.files.length);for(let a=0;a<t.files.length;a++)e[a]=t.files[a].toLowerCase();const n=new Array(t.dirs.length);for(let a=0;a<t.dirs.length;a++)n[a]=t.dirs[a].toLowerCase();const i=new Map,s=a=>{let r=i.get(a);return r||i.set(a,r={dirs:[],files:[],sorted:!1}),r};for(const a of t.dirs)s(a.slice(0,Math.max(0,a.lastIndexOf("/")))).dirs.push(a);for(const a of t.files)s(a.slice(0,Math.max(0,a.lastIndexOf("/")))).files.push(a);return{...t,lower:e,dirLower:n,children:i,submodules:t.submodules??{}}}export async function buildIndex(t){return hydrateIndex(await ot(t))}const h=new Map,S=new Map;let E=null;export function setFileIndexRoot(t){E=t}function R(t){return l.join(E??L(),`${t}.json`)}function ct(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 lt(t,e){const n=R(t),i=`${n}.tmp`;try{await B(l.dirname(n),{recursive:!0}),await K(i,JSON.stringify(ct(e)),"utf8"),await Y(i,n)}catch{}}async function T(t,e){try{const n=JSON.parse(await x(R(t),"utf8"));return n?.v!==INDEX_VERSION||n.root!==e||!Array.isArray(n.files)||!Array.isArray(n.dirs)?null:n}catch{return null}}function M(t,e){for(h.delete(t),h.set(t,e);h.size>tt;){const n=h.keys().next().value;if(n===void 0)break;h.delete(n)}}function F(t,e){const n=S.get(t);if(n)return n;const i=buildIndex(e).then(a=>(M(t,a),lt(t,a),a));S.set(t,i);const s=()=>{S.delete(t)};return i.then(s,s),i}export async function projectFileIndex(t,e,n={}){if(n.fresh){const r=S.get(t);if(r)return r}const i=h.get(t);i&&i.root!==e&&h.delete(t);const s=i&&i.root===e?i:null;if(s&&n.fresh)return F(t,e).catch(()=>{}),s;if(s&&await O(e)===s.stamp){if(Date.now()-s.at<W)return s;h.delete(t)}else s&&h.delete(t);const a=S.get(t);if(a)return a;if(!s){const r=await T(t,e);if(r&&Date.now()-r.at<j){const c=hydrateIndex(r);if(n.fresh)return M(t,c),F(t,e).catch(()=>{}),c;if(await O(e)===r.stamp)return M(t,c),c}}return F(t,e)}export async function peekCachedIndex(t,e,n={}){const i=h.get(t);if(i&&i.root===e)return Date.now()-i.at<W&&await O(e)===i.stamp?i:(h.delete(t),null);const s=n.maxStaleMs??j,a=await T(t,e);if(a&&Date.now()-a.at<s&&await O(e)===a.stamp){const r=hydrateIndex(a);return M(t,r),r}return null}export function clearFileIndexCache(){h.clear()}export function pruneFileIndexes(t){const e=E??L(),n=new Set(t.map(s=>`${s}.json`));let i;try{i=Q(e)}catch{return}for(const s of i)if(!(!s.endsWith(".json")||n.has(s)))try{U(l.join(e,s))}catch{}}const G=new Intl.Collator(void 0,{numeric:!0});export function listDirOf(t,e){const n=t.children.get(e);if(!n)return[];n.sorted||(n.dirs.sort(G.compare),n.files.sort(G.compare),n.sorted=!0);const i=[];for(const s of n.dirs){const a=t.submodules[s];i.push(a?{path:s,kind:"dir",head:a}:{path:s,kind:"dir"})}for(const s of n.files)i.push({path:s,kind:"file"});return i}function ft(t,e){return t.startsWith(e)?3:t.includes(e)?2:ut(t,e)?1:-1}function ut(t,e){let n=0;for(let i=0;i<t.length&&n<e.length;i++)t[i]===e[n]&&n++;return n===e.length}function ht(t,e,n){const i=t.lastIndexOf("/")+1,s=t.slice(i).toLowerCase();if(e===3||e===2){const c=s.indexOf(n);return c<0?[]:[[i+c,n.length]]}const a=[];let r=0;for(let c=0;c<s.length&&r<n.length;c++)s[c]===n[r]&&(a.push([i+c,1]),r++);return a}function V(t,e){return e.rank-t.rank||t.len-e.len||t.path.localeCompare(e.path)}const dt=8,wt=1024;function mt(t,e){if(!e)return 0;let n=0,i=t.length;for(;n<i;){const s=n+i>>1;t[s]<e?n=s+1:i=s}return n}export function startMatch(t,e,n,i=""){const s=e.trim().toLowerCase(),a=i?`${i}/`:"",r=[];let c=s&&n>0?"files":"done",f=0,d=0,y=!1;const D=(o,w)=>{const g=o.slice(o.lastIndexOf("/")+1).toLowerCase(),u=ft(g,s);if(u<0)return;d++;const m={path:o,kind:w,rank:u,len:o.length};if(r.length===n&&V(m,r[n-1])>=0)return;const p=r.length===n;let k=p?n-1:r.length;for(p?r[n-1]=m:r.push(m);k>0&&V(m,r[k-1])<0;)r[k]=r[k-1],k--;r[k]=m};return{step(o){const w=Date.now()+o;let g=0;for(;c!=="done";){const u=c==="files"?t.files:t.dirs,m=c==="files"?"file":"dir";for(f===0&&(f=mt(u,a));f<u.length;){const p=u[f];if(a&&!p.startsWith(a))break;if(D(p,m),f++,r.length===n&&r[n-1].rank===3)return y=!0,c="done",!0;if((++g&wt-1)===0&&Date.now()>w)return!1}f=0,c=c==="files"?"dirs":"done"}return!0},result(){return{hits:r.map(o=>({path:o.path,kind:o.kind,ranges:ht(o.path,o.rank,s)})),total:y?r.length:d,capped:y}}}}export async function matchPaths(t,e,n,i=""){const s=startMatch(t,e,n,i);for(;!s.step(dt);)await new Promise(a=>setImmediate(a));return s.result()}
1
+ import{execFile as R}from"node:child_process";import{lstat as b,mkdir as T,readFile as k,readdir as V,realpath as $,rename as q,stat as S,writeFile as K}from"node:fs/promises";import{readdirSync as Q,rmSync as U}from"node:fs";import{homedir as Y}from"node:os";import l from"node:path";import{promisify as Z}from"node:util";import{getIndexDir as C}from"../db/paths.js";const L=Z(R);export const MAX_INDEX_FILES=3e5,INDEX_VERSION=3;const A=3e4,E=10*6e4,tt=3,et=new Set(["node_modules",".git","dist","build","out",".next","target","coverage",".turbo"]);async function v(t,e){try{const{stdout:n}=await L("git",["ls-files","-z",...e],{cwd:t,timeout:1e4,maxBuffer:67108864,windowsHide:!0});return n.split("\0").filter(Boolean)}catch{return null}}async function nt(t){const e=async s=>await b(s).then(()=>!0,()=>!1)?s:null;try{const{stdout:s}=await L("git",["config","--get","--path","core.excludesFile"],{cwd:t,timeout:5e3,windowsHide:!0}),i=s.trim();if(i)return e(l.resolve(t,i))}catch{}const n=process.env.XDG_CONFIG_HOME||l.join(Y(),".config");return e(l.join(n,"git","ignore"))}async function st(t){const e=["--exclude-per-directory=.gitignore"],n=await nt(t);return n&&e.push(`--exclude-from=${n}`),e}const N=new Map;async function _(t){let e=N.get(t);return e||(e=await st(t),N.set(t,e)),e}async function it(t){const e=await v(t,["--stage"]),n=[],s=[];for(const i of e??[])i.startsWith("160000 ")?n.push(i.slice(i.indexOf(" ")+1)):i.startsWith("120000 ")&&s.push(i.slice(i.indexOf(" ")+1));return{links:n,symlinks:s}}function H(t){return b(l.join(t,".git")).then(()=>!0,()=>!1)}async function rt(t){try{let e=l.join(t,".git");if(!(await b(e)).isDirectory()){const i=/^gitdir:\s*(.+)$/m.exec(await k(e,"utf8"));if(!i)return null;e=l.resolve(t,i[1].trim())}const n=(await k(l.join(e,"HEAD"),"utf8")).trim(),s=n.startsWith("ref: ")?await(async()=>{const i=n.slice(5);try{return(await k(l.join(e,i),"utf8")).trim()}catch{const r=(await k(l.join(e,"packed-refs"),"utf8")).split(`
2
+ `).find(o=>o.endsWith(` ${i}`));return r?r.slice(0,r.indexOf(" ")):null}})():n;return s!==null&&/^[0-9a-f]{40}$/i.test(s)?s.slice(0,7):null}catch{return null}}async function ot(t){const e=await v(t,["--others","--ignored",...await _(t),"--directory"]),n=[];for(const s of e??[]){if(!s.endsWith("/"))continue;const i=s.slice(0,-1);await H(l.join(t,i))&&n.push(i)}return n}async function F(t,e="",n=[]){const[s,i,r]=await Promise.all([(async()=>{const a=["--cached","--others",...n.length?n:await _(t)];return v(t,a)})(),it(t),ot(t)]);if(!s)return null;const o=new Set;for(const a of i.links)o.add(a);for(const a of s)a.endsWith("/")&&o.add(a.slice(0,-1));for(const a of r)o.add(a);const c=new Set;for(const a of i.symlinks)if(!o.has(a))try{(await S(l.join(t,a))).isDirectory()&&c.add(a)}catch{}const f=s.filter(a=>!a.endsWith("/")&&!o.has(a)&&!c.has(a)).map(a=>e+a),h=[...o,...c].map(a=>e+a),g={};for(const a of o){const w=l.join(t,a);if(!await H(w))continue;const m=await rt(w);m&&(g[`${e}${a}`]=m);const u=await F(w,`${e}${a}/`,n);u&&(f.push(...u.files),h.push(...u.links),Object.assign(g,u.heads))}const O=new Set([await $(t).catch(()=>t)]);for(const a of c){const w=l.join(t,a),m=await $(w).catch(()=>null);if(m===null||O.has(m))continue;O.add(m);const u=`${e}${a}/`;for(let y=f.length-1;y>=0;y--)f[y].startsWith(u)&&f.splice(y,1);const p=await F(w,u,n)??{files:await X(w),links:[],heads:{}};f.push(...p.files),h.push(...p.links),Object.assign(g,p.heads)}return{files:f,links:h,heads:g}}async function X(t){const e=[],n=new Set([await $(t).catch(()=>t)]),s=async i=>{if(e.length>=MAX_INDEX_FILES)return;let r;try{r=await V(l.join(t,i),{withFileTypes:!0})}catch{return}for(const o of r){if(e.length>=MAX_INDEX_FILES)return;const c=i?`${i}/${o.name}`:o.name;if(o.isDirectory()||o.isSymbolicLink()){if(et.has(o.name))continue;if(o.isSymbolicLink()){let f;try{f=(await S(l.join(t,c))).isDirectory()}catch{f=!1}if(!f){o.name!==".git"&&e.push(c);continue}const h=await $(l.join(t,c)).catch(()=>null);if(h===null||n.has(h))continue;n.add(h);try{await s(c)}finally{n.delete(h)}}else await s(c)}else o.isFile()&&o.name!==".git"&&e.push(c)}};return await s(""),e}function z(t){const e=new Set;for(const n of t){let s=n.lastIndexOf("/");for(;s>0;){const i=n.slice(0,s);if(e.has(i))break;e.add(i),s=i.lastIndexOf("/")}}return[...e].sort()}async function j(t){try{let e=l.join(t,".git");if(!(await b(e)).isDirectory()){const s=/^gitdir:\s*(.+)$/m.exec(await k(e,"utf8"));if(!s)return null;e=l.resolve(t,s[1].trim())}const n=await S(l.join(e,"index"));return`${n.mtimeMs}:${n.size}`}catch{return null}}async function at(t){const e=await F(t),n=e?.files??await X(t),s=n.length>MAX_INDEX_FILES,i=s?n.slice(0,MAX_INDEX_FILES):n;i.sort();const r=e?.links??[],o=[...new Set([...z(i),...r,...z(r)])].sort();return{v:INDEX_VERSION,root:t,at:Date.now(),stamp:await j(t),truncated:s,files:i,dirs:o,...e&&Object.keys(e.heads).length>0?{submodules:e.heads}:{}}}export function hydrateIndex(t){const e=new Array(t.files.length);for(let r=0;r<t.files.length;r++)e[r]=t.files[r].toLowerCase();const n=new Array(t.dirs.length);for(let r=0;r<t.dirs.length;r++)n[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:e,dirLower:n,children:s,submodules:t.submodules??{}}}export async function buildIndex(t){return hydrateIndex(await at(t))}const d=new Map,I=new Map;let M=null;export function setFileIndexRoot(t){M=t}function P(t){return l.join(M??C(),`${t}.json`)}function ct(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 lt(t,e){const n=P(t),s=`${n}.tmp`;try{await T(l.dirname(n),{recursive:!0}),await K(s,JSON.stringify(ct(e)),"utf8"),await q(s,n)}catch{}}async function B(t,e){try{const n=JSON.parse(await k(P(t),"utf8"));return n?.v!==INDEX_VERSION||n.root!==e||!Array.isArray(n.files)||!Array.isArray(n.dirs)?null:n}catch{return null}}function D(t,e){for(d.delete(t),d.set(t,e);d.size>tt;){const n=d.keys().next().value;if(n===void 0)break;d.delete(n)}}function W(t,e){const n=I.get(t);if(n)return n;const s=buildIndex(e).then(r=>(D(t,r),lt(t,r),r));I.set(t,s);const i=()=>{I.delete(t)};return s.then(i,i),s}export async function projectFileIndex(t,e,n={}){if(n.fresh){const o=I.get(t);if(o)return o}const s=d.get(t);s&&s.root!==e&&d.delete(t);const i=s&&s.root===e?s:null;if(i&&n.fresh)return W(t,e).catch(()=>{}),i;if(i&&await j(e)===i.stamp){if(Date.now()-i.at<A)return i;d.delete(t)}else i&&d.delete(t);const r=I.get(t);if(r)return r;if(!i){const o=await B(t,e);if(o&&Date.now()-o.at<E){const c=hydrateIndex(o);if(n.fresh)return D(t,c),W(t,e).catch(()=>{}),c;if(await j(e)===o.stamp)return D(t,c),c}}return W(t,e)}export async function peekCachedIndex(t,e,n={}){const s=d.get(t);if(s&&s.root===e)return Date.now()-s.at<A&&await j(e)===s.stamp?s:(d.delete(t),null);const i=n.maxStaleMs??E,r=await B(t,e);if(r&&Date.now()-r.at<i&&await j(e)===r.stamp){const o=hydrateIndex(r);return D(t,o),o}return null}export function clearFileIndexCache(){d.clear()}export function pruneFileIndexes(t){const e=M??C(),n=new Set(t.map(i=>`${i}.json`));let s;try{s=Q(e)}catch{return}for(const i of s)if(!(!i.endsWith(".json")||n.has(i)))try{U(l.join(e,i))}catch{}}const G=new Intl.Collator(void 0,{numeric:!0});export function listDirOf(t,e){const n=t.children.get(e);if(!n)return[];n.sorted||(n.dirs.sort(G.compare),n.files.sort(G.compare),n.sorted=!0);const s=[];for(const i of n.dirs){const r=t.submodules[i];s.push(r?{path:i,kind:"dir",head:r}:{path:i,kind:"dir"})}for(const i of n.files)s.push({path:i,kind:"file"});return s}function ft(t,e){return t.startsWith(e)?3:t.includes(e)?2:ut(t,e)?1:-1}function ut(t,e){let n=0;for(let s=0;s<t.length&&n<e.length;s++)t[s]===e[n]&&n++;return n===e.length}function dt(t,e,n){const s=t.lastIndexOf("/")+1,i=t.slice(s).toLowerCase();if(e===3||e===2){const c=i.indexOf(n);return c<0?[]:[[s+c,n.length]]}const r=[];let o=0;for(let c=0;c<i.length&&o<n.length;c++)i[c]===n[o]&&(r.push([s+c,1]),o++);return r}function J(t,e){return e.rank-t.rank||t.len-e.len||t.path.localeCompare(e.path)}const ht=8,wt=1024;function pt(t,e){if(!e)return 0;let n=0,s=t.length;for(;n<s;){const i=n+s>>1;t[i]<e?n=i+1:s=i}return n}export function startMatch(t,e,n,s=""){const i=e.trim().toLowerCase(),r=s?`${s}/`:"",o=[];let c=i&&n>0?"files":"done",f=0,h=0,g=!1;const O=(a,w)=>{const m=a.slice(a.lastIndexOf("/")+1).toLowerCase(),u=ft(m,i);if(u<0)return;h++;const p={path:a,kind:w,rank:u,len:a.length};if(o.length===n&&J(p,o[n-1])>=0)return;const y=o.length===n;let x=y?n-1:o.length;for(y?o[n-1]=p:o.push(p);x>0&&J(p,o[x-1])<0;)o[x]=o[x-1],x--;o[x]=p};return{step(a){const w=Date.now()+a;let m=0;for(;c!=="done";){const u=c==="files"?t.files:t.dirs,p=c==="files"?"file":"dir";for(f===0&&(f=pt(u,r));f<u.length;){const y=u[f];if(r&&!y.startsWith(r))break;if(O(y,p),f++,o.length===n&&o[n-1].rank===3)return g=!0,c="done",!0;if((++m&wt-1)===0&&Date.now()>w)return!1}f=0,c=c==="files"?"dirs":"done"}return!0},result(){return{hits:o.map(a=>({path:a.path,kind:a.kind,ranges:dt(a.path,a.rank,i)})),total:g?o.length:h,capped:g}}}}export async function matchPaths(t,e,n,s=""){const i=startMatch(t,e,n,s);for(;!i.step(ht);)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(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(i=>i.startsWith("harnesses:"));if(!t)return e;try{const i=JSON.parse(t.slice(t.indexOf(":")+1).trim()),r=Array.isArray(i)?i.filter(w):[];return r.length>0?r:e}catch{return e}}const h=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"]}),i=setTimeout(()=>{t.kill("SIGKILL"),e(null)},5e3);t.stdout?.on("data",r=>s+=r.toString()),t.on("error",()=>{clearTimeout(i),e(null)}),t.on("close",()=>{clearTimeout(i);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<h)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 i=>{const r=e?.get(i)?.resume;if(!r?.bin)return{id:i,canStartSession:!1};if(!r.minVersion)return{id:i,canStartSession:!0};const o=await s(r.bin),l=r.minVersion.split(".").map(u=>Number.parseInt(u,10)),p=o===null||S(o,l);return{id:i,canStartSession:p,version:o,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 +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)}}
@@ -1 +1 @@
1
- import{imagesSurfaceFor as N}from"../surfaces.js";const d=/\[Image #\d+\]/gi,b=64,I=64*1024*1024,P=12e4,E=t=>t.replace(d,"").replace(/\s+/g," ").trim(),w={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};function _(t,e,n){const r=t.hookEvents?.listBySession(e,2e3,void 0,["UserPromptSubmit"])??[],o=[];for(const i of r){if(n.get(i.id)?.length)continue;const c=S(i.payload);!c||!c.match(d)||o.push({eventId:i.id,at:i.createdAt,text:E(c)})}return o}function S(t){try{const e=JSON.parse(t).raw;return typeof e?.prompt=="string"&&e.prompt?e.prompt:null}catch{return null}}function O(t,e,n){for(let r=n.length-1;r>=0;r--)try{const o=JSON.parse(n[r].payload).transcriptPath;if(typeof o=="string"&&o)return o}catch{}return t.sessionProbe?.transcriptPathOf(e)??null}export async function importPromptImages(t,e,n){const r=n?N(n):null;if(!r||!t.hookEvents||!t.uploads)return 0;const o=t.uploads.imagesBySession(e),i=_(t,e,o);if(i.length===0)return 0;const c=t.hookEvents.listBySession(e),u=await r.sessionImages({sessionId:e,transcriptPath:O(t,e,c)});if(!u?.length)return 0;let s=0,a=0;for(const l of u){if(s>=b||a>=I)break;const m=x(i,l.text,l.at);if(!m)continue;const p=[];for(const f of l.images){if(s>=b||a>=I)break;const g=w[f.mediaType];if(!g)continue;const h=Buffer.from(f.bytes),y=t.uploads.save({name:`pasted-${s+1}${g}`,mediaType:f.mediaType,bytes:h,dir:t.uploadDir??null});p.includes(y.id)||p.push(y.id),s+=1,a+=h.length}p.length>0&&t.uploads.linkToEvent(m.eventId,p)}return s}function x(t,e,n){const r=E(e),o=r===""?[]:t.filter(a=>a.text===r),i=o.length>0?o:r===""?t.filter(a=>a.text===""):[];if(i.length===0)return null;const c=n?Date.parse(n):NaN;let u=null,s=Number.POSITIVE_INFINITY;for(const a of i){const l=Number.isNaN(c)||!a.at?Number.POSITIVE_INFINITY:Math.abs(Date.parse(a.at)-c);l<s&&(u=a,s=l)}return!u||o.length===0&&!(s<=P)?null:(t.splice(t.indexOf(u),1),u)}export function needsImageImport(t,e){return t.some(n=>{if(n.eventType!=="UserPromptSubmit"||e?.get(n.id)?.length)return!1;const r=S(n.payload);return!!r&&/\[Image #\d+\]/i.test(r)})}const T=new Set;export async function importPromptImagesOnce(t,e,n){if(T.has(e))return!1;T.add(e);try{return await importPromptImages(t,e,n)>0}catch{return!1}}
1
+ import{imagesSurfaceFor as v}from"../surfaces.js";const I=/\[Image #\d+\]/gi,y=64,b=64*1024*1024,T=12e4,N=t=>t.replace(I,"").replace(/\s+/g," ").trim(),x={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};function O(t,e,n){const r=t.hookEvents?.listBySession(e,2e3,void 0,["UserPromptSubmit"])??[],o=[];for(const i of r){if(n.get(i.id)?.length)continue;const c=S(i.payload);!c||!c.match(I)||o.push({eventId:i.id,at:i.createdAt,text:N(c)})}return o}function S(t){try{const e=JSON.parse(t).raw;return typeof e?.prompt=="string"&&e.prompt?e.prompt:null}catch{return null}}function w(t,e,n){for(let r=n.length-1;r>=0;r--)try{const o=JSON.parse(n[r].payload).transcriptPath;if(typeof o=="string"&&o)return o}catch{}return t.sessionProbe?.transcriptPathOf(e)??null}export async function importPromptImages(t,e,n){const r=n?v(n):null;if(!r||!t.hookEvents||!t.uploads)return 0;const o=t.uploads.imagesBySession(e),i=O(t,e,o);if(i.length===0)return 0;const c=t.hookEvents.listBySession(e),p=await r.sessionImages({sessionId:e,transcriptPath:w(t,e,c)});if(!p?.length)return 0;let a=0,s=0;for(const u of p){if(a>=y||s>=b)break;const m=E(i,u.text,u.at);if(!m)continue;const l=[];for(const f of u.images){if(a>=y||s>=b)break;const g=x[f.mediaType];if(!g)continue;const d=Buffer.from(f.bytes),h=t.uploads.save({name:`pasted-${a+1}${g}`,mediaType:f.mediaType,bytes:d,dir:t.uploadDir??null});l.includes(h.id)||l.push(h.id),a+=1,s+=d.length}l.length>0&&t.uploads.linkToEvent(m.eventId,l)}return a}function E(t,e,n){const r=N(e),o=r===""?[]:t.filter(s=>s.text===r),i=o.length>0?o:r===""?t.filter(s=>s.text===""):[];if(i.length===0)return null;const c=n?Date.parse(n):NaN;let p=null,a=Number.POSITIVE_INFINITY;for(const s of i){const u=Number.isNaN(c)||!s.at?Number.POSITIVE_INFINITY:Math.abs(Date.parse(s.at)-c);u<a&&(p=s,a=u)}return!p||o.length===0&&!(a<=T)?null:(t.splice(t.indexOf(p),1),p)}export function needsImageImport(t,e){return t.some(n=>{if(n.eventType!=="UserPromptSubmit"||e?.get(n.id)?.length)return!1;const r=S(n.payload);return!!r&&/\[Image #\d+\]/i.test(r)})}const P=new Set;export async function importPromptImagesOnce(t,e,n){if(P.has(e))return!1;P.add(e);try{return await importPromptImages(t,e,n)>0}catch{return!1}}