@weavecode/weave 0.1.5 → 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 (249) hide show
  1. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/encodeurl/README.md +14 -0
  2. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/encodeurl/index.js +5 -10
  3. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/encodeurl/package.json +10 -6
  4. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/CHANGELOG.md +42 -0
  5. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/README.md +38 -10
  6. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/dist/qs.js +18 -18
  7. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/lib/parse.js +16 -4
  8. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/lib/utils.js +13 -2
  9. package/node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/qs/package.json +1 -1
  10. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.cjs +6 -2
  11. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.mjs +6 -2
  12. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/package.json +10 -10
  13. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/decrypt.d.ts +3 -0
  14. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/unsecured.d.ts +2 -0
  15. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/verify.d.ts +3 -0
  16. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/types.d.ts +8 -0
  17. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/util/decode_jwt.d.ts +1 -0
  18. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/remote.js +1 -1
  19. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/package.json +1 -1
  20. package/node_modules/@weavecode/cli/dist/cli.js +4 -4
  21. package/node_modules/@weavecode/cli/dist/commands/chpass.js +1 -1
  22. package/node_modules/@weavecode/cli/dist/commands/daemon-auth.js +1 -1
  23. package/node_modules/@weavecode/cli/dist/commands/daemon.d.ts +2 -0
  24. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  25. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -2
  26. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  27. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  28. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  29. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  30. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  31. package/node_modules/@weavecode/cli/dist/commands/uninstall.js +1 -1
  32. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +5 -5
  33. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +6 -1
  34. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +5 -5
  35. package/node_modules/@weavecode/cli/dist/i18n/index.js +1 -1
  36. package/node_modules/@weavecode/cli/dist/i18n/t.js +1 -1
  37. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +3 -3
  38. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  39. package/node_modules/@weavecode/cli/dist/init/git-commit.js +2 -2
  40. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  41. package/node_modules/@weavecode/cli/dist/init/harnesses/codex.js +1 -1
  42. package/node_modules/@weavecode/cli/dist/init/instruction-link.js +1 -1
  43. package/node_modules/@weavecode/cli/dist/init/plugin-templates.js +1 -1
  44. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  45. package/node_modules/@weavecode/cli/dist/init/provision.js +1 -1
  46. package/node_modules/@weavecode/cli/dist/init/uninstall.js +6 -6
  47. package/node_modules/@weavecode/cli/dist/init/wiring.js +1 -1
  48. package/node_modules/@weavecode/cli/dist/parser.js +1 -1
  49. package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
  50. package/node_modules/@weavecode/cli/dist/statusline/mock-input.js +1 -1
  51. package/node_modules/@weavecode/cli/dist/statusline/preview.js +2 -2
  52. package/node_modules/@weavecode/cli/package.json +5 -5
  53. package/node_modules/@weavecode/core/dist/harness-checks.js +1 -1
  54. package/node_modules/@weavecode/core/dist/harness.d.ts +25 -0
  55. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  56. package/node_modules/@weavecode/core/dist/index.d.ts +1 -1
  57. package/node_modules/@weavecode/core/dist/index.js +1 -1
  58. package/node_modules/@weavecode/core/dist/platform.js +1 -1
  59. package/node_modules/@weavecode/core/dist/types.js +1 -1
  60. package/node_modules/@weavecode/core/dist/utils/fs.js +1 -1
  61. package/node_modules/@weavecode/core/dist/utils/logger.js +1 -1
  62. package/node_modules/@weavecode/core/package.json +1 -1
  63. package/node_modules/@weavecode/harness/dist/claude/assets.js +4 -4
  64. package/node_modules/@weavecode/harness/dist/claude/capture.js +9 -9
  65. package/node_modules/@weavecode/harness/dist/claude/commands.d.ts +3 -0
  66. package/node_modules/@weavecode/harness/dist/claude/commands.js +2 -3
  67. package/node_modules/@weavecode/harness/dist/claude/config.js +2 -2
  68. package/node_modules/@weavecode/harness/dist/claude/detect.js +1 -1
  69. package/node_modules/@weavecode/harness/dist/claude/edits.js +1 -1
  70. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  71. package/node_modules/@weavecode/harness/dist/claude/images.js +2 -2
  72. package/node_modules/@weavecode/harness/dist/claude/index.d.ts +1 -0
  73. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  74. package/node_modules/@weavecode/harness/dist/claude/liveness.js +1 -1
  75. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -1
  76. package/node_modules/@weavecode/harness/dist/claude/messaging.js +2 -2
  77. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -1
  78. package/node_modules/@weavecode/harness/dist/claude/narration.d.ts +0 -11
  79. package/node_modules/@weavecode/harness/dist/claude/narration.js +1 -1
  80. package/node_modules/@weavecode/harness/dist/claude/peers.js +1 -1
  81. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -1
  82. package/node_modules/@weavecode/harness/dist/claude/plugins.js +4 -4
  83. package/node_modules/@weavecode/harness/dist/claude/prompt-inbox.js +1 -1
  84. package/node_modules/@weavecode/harness/dist/claude/prompt.js +3 -3
  85. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -2
  86. package/node_modules/@weavecode/harness/dist/claude/resume.js +1 -1
  87. package/node_modules/@weavecode/harness/dist/claude/rewind.d.ts +8 -0
  88. package/node_modules/@weavecode/harness/dist/claude/rewind.js +1 -0
  89. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -1
  90. package/node_modules/@weavecode/harness/dist/claude/side-question.js +2 -2
  91. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +36 -15
  92. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -1
  93. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -2
  94. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.d.ts +26 -0
  95. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.js +2 -0
  96. package/node_modules/@weavecode/harness/dist/claude/transcript.js +7 -7
  97. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  98. package/node_modules/@weavecode/harness/dist/codex/capture.js +2 -2
  99. package/node_modules/@weavecode/harness/dist/codex/commands.js +4 -4
  100. package/node_modules/@weavecode/harness/dist/codex/config.js +2 -2
  101. package/node_modules/@weavecode/harness/dist/codex/detect.js +1 -1
  102. package/node_modules/@weavecode/harness/dist/codex/event-source.js +2 -2
  103. package/node_modules/@weavecode/harness/dist/codex/images.js +1 -1
  104. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  105. package/node_modules/@weavecode/harness/dist/codex/liveness.js +1 -1
  106. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -1
  107. package/node_modules/@weavecode/harness/dist/codex/messaging.js +2 -2
  108. package/node_modules/@weavecode/harness/dist/codex/narration.js +1 -1
  109. package/node_modules/@weavecode/harness/dist/codex/plugin-state.js +1 -1
  110. package/node_modules/@weavecode/harness/dist/codex/plugins.js +3 -3
  111. package/node_modules/@weavecode/harness/dist/codex/provision.js +1 -1
  112. package/node_modules/@weavecode/harness/dist/codex/questions.js +2 -2
  113. package/node_modules/@weavecode/harness/dist/codex/rollout.js +5 -5
  114. package/node_modules/@weavecode/harness/dist/codex/side-question.js +4 -4
  115. package/node_modules/@weavecode/harness/dist/codex/titles.js +4 -4
  116. package/node_modules/@weavecode/harness/dist/codex/toml.js +13 -13
  117. package/node_modules/@weavecode/harness/dist/codex/transcript.js +2 -2
  118. package/node_modules/@weavecode/harness/dist/driver.d.ts +56 -1
  119. package/node_modules/@weavecode/harness/dist/driver.js +1 -1
  120. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -2
  121. package/node_modules/@weavecode/harness/dist/init/pipeline.js +1 -1
  122. package/node_modules/@weavecode/harness/dist/registry-wiring.js +1 -1
  123. package/node_modules/@weavecode/harness/dist/shared/install-link.js +1 -1
  124. package/node_modules/@weavecode/harness/dist/shared/json-cap.js +1 -1
  125. package/node_modules/@weavecode/harness/package.json +2 -2
  126. package/node_modules/@weavecode/server/dist/config/profiles.d.ts +19 -13
  127. package/node_modules/@weavecode/server/dist/config/profiles.js +2 -2
  128. package/node_modules/@weavecode/server/dist/daemon/config-routes.js +1 -1
  129. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  130. package/node_modules/@weavecode/server/dist/daemon/entry.js +7 -1
  131. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  132. package/node_modules/@weavecode/server/dist/daemon/opener/launch.js +1 -1
  133. package/node_modules/@weavecode/server/dist/daemon/opener.d.ts +2 -0
  134. package/node_modules/@weavecode/server/dist/daemon/opener.js +1 -1
  135. package/node_modules/@weavecode/server/dist/daemon/routes/session-control.js +1 -1
  136. package/node_modules/@weavecode/server/dist/daemon/routes/session-insights.js +1 -1
  137. package/node_modules/@weavecode/server/dist/daemon/routes/uploads.js +1 -1
  138. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.d.ts +3 -0
  139. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.js +1 -0
  140. package/node_modules/@weavecode/server/dist/daemon/server.js +2 -2
  141. package/node_modules/@weavecode/server/dist/daemon/session-open.d.ts +17 -0
  142. package/node_modules/@weavecode/server/dist/daemon/session-open.js +1 -1
  143. package/node_modules/@weavecode/server/dist/daemon/session-probe.d.ts +5 -4
  144. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  145. package/node_modules/@weavecode/server/dist/db/db.js +6 -2
  146. package/node_modules/@weavecode/server/dist/hooks/bus.d.ts +3 -1
  147. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.d.ts +12 -6
  148. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.js +1 -1
  149. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.d.ts +3 -3
  150. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.js +1 -1
  151. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.d.ts +19 -9
  152. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.js +1 -1
  153. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.d.ts +2 -2
  154. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.js +1 -1
  155. package/node_modules/@weavecode/server/dist/hooks/delivery/views.d.ts +5 -1
  156. package/node_modules/@weavecode/server/dist/hooks/delivery/views.js +1 -1
  157. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.d.ts +45 -38
  158. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +5 -3
  159. package/node_modules/@weavecode/server/dist/repositories/hook-events.d.ts +1 -1
  160. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +4 -4
  161. package/node_modules/@weavecode/server/dist/repositories/sessions.d.ts +11 -1
  162. package/node_modules/@weavecode/server/dist/repositories/sessions.js +4 -2
  163. package/node_modules/@weavecode/server/dist/repositories/uploads.d.ts +14 -4
  164. package/node_modules/@weavecode/server/dist/repositories/uploads.js +11 -11
  165. package/node_modules/@weavecode/server/dist/surfaces.d.ts +3 -1
  166. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  167. package/node_modules/@weavecode/server/package.json +4 -4
  168. package/node_modules/@weavecode/server/web/dist/assets/{abnfDiagram-WEYOIA3C-C-f9WfD3.js → abnfDiagram-WEYOIA3C-DDeQkTf5.js} +1 -1
  169. package/node_modules/@weavecode/server/web/dist/assets/{arc-D62qulAD.js → arc-CRZTRyjb.js} +1 -1
  170. package/node_modules/@weavecode/server/web/dist/assets/{architectureDiagram-ZHVYKT53-B6ZJRpcL.js → architectureDiagram-ZHVYKT53-Dj54DE3O.js} +1 -1
  171. package/node_modules/@weavecode/server/web/dist/assets/{blockDiagram-RJAE7QA3-DOtDFeiT.js → blockDiagram-RJAE7QA3-BIH8mSIZ.js} +1 -1
  172. package/node_modules/@weavecode/server/web/dist/assets/{c4Diagram-XDPPPE54-DWn3ng8X.js → c4Diagram-XDPPPE54-5YoKWFOD.js} +1 -1
  173. package/node_modules/@weavecode/server/web/dist/assets/channel-5VM93AJ8.js +1 -0
  174. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2E7WHVMD-B5IIc9cn.js → chunk-2E7WHVMD-B653kMXt.js} +1 -1
  175. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2Q5K7J3B-BUU9Zvt8.js → chunk-2Q5K7J3B-f_A4_eDz.js} +1 -1
  176. package/node_modules/@weavecode/server/web/dist/assets/{chunk-4EMNKR2T-CqEGIghP.js → chunk-4EMNKR2T-v5j5qNGj.js} +1 -1
  177. package/node_modules/@weavecode/server/web/dist/assets/{chunk-55XCU76K-D36o_E2b.js → chunk-55XCU76K-CgEqeP7j.js} +1 -1
  178. package/node_modules/@weavecode/server/web/dist/assets/{chunk-5VM5RSS4-sxws8ERh.js → chunk-5VM5RSS4-BeROhLXN.js} +1 -1
  179. package/node_modules/@weavecode/server/web/dist/assets/{chunk-JWPE2WC7-CJo_rEEb.js → chunk-JWPE2WC7-D6dXb_jr.js} +1 -1
  180. package/node_modules/@weavecode/server/web/dist/assets/{chunk-VQ5W62QI-9UlLCpsb.js → chunk-VQ5W62QI-CnHdSEMi.js} +1 -1
  181. package/node_modules/@weavecode/server/web/dist/assets/{chunk-XXDRQBXY-CX9CPbWb.js → chunk-XXDRQBXY-BkG_e6PE.js} +1 -1
  182. package/node_modules/@weavecode/server/web/dist/assets/{chunk-ZCHMQSOR-DwEfdZcF.js → chunk-ZCHMQSOR-DxR-fxzs.js} +2 -2
  183. package/node_modules/@weavecode/server/web/dist/assets/{classDiagram-v2-4MYWR3UA-CFCmIyt8.js → classDiagram-v2-4MYWR3UA-DQe1b_k8.js} +1 -1
  184. package/node_modules/@weavecode/server/web/dist/assets/{cose-bilkent-JH36ORCC-qWXeXJTn.js → cose-bilkent-JH36ORCC-DThrA8S5.js} +1 -1
  185. package/node_modules/@weavecode/server/web/dist/assets/{cynefin-EF2NZ3EQ-CXabWQxz.js → cynefin-EF2NZ3EQ-OZotFKUu.js} +1 -1
  186. package/node_modules/@weavecode/server/web/dist/assets/{cynefinDiagram-WF24UDRP-Bzpj8Qbj.js → cynefinDiagram-WF24UDRP-DJjq2hfT.js} +1 -1
  187. package/node_modules/@weavecode/server/web/dist/assets/{dagre-NK4GIZVX-CXsL8t30.js → dagre-NK4GIZVX-C2vH93HT.js} +1 -1
  188. package/node_modules/@weavecode/server/web/dist/assets/{diagram-CBK3MWTC-xfR-zlAD.js → diagram-CBK3MWTC-DrF_ScM-.js} +1 -1
  189. package/node_modules/@weavecode/server/web/dist/assets/{diagram-I5XIIV2D-BjMqEsXr.js → diagram-I5XIIV2D-D1qoUJ4t.js} +1 -1
  190. package/node_modules/@weavecode/server/web/dist/assets/{diagram-ODIL2UCW-QZpf8KhT.js → diagram-ODIL2UCW-D9A6W8oB.js} +1 -1
  191. package/node_modules/@weavecode/server/web/dist/assets/{diagram-PFBEJUXE-Cw1ESWft.js → diagram-PFBEJUXE-PeI-eyu2.js} +1 -1
  192. package/node_modules/@weavecode/server/web/dist/assets/{diagram-RJA3I4VV-CAy2RYYZ.js → diagram-RJA3I4VV-DITY0Rd8.js} +1 -1
  193. package/node_modules/@weavecode/server/web/dist/assets/{diagram-TYUNFSNR-B09WciWt.js → diagram-TYUNFSNR-D5KieEw5.js} +1 -1
  194. package/node_modules/@weavecode/server/web/dist/assets/{ebnfDiagram-V4P3TTPT-DuLmHG0U.js → ebnfDiagram-V4P3TTPT-DDylK-gz.js} +1 -1
  195. package/node_modules/@weavecode/server/web/dist/assets/{elk-QONTBCTQ--zzx0EVP.js → elk-QONTBCTQ-D3xrVg0U.js} +1 -1
  196. package/node_modules/@weavecode/server/web/dist/assets/{erDiagram-KYQIGQAA-BPDjG5vB.js → erDiagram-KYQIGQAA-y_V1cor7.js} +1 -1
  197. package/node_modules/@weavecode/server/web/dist/assets/{flowDiagram-IUGLLWBU-DtE2M9a_.js → flowDiagram-IUGLLWBU-BJ8Z0MkF.js} +1 -1
  198. package/node_modules/@weavecode/server/web/dist/assets/{ganttDiagram-R7GPNTJY-B-4AaWVa.js → ganttDiagram-R7GPNTJY-C0q-CS1T.js} +1 -1
  199. package/node_modules/@weavecode/server/web/dist/assets/{gitGraphDiagram-PDYL7XHY-CYj5FGYx.js → gitGraphDiagram-PDYL7XHY-BYTComiB.js} +1 -1
  200. package/node_modules/@weavecode/server/web/dist/assets/index-BKxAxaVG.js +1091 -0
  201. package/node_modules/@weavecode/server/web/dist/assets/index-C0Sd4MH7.css +11 -0
  202. package/node_modules/@weavecode/server/web/dist/assets/{infoDiagram-MVDRKAX5-DHYSDj-3.js → infoDiagram-MVDRKAX5-DtixgjLP.js} +1 -1
  203. package/node_modules/@weavecode/server/web/dist/assets/{ishikawaDiagram-HPEHV2GE-CumAEBoU.js → ishikawaDiagram-HPEHV2GE-ChEnND76.js} +1 -1
  204. package/node_modules/@weavecode/server/web/dist/assets/{journeyDiagram-BOSHW7O7-ES3O3X05.js → journeyDiagram-BOSHW7O7-DHcNtpYF.js} +1 -1
  205. package/node_modules/@weavecode/server/web/dist/assets/{kanban-definition-FNSA4HC5-BMIrf0d9.js → kanban-definition-FNSA4HC5-Dft7qpW5.js} +1 -1
  206. package/node_modules/@weavecode/server/web/dist/assets/{linear-DEZ5FO1r.js → linear-DEo11t-X.js} +1 -1
  207. package/node_modules/@weavecode/server/web/dist/assets/{mermaid.core-D7gm2szA.js → mermaid.core-D_Dp_Kl2.js} +4 -4
  208. package/node_modules/@weavecode/server/web/dist/assets/{mindmap-definition-6OY57UG3-BBQP8lyN.js → mindmap-definition-6OY57UG3-CM6OAd_-.js} +1 -1
  209. package/node_modules/@weavecode/server/web/dist/assets/{pegDiagram-ECIUJNBX-DzkKsqmg.js → pegDiagram-ECIUJNBX-_QkY0h8Q.js} +1 -1
  210. package/node_modules/@weavecode/server/web/dist/assets/{pieDiagram-GNMPY74T-zR3q7Qs1.js → pieDiagram-GNMPY74T-ZGr5vtDj.js} +1 -1
  211. package/node_modules/@weavecode/server/web/dist/assets/{quadrantDiagram-D57K4MC3-B4xuIsMW.js → quadrantDiagram-D57K4MC3-D8pQ_PU2.js} +1 -1
  212. package/node_modules/@weavecode/server/web/dist/assets/{railroadDiagram-Y72NRBL7-D2I52m9D.js → railroadDiagram-Y72NRBL7-DUIo-WmA.js} +1 -1
  213. package/node_modules/@weavecode/server/web/dist/assets/{requirementDiagram-EQYSW5RA-aJ1KfKj2.js → requirementDiagram-EQYSW5RA-C90DU5Ny.js} +1 -1
  214. package/node_modules/@weavecode/server/web/dist/assets/{sankeyDiagram-SY24JHO5-CEq16Ecf.js → sankeyDiagram-SY24JHO5-B_poYGgJ.js} +1 -1
  215. package/node_modules/@weavecode/server/web/dist/assets/{sequenceDiagram-BLEHNHQU-Bc66KG9f.js → sequenceDiagram-BLEHNHQU-DDW7b2Dn.js} +1 -1
  216. package/node_modules/@weavecode/server/web/dist/assets/{sizeCapture-INFHLROL-Ddizw_UG.js → sizeCapture-INFHLROL-CmKoqX6K.js} +1 -1
  217. package/node_modules/@weavecode/server/web/dist/assets/{stateDiagram-v2-A6IESKWZ-C1eVtEX9.js → stateDiagram-v2-A6IESKWZ-CkVMAyxG.js} +1 -1
  218. package/node_modules/@weavecode/server/web/dist/assets/{swimlanes-B3ENRKFQ-CCd_KlpZ.js → swimlanes-B3ENRKFQ-Dm_Omzky.js} +1 -1
  219. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-Bjj8ZA4d.js +8 -0
  220. package/node_modules/@weavecode/server/web/dist/assets/{timeline-definition-JXYKGLGB-DqpBhIII.js → timeline-definition-JXYKGLGB-DnhkRGLb.js} +1 -1
  221. package/node_modules/@weavecode/server/web/dist/assets/{usecaseDiagram-WPOLBNNX-bX_jNjSt.js → usecaseDiagram-WPOLBNNX-_TdIjC6Z.js} +1 -1
  222. package/node_modules/@weavecode/server/web/dist/assets/{vennDiagram-Q3Y3IDCW-D07CUHl3.js → vennDiagram-Q3Y3IDCW-FzgsymXB.js} +1 -1
  223. package/node_modules/@weavecode/server/web/dist/assets/{wardleyDiagram-IVAIDKWA-CZ5ovcWa.js → wardleyDiagram-IVAIDKWA-BwqimStC.js} +1 -1
  224. package/node_modules/@weavecode/server/web/dist/assets/{xychartDiagram-4URNHDU4-CBTh52hU.js → xychartDiagram-4URNHDU4-CFjjVPIV.js} +1 -1
  225. package/node_modules/@weavecode/server/web/dist/icons/apple-touch-icon.png +0 -0
  226. package/node_modules/@weavecode/server/web/dist/icons/icon-192.png +0 -0
  227. package/node_modules/@weavecode/server/web/dist/icons/icon-512.png +0 -0
  228. package/node_modules/@weavecode/server/web/dist/icons/icon-maskable-512.png +0 -0
  229. package/node_modules/@weavecode/server/web/dist/index.html +11 -2
  230. package/node_modules/@weavecode/server/web/dist/manifest.webmanifest +16 -0
  231. package/node_modules/@weavecode/server/web/dist/sw.js +14 -12
  232. package/node_modules/@weavecode/templates/package.json +2 -2
  233. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/README.md +3 -8
  234. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/package.json +1 -1
  235. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.d.ts +4 -2
  236. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.es6.js +10 -1
  237. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.es6.mjs +10 -1
  238. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.js +10 -1
  239. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/README.md +3 -8
  240. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/package.json +1 -1
  241. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.d.ts +4 -2
  242. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.es6.js +10 -1
  243. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.es6.mjs +10 -1
  244. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.js +10 -1
  245. package/package.json +6 -6
  246. package/node_modules/@weavecode/server/web/dist/assets/channel-CjSr3Zfg.js +0 -1
  247. package/node_modules/@weavecode/server/web/dist/assets/index-BGdTLG4q.js +0 -1031
  248. package/node_modules/@weavecode/server/web/dist/assets/index-CEpJpR7P.css +0 -11
  249. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-yIifcHaR.js +0 -8
@@ -1,3 +1,5 @@
1
- import{randomUUID as R}from"node:crypto";import{chmodSync as y,mkdirSync as w,readFileSync as v,renameSync as O,writeFileSync as b}from"node:fs";import{dirname as I,join as g}from"node:path";import{isHarness as E}from"@weavecode/core";import{turnOutputOf as B}from"@weavecode/harness";import{isImageMediaType as T}from"../repositories/uploads.js";import{messagingSurfaceFor as L}from"../surfaces.js";import{pidAliveOf as F}from"../daemon/claude-liveness.js";import{combinedLivenessOf as A}from"../daemon/liveness.js";import{HeadlessRunner as N}from"./headless-runner.js";import{hooksRoot as Q}from"./mirror.js";import{INBOX_TARGETS_FILE as G,InboxSocketRegistry as W,deliverViaInboxSocket as J}from"./inbox-socket.js";import{AckGate as H}from"./delivery/ack-gate.js";import{ANSWER_ATOM as D,ANSWER_ATOM_GAP_MS as U,ANSWER_TEXT as V,CTRL_C as $,ENTER as X,ESC as z,MODEL_NAME as Z,SHIFT_TAB as Y,effortCommand as ee,effortLevelsOf as te,locateTerminalPane as se,modelCommand as ie,sessionKeysTarget as ne}from"./delivery/keys.js";import{hasImages as re,settleDelivered as P,spawnOnce as ae,wireTextOf as oe}from"./delivery/channels.js";import{deliverHeadless as le,deliverInject as ue,resolveChannel as he}from"./delivery/send.js";import{appendQueueEntry as de,failOffline as ce,failQueuedOffline as me,sessionJudgedDead as fe}from"./delivery/queue.js";import{runRelay as pe}from"./delivery/relay.js";import{listInflightCounts as ge,listVisible as ke,sessionTerminals as Se}from"./delivery/views.js";import{readPromptbox as k,removePromptboxBySession as ye,removePromptboxEntries as f,scanQueuedSessionIds as we}from"./promptbox.js";const ve=1e3,Oe=6e4,be=3e4,Ie=9e4,Ee=5e3,Te=8,Ae=250,De=5,Pe=200;export function isSlashCommand(m){return/^\/[A-Za-z][A-Za-z0-9:_-]*(\s|$)/.test(m.trim())}const x="pane-envs.json",_="pending-origins.json",M=15*6e4;function xe(m){try{const e=JSON.parse(v(m,"utf8"));if(!Array.isArray(e))return[];const t=[];for(const s of e){if(typeof s!="object"||s===null)continue;const i=s;if(!E(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)<M)}catch{return[]}}function _e(m){try{const e=JSON.parse(v(m,"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 p=m=>new Promise(e=>setTimeout(e,m)),j=300,C=1500,Me=1e3,je=12e4;export class MessageDeliverer{deps;headless;hooksDir;sideAnswerStore;memory=new Map;queuedSessions;inboxSockets;paneEnvs;revokedPaneEnvs=new Set;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 N({spawnImpl:e.spawnImpl,killImpl:e.killImpl}),this.hooksDir=e.hooksDir??Q(),this.sideAnswerStore=e.sideAnswerStore,this.inboxSockets=new W(g(this.hooksDir,G));const t=_e(g(this.hooksDir,x));this.paneEnvs=new Map(Object.entries(t)),this.persistedPaneEnvs=JSON.stringify(t),this.pendingOrigins=xe(g(this.hooksDir,_)),this.persistedPendingOrigins=JSON.stringify(this.pendingOrigins),this.queuedSessions=we(this.hooksDir),this.gate=new H({awaitingAck:this.awaitingAck,stalled:this.stalled,memory:this.memory},{ackStallMs:e.ackStallMs??be,ackStallReleaseMs:e.ackStallReleaseMs??Ie,commandAckGraceMs:e.commandAckGraceMs??Ee},{emit:s=>this.bus(s)}),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(h=>T(h.mediaType))&&!s.attach.kinds.includes("image"))return{ok:!1,status:409,error:"This harness cannot receive images"};if(i.some(h=>!T(h.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:R(),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 c=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}),c}getMessage(e){return this.memory.get(e)??null}listVisible(e){return ke(this.deps,this.hooksDir,this.memory,e,this.deps.visibleTtlMs??Oe)}hasQueued(e){return this.queuedSessions.has(e)}listInflightCounts(){return ge(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??ve).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,Ae))}return!0}lastTurnOutput(e){const t=this.deps.hookEvents.listBySession(e,De);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){this.paneEnvs.set(e,t),this.revokedPaneEnvs.delete(e),this.persistPaneEnvs()}notePendingOrigin(e){this.pendingOrigins=this.pendingOrigins.filter(t=>Date.now()-Date.parse(t.at)<M),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,x);try{w(I(t),{recursive:!0});const s=`${t}.tmp`;b(s,`${e}
2
- `,{encoding:"utf8",mode:384}),O(s,t),y(t,384),this.persistedPaneEnvs=e}catch{}}persistPendingOrigins(){const e=JSON.stringify(this.pendingOrigins);if(e===this.persistedPendingOrigins)return;const t=g(this.hooksDir,_);try{w(I(t),{recursive:!0});const s=`${t}.tmp`;b(s,`${e}
3
- `,{encoding:"utf8",mode:384}),O(s,t),y(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 Se(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?F(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,c=t?.prompt?o?{status:"ready",reason:null}:{status:"unavailable",reason:"no-peer-name"}:{status:"unavailable",reason:"no-mechanism"},h=this.paneEnvs.has(e),u=this.terminalChannel()?h?{status:"ready",reason:null}:{status:"unknown",reason:"no-pane-env"}:{status:"unavailable",reason:"no-backend"},d=this.deps.sessions.getBySessionId(e),S=d?.projectId==null?null:this.deps.projects.getById(d.projectId),q=S?k(this.hooksDir,S.token).filter(K=>K.sessionId===e).length:0;return{alive:i,inbox:l,queue:a,relay:c,terminal:u,paneEnvReported:h,pending:q,stalled:this.gate.isStalled(e)}}onSessionPrompt(e,t,s){const i=this.gate.acknowledge(e,t,s,{ackMinText:Te});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)&&!V.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 p(U),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,t="both",s){const i=await this.sessionKeysTarget(e,"\u51FB\u952E",t);if(!i.ok)return i;if(s!=null&&i.paneId===s)return{ok:!0,paneId:i.paneId,sent:!1};try{return await i.terminal.sendKeys(i.paneId,z),{ok:!0,paneId:i.paneId,sent:!0}}catch(n){return{ok:!1,status:409,error:n instanceof Error?n.message:String(n)}}}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,Y),{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,X),{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,$),{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(!Z.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,ie(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=te(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,ee(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 p(j),await t.sendKeys(s,r.submitKey).catch(()=>{}),await p(C);let o=await l();if((!o||!r.panelOpen(o))&&(await t.sendKeys(s,r.submitKey).catch(()=>{}),await p(C),o=await l(),!o||!r.panelOpen(o)))return;await t.sendText(s,n).catch(()=>{}),await p(j),await t.sendKeys(s,r.submitKey).catch(()=>{});const c=Date.now()+je;let h=null;for(;Date.now()<c;){if(await p(Me),o=await l(),o==null)return;const d=r.extractAnswer(n,a,o);if(d.done){h=d.answer;break}}h!=null&&(this.sideAnswerStore?.answerById(e,n,h),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",s="both"){return ne(this.keysDeps(),e,t,s)}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),isSlashCommand,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 oe(e,t=>this.surfaceOfSession(t))}hasImagesEntry(e){return re(e)}keysDeps(){return{sessions:this.deps.sessions,projects:this.deps.projects,hookEvents:this.deps.hookEvents,terminalChannel:()=>this.terminalChannel(),terminalPaneFor:(e,t,s)=>this.terminalPaneFor(e,t,s)}}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(f(this.hooksDir,i.token,new Set([t])),this.dismissedIds.add(t);this.dismissedIds.size>Pe;){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){f(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)){f(this.hooksDir,s.token,new Set([a.id])),this.settleQueueIndex(e,s.token);return}if(n&&await this.tryInboxDeliver(o,n)){f(this.hooksDir,s.token,new Set([a.id])),this.settleQueueIndex(e,s.token);return}const c=r?.resolve(e)??null,h=o.forceTerminal===!0?["terminal"]:o.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const u of h){if(u==="relay"&&r&&c){if(this.memory.set(o.id,{...o,status:"delivering",via:"relay"}),!this.runRelay(o,r,c.name)){this.memory.delete(o.id);return}this.awaitingAck.set(e,o.id),f(this.hooksDir,s.token,new Set([a.id]));break}if(u==="terminal"&&!l&&this.terminalChannel()){const d=await this.terminalPaneFor(t,s);if(d){f(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,d.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+=ye(this.hooksDir,e),this.queuedSessions.delete(e),this.gate.clearStall(e),this.gate.release(e),this.inboxSockets.forget(e),this.paneEnvs.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 E(s)?this.deps.surfaceFor?.(s)??L(s):null}resolveChannel(e,t,s){return he(this.deps.sessions,()=>this.terminalChannel()!=null,e,t,s)}async terminalPaneFor(e,t,s="both"){return se(this.terminalChannel(),this.paneEnvs,e,t,s)}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,c=e.forceTerminal===!0?["terminal"]:e.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const u of c){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 d=await this.terminalPaneFor(t,s);if(d)return this.memory.set(e.id,{...e,status:"delivering",via:"terminal"}),this.awaitingAck.set(e.sessionId,e.id),this.runTerminalPrompt(e.id,d.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 h={...e,status:"pending"};return{ok:!0,messageId:e.id,status:"pending",message:h}}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 ae(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 J(s,i,this.wireTextOfEntry(e))}catch{return this.memory.delete(e.id),null}return P(this.channelDeps(),e,"socket")}queueEntry(e,t){de(this.hooksDir,t,e),this.queuedSessions.add(e.sessionId)}sessionJudgedDead(e,t=this.deps.livenessOf?.()??A()){return fe(this.deps.sessions,e,t)}failOffline(e){return ce(this.memory,t=>this.bus(t),e)}failQueuedOffline(e,t){me(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),isSlashCommand,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 pe(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),isSlashCommand(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 ue({hooksDir:this.hooksDir,memory:this.memory,bus:this.busSafe()},e,t,s,i,this.wireTextOfEntry(e))}deliverHeadless(e,t,s,i){return le({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
+ 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{}}}
@@ -78,7 +78,7 @@ export declare class HookEventRepository {
78
78
  * 几 MB 的 tool_input 一起捞回来。`payload` 是归一化 JSON(toolName 顶格),故
79
79
  * 直接按 `"toolName":"<名>"` 匹配,不必解 JSON。
80
80
  */
81
- listByTools(sessionId: string, tools: readonly string[], needle: string | null, limit: number): HookEventRow[];
81
+ listByTools(sessionId: string, tools: readonly string[], needle: string | null, limit: number, sinceId?: number): HookEventRow[];
82
82
  /** `types` 非空只取这些事件类型(对话视图按开/闭轮类型翻页,不拉整条事件链)。 */
83
83
  listBySession(sessionId: string, limit?: number, beforeId?: number, types?: readonly string[]): HookEventRow[];
84
84
  /**
@@ -1,9 +1,9 @@
1
1
  import{HARNESS_LIFECYCLE as u}from"@weavecode/core";import{readDaemonSettingsSync as l,DEFAULT_EVENT_RETENTION_DAYS as _}from"../daemon/settings.js";export class HookEventRepository{db;lastPruneDay=-1;insertEvent;pruneByCutoff;constructor(e){this.db=e,this.insertEvent=e.prepare(`INSERT INTO hook_events (project_id, source, event_type, session_id, payload, created_at)
2
- VALUES (?, ?, ?, ?, ?, ?)`),this.pruneByCutoff=e.prepare("DELETE FROM hook_events WHERE created_at < ?")}resetPrune(){this.lastPruneDay=-1}insert(e){this.pruneExpired();const s=this.insertEvent.run(e.projectId,e.source,e.eventType,e.sessionId??null,e.payload,e.createdAt??new Date().toISOString());return Number(s.lastInsertRowid)}insertMany(e){this.pruneExpired();const s=[];this.db.exec("BEGIN");try{for(const t of e){const r=this.insertEvent.run(t.projectId,t.source,t.eventType,t.sessionId??null,t.payload,t.createdAt??new Date().toISOString());s.push(Number(r.lastInsertRowid))}this.db.exec("COMMIT")}catch(t){throw this.db.exec("ROLLBACK"),t}return s}pruneExpired(){const e=Math.floor(Date.now()/864e5);if(e===this.lastPruneDay)return;this.lastPruneDay=e;const s=l().events?.retentionDays??_,t=new Date((e-s)*864e5).toISOString();this.pruneByCutoff.run(t)}listByProject(e,s=100){return this.db.prepare("SELECT * FROM hook_events WHERE project_id = ? ORDER BY created_at DESC LIMIT ?").all(e,s).map(t=>c(t))}deleteBySession(e){return Number(this.db.prepare("DELETE FROM hook_events WHERE session_id = ?").run(e).changes)}deleteByProject(e){return Number(this.db.prepare("DELETE FROM hook_events WHERE project_id = ?").run(e).changes)}countAll(){return Number(this.db.prepare("SELECT COUNT(*) AS n FROM hook_events").get().n)}countSince(e,s){const t=this.db.prepare("SELECT COUNT(*) AS n FROM hook_events WHERE project_id = ? AND created_at >= ?");let r=0;for(const n of e)r+=Number(t.get(n,s).n);return r}seriesBySecond(e,s){const t=this.db.prepare(`SELECT substr(created_at, 1, 19) AS at, COUNT(*) AS n
3
- FROM hook_events WHERE project_id = ? AND created_at >= ? GROUP BY at`),r=new Map;for(const n of e)for(const a of t.all(n,s))r.set(a.at,(r.get(a.at)??0)+Number(a.n));return[...r].map(([n,a])=>({at:n,n:a})).sort((n,a)=>n.at<a.at?-1:1)}listByTools(e,s,t,r){if(s.length===0)return[];const n=["session_id = ?","event_type IN ('PreToolUse','PostToolUse')",`(${s.map(()=>"payload LIKE ?").join(" OR ")})`],a=[e,...s.map(p=>`%"toolName":"${p}"%`)];return t&&(n.push("payload LIKE ?"),a.push(`%${t}%`)),this.db.prepare(`SELECT * FROM hook_events WHERE ${n.join(" AND ")} ORDER BY id DESC LIMIT ?`).all(...a,r).map(p=>c(p))}listBySession(e,s=300,t,r){const n=["session_id = ?"],a=[e];return t!=null&&(n.push("id < ?"),a.push(t)),r?.length&&(n.push(`event_type IN (${r.map(()=>"?").join(",")})`),a.push(...r)),this.db.prepare(`SELECT * FROM hook_events WHERE ${n.join(" AND ")} ORDER BY id DESC LIMIT ?`).all(...a,s).map(p=>c(p)).reverse()}searchConversationTexts(e,s){const t=new Set;for(const i of Object.values(u)){t.add(i.open);for(const p of i.close)t.add(p)}const r=[...t].map(i=>`'${i}'`).join(","),n=h(e);return this.db.prepare(`SELECT id, project_id, source, event_type, session_id, payload, created_at
2
+ VALUES (?, ?, ?, ?, ?, ?)`),this.pruneByCutoff=e.prepare("DELETE FROM hook_events WHERE created_at < ?")}resetPrune(){this.lastPruneDay=-1}insert(e){this.pruneExpired();const s=this.insertEvent.run(e.projectId,e.source,e.eventType,e.sessionId??null,e.payload,e.createdAt??new Date().toISOString());return Number(s.lastInsertRowid)}insertMany(e){this.pruneExpired();const s=[];this.db.exec("BEGIN");try{for(const t of e){const o=this.insertEvent.run(t.projectId,t.source,t.eventType,t.sessionId??null,t.payload,t.createdAt??new Date().toISOString());s.push(Number(o.lastInsertRowid))}this.db.exec("COMMIT")}catch(t){throw this.db.exec("ROLLBACK"),t}return s}pruneExpired(){const e=Math.floor(Date.now()/864e5);if(e===this.lastPruneDay)return;this.lastPruneDay=e;const s=l().events?.retentionDays??_,t=new Date((e-s)*864e5).toISOString();this.pruneByCutoff.run(t)}listByProject(e,s=100){return this.db.prepare("SELECT * FROM hook_events WHERE project_id = ? ORDER BY created_at DESC LIMIT ?").all(e,s).map(t=>d(t))}deleteBySession(e){return Number(this.db.prepare("DELETE FROM hook_events WHERE session_id = ?").run(e).changes)}deleteByProject(e){return Number(this.db.prepare("DELETE FROM hook_events WHERE project_id = ?").run(e).changes)}countAll(){return Number(this.db.prepare("SELECT COUNT(*) AS n FROM hook_events").get().n)}countSince(e,s){const t=this.db.prepare("SELECT COUNT(*) AS n FROM hook_events WHERE project_id = ? AND created_at >= ?");let o=0;for(const r of e)o+=Number(t.get(r,s).n);return o}seriesBySecond(e,s){const t=this.db.prepare(`SELECT substr(created_at, 1, 19) AS at, COUNT(*) AS n
3
+ FROM hook_events WHERE project_id = ? AND created_at >= ? GROUP BY at`),o=new Map;for(const r of e)for(const a of t.all(r,s))o.set(a.at,(o.get(a.at)??0)+Number(a.n));return[...o].map(([r,a])=>({at:r,n:a})).sort((r,a)=>r.at<a.at?-1:1)}listByTools(e,s,t,o,r){if(s.length===0)return[];const a=["session_id = ?","event_type IN ('PreToolUse','PostToolUse')",`(${s.map(()=>"payload LIKE ?").join(" OR ")})`],n=[e,...s.map(c=>`%"toolName":"${c}"%`)];return t&&(a.push("payload LIKE ?"),n.push(`%${t}%`)),r!=null&&(a.push("id > ?"),n.push(r)),this.db.prepare(`SELECT * FROM hook_events WHERE ${a.join(" AND ")} ORDER BY id DESC LIMIT ?`).all(...n,o).map(c=>d(c))}listBySession(e,s=300,t,o){const r=["session_id = ?"],a=[e];return t!=null&&(r.push("id < ?"),a.push(t)),o?.length&&(r.push(`event_type IN (${o.map(()=>"?").join(",")})`),a.push(...o)),this.db.prepare(`SELECT * FROM hook_events WHERE ${r.join(" AND ")} ORDER BY id DESC LIMIT ?`).all(...a,s).map(p=>d(p)).reverse()}searchConversationTexts(e,s){const t=new Set;for(const n of Object.values(u)){t.add(n.open);for(const p of n.close)t.add(p)}const o=[...t].map(n=>`'${n}'`).join(","),r=h(e);return this.db.prepare(`SELECT id, project_id, source, event_type, session_id, payload, created_at
4
4
  FROM hook_events
5
- WHERE event_type IN (${r})
5
+ WHERE event_type IN (${o})
6
6
  AND (COALESCE(json_extract(payload, '$.raw.prompt'), '') LIKE '%' || ? || '%' ESCAPE '\\'
7
7
  OR COALESCE(json_extract(payload, '$.raw.last_assistant_message'), '') LIKE '%' || ? || '%' ESCAPE '\\')
8
8
  ORDER BY id DESC
9
- LIMIT ?`).all(n,n,s).map(i=>{const p=JSON.parse(String(i.payload)),E=d(p.raw?.prompt)??d(p.raw?.last_assistant_message)??"";return{eventId:Number(i.id),projectId:Number(i.project_id),source:String(i.source),eventType:String(i.event_type),sessionId:i.session_id==null?null:String(i.session_id),at:String(i.created_at),text:E}})}}function h(o){return o.replace(/[\\%_]/g,e=>`\\${e}`)}function d(o){return typeof o=="string"&&o.length>0?o:null}function c(o){return{id:Number(o.id),projectId:Number(o.project_id),source:String(o.source),eventType:String(o.event_type),sessionId:o.session_id==null?null:String(o.session_id),payload:String(o.payload),createdAt:String(o.created_at)}}
9
+ LIMIT ?`).all(r,r,s).map(n=>{const p=JSON.parse(String(n.payload)),c=E(p.raw?.prompt)??E(p.raw?.last_assistant_message)??"";return{eventId:Number(n.id),projectId:Number(n.project_id),source:String(n.source),eventType:String(n.event_type),sessionId:n.session_id==null?null:String(n.session_id),at:String(n.created_at),text:c}})}}function h(i){return i.replace(/[\\%_]/g,e=>`\\${e}`)}function E(i){return typeof i=="string"&&i.length>0?i:null}function d(i){return{id:Number(i.id),projectId:Number(i.project_id),source:String(i.source),eventType:String(i.event_type),sessionId:i.session_id==null?null:String(i.session_id),payload:String(i.payload),createdAt:String(i.created_at)}}
@@ -59,8 +59,11 @@ export declare class SessionRepository {
59
59
  /**
60
60
  * 会话列表 + 事件计数(任务视图左栏用):LEFT JOIN 一次查出避免 N+1。
61
61
  * 计数不过滤项目(会话可能有跨项目事件),与事件链的 sessionId-only 语义一致。
62
+ *
63
+ * `sessionIds` = 只算这几行(增量补丁用):事件只会改动它自己那条会话的
64
+ * 「最新事件 / 回合开合」判据,没必要为了一条事件把 200 行全部重算一遍。
62
65
  */
63
- listWithCounts(projectId?: number): SessionRow[];
66
+ listWithCounts(projectId?: number, sessionIds?: readonly string[]): SessionRow[];
64
67
  /**
65
68
  * 单会话 turnOpen(消息域 auto 裁决的忙/闲基准):语义与 listWithCounts 的
66
69
  * 计算字段完全一致(最后一条 UserPromptSubmit 晚于最后一条回合收尾事件,
@@ -74,6 +77,13 @@ export declare class SessionRepository {
74
77
  * 本来就还没有转录文件,那不算丢失。
75
78
  */
76
79
  hasRunOf(sessionId: string): boolean;
80
+ /**
81
+ * 最后一条**主回合**事件的真实时刻(排除 SubagentStop——后台子代理收尾与主回合
82
+ * 无关,可在主回合停下后很久才异步到达):「已中断」的盖过基准用它而不是
83
+ * lastSeenAt,否则中断后被 SubagentStop 盖回「生成中」(256de1f1 实测)。
84
+ * 事件名取生命周期表;无事件 / 会话不存在 → null。
85
+ */
86
+ lastMainEventAtOf(sessionId: string): string | null;
77
87
  /**
78
88
  * 单会话判活输入(`daemon/claude-liveness.ts` 的 `pidAliveOf` 消费形状)——
79
89
  * harness / lastEventType / eventCount 都是 listWithCounts 的计算字段,单行版与
@@ -1,5 +1,7 @@
1
- import{HARNESS_COMPACTION as c,HARNESS_LIFECYCLE as R,HARNESS_TOOL_EVENTS as T,isHarness as a}from"@weavecode/core";import{readDaemonSettingsSync as O,DEFAULT_SESSION_IDLE_DAYS as h}from"../daemon/settings.js";export const PROMPTLESS_GRACE_MS=60*6e4;function A(){return(O().sessions?.idleDays??h)*864e5}function d(i){const e=new Set;for(const t of Object.values(R)){for(const o of t.close)e.add(o);for(const o of t.sessionMarkers)e.add(o);t.sessionExit&&e.add(t.sessionExit)}const s=[...e].map(t=>`'${t}'`).join(","),n=Object.values(c).filter(t=>t.end&&t.endSource).map(t=>`(${i}.event_type = '${t.end}' AND COALESCE(json_extract(${i}.payload, '$.raw.source'), '') = '${t.endSource}')`).join(" OR ");return`${i}.event_type IN (${s})${n?` AND NOT (${n})`:""}`}function u(i){const e=new Set;for(const n of Object.values(T))for(const t of n)e.add(t);const s=[...e].map(n=>`'${n}'`).join(",");return`${i}.event_type IN (${s})`}export class SessionRepository{db;constructor(e){this.db=e}touch(e,s,n){const t=n??new Date().toISOString();return this.db.prepare(`INSERT INTO sessions (session_id, project_id, last_seen_at, created_at)
1
+ import{HARNESS_COMPACTION as h,HARNESS_LIFECYCLE as d,HARNESS_TOOL_EVENTS as O,isHarness as p}from"@weavecode/core";import{readDaemonSettingsSync as A,DEFAULT_SESSION_IDLE_DAYS as L}from"../daemon/settings.js";export const PROMPTLESS_GRACE_MS=60*6e4;function N(){return(A().sessions?.idleDays??L)*864e5}function S(i){const e=new Set;for(const n of Object.values(d)){for(const o of n.close)e.add(o);for(const o of n.sessionMarkers)e.add(o);n.sessionExit&&e.add(n.sessionExit)}const s=[...e].map(n=>`'${n}'`).join(","),t=Object.values(h).filter(n=>n.end&&n.endSource).map(n=>`(${i}.event_type = '${n.end}' AND COALESCE(json_extract(${i}.payload, '$.raw.source'), '') = '${n.endSource}')`).join(" OR ");return`${i}.event_type IN (${s})${t?` AND NOT (${t})`:""}`}function c(i){const e=new Set;for(const t of Object.values(O))for(const n of t)e.add(n);const s=[...e].map(t=>`'${t}'`).join(",");return`${i}.event_type IN (${s})`}export class SessionRepository{db;constructor(e){this.db=e}touch(e,s,t){const n=t??new Date().toISOString();return this.db.prepare(`INSERT INTO sessions (session_id, project_id, last_seen_at, created_at)
2
2
  VALUES (?, ?, ?, ?)
3
3
  ON CONFLICT(session_id) DO UPDATE SET
4
4
  last_seen_at = MAX(sessions.last_seen_at, excluded.last_seen_at),
5
- project_id = COALESCE(sessions.project_id, excluded.project_id)`).run(e,s??null,t,t),this.getBySessionId(e)}getBySessionId(e){const s=this.db.prepare("SELECT * FROM sessions WHERE session_id = ?").get(e);return s?E(s):void 0}countAll(){return Number(this.db.prepare("SELECT COUNT(*) AS n FROM sessions").get().n)}list(e){return(e===void 0?this.db.prepare("SELECT * FROM sessions ORDER BY created_at DESC LIMIT 200").all():this.db.prepare("SELECT * FROM sessions WHERE project_id = ? ORDER BY created_at DESC LIMIT 200").all(e)).map(E)}searchByTitle(e,s){const n=`%${e.replace(/[\\%_]/g,o=>`\\${o}`)}%`;return this.db.prepare("SELECT * FROM sessions WHERE title LIKE ? ESCAPE '\\' ORDER BY last_seen_at DESC LIMIT ?").all(n,s).map(E)}listWithCounts(e){const s=`SELECT s.*, COUNT(e.id) AS event_count, (SELECT e2.source FROM hook_events e2 WHERE e2.session_id = s.session_id ORDER BY e2.id DESC LIMIT 1) AS harness, (SELECT e5.event_type FROM hook_events e5 WHERE e5.session_id = s.session_id ORDER BY e5.id DESC LIMIT 1) AS last_event_type, (SELECT MAX(e3.id) FROM hook_events e3 WHERE e3.session_id = s.session_id AND e3.event_type = 'UserPromptSubmit') AS last_ups, (SELECT MAX(e6.id) FROM hook_events e6 WHERE e6.session_id = s.session_id AND ${d("e6")}) AS last_close, (SELECT MAX(e7.id) FROM hook_events e7 WHERE e7.session_id = s.session_id AND ${u("e7")}) AS last_tool, (SELECT MAX(e4.id) FROM hook_events e4 WHERE e4.session_id = s.session_id AND e4.event_type IN ('Stop', 'StopFailure', 'SessionEnd')) AS last_stop FROM sessions s LEFT JOIN hook_events e ON e.session_id = s.session_id`;return(e===void 0?this.db.prepare(`${s} GROUP BY s.session_id ORDER BY s.created_at DESC LIMIT 200`).all():this.db.prepare(`${s} WHERE s.project_id = ? GROUP BY s.session_id ORDER BY s.created_at DESC LIMIT 200`).all(e)).map(t=>{const o=t.harness,r=t.last_ups,l=t.last_close,_=t.last_tool,S=t.last_stop,p=t.last_event_type;return{...E(t),eventCount:Number(t.event_count??0),harness:a(o)?o:null,turnOpen:r!=null&&(l==null||Number(r)>Number(l))||_!=null&&(l==null||Number(_)>Number(l)),lastEventType:p??null,hasRun:r!=null||S!=null,autoDeleteAt:new Date(Date.parse(String(t.last_seen_at))+(r==null?PROMPTLESS_GRACE_MS:A())).toISOString(),promptless:r==null}})}turnOpenOf(e){const s=this.db.prepare(`SELECT (SELECT MAX(e3.id) FROM hook_events e3 WHERE e3.session_id = ? AND e3.event_type = 'UserPromptSubmit') AS last_ups, (SELECT MAX(e6.id) FROM hook_events e6 WHERE e6.session_id = ? AND ${d("e6")}) AS last_close, (SELECT MAX(e7.id) FROM hook_events e7 WHERE e7.session_id = ? AND ${u("e7")}) AS last_tool`).get(e,e,e);if(!this.getBySessionId(e))return null;const n=s?.last_ups??null,t=s?.last_close??null,o=s?.last_tool??null;return n!=null&&(t==null||Number(n)>Number(t))||o!=null&&(t==null||Number(o)>Number(t))}hasRunOf(e){const s=this.db.prepare("SELECT EXISTS(SELECT 1 FROM hook_events e WHERE e.session_id = ? AND e.event_type IN ('UserPromptSubmit','Stop','StopFailure','SessionEnd')) AS hit").get(e);return Number(s?.hit??0)>0}livenessRowOf(e){const s=this.db.prepare("SELECT s.session_id, s.last_seen_at, COUNT(e.id) AS event_count, (SELECT e2.source FROM hook_events e2 WHERE e2.session_id = s.session_id ORDER BY e2.id DESC LIMIT 1) AS harness, (SELECT e5.event_type FROM hook_events e5 WHERE e5.session_id = s.session_id ORDER BY e5.id DESC LIMIT 1) AS last_event_type FROM sessions s LEFT JOIN hook_events e ON e.session_id = s.session_id WHERE s.session_id = ? GROUP BY s.session_id").get(e);if(!s)return null;const n=s.harness;return{sessionId:String(s.session_id),harness:a(n)?n:null,lastSeenAt:String(s.last_seen_at),lastEventType:s.last_event_type==null?null:String(s.last_event_type),eventCount:Number(s.event_count??0)}}setPendingTitle(e,s){const n=this.getBySessionId(e);if(n)return n.pendingTitle===s?n:n.title===s?(n.pendingTitle!=null&&this.db.prepare("UPDATE sessions SET pending_title = NULL WHERE session_id = ?").run(e),this.getBySessionId(e)):(this.db.prepare("UPDATE sessions SET title = ?, pending_title = ? WHERE session_id = ?").run(s,s,e),this.getBySessionId(e))}applyReportedTitle(e,s){const n=this.getBySessionId(e);return n?n.pendingTitle!=null?s===n.pendingTitle?(this.db.prepare("UPDATE sessions SET title = ?, pending_title = NULL WHERE session_id = ?").run(s,e),n.title!==s):!1:s!=null&&s!==n.title?(this.db.prepare("UPDATE sessions SET title = ? WHERE session_id = ?").run(s,e),!0):!1:!1}confirmPendingTitle(e,s){return this.db.prepare("UPDATE sessions SET title = ?, pending_title = NULL WHERE session_id = ? AND pending_title = ?").run(s,e,s).changes>0}setTitle(e,s){return this.db.prepare("UPDATE sessions SET title = ?, pending_title = NULL WHERE session_id = ?").run(s,e),this.getBySessionId(e)}remove(e){this.db.prepare("DELETE FROM sessions WHERE session_id = ?").run(e)}removeByProject(e){return Number(this.db.prepare("DELETE FROM sessions WHERE project_id = ?").run(e).changes)}}function E(i){return{sessionId:String(i.session_id),projectId:i.project_id==null?null:Number(i.project_id),title:i.title==null?null:String(i.title),pendingTitle:i.pending_title==null?null:String(i.pending_title),lastSeenAt:String(i.last_seen_at),createdAt:String(i.created_at)}}
5
+ project_id = COALESCE(sessions.project_id, excluded.project_id)`).run(e,s??null,n,n),this.getBySessionId(e)}getBySessionId(e){const s=this.db.prepare("SELECT * FROM sessions WHERE session_id = ?").get(e);return s?_(s):void 0}countAll(){return Number(this.db.prepare("SELECT COUNT(*) AS n FROM sessions").get().n)}list(e){return(e===void 0?this.db.prepare("SELECT * FROM sessions ORDER BY created_at DESC LIMIT 200").all():this.db.prepare("SELECT * FROM sessions WHERE project_id = ? ORDER BY created_at DESC LIMIT 200").all(e)).map(_)}searchByTitle(e,s){const t=`%${e.replace(/[\\%_]/g,o=>`\\${o}`)}%`;return this.db.prepare("SELECT * FROM sessions WHERE title LIKE ? ESCAPE '\\' ORDER BY last_seen_at DESC LIMIT ?").all(t,s).map(_)}listWithCounts(e,s){const t=`SELECT s.*, (SELECT COUNT(*) FROM hook_events e WHERE e.session_id = s.session_id) AS event_count, (SELECT e2.source FROM hook_events e2 WHERE e2.session_id = s.session_id ORDER BY e2.id DESC LIMIT 1) AS harness, (SELECT e5.event_type FROM hook_events e5 WHERE e5.session_id = s.session_id ORDER BY e5.id DESC LIMIT 1) AS last_event_type, (SELECT MAX(e3.id) FROM hook_events e3 WHERE e3.session_id = s.session_id AND e3.event_type = 'UserPromptSubmit') AS last_ups, (SELECT MAX(e6.id) FROM hook_events e6 WHERE e6.session_id = s.session_id AND ${S("e6")}) AS last_close, (SELECT MAX(e7.id) FROM hook_events e7 WHERE e7.session_id = s.session_id AND ${c("e7")}) AS last_tool, (SELECT MAX(e4.id) FROM hook_events e4 WHERE e4.session_id = s.session_id AND e4.event_type IN ('Stop', 'StopFailure', 'SessionEnd')) AS last_stop FROM sessions s`,n=[],o=[];return e!==void 0&&(n.push("s.project_id = ?"),o.push(e)),s&&s.length>0&&(n.push(`s.session_id IN (${s.map(()=>"?").join(",")})`),o.push(...s)),this.db.prepare(`${t}${n.length>0?` WHERE ${n.join(" AND ")}`:""} ORDER BY s.created_at DESC LIMIT 200`).all(...o).map(r=>{const a=r.harness,l=r.last_ups,E=r.last_close,u=r.last_tool,R=r.last_stop,T=r.last_event_type;return{..._(r),eventCount:Number(r.event_count??0),harness:p(a)?a:null,turnOpen:l!=null&&(E==null||Number(l)>Number(E))||u!=null&&(E==null||Number(u)>Number(E)),lastEventType:T??null,hasRun:l!=null||R!=null,autoDeleteAt:new Date(Date.parse(String(r.last_seen_at))+(l==null?PROMPTLESS_GRACE_MS:N())).toISOString(),promptless:l==null}})}turnOpenOf(e){const s=this.db.prepare(`SELECT (SELECT MAX(e3.id) FROM hook_events e3 WHERE e3.session_id = ? AND e3.event_type = 'UserPromptSubmit') AS last_ups, (SELECT MAX(e6.id) FROM hook_events e6 WHERE e6.session_id = ? AND ${S("e6")}) AS last_close, (SELECT MAX(e7.id) FROM hook_events e7 WHERE e7.session_id = ? AND ${c("e7")}) AS last_tool`).get(e,e,e);if(!this.getBySessionId(e))return null;const t=s?.last_ups??null,n=s?.last_close??null,o=s?.last_tool??null;return t!=null&&(n==null||Number(t)>Number(n))||o!=null&&(n==null||Number(o)>Number(n))}hasRunOf(e){const s=this.db.prepare("SELECT EXISTS(SELECT 1 FROM hook_events e WHERE e.session_id = ? AND e.event_type IN ('UserPromptSubmit','Stop','StopFailure','SessionEnd')) AS hit").get(e);return Number(s?.hit??0)>0}lastMainEventAtOf(e){const s=[...new Set(Object.values(d).map(n=>n.subagentStop))].map(n=>`'${n}'`).join(","),t=this.db.prepare(`SELECT created_at FROM hook_events
6
+ WHERE session_id = ? AND event_type NOT IN (${s})
7
+ ORDER BY id DESC LIMIT 1`).get(e);return t?String(t.created_at):null}livenessRowOf(e){const s=this.db.prepare("SELECT s.session_id, s.last_seen_at, COUNT(e.id) AS event_count, (SELECT e2.source FROM hook_events e2 WHERE e2.session_id = s.session_id ORDER BY e2.id DESC LIMIT 1) AS harness, (SELECT e5.event_type FROM hook_events e5 WHERE e5.session_id = s.session_id ORDER BY e5.id DESC LIMIT 1) AS last_event_type FROM sessions s LEFT JOIN hook_events e ON e.session_id = s.session_id WHERE s.session_id = ? GROUP BY s.session_id").get(e);if(!s)return null;const t=s.harness;return{sessionId:String(s.session_id),harness:p(t)?t:null,lastSeenAt:String(s.last_seen_at),lastEventType:s.last_event_type==null?null:String(s.last_event_type),eventCount:Number(s.event_count??0)}}setPendingTitle(e,s){const t=this.getBySessionId(e);if(t)return t.pendingTitle===s?t:t.title===s?(t.pendingTitle!=null&&this.db.prepare("UPDATE sessions SET pending_title = NULL WHERE session_id = ?").run(e),this.getBySessionId(e)):(this.db.prepare("UPDATE sessions SET title = ?, pending_title = ? WHERE session_id = ?").run(s,s,e),this.getBySessionId(e))}applyReportedTitle(e,s){const t=this.getBySessionId(e);return t?t.pendingTitle!=null?s===t.pendingTitle?(this.db.prepare("UPDATE sessions SET title = ?, pending_title = NULL WHERE session_id = ?").run(s,e),t.title!==s):!1:s!=null&&s!==t.title?(this.db.prepare("UPDATE sessions SET title = ? WHERE session_id = ?").run(s,e),!0):!1:!1}confirmPendingTitle(e,s){return this.db.prepare("UPDATE sessions SET title = ?, pending_title = NULL WHERE session_id = ? AND pending_title = ?").run(s,e,s).changes>0}setTitle(e,s){return this.db.prepare("UPDATE sessions SET title = ?, pending_title = NULL WHERE session_id = ?").run(s,e),this.getBySessionId(e)}remove(e){this.db.prepare("DELETE FROM sessions WHERE session_id = ?").run(e)}removeByProject(e){return Number(this.db.prepare("DELETE FROM sessions WHERE project_id = ?").run(e).changes)}}function _(i){return{sessionId:String(i.session_id),projectId:i.project_id==null?null:Number(i.project_id),title:i.title==null?null:String(i.title),pendingTitle:i.pending_title==null?null:String(i.pending_title),lastSeenAt:String(i.last_seen_at),createdAt:String(i.created_at)}}
@@ -1,8 +1,10 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  /**
3
- * 会话上传件:文件内容寻址(sha256 = id)落 `<dataDir>/data/uploads/<id>.<ext>`,
4
- * 行只记展示名与媒体类型。**上传 ≠ 投递**——资源不因消息发送而搬家,harness
5
- * 拿到的是这个稳定绝对路径(claude 的粘贴处理器按扩展名认出它是图)。
3
+ * 会话上传件:文件内容寻址(sha256 = id)落
4
+ * `<dataDir>/data/uploads/<净化原名>-<id 前 16 位><ext>`——原名进路径,会话里才
5
+ * 看得见用户传的是哪个文件;行只记展示名与媒体类型。**上传 ≠ 投递**——资源不因
6
+ * 消息发送而搬家,harness 拿到的是这个稳定绝对路径(claude 的粘贴处理器按扩展名
7
+ * 认出它是图)。
6
8
  *
7
9
  * 图片四型 = claude 路径识别集 `\.(png|jpe?g|gif|webp)$`(宿主把它变成 image
8
10
  * block + 输入框 `[Image #N]` 占位);**其它类型宿主没有附件形态**,路径原样
@@ -67,8 +69,16 @@ export declare class UploadRepository {
67
69
  dir?: string | null;
68
70
  }): Promise<UploadRow>;
69
71
  getById(id: string): UploadRow | undefined;
70
- /** 磁盘绝对路径(harness 的 `composePrompt` 引用的就是它)。 */
72
+ /**
73
+ * 磁盘绝对路径(harness 的 `composePrompt` 引用的就是它):`<原名>-<id 前 16 位><ext>`。
74
+ * 原名进路径 = 会话 TUI / 转录 / 模型上下文直接看得见用户传的是哪个文件。
75
+ */
71
76
  filePath(id: string, mediaType: string, name: string, dir?: string): string;
77
+ /**
78
+ * 盘上真实路径:新形状优先,没有就回落旧形状 `<sha256><ext>`(存量件不迁移)。
79
+ * 两处都没有就答新形状(写入口据此建文件)。
80
+ */
81
+ pathOf(row: Pick<UploadRow, 'id' | 'mediaType' | 'name' | 'dir'>): string;
72
82
  /** 行的实际落盘目录:行里记了就用行里的,否则全局默认。 */
73
83
  private dirOf;
74
84
  /** 投递引用(id + 展示名 + 落盘绝对路径);任一 id 查不到即 null(整条拒绝)。 */
@@ -1,31 +1,31 @@
1
- import{createHash as m}from"node:crypto";import{createReadStream as l,mkdirSync as c,readFileSync as O,writeFileSync as f,existsSync as a,renameSync as g,rmSync as u,statSync as S}from"node:fs";import h from"node:path";import{getUploadsDir as y}from"../db/paths.js";export const UPLOAD_IMAGE_TYPES=["image/png","image/jpeg","image/gif","image/webp"],UPLOAD_MEDIA_TYPES=UPLOAD_IMAGE_TYPES;export function isImageMediaType(d){return UPLOAD_IMAGE_TYPES.includes(d)}export const UPLOAD_MAX_BYTES=10*1024*1024,UPLOAD_FILE_MAX_BYTES=512*1024*1024;export function maxUploadBytes(d){return isImageMediaType(d)?UPLOAD_MAX_BYTES:UPLOAD_FILE_MAX_BYTES}export const UPLOAD_CLEANUP_GRACE_MS=5*6e4,UPLOAD_ORPHAN_GRACE_MS=60*6e4;const _={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};function b(d,t){if(isImageMediaType(d))return _[d];const e=/\.([A-Za-z0-9]{1,10})$/.exec(t);return e?`.${e[1].toLowerCase()}`:".bin"}export class UploadRepository{db;dir;constructor(t,e=y()){this.db=t,this.dir=e}get defaultDir(){return this.dir}save(t){const e=m("sha256").update(t.bytes).digest("hex"),i=t.dir??this.dir;c(i,{recursive:!0});const r=this.filePath(e,t.mediaType,t.name,i);return a(r)||f(r,t.bytes),this.db.prepare(`INSERT INTO uploads (id, media_type, name, size, created_at, dir) VALUES (?, ?, ?, ?, ?, ?)
2
- ON CONFLICT(id) DO NOTHING`).run(e,t.mediaType,t.name,t.bytes.length,new Date().toISOString(),t.dir??null),this.getById(e)}async adoptFromFile(t){const e=m("sha256");await new Promise((o,p)=>{l(t.file).on("data",N=>e.update(N)).on("end",()=>o()).on("error",p)});const i=e.digest("hex"),r=S(t.file).size,s=t.dir??this.dir;c(s,{recursive:!0});const n=this.filePath(i,t.mediaType,t.name,s);return a(n)?u(t.file,{force:!0}):g(t.file,n),this.db.prepare(`INSERT INTO uploads (id, media_type, name, size, created_at, dir) VALUES (?, ?, ?, ?, ?, ?)
3
- ON CONFLICT(id) DO NOTHING`).run(i,t.mediaType,t.name,r,new Date().toISOString(),t.dir??null),this.getById(i)}getById(t){const e=this.db.prepare("SELECT * FROM uploads WHERE id = ?").get(t);return e?E(e):void 0}filePath(t,e,i,r=this.dir){return h.join(r,`${t}${b(e,i)}`)}dirOf(t){return t.dir??this.dir}refsOf(t){const e=[];for(const i of t){const r=this.getById(i);if(!r)return null;e.push({id:r.id,name:r.name,mediaType:r.mediaType,path:this.filePath(r.id,r.mediaType,r.name,this.dirOf(r))})}return e}fileStatOf(t){const e=this.getById(t);if(!e)return;const i=this.filePath(e.id,e.mediaType,e.name,this.dirOf(e));if(a(i))return{row:e,file:i,size:S(i).size}}fileOf(t){const e=this.getById(t);if(!e)return;const i=this.filePath(e.id,e.mediaType,e.name,this.dirOf(e));if(a(i))return{row:e,bytes:O(i)}}linkToEvent(t,e){const i=this.db.prepare("INSERT INTO event_images (event_id, upload_id) VALUES (?, ?) ON CONFLICT DO NOTHING");for(const r of e)i.run(t,r)}pruneUnreferenced(t=UPLOAD_ORPHAN_GRACE_MS,e=Date.now()){const i=this.db.prepare(`SELECT id, media_type, name, dir FROM uploads
4
- WHERE created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images)`).all(new Date(e-t).toISOString()),r=this.db.prepare("DELETE FROM uploads WHERE id = ?");for(const s of i)u(this.filePath(s.id,s.media_type,s.name,s.dir??this.dir),{force:!0}),r.run(s.id);return i.length}imagesBySession(t){const e=this.db.prepare(`SELECT e.event_id AS eventId, u.* FROM event_images e
1
+ import{createHash as m}from"node:crypto";import{createReadStream as y,mkdirSync as c,readFileSync as _,writeFileSync as f,existsSync as o,renameSync as S,rmSync as u,statSync as l}from"node:fs";import O from"node:path";import{getUploadsDir as b}from"../db/paths.js";export const UPLOAD_IMAGE_TYPES=["image/png","image/jpeg","image/gif","image/webp"],UPLOAD_MEDIA_TYPES=UPLOAD_IMAGE_TYPES;export function isImageMediaType(d){return UPLOAD_IMAGE_TYPES.includes(d)}export const UPLOAD_MAX_BYTES=10*1024*1024,UPLOAD_FILE_MAX_BYTES=512*1024*1024;export function maxUploadBytes(d){return isImageMediaType(d)?UPLOAD_MAX_BYTES:UPLOAD_FILE_MAX_BYTES}export const UPLOAD_CLEANUP_GRACE_MS=5*6e4,UPLOAD_ORPHAN_GRACE_MS=60*6e4;const T={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"},I=48,A=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;function C(d){const t=(d.split(/[\\/]/).pop()??"").replace(/\.[A-Za-z0-9]{1,10}$/,"").replace(/[\u0000-\u001f<>:"|?*]/g,"-").replace(/\s+/g,"-").replace(/^[.-]+/,"").replace(/[.-]+$/,"").slice(0,I);return t?A.test(t)?`_${t}`:t:""}function N(d,e){if(isImageMediaType(d))return T[d];const t=/\.([A-Za-z0-9]{1,10})$/.exec(e);return t?`.${t[1].toLowerCase()}`:".bin"}export class UploadRepository{db;dir;constructor(e,t=b()){this.db=e,this.dir=t}get defaultDir(){return this.dir}save(e){const t=m("sha256").update(e.bytes).digest("hex"),i=this.getById(t);if(i){const n=this.pathOf(i);return o(n)||(c(this.dirOf(i),{recursive:!0}),f(this.filePath(i.id,i.mediaType,i.name,this.dirOf(i)),e.bytes)),i}const r=e.dir??this.dir;c(r,{recursive:!0});const s=this.filePath(t,e.mediaType,e.name,r);return o(s)||f(s,e.bytes),this.db.prepare(`INSERT INTO uploads (id, media_type, name, size, created_at, dir) VALUES (?, ?, ?, ?, ?, ?)
2
+ ON CONFLICT(id) DO NOTHING`).run(t,e.mediaType,e.name,e.bytes.length,new Date().toISOString(),e.dir??null),this.getById(t)}async adoptFromFile(e){const t=m("sha256");await new Promise((E,h)=>{y(e.file).on("data",g=>t.update(g)).on("end",()=>E()).on("error",h)});const i=t.digest("hex"),r=l(e.file).size,s=this.getById(i);if(s){const E=this.pathOf(s);return o(E)?u(e.file,{force:!0}):(c(this.dirOf(s),{recursive:!0}),S(e.file,this.filePath(s.id,s.mediaType,s.name,this.dirOf(s)))),s}const n=e.dir??this.dir;c(n,{recursive:!0});const a=this.filePath(i,e.mediaType,e.name,n);return o(a)?u(e.file,{force:!0}):S(e.file,a),this.db.prepare(`INSERT INTO uploads (id, media_type, name, size, created_at, dir) VALUES (?, ?, ?, ?, ?, ?)
3
+ ON CONFLICT(id) DO NOTHING`).run(i,e.mediaType,e.name,r,new Date().toISOString(),e.dir??null),this.getById(i)}getById(e){const t=this.db.prepare("SELECT * FROM uploads WHERE id = ?").get(e);return t?p(t):void 0}filePath(e,t,i,r=this.dir){const s=C(i),n=e.slice(0,16);return O.join(r,`${s?`${s}-${n}`:n}${N(t,i)}`)}pathOf(e){const t=this.filePath(e.id,e.mediaType,e.name,this.dirOf(e));if(o(t))return t;const i=O.join(this.dirOf(e),`${e.id}${N(e.mediaType,e.name)}`);return o(i)?i:t}dirOf(e){return e.dir??this.dir}refsOf(e){const t=[];for(const i of e){const r=this.getById(i);if(!r)return null;t.push({id:r.id,name:r.name,mediaType:r.mediaType,path:this.pathOf(r)})}return t}fileStatOf(e){const t=this.getById(e);if(!t)return;const i=this.pathOf(t);if(o(i))return{row:t,file:i,size:l(i).size}}fileOf(e){const t=this.getById(e);if(!t)return;const i=this.pathOf(t);if(o(i))return{row:t,bytes:_(i)}}linkToEvent(e,t){const i=this.db.prepare("INSERT INTO event_images (event_id, upload_id) VALUES (?, ?) ON CONFLICT DO NOTHING");for(const r of t)i.run(e,r)}pruneUnreferenced(e=UPLOAD_ORPHAN_GRACE_MS,t=Date.now()){const i=this.db.prepare(`SELECT id, media_type, name, dir FROM uploads
4
+ WHERE created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images)`).all(new Date(t-e).toISOString()),r=this.db.prepare("DELETE FROM uploads WHERE id = ?");for(const s of i)u(this.pathOf({id:s.id,mediaType:s.media_type,name:s.name,dir:s.dir}),{force:!0}),r.run(s.id);return i.length}imagesBySession(e){const t=this.db.prepare(`SELECT e.event_id AS eventId, u.* FROM event_images e
5
5
  JOIN uploads u ON u.id = e.upload_id
6
6
  JOIN hook_events h ON h.id = e.event_id
7
7
  WHERE h.session_id = ?
8
- ORDER BY e.event_id, u.created_at`).all(t),i=new Map;for(const r of e){const s=Number(r.eventId),n=i.get(s)??[];n.push(E(r)),i.set(s,n)}return i}uploadsBySession(t){const e=this.db.prepare(`SELECT DISTINCT u.* FROM event_images e
8
+ ORDER BY e.event_id, u.created_at`).all(e),i=new Map;for(const r of t){const s=Number(r.eventId),n=i.get(s)??[];n.push(p(r)),i.set(s,n)}return i}uploadsBySession(e){const t=this.db.prepare(`SELECT DISTINCT u.* FROM event_images e
9
9
  JOIN uploads u ON u.id = e.upload_id
10
10
  JOIN hook_events h ON h.id = e.event_id
11
11
  WHERE h.session_id = ?
12
- ORDER BY u.created_at`).all(t);return e.length===0?null:e.map(E)}sessionBreakdown(t){const e=this.db.prepare(`SELECT u.media_type AS mediaType, COUNT(DISTINCT u.id) AS n, SUM(u.size) AS bytes
12
+ ORDER BY u.created_at`).all(e);return t.length===0?null:t.map(p)}sessionBreakdown(e){const t=this.db.prepare(`SELECT u.media_type AS mediaType, COUNT(DISTINCT u.id) AS n, SUM(u.size) AS bytes
13
13
  FROM event_images e
14
14
  JOIN uploads u ON u.id = e.upload_id
15
15
  JOIN hook_events h ON h.id = e.event_id
16
16
  WHERE h.session_id = ?
17
- GROUP BY u.media_type`).all(t);if(e.length===0)return null;let i={count:0,bytes:0};for(const s of e)isImageMediaType(String(s.mediaType))&&(i={count:i.count+Number(s.n),bytes:i.bytes+Number(s.bytes)});const r={count:e.reduce((s,n)=>s+Number(n.n),0),bytes:e.reduce((s,n)=>s+Number(n.bytes),0)};return{images:i,files:{count:r.count-i.count,bytes:r.bytes-i.bytes}}}usageBySession(){return this.db.prepare(`SELECT h.session_id AS sessionId, COUNT(DISTINCT u.id) AS count, COALESCE(SUM(u.size), 0) AS bytes
17
+ GROUP BY u.media_type`).all(e);if(t.length===0)return null;let i={count:0,bytes:0};for(const s of t)isImageMediaType(String(s.mediaType))&&(i={count:i.count+Number(s.n),bytes:i.bytes+Number(s.bytes)});const r={count:t.reduce((s,n)=>s+Number(n.n),0),bytes:t.reduce((s,n)=>s+Number(n.bytes),0)};return{images:i,files:{count:r.count-i.count,bytes:r.bytes-i.bytes}}}usageBySession(){return this.db.prepare(`SELECT h.session_id AS sessionId, COUNT(DISTINCT u.id) AS count, COALESCE(SUM(u.size), 0) AS bytes
18
18
  FROM event_images e
19
19
  JOIN uploads u ON u.id = e.upload_id
20
20
  JOIN hook_events h ON h.id = e.event_id
21
21
  GROUP BY h.session_id
22
- ORDER BY bytes DESC`).all().map(e=>({sessionId:String(e.sessionId),count:Number(e.count),bytes:Number(e.bytes)}))}removeMany(t){const e=this.db.prepare("DELETE FROM uploads WHERE id = ?");let i=0;for(const r of t){const s=this.getById(r);s&&(u(this.filePath(s.id,s.mediaType,s.name,this.dirOf(s)),{force:!0}),i+=Number(e.run(r).changes))}return i}unreferencedStats(t=UPLOAD_CLEANUP_GRACE_MS,e=Date.now()){const i=this.db.prepare(`SELECT COUNT(*) AS n, COALESCE(SUM(size), 0) AS bytes FROM uploads
23
- WHERE created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images)`).get(new Date(e-t).toISOString());return{count:Number(i.n),bytes:Number(i.bytes)}}overview(t=UPLOAD_CLEANUP_GRACE_MS,e=Date.now()){const i=new Date(e-t).toISOString(),r=this.db.prepare(`SELECT COUNT(*) AS n, COALESCE(SUM(size), 0) AS bytes,
22
+ ORDER BY bytes DESC`).all().map(t=>({sessionId:String(t.sessionId),count:Number(t.count),bytes:Number(t.bytes)}))}removeMany(e){const t=this.db.prepare("DELETE FROM uploads WHERE id = ?");let i=0;for(const r of e){const s=this.getById(r);s&&(u(this.pathOf(s),{force:!0}),i+=Number(t.run(r).changes))}return i}unreferencedStats(e=UPLOAD_CLEANUP_GRACE_MS,t=Date.now()){const i=this.db.prepare(`SELECT COUNT(*) AS n, COALESCE(SUM(size), 0) AS bytes FROM uploads
23
+ WHERE created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images)`).get(new Date(t-e).toISOString());return{count:Number(i.n),bytes:Number(i.bytes)}}overview(e=UPLOAD_CLEANUP_GRACE_MS,t=Date.now()){const i=new Date(t-e).toISOString(),r=this.db.prepare(`SELECT COUNT(*) AS n, COALESCE(SUM(size), 0) AS bytes,
24
24
  COALESCE(SUM(CASE WHEN media_type IN ('image/png','image/jpeg','image/gif','image/webp') THEN size ELSE 0 END), 0) AS imgBytes,
25
25
  COALESCE(SUM(CASE WHEN media_type IN ('image/png','image/jpeg','image/gif','image/webp') THEN 1 ELSE 0 END), 0) AS imgN,
26
26
  COALESCE(SUM(CASE WHEN id IN (SELECT upload_id FROM event_images) THEN size ELSE 0 END), 0) AS refBytes,
27
27
  COALESCE(SUM(CASE WHEN id IN (SELECT upload_id FROM event_images) THEN 1 ELSE 0 END), 0) AS refN,
28
28
  COALESCE(SUM(CASE WHEN created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images) THEN size ELSE 0 END), 0) AS unrefBytes,
29
29
  COALESCE(SUM(CASE WHEN created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images) THEN 1 ELSE 0 END), 0) AS unrefN
30
- FROM uploads`).get(i,i),s={count:Number(r.n),bytes:Number(r.bytes)},n={count:Number(r.imgN),bytes:Number(r.imgBytes)};return{total:s,images:n,files:{count:s.count-n.count,bytes:s.bytes-n.bytes},referenced:{count:Number(r.refN),bytes:Number(r.refBytes)},unreferenced:{count:Number(r.unrefN),bytes:Number(r.unrefBytes)}}}cleanupUnreferenced(t,e=UPLOAD_CLEANUP_GRACE_MS,i=Date.now()){const r=this.db.prepare(`SELECT id, media_type, name, dir FROM uploads
31
- WHERE created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images)`).all(new Date(i-e).toISOString()),s=this.db.prepare("DELETE FROM uploads WHERE id = ?");let n=0;for(const o of r)u(this.filePath(o.id,o.media_type,o.name,o.dir??this.dir),{force:!0}),n+=Number(s.run(o.id).changes),t(n,r.length);return n}}function E(d){return{id:String(d.id),mediaType:String(d.media_type),name:String(d.name),size:Number(d.size),createdAt:String(d.created_at),dir:d.dir==null?null:String(d.dir)}}
30
+ FROM uploads`).get(i,i),s={count:Number(r.n),bytes:Number(r.bytes)},n={count:Number(r.imgN),bytes:Number(r.imgBytes)};return{total:s,images:n,files:{count:s.count-n.count,bytes:s.bytes-n.bytes},referenced:{count:Number(r.refN),bytes:Number(r.refBytes)},unreferenced:{count:Number(r.unrefN),bytes:Number(r.unrefBytes)}}}cleanupUnreferenced(e,t=UPLOAD_CLEANUP_GRACE_MS,i=Date.now()){const r=this.db.prepare(`SELECT id, media_type, name, dir FROM uploads
31
+ WHERE created_at <= ? AND id NOT IN (SELECT upload_id FROM event_images)`).all(new Date(i-t).toISOString()),s=this.db.prepare("DELETE FROM uploads WHERE id = ?");let n=0;for(const a of r)u(this.pathOf({id:a.id,mediaType:a.media_type,name:a.name,dir:a.dir}),{force:!0}),n+=Number(s.run(a.id).changes),e(n,r.length);return n}}function p(d){return{id:String(d.id),mediaType:String(d.media_type),name:String(d.name),size:Number(d.size),createdAt:String(d.created_at),dir:d.dir==null?null:String(d.dir)}}
@@ -1,5 +1,5 @@
1
1
  import type { Harness } from '@weavecode/core';
2
- import { type AssetSurface, type BlockingPromptSpec, type CaptureSurface, type CommandsSurface, type ConfigSurface, type EditsSurface, type ImagesSurface, type MessagingSurface, type NarrationSurface, type PluginStateSurface, type PluginSurface, type SessionTitleSurface, type StatuslineSurface } from '@weavecode/harness';
2
+ import { type AssetSurface, type BlockingPromptSpec, type CaptureSurface, type CommandsSurface, type ConfigSurface, type EditsSurface, type ImagesSurface, type MessagingSurface, type NarrationSurface, type PluginStateSurface, type PluginSurface, type RewindSurface, type SessionTitleSurface, type StatuslineSurface } from '@weavecode/harness';
3
3
  /** 按 harness 取资产表面;未注册或未补 assets 槽抛错。 */
4
4
  export declare function assetSurfaceFor(harness: Harness): AssetSurface;
5
5
  /**
@@ -69,6 +69,8 @@ export declare function editSurfaceFor(harness: Harness): EditsSurface | null;
69
69
  export declare function imagesSurfaceFor(harness: Harness): ImagesSurface | null;
70
70
  /** 按 harness 取旁白面;null = 该 harness 的中间输出无处可取(对话里只有每轮收尾那句)。 */
71
71
  export declare function narrationSurfaceFor(harness: Harness): NarrationSurface | null;
72
+ /** 按 harness 取回退面;null = 该 harness 的 rewind 不可观测(前端不摆「已回退」标记)。 */
73
+ export declare function rewindSurfaceFor(harness: Harness): RewindSurface | null;
72
74
  /** 按 harness 取命令面;null = 该 harness 没有 `/` 提示(前端不弹命令菜单)。 */
73
75
  export declare function commandsSurfaceFor(harness: Harness): CommandsSurface | null;
74
76
  /** 全部声明了 config 槽的 (harness, 面) 列表——配置面板的 harness 页签按本表枚举。 */
@@ -1 +1 @@
1
- import{createRuntimeRegistry as n}from"@weavecode/harness";const r=n();export function assetSurfaceFor(e){const t=r.get(e)?.assets;if(!t)throw new Error(`no asset surface registered for harness: ${e}`);return t}export function assetSurfaces(){return r.all().map(e=>e.assets).filter(e=>e!==void 0)}export function pluginSurfaceFor(e){const t=r.get(e)?.plugins;if(!t)throw new Error(`no plugin surface registered for harness: ${e}`);return t}export function pluginSurfaces(){return r.all().filter(e=>e.plugins!==void 0).map(e=>({harness:e.id,surface:e.plugins}))}export function pluginStateFor(e){const t=r.get(e)?.pluginState;if(!t)throw new Error(`no plugin state surface registered for harness: ${e}`);return t}export function pluginStateSurfaces(){return r.all().filter(e=>e.pluginState!==void 0).map(e=>({harness:e.id,state:e.pluginState}))}export function messagingSurfaceFor(e){const t=r.get(e)?.messaging;if(!t)throw new Error(`no messaging surface registered for harness: ${e}`);return t}export function messagingSurfaces(){return r.all().filter(e=>e.messaging!==void 0).map(e=>({harness:e.id,surface:e.messaging}))}export function captureSurfaces(){return r.all().filter(e=>e.capture!==void 0).map(e=>({harness:e.id,surface:e.capture}))}export function blockingPromptFor(e){return r.get(e)?.questions??null}export function statuslineSurfaceFor(e){return r.get(e)?.statusline??null}export function statuslineSurfaces(){return r.all().filter(e=>e.statusline!==void 0).map(e=>({harness:e.id,surface:e.statusline}))}export function configSurfaceFor(e){return r.get(e)?.config??null}export function editSurfaceFor(e){return r.get(e)?.edits??null}export function imagesSurfaceFor(e){return r.get(e)?.images??null}export function narrationSurfaceFor(e){return r.get(e)?.narration??null}export function commandsSurfaceFor(e){return r.get(e)?.commands??null}export function configSurfaces(){return r.all().filter(e=>e.config!==void 0).map(e=>({harness:e.id,surface:e.config}))}export function sessionTitleSurfaceFor(e){return r.get(e)?.titles??null}
1
+ import{createRuntimeRegistry as t}from"@weavecode/harness";const r=t();export function assetSurfaceFor(e){const n=r.get(e)?.assets;if(!n)throw new Error(`no asset surface registered for harness: ${e}`);return n}export function assetSurfaces(){return r.all().map(e=>e.assets).filter(e=>e!==void 0)}export function pluginSurfaceFor(e){const n=r.get(e)?.plugins;if(!n)throw new Error(`no plugin surface registered for harness: ${e}`);return n}export function pluginSurfaces(){return r.all().filter(e=>e.plugins!==void 0).map(e=>({harness:e.id,surface:e.plugins}))}export function pluginStateFor(e){const n=r.get(e)?.pluginState;if(!n)throw new Error(`no plugin state surface registered for harness: ${e}`);return n}export function pluginStateSurfaces(){return r.all().filter(e=>e.pluginState!==void 0).map(e=>({harness:e.id,state:e.pluginState}))}export function messagingSurfaceFor(e){const n=r.get(e)?.messaging;if(!n)throw new Error(`no messaging surface registered for harness: ${e}`);return n}export function messagingSurfaces(){return r.all().filter(e=>e.messaging!==void 0).map(e=>({harness:e.id,surface:e.messaging}))}export function captureSurfaces(){return r.all().filter(e=>e.capture!==void 0).map(e=>({harness:e.id,surface:e.capture}))}export function blockingPromptFor(e){return r.get(e)?.questions??null}export function statuslineSurfaceFor(e){return r.get(e)?.statusline??null}export function statuslineSurfaces(){return r.all().filter(e=>e.statusline!==void 0).map(e=>({harness:e.id,surface:e.statusline}))}export function configSurfaceFor(e){return r.get(e)?.config??null}export function editSurfaceFor(e){return r.get(e)?.edits??null}export function imagesSurfaceFor(e){return r.get(e)?.images??null}export function narrationSurfaceFor(e){return r.get(e)?.narration??null}export function rewindSurfaceFor(e){return r.get(e)?.rewind??null}export function commandsSurfaceFor(e){return r.get(e)?.commands??null}export function configSurfaces(){return r.all().filter(e=>e.config!==void 0).map(e=>({harness:e.id,surface:e.config}))}export function sessionTitleSurfaceFor(e){return r.get(e)?.titles??null}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weavecode/server",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Weave daemon — HTTP server, SQLite data layer, and hook ingestion",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,9 +21,9 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@modelcontextprotocol/sdk": "1.32.1",
24
- "@weavecode/core": "^0.1.5",
25
- "@weavecode/harness": "^0.1.5",
26
- "@weavecode/templates": "^0.1.5",
24
+ "@weavecode/core": "^0.1.7",
25
+ "@weavecode/harness": "^0.1.7",
26
+ "@weavecode/templates": "^0.1.7",
27
27
  "chokidar": "^4.0.0",
28
28
  "selfsigned": "^5.5.0",
29
29
  "smol-toml": "^1.3.0",
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-2E7WHVMD-B5IIc9cn.js";import{p as f}from"./chunk-JWPE2WC7-CJo_rEEb.js";import{_ as n,l as o}from"./mermaid.core-D7gm2szA.js";import"./index-BGdTLG4q.js";import{M as c,b as d}from"./cynefin-EF2NZ3EQ-CXabWQxz.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-2E7WHVMD-B653kMXt.js";import{p as f}from"./chunk-JWPE2WC7-D6dXb_jr.js";import{_ as n,l as o}from"./mermaid.core-D_Dp_Kl2.js";import"./index-BKxAxaVG.js";import{M as c,b as d}from"./cynefin-EF2NZ3EQ-OZotFKUu.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
@@ -1 +1 @@
1
- import{a5 as ln,a6 as an,a7 as H,a8 as j,a9 as B,aa as un,ab as g,ac as tn,ad as L,ae as _,af as rn,ag as o,ah as on,ai as sn,aj as fn}from"./mermaid.core-D7gm2szA.js";function cn(l){return l.innerRadius}function gn(l){return l.outerRadius}function yn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,E,q,v,A,C,a){var I=E-l,i=q-h,n=C-v,d=a-A,u=d*I-n*i;if(!(u*u<g))return u=(n*(h-A)-d*(l-v))/u,[l+u*I,h+u*i]}function W(l,h,E,q,v,A,C){var a=l-E,I=h-q,i=(C?A:-A)/L(a*a+I*I),n=i*I,d=-i*a,u=l+n,s=h+d,f=E+n,c=q+d,F=(u+f)/2,t=(s+c)/2,m=f-u,y=c-s,R=m*m+y*y,T=v-A,P=u*c-f*s,O=(y<0?-1:1)*L(on(0,T*T*R-P*P)),S=(P*y-m*O)/R,z=(-P*m-y*O)/R,w=(P*y+m*O)/R,p=(-P*m+y*O)/R,x=S-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(S=w,z=p),{cx:S,cy:z,x01:-n,y01:-d,x11:S*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=gn,E=B(0),q=null,v=yn,A=dn,C=mn,a=null,I=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,F=rn(c-f),t=c>f;if(a||(a=n=I()),s<u&&(d=s,s=u,u=d),!(s>g))a.moveTo(0,0);else if(F>tn-g)a.moveTo(s*H(f),s*j(f)),a.arc(0,0,s,f,c,!t),u>g&&(a.moveTo(u*H(c),u*j(c)),a.arc(0,0,u,c,f,t));else{var m=f,y=c,R=f,T=c,P=F,O=F,S=C.apply(this,arguments)/2,z=S>g&&(q?+q.apply(this,arguments):L(u*u+s*s)),w=_(rn(s-u)/2,+E.apply(this,arguments)),p=w,x=w,e,r;if(z>g){var G=sn(z/u*j(S)),M=sn(z/s*j(S));(P-=G*2)>g?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(O-=M*2)>g?(M*=t?1:-1,m+=M,y-=M):(O=0,m=y=(f+c)/2)}var J=s*H(m),K=s*j(m),N=u*H(T),Q=u*j(T);if(w>g){var U=s*H(y),V=s*j(y),X=u*H(R),Y=u*j(R),D;if(F<an)if(D=pn(J,K,X,Y,U,V,N,Q)){var Z=J-D[0],$=K-D[1],b=U-D[0],k=V-D[1],nn=1/j(fn((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(D[0]*D[0]+D[1]*D[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}O>g?x>g?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,y,!t)):a.moveTo(J,K),!(u>g)||!(P>g)?a.lineTo(N,Q):p>g?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[H(d)*n,j(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(E=typeof n=="function"?n:B(+n),i):E},i.padRadius=function(n){return arguments.length?(q=n==null?null:typeof n=="function"?n:B(+n),i):q},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{a5 as ln,a6 as an,a7 as H,a8 as j,a9 as B,aa as un,ab as g,ac as tn,ad as L,ae as _,af as rn,ag as o,ah as on,ai as sn,aj as fn}from"./mermaid.core-D_Dp_Kl2.js";function cn(l){return l.innerRadius}function gn(l){return l.outerRadius}function yn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,E,q,v,A,C,a){var I=E-l,i=q-h,n=C-v,d=a-A,u=d*I-n*i;if(!(u*u<g))return u=(n*(h-A)-d*(l-v))/u,[l+u*I,h+u*i]}function W(l,h,E,q,v,A,C){var a=l-E,I=h-q,i=(C?A:-A)/L(a*a+I*I),n=i*I,d=-i*a,u=l+n,s=h+d,f=E+n,c=q+d,F=(u+f)/2,t=(s+c)/2,m=f-u,y=c-s,R=m*m+y*y,T=v-A,P=u*c-f*s,O=(y<0?-1:1)*L(on(0,T*T*R-P*P)),S=(P*y-m*O)/R,z=(-P*m-y*O)/R,w=(P*y+m*O)/R,p=(-P*m+y*O)/R,x=S-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(S=w,z=p),{cx:S,cy:z,x01:-n,y01:-d,x11:S*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=gn,E=B(0),q=null,v=yn,A=dn,C=mn,a=null,I=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,F=rn(c-f),t=c>f;if(a||(a=n=I()),s<u&&(d=s,s=u,u=d),!(s>g))a.moveTo(0,0);else if(F>tn-g)a.moveTo(s*H(f),s*j(f)),a.arc(0,0,s,f,c,!t),u>g&&(a.moveTo(u*H(c),u*j(c)),a.arc(0,0,u,c,f,t));else{var m=f,y=c,R=f,T=c,P=F,O=F,S=C.apply(this,arguments)/2,z=S>g&&(q?+q.apply(this,arguments):L(u*u+s*s)),w=_(rn(s-u)/2,+E.apply(this,arguments)),p=w,x=w,e,r;if(z>g){var G=sn(z/u*j(S)),M=sn(z/s*j(S));(P-=G*2)>g?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(O-=M*2)>g?(M*=t?1:-1,m+=M,y-=M):(O=0,m=y=(f+c)/2)}var J=s*H(m),K=s*j(m),N=u*H(T),Q=u*j(T);if(w>g){var U=s*H(y),V=s*j(y),X=u*H(R),Y=u*j(R),D;if(F<an)if(D=pn(J,K,X,Y,U,V,N,Q)){var Z=J-D[0],$=K-D[1],b=U-D[0],k=V-D[1],nn=1/j(fn((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(D[0]*D[0]+D[1]*D[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}O>g?x>g?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,y,!t)):a.moveTo(J,K),!(u>g)||!(P>g)?a.lineTo(N,Q):p>g?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[H(d)*n,j(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(E=typeof n=="function"?n:B(+n),i):E},i.padRadius=function(n){return arguments.length?(q=n==null?null:typeof n=="function"?n:B(+n),i):q},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};