@weavecode/weave 0.1.6 → 0.1.7

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 (340) hide show
  1. package/node_modules/@weavecode/cli/dist/cli.js +3 -3
  2. package/node_modules/@weavecode/cli/dist/commands/chpass.js +1 -1
  3. package/node_modules/@weavecode/cli/dist/commands/daemon-auth.js +1 -1
  4. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  5. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -2
  6. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  7. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  8. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  9. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  10. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  11. package/node_modules/@weavecode/cli/dist/commands/uninstall.js +1 -1
  12. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +1 -1
  13. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +1 -0
  14. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +2 -2
  15. package/node_modules/@weavecode/cli/dist/i18n/index.js +1 -1
  16. package/node_modules/@weavecode/cli/dist/i18n/t.js +1 -1
  17. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +3 -3
  18. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  19. package/node_modules/@weavecode/cli/dist/init/git-commit.js +2 -2
  20. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  21. package/node_modules/@weavecode/cli/dist/init/harnesses/codex.js +1 -1
  22. package/node_modules/@weavecode/cli/dist/init/instruction-link.js +1 -1
  23. package/node_modules/@weavecode/cli/dist/init/plugin-templates.js +1 -1
  24. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  25. package/node_modules/@weavecode/cli/dist/init/provision.js +1 -1
  26. package/node_modules/@weavecode/cli/dist/init/uninstall.js +6 -6
  27. package/node_modules/@weavecode/cli/dist/init/wiring.js +1 -1
  28. package/node_modules/@weavecode/cli/dist/parser.js +1 -1
  29. package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
  30. package/node_modules/@weavecode/cli/dist/statusline/mock-input.js +1 -1
  31. package/node_modules/@weavecode/cli/dist/statusline/preview.js +2 -2
  32. package/node_modules/@weavecode/cli/package.json +5 -5
  33. package/node_modules/@weavecode/core/dist/harness-checks.js +1 -1
  34. package/node_modules/@weavecode/core/dist/harness.d.ts +11 -0
  35. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  36. package/node_modules/@weavecode/core/dist/platform.js +1 -1
  37. package/node_modules/@weavecode/core/dist/types.js +1 -1
  38. package/node_modules/@weavecode/core/dist/utils/fs.js +1 -1
  39. package/node_modules/@weavecode/core/dist/utils/logger.js +1 -1
  40. package/node_modules/@weavecode/core/package.json +1 -1
  41. package/node_modules/@weavecode/harness/dist/claude/assets.js +4 -4
  42. package/node_modules/@weavecode/harness/dist/claude/capture.js +9 -9
  43. package/node_modules/@weavecode/harness/dist/claude/commands.js +2 -2
  44. package/node_modules/@weavecode/harness/dist/claude/config.js +2 -2
  45. package/node_modules/@weavecode/harness/dist/claude/detect.js +1 -1
  46. package/node_modules/@weavecode/harness/dist/claude/edits.js +1 -1
  47. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  48. package/node_modules/@weavecode/harness/dist/claude/images.js +2 -2
  49. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  50. package/node_modules/@weavecode/harness/dist/claude/liveness.js +1 -1
  51. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -1
  52. package/node_modules/@weavecode/harness/dist/claude/messaging.js +2 -2
  53. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -1
  54. package/node_modules/@weavecode/harness/dist/claude/narration.js +1 -1
  55. package/node_modules/@weavecode/harness/dist/claude/peers.js +1 -1
  56. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -1
  57. package/node_modules/@weavecode/harness/dist/claude/plugins.js +4 -4
  58. package/node_modules/@weavecode/harness/dist/claude/prompt-inbox.js +1 -1
  59. package/node_modules/@weavecode/harness/dist/claude/prompt.js +3 -3
  60. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -2
  61. package/node_modules/@weavecode/harness/dist/claude/resume.js +1 -1
  62. package/node_modules/@weavecode/harness/dist/claude/rewind.js +1 -1
  63. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -1
  64. package/node_modules/@weavecode/harness/dist/claude/side-question.js +2 -2
  65. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +14 -14
  66. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -1
  67. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -2
  68. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.js +2 -2
  69. package/node_modules/@weavecode/harness/dist/claude/transcript.js +7 -7
  70. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  71. package/node_modules/@weavecode/harness/dist/codex/capture.js +2 -2
  72. package/node_modules/@weavecode/harness/dist/codex/commands.js +4 -4
  73. package/node_modules/@weavecode/harness/dist/codex/config.js +2 -2
  74. package/node_modules/@weavecode/harness/dist/codex/detect.js +1 -1
  75. package/node_modules/@weavecode/harness/dist/codex/event-source.js +2 -2
  76. package/node_modules/@weavecode/harness/dist/codex/images.js +1 -1
  77. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  78. package/node_modules/@weavecode/harness/dist/codex/liveness.js +1 -1
  79. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -1
  80. package/node_modules/@weavecode/harness/dist/codex/messaging.js +2 -2
  81. package/node_modules/@weavecode/harness/dist/codex/narration.js +1 -1
  82. package/node_modules/@weavecode/harness/dist/codex/plugin-state.js +1 -1
  83. package/node_modules/@weavecode/harness/dist/codex/plugins.js +3 -3
  84. package/node_modules/@weavecode/harness/dist/codex/provision.js +1 -1
  85. package/node_modules/@weavecode/harness/dist/codex/questions.js +2 -2
  86. package/node_modules/@weavecode/harness/dist/codex/rollout.js +5 -5
  87. package/node_modules/@weavecode/harness/dist/codex/side-question.js +4 -4
  88. package/node_modules/@weavecode/harness/dist/codex/titles.js +4 -4
  89. package/node_modules/@weavecode/harness/dist/codex/toml.js +13 -13
  90. package/node_modules/@weavecode/harness/dist/codex/transcript.js +2 -2
  91. package/node_modules/@weavecode/harness/dist/driver.d.ts +7 -0
  92. package/node_modules/@weavecode/harness/dist/driver.js +1 -1
  93. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -2
  94. package/node_modules/@weavecode/harness/dist/init/pipeline.js +1 -1
  95. package/node_modules/@weavecode/harness/dist/registry-wiring.js +1 -1
  96. package/node_modules/@weavecode/harness/dist/shared/install-link.js +1 -1
  97. package/node_modules/@weavecode/harness/dist/shared/json-cap.js +1 -1
  98. package/node_modules/@weavecode/harness/dist/zcode/assets.js +1 -1
  99. package/node_modules/@weavecode/harness/dist/zcode/capture.js +3 -3
  100. package/node_modules/@weavecode/harness/dist/zcode/mcp.js +2 -2
  101. package/node_modules/@weavecode/harness/package.json +2 -2
  102. package/node_modules/@weavecode/server/dist/config/dotted.js +1 -1
  103. package/node_modules/@weavecode/server/dist/config/profiles.js +2 -2
  104. package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
  105. package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
  106. package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
  107. package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -3
  108. package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
  109. package/node_modules/@weavecode/server/dist/daemon/auto-start.js +6 -6
  110. package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
  111. package/node_modules/@weavecode/server/dist/daemon/config-routes.js +1 -1
  112. package/node_modules/@weavecode/server/dist/daemon/cron.js +1 -1
  113. package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
  114. package/node_modules/@weavecode/server/dist/daemon/dashboard-pusher.js +1 -1
  115. package/node_modules/@weavecode/server/dist/daemon/data-bus.js +1 -1
  116. package/node_modules/@weavecode/server/dist/daemon/decision-config.js +2 -2
  117. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  118. package/node_modules/@weavecode/server/dist/daemon/entry.js +2 -2
  119. package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
  120. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
  121. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  122. package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
  123. package/node_modules/@weavecode/server/dist/daemon/liveness.js +1 -1
  124. package/node_modules/@weavecode/server/dist/daemon/mcp-orchestration.js +1 -1
  125. package/node_modules/@weavecode/server/dist/daemon/narration-watcher.js +2 -2
  126. package/node_modules/@weavecode/server/dist/daemon/opener/backend-ghostty.js +1 -1
  127. package/node_modules/@weavecode/server/dist/daemon/opener/backend-iterm.js +1 -1
  128. package/node_modules/@weavecode/server/dist/daemon/opener/backend-konsole.js +2 -2
  129. package/node_modules/@weavecode/server/dist/daemon/opener/backend-terminal-app.js +1 -1
  130. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wezterm.js +1 -1
  131. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wt.js +1 -1
  132. package/node_modules/@weavecode/server/dist/daemon/opener/backend.js +1 -1
  133. package/node_modules/@weavecode/server/dist/daemon/opener/launch.js +1 -1
  134. package/node_modules/@weavecode/server/dist/daemon/opener/pty-terminals.js +4 -4
  135. package/node_modules/@weavecode/server/dist/daemon/opener/shared.js +1 -1
  136. package/node_modules/@weavecode/server/dist/daemon/opener/wezterm-mux.js +1 -1
  137. package/node_modules/@weavecode/server/dist/daemon/opener/wt.js +3 -3
  138. package/node_modules/@weavecode/server/dist/daemon/opener.js +1 -1
  139. package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
  140. package/node_modules/@weavecode/server/dist/daemon/project-files.js +2 -2
  141. package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
  142. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
  143. package/node_modules/@weavecode/server/dist/daemon/prompt-images.js +1 -1
  144. package/node_modules/@weavecode/server/dist/daemon/routes/hooks-admin.js +1 -1
  145. package/node_modules/@weavecode/server/dist/daemon/routes/market.js +1 -1
  146. package/node_modules/@weavecode/server/dist/daemon/routes/orchestration.js +1 -1
  147. package/node_modules/@weavecode/server/dist/daemon/routes/path-refs.js +1 -1
  148. package/node_modules/@weavecode/server/dist/daemon/routes/project-files.js +1 -1
  149. package/node_modules/@weavecode/server/dist/daemon/routes/projects.js +1 -1
  150. package/node_modules/@weavecode/server/dist/daemon/routes/search.js +1 -1
  151. package/node_modules/@weavecode/server/dist/daemon/routes/session-control.js +1 -1
  152. package/node_modules/@weavecode/server/dist/daemon/routes/session-insights.js +1 -1
  153. package/node_modules/@weavecode/server/dist/daemon/routes/settings-statusline.js +1 -1
  154. package/node_modules/@weavecode/server/dist/daemon/routes/uploads.js +1 -1
  155. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.js +1 -1
  156. package/node_modules/@weavecode/server/dist/daemon/routes/watches.js +1 -1
  157. package/node_modules/@weavecode/server/dist/daemon/server.js +8 -8
  158. package/node_modules/@weavecode/server/dist/daemon/session-open.d.ts +17 -0
  159. package/node_modules/@weavecode/server/dist/daemon/session-open.js +1 -1
  160. package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
  161. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  162. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.js +1 -1
  163. package/node_modules/@weavecode/server/dist/daemon/sse-hub.js +1 -1
  164. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  165. package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
  166. package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
  167. package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.js +1 -1
  168. package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
  169. package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
  170. package/node_modules/@weavecode/server/dist/daemon/upload-sessions.js +1 -1
  171. package/node_modules/@weavecode/server/dist/db/db.js +2 -2
  172. package/node_modules/@weavecode/server/dist/db/layout.js +1 -1
  173. package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
  174. package/node_modules/@weavecode/server/dist/hooks/bus.js +1 -1
  175. package/node_modules/@weavecode/server/dist/hooks/dashboard-rate.js +1 -1
  176. package/node_modules/@weavecode/server/dist/hooks/decision-judge.js +1 -1
  177. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.js +1 -1
  178. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.js +1 -1
  179. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.js +1 -1
  180. package/node_modules/@weavecode/server/dist/hooks/delivery/queue.js +1 -1
  181. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.js +1 -1
  182. package/node_modules/@weavecode/server/dist/hooks/delivery/send.js +2 -2
  183. package/node_modules/@weavecode/server/dist/hooks/delivery/views.d.ts +3 -1
  184. package/node_modules/@weavecode/server/dist/hooks/delivery/views.js +1 -1
  185. package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
  186. package/node_modules/@weavecode/server/dist/hooks/edge-extract.js +1 -1
  187. package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
  188. package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
  189. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -2
  190. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
  191. package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
  192. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +5 -5
  193. package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
  194. package/node_modules/@weavecode/server/dist/hooks/orchestration-engine.js +7 -7
  195. package/node_modules/@weavecode/server/dist/hooks/orchestration-graph.js +1 -1
  196. package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
  197. package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
  198. package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
  199. package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
  200. package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
  201. package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
  202. package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
  203. package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
  204. package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
  205. package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
  206. package/node_modules/@weavecode/server/dist/hooks/side-questions.js +1 -1
  207. package/node_modules/@weavecode/server/dist/hooks/synthetic-sessions.js +1 -1
  208. package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
  209. package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
  210. package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
  211. package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
  212. package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
  213. package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
  214. package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
  215. package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
  216. package/node_modules/@weavecode/server/dist/install/global-config.js +1 -1
  217. package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
  218. package/node_modules/@weavecode/server/dist/install/init-files.js +2 -2
  219. package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
  220. package/node_modules/@weavecode/server/dist/install/installer.js +1 -1
  221. package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
  222. package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
  223. package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
  224. package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
  225. package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
  226. package/node_modules/@weavecode/server/dist/install/project-config.js +1 -1
  227. package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
  228. package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
  229. package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
  230. package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
  231. package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
  232. package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
  233. package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
  234. package/node_modules/@weavecode/server/dist/market/import.js +2 -2
  235. package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
  236. package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
  237. package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
  238. package/node_modules/@weavecode/server/dist/registry.js +2 -2
  239. package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +5 -5
  240. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +4 -4
  241. package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
  242. package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
  243. package/node_modules/@weavecode/server/dist/repositories/orchestrations.js +7 -7
  244. package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
  245. package/node_modules/@weavecode/server/dist/repositories/projects.js +2 -2
  246. package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
  247. package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
  248. package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
  249. package/node_modules/@weavecode/server/dist/repositories/uploads.js +11 -11
  250. package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
  251. package/node_modules/@weavecode/server/dist/statusline/generator.js +1 -1
  252. package/node_modules/@weavecode/server/dist/statusline/manager.js +3 -3
  253. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  254. package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
  255. package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
  256. package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
  257. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
  258. package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
  259. package/node_modules/@weavecode/server/package.json +4 -4
  260. package/node_modules/@weavecode/server/web/dist/assets/{abnfDiagram-WEYOIA3C-CbIFQh0R.js → abnfDiagram-WEYOIA3C-DDeQkTf5.js} +1 -1
  261. package/node_modules/@weavecode/server/web/dist/assets/{arc-DH8-rYAa.js → arc-CRZTRyjb.js} +1 -1
  262. package/node_modules/@weavecode/server/web/dist/assets/{architectureDiagram-ZHVYKT53-qnv6S0sc.js → architectureDiagram-ZHVYKT53-Dj54DE3O.js} +1 -1
  263. package/node_modules/@weavecode/server/web/dist/assets/{blockDiagram-RJAE7QA3-pT5eO-cB.js → blockDiagram-RJAE7QA3-BIH8mSIZ.js} +1 -1
  264. package/node_modules/@weavecode/server/web/dist/assets/{c4Diagram-XDPPPE54-DHDBDMb1.js → c4Diagram-XDPPPE54-5YoKWFOD.js} +1 -1
  265. package/node_modules/@weavecode/server/web/dist/assets/channel-5VM93AJ8.js +1 -0
  266. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2E7WHVMD-CT951PH5.js → chunk-2E7WHVMD-B653kMXt.js} +1 -1
  267. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2Q5K7J3B-E5AD7_ZY.js → chunk-2Q5K7J3B-f_A4_eDz.js} +1 -1
  268. package/node_modules/@weavecode/server/web/dist/assets/{chunk-4EMNKR2T-DWz9qkcy.js → chunk-4EMNKR2T-v5j5qNGj.js} +1 -1
  269. package/node_modules/@weavecode/server/web/dist/assets/{chunk-55XCU76K-D-SgWD8w.js → chunk-55XCU76K-CgEqeP7j.js} +1 -1
  270. package/node_modules/@weavecode/server/web/dist/assets/{chunk-5VM5RSS4-ci6YzbO5.js → chunk-5VM5RSS4-BeROhLXN.js} +1 -1
  271. package/node_modules/@weavecode/server/web/dist/assets/{chunk-JWPE2WC7-CY4mr2f4.js → chunk-JWPE2WC7-D6dXb_jr.js} +1 -1
  272. package/node_modules/@weavecode/server/web/dist/assets/{chunk-VQ5W62QI-CON8zyg8.js → chunk-VQ5W62QI-CnHdSEMi.js} +1 -1
  273. package/node_modules/@weavecode/server/web/dist/assets/{chunk-XXDRQBXY-DXXXZ4pW.js → chunk-XXDRQBXY-BkG_e6PE.js} +1 -1
  274. package/node_modules/@weavecode/server/web/dist/assets/{chunk-ZCHMQSOR-CukvPvkM.js → chunk-ZCHMQSOR-DxR-fxzs.js} +2 -2
  275. package/node_modules/@weavecode/server/web/dist/assets/{classDiagram-v2-4MYWR3UA-GiWZ9xtF.js → classDiagram-v2-4MYWR3UA-DQe1b_k8.js} +1 -1
  276. package/node_modules/@weavecode/server/web/dist/assets/{cose-bilkent-JH36ORCC-D7aJ-akq.js → cose-bilkent-JH36ORCC-DThrA8S5.js} +1 -1
  277. package/node_modules/@weavecode/server/web/dist/assets/{cynefin-EF2NZ3EQ-9B__MaRM.js → cynefin-EF2NZ3EQ-OZotFKUu.js} +1 -1
  278. package/node_modules/@weavecode/server/web/dist/assets/{cynefinDiagram-WF24UDRP-B2ujZh2k.js → cynefinDiagram-WF24UDRP-DJjq2hfT.js} +1 -1
  279. package/node_modules/@weavecode/server/web/dist/assets/{dagre-NK4GIZVX-nHaB6IWf.js → dagre-NK4GIZVX-C2vH93HT.js} +1 -1
  280. package/node_modules/@weavecode/server/web/dist/assets/{diagram-CBK3MWTC-xKfjDvgr.js → diagram-CBK3MWTC-DrF_ScM-.js} +1 -1
  281. package/node_modules/@weavecode/server/web/dist/assets/{diagram-I5XIIV2D-BHT2-5mY.js → diagram-I5XIIV2D-D1qoUJ4t.js} +1 -1
  282. package/node_modules/@weavecode/server/web/dist/assets/{diagram-ODIL2UCW-CckywF4W.js → diagram-ODIL2UCW-D9A6W8oB.js} +1 -1
  283. package/node_modules/@weavecode/server/web/dist/assets/{diagram-PFBEJUXE-Dpjlc7Wh.js → diagram-PFBEJUXE-PeI-eyu2.js} +1 -1
  284. package/node_modules/@weavecode/server/web/dist/assets/{diagram-RJA3I4VV-M6WznOaW.js → diagram-RJA3I4VV-DITY0Rd8.js} +1 -1
  285. package/node_modules/@weavecode/server/web/dist/assets/{diagram-TYUNFSNR-DgRJ3zL1.js → diagram-TYUNFSNR-D5KieEw5.js} +1 -1
  286. package/node_modules/@weavecode/server/web/dist/assets/{ebnfDiagram-V4P3TTPT-BzzVN__a.js → ebnfDiagram-V4P3TTPT-DDylK-gz.js} +1 -1
  287. package/node_modules/@weavecode/server/web/dist/assets/{elk-QONTBCTQ-Ch6Gs9G9.js → elk-QONTBCTQ-D3xrVg0U.js} +1 -1
  288. package/node_modules/@weavecode/server/web/dist/assets/{erDiagram-KYQIGQAA-COxT-Pxb.js → erDiagram-KYQIGQAA-y_V1cor7.js} +1 -1
  289. package/node_modules/@weavecode/server/web/dist/assets/{flowDiagram-IUGLLWBU-CJVWnTBa.js → flowDiagram-IUGLLWBU-BJ8Z0MkF.js} +1 -1
  290. package/node_modules/@weavecode/server/web/dist/assets/{ganttDiagram-R7GPNTJY-BkRpWPUl.js → ganttDiagram-R7GPNTJY-C0q-CS1T.js} +1 -1
  291. package/node_modules/@weavecode/server/web/dist/assets/{gitGraphDiagram-PDYL7XHY-Ba8BJcvZ.js → gitGraphDiagram-PDYL7XHY-BYTComiB.js} +1 -1
  292. package/node_modules/@weavecode/server/web/dist/assets/index-BKxAxaVG.js +1091 -0
  293. package/node_modules/@weavecode/server/web/dist/assets/index-C0Sd4MH7.css +11 -0
  294. package/node_modules/@weavecode/server/web/dist/assets/{infoDiagram-MVDRKAX5-HTQ5FUNK.js → infoDiagram-MVDRKAX5-DtixgjLP.js} +1 -1
  295. package/node_modules/@weavecode/server/web/dist/assets/{ishikawaDiagram-HPEHV2GE-BNjEDIZy.js → ishikawaDiagram-HPEHV2GE-ChEnND76.js} +1 -1
  296. package/node_modules/@weavecode/server/web/dist/assets/{journeyDiagram-BOSHW7O7-Cao6h91a.js → journeyDiagram-BOSHW7O7-DHcNtpYF.js} +1 -1
  297. package/node_modules/@weavecode/server/web/dist/assets/{kanban-definition-FNSA4HC5-CXIx2CHQ.js → kanban-definition-FNSA4HC5-Dft7qpW5.js} +1 -1
  298. package/node_modules/@weavecode/server/web/dist/assets/{linear-65WmlvQb.js → linear-DEo11t-X.js} +1 -1
  299. package/node_modules/@weavecode/server/web/dist/assets/{mermaid.core-D39fi_iR.js → mermaid.core-D_Dp_Kl2.js} +4 -4
  300. package/node_modules/@weavecode/server/web/dist/assets/{mindmap-definition-6OY57UG3-DHqpz_AK.js → mindmap-definition-6OY57UG3-CM6OAd_-.js} +1 -1
  301. package/node_modules/@weavecode/server/web/dist/assets/{pegDiagram-ECIUJNBX-Cpy1nsER.js → pegDiagram-ECIUJNBX-_QkY0h8Q.js} +1 -1
  302. package/node_modules/@weavecode/server/web/dist/assets/{pieDiagram-GNMPY74T-B1IyNqzr.js → pieDiagram-GNMPY74T-ZGr5vtDj.js} +1 -1
  303. package/node_modules/@weavecode/server/web/dist/assets/{quadrantDiagram-D57K4MC3-zSM6o7mB.js → quadrantDiagram-D57K4MC3-D8pQ_PU2.js} +1 -1
  304. package/node_modules/@weavecode/server/web/dist/assets/{railroadDiagram-Y72NRBL7-oM4XJIwA.js → railroadDiagram-Y72NRBL7-DUIo-WmA.js} +1 -1
  305. package/node_modules/@weavecode/server/web/dist/assets/{requirementDiagram-EQYSW5RA-CbCLBjHf.js → requirementDiagram-EQYSW5RA-C90DU5Ny.js} +1 -1
  306. package/node_modules/@weavecode/server/web/dist/assets/{sankeyDiagram-SY24JHO5-BucVk6EP.js → sankeyDiagram-SY24JHO5-B_poYGgJ.js} +1 -1
  307. package/node_modules/@weavecode/server/web/dist/assets/{sequenceDiagram-BLEHNHQU-Dg8CYEnT.js → sequenceDiagram-BLEHNHQU-DDW7b2Dn.js} +1 -1
  308. package/node_modules/@weavecode/server/web/dist/assets/{sizeCapture-INFHLROL-C51zb7Oc.js → sizeCapture-INFHLROL-CmKoqX6K.js} +1 -1
  309. package/node_modules/@weavecode/server/web/dist/assets/{stateDiagram-v2-A6IESKWZ-BvK2l3is.js → stateDiagram-v2-A6IESKWZ-CkVMAyxG.js} +1 -1
  310. package/node_modules/@weavecode/server/web/dist/assets/{swimlanes-B3ENRKFQ-Ds7QOfXW.js → swimlanes-B3ENRKFQ-Dm_Omzky.js} +1 -1
  311. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-Bjj8ZA4d.js +8 -0
  312. package/node_modules/@weavecode/server/web/dist/assets/{timeline-definition-JXYKGLGB-CadU4Qq4.js → timeline-definition-JXYKGLGB-DnhkRGLb.js} +1 -1
  313. package/node_modules/@weavecode/server/web/dist/assets/{usecaseDiagram-WPOLBNNX-BYuZwTDZ.js → usecaseDiagram-WPOLBNNX-_TdIjC6Z.js} +1 -1
  314. package/node_modules/@weavecode/server/web/dist/assets/{vennDiagram-Q3Y3IDCW-C7zgxe07.js → vennDiagram-Q3Y3IDCW-FzgsymXB.js} +1 -1
  315. package/node_modules/@weavecode/server/web/dist/assets/{wardleyDiagram-IVAIDKWA-DA4Otf4s.js → wardleyDiagram-IVAIDKWA-BwqimStC.js} +1 -1
  316. package/node_modules/@weavecode/server/web/dist/assets/{xychartDiagram-4URNHDU4-Bs5YGwMU.js → xychartDiagram-4URNHDU4-CFjjVPIV.js} +1 -1
  317. package/node_modules/@weavecode/server/web/dist/icons/apple-touch-icon.png +0 -0
  318. package/node_modules/@weavecode/server/web/dist/icons/icon-192.png +0 -0
  319. package/node_modules/@weavecode/server/web/dist/icons/icon-512.png +0 -0
  320. package/node_modules/@weavecode/server/web/dist/icons/icon-maskable-512.png +0 -0
  321. package/node_modules/@weavecode/server/web/dist/index.html +11 -2
  322. package/node_modules/@weavecode/server/web/dist/manifest.webmanifest +16 -0
  323. package/node_modules/@weavecode/templates/package.json +2 -2
  324. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/README.md +3 -8
  325. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/package.json +1 -1
  326. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.d.ts +4 -2
  327. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.es6.js +10 -1
  328. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.es6.mjs +10 -1
  329. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.js +10 -1
  330. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/README.md +3 -8
  331. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/package.json +1 -1
  332. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.d.ts +4 -2
  333. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.es6.js +10 -1
  334. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.es6.mjs +10 -1
  335. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.js +10 -1
  336. package/package.json +6 -6
  337. package/node_modules/@weavecode/server/web/dist/assets/channel-BHPeeuzN.js +0 -1
  338. package/node_modules/@weavecode/server/web/dist/assets/index-CtifxEiF.css +0 -11
  339. package/node_modules/@weavecode/server/web/dist/assets/index-FwH9INgS.js +0 -1090
  340. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-ByBF02UJ.js +0 -8
@@ -1 +1 @@
1
- import{isImageMediaType as k}from"../../repositories/uploads.js";const p=a=>new Promise(e=>setTimeout(e,a));export class AckGate{store;times;events;isCommandInput;constructor(e,t,s,o=()=>!1){this.store=e,this.times=t,this.events=s,this.isCommandInput=o}open(e){const t=this.store.awaitingAck.get(e);if(t===void 0)return!0;const s=this.store.memory.get(t);return s&&s.acked!==!0&&s.status!=="failed"&&s.status!=="timeout"?!1:(this.store.awaitingAck.delete(e),!0)}awaiting(e){return!this.open(e)}headOf(e){return this.store.awaitingAck.get(e)}await(e,t){this.store.awaitingAck.set(e,t)}release(e,t){if(t===void 0){this.store.awaitingAck.delete(e);return}this.store.awaitingAck.get(e)===t&&this.store.awaitingAck.delete(e)}isStalled(e){return this.store.stalled.has(e)}stallCause(e){return this.store.stalled.get(e)}clearStall(e,t){const s=this.store.stalled.get(e);s&&(t===void 0||s.messageId===t)&&this.store.stalled.delete(e)}armAckWatch(e){setTimeout(()=>{const t=this.store.memory.get(e.id);!t||t.acked||t.status!=="delivered"||this.stall(e.sessionId,t,"unacked")},this.times.ackStallMs).unref?.()}armCommandAck(e,t){setTimeout(()=>{const s=this.store.memory.get(e);!s||s.acked||s.status!=="delivered"||(this.acknowledge_(s.sessionId,e),t(s.sessionId))},this.times.commandAckGraceMs).unref?.()}noteActivity(e){let t=!1;for(const s of this.store.memory.values())s.sessionId!==e||s.acked||s.status!=="delivered"||s.mode!=="prompt"||!this.isCommandInput(e,s.text)||(this.acknowledge_(e,s.id),t=!0);return t}acknowledge_(e,t){const s=this.store.memory.get(t);!s||s.acked||(this.store.memory.set(t,{...s,acked:!0}),this.release(e,t),this.events.emit({kind:"message.acknowledged",messageId:t,sessionId:e,at:new Date().toISOString()}))}stall(e,t,s){this.store.stalled.set(e,{messageId:t.id,reason:s});const o=this.store.memory.get(t.id),n=o&&o.status==="delivered"&&o.acked!==!0?new Date(Date.now()+this.times.ackStallReleaseMs).toISOString():null;o&&this.store.memory.set(t.id,{...o,stalled:!0,releaseAt:n}),this.events.emit({kind:"message.stalled",messageId:t.id,sessionId:e,reason:s,at:new Date().toISOString()}),setTimeout(()=>this.autoRelease(e,t.id),this.times.ackStallReleaseMs).unref?.()}autoRelease(e,t){if(this.store.stalled.get(e)?.messageId!==t)return;const s=this.store.memory.get(t);if(s&&s.status==="delivered"&&s.acked!==!0){this.dropAndRelease(e,t);return}this.store.stalled.delete(e),this.release(e,t),this.onAutoRelease?.(e)}dropAndRelease(e,t){this.store.memory.delete(t),this.store.stalled.delete(e),this.release(e,t),this.events.emit({kind:"message.dismissed",messageId:t,sessionId:e,at:new Date().toISOString()}),this.onAutoRelease?.(e)}onAutoRelease;hitLast=!1;acknowledge(e,t,s,o){const n=normalizePromptText(t),l=n.replace(/\[Image #\d+\]/gi,"").trim(),m=[];let d=!1;this.hitLast=!1;for(const i of[...this.store.memory.values()].reverse()){if(i.sessionId!==e||i.acked||i.mode!=="prompt")continue;const r=normalizePromptText(i.text),c=dropInlineImagePaths(r,i.attachments),h=!!r&&(r.length>=o.ackMinText?n.includes(r)||stripSpace(n).includes(stripSpace(r)):n.endsWith(r)),g=(i.attachments?.length??0)>0&&(c?stripSpace(l).includes(stripSpace(c))||stripSpace(n).includes(stripSpace(r)):l.length===0);!h&&!g||(d=!0,this.store.memory.set(i.id,{...i,acked:!0,stalled:!1,...s===void 0?{}:{ackedEventId:s}}),this.store.stalled.get(e)?.messageId===i.id&&this.store.stalled.delete(e),this.release(e,i.id),m.push(...i.attachments?.map(u=>u.id)??[]),this.events.emit({kind:"message.acknowledged",messageId:i.id,sessionId:e,...s===void 0?{}:{eventId:s},at:new Date().toISOString()}))}return this.hitLast=d,d?m:[]}sessionExited(e){this.release(e)}static sleep=p}export function normalizePromptText(a){return a.replace(/<\/?cross-session-message[^>]*>/g,"").replace(/\s+/g," ").trim()}export function stripSpace(a){return a.replace(/\s+/g,"")}export function dropInlineImagePaths(a,e){const t=(e??[]).filter(s=>s.path&&k(s.mediaType)).map(s=>s.path.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return t.length===0?a:a.replace(new RegExp(t.join("|"),"g"),"")}
1
+ import{isImageMediaType as f}from"../../repositories/uploads.js";const p=a=>new Promise(e=>setTimeout(e,a));export class AckGate{store;times;events;isCommandInput;constructor(e,t,s,i=()=>!1){this.store=e,this.times=t,this.events=s,this.isCommandInput=i}open(e){const t=this.store.awaitingAck.get(e);if(t===void 0)return!0;const s=this.store.memory.get(t);return s&&s.acked!==!0&&s.status!=="failed"&&s.status!=="timeout"?!1:(this.store.awaitingAck.delete(e),!0)}awaiting(e){return!this.open(e)}headOf(e){return this.store.awaitingAck.get(e)}await(e,t){this.store.awaitingAck.set(e,t)}release(e,t){if(t===void 0){this.store.awaitingAck.delete(e);return}this.store.awaitingAck.get(e)===t&&this.store.awaitingAck.delete(e)}isStalled(e){return this.store.stalled.has(e)}stallCause(e){return this.store.stalled.get(e)}clearStall(e,t){const s=this.store.stalled.get(e);s&&(t===void 0||s.messageId===t)&&this.store.stalled.delete(e)}armAckWatch(e){setTimeout(()=>{const s=this.store.memory.get(e.id);!s||s.acked||s.status!=="delivered"||this.stall(e.sessionId,s,"unacked")},this.times.ackStallMs).unref?.()}armCommandAck(e,t){setTimeout(()=>{const i=this.store.memory.get(e);!i||i.acked||i.status!=="delivered"||(this.acknowledge_(i.sessionId,e),t(i.sessionId))},this.times.commandAckGraceMs).unref?.()}noteActivity(e){let t=!1;for(const s of this.store.memory.values())s.sessionId!==e||s.acked||s.status!=="delivered"||s.mode!=="prompt"||!this.isCommandInput(e,s.text)||(this.acknowledge_(e,s.id),t=!0);return t}acknowledge_(e,t){const s=this.store.memory.get(t);!s||s.acked||(this.store.memory.set(t,{...s,acked:!0}),this.release(e,t),this.events.emit({kind:"message.acknowledged",messageId:t,sessionId:e,at:new Date().toISOString()}))}stall(e,t,s){this.store.stalled.set(e,{messageId:t.id,reason:s});const i=this.store.memory.get(t.id),n=i&&i.status==="delivered"&&i.acked!==!0?new Date(Date.now()+this.times.ackStallReleaseMs).toISOString():null;i&&this.store.memory.set(t.id,{...i,stalled:!0,releaseAt:n}),this.events.emit({kind:"message.stalled",messageId:t.id,sessionId:e,reason:s,at:new Date().toISOString()}),setTimeout(()=>this.autoRelease(e,t.id),this.times.ackStallReleaseMs).unref?.()}autoRelease(e,t){if(this.store.stalled.get(e)?.messageId!==t)return;const s=this.store.memory.get(t);if(s&&s.status==="delivered"&&s.acked!==!0){this.dropAndRelease(e,t);return}this.store.stalled.delete(e),this.release(e,t),this.onAutoRelease?.(e)}dropAndRelease(e,t){this.store.memory.delete(t),this.store.stalled.delete(e),this.release(e,t),this.events.emit({kind:"message.dismissed",messageId:t,sessionId:e,at:new Date().toISOString()}),this.onAutoRelease?.(e)}onAutoRelease;hitLast=!1;acknowledge(e,t,s,i){const n=normalizePromptText(t),l=n.replace(/\[Image #\d+\]/gi,"").trim(),d=[];let c=!1;this.hitLast=!1;for(const r of[...this.store.memory.values()].reverse()){if(r.sessionId!==e||r.acked||r.mode!=="prompt")continue;const o=normalizePromptText(r.text),u=dropInlineImagePaths(o,r.attachments),h=!!o&&(o.length>=i.ackMinText?n.includes(o)||stripSpace(n).includes(stripSpace(o)):n.endsWith(o)),m=(r.attachments?.length??0)>0&&(u?stripSpace(l).includes(stripSpace(u))||stripSpace(n).includes(stripSpace(o)):l.length===0);!h&&!m||(c=!0,this.store.memory.set(r.id,{...r,acked:!0,stalled:!1,...s===void 0?{}:{ackedEventId:s}}),this.store.stalled.get(e)?.messageId===r.id&&this.store.stalled.delete(e),this.release(e,r.id),d.push(...r.attachments?.map(g=>g.id)??[]),this.events.emit({kind:"message.acknowledged",messageId:r.id,sessionId:e,...s===void 0?{}:{eventId:s},at:new Date().toISOString()}))}return this.hitLast=c,c?d:[]}sessionExited(e){this.release(e)}static sleep=p}export function normalizePromptText(a){return a.replace(/<\/?cross-session-message[^>]*>/g,"").replace(/\s+/g," ").trim()}export function stripSpace(a){return a.replace(/\s+/g,"")}export function dropInlineImagePaths(a,e){const t=(e??[]).filter(s=>s.path&&f(s.mediaType)).map(s=>s.path.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return t.length===0?a:a.replace(new RegExp(t.join("|"),"g"),"")}
@@ -1 +1 @@
1
- import{spawn as p}from"node:child_process";import{defaultKill as f}from"../headless-runner.js";import{tmpdir as l}from"node:os";import{isImageMediaType as w}from"../../repositories/uploads.js";export function wireTextOf(e,t){const o=e.attachments;return!o||o.length===0?e.text:t(e.sessionId)?.attach?.composePrompt(e.text,o)??e.text}export function hasImages(e){return(e.attachments??[]).some(t=>w(t.mediaType))}export function spawnOnce(e,t,o,i){const u=i??((a,n,r)=>p(a,[...n],r));return new Promise((a,n)=>{const r=u(e,t,{cwd:l(),windowsHide:!0,stdio:["ignore","pipe","pipe"]}),d=[];r.stdout?.on("data",s=>d.push(s)),r.stderr?.on("data",s=>d.push(s));const m=setTimeout(()=>{if(r.pid!==void 0)try{f(r.pid)}catch{}n(new Error(`queue timeout after ${o}ms`))},o);r.on("error",s=>{clearTimeout(m),n(s)}),r.on("exit",s=>{if(clearTimeout(m),s===0){a();return}const c=Buffer.concat(d).toString("utf8").slice(-500);n(new Error(`queue exit ${s}${c?`: ${c}`:""}`))})})}export function settleDelivered(e,t,o){const i={...t,status:"delivered",via:o,settledAt:new Date().toISOString()};return e.setMemory(i),e.awaitAck(t.sessionId,t.id),e.commandModeOf(t.text,t.sessionId)?e.armCommandAck(t.id):e.armAckWatch(i),e.emit({kind:"message.delivered",messageId:t.id,sessionId:t.sessionId,at:new Date().toISOString()}),i}
1
+ import{spawn as f}from"node:child_process";import{defaultKill as p}from"../headless-runner.js";import{tmpdir as l}from"node:os";import{isImageMediaType as w}from"../../repositories/uploads.js";export function wireTextOf(t,e){const i=t.attachments;return!i||i.length===0?t.text:e(t.sessionId)?.attach?.composePrompt(t.text,i)??t.text}export function hasImages(t){return(t.attachments??[]).some(e=>w(e.mediaType))}export function spawnOnce(t,e,i,r){const u=r??((a,n,o)=>f(a,[...n],o));return new Promise((a,n)=>{const o=u(t,e,{cwd:l(),windowsHide:!0,stdio:["ignore","pipe","pipe"]}),d=[];o.stdout?.on("data",s=>d.push(s)),o.stderr?.on("data",s=>d.push(s));const m=setTimeout(()=>{if(o.pid!==void 0)try{p(o.pid)}catch{}n(new Error(`queue timeout after ${i}ms`))},i);o.on("error",s=>{clearTimeout(m),n(s)}),o.on("exit",s=>{if(clearTimeout(m),s===0){a();return}const c=Buffer.concat(d).toString("utf8").slice(-500);n(new Error(`queue exit ${s}${c?`: ${c}`:""}`))})})}export function settleDelivered(t,e,i){const r={...e,status:"delivered",via:i,settledAt:new Date().toISOString()};return t.setMemory(r),t.awaitAck(e.sessionId,e.id),t.commandModeOf(e.text,e.sessionId)?t.armCommandAck(e.id):t.armAckWatch(r),t.emit({kind:"message.delivered",messageId:e.id,sessionId:e.sessionId,at:new Date().toISOString()}),r}
@@ -1 +1 @@
1
- import{HARNESS_SESSION_CONTROL as f,isHarness as c}from"@weavecode/core";import{normalizeDirKey as E}from"../../daemon/opener.js";export const ESC="\x1B",ESC_KITTY="\x1B[27u",CTRL_C_KITTY="\x1B[99;5u",SHIFT_TAB="\x1B[Z",ENTER="\r",CTRL_B="",MODEL_NAME=/^[^\s\x00-\x1f\x7f]{1,128}$/,modelCommand=u=>`/model ${u}`,effortCommand=u=>`/effort ${u}`,ANSWER_ATOM=/^(?:[1-9]|y|n|d|\t|\r|\x1b\[B|\x1b\[Z)$/,ANSWER_TEXT=/^[^\x00-\x1f\x7f]*$/,ANSWER_ATOM_GAP_MS=120,sleep=u=>new Promise(n=>setTimeout(n,u));export async function sessionKeysTarget(u,n,t="\u51FB\u952E"){const e=u.sessions.getBySessionId(n);if(!e)return{ok:!1,status:404,error:"Session not found"};if(e.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const r=u.projects.getById(e.projectId);if(!r)return{ok:!1,status:404,error:"Project not found"};const i=u.terminalChannel();if(!i)return{ok:!1,status:409,error:`\u7EC8\u7AEF\u901A\u9053\u672A\u88C5\u914D\uFF0C\u65E0\u6CD5\u8FDC\u7A0B${t}`};const s=u.paneEnvConflictOf?.(n)??null;if(s)return{ok:!1,status:409,error:`\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7EC8\u7AEF\u5B9A\u4F4D\u88AB\u53E6\u4E00\u4E2A\u4F1A\u8BDD\uFF08${s.slice(0,8)}\uFF09\u5360\u7740\uFF08fork \u7EE7\u627F\u4E86\u540C\u4E00\u4E2A pane\uFF09\uFF0C\u4E3A\u907F\u514D\u628A${t}\u6253\u8FDB\u522B\u4EBA\u7684\u7EC8\u7AEF\u5DF2\u62D2\u7EDD`};const l=await u.terminalPaneFor(e,r);return l?{ok:!0,terminal:i,paneId:l.id}:{ok:!1,status:409,error:`\u627E\u4E0D\u5230\u4F1A\u8BDD\u6240\u5728\u7684\u7EC8\u7AEF\u7A97\u53E3\u2014\u2014\u8FD9\u4E2A\u4F1A\u8BDD\u6240\u5728\u7EC8\u7AEF\u6CA1\u6709\u53EF\u7528\u7684\u8FDC\u7A0B${t}\u901A\u9053`}}export function effortLevelsOf(u,n){const t=u.listBySession(n,1),e=t[t.length-1]?.source;return c(e)?f[e]?.effortLevels??[]:[]}export function sideQuestionSurfaceOf(u,n,t){const e=u.listBySession(n,1),r=e[e.length-1]?.source;return c(r)?t?.(r)??null:null}export async function locateTerminalPane(u,n,t,e){if(!u)return null;const r=n.get(t.sessionId);if(r){const o=await u.locatePane?.(r).catch(()=>null);if(o)return{id:o}}if(!t.title)return null;const i=t.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,""),s=E(e.path,process.platform);let l;try{l=await u.listPanes()}catch{return null}const a=l.filter(o=>o.title!=null&&o.cwd!=null&&s!=null&&o.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,"")===i&&E(o.cwd,process.platform)===s);return a.length===1?a[0]:null}
1
+ import{HARNESS_SESSION_CONTROL as p,isHarness as u}from"@weavecode/core";import{normalizeDirKey as f}from"../../daemon/opener.js";export const ESC="\x1B",ESC_KITTY="\x1B[27u",CTRL_C_KITTY="\x1B[99;5u",SHIFT_TAB="\x1B[Z",ENTER="\r",CTRL_B="",MODEL_NAME=/^[^\s\x00-\x1f\x7f]{1,128}$/,modelCommand=t=>`/model ${t}`,effortCommand=t=>`/effort ${t}`,ANSWER_ATOM=/^(?:[1-9]|y|n|d|\t|\r|\x1b\[B|\x1b\[Z)$/,ANSWER_TEXT=/^[^\x00-\x1f\x7f]*$/,ANSWER_ATOM_GAP_MS=120,sleep=t=>new Promise(r=>setTimeout(r,t));export async function sessionKeysTarget(t,r,e="\u51FB\u952E"){const o=t.sessions.getBySessionId(r);if(!o)return{ok:!1,status:404,error:"Session not found"};if(o.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const n=t.projects.getById(o.projectId);if(!n)return{ok:!1,status:404,error:"Project not found"};const a=t.terminalChannel();if(!a)return{ok:!1,status:409,error:`\u7EC8\u7AEF\u901A\u9053\u672A\u88C5\u914D\uFF0C\u65E0\u6CD5\u8FDC\u7A0B${e}`};const l=t.paneEnvConflictOf?.(r)??null;if(l)return{ok:!1,status:409,error:`\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7EC8\u7AEF\u5B9A\u4F4D\u88AB\u53E6\u4E00\u4E2A\u4F1A\u8BDD\uFF08${l.slice(0,8)}\uFF09\u5360\u7740\uFF08fork \u7EE7\u627F\u4E86\u540C\u4E00\u4E2A pane\uFF09\uFF0C\u4E3A\u907F\u514D\u628A${e}\u6253\u8FDB\u522B\u4EBA\u7684\u7EC8\u7AEF\u5DF2\u62D2\u7EDD`};const c=await t.terminalPaneFor(o,n);return c?{ok:!0,terminal:a,paneId:c.id}:{ok:!1,status:409,error:`\u627E\u4E0D\u5230\u4F1A\u8BDD\u6240\u5728\u7684\u7EC8\u7AEF\u7A97\u53E3\u2014\u2014\u8FD9\u4E2A\u4F1A\u8BDD\u6240\u5728\u7EC8\u7AEF\u6CA1\u6709\u53EF\u7528\u7684\u8FDC\u7A0B${e}\u901A\u9053`}}export function effortLevelsOf(t,r){const e=t.listBySession(r,1),o=e[e.length-1]?.source;return u(o)?p[o]?.effortLevels??[]:[]}export function sideQuestionSurfaceOf(t,r,e){const o=t.listBySession(r,1),n=o[o.length-1]?.source;return u(n)?e?.(n)??null:null}export async function locateTerminalPane(t,r,e,o){if(!t)return null;const n=r.get(e.sessionId);if(n){const s=await t.locatePane?.(n).catch(()=>null);if(s)return{id:s}}if(!e.title)return null;const a=e.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,""),l=f(o.path,process.platform);let c;try{c=await t.listPanes()}catch{return null}const i=c.filter(s=>s.title!=null&&s.cwd!=null&&l!=null&&s.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,"")===a&&f(s.cwd,process.platform)===l);return i.length===1?i[0]:null}
@@ -1 +1 @@
1
- import{pidAliveOf as f}from"../../daemon/claude-liveness.js";import{combinedLivenessOf as m}from"../../daemon/liveness.js";import{appendPromptbox as c,removePromptboxEntries as p}from"../promptbox.js";export const OFFLINE_ERROR="Session is not running";export function appendQueueEntry(n,s,e){c(n,s,[{id:e.id,sessionId:e.sessionId,text:e.text,oneWay:e.oneWay===!0,...e.forceTerminal===!0?{forceTerminal:!0}:{},...e.attachments&&e.attachments.length>0?{attachments:e.attachments}:{}}])}export function sessionJudgedDead(n,s,e=m()){const o=n.livenessRowOf(s);return o?f(o,e)===!1:!1}export function failOffline(n,s,e){const o=new Date().toISOString(),i={...e,status:"failed",reason:"offline",error:OFFLINE_ERROR,settledAt:o};return n.set(e.id,i),s({kind:"message.finished",messageId:e.id,sessionId:e.sessionId,status:"failed",at:o}),i}export function failQueuedOffline(n,s,e,o,i,a){const r=n.sessions.getBySessionId(i),d=r?.projectId==null?null:n.projects.getById(r.projectId);if(!(!d||a.length===0)){for(const t of a)failOffline(e,o,{id:t.id,sessionId:i,text:t.text,...t.attachments&&t.attachments.length>0?{attachments:t.attachments}:{},mode:"prompt",oneWay:t.oneWay===!0,channel:"prompt",status:"pending",at:t.at});p(s,d.token,new Set(a.map(t=>t.id)))}}
1
+ import{pidAliveOf as f}from"../../daemon/claude-liveness.js";import{combinedLivenessOf as c}from"../../daemon/liveness.js";import{appendPromptbox as m,removePromptboxEntries as p}from"../promptbox.js";export const OFFLINE_ERROR="Session is not running";export function appendQueueEntry(n,o,t){m(n,o,[{id:t.id,sessionId:t.sessionId,text:t.text,oneWay:t.oneWay===!0,...t.forceTerminal===!0?{forceTerminal:!0}:{},...t.attachments&&t.attachments.length>0?{attachments:t.attachments}:{}}])}export function sessionJudgedDead(n,o,t=c()){const s=n.livenessRowOf(o);return s?f(s,t)===!1:!1}export function failOffline(n,o,t){const s=new Date().toISOString(),i={...t,status:"failed",reason:"offline",error:OFFLINE_ERROR,settledAt:s};return n.set(t.id,i),o({kind:"message.finished",messageId:t.id,sessionId:t.sessionId,status:"failed",at:s}),i}export function failQueuedOffline(n,o,t,s,i,a){const r=n.sessions.getBySessionId(i),d=r?.projectId==null?null:n.projects.getById(r.projectId);if(!(!d||a.length===0)){for(const e of a)failOffline(t,s,{id:e.id,sessionId:i,text:e.text,...e.attachments&&e.attachments.length>0?{attachments:e.attachments}:{},mode:"prompt",oneWay:e.oneWay===!0,channel:"prompt",status:"pending",at:e.at});p(o,d.token,new Set(a.map(e=>e.id)))}}
@@ -1 +1 @@
1
- import{tmpdir as r}from"node:os";export function runRelay(e,i,n,s,o){try{return e.headless.run({sessionId:`prompt-relay:${i.sessionId}`,cwd:r(),prompt:n.instruction(s,o,{oneWay:i.oneWay===!0}),spec:{supported:!0,bin:n.bin,args:()=>[...n.args],promptStdin:!0},bin:e.bin??process.env.WEAVE_CLAUDE_BIN??n.bin,timeoutMs:e.relayTimeoutMs??0,detached:!1,onSettle:t=>settleRelay(e,i.id,t)})}catch(t){return settleRelay(e,i.id,{status:"failed",output:null,error:t instanceof Error?t.message:String(t)}),!0}}export function settleRelay(e,i,n){const s=e.getMemory(i);if(!s)return;if(n.status==="succeeded"){e.onReleased(s.sessionId);const t={...s,status:"delivered",settledAt:new Date().toISOString()};e.setMemory(t),e.commandModeOf(s.text,s.sessionId)?e.armCommandAck(i,e.onReleased):e.armAckWatch(t),e.emit({kind:"message.delivered",messageId:i,sessionId:s.sessionId,at:new Date().toISOString()});return}if(s.acked===!0){const t=new Date().toISOString();e.setMemory({...s,status:"delivered",settledAt:t}),e.emit({kind:"message.delivered",messageId:i,sessionId:s.sessionId,at:t});return}const o={...s,status:"failed",error:n.error??`prompt relay ${n.status}`,settledAt:new Date().toISOString()};e.setMemory(o),e.stall(s.sessionId,o,"failed"),e.emit({kind:"message.finished",messageId:i,sessionId:s.sessionId,status:"failed",at:new Date().toISOString()})}export{r as tmpdir};
1
+ import{tmpdir as o}from"node:os";export function runRelay(t,r,n,e,i){try{return t.headless.run({sessionId:`prompt-relay:${r.sessionId}`,cwd:o(),prompt:n.instruction(e,i,{oneWay:r.oneWay===!0}),spec:{supported:!0,bin:n.bin,args:()=>[...n.args],promptStdin:!0},bin:t.bin??process.env.WEAVE_CLAUDE_BIN??n.bin,timeoutMs:t.relayTimeoutMs??0,detached:!1,onSettle:s=>settleRelay(t,r.id,s)})}catch(s){return settleRelay(t,r.id,{status:"failed",output:null,error:s instanceof Error?s.message:String(s)}),!0}}export function settleRelay(t,r,n){const e=t.getMemory(r);if(!e)return;if(n.status==="succeeded"){t.onReleased(e.sessionId);const s={...e,status:"delivered",settledAt:new Date().toISOString()};t.setMemory(s),t.commandModeOf(e.text,e.sessionId)?t.armCommandAck(r,t.onReleased):t.armAckWatch(s),t.emit({kind:"message.delivered",messageId:r,sessionId:e.sessionId,at:new Date().toISOString()});return}if(e.acked===!0){const s=new Date().toISOString();t.setMemory({...e,status:"delivered",settledAt:s}),t.emit({kind:"message.delivered",messageId:r,sessionId:e.sessionId,at:s});return}const i={...e,status:"failed",error:n.error??`prompt relay ${n.status}`,settledAt:new Date().toISOString()};t.setMemory(i),t.stall(e.sessionId,i,"failed"),t.emit({kind:"message.finished",messageId:r,sessionId:e.sessionId,status:"failed",at:new Date().toISOString()})}export{o as tmpdir};
@@ -1,3 +1,3 @@
1
- import{appendOutbox as p}from"../mirror.js";export function resolveChannel(e,s,n,o,t){if(n==="prompt")return t.prompt||t.queuedPrompt||s()?"prompt":{reason:t.unsupportedReasons?.prompt??`Harness "${t.harness}" has no native prompt channel and the configured terminal cannot inject text`};if(n==="inject"||n==="headless")return(n==="inject"?t.inject:t.headless)?n:{reason:unsupportedReason(t,n)};const i=e.turnOpenOf(o)?"inject":"headless";return(i==="inject"?t.inject:t.headless)?i:{reason:unsupportedReason(t,i)}}export function unsupportedReason(e,s){return e.unsupportedReasons?.[s]??`Harness "${e.harness}" does not support the ${s} messaging channel`}export function renderEnvelope(e,s,n){return n.renderEnvelope?.(e,s)??`[weave message] from=${s.fromLabel} at=${s.at} mode=${s.mode}
1
+ import{appendOutbox as m}from"../mirror.js";export function resolveChannel(e,t,s,o,n){if(s==="prompt")return n.prompt||n.queuedPrompt||t()?"prompt":{reason:n.unsupportedReasons?.prompt??`Harness "${n.harness}" has no native prompt channel and the configured terminal cannot inject text`};if(s==="inject"||s==="headless")return(s==="inject"?n.inject:n.headless)?s:{reason:unsupportedReason(n,s)};const i=e.turnOpenOf(o)?"inject":"headless";return(i==="inject"?n.inject:n.headless)?i:{reason:unsupportedReason(n,i)}}export function unsupportedReason(e,t){return e.unsupportedReasons?.[t]??`Harness "${e.harness}" does not support the ${t} messaging channel`}export function renderEnvelope(e,t,s){return s.renderEnvelope?.(e,t)??`[weave message] from=${t.fromLabel} at=${t.at} mode=${t.mode}
2
2
 
3
- ${e}`}export function deliverInject(e,s,n,o,t,i){const d=renderEnvelope(i,o,t);p(e.hooksDir,n,[{sessionId:s.sessionId,text:d}]);const r={...s,status:"injected",settledAt:new Date().toISOString()};return e.memory.set(r.id,r),e.bus.emit({kind:"message.delivered",messageId:r.id,sessionId:s.sessionId,at:new Date().toISOString()}),{ok:!0,messageId:r.id,status:"injected",message:r}}export function deliverHeadless(e,s,n,o,t,i){const d=t.headless,r={...s,status:"running"};e.memory.set(r.id,r);const u={settled:!1};try{e.headless.run({sessionId:r.sessionId,cwd:n,prompt:renderEnvelope(i,o,t),spec:d,bin:e.bin??process.env.WEAVE_CLAUDE_BIN??d.bin,timeoutMs:e.timeoutMs,onSettle:a=>m(e,r,u,a)})||m(e,r,u,{status:"failed",output:null,error:"Session already has a running run"})}catch(a){m(e,r,u,{status:"failed",output:null,error:a instanceof Error?a.message:String(a)})}return{ok:!0,messageId:r.id,status:"running",message:e.memory.get(r.id)}}function m(e,s,n,o){if(n.settled)return;n.settled=!0;const t=e.memory.get(s.id);if(t)try{e.memory.set(s.id,{...t,status:o.status,output:o.output,error:o.error,settledAt:new Date().toISOString()}),e.bus.emit({kind:"message.finished",messageId:s.id,sessionId:s.sessionId,status:o.status,at:new Date().toISOString()})}catch{}}
3
+ ${e}`}export function deliverInject(e,t,s,o,n,a){const i=renderEnvelope(a,o,n);m(e.hooksDir,s,[{sessionId:t.sessionId,text:i}]);const r={...t,status:"injected",settledAt:new Date().toISOString()};return e.memory.set(r.id,r),e.bus.emit({kind:"message.delivered",messageId:r.id,sessionId:t.sessionId,at:new Date().toISOString()}),{ok:!0,messageId:r.id,status:"injected",message:r}}export function deliverHeadless(e,t,s,o,n,a){const i=n.headless,r={...t,status:"running"};e.memory.set(r.id,r);const u={settled:!1};try{e.headless.run({sessionId:r.sessionId,cwd:s,prompt:renderEnvelope(a,o,n),spec:i,bin:e.bin??process.env.WEAVE_CLAUDE_BIN??i.bin,timeoutMs:e.timeoutMs,onSettle:l=>p(e,r,u,l)})||p(e,r,u,{status:"failed",output:null,error:"Session already has a running run"})}catch(d){p(e,r,u,{status:"failed",output:null,error:d instanceof Error?d.message:String(d)})}return{ok:!0,messageId:r.id,status:"running",message:e.memory.get(r.id)}}function p(e,t,s,o){if(s.settled)return;s.settled=!0;const n=e.memory.get(t.id);if(n)try{e.memory.set(t.id,{...n,status:o.status,output:o.output,error:o.error,settledAt:new Date().toISOString()}),e.bus.emit({kind:"message.finished",messageId:t.id,sessionId:t.sessionId,status:o.status,at:new Date().toISOString()})}catch{}}
@@ -7,7 +7,9 @@ import type { PipeMessage } from '../message-deliverer.js';
7
7
  * 终态短时驻留(delivered/injected/succeeded 在 settledAt+ttl 内可见,展示
8
8
  * via/acked),failed/timeout/暂停闸成因常驻。历史在会话自己的转录里。
9
9
  * 例外:已执行的斜杠命令(/rewind 类,宿主不回 UPS)也常驻——它们没有认领
10
- * 事件可退场,TTL 一到就消失会让「刚才那条命令呢」无从查起。
10
+ * 事件可退场,TTL 一到就消失会让「刚才那条命令呢」无从查起。**判据是「没有
11
+ * 认领事件」**(`ackedEventId` 空):skill/插件命令的正文也以 `/` 开头,但它的
12
+ * UPS 就是气泡,留着这行等于同一条消息在对话尾巴上多挂一个「已执行」。
11
13
  */
12
14
  export declare function listVisible(deps: {
13
15
  sessions: Pick<SessionRepository, 'getBySessionId'>;
@@ -1 +1 @@
1
- import{combinedLivenessOf as p}from"../../daemon/liveness.js";import{readAllPromptbox as m,readPromptbox as g}from"../promptbox.js";import{sessionJudgedDead as h}from"./queue.js";function I(n,s){return{id:s.id,sessionId:n,text:s.text,...s.attachments&&s.attachments.length>0?{attachments:s.attachments}:{},mode:"prompt",oneWay:s.oneWay===!0,...s.forceTerminal===!0?{forceTerminal:!0}:{},channel:"prompt",status:"pending",at:s.at}}export function listVisible(n,s,o,i,e,u=()=>!1){const f=Date.now(),r=[],a=n.sessions.getBySessionId(i);if(a?.projectId!=null){const t=n.projects.getById(a.projectId);if(t)for(const c of g(s,t.token))c.sessionId===i&&r.push(I(i,c))}for(const t of o.values()){if(t.sessionId!==i)continue;if(t.stalled===!0||t.status==="delivering"||t.status==="running"){r.push(t);continue}if(t.status==="failed"||t.status==="timeout"){r.push(t);continue}const c=t.settledAt?Date.parse(t.settledAt):NaN,l=t.status==="delivered"&&t.acked!==!0,d=t.status==="delivered"&&t.acked===!0&&u(t.text);(l||d||!Number.isNaN(c)&&f-c<e)&&r.push(t)}return r.sort((t,c)=>t.at<c.at?-1:1)}export function listInflightCounts(n,s){const o=new Map,i=e=>{o.set(e,(o.get(e)??0)+1)};for(const e of m(n))i(e.sessionId);for(const e of s.values())(e.status==="delivering"||e.status==="running")&&i(e.sessionId);return o}export async function sessionTerminals(n,s,o,i,e){const u={};if(e&&e.size>0){for(const a of e)u[a]=null;e.clear()}if(!s?.locateScreens||o.size===0)return u;const f={},r=n.livenessOf?.()??p();for(const[a,t]of o){if(h(n.sessions,a,r)){o.delete(a),i(),u[a]=null;continue}f[a]=t}return{...u,...await s.locateScreens(f)}}
1
+ import{combinedLivenessOf as m}from"../../daemon/liveness.js";import{readAllPromptbox as p,readPromptbox as g}from"../promptbox.js";import{sessionJudgedDead as h}from"./queue.js";function x(n,e){return{id:e.id,sessionId:n,text:e.text,...e.attachments&&e.attachments.length>0?{attachments:e.attachments}:{},mode:"prompt",oneWay:e.oneWay===!0,...e.forceTerminal===!0?{forceTerminal:!0}:{},channel:"prompt",status:"pending",at:e.at}}export function listVisible(n,e,o,i,s,a=()=>!1){const f=Date.now(),u=[],c=n.sessions.getBySessionId(i);if(c?.projectId!=null){const t=n.projects.getById(c.projectId);if(t)for(const r of g(e,t.token))r.sessionId===i&&u.push(x(i,r))}for(const t of o.values()){if(t.sessionId!==i)continue;if(t.stalled===!0||t.status==="delivering"||t.status==="running"){u.push(t);continue}if(t.status==="failed"||t.status==="timeout"){u.push(t);continue}const r=t.settledAt?Date.parse(t.settledAt):NaN,l=t.status==="delivered"&&t.acked!==!0,d=t.status==="delivered"&&t.acked===!0&&t.ackedEventId==null&&a(t.text);(l||d||!Number.isNaN(r)&&f-r<s)&&u.push(t)}return u.sort((t,r)=>t.at<r.at?-1:1)}export function listInflightCounts(n,e){const o=new Map,i=s=>{o.set(s,(o.get(s)??0)+1)};for(const s of p(n))i(s.sessionId);for(const s of e.values())(s.status==="delivering"||s.status==="running")&&i(s.sessionId);return o}export async function sessionTerminals(n,e,o,i,s){const a={};if(s&&s.size>0){for(const c of s)a[c]=null;s.clear()}if(!e?.locateScreens||o.size===0)return a;const f={},u=n.livenessOf?.()??m();for(const[c,t]of o){if(h(n.sessions,c,u)){o.delete(c),i(),a[c]=null;continue}f[c]=t}return{...a,...await e.locateScreens(f)}}
@@ -1,11 +1,11 @@
1
- import{INJECTABLE_EVENTS as b,TITLE_EFFECTIVE_EVENTS as S,hookSourceHarness as w}from"@weavecode/core";import{createPluginLogger as P}from"./plugin-loader.js";import{readHooksEnabled as k}from"../daemon/settings.js";import{effective as v,pluginsStateOf as j}from"./plugin-project-state.js";import{postJson as D,runWebhook as T}from"./handlers/webhook.js";import{DISPATCH_MARKER as I,extractFilePath as h,isCrossProjectPath as W,matchesAnyGlob as C,projectLabel as O,renderTemplate as E,templateVars as A}from"./match.js";function $(c){if(!c)return null;const t=c.match(/\{[\s\S]*\}/);if(t)try{const i=JSON.parse(t[0]);if(typeof i.label=="string"&&i.label.trim())return i.label.trim()}catch{}const s=/label\s*[:=]\s*"?([A-Za-z0-9_-]+)/i.exec(c);return s?s[1]:null}const y=6e4,N=10*6e4,x=4,H=4,L=3e3;export class HookDispatcher{deps;runningWebhooks=new Set;lastClassifyAt=new Map;recentPool=new Map;activeWebhooks=0;pendingWebhooks=[];activePlugins=0;pendingPlugins=[];constructor(t){this.deps=t}async onIngest(t){try{if(!k())return{};this.deps.plugins?.notifyEvent?.(t.payload.eventType,t.payload,t.sessionId);const s={};if(t.sessionId){const e=_(t.payload);let n=null;if(e===null&&this.deps.sessionTitleOf)try{n=await this.deps.sessionTitleOf(t.sessionId)}catch{}const r=e??n;r!==null&&this.deps.sessions.applyReportedTitle(t.sessionId,r)&&this.deps.bus.emit({kind:"session.renamed",sessionId:t.sessionId,title:r,at:new Date().toISOString()});const d=this.deps.sessions.getBySessionId(t.sessionId)?.pendingTitle;if(d){s.sessionTitle=d;const p=S[t.source].includes(t.payload.eventType);(t.deliveredTitle===d&&p||e!==null)&&this.deps.sessions.confirmPendingTitle(t.sessionId,d)&&this.deps.bus.emit({kind:"session.renamed",sessionId:t.sessionId,title:d,at:new Date().toISOString()})}}const i=this.match(t);if(i.length===0)return s;const a=[],o=[],l=Date.now(),u=l+L;for(const e of i)if(this.deps.bus.emit({kind:"rule.matched",ruleId:e.id,eventId:t.eventId,sessionId:t.sessionId,at:new Date(l).toISOString()}),e.handler.type!=="log"){if(e.handler.type==="manual"||e.handler.type==="inject"){if(this.dedupe(e,t,l))continue;const n=E(e.handler.template,A({event:t.payload.eventType,tool:t.payload.toolName,filePath:h(t.payload.toolInput),cwd:t.payload.cwd,session:t.sessionId,project:O(t.project.path),rule:e.name}))+`
2
- ${I}`,r=e.handler.type==="inject"?"injected":"pending";this.createDispatch(e,t,{prompt:n,status:r,mode:e.handler.type==="inject"?"auto":"manual"}),e.handler.type==="inject"&&(e.filter.crossProjectOnly?o.push(n):a.push(n));continue}if(e.handler.type==="webhook"){if(this.runningWebhooks.has(e.id))continue;this.runningWebhooks.add(e.id);const n=this.createDispatch(e,t,{prompt:`webhook ${e.handler.url}`,status:"running",mode:"auto"});this.deps.bus.emit({kind:"dispatch.started",ruleId:e.id,dispatchId:n.id,sessionId:t.sessionId,at:new Date().toISOString()}),this.runWebhookAsync(e,this.summary(e,t),n.id);continue}if(e.handler.type==="classify"){const n=this.turnText(t);if(!n)continue;const r=e.handler,d=n.toLowerCase();if(r.prefilter&&r.prefilter.length>0&&!r.prefilter.some(m=>d.includes(m.toLowerCase())))continue;const p=`classify:${e.id}`,f=r.cooldownMs??N;if(l-(this.lastClassifyAt.get(p)??0)<f||this.runningWebhooks.has(p))continue;this.lastClassifyAt.set(p,l),this.runningWebhooks.add(p);const g=this.createDispatch(e,t,{prompt:`classify \u2192 ${r.routes.map(m=>m.label).join("/")}`,status:"running",mode:"auto"});this.deps.bus.emit({kind:"dispatch.started",ruleId:e.id,dispatchId:g.id,sessionId:t.sessionId,at:new Date().toISOString()}),this.runClassifyAsync(e,t,g.id,n);continue}if(e.handler.type==="plugin"){const n=this.deps.plugins;if(!n)continue;const r=n.getHandler(e.handler.pluginId,e.handler.handlerType);if(!r||this.dedupe(e,t,l))continue;if(!this.injectable(t)){this.runPluginDetached(e,t,n,r);continue}const d=u-Date.now();if(d<=0)continue;const p=await this.runPluginHandler(e,t,n,r,d);if(!p)continue;p.prompt&&this.createDispatch(e,t,{prompt:p.prompt+`
3
- ${I}`,status:"pending",mode:"auto"}),p.additionalContext&&o.push(p.additionalContext)}}return(a.length>0||o.length>0)&&(s.additionalContext=[...a,...o].join(`
1
+ import{INJECTABLE_EVENTS as b,TITLE_EFFECTIVE_EVENTS as S,hookSourceHarness as w}from"@weavecode/core";import{createPluginLogger as P}from"./plugin-loader.js";import{readHooksEnabled as k}from"../daemon/settings.js";import{effective as v,pluginsStateOf as T}from"./plugin-project-state.js";import{postJson as D,runWebhook as j}from"./handlers/webhook.js";import{DISPATCH_MARKER as g,extractFilePath as c,isCrossProjectPath as W,matchesAnyGlob as C,projectLabel as O,renderTemplate as _,templateVars as E}from"./match.js";function N(h){if(!h)return null;const e=h.match(/\{[\s\S]*\}/);if(e)try{const n=JSON.parse(e[0]);if(typeof n.label=="string"&&n.label.trim())return n.label.trim()}catch{}const s=/label\s*[:=]\s*"?([A-Za-z0-9_-]+)/i.exec(h);return s?s[1]:null}const I=6e4,A=10*6e4,$=4,L=4,M=3e3;export class HookDispatcher{deps;runningWebhooks=new Set;lastClassifyAt=new Map;recentPool=new Map;activeWebhooks=0;pendingWebhooks=[];activePlugins=0;pendingPlugins=[];constructor(e){this.deps=e}async onIngest(e){try{if(!k())return{};this.deps.plugins?.notifyEvent?.(e.payload.eventType,e.payload,e.sessionId);const s={};if(e.sessionId){const t=H(e.payload);let i=null;if(t===null&&this.deps.sessionTitleOf)try{i=await this.deps.sessionTitleOf(e.sessionId)}catch{}const r=t??i;r!==null&&this.deps.sessions.applyReportedTitle(e.sessionId,r)&&this.deps.bus.emit({kind:"session.renamed",sessionId:e.sessionId,title:r,at:new Date().toISOString()});const d=this.deps.sessions.getBySessionId(e.sessionId)?.pendingTitle;if(d){s.sessionTitle=d;const p=S[e.source].includes(e.payload.eventType);(e.deliveredTitle===d&&p||t!==null)&&this.deps.sessions.confirmPendingTitle(e.sessionId,d)&&this.deps.bus.emit({kind:"session.renamed",sessionId:e.sessionId,title:d,at:new Date().toISOString()})}}const n=this.match(e);if(n.length===0)return s;const a=[],o=[],l=Date.now(),u=l+M;for(const t of n)if(this.deps.bus.emit({kind:"rule.matched",ruleId:t.id,eventId:e.eventId,sessionId:e.sessionId,at:new Date(l).toISOString()}),t.handler.type!=="log"){if(t.handler.type==="manual"||t.handler.type==="inject"){if(this.dedupe(t,e,l))continue;const i=_(t.handler.template,E({event:e.payload.eventType,tool:e.payload.toolName,filePath:c(e.payload.toolInput),cwd:e.payload.cwd,session:e.sessionId,project:O(e.project.path),rule:t.name}))+`
2
+ ${g}`,r=t.handler.type==="inject"?"injected":"pending";this.createDispatch(t,e,{prompt:i,status:r,mode:t.handler.type==="inject"?"auto":"manual"}),t.handler.type==="inject"&&(t.filter.crossProjectOnly?o.push(i):a.push(i));continue}if(t.handler.type==="webhook"){if(this.runningWebhooks.has(t.id))continue;this.runningWebhooks.add(t.id);const i=this.createDispatch(t,e,{prompt:`webhook ${t.handler.url}`,status:"running",mode:"auto"});this.deps.bus.emit({kind:"dispatch.started",ruleId:t.id,dispatchId:i.id,sessionId:e.sessionId,at:new Date().toISOString()}),this.runWebhookAsync(t,this.summary(t,e),i.id);continue}if(t.handler.type==="classify"){const i=this.turnText(e);if(!i)continue;const r=t.handler,d=i.toLowerCase();if(r.prefilter&&r.prefilter.length>0&&!r.prefilter.some(m=>d.includes(m.toLowerCase())))continue;const p=`classify:${t.id}`,f=r.cooldownMs??A;if(l-(this.lastClassifyAt.get(p)??0)<f||this.runningWebhooks.has(p))continue;this.lastClassifyAt.set(p,l),this.runningWebhooks.add(p);const y=this.createDispatch(t,e,{prompt:`classify \u2192 ${r.routes.map(m=>m.label).join("/")}`,status:"running",mode:"auto"});this.deps.bus.emit({kind:"dispatch.started",ruleId:t.id,dispatchId:y.id,sessionId:e.sessionId,at:new Date().toISOString()}),this.runClassifyAsync(t,e,y.id,i);continue}if(t.handler.type==="plugin"){const i=this.deps.plugins;if(!i)continue;const r=i.getHandler(t.handler.pluginId,t.handler.handlerType);if(!r||this.dedupe(t,e,l))continue;if(!this.injectable(e)){this.runPluginDetached(t,e,i,r);continue}const d=u-Date.now();if(d<=0)continue;const p=await this.runPluginHandler(t,e,i,r,d);if(!p)continue;p.prompt&&this.createDispatch(t,e,{prompt:p.prompt+`
3
+ ${g}`,status:"pending",mode:"auto"}),p.additionalContext&&o.push(p.additionalContext)}}return(a.length>0||o.length>0)&&(s.additionalContext=[...a,...o].join(`
4
4
 
5
5
  `)),o.length>0&&(s.deferred=o.join(`
6
6
 
7
- `)),s}catch{return{}}}createDispatch(t,s,i){const a=this.deps.dispatches.insert({ruleId:t.id,eventId:s.eventId,sessionId:s.sessionId,...i});return this.deps.bus.emit({kind:"dispatch.created",ruleId:t.id,dispatchId:a.id,status:i.status,mode:a.mode,sessionId:s.sessionId,at:a.startedAt}),a}dedupe(t,s,i){const a=`${t.id}:${s.sessionId??""}`,o=this.recentPool.get(a);return o!==void 0&&i-o<y?!0:(this.recentPool.set(a,i),this.trimDedupe(i),!1)}match(t){const s=this.deps.pluginStates,i=s?j(t.project.meta).enabled:null;let a=null;return this.deps.registry.candidates(t.payload.eventType,s?{includeDisabled:!0}:void 0).filter(o=>{const l=w(o.source);if(l!==null&&l!=="any"&&l!==t.source||o.projectId!==null&&o.projectId!==t.project.id)return!1;if(o.pluginId!==null){if(!o.enabled&&i?.[o.pluginId]!==!0||s&&!v(t.project,o.pluginId,{states:s}))return!1}else if(!o.enabled)return!1;const u=o.filter;if(u.toolNames?.length&&(!t.payload.toolName||!u.toolNames.includes(t.payload.toolName)))return!1;if(u.pathGlobs?.length){const e=h(t.payload.toolInput);if(!e||!C(e,u.pathGlobs))return!1}if(u.crossProjectOnly){const e=h(t.payload.toolInput)??t.payload.cwd;if(!e||(a??=this.deps.projects.list().map(n=>n.path).filter(n=>n!==t.project.path),!W(e,t.project.path,a)))return!1}return!0})}injectable(t){const s=t.payload.eventType;return s!==null&&b[t.source].includes(s)}async runPluginHandler(t,s,i,a,o){if(t.handler.type!=="plugin")return;const{pluginId:l}=t.handler,u=P(l),e=o===void 0?t.timeoutMs:Math.min(t.timeoutMs,o);let n;try{const r=(async()=>{await this.acquirePluginSlot();try{return await a.execute({event:s.payload,rule:t,config:i.getConfig(l),logger:u})}finally{this.releasePluginSlot()}})(),d=await Promise.race([r,new Promise((p,f)=>{n=setTimeout(()=>f(new Error("plugin handler timeout")),e)})]);return d&&typeof d=="object"?d:void 0}catch{return}finally{n&&clearTimeout(n)}}async runPluginDetached(t,s,i,a){try{const o=await this.runPluginHandler(t,s,i,a);if(!o?.prompt)return;this.createDispatch(t,s,{prompt:o.prompt+`
8
- ${I}`,status:"pending",mode:"auto"})}catch{}}summary(t,s){return{ruleId:t.id,ruleName:t.name,projectId:s.project.id,sessionId:s.sessionId,event:s.payload.eventType,toolName:s.payload.toolName,filePath:h(s.payload.toolInput),cwd:s.payload.cwd,at:new Date().toISOString()}}turnText(t){const s=t.payload.raw?.last_assistant_message;return typeof s=="string"?s.trim():""}async runClassifyAsync(t,s,i,a){const o=t.handler;if(o.type!=="classify")return;const l=`classify:${t.id}`;try{const u=await this.deps.classify?.({sessionId:s.sessionId??"",prompt:`${o.prompt}
7
+ `)),s}catch{return{}}}createDispatch(e,s,n){const a=this.deps.dispatches.insert({ruleId:e.id,eventId:s.eventId,sessionId:s.sessionId,...n});return this.deps.bus.emit({kind:"dispatch.created",ruleId:e.id,dispatchId:a.id,status:n.status,mode:a.mode,sessionId:s.sessionId,at:a.startedAt}),a}dedupe(e,s,n){const a=`${e.id}:${s.sessionId??""}`,o=this.recentPool.get(a);return o!==void 0&&n-o<I?!0:(this.recentPool.set(a,n),this.trimDedupe(n),!1)}match(e){const s=this.deps.pluginStates,n=s?T(e.project.meta).enabled:null;let a=null;return this.deps.registry.candidates(e.payload.eventType,s?{includeDisabled:!0}:void 0).filter(o=>{const l=w(o.source);if(l!==null&&l!=="any"&&l!==e.source||o.projectId!==null&&o.projectId!==e.project.id)return!1;if(o.pluginId!==null){if(!o.enabled&&n?.[o.pluginId]!==!0||s&&!v(e.project,o.pluginId,{states:s}))return!1}else if(!o.enabled)return!1;const u=o.filter;if(u.toolNames?.length&&(!e.payload.toolName||!u.toolNames.includes(e.payload.toolName)))return!1;if(u.pathGlobs?.length){const t=c(e.payload.toolInput);if(!t||!C(t,u.pathGlobs))return!1}if(u.crossProjectOnly){const t=c(e.payload.toolInput)??e.payload.cwd;if(!t||(a??=this.deps.projects.list().map(i=>i.path).filter(i=>i!==e.project.path),!W(t,e.project.path,a)))return!1}return!0})}injectable(e){const s=e.payload.eventType;return s!==null&&b[e.source].includes(s)}async runPluginHandler(e,s,n,a,o){if(e.handler.type!=="plugin")return;const{pluginId:l}=e.handler,u=P(l),t=o===void 0?e.timeoutMs:Math.min(e.timeoutMs,o);let i;try{const r=(async()=>{await this.acquirePluginSlot();try{return await a.execute({event:s.payload,rule:e,config:n.getConfig(l),logger:u})}finally{this.releasePluginSlot()}})(),d=await Promise.race([r,new Promise((p,f)=>{i=setTimeout(()=>f(new Error("plugin handler timeout")),t)})]);return d&&typeof d=="object"?d:void 0}catch{return}finally{i&&clearTimeout(i)}}async runPluginDetached(e,s,n,a){try{const o=await this.runPluginHandler(e,s,n,a);if(!o?.prompt)return;this.createDispatch(e,s,{prompt:o.prompt+`
8
+ ${g}`,status:"pending",mode:"auto"})}catch{}}summary(e,s){return{ruleId:e.id,ruleName:e.name,projectId:s.project.id,sessionId:s.sessionId,event:s.payload.eventType,toolName:s.payload.toolName,filePath:c(s.payload.toolInput),cwd:s.payload.cwd,at:new Date().toISOString()}}turnText(e){const n=e.payload.raw?.last_assistant_message;return typeof n=="string"?n.trim():""}async runClassifyAsync(e,s,n,a){const o=e.handler;if(o.type!=="classify")return;const l=`classify:${e.id}`;try{const u=await this.deps.classify?.({sessionId:s.sessionId??"",prompt:`${o.prompt}
9
9
 
10
10
  \u672C\u8F6E\u6700\u7EC8\u8F93\u51FA\uFF1A
11
- ${a.slice(0,8e3)}`}),e=$(u),n=e?o.routes.find(d=>d.label.toLowerCase()===e.toLowerCase()):void 0;if(!n){this.deps.dispatches.updateStatus(i,{status:"succeeded",output:e?`label=${e} (no route)`:"no label",finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:t.id,dispatchId:i,status:"succeeded",sessionId:s.sessionId,at:new Date().toISOString()});return}const r=await D(n.url,n.secret,{...this.summary(t,s),label:e,verdict:u?.slice(0,500)},this.deps.fetchImpl);this.deps.dispatches.updateStatus(i,{status:r.status,output:`label=${e} ${r.output??""}`.trim(),error:r.error??null,finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:t.id,dispatchId:i,status:r.status,sessionId:s.sessionId,at:new Date().toISOString()})}catch(u){this.deps.dispatches.updateStatus(i,{status:"failed",error:String(u),finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:t.id,dispatchId:i,status:"failed",sessionId:s.sessionId,at:new Date().toISOString()})}finally{this.runningWebhooks.delete(l)}}async runWebhookAsync(t,s,i){await this.acquireWebhookSlot();try{const a=await T(t,s,this.deps.fetchImpl);this.deps.dispatches.updateStatus(i,{status:a.status,output:a.output??null,error:a.error??null,finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:t.id,dispatchId:i,status:a.status,sessionId:s.sessionId,at:new Date().toISOString()})}catch(a){this.deps.dispatches.updateStatus(i,{status:"failed",error:String(a),finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:t.id,dispatchId:i,status:"failed",sessionId:s.sessionId,at:new Date().toISOString()})}finally{this.runningWebhooks.delete(t.id),this.releaseWebhookSlot()}}acquireWebhookSlot(){return this.activeWebhooks<x?(this.activeWebhooks++,Promise.resolve()):new Promise(t=>{this.pendingWebhooks.push(()=>{this.activeWebhooks++,t()})})}releaseWebhookSlot(){this.activeWebhooks--;const t=this.pendingWebhooks.shift();t&&t()}acquirePluginSlot(){return this.activePlugins<H?(this.activePlugins++,Promise.resolve()):new Promise(t=>{this.pendingPlugins.push(()=>{this.activePlugins++,t()})})}releasePluginSlot(){this.activePlugins--;const t=this.pendingPlugins.shift();t&&t()}trimDedupe(t){if(!(this.recentPool.size<1e3))for(const[s,i]of this.recentPool)t-i>=y&&this.recentPool.delete(s)}}function _(c){const t=c.raw;if(typeof t!="object"||t===null)return null;const s=t.session_title;return typeof s=="string"&&s.length>0?s:null}
11
+ ${a.slice(0,8e3)}`}),t=N(u),i=t?o.routes.find(d=>d.label.toLowerCase()===t.toLowerCase()):void 0;if(!i){this.deps.dispatches.updateStatus(n,{status:"succeeded",output:t?`label=${t} (no route)`:"no label",finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:e.id,dispatchId:n,status:"succeeded",sessionId:s.sessionId,at:new Date().toISOString()});return}const r=await D(i.url,i.secret,{...this.summary(e,s),label:t,verdict:u?.slice(0,500)},this.deps.fetchImpl);this.deps.dispatches.updateStatus(n,{status:r.status,output:`label=${t} ${r.output??""}`.trim(),error:r.error??null,finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:e.id,dispatchId:n,status:r.status,sessionId:s.sessionId,at:new Date().toISOString()})}catch(u){this.deps.dispatches.updateStatus(n,{status:"failed",error:String(u),finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:e.id,dispatchId:n,status:"failed",sessionId:s.sessionId,at:new Date().toISOString()})}finally{this.runningWebhooks.delete(l)}}async runWebhookAsync(e,s,n){await this.acquireWebhookSlot();try{const a=await j(e,s,this.deps.fetchImpl);this.deps.dispatches.updateStatus(n,{status:a.status,output:a.output??null,error:a.error??null,finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:e.id,dispatchId:n,status:a.status,sessionId:s.sessionId,at:new Date().toISOString()})}catch(a){this.deps.dispatches.updateStatus(n,{status:"failed",error:String(a),finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:e.id,dispatchId:n,status:"failed",sessionId:s.sessionId,at:new Date().toISOString()})}finally{this.runningWebhooks.delete(e.id),this.releaseWebhookSlot()}}acquireWebhookSlot(){return this.activeWebhooks<$?(this.activeWebhooks++,Promise.resolve()):new Promise(e=>{this.pendingWebhooks.push(()=>{this.activeWebhooks++,e()})})}releaseWebhookSlot(){this.activeWebhooks--;const e=this.pendingWebhooks.shift();e&&e()}acquirePluginSlot(){return this.activePlugins<L?(this.activePlugins++,Promise.resolve()):new Promise(e=>{this.pendingPlugins.push(()=>{this.activePlugins++,e()})})}releasePluginSlot(){this.activePlugins--;const e=this.pendingPlugins.shift();e&&e()}trimDedupe(e){if(!(this.recentPool.size<1e3))for(const[s,n]of this.recentPool)e-n>=I&&this.recentPool.delete(s)}}function H(h){const e=h.raw;if(typeof e!="object"||e===null)return null;const s=e.session_title;return typeof s=="string"&&s.length>0?s:null}
@@ -1 +1 @@
1
- import{isSyntheticSession as f,registerSyntheticSession as S,syntheticSessionIds as g}from"./synthetic-sessions.js";const y=8e3;export function createEdgeExtract(s){const d=s.concurrency??4;let o=0;return{supports(t){const r=s.harnessOf(t);return r?s.surfaceFor(r).headless?.extractArgs!=null:!1},run({sessionId:t,prompt:r}){if(o>=d)return Promise.resolve(null);const i=s.harnessOf(t),c=s.sessions.getBySessionId(t);if(!i||!c?.projectId)return Promise.resolve(null);const u=s.projects.getById(c.projectId),n=s.surfaceFor(i).headless,l=process.env.WEAVE_CLAUDE_BIN??n?.bin;if(!u||!n?.extractArgs||!l)return Promise.resolve(null);const h=S();return s.onSyntheticChange(),o++,new Promise(m=>{let a=!1;const p=e=>{a||(a=!0,o--,m(e))};s.headless.run({sessionId:h,cwd:u.path,prompt:r,spec:n,bin:l,argsOf:e=>n.extractArgs(t,e),timeoutMs:s.timeoutMs??12e4,onSettle:e=>{p(e.status==="succeeded"&&e.output?.trim()?e.output.trim().slice(0,y):null)}})||p(null)})}}}export{f as isSyntheticSession,g as syntheticSessionIds};
1
+ import{isSyntheticSession as g,registerSyntheticSession as d,syntheticSessionIds as x}from"./synthetic-sessions.js";const y=8e3;export function createEdgeExtract(t){const h=t.concurrency??4;let o=0;return{supports(s){const r=t.harnessOf(s);return r?t.surfaceFor(r).headless?.extractArgs!=null:!1},run({sessionId:s,prompt:r}){if(o>=h)return Promise.resolve(null);const c=t.harnessOf(s),i=t.sessions.getBySessionId(s);if(!c||!i?.projectId)return Promise.resolve(null);const u=t.projects.getById(i.projectId),n=t.surfaceFor(c).headless,a=process.env.WEAVE_CLAUDE_BIN??n?.bin;if(!u||!n?.extractArgs||!a)return Promise.resolve(null);const m=d();return t.onSyntheticChange(),o++,new Promise(S=>{let l=!1;const f=e=>{l||(l=!0,o--,S(e))};t.headless.run({sessionId:m,cwd:u.path,prompt:r,spec:n,bin:a,argsOf:e=>n.extractArgs(s,e),timeoutMs:t.timeoutMs??12e4,onSettle:e=>{f(e.status==="succeeded"&&e.output?.trim()?e.output.trim().slice(0,y):null)}})||f(null)})}}}export{g as isSyntheticSession,x as syntheticSessionIds};
@@ -1 +1 @@
1
- import{createHmac as l}from"node:crypto";const c=5e3,d=4096;export async function postJson(o,s,n,e=fetch){let r;try{r=new URL(o)}catch{return{ok:!1,status:"failed",error:`invalid url: ${o}`}}if(r.protocol!=="http:"&&r.protocol!=="https:")return{ok:!1,status:"failed",error:`unsupported protocol: ${r.protocol}`};const u=JSON.stringify(n),i={"content-type":"application/json","user-agent":"weave-daemon"};s&&(i["x-weave-signature"]=`sha256=${l("sha256",s).update(u).digest("hex")}`);try{const t=await e(r,{method:"POST",headers:i,body:u,signal:AbortSignal.timeout(c)}),a=(await t.text()).slice(0,d);return t.ok?{ok:!0,status:"succeeded",output:a||`HTTP ${t.status}`}:{ok:!1,status:"failed",error:`HTTP ${t.status}`,output:a}}catch(t){const a=t instanceof Error&&(t.name==="TimeoutError"||t.name==="AbortError");return{ok:!1,status:a?"timeout":"failed",error:a?`webhook timed out after ${c}ms`:String(t)}}}export async function runWebhook(o,s,n=fetch){const e=o.handler;return e.type!=="webhook"?{ok:!1,status:"failed",error:`rule ${o.id} is not a webhook handler`}:postJson(e.url,e.secret,s,n)}
1
+ import{createHmac as l}from"node:crypto";const c=5e3,f=4096;export async function postJson(e,s,n,o=fetch){let r;try{r=new URL(e)}catch{return{ok:!1,status:"failed",error:`invalid url: ${e}`}}if(r.protocol!=="http:"&&r.protocol!=="https:")return{ok:!1,status:"failed",error:`unsupported protocol: ${r.protocol}`};const u=JSON.stringify(n),i={"content-type":"application/json","user-agent":"weave-daemon"};s&&(i["x-weave-signature"]=`sha256=${l("sha256",s).update(u).digest("hex")}`);try{const t=await o(r,{method:"POST",headers:i,body:u,signal:AbortSignal.timeout(c)}),a=(await t.text()).slice(0,f);return t.ok?{ok:!0,status:"succeeded",output:a||`HTTP ${t.status}`}:{ok:!1,status:"failed",error:`HTTP ${t.status}`,output:a}}catch(t){const a=t instanceof Error&&(t.name==="TimeoutError"||t.name==="AbortError");return{ok:!1,status:a?"timeout":"failed",error:a?`webhook timed out after ${c}ms`:String(t)}}}export async function runWebhook(e,s,n=fetch){const o=e.handler;return o.type!=="webhook"?{ok:!1,status:"failed",error:`rule ${e.id} is not a webhook handler`}:postJson(o.url,o.secret,s,n)}
@@ -1,2 +1,2 @@
1
- import{spawn as k}from"node:child_process";const L=3e5,y=32*1024,E=2e3;export class HeadlessRunner{spawnImpl;killImpl;active=new Set;livePids=new Map;constructor(t={}){this.spawnImpl=t.spawnImpl??k,this.killImpl=t.killImpl??defaultKill}isBusy(t){return this.active.has(t)}killAll(){let t=0;for(const e of this.livePids.values())try{this.killImpl(e),t++}catch{}return this.livePids.clear(),t}run(t){if(this.active.has(t.sessionId))return!1;this.active.add(t.sessionId);const e={settled:!1};try{this.watch(t,e)}catch(n){this.settle(t,e,{status:"failed",output:null,error:P(n)})}return!0}watch(t,e){const n=t.timeoutMs??L,a=t.spec.promptStdin===!0,f=t.argsOf?t.argsOf(t.sessionId):t.spec.args(t.sessionId,a?"":t.prompt),d=a&&process.platform==="win32"&&!/[\s"\\/]/.test(t.bin),T=(t.detached??!0)&&!d,m={cwd:t.cwd,detached:T,windowsHide:!0,shell:d,stdio:[a?"pipe":"ignore","pipe","pipe"],env:(()=>{const s={...process.env,WEAVE_HOOK_DISPATCH:"1"};return delete s.CLAUDE_CODE_CHILD_SESSION,s})()},i=d?this.spawnImpl([t.bin,...f].join(" "),[],m):this.spawnImpl(t.bin,f,m);if(i.pid!==void 0&&this.livePids.set(t.sessionId,i.pid),a){i.stdin?.on("error",()=>{});try{i.stdin?.write(t.prompt),i.stdin?.end()}catch{}}const I=[],p=[];let w=0,v=0;const g=(s,o,l)=>{if(o>=y)return o;const c=y-o;return s.push(l.length>c?l.subarray(0,c):l),o+Math.min(l.length,c)},h=()=>Buffer.concat([...I,...p]).toString("utf8"),H=()=>{const s=Buffer.concat(p).toString("utf8");return s.length>E?s.slice(-E):s};i.stdout?.on("data",s=>{w=g(I,w,s)}),i.stderr?.on("data",s=>{v=g(p,v,s)});const u=n>0?setTimeout(()=>{if(i.pid!==void 0)try{this.killImpl(i.pid)}catch{}this.settle(t,e,{status:"timeout",output:h(),error:`Timeout after ${n}ms`})},n):null;i.on("error",s=>{u!==null&&clearTimeout(u),this.settle(t,e,{status:"failed",output:h(),error:P(s)})}),i.on("exit",(s,o)=>{u!==null&&clearTimeout(u);const l=h();if(s===0){this.settle(t,e,{status:"succeeded",output:l,error:null});return}const c=s!==null?`exit ${s}`:`exit signal ${o??"unknown"}`,S=H();this.settle(t,e,{status:"failed",output:l,error:S?`${c}
2
- ${S}`:c})})}settle(t,e,n){if(!e.settled){e.settled=!0,this.active.delete(t.sessionId),this.livePids.delete(t.sessionId);try{t.onSettle(n)}catch{}}}}export function defaultKill(r){if(process.platform==="win32"){try{k("taskkill",["/PID",String(r),"/T","/F"],{windowsHide:!0,stdio:"ignore"}).on("error",()=>{})}catch{}return}try{process.kill(-r,"SIGKILL")}catch{try{process.kill(r,"SIGKILL")}catch{}}}function P(r){return r instanceof Error?r.message:String(r)}
1
+ import{spawn as k}from"node:child_process";const A=3e5,T=32*1024,_=2e3;export class HeadlessRunner{spawnImpl;killImpl;active=new Set;livePids=new Map;constructor(t={}){this.spawnImpl=t.spawnImpl??k,this.killImpl=t.killImpl??defaultKill}isBusy(t){return this.active.has(t)}killAll(){let t=0;for(const e of this.livePids.values())try{this.killImpl(e),t++}catch{}return this.livePids.clear(),t}run(t){if(this.active.has(t.sessionId))return!1;this.active.add(t.sessionId);const e={settled:!1};try{this.watch(t,e)}catch(l){this.settle(t,e,{status:"failed",output:null,error:y(l)})}return!0}watch(t,e){const l=t.timeoutMs??A,a=t.spec.promptStdin===!0,m=t.argsOf?t.argsOf(t.sessionId):t.spec.args(t.sessionId,a?"":t.prompt),h=a&&process.platform==="win32"&&!/[\s"\\/]/.test(t.bin),E=(t.detached??!0)&&!h,p={cwd:t.cwd,detached:E,windowsHide:!0,shell:h,stdio:[a?"pipe":"ignore","pipe","pipe"],env:(()=>{const s={...process.env,WEAVE_HOOK_DISPATCH:"1"};return delete s.CLAUDE_CODE_CHILD_SESSION,s})()},r=h?this.spawnImpl([t.bin,...m].join(" "),[],p):this.spawnImpl(t.bin,m,p);if(r.pid!==void 0&&this.livePids.set(t.sessionId,r.pid),a){r.stdin?.on("error",()=>{});try{r.stdin?.write(t.prompt),r.stdin?.end()}catch{}}const I=[],u=[];let w=0,S=0;const g=(s,n,o)=>{if(n>=T)return n;const c=T-n;return s.push(o.length>c?o.subarray(0,c):o),n+Math.min(o.length,c)},f=()=>Buffer.concat([...I,...u]).toString("utf8"),M=()=>{const s=Buffer.concat(u).toString("utf8");return s.length>_?s.slice(-_):s};r.stdout?.on("data",s=>{w=g(I,w,s)}),r.stderr?.on("data",s=>{S=g(u,S,s)});const d=l>0?setTimeout(()=>{if(r.pid!==void 0)try{this.killImpl(r.pid)}catch{}this.settle(t,e,{status:"timeout",output:f(),error:`Timeout after ${l}ms`})},l):null;r.on("error",s=>{d!==null&&clearTimeout(d),this.settle(t,e,{status:"failed",output:f(),error:y(s)})}),r.on("exit",(s,n)=>{d!==null&&clearTimeout(d);const o=f();if(s===0){this.settle(t,e,{status:"succeeded",output:o,error:null});return}const c=s!==null?`exit ${s}`:`exit signal ${n??"unknown"}`,v=M();this.settle(t,e,{status:"failed",output:o,error:v?`${c}
2
+ ${v}`:c})})}settle(t,e,l){if(!e.settled){e.settled=!0,this.active.delete(t.sessionId),this.livePids.delete(t.sessionId);try{t.onSettle(l)}catch{}}}}export function defaultKill(i){if(process.platform==="win32"){try{k("taskkill",["/PID",String(i),"/T","/F"],{windowsHide:!0,stdio:"ignore"}).on("error",()=>{})}catch{}return}try{process.kill(-i,"SIGKILL")}catch{try{process.kill(i,"SIGKILL")}catch{}}}function y(i){return i instanceof Error?i.message:String(i)}
@@ -1,2 +1,2 @@
1
- import k from"node:net";import{chmodSync as m,mkdirSync as y,readFileSync as S,renameSync as b,writeFileSync as d}from"node:fs";import{dirname as x}from"node:path";export function inboxSocketPathOf(s){return s.startsWith("uds:")?s.slice(4):s}export function deliverViaInboxSocket(s,t,e,o={}){const c=o.platform??process.platform,n=o.timeoutMs??3e3,u=inboxSocketPathOf(t.socket);return s.requiresAuthOn(c)&&!t.token?Promise.reject(new Error(`inbox delivery requires a token on platform "${c}"`)):new Promise((a,l)=>{const p=s.frame({token:t.token,text:e});let f=!1;const h=r=>{f||(f=!0,i.destroy(),l(r))},i=k.connect(u);i.setTimeout(n),i.on("timeout",()=>h(new Error(`inbox socket timeout after ${n}ms`))),i.on("error",r=>h(r)),i.on("connect",()=>{i.write(p,r=>{r?h(r):i.end()})}),i.on("close",()=>{f||(f=!0,a())})})}export const INBOX_TARGETS_FILE="inbox-targets.json";function g(s){try{const t=JSON.parse(S(s,"utf8"));if(typeof t!="object"||t===null)return{};const e={};for(const[o,c]of Object.entries(t)){const n=c;typeof n?.socket!="string"||!n.socket||(e[o]={socket:n.socket,token:typeof n.token=="string"&&n.token?n.token:null})}return e}catch{return{}}}export class InboxSocketRegistry{file;bySession;persisted;constructor(t){this.file=t;const e=t?g(t):{};this.bySession=new Map(Object.entries(e)),this.persisted=JSON.stringify(e)}set(t,e){const o=this.bySession.get(t);if(!e?.socket){o&&(this.bySession.delete(t),this.persist());return}o&&o.socket===e.socket&&o.token===e.token||(this.bySession.set(t,e),this.persist())}get(t){return this.bySession.get(t)}forget(t){this.bySession.delete(t)&&this.persist()}persist(){if(!this.file)return;const t=JSON.stringify(Object.fromEntries(this.bySession));if(t!==this.persisted)try{y(x(this.file),{recursive:!0});const e=`${this.file}.tmp`;d(e,`${t}
2
- `,{encoding:"utf8",mode:384}),b(e,this.file),m(this.file,384),this.persisted=t}catch{}}}
1
+ import a from"node:net";import{chmodSync as y,mkdirSync as d,readFileSync as k,renameSync as S,writeFileSync as b}from"node:fs";import{dirname as x}from"node:path";export function inboxSocketPathOf(s){return s.startsWith("uds:")?s.slice(4):s}export function deliverViaInboxSocket(s,t,e,o={}){const c=o.platform??process.platform,n=o.timeoutMs??3e3,l=inboxSocketPathOf(t.socket);return s.requiresAuthOn(c)&&!t.token?Promise.reject(new Error(`inbox delivery requires a token on platform "${c}"`)):new Promise((p,m)=>{const h=s.frame({token:t.token,text:e});let f=!1;const u=i=>{f||(f=!0,r.destroy(),m(i))},r=a.connect(l);r.setTimeout(n),r.on("timeout",()=>u(new Error(`inbox socket timeout after ${n}ms`))),r.on("error",i=>u(i)),r.on("connect",()=>{r.write(h,i=>{i?u(i):r.end()})}),r.on("close",()=>{f||(f=!0,p())})})}export const INBOX_TARGETS_FILE="inbox-targets.json";function O(s){try{const t=JSON.parse(k(s,"utf8"));if(typeof t!="object"||t===null)return{};const e={};for(const[o,c]of Object.entries(t)){const n=c;typeof n?.socket!="string"||!n.socket||(e[o]={socket:n.socket,token:typeof n.token=="string"&&n.token?n.token:null})}return e}catch{return{}}}export class InboxSocketRegistry{file;bySession;persisted;constructor(t){this.file=t;const e=t?O(t):{};this.bySession=new Map(Object.entries(e)),this.persisted=JSON.stringify(e)}set(t,e){const o=this.bySession.get(t);if(!e?.socket){o&&(this.bySession.delete(t),this.persist());return}o&&o.socket===e.socket&&o.token===e.token||(this.bySession.set(t,e),this.persist())}get(t){return this.bySession.get(t)}forget(t){this.bySession.delete(t)&&this.persist()}persist(){if(!this.file)return;const t=JSON.stringify(Object.fromEntries(this.bySession));if(t!==this.persisted)try{d(x(this.file),{recursive:!0});const e=`${this.file}.tmp`;b(e,`${t}
2
+ `,{encoding:"utf8",mode:384}),S(e,this.file),y(this.file,384),this.persisted=t}catch{}}}
@@ -1,4 +1,4 @@
1
- import{existsSync as I,readdirSync as v,readFileSync as j,renameSync as h,unlinkSync as b,writeFileSync as E}from"node:fs";import{join as d}from"node:path";import{isMainThread as T,parentPort as m,Worker as P,workerData as k}from"node:worker_threads";import{createRuntimeRegistry as x,effortLevelOf as M,frameFacts as O,permissionModeOf as D,startedModelOf as W,switchedModelOf as A}from"@weavecode/harness";import{HARNESS_LIFECYCLE as F,isHarness as g}from"@weavecode/core";import{getLogsDir as R}from"../db/paths.js";import{projectHarnessIds as L}from"../daemon/project-harnesses.js";import{openDatabase as _}from"../db/db.js";import{HookEventRepository as C}from"../repositories/hook-events.js";import{ProjectRepository as N}from"../repositories/projects.js";import{SessionRepository as B}from"../repositories/sessions.js";import{appendOutbox as X}from"./mirror.js";import{isSyntheticSession as H,replaceSyntheticSessions as U}from"./synthetic-sessions.js";export const INBOX_TICK_MS=200,INBOX_CLAIM_SUFFIX=".claim.jsonl",INBOX_FAILED_SUFFIX=".failed.jsonl";const $=5;export function drainInboxOnce(t,n=new Map){const e=d(t.hooksDir,"inbox");let i;try{i=v(e)}catch{return[]}const o=[];for(const c of i)c.endsWith(INBOX_FAILED_SUFFIX)||c.endsWith(".tmp")||c.endsWith(INBOX_CLAIM_SUFFIX)||c.endsWith(".jsonl")&&o.push(c);const r=[];for(const c of i)c.endsWith(INBOX_CLAIM_SUFFIX)&&r.push(...w(t,d(e,c),n));for(const c of o){const a=d(e,`${c.slice(0,-6)}${INBOX_CLAIM_SUFFIX}`);if(!I(a)){try{h(d(e,c),a)}catch{continue}r.push(...w(t,a,n))}}return r}function w(t,n,e){let i;try{i=j(n,"utf8").split(`
2
- `)}catch{return[]}const o=new Map;for(const p of i){const u=p.trim();if(!u)continue;const s=z(u);if(!s)continue;const l=o.get(s.token)??{lines:[],inputs:[],delivered:[],terminals:[],messaging:[]};if(l.lines.push(u),l.project||(l.project=t.projects.getByToken(s.token),o.set(s.token,l)),!l.project||l.project.archivedAt)continue;const y=s.report&&typeof s.report=="object"?t.adapters.find(f=>f.source===s.report.source):void 0;if(!(!y||!s.report.eventType))try{const f=y.normalize(s.report,l.project.id);if(H(f.sessionId))continue;l.inputs.push(f),l.delivered.push(s.report.deliveredTitle??null),l.terminals.push(s.terminalEnv),l.messaging.push(s.messaging)}catch{}}const r=[],c=[];for(const p of o.values())if(!(!p.project||p.inputs.length===0))try{const u=S(t,p.project,p.inputs);for(let s=0;s<p.inputs.length;s++)r.push({eventId:u[s],projectId:p.project.id,input:p.inputs[s],deliveredTitle:p.delivered[s]??null,messaging:p.messaging[s]??null,terminalEnv:p.terminals[s]??null})}catch{c.push(...p.lines)}if(c.length===0){e.delete(n);try{b(n)}catch{}return r}const a=(e.get(n)??0)+1;if(e.set(n,a),a>=$){e.delete(n);try{h(n,n.replace(INBOX_CLAIM_SUFFIX,INBOX_FAILED_SUFFIX))}catch{}return r}try{E(n,c.join(`
1
+ import{existsSync as v,readdirSync as I,readFileSync as w,renameSync as g,unlinkSync as S,writeFileSync as T}from"node:fs";import{join as f}from"node:path";import{isMainThread as E,parentPort as h,Worker as x,workerData as k}from"node:worker_threads";import{createRuntimeRegistry as M,effortLevelOf as O,frameFacts as P,permissionModeOf as D,startedModelOf as A,switchedModelOf as L}from"@weavecode/harness";import{HARNESS_LIFECYCLE as W,isHarness as m}from"@weavecode/core";import{getLogsDir as _}from"../db/paths.js";import{projectHarnessIds as C}from"../daemon/project-harnesses.js";import{openDatabase as F}from"../db/db.js";import{HookEventRepository as R}from"../repositories/hook-events.js";import{ProjectRepository as N}from"../repositories/projects.js";import{SessionRepository as B}from"../repositories/sessions.js";import{appendOutbox as X}from"./mirror.js";import{isSyntheticSession as H,replaceSyntheticSessions as U}from"./synthetic-sessions.js";export const INBOX_TICK_MS=200,INBOX_CLAIM_SUFFIX=".claim.jsonl",INBOX_FAILED_SUFFIX=".failed.jsonl";const $=5;export function drainInboxOnce(n,o=new Map){const e=f(n.hooksDir,"inbox");let i;try{i=I(e)}catch{return[]}const s=[];for(const c of i)c.endsWith(INBOX_FAILED_SUFFIX)||c.endsWith(".tmp")||c.endsWith(INBOX_CLAIM_SUFFIX)||c.endsWith(".jsonl")&&s.push(c);const r=[];for(const c of i)c.endsWith(INBOX_CLAIM_SUFFIX)&&r.push(...j(n,f(e,c),o));for(const c of s){const p=f(e,`${c.slice(0,-6)}${INBOX_CLAIM_SUFFIX}`);if(!v(p)){try{g(f(e,c),p)}catch{continue}r.push(...j(n,p,o))}}return r}function j(n,o,e){let i;try{i=w(o,"utf8").split(`
2
+ `)}catch{return[]}const s=new Map;for(const u of i){const a=u.trim();if(!a)continue;const t=z(a);if(!t)continue;const l=s.get(t.token)??{lines:[],inputs:[],delivered:[],terminals:[],messaging:[]};if(l.lines.push(a),l.project||(l.project=n.projects.getByToken(t.token),s.set(t.token,l)),!l.project||l.project.archivedAt)continue;const y=t.report&&typeof t.report=="object"?n.adapters.find(d=>d.source===t.report.source):void 0;if(!(!y||!t.report.eventType))try{const d=y.normalize(t.report,l.project.id);if(H(d.sessionId))continue;l.inputs.push(d),l.delivered.push(t.report.deliveredTitle??null),l.terminals.push(t.terminalEnv),l.messaging.push(t.messaging)}catch{}}const r=[],c=[];for(const u of s.values())if(!(!u.project||u.inputs.length===0))try{const a=b(n,u.project,u.inputs);for(let t=0;t<u.inputs.length;t++)r.push({eventId:a[t],projectId:u.project.id,input:u.inputs[t],deliveredTitle:u.delivered[t]??null,messaging:u.messaging[t]??null,terminalEnv:u.terminals[t]??null})}catch{c.push(...u.lines)}if(c.length===0){e.delete(o);try{S(o)}catch{}return r}const p=(e.get(o)??0)+1;if(e.set(o,p),p>=$){e.delete(o);try{g(o,o.replace(INBOX_CLAIM_SUFFIX,INBOX_FAILED_SUFFIX))}catch{}return r}try{T(o,c.join(`
3
3
  `)+`
4
- `)}catch{}return r}function S(t,n,e){const i=t.hookEvents.insertMany(e),o=new Map;for(const r of e){if(!r.sessionId)continue;const c=o.get(r.sessionId),a=r.createdAt;(!o.has(r.sessionId)||a&&(!c||a>c))&&o.set(r.sessionId,a)}for(const[r,c]of o)t.hookSessions.touch(r,n.id,c);return i}export const LOGS_TICK_MS=1e3;export async function pollLogsOnce(t){if(t.sources.length===0)return[];const n=new Map;for(const i of t.projects.list()){const o=await L(i.path);t.sources.some(r=>o.includes(r.harness))&&n.set(i.path,i)}if(n.size===0)return[];const e=[];for(const i of t.sources){const o=t.adapters.find(a=>a.source===i.harness);if(!o)continue;let r;try{r=await i.poll({stateDir:d(t.logsDir,i.harness),cwdWhitelist:[...n.keys()]})}catch{continue}const c=new Map;for(const a of r){const p=a.report.cwd?n.get(a.report.cwd):void 0;if(p)try{const u=o.normalize(a.report,p.id);u.createdAt=a.at;const s=c.get(p);s?s.push(u):c.set(p,[u])}catch{}}for(const[a,p]of c)try{const u=S(t,a,p);for(let s=0;s<p.length;s++)e.push({eventId:u[s],projectId:a.id,input:p[s]})}catch(u){console.error("[weave] log ingest failed:",u)}}return e}function z(t){try{const n=JSON.parse(t);if(!n||typeof n.token!="string"||!n.token||!n.report||typeof n.report!="object")return null;const e=n.messaging?.socket,i=typeof e=="string"&&e?{socket:e,token:typeof n.messaging?.token=="string"?n.messaging.token:null}:null;return{token:n.token,report:n.report,messaging:i,terminalEnv:K(n.terminal)}}catch{return null}}function K(t){if(typeof t!="object"||t===null)return null;const n={};for(const[e,i]of Object.entries(t))typeof i=="string"&&i&&(n[e]=i);return Object.keys(n).length>0?n:null}export function unparkFailedInbox(t){const n=d(t,"inbox");let e;try{e=v(n)}catch{return 0}let i=0;for(const o of e){if(!o.endsWith(INBOX_FAILED_SUFFIX))continue;const r=d(n,`${o.slice(0,-INBOX_FAILED_SUFFIX.length)}${INBOX_CLAIM_SUFFIX}`);if(!I(r))try{h(d(n,o),r),i++}catch{}}return i}export function handleIngestedRecords(t,n){for(const e of n){const i=t.projects.getById(e.projectId);if(!i)continue;t.dashboardRate?.record();let o=null;try{o=JSON.parse(e.input.payload)}catch{o=null}if(t.bus?.emit({kind:"event.ingested",eventId:e.eventId,projectId:i.id,sessionId:e.input.sessionId??null,eventType:e.input.eventType,...O(o),at:e.input.createdAt??new Date().toISOString()}),e.input.sessionId){t.questionTracker?.onEvent({sessionId:e.input.sessionId,source:e.input.source,payload:o}),t.sideQuestions?.onEvent({sessionId:e.input.sessionId,source:e.input.source,eventType:e.input.eventType,payload:o,eventId:e.eventId}),t.watchEngine?.onEvent({sessionId:e.input.sessionId,eventType:e.input.eventType,source:e.input.source}),t.orchestrationEngine?.onEvent({sessionId:e.input.sessionId,eventType:e.input.eventType,source:e.input.source}),e.messaging&&t.messagePipe?.noteInboxSocket?.(e.input.sessionId,e.messaging),t.sessionProbe?.noteTranscript(e.input.sessionId,o?.transcriptPath??null);const r=A(e.input.eventType,o?.raw);r&&t.sessionProbe?.noteModel?.(e.input.sessionId,r.to);const c=W(e.input.eventType,o?.raw);c&&t.sessionProbe?.sessionStarted?.(e.input.sessionId,c.model);const a=M(o?.raw);a&&t.sessionProbe?.noteEffort?.(e.input.sessionId,a);const p=D(o?.raw);if(p&&t.sessionProbe?.noteMode?.(e.input.sessionId,p),e.terminalEnv||g(e.input.source)){const s=e.input.source;g(s)&&t.paneEnvSource?.(s)==="launch"?t.messagePipe?.claimPendingOrigin?.(e.input.sessionId,s,e.projectId):e.terminalEnv&&t.messagePipe?.notePaneEnv?.(e.input.sessionId,e.terminalEnv)}if(e.input.eventType==="UserPromptSubmit"){const s=t.messagePipe?.onSessionPrompt?.(e.input.sessionId,J(o)??"",e.eventId)??[];s.length>0&&t.uploads?.linkToEvent(e.eventId,s)}else t.messagePipe?.noteActivity?.(e.input.sessionId);const u=g(e.input.source)?F[e.input.source].sessionExit:null;u!==null&&e.input.eventType===u&&(t.messagePipe?.sessionExited?.(e.input.sessionId),t.terminalTopologyKick?.()),t.messagePipe?.hasQueued(e.input.sessionId)&&t.messagePipe.flushSession(e.input.sessionId)}t.dispatcher&&t.dispatcher.onIngest({eventId:e.eventId,project:i,sessionId:e.input.sessionId??null,payload:o??{eventType:e.input.eventType,toolName:null,toolInput:null,toolResponse:null,cwd:null,transcriptPath:null,raw:null},source:e.input.source,deliveredTitle:e.deliveredTitle??null}).then(r=>{r.deferred&&e.input.sessionId&&X(t.hooksDir,i.token,[{sessionId:e.input.sessionId,text:r.deferred}])}).catch(()=>{})}}function J(t){const n=t?.raw;return typeof n?.prompt=="string"&&n.prompt?n.prompt:null}export function startInboxWorker(t){return new P(new URL(import.meta.url),{workerData:{inboxWorker:!0,...t}})}if(!T&&k?.inboxWorker===!0){const t=k,n=_(t.dbPath),e=x(),i=new N(n),o={hooksDir:t.hooksDir,projects:i,hookEvents:new C(n),hookSessions:new B(n),adapters:e.byCapability("events").flatMap(s=>s.events??[])};m?.on("message",s=>{s?.type==="synthetic-sessions"&&Array.isArray(s.ids)&&U(s.ids)});const r=new Map,c=()=>{try{const s=drainInboxOnce(o,r);s.length>0&&m?.postMessage(s)}catch(s){console.error("[weave] inbox drain failed:",s)}};c(),setInterval(c,t.tickMs??INBOX_TICK_MS);const a={projects:i,hookEvents:o.hookEvents,hookSessions:o.hookSessions,adapters:o.adapters,logsDir:R(),sources:e.byCapability("logs").flatMap(s=>s.logs??[])};let p=!1;const u=()=>{p||(p=!0,pollLogsOnce(a).then(s=>{s.length>0&&m?.postMessage(s)}).catch(s=>console.error("[weave] log poll failed:",s)).finally(()=>{p=!1}))};a.sources.length>0&&(u(),setInterval(u,LOGS_TICK_MS))}
4
+ `)}catch{}return r}function b(n,o,e){const i=n.hookEvents.insertMany(e),s=new Map;for(const r of e){if(!r.sessionId)continue;const c=s.get(r.sessionId),p=r.createdAt;(!s.has(r.sessionId)||p&&(!c||p>c))&&s.set(r.sessionId,p)}for(const[r,c]of s)n.hookSessions.touch(r,o.id,c);return i}export const LOGS_TICK_MS=1e3;export async function pollLogsOnce(n){if(n.sources.length===0)return[];const o=new Map;for(const i of n.projects.list()){const s=await C(i.path);n.sources.some(r=>s.includes(r.harness))&&o.set(i.path,i)}if(o.size===0)return[];const e=[];for(const i of n.sources){const s=n.adapters.find(p=>p.source===i.harness);if(!s)continue;let r;try{r=await i.poll({stateDir:f(n.logsDir,i.harness),cwdWhitelist:[...o.keys()]})}catch{continue}const c=new Map;for(const p of r){const u=p.report.cwd?o.get(p.report.cwd):void 0;if(u)try{const a=s.normalize(p.report,u.id);a.createdAt=p.at;const t=c.get(u);t?t.push(a):c.set(u,[a])}catch{}}for(const[p,u]of c)try{const a=b(n,p,u);for(let t=0;t<u.length;t++)e.push({eventId:a[t],projectId:p.id,input:u[t]})}catch(a){console.error("[weave] log ingest failed:",a)}}return e}function z(n){try{const o=JSON.parse(n);if(!o||typeof o.token!="string"||!o.token||!o.report||typeof o.report!="object")return null;const e=o.messaging?.socket,i=typeof e=="string"&&e?{socket:e,token:typeof o.messaging?.token=="string"?o.messaging.token:null}:null;return{token:o.token,report:o.report,messaging:i,terminalEnv:K(o.terminal)}}catch{return null}}function K(n){if(typeof n!="object"||n===null)return null;const o={};for(const[e,i]of Object.entries(n))typeof i=="string"&&i&&(o[e]=i);return Object.keys(o).length>0?o:null}export function unparkFailedInbox(n){const o=f(n,"inbox");let e;try{e=I(o)}catch{return 0}let i=0;for(const s of e){if(!s.endsWith(INBOX_FAILED_SUFFIX))continue;const r=f(o,`${s.slice(0,-INBOX_FAILED_SUFFIX.length)}${INBOX_CLAIM_SUFFIX}`);if(!v(r))try{g(f(o,s),r),i++}catch{}}return i}export function handleIngestedRecords(n,o){for(const e of o){const i=n.projects.getById(e.projectId);if(!i)continue;n.dashboardRate?.record();let s=null;try{s=JSON.parse(e.input.payload)}catch{s=null}if(n.bus?.emit({kind:"event.ingested",eventId:e.eventId,projectId:i.id,sessionId:e.input.sessionId??null,eventType:e.input.eventType,...P(s),at:e.input.createdAt??new Date().toISOString()}),e.input.sessionId){n.questionTracker?.onEvent({sessionId:e.input.sessionId,source:e.input.source,payload:s}),n.sideQuestions?.onEvent({sessionId:e.input.sessionId,source:e.input.source,eventType:e.input.eventType,payload:s,eventId:e.eventId}),n.watchEngine?.onEvent({sessionId:e.input.sessionId,eventType:e.input.eventType,source:e.input.source}),n.orchestrationEngine?.onEvent({sessionId:e.input.sessionId,eventType:e.input.eventType,source:e.input.source}),e.messaging&&n.messagePipe?.noteInboxSocket?.(e.input.sessionId,e.messaging),n.sessionProbe?.noteTranscript(e.input.sessionId,s?.transcriptPath??null);const r=L(e.input.eventType,s?.raw);r&&n.sessionProbe?.noteModel?.(e.input.sessionId,r.to);const c=A(e.input.eventType,s?.raw);c&&n.sessionProbe?.sessionStarted?.(e.input.sessionId,c.model);const p=O(s?.raw);p&&n.sessionProbe?.noteEffort?.(e.input.sessionId,p);const u=D(s?.raw);if(u&&n.sessionProbe?.noteMode?.(e.input.sessionId,u),e.terminalEnv||m(e.input.source)){const t=e.input.source;m(t)&&n.paneEnvSource?.(t)==="launch"?n.messagePipe?.claimPendingOrigin?.(e.input.sessionId,t,e.projectId):e.terminalEnv&&n.messagePipe?.notePaneEnv?.(e.input.sessionId,e.terminalEnv)}if(e.input.eventType==="UserPromptSubmit"){const t=n.messagePipe?.onSessionPrompt?.(e.input.sessionId,J(s)??"",e.eventId)??[];t.length>0&&n.uploads?.linkToEvent(e.eventId,t)}else n.messagePipe?.noteActivity?.(e.input.sessionId);const a=m(e.input.source)?W[e.input.source].sessionExit:null;a!==null&&e.input.eventType===a&&(n.messagePipe?.sessionExited?.(e.input.sessionId),n.terminalTopologyKick?.()),n.messagePipe?.hasQueued(e.input.sessionId)&&n.messagePipe.flushSession(e.input.sessionId)}n.dispatcher&&n.dispatcher.onIngest({eventId:e.eventId,project:i,sessionId:e.input.sessionId??null,payload:s??{eventType:e.input.eventType,toolName:null,toolInput:null,toolResponse:null,cwd:null,transcriptPath:null,raw:null},source:e.input.source,deliveredTitle:e.deliveredTitle??null}).then(r=>{r.deferred&&e.input.sessionId&&X(n.hooksDir,i.token,[{sessionId:e.input.sessionId,text:r.deferred}])}).catch(()=>{})}}function J(n){const o=n?.raw;return typeof o?.prompt=="string"&&o.prompt?o.prompt:null}export function startInboxWorker(n){return new x(new URL(import.meta.url),{workerData:{inboxWorker:!0,...n}})}if(!E&&k?.inboxWorker===!0){const n=k,o=F(n.dbPath),e=M(),i=new N(o),s={hooksDir:n.hooksDir,projects:i,hookEvents:new R(o),hookSessions:new B(o),adapters:e.byCapability("events").flatMap(t=>t.events??[])};h?.on("message",t=>{t?.type==="synthetic-sessions"&&Array.isArray(t.ids)&&U(t.ids)});const r=new Map,c=()=>{try{const t=drainInboxOnce(s,r);t.length>0&&h?.postMessage(t)}catch(t){console.error("[weave] inbox drain failed:",t)}};c(),setInterval(c,n.tickMs??INBOX_TICK_MS);const p={projects:i,hookEvents:s.hookEvents,hookSessions:s.hookSessions,adapters:s.adapters,logsDir:_(),sources:e.byCapability("logs").flatMap(t=>t.logs??[])};let u=!1;const a=()=>{u||(u=!0,pollLogsOnce(p).then(t=>{t.length>0&&h?.postMessage(t)}).catch(t=>console.error("[weave] log poll failed:",t)).finally(()=>{u=!1}))};p.sources.length>0&&(a(),setInterval(a,LOGS_TICK_MS))}
@@ -1 +1 @@
1
- import i from"node:path";export const DISPATCH_MARKER="<!--weave-dispatch-->";const c=t=>process.platform==="win32"?t.toLowerCase():t;export function normalizePosix(t){return t.replace(/\\/g,"/")}function p(t){return/[.+^${}()|[\]\\]/.test(t)?`\\${t}`:t}const s=new Map;export function globToRegex(t){const o=s.get(t);if(o)return o;let n="";for(let r=0;r<t.length;r++){const l=t[r];l==="*"?t[r+1]==="*"?(r++,t[r+1]==="/"?(r++,n+="(?:.*/)?"):n+=".*"):n+="[^/]*":l==="?"?n+="[^/]":n+=p(l)}const e=new RegExp(`^${n}$`,"i");return s.set(t,e),e}export function matchGlob(t,o){return globToRegex(o).test(normalizePosix(t))}export function extractFilePath(t){if(typeof t!="object"||t===null)return null;const o=t;for(const n of["file_path","notebook_path","filePath"]){const e=o[n];if(typeof e=="string"&&e.length>0)return e}return null}function u(t,o){const n=c(normalizePosix(t)),e=c(normalizePosix(o).replace(/\/+$/,""));return n===e||n.startsWith(`${e}/`)}export function isCrossProjectPath(t,o,n){const e=c(normalizePosix(o));return u(t,o)?!1:n.some(r=>c(normalizePosix(r))!==e&&u(t,r))}export function renderTemplate(t,o){return t.replace(/\{(\w+)\}/g,(n,e)=>{const r=o[e];return r==null?n:String(r)})}export function templateVars(t){return{event:t.event,tool:t.tool,file:t.filePath?normalizePosix(t.filePath):null,cwd:t.cwd?normalizePosix(t.cwd):null,session:t.session,project:t.project,rule:t.rule}}export function matchesAnyGlob(t,o){return o.some(n=>matchGlob(t,n))}export function projectLabel(t){return i.basename(normalizePosix(t).replace(/\/+$/,""))||t}
1
+ import f from"node:path";export const DISPATCH_MARKER="<!--weave-dispatch-->";const s=e=>process.platform==="win32"?e.toLowerCase():e;export function normalizePosix(e){return e.replace(/\\/g,"/")}function a(e){return/[.+^${}()|[\]\\]/.test(e)?`\\${e}`:e}const l=new Map;export function globToRegex(e){const r=l.get(e);if(r)return r;let t="";for(let n=0;n<e.length;n++){const c=e[n];c==="*"?e[n+1]==="*"?(n++,e[n+1]==="/"?(n++,t+="(?:.*/)?"):t+=".*"):t+="[^/]*":c==="?"?t+="[^/]":t+=a(c)}const o=new RegExp(`^${t}$`,"i");return l.set(e,o),o}export function matchGlob(e,r){return globToRegex(r).test(normalizePosix(e))}export function extractFilePath(e){if(typeof e!="object"||e===null)return null;const r=e;for(const t of["file_path","notebook_path","filePath"]){const o=r[t];if(typeof o=="string"&&o.length>0)return o}return null}function i(e,r){const t=s(normalizePosix(e)),o=s(normalizePosix(r).replace(/\/+$/,""));return t===o||t.startsWith(`${o}/`)}export function isCrossProjectPath(e,r,t){const o=s(normalizePosix(r));return i(e,r)?!1:t.some(n=>s(normalizePosix(n))!==o&&i(e,n))}export function renderTemplate(e,r){return e.replace(/\{(\w+)\}/g,(t,o)=>{const n=r[o];return n==null?t:String(n)})}export function templateVars(e){return{event:e.event,tool:e.tool,file:e.filePath?normalizePosix(e.filePath):null,cwd:e.cwd?normalizePosix(e.cwd):null,session:e.session,project:e.project,rule:e.rule}}export function matchesAnyGlob(e,r){return r.some(t=>matchGlob(e,t))}export function projectLabel(e){return f.basename(normalizePosix(e).replace(/\/+$/,""))||e}
@@ -1,5 +1,5 @@
1
- import{randomUUID as K}from"node:crypto";import{chmodSync as S,mkdirSync as v,readFileSync as w,renameSync as O,writeFileSync as E}from"node:fs";import{dirname as b,join as g}from"node:path";import{isHarness as k}from"@weavecode/core";import{commandModeAt as Q,turnOutputOf as R}from"@weavecode/harness";import{isImageMediaType as D}from"../repositories/uploads.js";import{commandsSurfaceFor as N,messagingSurfaceFor as W}from"../surfaces.js";import{pidAliveOf as _}from"../daemon/claude-liveness.js";import{combinedLivenessOf as T}from"../daemon/liveness.js";import{HeadlessRunner as J}from"./headless-runner.js";import{hooksRoot as G}from"./mirror.js";import{INBOX_TARGETS_FILE as L,InboxSocketRegistry as H,deliverViaInboxSocket as $}from"./inbox-socket.js";import{AckGate as V}from"./delivery/ack-gate.js";import{ANSWER_ATOM as A,ANSWER_ATOM_GAP_MS as Y,ANSWER_TEXT as U,CTRL_B as X,CTRL_C_KITTY as z,ENTER as Z,ESC as ss,ESC_KITTY as es,MODEL_NAME as ts,SHIFT_TAB as is,effortCommand as ns,effortLevelsOf as rs,locateTerminalPane as as,modelCommand as os,sessionKeysTarget as ds}from"./delivery/keys.js";import{hasImages as us,settleDelivered as P,spawnOnce as hs,wireTextOf as ls}from"./delivery/channels.js";import{deliverHeadless as cs,deliverInject as ms,resolveChannel as fs}from"./delivery/send.js";import{appendQueueEntry as ps,failOffline as gs,failQueuedOffline as ys,sessionJudgedDead as ks}from"./delivery/queue.js";import{runRelay as Is}from"./delivery/relay.js";import{listInflightCounts as Ss,listVisible as vs,sessionTerminals as ws}from"./delivery/views.js";import{readPromptbox as y,removePromptboxBySession as Os,removePromptboxEntries as p,scanQueuedSessionIds as Es}from"./promptbox.js";const bs=1e3,Ds=6e4,Ts=3e4,As=9e4,Ps=5e3,xs=8,Cs=12e4,js=1200,Ms=/interrupted/i,Fs=/· done/,Bs=12,qs=[es,ss,X],Ks=600,Qs=250,Rs=5,Ns=200,x="pane-envs.json",C="pending-origins.json",j=15*6e4;function Ws(f){try{const s=JSON.parse(w(f,"utf8"));if(!Array.isArray(s))return[];const e=[];for(const t of s){if(typeof t!="object"||t===null)continue;const i=t;if(!k(i.harness)||typeof i.projectId!="number"||typeof i.env!="object"||i.env===null||typeof i.at!="string")continue;const n={};for(const[r,d]of Object.entries(i.env))typeof d=="string"&&d&&(n[r]=d);Object.keys(n).length!==0&&e.push({harness:i.harness,projectId:i.projectId,env:n,at:i.at})}return e.filter(t=>Date.now()-Date.parse(t.at)<j)}catch{return[]}}function _s(f){try{const s=JSON.parse(w(f,"utf8"));if(typeof s!="object"||s===null)return{};const e={};for(const[t,i]of Object.entries(s)){if(typeof i!="object"||i===null)continue;const n={};for(const[r,d]of Object.entries(i))typeof d=="string"&&d&&(n[r]=d);Object.keys(n).length>0&&(e[t]=n)}return e}catch{return{}}}const m=f=>new Promise(s=>setTimeout(s,f)),M=300,F=1500,Js=1e3,Gs=12e4;export class MessageDeliverer{deps;headless;hooksDir;sideAnswerStore;memory=new Map;queuedSessions;inboxSockets;paneEnvs;revokedPaneEnvs=new Set;paneEnvConflicts=new Map;persistedPaneEnvs;pendingOrigins;persistedPendingOrigins;flushScheduled=new Set;flushing=new Map;stalled=new Map;awaitingAck=new Map;dismissedIds=new Set;gate;constructor(s){this.deps=s,this.headless=s.headless??new J({spawnImpl:s.spawnImpl,killImpl:s.killImpl}),this.hooksDir=s.hooksDir??G(),this.sideAnswerStore=s.sideAnswerStore,this.inboxSockets=new H(g(this.hooksDir,L));const e=_s(g(this.hooksDir,x));this.paneEnvs=new Map(Object.entries(e)),this.persistedPaneEnvs=JSON.stringify(e),this.pendingOrigins=Ws(g(this.hooksDir,C)),this.persistedPendingOrigins=JSON.stringify(this.pendingOrigins),this.queuedSessions=Es(this.hooksDir),this.gate=new V({awaitingAck:this.awaitingAck,stalled:this.stalled,memory:this.memory},{ackStallMs:s.ackStallMs??Ts,ackStallReleaseMs:s.ackStallReleaseMs??As,commandAckGraceMs:s.commandAckGraceMs??Ps},{emit:t=>this.bus(t)},(t,i)=>this.commandModeOf(t,i)!==null),this.gate.onAutoRelease=t=>this.scheduleFlushContinuation(t)}async send(s){const e=this.deps.sessions.getBySessionId(s.toSessionId);if(!e)return{ok:!1,status:404,error:"Session not found"};const t=this.surfaceOfSession(s.toSessionId);if(!t)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};const i=s.attachments?[...s.attachments]:[];if(i.length>0){if(!t.attach)return{ok:!1,status:409,error:"This harness cannot receive attachments"};if(i.some(l=>D(l.mediaType))&&!t.attach.kinds.includes("image"))return{ok:!1,status:409,error:"This harness cannot receive images"};if(i.some(l=>!D(l.mediaType))&&!t.attach.kinds.includes("file"))return{ok:!1,status:409,error:"This harness cannot receive file attachments"}}const n=this.resolveChannel(s.mode,s.toSessionId,t);if(typeof n!="string")return{ok:!1,status:409,error:n.reason};if(e.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const r=this.deps.projects.getById(e.projectId);if(!r)return{ok:!1,status:404,error:"Project not found"};if(n==="headless"&&this.headless.isBusy(s.toSessionId))return{ok:!1,status:409,error:"Session already has a running run"};const d={fromLabel:s.fromKind==="session"?`session ${s.fromSessionId??"unknown"}`:s.fromKind,at:new Date().toISOString(),mode:n},a={id:K(),sessionId:s.toSessionId,text:s.text,...i.length>0?{attachments:i}:{},mode:s.mode,oneWay:s.oneWay===!0,...s.forceTerminal===!0?{forceTerminal:!0}:{},channel:n,status:"pending",at:d.at},o=n==="prompt"&&this.blockedAhead(a.sessionId);o&&(this.queueEntry(a,r.token),this.scheduleFlushContinuation(a.sessionId));const h=o?{ok:!0,messageId:a.id,status:"pending",message:a}:n==="inject"?this.deliverInject(a,r.token,d,t):n==="headless"?this.deliverHeadless(a,r.path,d,t):await this.deliverPrompt(a,e,r,t);return this.bus({kind:"message.created",messageId:a.id,sessionId:a.sessionId,mode:a.mode,at:a.at}),h}getMessage(s){return this.memory.get(s)??null}listVisible(s){return vs(this.deps,this.hooksDir,this.memory,s,this.deps.visibleTtlMs??Ds,e=>this.commandModeOf(s,e)!==null)}hasQueued(s){return this.queuedSessions.has(s)}listInflightCounts(){return Ss(this.hooksDir,this.memory)}hasTerminalChannel(){return this.terminalChannel()!=null}scheduleFlushContinuation(s){this.flushScheduled.has(s)||(this.flushScheduled.add(s),setTimeout(()=>{this.flushScheduled.delete(s),this.flushSession(s)},this.deps.flushGapMs??bs).unref?.())}ackGateOpen(s){return this.gate.open(s)}blockedAhead(s){return this.ackGateOpen(s)?this.queuedSessions.has(s)||this.flushing.has(s):!0}noteInboxSocket(s,e){this.inboxSockets.set(s,e)}async awaitInboxReady(s,e){const t=this.surfaceOfSession(s)?.promptInbox??null;if(!t)return!1;const i=()=>{const r=this.inboxSockets.get(s);return!!r&&(!t.requiresAuthOn(process.platform)||!!r.token)},n=Date.now()+e;for(;!i();){if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,Qs))}return!0}lastTurnOutput(s){const e=this.deps.hookEvents.listBySession(s,Rs);for(let t=e.length-1;t>=0;t--){const i=e[t];let n=null;try{n=JSON.parse(i.payload)}catch{continue}const r=R(n?.raw);if(r)return{output:r,at:i.createdAt}}return null}notePaneEnv(s,e){const t=JSON.stringify(e);for(const[i,n]of this.paneEnvs){if(i===s||JSON.stringify(n)!==t)continue;const r=this.deps.sessions.getBySessionId(i)?.lastSeenAt;if((r?Date.now()-Date.parse(r):Number.POSITIVE_INFINITY)<Cs){this.paneEnvs.delete(s),this.paneEnvConflicts.set(s,i),this.persistPaneEnvs();return}this.paneEnvs.delete(i),this.revokedPaneEnvs.add(i)}this.paneEnvConflicts.delete(s),this.paneEnvs.set(s,e),this.revokedPaneEnvs.delete(s),this.persistPaneEnvs()}paneEnvConflictOf(s){return this.paneEnvConflicts.get(s)??null}notePendingOrigin(s){this.pendingOrigins=this.pendingOrigins.filter(e=>Date.now()-Date.parse(e.at)<j),this.pendingOrigins.push({...s,at:new Date().toISOString()}),this.persistPendingOrigins()}claimPendingOrigin(s,e,t){const i=this.pendingOrigins.findIndex(r=>r.harness===e&&r.projectId===t);if(i<0)return;const[n]=this.pendingOrigins.splice(i,1);this.notePaneEnv(s,n.env),this.persistPendingOrigins()}persistPaneEnvs(){const s=JSON.stringify(Object.fromEntries(this.paneEnvs));if(s===this.persistedPaneEnvs)return;const e=g(this.hooksDir,x);try{v(b(e),{recursive:!0});const t=`${e}.tmp`;E(t,`${s}
2
- `,{encoding:"utf8",mode:384}),O(t,e),S(e,384),this.persistedPaneEnvs=s}catch{}}persistPendingOrigins(){const s=JSON.stringify(this.pendingOrigins);if(s===this.persistedPendingOrigins)return;const e=g(this.hooksDir,C);try{v(b(e),{recursive:!0});const t=`${e}.tmp`;E(t,`${s}
3
- `,{encoding:"utf8",mode:384}),O(t,e),S(e,384),this.persistedPendingOrigins=s}catch{}}sessionExited(s){this.inboxSockets.forget(s),this.paneEnvs.delete(s),this.revokedPaneEnvs.add(s),this.persistPaneEnvs(),this.awaitingAck.delete(s);const e=this.deps.sessions.getBySessionId(s),t=e?.projectId==null?null:this.deps.projects.getById(e.projectId);if(!t)return;const i=y(this.hooksDir,t.token).filter(n=>n.sessionId===s);this.failQueuedOffline(s,i.filter(n=>!this.dismissedIds.has(n.id)))}async sessionTerminals(){return ws(this.deps,this.terminalChannel(),this.paneEnvs,()=>this.persistPaneEnvs(),this.revokedPaneEnvs)}diagnose(s){const e=this.surfaceOfSession(s),t=this.deps.sessions.livenessRowOf(s),i=t?_(t,this.deps.livenessOf?.()??T()):null,n=e?.promptInbox??null,r=this.inboxSockets.get(s),d=n?r?n.requiresAuthOn(process.platform)&&!r.token?{status:"unavailable",reason:"auth-token-required"}:{status:"ready",reason:null}:{status:"unavailable",reason:"no-credentials"}:{status:"unavailable",reason:"no-mechanism"},a=e?.queuedPrompt?{status:"ready",reason:null}:{status:"unavailable",reason:"no-mechanism"},o=e?.prompt?.resolve(s)??null,h=e?.prompt?o?{status:"ready",reason:null}:{status:"unavailable",reason:"no-peer-name"}:{status:"unavailable",reason:"no-mechanism"},l=this.paneEnvs.has(s),u=this.terminalChannel()?l?{status:"ready",reason:null}:this.paneEnvConflicts.has(s)?{status:"unavailable",reason:"pane-env-conflict"}:{status:"unknown",reason:"no-pane-env"}:{status:"unavailable",reason:"no-backend"},c=this.deps.sessions.getBySessionId(s),I=c?.projectId==null?null:this.deps.projects.getById(c.projectId),B=I?y(this.hooksDir,I.token).filter(q=>q.sessionId===s).length:0;return{alive:i,inbox:d,queue:a,relay:h,terminal:u,paneEnvReported:l,pending:B,stalled:this.gate.isStalled(s)}}onSessionPrompt(s,e,t){const i=this.gate.acknowledge(s,e,t,{ackMinText:xs});return this.gate.hitLast&&this.queuedSessions.has(s)&&this.scheduleFlushContinuation(s),i}noteActivity(s){this.gate.noteActivity(s)&&this.queuedSessions.has(s)&&this.scheduleFlushContinuation(s)}armAckWatch(s){this.gate.armAckWatch(s)}armCommandAck(s){this.gate.armCommandAck(s,e=>{this.queuedSessions.has(e)&&this.scheduleFlushContinuation(e)})}stall(s,e,t){this.gate.stall(s,e,t)}async answer(s,e){if(e.length===0||!A.test(e[0])||e.some(i=>!A.test(i)&&!U.test(i)))return{ok:!1,status:400,error:"Invalid answer keys"};const t=await this.sessionKeysTarget(s);if(!t.ok)return t;try{for(const[i,n]of e.entries())i>0&&await m(Y),await t.terminal.sendKeys(t.paneId,n);return{ok:!0}}catch(i){return{ok:!1,status:409,error:i instanceof Error?i.message:String(i)}}}async interrupt(s){const e=await this.sessionKeysTarget(s,"\u51FB\u952E");if(!e.ok)return e;const t=async()=>{try{return await e.terminal.getPaneText?.(e.paneId)??null}catch{return null}},i=d=>{const a=d.split(`
4
- `).slice(-Bs).join(`
5
- `);return Ms.test(a)||Fs.test(a)},n=this.deps.interruptVerifyMs??js;let r=!1;for(const[d,a]of qs.entries()){try{await e.terminal.sendKeys(e.paneId,a)}catch(h){if(d===0)return{ok:!1,status:409,error:h instanceof Error?h.message:String(h)};break}await m(d===0?n:Ks);const o=await t();if(o===null)return{ok:!0,paneId:e.paneId,sent:!0,confirmed:!0};if(i(o)){r=!0;break}}return{ok:!0,paneId:e.paneId,sent:!0,confirmed:r}}async closePane(s){const e=await this.sessionKeysTarget(s,"\u5173\u95ED");if(!e.ok)return e;try{return await e.terminal.closePane(e.paneId),{ok:!0}}catch(t){return{ok:!1,status:409,error:t instanceof Error?t.message:String(t)}}}async cycleMode(s){const e=await this.sessionKeysTarget(s);if(!e.ok)return e;try{return await e.terminal.sendKeys(e.paneId,is),{ok:!0}}catch(t){return{ok:!1,status:409,error:t instanceof Error?t.message:String(t)}}}async pressEnter(s){const e=await this.sessionKeysTarget(s);if(!e.ok)return e;try{return await e.terminal.sendKeys(e.paneId,Z),{ok:!0}}catch(t){return{ok:!1,status:409,error:t instanceof Error?t.message:String(t)}}}async pressCtrlC(s){const e=await this.sessionKeysTarget(s);if(!e.ok)return e;try{return await e.terminal.sendKeys(e.paneId,z),{ok:!0}}catch(t){return{ok:!1,status:409,error:t instanceof Error?t.message:String(t)}}}async setModel(s,e){const t=e.trim();if(!ts.test(t))return{ok:!1,status:400,error:"\u6A21\u578B\u540D\u5F62\u6001\u4E0D\u5408\u6CD5\uFF08\u4E0D\u542B\u7A7A\u767D\u4E0E\u63A7\u5236\u5B57\u7B26\uFF0C\u2264128 \u5B57\u7B26\uFF09"};const i=await this.sessionKeysTarget(s);if(!i.ok)return i;try{return await i.terminal.sendText(i.paneId,os(t)),{ok:!0}}catch(n){return{ok:!1,status:409,error:n instanceof Error?n.message:String(n)}}}async setEffort(s,e){const t=e.trim(),i=await this.sessionKeysTarget(s);if(!i.ok)return i;const n=rs(this.deps.hookEvents,s);if(!n.includes(t))return{ok:!1,status:400,error:`\u601D\u8003\u5F3A\u5EA6\u6863\u4F4D\u4E0D\u5408\u6CD5\uFF08\u53EF\u9009\uFF1A${n.join(" / ")||"\u65E0"}\uFF09`};try{return await i.terminal.sendText(i.paneId,ns(t)),{ok:!0}}catch(r){return{ok:!1,status:409,error:r instanceof Error?r.message:String(r)}}}async askSideQuestion(s,e){if(!this.deps.sessions.getBySessionId(s))return{ok:!1,status:404,error:"Session not found"};const t=this.surfaceOfSession(s),i=t?.sideQuestion??null;if(!i)return{ok:!1,status:409,error:t?.unsupportedReasons?.sideQuestion??"\u8FD9\u4E2A harness \u6CA1\u6709\u65C1\u8DEF\u4F1A\u8BDD\u901A\u9053"};const n=i.validate(e);if(!n.ok)return{ok:!1,status:400,error:n.error};if(i.prerequisite&&this.deps.sessions.hasRunOf(s)!==!0)return{ok:!1,status:409,error:i.prerequisite};const r=await this.sessionKeysTarget(s,"\u53D1\u8D77\u65C1\u8DEF\u4F1A\u8BDD");if(!r.ok)return r;try{return i.screen?(this.pollScreenAnswer(s,r.terminal,r.paneId,i,n.text),{ok:!0,question:n.text}):(await r.terminal.sendText(r.paneId,i.command(n.text)),{ok:!0,question:n.text})}catch(d){return{ok:!1,status:409,error:d instanceof Error?d.message:String(d)}}}pollScreenAnswer(s,e,t,i,n){const r=i.screen,d=async()=>await e.getPaneText?.(t).catch(()=>null)??null;(async()=>{const a=await d()??"";await e.sendKeys(t,r.openKeys).catch(()=>{}),await m(M),await e.sendKeys(t,r.submitKey).catch(()=>{}),await m(F);let o=await d();if((!o||!r.panelOpen(o))&&(await e.sendKeys(t,r.submitKey).catch(()=>{}),await m(F),o=await d(),!o||!r.panelOpen(o)))return;await e.sendText(t,n).catch(()=>{}),await m(M),await e.sendKeys(t,r.submitKey).catch(()=>{});const h=Date.now()+Gs;let l=null;for(;Date.now()<h;){if(await m(Js),o=await d(),o==null)return;const c=r.extractAnswer(n,a,o);if(c.done){l=c.answer;break}}l!=null&&(this.sideAnswerStore?.answerById(s,n,l),this.bus({kind:"sideQuestion.answered",sessionId:s,at:new Date().toISOString()}));const u=await d();u&&r.panelOpen(u)&&await e.sendKeys(t,r.closeKey).catch(()=>{})})()}async sessionKeysTarget(s,e="\u51FB\u952E"){return ds(this.keysDeps(),s,e)}busSafe(){return{emit:s=>this.bus(s)}}channelDeps(){return{setMemory:s=>this.memory.set(s.id,s),deleteMemory:s=>this.memory.delete(s),awaitAck:(s,e)=>this.gate.await(s,e),commandModeOf:(s,e)=>this.commandModeOf(e,s),armAckWatch:s=>this.gate.armAckWatch(s),armCommandAck:s=>this.gate.armCommandAck(s,e=>{this.queuedSessions.has(e)&&this.scheduleFlushContinuation(e)}),emit:s=>this.bus(s),...this.deps.spawnImpl?{spawnImpl:this.deps.spawnImpl}:{}}}wireTextOfEntry(s){return ls(s,e=>this.surfaceOfSession(e))}hasImagesEntry(s){return us(s)}keysDeps(){return{sessions:this.deps.sessions,projects:this.deps.projects,hookEvents:this.deps.hookEvents,terminalChannel:()=>this.terminalChannel(),terminalPaneFor:(s,e)=>this.terminalPaneFor(s,e),paneEnvConflictOf:s=>this.paneEnvConflictOf(s)}}async resend(s){const e=this.memory.get(s);if(!e)return{ok:!1,status:404,error:"Message not found"};if(!(e.channel==="prompt"&&(e.status==="failed"||e.status==="delivered"&&!e.acked)))return{ok:!1,status:409,error:"Message is not resendable"};const t=this.deps.sessions.getBySessionId(e.sessionId);if(!t)return{ok:!1,status:404,error:"Session not found"};if(t.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const i=this.deps.projects.getById(t.projectId);if(!i)return{ok:!1,status:404,error:"Project not found"};const n=this.surfaceOfSession(e.sessionId);if(!n)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};if(this.gate.clearStall(e.sessionId,s),e.status==="delivered"&&e.via==="terminal"&&this.terminalChannel()){const a=await this.terminalPaneFor(t,i);if(a)return this.memory.set(s,{...e,status:"delivering",stalled:!1,settledAt:null}),this.runTerminalSubmit(s,a.id),this.bus({kind:"message.created",messageId:s,sessionId:e.sessionId,mode:e.mode,at:new Date().toISOString()}),{ok:!0,messageId:s,status:"delivering",message:this.memory.get(s)}}this.memory.delete(s);const r={...e,status:"pending",stalled:!1,acked:!1,settledAt:null,reason:void 0,error:null},d=await this.deliverPrompt(r,t,i,n);return this.bus({kind:"message.created",messageId:r.id,sessionId:r.sessionId,mode:r.mode,at:new Date().toISOString()}),d}dismiss(s,e){const t=this.memory.get(e);if(t){if(t.status==="running")return{ok:!1,status:409,error:"Message is still in flight"};t.status==="delivering"&&this.gate.headOf(t.sessionId)===e&&this.flushing.delete(t.sessionId),this.memory.delete(e),this.gate.clearStall(t.sessionId,e),this.gate.release(t.sessionId,e),this.queuedSessions.has(t.sessionId)&&this.scheduleFlushContinuation(t.sessionId)}else if(!this.dropQueued(s,e))return{ok:!1,status:404,error:"Message not found"};return this.bus({kind:"message.dismissed",messageId:e,sessionId:s,at:new Date().toISOString()}),{ok:!0}}dropQueued(s,e){const t=this.deps.sessions.getBySessionId(s);if(t?.projectId==null)return!1;const i=this.deps.projects.getById(t.projectId);if(!i)return!1;const n=y(this.hooksDir,i.token);if(!n.some(r=>r.id===e&&r.sessionId===s))return!1;for(p(this.hooksDir,i.token,new Set([e])),this.dismissedIds.add(e);this.dismissedIds.size>Ns;){const r=this.dismissedIds.values().next().value;if(r===void 0)break;this.dismissedIds.delete(r)}return n.some(r=>r.sessionId===s&&r.id!==e)||this.queuedSessions.delete(s),!0}async flushSession(s){if(this.stalled.has(s)||this.flushing.has(s)||!this.queuedSessions.has(s))return;const e=Symbol(s);this.flushing.set(s,e);try{await this.flushSessionInner(s)}catch{}finally{this.flushing.get(s)===e&&this.flushing.delete(s)}}async flushSessionInner(s){if(!this.ackGateOpen(s))return;const e=this.deps.sessions.getBySessionId(s);if(e?.projectId==null)return;const t=this.deps.projects.getById(e.projectId);if(!t)return;const i=y(this.hooksDir,t.token).filter(a=>a.sessionId===s);if(i.length===0){this.queuedSessions.delete(s);return}if(this.sessionJudgedDead(s)){this.failQueuedOffline(s,i.filter(a=>!this.dismissedIds.has(a.id)));return}const n=this.surfaceOfSession(s),r=n?.prompt??null,d=this.modalBlocked(s);for(const a of i){if(this.stalled.has(s))return;if(this.dismissedIds.has(a.id))continue;const o={id:a.id,sessionId:s,text:a.text,...a.attachments&&a.attachments.length>0?{attachments:a.attachments}:{},mode:"prompt",oneWay:a.oneWay===!0,...a.forceTerminal===!0?{forceTerminal:!0}:{},via:"socket",channel:"prompt",status:"pending",at:a.at};if(!d&&this.hasImagesEntry(o)&&this.terminalChannel()){const u=await this.terminalPaneFor(e,t);if(u){p(this.hooksDir,t.token,new Set([a.id])),this.memory.set(o.id,{...o,via:"terminal",status:"delivering"}),this.awaitingAck.set(s,o.id),await this.runTerminalPrompt(o.id,u.id,this.wireTextOfEntry(o)),this.settleQueueIndex(s,t.token);return}}if(n&&await this.tryQueuedDeliver(o,n)){p(this.hooksDir,t.token,new Set([a.id])),this.settleQueueIndex(s,t.token);return}if(n&&await this.tryInboxDeliver(o,n)){p(this.hooksDir,t.token,new Set([a.id])),this.settleQueueIndex(s,t.token);return}const h=r?.resolve(s)??null,l=o.forceTerminal===!0?["terminal"]:o.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const u of l){if(u==="relay"&&r&&h){if(this.memory.set(o.id,{...o,status:"delivering",via:"relay"}),!this.runRelay(o,r,h.name)){this.memory.delete(o.id);return}this.awaitingAck.set(s,o.id),p(this.hooksDir,t.token,new Set([a.id]));break}if(u==="terminal"&&!d&&this.terminalChannel()){const c=await this.terminalPaneFor(e,t);if(c){p(this.hooksDir,t.token,new Set([a.id])),this.memory.set(o.id,{...o,via:"terminal",status:"delivering"}),this.awaitingAck.set(s,o.id),await this.runTerminalPrompt(o.id,c.id,this.wireTextOfEntry(o));break}}}if(this.awaitingAck.get(s)===o.id){this.settleQueueIndex(s,t.token);return}return}this.settleQueueIndex(s,t.token)}settleQueueIndex(s,e){y(this.hooksDir,e).every(t=>t.sessionId!==s)&&this.queuedSessions.delete(s)}async flushAll(){for(const s of[...this.queuedSessions])await this.flushSession(s)}forgetSession(s){let e=0;for(const[t,i]of this.memory)i.sessionId===s&&(this.memory.delete(t),e++);return e+=Os(this.hooksDir,s),this.queuedSessions.delete(s),this.gate.clearStall(s),this.gate.release(s),this.inboxSockets.forget(s),this.paneEnvs.delete(s),this.paneEnvConflicts.delete(s),this.revokedPaneEnvs.add(s),this.persistPaneEnvs(),e}forgetProject(s){const e=this.pendingOrigins.length;this.pendingOrigins=this.pendingOrigins.filter(i=>i.projectId!==s),this.pendingOrigins.length!==e&&this.persistPendingOrigins();let t=0;for(const[i,n]of this.memory)this.deps.sessions.getBySessionId(n.sessionId)?.projectId===s&&(this.memory.delete(i),this.inboxSockets.forget(n.sessionId),this.paneEnvs.delete(n.sessionId),this.gate.clearStall(n.sessionId),this.gate.release(n.sessionId),t++);for(const i of[...this.queuedSessions])this.deps.sessions.getBySessionId(i)?.projectId===s&&(t+=this.forgetSession(i));return this.persistPaneEnvs(),t}surfaceOfSession(s){const e=this.deps.hookEvents.listBySession(s,1),t=e[e.length-1]?.source;return k(t)?this.deps.surfaceFor?.(t)??W(t):null}commandModeOf(s,e){const t=this.deps.hookEvents.listBySession(s,1),i=t[t.length-1]?.source;if(!k(i))return null;const n=this.deps.commandsFor?.(i)??N(i);return n?Q(e,n.inputModes):null}resolveChannel(s,e,t){return fs(this.deps.sessions,()=>this.terminalChannel()!=null,s,e,t)}async terminalPaneFor(s,e){return this.paneEnvConflicts.has(s.sessionId)?null:as(this.terminalChannel(),this.paneEnvs,s,e)}terminalChannel(){const s=this.deps.terminal;return s&&s.available()?s:null}modalBlocked(s){return this.deps.blockedByQuestion?.(s)===!0}async deliverPrompt(s,e,t,i){if(this.sessionJudgedDead(s.sessionId))return{ok:!0,messageId:s.id,status:"failed",message:this.failOffline(s)};const n=this.modalBlocked(s.sessionId);if(!n&&this.hasImagesEntry(s)&&this.terminalChannel()){const u=await this.terminalPaneFor(e,t);if(u)return this.memory.set(s.id,{...s,status:"delivering",via:"terminal"}),this.awaitingAck.set(s.sessionId,s.id),this.runTerminalPrompt(s.id,u.id,this.wireTextOfEntry(s)),{ok:!0,messageId:s.id,status:"delivering",message:this.memory.get(s.id)}}const r=await this.tryQueuedDeliver(s,i);if(r)return{ok:!0,messageId:s.id,status:"delivered",message:r};const d=await this.tryInboxDeliver(s,i);if(d)return{ok:!0,messageId:s.id,status:"delivered",message:d};const a=i.prompt,o=a?.resolve(s.sessionId)??null,h=s.forceTerminal===!0?["terminal"]:s.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const u of h){if(u==="relay"&&a&&o){if(this.memory.set(s.id,{...s,status:"delivering",via:"relay"}),this.runRelay(s,a,o.name))return this.awaitingAck.set(s.sessionId,s.id),{ok:!0,messageId:s.id,status:"delivering",message:this.memory.get(s.id)};this.memory.delete(s.id)}if(u==="terminal"&&!n&&this.terminalChannel()){const c=await this.terminalPaneFor(e,t);if(c)return this.memory.set(s.id,{...s,status:"delivering",via:"terminal"}),this.awaitingAck.set(s.sessionId,s.id),this.runTerminalPrompt(s.id,c.id,this.wireTextOfEntry(s)),{ok:!0,messageId:s.id,status:"delivering",message:this.memory.get(s.id)}}}if(this.sessionJudgedDead(s.sessionId))return{ok:!0,messageId:s.id,status:"failed",message:this.failOffline(s)};this.queueEntry(s,t.token);const l={...s,status:"pending"};return{ok:!0,messageId:s.id,status:"pending",message:l}}async tryQueuedDeliver(s,e){const t=e.queuedPrompt;if(!t||this.hasImagesEntry(s))return null;const{bin:i,args:n}=t.command(s.sessionId,this.wireTextOfEntry(s));this.memory.set(s.id,{...s,status:"delivering",via:"queue"});try{await hs(i,n,t.timeoutMs??3e4,this.deps.spawnImpl)}catch{return this.memory.delete(s.id),null}return P(this.channelDeps(),{...s,via:"queue"},"queue")}async tryInboxDeliver(s,e){const t=e.promptInbox,i=this.inboxSockets.get(s.sessionId);if(!t||!i||s.forceTerminal===!0)return null;this.memory.set(s.id,{...s,status:"delivering",via:"socket"});try{await $(t,i,this.wireTextOfEntry(s))}catch{return this.memory.delete(s.id),null}return P(this.channelDeps(),s,"socket")}queueEntry(s,e){ps(this.hooksDir,e,s),this.queuedSessions.add(s.sessionId)}sessionJudgedDead(s,e=this.deps.livenessOf?.()??T()){return ks(this.deps.sessions,s,e)}failOffline(s){return gs(this.memory,e=>this.bus(e),s)}failQueuedOffline(s,e){ys(this.deps,this.hooksDir,this.memory,t=>this.bus(t),s,e),this.queuedSessions.delete(s)}relayDeps(){return{headless:this.headless,getMemory:s=>this.memory.get(s)??null,setMemory:s=>this.memory.set(s.id,s),awaitAck:(s,e)=>this.gate.await(s,e),stall:(s,e,t)=>this.gate.stall(s,e,t),commandModeOf:(s,e)=>this.commandModeOf(e,s),armAckWatch:s=>this.gate.armAckWatch(s),armCommandAck:(s,e)=>this.gate.armCommandAck(s,t=>{e(t),this.queuedSessions.has(t)&&this.scheduleFlushContinuation(t)}),onReleased:s=>{this.queuedSessions.has(s)&&this.scheduleFlushContinuation(s)},emit:s=>this.bus(s),...this.deps.bin?{bin:this.deps.bin}:{},...this.deps.relayTimeoutMs===void 0?{}:{relayTimeoutMs:this.deps.relayTimeoutMs}}}runRelay(s,e,t){return Is(this.relayDeps(),s,e,t,this.wireTextOfEntry(s))}async runTerminalPrompt(s,e,t){await this.runTerminal(s,i=>i.sendText(e,t))}async runTerminalSubmit(s,e){await this.runTerminal(s,t=>t.sendKeys(e,"\r"))}async runTerminal(s,e){const t=this.memory.get(s);if(!t)return;const i=this.terminalChannel();if(i)try{await e(i);const n=this.memory.get(s);if(!n)return;const r={...n,status:"delivered",settledAt:new Date().toISOString()};this.memory.set(s,r),this.commandModeOf(n.sessionId,n.text)?this.armCommandAck(s):this.armAckWatch(r),this.bus({kind:"message.delivered",messageId:s,sessionId:t.sessionId,at:new Date().toISOString()})}catch(n){const r=this.memory.get(s);if(!r)return;if(r.acked===!0){const a=new Date().toISOString();this.memory.set(s,{...r,status:"delivered",settledAt:a}),this.bus({kind:"message.delivered",messageId:s,sessionId:r.sessionId,at:a});return}const d={...r,status:"failed",error:n instanceof Error?n.message:String(n),settledAt:new Date().toISOString()};this.memory.set(s,d),this.stall(t.sessionId,d,"failed"),this.bus({kind:"message.finished",messageId:s,sessionId:t.sessionId,status:"failed",at:new Date().toISOString()})}}deliverInject(s,e,t,i){return ms({hooksDir:this.hooksDir,memory:this.memory,bus:this.busSafe()},s,e,t,i,this.wireTextOfEntry(s))}deliverHeadless(s,e,t,i){return cs({memory:this.memory,headless:this.headless,bus:this.busSafe(),...this.deps.bin?{bin:this.deps.bin}:{},...this.deps.timeoutMs===void 0?{}:{timeoutMs:this.deps.timeoutMs}},s,e,t,i,this.wireTextOfEntry(s))}bus(s){try{this.deps.bus?.emit(s)}catch{}}}
1
+ import{randomUUID as K}from"node:crypto";import{chmodSync as v,mkdirSync as w,readFileSync as E,renameSync as O,writeFileSync as I}from"node:fs";import{dirname as T,join as g}from"node:path";import{isHarness as S}from"@weavecode/core";import{commandModeAt as q,turnOutputOf as B}from"@weavecode/harness";import{isImageMediaType as b}from"../repositories/uploads.js";import{commandsSurfaceFor as L,messagingSurfaceFor as F}from"../surfaces.js";import{pidAliveOf as Q}from"../daemon/claude-liveness.js";import{combinedLivenessOf as A}from"../daemon/liveness.js";import{HeadlessRunner as G}from"./headless-runner.js";import{hooksRoot as W}from"./mirror.js";import{INBOX_TARGETS_FILE as J,InboxSocketRegistry as U,deliverViaInboxSocket as V}from"./inbox-socket.js";import{AckGate as H}from"./delivery/ack-gate.js";import{ANSWER_ATOM as D,ANSWER_ATOM_GAP_MS as Y,ANSWER_TEXT as $,CTRL_B as X,CTRL_C_KITTY as z,ENTER as Z,ESC as ee,ESC_KITTY as te,MODEL_NAME as se,SHIFT_TAB as ie,effortCommand as ne,effortLevelsOf as re,locateTerminalPane as ae,modelCommand as oe,sessionKeysTarget as le}from"./delivery/keys.js";import{hasImages as ue,settleDelivered as P,spawnOnce as he,wireTextOf as de}from"./delivery/channels.js";import{deliverHeadless as ce,deliverInject as me,resolveChannel as fe}from"./delivery/send.js";import{appendQueueEntry as pe,failOffline as ge,failQueuedOffline as ke,sessionJudgedDead as Se}from"./delivery/queue.js";import{runRelay as ye}from"./delivery/relay.js";import{listInflightCounts as ve,listVisible as we,sessionTerminals as Ee}from"./delivery/views.js";import{readPromptbox as k,removePromptboxBySession as Oe,removePromptboxEntries as p,scanQueuedSessionIds as Ie}from"./promptbox.js";const Te=1e3,be=6e4,Ae=3e4,De=9e4,Pe=5e3,_e=8,Me=12e4,Ce=1200,xe=/interrupted/i,je=/· done/,Re=12,Ne=[te,ee,X],Ke=600,qe=250,Be=5,Le=200,_="pane-envs.json",M="pending-origins.json",C=15*6e4;function Fe(f){try{const e=JSON.parse(E(f,"utf8"));if(!Array.isArray(e))return[];const t=[];for(const s of e){if(typeof s!="object"||s===null)continue;const i=s;if(!S(i.harness)||typeof i.projectId!="number"||typeof i.env!="object"||i.env===null||typeof i.at!="string")continue;const n={};for(const[r,l]of Object.entries(i.env))typeof l=="string"&&l&&(n[r]=l);Object.keys(n).length!==0&&t.push({harness:i.harness,projectId:i.projectId,env:n,at:i.at})}return t.filter(s=>Date.now()-Date.parse(s.at)<C)}catch{return[]}}function Qe(f){try{const e=JSON.parse(E(f,"utf8"));if(typeof e!="object"||e===null)return{};const t={};for(const[s,i]of Object.entries(e)){if(typeof i!="object"||i===null)continue;const n={};for(const[r,l]of Object.entries(i))typeof l=="string"&&l&&(n[r]=l);Object.keys(n).length>0&&(t[s]=n)}return t}catch{return{}}}const m=f=>new Promise(e=>setTimeout(e,f)),x=300,j=1500,Ge=1e3,We=12e4;export class MessageDeliverer{deps;headless;hooksDir;sideAnswerStore;memory=new Map;queuedSessions;inboxSockets;paneEnvs;revokedPaneEnvs=new Set;paneEnvConflicts=new Map;persistedPaneEnvs;pendingOrigins;persistedPendingOrigins;flushScheduled=new Set;flushing=new Map;stalled=new Map;awaitingAck=new Map;dismissedIds=new Set;gate;constructor(e){this.deps=e,this.headless=e.headless??new G({spawnImpl:e.spawnImpl,killImpl:e.killImpl}),this.hooksDir=e.hooksDir??W(),this.sideAnswerStore=e.sideAnswerStore,this.inboxSockets=new U(g(this.hooksDir,J));const t=Qe(g(this.hooksDir,_));this.paneEnvs=new Map(Object.entries(t)),this.persistedPaneEnvs=JSON.stringify(t),this.pendingOrigins=Fe(g(this.hooksDir,M)),this.persistedPendingOrigins=JSON.stringify(this.pendingOrigins),this.queuedSessions=Ie(this.hooksDir),this.gate=new H({awaitingAck:this.awaitingAck,stalled:this.stalled,memory:this.memory},{ackStallMs:e.ackStallMs??Ae,ackStallReleaseMs:e.ackStallReleaseMs??De,commandAckGraceMs:e.commandAckGraceMs??Pe},{emit:s=>this.bus(s)},(s,i)=>this.commandModeOf(s,i)!==null),this.gate.onAutoRelease=s=>this.scheduleFlushContinuation(s)}async send(e){const t=this.deps.sessions.getBySessionId(e.toSessionId);if(!t)return{ok:!1,status:404,error:"Session not found"};const s=this.surfaceOfSession(e.toSessionId);if(!s)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};const i=e.attachments?[...e.attachments]:[];if(i.length>0){if(!s.attach)return{ok:!1,status:409,error:"This harness cannot receive attachments"};if(i.some(d=>b(d.mediaType))&&!s.attach.kinds.includes("image"))return{ok:!1,status:409,error:"This harness cannot receive images"};if(i.some(d=>!b(d.mediaType))&&!s.attach.kinds.includes("file"))return{ok:!1,status:409,error:"This harness cannot receive file attachments"}}const n=this.resolveChannel(e.mode,e.toSessionId,s);if(typeof n!="string")return{ok:!1,status:409,error:n.reason};if(t.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const r=this.deps.projects.getById(t.projectId);if(!r)return{ok:!1,status:404,error:"Project not found"};if(n==="headless"&&this.headless.isBusy(e.toSessionId))return{ok:!1,status:409,error:"Session already has a running run"};const l={fromLabel:e.fromKind==="session"?`session ${e.fromSessionId??"unknown"}`:e.fromKind,at:new Date().toISOString(),mode:n},a={id:K(),sessionId:e.toSessionId,text:e.text,...i.length>0?{attachments:i}:{},mode:e.mode,oneWay:e.oneWay===!0,...e.forceTerminal===!0?{forceTerminal:!0}:{},channel:n,status:"pending",at:l.at},o=n==="prompt"&&this.blockedAhead(a.sessionId);o&&(this.queueEntry(a,r.token),this.scheduleFlushContinuation(a.sessionId));const h=o?{ok:!0,messageId:a.id,status:"pending",message:a}:n==="inject"?this.deliverInject(a,r.token,l,s):n==="headless"?this.deliverHeadless(a,r.path,l,s):await this.deliverPrompt(a,t,r,s);return this.bus({kind:"message.created",messageId:a.id,sessionId:a.sessionId,mode:a.mode,at:a.at}),h}getMessage(e){return this.memory.get(e)??null}listVisible(e){return we(this.deps,this.hooksDir,this.memory,e,this.deps.visibleTtlMs??be,t=>this.commandModeOf(e,t)!==null)}hasQueued(e){return this.queuedSessions.has(e)}listInflightCounts(){return ve(this.hooksDir,this.memory)}hasTerminalChannel(){return this.terminalChannel()!=null}scheduleFlushContinuation(e){if(this.flushScheduled.has(e))return;this.flushScheduled.add(e),setTimeout(()=>{this.flushScheduled.delete(e),this.flushSession(e)},this.deps.flushGapMs??Te).unref?.()}ackGateOpen(e){return this.gate.open(e)}blockedAhead(e){return this.ackGateOpen(e)?this.queuedSessions.has(e)||this.flushing.has(e):!0}noteInboxSocket(e,t){this.inboxSockets.set(e,t)}async awaitInboxReady(e,t){const s=this.surfaceOfSession(e)?.promptInbox??null;if(!s)return!1;const i=()=>{const r=this.inboxSockets.get(e);return!!r&&(!s.requiresAuthOn(process.platform)||!!r.token)},n=Date.now()+t;for(;!i();){if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,qe))}return!0}lastTurnOutput(e){const t=this.deps.hookEvents.listBySession(e,Be);for(let s=t.length-1;s>=0;s--){const i=t[s];let n=null;try{n=JSON.parse(i.payload)}catch{continue}const r=B(n?.raw);if(r)return{output:r,at:i.createdAt}}return null}notePaneEnv(e,t){const s=JSON.stringify(t);for(const[i,n]of this.paneEnvs){if(i===e||JSON.stringify(n)!==s)continue;const r=this.deps.sessions.getBySessionId(i)?.lastSeenAt;if((r?Date.now()-Date.parse(r):Number.POSITIVE_INFINITY)<Me){this.paneEnvs.delete(e),this.paneEnvConflicts.set(e,i),this.persistPaneEnvs();return}this.paneEnvs.delete(i),this.revokedPaneEnvs.add(i)}this.paneEnvConflicts.delete(e),this.paneEnvs.set(e,t),this.revokedPaneEnvs.delete(e),this.persistPaneEnvs()}paneEnvConflictOf(e){return this.paneEnvConflicts.get(e)??null}notePendingOrigin(e){this.pendingOrigins=this.pendingOrigins.filter(t=>Date.now()-Date.parse(t.at)<C),this.pendingOrigins.push({...e,at:new Date().toISOString()}),this.persistPendingOrigins()}claimPendingOrigin(e,t,s){const i=this.pendingOrigins.findIndex(r=>r.harness===t&&r.projectId===s);if(i<0)return;const[n]=this.pendingOrigins.splice(i,1);this.notePaneEnv(e,n.env),this.persistPendingOrigins()}persistPaneEnvs(){const e=JSON.stringify(Object.fromEntries(this.paneEnvs));if(e===this.persistedPaneEnvs)return;const t=g(this.hooksDir,_);try{w(T(t),{recursive:!0});const s=`${t}.tmp`;I(s,`${e}
2
+ `,{encoding:"utf8",mode:384}),O(s,t),v(t,384),this.persistedPaneEnvs=e}catch{}}persistPendingOrigins(){const e=JSON.stringify(this.pendingOrigins);if(e===this.persistedPendingOrigins)return;const t=g(this.hooksDir,M);try{w(T(t),{recursive:!0});const s=`${t}.tmp`;I(s,`${e}
3
+ `,{encoding:"utf8",mode:384}),O(s,t),v(t,384),this.persistedPendingOrigins=e}catch{}}sessionExited(e){this.inboxSockets.forget(e),this.paneEnvs.delete(e),this.revokedPaneEnvs.add(e),this.persistPaneEnvs(),this.awaitingAck.delete(e);const t=this.deps.sessions.getBySessionId(e),s=t?.projectId==null?null:this.deps.projects.getById(t.projectId);if(!s)return;const i=k(this.hooksDir,s.token).filter(n=>n.sessionId===e);this.failQueuedOffline(e,i.filter(n=>!this.dismissedIds.has(n.id)))}async sessionTerminals(){return Ee(this.deps,this.terminalChannel(),this.paneEnvs,()=>this.persistPaneEnvs(),this.revokedPaneEnvs)}diagnose(e){const t=this.surfaceOfSession(e),s=this.deps.sessions.livenessRowOf(e),i=s?Q(s,this.deps.livenessOf?.()??A()):null,n=t?.promptInbox??null,r=this.inboxSockets.get(e),l=n?r?n.requiresAuthOn(process.platform)&&!r.token?{status:"unavailable",reason:"auth-token-required"}:{status:"ready",reason:null}:{status:"unavailable",reason:"no-credentials"}:{status:"unavailable",reason:"no-mechanism"},a=t?.queuedPrompt?{status:"ready",reason:null}:{status:"unavailable",reason:"no-mechanism"},o=t?.prompt?.resolve(e)??null,h=t?.prompt?o?{status:"ready",reason:null}:{status:"unavailable",reason:"no-peer-name"}:{status:"unavailable",reason:"no-mechanism"},d=this.paneEnvs.has(e),u=this.terminalChannel()?d?{status:"ready",reason:null}:this.paneEnvConflicts.has(e)?{status:"unavailable",reason:"pane-env-conflict"}:{status:"unknown",reason:"no-pane-env"}:{status:"unavailable",reason:"no-backend"},c=this.deps.sessions.getBySessionId(e),y=c?.projectId==null?null:this.deps.projects.getById(c.projectId),R=y?k(this.hooksDir,y.token).filter(N=>N.sessionId===e).length:0;return{alive:i,inbox:l,queue:a,relay:h,terminal:u,paneEnvReported:d,pending:R,stalled:this.gate.isStalled(e)}}onSessionPrompt(e,t,s){const i=this.gate.acknowledge(e,t,s,{ackMinText:_e});return this.gate.hitLast&&this.queuedSessions.has(e)&&this.scheduleFlushContinuation(e),i}noteActivity(e){this.gate.noteActivity(e)&&this.queuedSessions.has(e)&&this.scheduleFlushContinuation(e)}armAckWatch(e){this.gate.armAckWatch(e)}armCommandAck(e){this.gate.armCommandAck(e,t=>{this.queuedSessions.has(t)&&this.scheduleFlushContinuation(t)})}stall(e,t,s){this.gate.stall(e,t,s)}async answer(e,t){if(t.length===0||!D.test(t[0])||t.some(i=>!D.test(i)&&!$.test(i)))return{ok:!1,status:400,error:"Invalid answer keys"};const s=await this.sessionKeysTarget(e);if(!s.ok)return s;try{for(const[i,n]of t.entries())i>0&&await m(Y),await s.terminal.sendKeys(s.paneId,n);return{ok:!0}}catch(i){return{ok:!1,status:409,error:i instanceof Error?i.message:String(i)}}}async interrupt(e){const t=await this.sessionKeysTarget(e,"\u51FB\u952E");if(!t.ok)return t;const s=async()=>{try{return await t.terminal.getPaneText?.(t.paneId)??null}catch{return null}},i=l=>{const a=l.split(`
4
+ `).slice(-Re).join(`
5
+ `);return xe.test(a)||je.test(a)},n=this.deps.interruptVerifyMs??Ce;let r=!1;for(const[l,a]of Ne.entries()){try{await t.terminal.sendKeys(t.paneId,a)}catch(h){if(l===0)return{ok:!1,status:409,error:h instanceof Error?h.message:String(h)};break}await m(l===0?n:Ke);const o=await s();if(o===null)return{ok:!0,paneId:t.paneId,sent:!0,confirmed:!0};if(i(o)){r=!0;break}}return{ok:!0,paneId:t.paneId,sent:!0,confirmed:r}}async closePane(e){const t=await this.sessionKeysTarget(e,"\u5173\u95ED");if(!t.ok)return t;try{return await t.terminal.closePane(t.paneId),{ok:!0}}catch(s){return{ok:!1,status:409,error:s instanceof Error?s.message:String(s)}}}async cycleMode(e){const t=await this.sessionKeysTarget(e);if(!t.ok)return t;try{return await t.terminal.sendKeys(t.paneId,ie),{ok:!0}}catch(s){return{ok:!1,status:409,error:s instanceof Error?s.message:String(s)}}}async pressEnter(e){const t=await this.sessionKeysTarget(e);if(!t.ok)return t;try{return await t.terminal.sendKeys(t.paneId,Z),{ok:!0}}catch(s){return{ok:!1,status:409,error:s instanceof Error?s.message:String(s)}}}async pressCtrlC(e){const t=await this.sessionKeysTarget(e);if(!t.ok)return t;try{return await t.terminal.sendKeys(t.paneId,z),{ok:!0}}catch(s){return{ok:!1,status:409,error:s instanceof Error?s.message:String(s)}}}async setModel(e,t){const s=t.trim();if(!se.test(s))return{ok:!1,status:400,error:"\u6A21\u578B\u540D\u5F62\u6001\u4E0D\u5408\u6CD5\uFF08\u4E0D\u542B\u7A7A\u767D\u4E0E\u63A7\u5236\u5B57\u7B26\uFF0C\u2264128 \u5B57\u7B26\uFF09"};const i=await this.sessionKeysTarget(e);if(!i.ok)return i;try{return await i.terminal.sendText(i.paneId,oe(s)),{ok:!0}}catch(n){return{ok:!1,status:409,error:n instanceof Error?n.message:String(n)}}}async setEffort(e,t){const s=t.trim(),i=await this.sessionKeysTarget(e);if(!i.ok)return i;const n=re(this.deps.hookEvents,e);if(!n.includes(s))return{ok:!1,status:400,error:`\u601D\u8003\u5F3A\u5EA6\u6863\u4F4D\u4E0D\u5408\u6CD5\uFF08\u53EF\u9009\uFF1A${n.join(" / ")||"\u65E0"}\uFF09`};try{return await i.terminal.sendText(i.paneId,ne(s)),{ok:!0}}catch(r){return{ok:!1,status:409,error:r instanceof Error?r.message:String(r)}}}async askSideQuestion(e,t){if(!this.deps.sessions.getBySessionId(e))return{ok:!1,status:404,error:"Session not found"};const s=this.surfaceOfSession(e),i=s?.sideQuestion??null;if(!i)return{ok:!1,status:409,error:s?.unsupportedReasons?.sideQuestion??"\u8FD9\u4E2A harness \u6CA1\u6709\u65C1\u8DEF\u4F1A\u8BDD\u901A\u9053"};const n=i.validate(t);if(!n.ok)return{ok:!1,status:400,error:n.error};if(i.prerequisite&&this.deps.sessions.hasRunOf(e)!==!0)return{ok:!1,status:409,error:i.prerequisite};const r=await this.sessionKeysTarget(e,"\u53D1\u8D77\u65C1\u8DEF\u4F1A\u8BDD");if(!r.ok)return r;try{return i.screen?(this.pollScreenAnswer(e,r.terminal,r.paneId,i,n.text),{ok:!0,question:n.text}):(await r.terminal.sendText(r.paneId,i.command(n.text)),{ok:!0,question:n.text})}catch(l){return{ok:!1,status:409,error:l instanceof Error?l.message:String(l)}}}pollScreenAnswer(e,t,s,i,n){const r=i.screen,l=async()=>await t.getPaneText?.(s).catch(()=>null)??null;(async()=>{const a=await l()??"";await t.sendKeys(s,r.openKeys).catch(()=>{}),await m(x),await t.sendKeys(s,r.submitKey).catch(()=>{}),await m(j);let o=await l();if((!o||!r.panelOpen(o))&&(await t.sendKeys(s,r.submitKey).catch(()=>{}),await m(j),o=await l(),!o||!r.panelOpen(o)))return;await t.sendText(s,n).catch(()=>{}),await m(x),await t.sendKeys(s,r.submitKey).catch(()=>{});const h=Date.now()+We;let d=null;for(;Date.now()<h;){if(await m(Ge),o=await l(),o==null)return;const c=r.extractAnswer(n,a,o);if(c.done){d=c.answer;break}}d!=null&&(this.sideAnswerStore?.answerById(e,n,d),this.bus({kind:"sideQuestion.answered",sessionId:e,at:new Date().toISOString()}));const u=await l();u&&r.panelOpen(u)&&await t.sendKeys(s,r.closeKey).catch(()=>{})})()}async sessionKeysTarget(e,t="\u51FB\u952E"){return le(this.keysDeps(),e,t)}busSafe(){return{emit:e=>this.bus(e)}}channelDeps(){return{setMemory:e=>this.memory.set(e.id,e),deleteMemory:e=>this.memory.delete(e),awaitAck:(e,t)=>this.gate.await(e,t),commandModeOf:(e,t)=>this.commandModeOf(t,e),armAckWatch:e=>this.gate.armAckWatch(e),armCommandAck:e=>this.gate.armCommandAck(e,t=>{this.queuedSessions.has(t)&&this.scheduleFlushContinuation(t)}),emit:e=>this.bus(e),...this.deps.spawnImpl?{spawnImpl:this.deps.spawnImpl}:{}}}wireTextOfEntry(e){return de(e,t=>this.surfaceOfSession(t))}hasImagesEntry(e){return ue(e)}keysDeps(){return{sessions:this.deps.sessions,projects:this.deps.projects,hookEvents:this.deps.hookEvents,terminalChannel:()=>this.terminalChannel(),terminalPaneFor:(e,t)=>this.terminalPaneFor(e,t),paneEnvConflictOf:e=>this.paneEnvConflictOf(e)}}async resend(e){const t=this.memory.get(e);if(!t)return{ok:!1,status:404,error:"Message not found"};if(!(t.channel==="prompt"&&(t.status==="failed"||t.status==="delivered"&&!t.acked)))return{ok:!1,status:409,error:"Message is not resendable"};const i=this.deps.sessions.getBySessionId(t.sessionId);if(!i)return{ok:!1,status:404,error:"Session not found"};if(i.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const n=this.deps.projects.getById(i.projectId);if(!n)return{ok:!1,status:404,error:"Project not found"};const r=this.surfaceOfSession(t.sessionId);if(!r)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};if(this.gate.clearStall(t.sessionId,e),t.status==="delivered"&&t.via==="terminal"&&this.terminalChannel()){const o=await this.terminalPaneFor(i,n);if(o)return this.memory.set(e,{...t,status:"delivering",stalled:!1,settledAt:null}),this.runTerminalSubmit(e,o.id),this.bus({kind:"message.created",messageId:e,sessionId:t.sessionId,mode:t.mode,at:new Date().toISOString()}),{ok:!0,messageId:e,status:"delivering",message:this.memory.get(e)}}this.memory.delete(e);const l={...t,status:"pending",stalled:!1,acked:!1,settledAt:null,reason:void 0,error:null},a=await this.deliverPrompt(l,i,n,r);return this.bus({kind:"message.created",messageId:l.id,sessionId:l.sessionId,mode:l.mode,at:new Date().toISOString()}),a}dismiss(e,t){const s=this.memory.get(t);if(s){if(s.status==="running")return{ok:!1,status:409,error:"Message is still in flight"};s.status==="delivering"&&this.gate.headOf(s.sessionId)===t&&this.flushing.delete(s.sessionId),this.memory.delete(t),this.gate.clearStall(s.sessionId,t),this.gate.release(s.sessionId,t),this.queuedSessions.has(s.sessionId)&&this.scheduleFlushContinuation(s.sessionId)}else if(!this.dropQueued(e,t))return{ok:!1,status:404,error:"Message not found"};return this.bus({kind:"message.dismissed",messageId:t,sessionId:e,at:new Date().toISOString()}),{ok:!0}}dropQueued(e,t){const s=this.deps.sessions.getBySessionId(e);if(s?.projectId==null)return!1;const i=this.deps.projects.getById(s.projectId);if(!i)return!1;const n=k(this.hooksDir,i.token);if(!n.some(r=>r.id===t&&r.sessionId===e))return!1;for(p(this.hooksDir,i.token,new Set([t])),this.dismissedIds.add(t);this.dismissedIds.size>Le;){const r=this.dismissedIds.values().next().value;if(r===void 0)break;this.dismissedIds.delete(r)}return n.some(r=>r.sessionId===e&&r.id!==t)||this.queuedSessions.delete(e),!0}async flushSession(e){if(this.stalled.has(e)||this.flushing.has(e)||!this.queuedSessions.has(e))return;const t=Symbol(e);this.flushing.set(e,t);try{await this.flushSessionInner(e)}catch{}finally{this.flushing.get(e)===t&&this.flushing.delete(e)}}async flushSessionInner(e){if(!this.ackGateOpen(e))return;const t=this.deps.sessions.getBySessionId(e);if(t?.projectId==null)return;const s=this.deps.projects.getById(t.projectId);if(!s)return;const i=k(this.hooksDir,s.token).filter(a=>a.sessionId===e);if(i.length===0){this.queuedSessions.delete(e);return}if(this.sessionJudgedDead(e)){this.failQueuedOffline(e,i.filter(a=>!this.dismissedIds.has(a.id)));return}const n=this.surfaceOfSession(e),r=n?.prompt??null,l=this.modalBlocked(e);for(const a of i){if(this.stalled.has(e))return;if(this.dismissedIds.has(a.id))continue;const o={id:a.id,sessionId:e,text:a.text,...a.attachments&&a.attachments.length>0?{attachments:a.attachments}:{},mode:"prompt",oneWay:a.oneWay===!0,...a.forceTerminal===!0?{forceTerminal:!0}:{},via:"socket",channel:"prompt",status:"pending",at:a.at};if(!l&&this.hasImagesEntry(o)&&this.terminalChannel()){const u=await this.terminalPaneFor(t,s);if(u){p(this.hooksDir,s.token,new Set([a.id])),this.memory.set(o.id,{...o,via:"terminal",status:"delivering"}),this.awaitingAck.set(e,o.id),await this.runTerminalPrompt(o.id,u.id,this.wireTextOfEntry(o)),this.settleQueueIndex(e,s.token);return}}if(n&&await this.tryQueuedDeliver(o,n)){p(this.hooksDir,s.token,new Set([a.id])),this.settleQueueIndex(e,s.token);return}if(n&&await this.tryInboxDeliver(o,n)){p(this.hooksDir,s.token,new Set([a.id])),this.settleQueueIndex(e,s.token);return}const h=r?.resolve(e)??null,d=o.forceTerminal===!0?["terminal"]:o.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const u of d){if(u==="relay"&&r&&h){if(this.memory.set(o.id,{...o,status:"delivering",via:"relay"}),!this.runRelay(o,r,h.name)){this.memory.delete(o.id);return}this.awaitingAck.set(e,o.id),p(this.hooksDir,s.token,new Set([a.id]));break}if(u==="terminal"&&!l&&this.terminalChannel()){const c=await this.terminalPaneFor(t,s);if(c){p(this.hooksDir,s.token,new Set([a.id])),this.memory.set(o.id,{...o,via:"terminal",status:"delivering"}),this.awaitingAck.set(e,o.id),await this.runTerminalPrompt(o.id,c.id,this.wireTextOfEntry(o));break}}}if(this.awaitingAck.get(e)===o.id){this.settleQueueIndex(e,s.token);return}return}this.settleQueueIndex(e,s.token)}settleQueueIndex(e,t){k(this.hooksDir,t).every(s=>s.sessionId!==e)&&this.queuedSessions.delete(e)}async flushAll(){for(const e of[...this.queuedSessions])await this.flushSession(e)}forgetSession(e){let t=0;for(const[s,i]of this.memory)i.sessionId===e&&(this.memory.delete(s),t++);return t+=Oe(this.hooksDir,e),this.queuedSessions.delete(e),this.gate.clearStall(e),this.gate.release(e),this.inboxSockets.forget(e),this.paneEnvs.delete(e),this.paneEnvConflicts.delete(e),this.revokedPaneEnvs.add(e),this.persistPaneEnvs(),t}forgetProject(e){const t=this.pendingOrigins.length;this.pendingOrigins=this.pendingOrigins.filter(i=>i.projectId!==e),this.pendingOrigins.length!==t&&this.persistPendingOrigins();let s=0;for(const[i,n]of this.memory)this.deps.sessions.getBySessionId(n.sessionId)?.projectId===e&&(this.memory.delete(i),this.inboxSockets.forget(n.sessionId),this.paneEnvs.delete(n.sessionId),this.gate.clearStall(n.sessionId),this.gate.release(n.sessionId),s++);for(const i of[...this.queuedSessions])this.deps.sessions.getBySessionId(i)?.projectId===e&&(s+=this.forgetSession(i));return this.persistPaneEnvs(),s}surfaceOfSession(e){const t=this.deps.hookEvents.listBySession(e,1),s=t[t.length-1]?.source;return S(s)?this.deps.surfaceFor?.(s)??F(s):null}commandModeOf(e,t){const s=this.deps.hookEvents.listBySession(e,1),i=s[s.length-1]?.source;if(!S(i))return null;const n=this.deps.commandsFor?.(i)??L(i);return n?q(t,n.inputModes):null}resolveChannel(e,t,s){return fe(this.deps.sessions,()=>this.terminalChannel()!=null,e,t,s)}async terminalPaneFor(e,t){return this.paneEnvConflicts.has(e.sessionId)?null:ae(this.terminalChannel(),this.paneEnvs,e,t)}terminalChannel(){const e=this.deps.terminal;return e&&e.available()?e:null}modalBlocked(e){return this.deps.blockedByQuestion?.(e)===!0}async deliverPrompt(e,t,s,i){if(this.sessionJudgedDead(e.sessionId))return{ok:!0,messageId:e.id,status:"failed",message:this.failOffline(e)};const n=this.modalBlocked(e.sessionId);if(!n&&this.hasImagesEntry(e)&&this.terminalChannel()){const u=await this.terminalPaneFor(t,s);if(u)return this.memory.set(e.id,{...e,status:"delivering",via:"terminal"}),this.awaitingAck.set(e.sessionId,e.id),this.runTerminalPrompt(e.id,u.id,this.wireTextOfEntry(e)),{ok:!0,messageId:e.id,status:"delivering",message:this.memory.get(e.id)}}const r=await this.tryQueuedDeliver(e,i);if(r)return{ok:!0,messageId:e.id,status:"delivered",message:r};const l=await this.tryInboxDeliver(e,i);if(l)return{ok:!0,messageId:e.id,status:"delivered",message:l};const a=i.prompt,o=a?.resolve(e.sessionId)??null,h=e.forceTerminal===!0?["terminal"]:e.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const u of h){if(u==="relay"&&a&&o){if(this.memory.set(e.id,{...e,status:"delivering",via:"relay"}),this.runRelay(e,a,o.name))return this.awaitingAck.set(e.sessionId,e.id),{ok:!0,messageId:e.id,status:"delivering",message:this.memory.get(e.id)};this.memory.delete(e.id)}if(u==="terminal"&&!n&&this.terminalChannel()){const c=await this.terminalPaneFor(t,s);if(c)return this.memory.set(e.id,{...e,status:"delivering",via:"terminal"}),this.awaitingAck.set(e.sessionId,e.id),this.runTerminalPrompt(e.id,c.id,this.wireTextOfEntry(e)),{ok:!0,messageId:e.id,status:"delivering",message:this.memory.get(e.id)}}}if(this.sessionJudgedDead(e.sessionId))return{ok:!0,messageId:e.id,status:"failed",message:this.failOffline(e)};this.queueEntry(e,s.token);const d={...e,status:"pending"};return{ok:!0,messageId:e.id,status:"pending",message:d}}async tryQueuedDeliver(e,t){const s=t.queuedPrompt;if(!s||this.hasImagesEntry(e))return null;const{bin:i,args:n}=s.command(e.sessionId,this.wireTextOfEntry(e));this.memory.set(e.id,{...e,status:"delivering",via:"queue"});try{await he(i,n,s.timeoutMs??3e4,this.deps.spawnImpl)}catch{return this.memory.delete(e.id),null}return P(this.channelDeps(),{...e,via:"queue"},"queue")}async tryInboxDeliver(e,t){const s=t.promptInbox,i=this.inboxSockets.get(e.sessionId);if(!s||!i||e.forceTerminal===!0)return null;this.memory.set(e.id,{...e,status:"delivering",via:"socket"});try{await V(s,i,this.wireTextOfEntry(e))}catch{return this.memory.delete(e.id),null}return P(this.channelDeps(),e,"socket")}queueEntry(e,t){pe(this.hooksDir,t,e),this.queuedSessions.add(e.sessionId)}sessionJudgedDead(e,t=this.deps.livenessOf?.()??A()){return Se(this.deps.sessions,e,t)}failOffline(e){return ge(this.memory,t=>this.bus(t),e)}failQueuedOffline(e,t){ke(this.deps,this.hooksDir,this.memory,s=>this.bus(s),e,t),this.queuedSessions.delete(e)}relayDeps(){return{headless:this.headless,getMemory:e=>this.memory.get(e)??null,setMemory:e=>this.memory.set(e.id,e),awaitAck:(e,t)=>this.gate.await(e,t),stall:(e,t,s)=>this.gate.stall(e,t,s),commandModeOf:(e,t)=>this.commandModeOf(t,e),armAckWatch:e=>this.gate.armAckWatch(e),armCommandAck:(e,t)=>this.gate.armCommandAck(e,s=>{t(s),this.queuedSessions.has(s)&&this.scheduleFlushContinuation(s)}),onReleased:e=>{this.queuedSessions.has(e)&&this.scheduleFlushContinuation(e)},emit:e=>this.bus(e),...this.deps.bin?{bin:this.deps.bin}:{},...this.deps.relayTimeoutMs===void 0?{}:{relayTimeoutMs:this.deps.relayTimeoutMs}}}runRelay(e,t,s){return ye(this.relayDeps(),e,t,s,this.wireTextOfEntry(e))}async runTerminalPrompt(e,t,s){await this.runTerminal(e,i=>i.sendText(t,s))}async runTerminalSubmit(e,t){await this.runTerminal(e,s=>s.sendKeys(t,"\r"))}async runTerminal(e,t){const s=this.memory.get(e);if(!s)return;const i=this.terminalChannel();if(i)try{await t(i);const n=this.memory.get(e);if(!n)return;const r={...n,status:"delivered",settledAt:new Date().toISOString()};this.memory.set(e,r),this.commandModeOf(n.sessionId,n.text)?this.armCommandAck(e):this.armAckWatch(r),this.bus({kind:"message.delivered",messageId:e,sessionId:s.sessionId,at:new Date().toISOString()})}catch(n){const r=this.memory.get(e);if(!r)return;if(r.acked===!0){const a=new Date().toISOString();this.memory.set(e,{...r,status:"delivered",settledAt:a}),this.bus({kind:"message.delivered",messageId:e,sessionId:r.sessionId,at:a});return}const l={...r,status:"failed",error:n instanceof Error?n.message:String(n),settledAt:new Date().toISOString()};this.memory.set(e,l),this.stall(s.sessionId,l,"failed"),this.bus({kind:"message.finished",messageId:e,sessionId:s.sessionId,status:"failed",at:new Date().toISOString()})}}deliverInject(e,t,s,i){return me({hooksDir:this.hooksDir,memory:this.memory,bus:this.busSafe()},e,t,s,i,this.wireTextOfEntry(e))}deliverHeadless(e,t,s,i){return ce({memory:this.memory,headless:this.headless,bus:this.busSafe(),...this.deps.bin?{bin:this.deps.bin}:{},...this.deps.timeoutMs===void 0?{}:{timeoutMs:this.deps.timeoutMs}},e,t,s,i,this.wireTextOfEntry(e))}bus(e){try{this.deps.bus?.emit(e)}catch{}}}
@@ -1,5 +1,5 @@
1
- import{createHash as h}from"node:crypto";import{mkdirSync as a,readFileSync as u,renameSync as d,writeFileSync as l}from"node:fs";import{join as i}from"node:path";import{hookSourceHarness as f}from"@weavecode/core";import{getDataDir as m,getHooksDir as y}from"../db/paths.js";import{projectLabel as j}from"./match.js";export const MIRROR_VERSION=1,OUTBOX_MAX_LINES=200;export function hookShardId(s){return h("sha256").update(s).digest("hex").slice(0,16)}export function hooksRoot(s){return y(s)}export function mirrorPathOf(s,e){return i(s,"mirror",`${e}.json`)}export function outboxPathOf(s,e){return i(s,"outbox",`${e}.jsonl`)}export function buildMirrorDoc(s,e,o){const r=e.filter(t=>!(t.source.kind!=="hook-event"||t.handler.type!=="inject"||!t.enabled||t.projectId!==null&&t.projectId!==s.id||t.filter.crossProjectOnly)).sort((t,n)=>n.priority-t.priority).map(t=>({id:t.id,name:t.name,harness:f(t.source)??"claude",events:[t.source.kind==="hook-event"?t.source.event:""],tools:t.filter.toolNames?.length?[...t.filter.toolNames]:null,globs:t.filter.pathGlobs?.length?[...t.filter.pathGlobs]:null,template:t.handler.type==="inject"?t.handler.template:""}));return{version:MIRROR_VERSION,project:j(s.path),pendingTitles:o,rules:r}}export class MirrorWriter{deps;dataDir;constructor(e){this.deps=e,this.dataDir=e.dataDir??m()}syncAll(){for(const e of this.deps.projects.list())this.syncProject(e.id)}syncProject(e){const o=this.deps.projects.getById(e);if(!o||o.archivedAt)return;const r={};for(const t of this.deps.sessions.list(e))t.pendingTitle&&(r[t.sessionId]=t.pendingTitle);this.write(o.token,buildMirrorDoc(o,this.deps.rules.list(),r))}write(e,o){try{const r=mirrorPathOf(hooksRoot(this.dataDir),hookShardId(e));a(i(hooksRoot(this.dataDir),"mirror"),{recursive:!0});const t=`${r}.tmp`;l(t,JSON.stringify(o)),d(t,r)}catch{}}attachToBus(e){e.subscribe(o=>{if(o.kind!=="session.renamed"||!o.sessionId)return;const r=this.deps.sessions.getBySessionId(o.sessionId);r?.projectId!=null&&this.syncProject(r.projectId)})}}export function appendInbox(s,e,o){const r=i(s,"inbox");a(r,{recursive:!0}),l(i(r,`${hookShardId(e)}.jsonl`),JSON.stringify({v:1,token:e,report:o})+`
2
- `,{flag:"a"})}export function appendOutbox(s,e,o){if(o.length!==0)try{const r=outboxPathOf(s,hookShardId(e));a(i(s,"outbox"),{recursive:!0});let t=[];try{t=u(r,"utf8").split(`
3
- `).filter(c=>c.trim())}catch{t=[]}for(const c of o)t.push(JSON.stringify({...c,at:new Date().toISOString()}));const n=t.slice(-OUTBOX_MAX_LINES),p=`${r}.tmp`;l(p,n.length?n.join(`
1
+ import{createHash as l}from"node:crypto";import{mkdirSync as a,readFileSync as h,renameSync as f,writeFileSync as p}from"node:fs";import{join as n}from"node:path";import{hookSourceHarness as u}from"@weavecode/core";import{getDataDir as m,getHooksDir as y}from"../db/paths.js";import{projectLabel as j}from"./match.js";export const MIRROR_VERSION=1,OUTBOX_MAX_LINES=200;export function hookShardId(i){return l("sha256").update(i).digest("hex").slice(0,16)}export function hooksRoot(i){return y(i)}export function mirrorPathOf(i,r){return n(i,"mirror",`${r}.json`)}export function outboxPathOf(i,r){return n(i,"outbox",`${r}.jsonl`)}export function buildMirrorDoc(i,r,e){const o=r.filter(t=>!(t.source.kind!=="hook-event"||t.handler.type!=="inject"||!t.enabled||t.projectId!==null&&t.projectId!==i.id||t.filter.crossProjectOnly)).sort((t,s)=>s.priority-t.priority).map(t=>({id:t.id,name:t.name,harness:u(t.source)??"claude",events:[t.source.kind==="hook-event"?t.source.event:""],tools:t.filter.toolNames?.length?[...t.filter.toolNames]:null,globs:t.filter.pathGlobs?.length?[...t.filter.pathGlobs]:null,template:t.handler.type==="inject"?t.handler.template:""}));return{version:MIRROR_VERSION,project:j(i.path),pendingTitles:e,rules:o}}export class MirrorWriter{deps;dataDir;constructor(r){this.deps=r,this.dataDir=r.dataDir??m()}syncAll(){for(const r of this.deps.projects.list())this.syncProject(r.id)}syncProject(r){const e=this.deps.projects.getById(r);if(!e||e.archivedAt)return;const o={};for(const t of this.deps.sessions.list(r))t.pendingTitle&&(o[t.sessionId]=t.pendingTitle);this.write(e.token,buildMirrorDoc(e,this.deps.rules.list(),o))}write(r,e){try{const o=mirrorPathOf(hooksRoot(this.dataDir),hookShardId(r));a(n(hooksRoot(this.dataDir),"mirror"),{recursive:!0});const t=`${o}.tmp`;p(t,JSON.stringify(e)),f(t,o)}catch{}}attachToBus(r){r.subscribe(e=>{if(e.kind!=="session.renamed"||!e.sessionId)return;const o=this.deps.sessions.getBySessionId(e.sessionId);o?.projectId!=null&&this.syncProject(o.projectId)})}}export function appendInbox(i,r,e){const o=n(i,"inbox");a(o,{recursive:!0}),p(n(o,`${hookShardId(r)}.jsonl`),JSON.stringify({v:1,token:r,report:e})+`
2
+ `,{flag:"a"})}export function appendOutbox(i,r,e){if(e.length!==0)try{const o=outboxPathOf(i,hookShardId(r));a(n(i,"outbox"),{recursive:!0});let t=[];try{t=h(o,"utf8").split(`
3
+ `).filter(c=>c.trim())}catch{t=[]}for(const c of e)t.push(JSON.stringify({...c,at:new Date().toISOString()}));const s=t.slice(-OUTBOX_MAX_LINES),d=`${o}.tmp`;p(d,s.length?s.join(`
4
4
  `)+`
5
- `:""),d(p,r)}catch{}}
5
+ `:""),f(d,o)}catch{}}