@weavecode/weave 0.1.7 → 0.1.8

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 (194) hide show
  1. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +1 -1
  2. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
  3. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/context.js +1 -1
  4. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/helper/css/common.js +3 -5
  5. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/hono-base.js +4 -10
  6. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/hono.js +0 -1
  7. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/basic-auth/index.js +1 -1
  8. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/bearer-auth/index.js +1 -1
  9. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/csrf/index.js +2 -2
  10. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +2 -2
  11. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +2 -2
  12. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/mount/index.js +4 -4
  13. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +13 -11
  14. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/prepared-router.js +4 -4
  15. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +39 -51
  16. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +15 -5
  17. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/utils/jwt/jwt.js +2 -1
  18. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/utils/mount.js +35 -0
  19. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/utils/url.js +10 -0
  20. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/validator/validator.js +1 -1
  21. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/context.js +1 -1
  22. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/helper/css/common.js +3 -5
  23. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/hono-base.js +4 -10
  24. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/hono.js +0 -1
  25. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/basic-auth/index.js +1 -1
  26. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/bearer-auth/index.js +1 -1
  27. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/csrf/index.js +2 -2
  28. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/jwk/jwk.js +2 -2
  29. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/jwt/jwt.js +2 -2
  30. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/language/language.js +1 -1
  31. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/mount/index.js +4 -4
  32. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/node.js +13 -11
  33. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/prepared-router.js +5 -5
  34. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/router.js +40 -52
  35. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/trie.js +15 -5
  36. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/middleware/mount/index.d.ts +1 -0
  37. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +3 -3
  38. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +1 -1
  39. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/utils/mount.d.ts +4 -0
  40. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/utils/url.d.ts +1 -0
  41. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/utils/jwt/jwt.js +2 -1
  42. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/utils/mount.js +34 -0
  43. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/utils/url.js +10 -1
  44. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/validator/validator.js +1 -1
  45. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/package.json +1 -1
  46. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/remote.js +3 -1
  47. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/deflate.js +2 -1
  48. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +2 -1
  49. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/package.json +1 -1
  50. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  51. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +1 -1
  52. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +1 -1
  53. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +3 -3
  54. package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
  55. package/node_modules/@weavecode/cli/dist/statusline/mock-input.js +1 -1
  56. package/node_modules/@weavecode/cli/dist/statusline/preview.js +2 -2
  57. package/node_modules/@weavecode/cli/package.json +5 -5
  58. package/node_modules/@weavecode/core/dist/harness.d.ts +78 -0
  59. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  60. package/node_modules/@weavecode/core/dist/index.d.ts +1 -1
  61. package/node_modules/@weavecode/core/dist/index.js +1 -1
  62. package/node_modules/@weavecode/core/package.json +1 -1
  63. package/node_modules/@weavecode/harness/dist/claude/commands.d.ts +2 -0
  64. package/node_modules/@weavecode/harness/dist/claude/commands.js +3 -2
  65. package/node_modules/@weavecode/harness/dist/driver.d.ts +6 -0
  66. package/node_modules/@weavecode/harness/dist/zcode/assets.js +1 -1
  67. package/node_modules/@weavecode/harness/dist/zcode/capture.js +3 -3
  68. package/node_modules/@weavecode/harness/dist/zcode/mcp.js +2 -2
  69. package/node_modules/@weavecode/harness/package.json +2 -2
  70. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  71. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  72. package/node_modules/@weavecode/server/dist/daemon/opener/launch.js +1 -1
  73. package/node_modules/@weavecode/server/dist/daemon/pet-seed.d.ts +6 -0
  74. package/node_modules/@weavecode/server/dist/daemon/pet-seed.js +1 -0
  75. package/node_modules/@weavecode/server/dist/daemon/pet-window.d.ts +17 -0
  76. package/node_modules/@weavecode/server/dist/daemon/pet-window.js +2 -0
  77. package/node_modules/@weavecode/server/dist/daemon/project-files.d.ts +1 -1
  78. package/node_modules/@weavecode/server/dist/daemon/project-files.js +2 -2
  79. package/node_modules/@weavecode/server/dist/daemon/routes/pets.d.ts +3 -0
  80. package/node_modules/@weavecode/server/dist/daemon/routes/pets.js +1 -0
  81. package/node_modules/@weavecode/server/dist/daemon/routes/settings-statusline.js +1 -1
  82. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.js +2 -1
  83. package/node_modules/@weavecode/server/dist/daemon/server.d.ts +2 -0
  84. package/node_modules/@weavecode/server/dist/daemon/settings.d.ts +21 -0
  85. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  86. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  87. package/node_modules/@weavecode/server/dist/db/db.d.ts +4 -1
  88. package/node_modules/@weavecode/server/dist/db/db.js +2 -2
  89. package/node_modules/@weavecode/server/dist/db/paths.d.ts +4 -0
  90. package/node_modules/@weavecode/server/dist/db/paths.js +1 -1
  91. package/node_modules/@weavecode/server/dist/index.d.ts +1 -1
  92. package/node_modules/@weavecode/server/dist/index.js +1 -1
  93. package/node_modules/@weavecode/server/dist/repositories/hook-events.d.ts +6 -0
  94. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +8 -5
  95. package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
  96. package/node_modules/@weavecode/server/package.json +4 -4
  97. package/node_modules/@weavecode/server/web/dist/assets/abnfDiagram-WEYOIA3C-t5OQjhuS.js +1 -0
  98. package/node_modules/@weavecode/server/web/dist/assets/{arc-CRZTRyjb.js → arc-De-uH_Q9.js} +1 -1
  99. package/node_modules/@weavecode/server/web/dist/assets/architectureDiagram-ZHVYKT53-ImPclD43.js +36 -0
  100. package/node_modules/@weavecode/server/web/dist/assets/{blockDiagram-RJAE7QA3-BIH8mSIZ.js → blockDiagram-RJAE7QA3-B5xEQs6X.js} +2 -2
  101. package/node_modules/@weavecode/server/web/dist/assets/{c4Diagram-XDPPPE54-5YoKWFOD.js → c4Diagram-XDPPPE54-DP8MjIgJ.js} +2 -2
  102. package/node_modules/@weavecode/server/web/dist/assets/channel-C0RGiobt.js +1 -0
  103. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2E7WHVMD-B653kMXt.js → chunk-2E7WHVMD-C3UFIDyj.js} +1 -1
  104. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2Q5K7J3B-f_A4_eDz.js → chunk-2Q5K7J3B-Bgw-3YfG.js} +1 -1
  105. package/node_modules/@weavecode/server/web/dist/assets/{chunk-4EMNKR2T-v5j5qNGj.js → chunk-4EMNKR2T-Dy_Wq9qn.js} +1 -1
  106. package/node_modules/@weavecode/server/web/dist/assets/chunk-55XCU76K-D32C0DXX.js +1 -0
  107. package/node_modules/@weavecode/server/web/dist/assets/{chunk-5VM5RSS4-BeROhLXN.js → chunk-5VM5RSS4-Dpmi-9Gi.js} +1 -1
  108. package/node_modules/@weavecode/server/web/dist/assets/{chunk-JWPE2WC7-D6dXb_jr.js → chunk-JWPE2WC7-CEYXaZDX.js} +1 -1
  109. package/node_modules/@weavecode/server/web/dist/assets/{chunk-VQ5W62QI-CnHdSEMi.js → chunk-VQ5W62QI-A616Pgzo.js} +1 -1
  110. package/node_modules/@weavecode/server/web/dist/assets/chunk-XXDRQBXY-CnxFMLWV.js +1 -0
  111. package/node_modules/@weavecode/server/web/dist/assets/chunk-ZCHMQSOR-BhjCTig8.js +2 -0
  112. package/node_modules/@weavecode/server/web/dist/assets/{classDiagram-v2-4MYWR3UA-DQe1b_k8.js → classDiagram-v2-4MYWR3UA-rzlq5tPv.js} +2 -2
  113. package/node_modules/@weavecode/server/web/dist/assets/cose-bilkent-JH36ORCC-CxWQXzj8.js +1 -0
  114. package/node_modules/@weavecode/server/web/dist/assets/{cynefin-EF2NZ3EQ-OZotFKUu.js → cynefin-EF2NZ3EQ-AFHjx2wU.js} +1 -1
  115. package/node_modules/@weavecode/server/web/dist/assets/cynefinDiagram-WF24UDRP-Bp_Oaf9U.js +62 -0
  116. package/node_modules/@weavecode/server/web/dist/assets/dagre-NK4GIZVX-7oUPIU35.js +4 -0
  117. package/node_modules/@weavecode/server/web/dist/assets/diagram-CBK3MWTC-D_rS_rSY.js +24 -0
  118. package/node_modules/@weavecode/server/web/dist/assets/diagram-I5XIIV2D-Duc_cKMb.js +24 -0
  119. package/node_modules/@weavecode/server/web/dist/assets/{diagram-ODIL2UCW-D9A6W8oB.js → diagram-ODIL2UCW-DA0XFVXm.js} +2 -2
  120. package/node_modules/@weavecode/server/web/dist/assets/{diagram-PFBEJUXE-PeI-eyu2.js → diagram-PFBEJUXE-D1U0Xhtt.js} +2 -2
  121. package/node_modules/@weavecode/server/web/dist/assets/diagram-RJA3I4VV-CbDFY871.js +41 -0
  122. package/node_modules/@weavecode/server/web/dist/assets/{diagram-TYUNFSNR-D5KieEw5.js → diagram-TYUNFSNR-jPg9AxQv.js} +2 -2
  123. package/node_modules/@weavecode/server/web/dist/assets/ebnfDiagram-V4P3TTPT-ZHfGTB0N.js +1 -0
  124. package/node_modules/@weavecode/server/web/dist/assets/{elk-QONTBCTQ-D3xrVg0U.js → elk-QONTBCTQ-C-ESJrUi.js} +3 -3
  125. package/node_modules/@weavecode/server/web/dist/assets/{erDiagram-KYQIGQAA-y_V1cor7.js → erDiagram-KYQIGQAA-DGK7TeHj.js} +2 -2
  126. package/node_modules/@weavecode/server/web/dist/assets/{flowDiagram-IUGLLWBU-BJ8Z0MkF.js → flowDiagram-IUGLLWBU-CVV4rL8v.js} +1 -1
  127. package/node_modules/@weavecode/server/web/dist/assets/ganttDiagram-R7GPNTJY-CuAwNvbm.js +292 -0
  128. package/node_modules/@weavecode/server/web/dist/assets/gitGraphDiagram-PDYL7XHY-D_15Wtf-.js +106 -0
  129. package/node_modules/@weavecode/server/web/dist/assets/infoDiagram-MVDRKAX5-ClqhbrCa.js +2 -0
  130. package/node_modules/@weavecode/server/web/dist/assets/{ishikawaDiagram-HPEHV2GE-ChEnND76.js → ishikawaDiagram-HPEHV2GE-CUJ891JX.js} +2 -2
  131. package/node_modules/@weavecode/server/web/dist/assets/{journeyDiagram-BOSHW7O7-DHcNtpYF.js → journeyDiagram-BOSHW7O7-B4skiMu-.js} +2 -2
  132. package/node_modules/@weavecode/server/web/dist/assets/{kanban-definition-FNSA4HC5-Dft7qpW5.js → kanban-definition-FNSA4HC5-UNGJR_y_.js} +2 -2
  133. package/node_modules/@weavecode/server/web/dist/assets/linear-BEB-UwbR.js +1 -0
  134. package/node_modules/@weavecode/server/web/dist/assets/main-B_0jS_Gz.js +1096 -0
  135. package/node_modules/@weavecode/server/web/dist/assets/main-Czzlavi4.css +11 -0
  136. package/node_modules/@weavecode/server/web/dist/assets/{mermaid.core-D_Dp_Kl2.js → mermaid.core-knGXJfjz.js} +4 -4
  137. package/node_modules/@weavecode/server/web/dist/assets/{mindmap-definition-6OY57UG3-CM6OAd_-.js → mindmap-definition-6OY57UG3-CEldbr3a.js} +2 -2
  138. package/node_modules/@weavecode/server/web/dist/assets/modulepreload-polyfill-B5Qt9EMX.js +1 -0
  139. package/node_modules/@weavecode/server/web/dist/assets/pegDiagram-ECIUJNBX-cNCkGLx3.js +1 -0
  140. package/node_modules/@weavecode/server/web/dist/assets/pet-DJCpIDM5.js +1 -0
  141. package/node_modules/@weavecode/server/web/dist/assets/pieDiagram-GNMPY74T-CfMEFiQD.js +39 -0
  142. package/node_modules/@weavecode/server/web/dist/assets/{quadrantDiagram-D57K4MC3-D8pQ_PU2.js → quadrantDiagram-D57K4MC3-knmi2rwP.js} +4 -4
  143. package/node_modules/@weavecode/server/web/dist/assets/railroadDiagram-Y72NRBL7-BJ7AzhEo.js +1 -0
  144. package/node_modules/@weavecode/server/web/dist/assets/{requirementDiagram-EQYSW5RA-C90DU5Ny.js → requirementDiagram-EQYSW5RA-Dte2LGQM.js} +2 -2
  145. package/node_modules/@weavecode/server/web/dist/assets/{sankeyDiagram-SY24JHO5-B_poYGgJ.js → sankeyDiagram-SY24JHO5-3noLaWgd.js} +2 -2
  146. package/node_modules/@weavecode/server/web/dist/assets/{sequenceDiagram-BLEHNHQU-DDW7b2Dn.js → sequenceDiagram-BLEHNHQU-CclOWTTc.js} +2 -2
  147. package/node_modules/@weavecode/server/web/dist/assets/sizeCapture-INFHLROL-B82sbLhA.js +1 -0
  148. package/node_modules/@weavecode/server/web/dist/assets/{stateDiagram-v2-A6IESKWZ-CkVMAyxG.js → stateDiagram-v2-A6IESKWZ-BXfVDwSN.js} +2 -2
  149. package/node_modules/@weavecode/server/web/dist/assets/swimlanes-B3ENRKFQ-D4lKZaeV.js +1 -0
  150. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-DbdFh_d6.js +8 -0
  151. package/node_modules/@weavecode/server/web/dist/assets/{timeline-definition-JXYKGLGB-DnhkRGLb.js → timeline-definition-JXYKGLGB-D6H6zP5b.js} +2 -2
  152. package/node_modules/@weavecode/server/web/dist/assets/{usecaseDiagram-WPOLBNNX-_TdIjC6Z.js → usecaseDiagram-WPOLBNNX-D2J2bKo_.js} +2 -2
  153. package/node_modules/@weavecode/server/web/dist/assets/{vennDiagram-Q3Y3IDCW-FzgsymXB.js → vennDiagram-Q3Y3IDCW-pdRbIkpB.js} +2 -2
  154. package/node_modules/@weavecode/server/web/dist/assets/{wardleyDiagram-IVAIDKWA-BwqimStC.js → wardleyDiagram-IVAIDKWA-Cyd2QPMf.js} +2 -2
  155. package/node_modules/@weavecode/server/web/dist/assets/{xychartDiagram-4URNHDU4-CFjjVPIV.js → xychartDiagram-4URNHDU4-Bd4BkwVM.js} +2 -2
  156. package/node_modules/@weavecode/server/web/dist/index.html +3 -2
  157. package/node_modules/@weavecode/server/web/dist/pet.html +60 -0
  158. package/node_modules/@weavecode/templates/dist/index.d.ts +2 -0
  159. package/node_modules/@weavecode/templates/dist/index.js +1 -1
  160. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/pet.json +7 -0
  161. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/spritesheet.png +0 -0
  162. package/node_modules/@weavecode/templates/dist/resources/weave-market/.claude-plugin/marketplace.json +6 -0
  163. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/.claude-plugin/plugin.json +8 -0
  164. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/skills/weave-pet-hatcher/SKILL.md +121 -0
  165. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/skills/weave-pet-hatcher/scripts/assemble-pet.mjs +308 -0
  166. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/weave.json +4 -0
  167. package/node_modules/@weavecode/templates/package.json +2 -2
  168. package/package.json +11 -7
  169. package/scripts/preinstall.mjs +70 -0
  170. package/node_modules/@weavecode/server/web/dist/assets/abnfDiagram-WEYOIA3C-DDeQkTf5.js +0 -1
  171. package/node_modules/@weavecode/server/web/dist/assets/architectureDiagram-ZHVYKT53-Dj54DE3O.js +0 -36
  172. package/node_modules/@weavecode/server/web/dist/assets/channel-5VM93AJ8.js +0 -1
  173. package/node_modules/@weavecode/server/web/dist/assets/chunk-55XCU76K-CgEqeP7j.js +0 -1
  174. package/node_modules/@weavecode/server/web/dist/assets/chunk-XXDRQBXY-BkG_e6PE.js +0 -1
  175. package/node_modules/@weavecode/server/web/dist/assets/chunk-ZCHMQSOR-DxR-fxzs.js +0 -2
  176. package/node_modules/@weavecode/server/web/dist/assets/cose-bilkent-JH36ORCC-DThrA8S5.js +0 -1
  177. package/node_modules/@weavecode/server/web/dist/assets/cynefinDiagram-WF24UDRP-DJjq2hfT.js +0 -62
  178. package/node_modules/@weavecode/server/web/dist/assets/dagre-NK4GIZVX-C2vH93HT.js +0 -4
  179. package/node_modules/@weavecode/server/web/dist/assets/diagram-CBK3MWTC-DrF_ScM-.js +0 -24
  180. package/node_modules/@weavecode/server/web/dist/assets/diagram-I5XIIV2D-D1qoUJ4t.js +0 -24
  181. package/node_modules/@weavecode/server/web/dist/assets/diagram-RJA3I4VV-DITY0Rd8.js +0 -41
  182. package/node_modules/@weavecode/server/web/dist/assets/ebnfDiagram-V4P3TTPT-DDylK-gz.js +0 -1
  183. package/node_modules/@weavecode/server/web/dist/assets/ganttDiagram-R7GPNTJY-C0q-CS1T.js +0 -292
  184. package/node_modules/@weavecode/server/web/dist/assets/gitGraphDiagram-PDYL7XHY-BYTComiB.js +0 -106
  185. package/node_modules/@weavecode/server/web/dist/assets/index-BKxAxaVG.js +0 -1091
  186. package/node_modules/@weavecode/server/web/dist/assets/index-C0Sd4MH7.css +0 -11
  187. package/node_modules/@weavecode/server/web/dist/assets/infoDiagram-MVDRKAX5-DtixgjLP.js +0 -2
  188. package/node_modules/@weavecode/server/web/dist/assets/linear-DEo11t-X.js +0 -1
  189. package/node_modules/@weavecode/server/web/dist/assets/pegDiagram-ECIUJNBX-_QkY0h8Q.js +0 -1
  190. package/node_modules/@weavecode/server/web/dist/assets/pieDiagram-GNMPY74T-ZGr5vtDj.js +0 -39
  191. package/node_modules/@weavecode/server/web/dist/assets/railroadDiagram-Y72NRBL7-DUIo-WmA.js +0 -1
  192. package/node_modules/@weavecode/server/web/dist/assets/sizeCapture-INFHLROL-CmKoqX6K.js +0 -1
  193. package/node_modules/@weavecode/server/web/dist/assets/swimlanes-B3ENRKFQ-Dm_Omzky.js +0 -1
  194. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-Bjj8ZA4d.js +0 -8
@@ -1 +1 @@
1
- import{spawn as a}from"node:child_process";export function resolveTerminalLaunch(n,e,r=process.platform,o){return terminalBackendFor(e,r).candidates(n,o)}export function resolveExplorerLaunch(n,e=process.platform){return e==="win32"?{command:"explorer.exe",args:[n]}:e==="darwin"?{command:"open",args:[n]}:{command:"xdg-open",args:[n]}}export function trySpawn(n){return new Promise(e=>{let r;try{r=a(n.command,n.args,{cwd:n.cwd,shell:n.shell,detached:!0,stdio:"ignore"})}catch{e(!1);return}r.on("error",()=>e(!1)),r.on("spawn",()=>{r.unref(),e(!0)})})}export async function openInExplorer(n){const e=resolveExplorerLaunch(n);if(!await trySpawn(e))throw new Error(`Failed to open file manager (${e.command})`)}export async function openInTerminal(n,e){await terminalBackendFor(e).open(n)}
1
+ import{spawn as a}from"node:child_process";export function resolveTerminalLaunch(r,e,n=process.platform,o){return terminalBackendFor(e,n).candidates(r,o)}export function resolveExplorerLaunch(r,e=process.platform){return e==="win32"?{command:"explorer.exe",args:[r]}:e==="darwin"?{command:"open",args:[r]}:{command:"xdg-open",args:[r]}}export function trySpawn(r){return new Promise(e=>{let n;try{n=a(r.command,r.args,{cwd:r.cwd,shell:r.shell,detached:!0,stdio:"ignore"})}catch{e(!1);return}n.on("error",()=>e(!1)),n.on("spawn",()=>{n.unref(),e(!0)})})}export async function openInExplorer(r){const e=resolveExplorerLaunch(r);if(!await trySpawn(e))throw new Error(`Failed to open file manager (${e.command})`)}export async function openInTerminal(r,e){await terminalBackendFor(e).open(r)}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 内置默认宠播种:`@weavecode/templates` 随包发货的 `resources/pets/` 落到
3
+ * `<data>/pets/<id>/`。**缺失才拷**(mtime+size 指纹对不上也不覆盖——用户改过
4
+ * 的资产是数据,不是包内容);目录已存在即视为用户领地,跳过。
5
+ */
6
+ export declare function seedBuiltinPets(): Promise<void>;
@@ -0,0 +1 @@
1
+ import{cp as c,mkdir as a,readdir as s,stat as u}from"node:fs/promises";import e from"node:path";import{builtinPetsRoot as n}from"@weavecode/templates";import{getPetsDir as m}from"../db/paths.js";export async function seedBuiltinPets(){let t;try{t=await s(n())}catch{return}const i=m();await a(i,{recursive:!0});for(const r of t){const o=e.join(i,r);(await u(o).catch(()=>null))?.isDirectory()||await c(e.join(n(),r),o,{recursive:!0}).catch(()=>{})}}
@@ -0,0 +1,17 @@
1
+ import type { AuthService } from './dashboard-auth.js';
2
+ /** exe 落点(发布产物随包分发;开发仓在 packages/weave-server/res/)。 */
3
+ export declare function petWindowExePath(): string;
4
+ /** 当前是否具备拉起条件(Windows + 产物在位)。 */
5
+ export declare function canOpenPetWindow(): boolean;
6
+ /**
7
+ * 拉起宠物窗(幂等:已在跑就不动)。返回是否真的拉起了;不具备条件返回
8
+ * false——调用方如实反馈,不静默。
9
+ */
10
+ export declare function openPetWindow(opts: {
11
+ baseUrl: string;
12
+ auth: AuthService | null;
13
+ }): boolean;
14
+ /** 关闭宠物窗:stdin 发一行(exe 收到即优雅退出)。 */
15
+ export declare function closePetWindow(): void;
16
+ /** daemon 关停钩子:宠物窗随 daemon 一起走。 */
17
+ export declare function shutdownPetWindow(): void;
@@ -0,0 +1,2 @@
1
+ import{spawn as f}from"node:child_process";import{existsSync as d}from"node:fs";import s from"node:path";import{fileURLToPath as h}from"node:url";import{PET_SIZE_PRESETS as a,readDaemonSettingsSync as p}from"./settings.js";const m=s.join(s.dirname(h(import.meta.url)),"../../res/pet-window"),w=3e4,t={proc:null,lastCrashAt:null};export function petWindowExePath(){return s.join(m,"weave-pet-window.exe")}export function canOpenPetWindow(){return process.platform==="win32"&&d(petWindowExePath())}export function openPetWindow(e){if(!canOpenPetWindow()||t.proc)return!1;const o=p().pet;if(!o?.enabled)return!1;const i=a[o.size]??a.small,r=o.pos,l=[`${e.baseUrl}/pet.html`,"--size",`${i.width}x${i.height}`,...r?["--pos",`${r.x},${r.y}`]:[],...e.auth?["--cookie",e.auth.issueSession()]:[]];let n;try{n=f(petWindowExePath(),l,{detached:!1,stdio:["pipe","ignore","ignore"],windowsHide:!0})}catch{return!1}return t.proc=n,n.on("exit",()=>{const u=t.proc===n;if(t.proc=null,!u)return;const c=Date.now();t.lastCrashAt!==null&&c-t.lastCrashAt<w||(t.lastCrashAt=c,setTimeout(()=>{p().pet?.enabled&&openPetWindow(e)},1e3).unref())}),!0}export function closePetWindow(){const e=t.proc;if(e){t.proc=null;try{e.stdin?.end(`close
2
+ `)}catch{e.kill()}}}export function shutdownPetWindow(){closePetWindow()}
@@ -11,7 +11,7 @@ import type { PathRefKind } from '@weavecode/harness';
11
11
  /** 索引条目上限:再大就不是「路径补全」该扛的量了,退化成目录浏览。 */
12
12
  export declare const MAX_INDEX_FILES = 300000;
13
13
  /** 快照格式版本:作废盘上的旧文件,改形状必须递增。 */
14
- export declare const INDEX_VERSION = 2;
14
+ export declare const INDEX_VERSION = 3;
15
15
  /**
16
16
  * 索引的可序列化部分 = **落盘那一份的形状**:枚举结果 + 建它时的根与 git 指纹。
17
17
  * 派生出来的东西(小写表、目录子项映射)**不在这层**,读回来现算。
@@ -1,2 +1,2 @@
1
- import{execFile as X}from"node:child_process";import{lstat as $,mkdir as V,readFile as x,readdir as z,realpath as b,rename as B,stat as A,writeFile as G}from"node:fs/promises";import{readdirSync as J,rmSync as Y}from"node:fs";import f from"node:path";import{promisify as K}from"node:util";import{getIndexDir as v}from"../db/paths.js";const Q=K(X);export const MAX_INDEX_FILES=3e5,INDEX_VERSION=2;const F=3e4,W=10*6e4,U=3,Z=new Set(["node_modules",".git","dist","build","out",".next","target","coverage",".turbo"]);async function M(t,e){try{const{stdout:n}=await Q("git",["ls-files","-z",...e],{cwd:t,timeout:1e4,maxBuffer:67108864,windowsHide:!0});return n.split("\0").filter(Boolean)}catch{return null}}async function q(t){const e=await M(t,["--stage"]),n=[],i=[];for(const s of e??[])s.startsWith("160000 ")?n.push(s.slice(s.indexOf(" ")+1)):s.startsWith("120000 ")&&i.push(s.slice(s.indexOf(" ")+1));return{links:n,symlinks:i}}function I(t){return $(f.join(t,".git")).then(()=>!0,()=>!1)}async function tt(t){try{let e=f.join(t,".git");if(!(await $(e)).isDirectory()){const s=/^gitdir:\s*(.+)$/m.exec(await x(e,"utf8"));if(!s)return null;e=f.resolve(t,s[1].trim())}const n=(await x(f.join(e,"HEAD"),"utf8")).trim(),i=n.startsWith("ref: ")?await(async()=>{const s=n.slice(5);try{return(await x(f.join(e,s),"utf8")).trim()}catch{const a=(await x(f.join(e,"packed-refs"),"utf8")).split(`
2
- `).find(o=>o.endsWith(` ${s}`));return a?a.slice(0,a.indexOf(" ")):null}})():n;return i!==null&&/^[0-9a-f]{40}$/i.test(i)?i.slice(0,7):null}catch{return null}}async function et(t){const e=await M(t,["--others","--ignored","--exclude-standard","--directory"]),n=[];for(const i of e??[]){if(!i.endsWith("/"))continue;const s=i.slice(0,-1);await I(f.join(t,s))&&n.push(s)}return n}async function C(t,e=""){const[n,i,s]=await Promise.all([M(t,["--cached","--others","--exclude-standard"]),q(t),et(t)]);if(!n)return null;const r=new Set;for(const c of i.links)r.add(c);for(const c of n)c.endsWith("/")&&r.add(c.slice(0,-1));for(const c of s)r.add(c);const a=new Set;for(const c of i.symlinks)if(!r.has(c))try{(await A(f.join(t,c))).isDirectory()&&a.add(c)}catch{}const o=n.filter(c=>!c.endsWith("/")&&!r.has(c)&&!a.has(c)).map(c=>e+c),u=[...r,...a].map(c=>e+c),d={};for(const c of r){const l=f.join(t,c);if(!await I(l))continue;const p=await tt(l);p&&(d[`${e}${c}`]=p);const m=await C(l,`${e}${c}/`);m&&(o.push(...m.files),u.push(...m.links),Object.assign(d,m.heads))}const y=new Set([await b(t).catch(()=>t)]);for(const c of a){const l=f.join(t,c),p=await b(l).catch(()=>null);if(p===null||y.has(p))continue;y.add(p);const m=`${e}${c}/`;for(let h=o.length-1;h>=0;h--)o[h].startsWith(m)&&o.splice(h,1);const g=await C(l,m)??{files:await j(l),links:[],heads:{}};o.push(...g.files),u.push(...g.links),Object.assign(d,g.heads)}return{files:o,links:u,heads:d}}async function j(t){const e=[],n=new Set([await b(t).catch(()=>t)]),i=async s=>{if(e.length>=MAX_INDEX_FILES)return;let r;try{r=await z(f.join(t,s),{withFileTypes:!0})}catch{return}for(const a of r){if(e.length>=MAX_INDEX_FILES)return;const o=s?`${s}/${a.name}`:a.name;if(a.isDirectory()||a.isSymbolicLink()){if(Z.has(a.name))continue;if(a.isSymbolicLink()){let u;try{u=(await A(f.join(t,o))).isDirectory()}catch{u=!1}if(!u){a.name!==".git"&&e.push(o);continue}const d=await b(f.join(t,o)).catch(()=>null);if(d===null||n.has(d))continue;n.add(d);try{await i(o)}finally{n.delete(d)}}else await i(o)}else a.isFile()&&a.name!==".git"&&e.push(o)}};return await i(""),e}function N(t){const e=new Set;for(const n of t){let i=n.lastIndexOf("/");for(;i>0;){const s=n.slice(0,i);if(e.has(s))break;e.add(s),i=s.lastIndexOf("/")}}return[...e].sort()}async function O(t){try{let e=f.join(t,".git");if(!(await $(e)).isDirectory()){const i=/^gitdir:\s*(.+)$/m.exec(await x(e,"utf8"));if(!i)return null;e=f.resolve(t,i[1].trim())}const n=await A(f.join(e,"index"));return`${n.mtimeMs}:${n.size}`}catch{return null}}async function nt(t){const e=await C(t),n=e?.files??await j(t),i=n.length>MAX_INDEX_FILES,s=i?n.slice(0,MAX_INDEX_FILES):n;s.sort();const r=e?.links??[],a=[...new Set([...N(s),...r,...N(r)])].sort();return{v:INDEX_VERSION,root:t,at:Date.now(),stamp:await O(t),truncated:i,files:s,dirs:a,...e&&Object.keys(e.heads).length>0?{submodules:e.heads}:{}}}export function hydrateIndex(t){const e=new Array(t.files.length);for(let r=0;r<t.files.length;r++)e[r]=t.files[r].toLowerCase();const n=new Array(t.dirs.length);for(let r=0;r<t.dirs.length;r++)n[r]=t.dirs[r].toLowerCase();const i=new Map,s=r=>{let a=i.get(r);return a||i.set(r,a={dirs:[],files:[],sorted:!1}),a};for(const r of t.dirs)s(r.slice(0,Math.max(0,r.lastIndexOf("/")))).dirs.push(r);for(const r of t.files)s(r.slice(0,Math.max(0,r.lastIndexOf("/")))).files.push(r);return{...t,lower:e,dirLower:n,children:i,submodules:t.submodules??{}}}export async function buildIndex(t){return hydrateIndex(await nt(t))}const w=new Map,D=new Map;let E=null;export function setFileIndexRoot(t){E=t}function H(t){return f.join(E??v(),`${t}.json`)}function it(t){return{v:t.v,root:t.root,at:t.at,stamp:t.stamp,truncated:t.truncated,files:t.files,dirs:t.dirs,...Object.keys(t.submodules).length>0?{submodules:{...t.submodules}}:{}}}async function st(t,e){const n=H(t),i=`${n}.tmp`;try{await V(f.dirname(n),{recursive:!0}),await G(i,JSON.stringify(it(e)),"utf8"),await B(i,n)}catch{}}async function P(t,e){try{const n=JSON.parse(await x(H(t),"utf8"));return n?.v!==INDEX_VERSION||n.root!==e||!Array.isArray(n.files)||!Array.isArray(n.dirs)?null:n}catch{return null}}function _(t,e){for(w.delete(t),w.set(t,e);w.size>U;){const n=w.keys().next().value;if(n===void 0)break;w.delete(n)}}function L(t,e){const n=D.get(t);if(n)return n;const i=buildIndex(e).then(r=>(_(t,r),st(t,r),r));D.set(t,i);const s=()=>{D.delete(t)};return i.then(s,s),i}export async function projectFileIndex(t,e,n={}){if(n.fresh){const a=D.get(t);if(a)return a}const i=w.get(t);i&&i.root!==e&&w.delete(t);const s=i&&i.root===e?i:null;if(s&&n.fresh)return L(t,e).catch(()=>{}),s;if(s&&await O(e)===s.stamp){if(Date.now()-s.at<F)return s;w.delete(t)}else s&&w.delete(t);const r=D.get(t);if(r)return r;if(!s){const a=await P(t,e);if(a&&Date.now()-a.at<W){const o=hydrateIndex(a);if(n.fresh)return _(t,o),L(t,e).catch(()=>{}),o;if(await O(e)===a.stamp)return _(t,o),o}}return L(t,e)}export async function peekCachedIndex(t,e,n={}){const i=w.get(t);if(i&&i.root===e)return Date.now()-i.at<F&&await O(e)===i.stamp?i:(w.delete(t),null);const s=n.maxStaleMs??W,r=await P(t,e);if(r&&Date.now()-r.at<s&&await O(e)===r.stamp){const a=hydrateIndex(r);return _(t,a),a}return null}export function clearFileIndexCache(){w.clear()}export function pruneFileIndexes(t){const e=E??v(),n=new Set(t.map(s=>`${s}.json`));let i;try{i=J(e)}catch{return}for(const s of i)if(!(!s.endsWith(".json")||n.has(s)))try{Y(f.join(e,s))}catch{}}const R=new Intl.Collator(void 0,{numeric:!0});export function listDirOf(t,e){const n=t.children.get(e);if(!n)return[];n.sorted||(n.dirs.sort(R.compare),n.files.sort(R.compare),n.sorted=!0);const i=[];for(const s of n.dirs){const r=t.submodules[s];i.push(r?{path:s,kind:"dir",head:r}:{path:s,kind:"dir"})}for(const s of n.files)i.push({path:s,kind:"file"});return i}function rt(t,e){return t.startsWith(e)?3:t.includes(e)?2:at(t,e)?1:-1}function at(t,e){let n=0;for(let i=0;i<t.length&&n<e.length;i++)t[i]===e[n]&&n++;return n===e.length}function ot(t,e,n){const i=t.lastIndexOf("/")+1,s=t.slice(i).toLowerCase();if(e===3||e===2){const o=s.indexOf(n);return o<0?[]:[[i+o,n.length]]}const r=[];let a=0;for(let o=0;o<s.length&&a<n.length;o++)s[o]===n[a]&&(r.push([i+o,1]),a++);return r}function T(t,e){return e.rank-t.rank||t.len-e.len||t.path.localeCompare(e.path)}const ct=8,lt=1024;function ft(t,e){if(!e)return 0;let n=0,i=t.length;for(;n<i;){const s=n+i>>1;t[s]<e?n=s+1:i=s}return n}export function startMatch(t,e,n,i=""){const s=e.trim().toLowerCase(),r=i?`${i}/`:"",a=[];let o=s&&n>0?"files":"done",u=0,d=0,y=!1;const c=(l,p)=>{const m=l.slice(l.lastIndexOf("/")+1).toLowerCase(),g=rt(m,s);if(g<0)return;d++;const h={path:l,kind:p,rank:g,len:l.length};if(a.length===n&&T(h,a[n-1])>=0)return;const S=a.length===n;let k=S?n-1:a.length;for(S?a[n-1]=h:a.push(h);k>0&&T(h,a[k-1])<0;)a[k]=a[k-1],k--;a[k]=h};return{step(l){const p=Date.now()+l;let m=0;for(;o!=="done";){const g=o==="files"?t.files:t.dirs,h=o==="files"?"file":"dir";for(u===0&&(u=ft(g,r));u<g.length;){const S=g[u];if(r&&!S.startsWith(r))break;if(c(S,h),u++,a.length===n&&a[n-1].rank===3)return y=!0,o="done",!0;if((++m&lt-1)===0&&Date.now()>p)return!1}u=0,o=o==="files"?"dirs":"done"}return!0},result(){return{hits:a.map(l=>({path:l.path,kind:l.kind,ranges:ot(l.path,l.rank,s)})),total:y?a.length:d,capped:y}}}}export async function matchPaths(t,e,n,i=""){const s=startMatch(t,e,n,i);for(;!s.step(ct);)await new Promise(r=>setImmediate(r));return s.result()}
1
+ import{execFile as z}from"node:child_process";import{lstat as b,mkdir as B,readFile as x,readdir as J,realpath as _,rename as Y,stat as $,writeFile as K}from"node:fs/promises";import{readdirSync as Q,rmSync as U}from"node:fs";import{homedir as Z}from"node:os";import l from"node:path";import{promisify as q}from"node:util";import{getIndexDir as L}from"../db/paths.js";const v=q(z);export const MAX_INDEX_FILES=3e5,INDEX_VERSION=3;const W=3e4,j=10*6e4,tt=3,et=new Set(["node_modules",".git","dist","build","out",".next","target","coverage",".turbo"]);async function C(t,e){try{const{stdout:n}=await v("git",["ls-files","-z",...e],{cwd:t,timeout:1e4,maxBuffer:67108864,windowsHide:!0});return n.split("\0").filter(Boolean)}catch{return null}}async function nt(t){const e=async i=>await b(i).then(()=>!0,()=>!1)?i:null;try{const{stdout:i}=await v("git",["config","--get","--path","core.excludesFile"],{cwd:t,timeout:5e3,windowsHide:!0}),s=i.trim();if(s)return e(l.resolve(t,s))}catch{}const n=process.env.XDG_CONFIG_HOME||l.join(Z(),".config");return e(l.join(n,"git","ignore"))}async function it(t){const e=["--exclude-per-directory=.gitignore"],n=await nt(t);return n&&e.push(`--exclude-from=${n}`),e}const I=new Map;async function H(t){let e=I.get(t);return e||(e=await it(t),I.set(t,e)),e}async function st(t){const e=await C(t,["--stage"]),n=[],i=[];for(const s of e??[])s.startsWith("160000 ")?n.push(s.slice(s.indexOf(" ")+1)):s.startsWith("120000 ")&&i.push(s.slice(s.indexOf(" ")+1));return{links:n,symlinks:i}}function N(t){return b(l.join(t,".git")).then(()=>!0,()=>!1)}async function rt(t){try{let e=l.join(t,".git");if(!(await b(e)).isDirectory()){const s=/^gitdir:\s*(.+)$/m.exec(await x(e,"utf8"));if(!s)return null;e=l.resolve(t,s[1].trim())}const n=(await x(l.join(e,"HEAD"),"utf8")).trim(),i=n.startsWith("ref: ")?await(async()=>{const s=n.slice(5);try{return(await x(l.join(e,s),"utf8")).trim()}catch{const r=(await x(l.join(e,"packed-refs"),"utf8")).split(`
2
+ `).find(c=>c.endsWith(` ${s}`));return r?r.slice(0,r.indexOf(" ")):null}})():n;return i!==null&&/^[0-9a-f]{40}$/i.test(i)?i.slice(0,7):null}catch{return null}}async function at(t){const e=await C(t,["--others","--ignored",...await H(t),"--directory"]),n=[];for(const i of e??[]){if(!i.endsWith("/"))continue;const s=i.slice(0,-1);await N(l.join(t,s))&&n.push(s)}return n}async function A(t,e="",n=[]){const[i,s,a]=await Promise.all([(async()=>{const o=["--cached","--others",...n.length?n:await H(t)];return C(t,o)})(),st(t),at(t)]);if(!i)return null;const r=new Set;for(const o of s.links)r.add(o);for(const o of i)o.endsWith("/")&&r.add(o.slice(0,-1));for(const o of a)r.add(o);const c=new Set;for(const o of s.symlinks)if(!r.has(o))try{(await $(l.join(t,o))).isDirectory()&&c.add(o)}catch{}const f=i.filter(o=>!o.endsWith("/")&&!r.has(o)&&!c.has(o)).map(o=>e+o),d=[...r,...c].map(o=>e+o),y={};for(const o of r){const w=l.join(t,o);if(!await N(w))continue;const g=await rt(w);g&&(y[`${e}${o}`]=g);const u=await A(w,`${e}${o}/`,n);u&&(f.push(...u.files),d.push(...u.links),Object.assign(y,u.heads))}const D=new Set([await _(t).catch(()=>t)]);for(const o of c){const w=l.join(t,o),g=await _(w).catch(()=>null);if(g===null||D.has(g))continue;D.add(g);const u=`${e}${o}/`;for(let p=f.length-1;p>=0;p--)f[p].startsWith(u)&&f.splice(p,1);const m=await A(w,u,n)??{files:await X(w),links:[],heads:{}};f.push(...m.files),d.push(...m.links),Object.assign(y,m.heads)}return{files:f,links:d,heads:y}}async function X(t){const e=[],n=new Set([await _(t).catch(()=>t)]),i=async s=>{if(e.length>=MAX_INDEX_FILES)return;let a;try{a=await J(l.join(t,s),{withFileTypes:!0})}catch{return}for(const r of a){if(e.length>=MAX_INDEX_FILES)return;const c=s?`${s}/${r.name}`:r.name;if(r.isDirectory()||r.isSymbolicLink()){if(et.has(r.name))continue;if(r.isSymbolicLink()){let f;try{f=(await $(l.join(t,c))).isDirectory()}catch{f=!1}if(!f){r.name!==".git"&&e.push(c);continue}const d=await _(l.join(t,c)).catch(()=>null);if(d===null||n.has(d))continue;n.add(d);try{await i(c)}finally{n.delete(d)}}else await i(c)}else r.isFile()&&r.name!==".git"&&e.push(c)}};return await i(""),e}function P(t){const e=new Set;for(const n of t){let i=n.lastIndexOf("/");for(;i>0;){const s=n.slice(0,i);if(e.has(s))break;e.add(s),i=s.lastIndexOf("/")}}return[...e].sort()}async function O(t){try{let e=l.join(t,".git");if(!(await b(e)).isDirectory()){const i=/^gitdir:\s*(.+)$/m.exec(await x(e,"utf8"));if(!i)return null;e=l.resolve(t,i[1].trim())}const n=await $(l.join(e,"index"));return`${n.mtimeMs}:${n.size}`}catch{return null}}async function ot(t){const e=await A(t),n=e?.files??await X(t),i=n.length>MAX_INDEX_FILES,s=i?n.slice(0,MAX_INDEX_FILES):n;s.sort();const a=e?.links??[],r=[...new Set([...P(s),...a,...P(a)])].sort();return{v:INDEX_VERSION,root:t,at:Date.now(),stamp:await O(t),truncated:i,files:s,dirs:r,...e&&Object.keys(e.heads).length>0?{submodules:e.heads}:{}}}export function hydrateIndex(t){const e=new Array(t.files.length);for(let a=0;a<t.files.length;a++)e[a]=t.files[a].toLowerCase();const n=new Array(t.dirs.length);for(let a=0;a<t.dirs.length;a++)n[a]=t.dirs[a].toLowerCase();const i=new Map,s=a=>{let r=i.get(a);return r||i.set(a,r={dirs:[],files:[],sorted:!1}),r};for(const a of t.dirs)s(a.slice(0,Math.max(0,a.lastIndexOf("/")))).dirs.push(a);for(const a of t.files)s(a.slice(0,Math.max(0,a.lastIndexOf("/")))).files.push(a);return{...t,lower:e,dirLower:n,children:i,submodules:t.submodules??{}}}export async function buildIndex(t){return hydrateIndex(await ot(t))}const h=new Map,S=new Map;let E=null;export function setFileIndexRoot(t){E=t}function R(t){return l.join(E??L(),`${t}.json`)}function ct(t){return{v:t.v,root:t.root,at:t.at,stamp:t.stamp,truncated:t.truncated,files:t.files,dirs:t.dirs,...Object.keys(t.submodules).length>0?{submodules:{...t.submodules}}:{}}}async function lt(t,e){const n=R(t),i=`${n}.tmp`;try{await B(l.dirname(n),{recursive:!0}),await K(i,JSON.stringify(ct(e)),"utf8"),await Y(i,n)}catch{}}async function T(t,e){try{const n=JSON.parse(await x(R(t),"utf8"));return n?.v!==INDEX_VERSION||n.root!==e||!Array.isArray(n.files)||!Array.isArray(n.dirs)?null:n}catch{return null}}function M(t,e){for(h.delete(t),h.set(t,e);h.size>tt;){const n=h.keys().next().value;if(n===void 0)break;h.delete(n)}}function F(t,e){const n=S.get(t);if(n)return n;const i=buildIndex(e).then(a=>(M(t,a),lt(t,a),a));S.set(t,i);const s=()=>{S.delete(t)};return i.then(s,s),i}export async function projectFileIndex(t,e,n={}){if(n.fresh){const r=S.get(t);if(r)return r}const i=h.get(t);i&&i.root!==e&&h.delete(t);const s=i&&i.root===e?i:null;if(s&&n.fresh)return F(t,e).catch(()=>{}),s;if(s&&await O(e)===s.stamp){if(Date.now()-s.at<W)return s;h.delete(t)}else s&&h.delete(t);const a=S.get(t);if(a)return a;if(!s){const r=await T(t,e);if(r&&Date.now()-r.at<j){const c=hydrateIndex(r);if(n.fresh)return M(t,c),F(t,e).catch(()=>{}),c;if(await O(e)===r.stamp)return M(t,c),c}}return F(t,e)}export async function peekCachedIndex(t,e,n={}){const i=h.get(t);if(i&&i.root===e)return Date.now()-i.at<W&&await O(e)===i.stamp?i:(h.delete(t),null);const s=n.maxStaleMs??j,a=await T(t,e);if(a&&Date.now()-a.at<s&&await O(e)===a.stamp){const r=hydrateIndex(a);return M(t,r),r}return null}export function clearFileIndexCache(){h.clear()}export function pruneFileIndexes(t){const e=E??L(),n=new Set(t.map(s=>`${s}.json`));let i;try{i=Q(e)}catch{return}for(const s of i)if(!(!s.endsWith(".json")||n.has(s)))try{U(l.join(e,s))}catch{}}const G=new Intl.Collator(void 0,{numeric:!0});export function listDirOf(t,e){const n=t.children.get(e);if(!n)return[];n.sorted||(n.dirs.sort(G.compare),n.files.sort(G.compare),n.sorted=!0);const i=[];for(const s of n.dirs){const a=t.submodules[s];i.push(a?{path:s,kind:"dir",head:a}:{path:s,kind:"dir"})}for(const s of n.files)i.push({path:s,kind:"file"});return i}function ft(t,e){return t.startsWith(e)?3:t.includes(e)?2:ut(t,e)?1:-1}function ut(t,e){let n=0;for(let i=0;i<t.length&&n<e.length;i++)t[i]===e[n]&&n++;return n===e.length}function ht(t,e,n){const i=t.lastIndexOf("/")+1,s=t.slice(i).toLowerCase();if(e===3||e===2){const c=s.indexOf(n);return c<0?[]:[[i+c,n.length]]}const a=[];let r=0;for(let c=0;c<s.length&&r<n.length;c++)s[c]===n[r]&&(a.push([i+c,1]),r++);return a}function V(t,e){return e.rank-t.rank||t.len-e.len||t.path.localeCompare(e.path)}const dt=8,wt=1024;function mt(t,e){if(!e)return 0;let n=0,i=t.length;for(;n<i;){const s=n+i>>1;t[s]<e?n=s+1:i=s}return n}export function startMatch(t,e,n,i=""){const s=e.trim().toLowerCase(),a=i?`${i}/`:"",r=[];let c=s&&n>0?"files":"done",f=0,d=0,y=!1;const D=(o,w)=>{const g=o.slice(o.lastIndexOf("/")+1).toLowerCase(),u=ft(g,s);if(u<0)return;d++;const m={path:o,kind:w,rank:u,len:o.length};if(r.length===n&&V(m,r[n-1])>=0)return;const p=r.length===n;let k=p?n-1:r.length;for(p?r[n-1]=m:r.push(m);k>0&&V(m,r[k-1])<0;)r[k]=r[k-1],k--;r[k]=m};return{step(o){const w=Date.now()+o;let g=0;for(;c!=="done";){const u=c==="files"?t.files:t.dirs,m=c==="files"?"file":"dir";for(f===0&&(f=mt(u,a));f<u.length;){const p=u[f];if(a&&!p.startsWith(a))break;if(D(p,m),f++,r.length===n&&r[n-1].rank===3)return y=!0,c="done",!0;if((++g&wt-1)===0&&Date.now()>w)return!1}f=0,c=c==="files"?"dirs":"done"}return!0},result(){return{hits:r.map(o=>({path:o.path,kind:o.kind,ranges:ht(o.path,o.rank,s)})),total:y?r.length:d,capped:y}}}}export async function matchPaths(t,e,n,i=""){const s=startMatch(t,e,n,i);for(;!s.step(dt);)await new Promise(a=>setImmediate(a));return s.result()}
@@ -0,0 +1,3 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { WeaveServerDeps } from '../server.js';
3
+ export declare function handlePetRoutes(req: IncomingMessage, res: ServerResponse, _deps: WeaveServerDeps, pathname: string, _url: URL): Promise<boolean>;
@@ -0,0 +1 @@
1
+ import s from"node:path";import{createReadStream as P,promises as u}from"node:fs";import{PET_SPRITE_CONTRACT as b}from"@weavecode/core";import{sendJson as o}from"../http.js";import{getPetsDir as g}from"../../db/paths.js";import{isInsideDir as j}from"../../market/resolve.js";async function w(a){let t;try{t=await u.readFile(s.join(a,"pet.json"),"utf8")}catch{return null}let e;try{e=JSON.parse(t)}catch{return null}const i=typeof e.id=="string"?e.id:"";if(!i||i!==s.basename(a))return null;const m=await u.stat(s.join(a,"pet.json")).catch(()=>null);return{id:i,displayName:typeof e.displayName=="string"?e.displayName:i,description:typeof e.description=="string"?e.description:"",spriteVersionNumber:typeof e.spriteVersionNumber=="number"?e.spriteVersionNumber:1,updatedAt:m?Math.floor(m.mtimeMs):0}}export async function handlePetRoutes(a,t,e,i,m){if(!i.startsWith("/pets"))return!1;if(i==="/pets"&&a.method==="GET"){const r=g();let c;try{c=await u.readdir(r)}catch{return o(t,200,{pets:[],root:r}),!0}const n=(await Promise.all(c.map(p=>w(s.join(r,p))))).filter(p=>p!==null);return n.sort((p,l)=>p.id.localeCompare(l.id)),o(t,200,{pets:n,root:r}),!0}const h=i.match(/^\/pets\/([^/]+)\/spritesheet$/);if(h&&a.method==="GET"){const r=h[1];if(!/^[a-z0-9][a-z0-9-]{0,63}$/i.test(r))return o(t,400,{error:"Invalid pet id"}),!0;const c=g(),n=s.join(c,r);if(!j(n,c))return o(t,403,{error:"Pet path escapes the pets root"}),!0;if(!await w(n))return o(t,404,{error:`Pet "${r}" not found`}),!0;const l=s.join(n,"spritesheet.webp"),f=(await u.stat(l).catch(()=>null))?.isFile()?l:s.join(n,"spritesheet.png"),d=await u.stat(f).catch(()=>null);if(!d)return o(t,404,{error:`Pet "${r}" has no spritesheet`}),!0;if(d.size>b.maxSpritesheetBytes)return o(t,413,{error:"Spritesheet exceeds the size limit"}),!0;t.writeHead(200,{"content-type":f.endsWith(".png")?"image/png":"image/webp","content-length":String(d.size),"cache-control":"private, max-age=31536000, immutable"});const y=P(f);return y.on("error",()=>{typeof t.destroy=="function"&&t.destroy()}),y.pipe(t),!0}return!1}
@@ -1 +1 @@
1
- import{readBody as m,sendJson as i}from"../http.js";import{DEFAULT_AI_SETTINGS as P,DEFAULT_DECISION_SETTINGS as K,readDaemonSettings as y,writeDaemonSettings as E,terminalPresetsFor as T}from"../settings.js";import{readAiKey as N,writeAiKey as G}from"../ai-config.js";import{readDecisionKey as j,writeDecisionKey as A}from"../decision-config.js";import{accessUrls as I}from"../tls.js";import{applyLaunchOnLogin as O}from"../auto-start.js";import{WEAVE_VERSION as U}from"../../version.js";import{readProjectConfig as h,writeProjectConfig as C}from"../../install/project-config.js";import{readStatuslineConfig as p,readStatuslineScript as v,readStatuslineFacts as D,applyStatuslineConfig as g,readGlobalStatuslineConfig as S,writeGlobalStatuslineConfig as J}from"../../statusline/manager.js";import{DEFAULT_STATUSLINE_CONFIG as F}from"../../statusline/config.js";import{listBrowseRoots as _,listDirectoryChildren as B}from"../fs-browser.js";import{projectFileNamespaces as L}from"../../hooks/toolkit.js";import{listGlobalFileAssets as k}from"../../install/global-file-assets.js";function w(a,r,o){const s=a.ai??P,u=a.decision??K,l=N(r),f=j(o);return{...a,ai:{baseUrl:s.baseUrl,model:s.model,apiKey:l,apiKeySet:l!==null},decision:{baseUrl:u.baseUrl,model:u.model,apiKey:f,apiKeySet:f!==null}}}function b(a){if(!a)return;const{apiKey:r,...o}=a;return o}export async function handleSettingsRoutes(a,r,o,s,u){if(s==="/settings"){if(a.method==="GET")return i(r,200,{settings:w(await y(),o.aiKeyPath,o.decisionKeyPath),presets:T(process.platform),platform:process.platform,urls:I(o.port,o.tlsPort??0),version:U,repoUrl:"https://github.com/zijing66/weave"}),!0;if(a.method==="PUT"){let t;try{t=JSON.parse(await m(a))}catch{return i(r,400,{error:"Invalid JSON body"}),!0}const e=t.ai?.apiKey;e!==void 0&&G(typeof e=="string"?e:null,o.aiKeyPath);const n=t.decision?.apiKey;n!==void 0&&A(typeof n=="string"?n:null,o.decisionKeyPath);const c=await y(),d=await E({...c,...t,ai:t.ai?b(t.ai):c.ai,decision:t.decision?b(t.decision):c.decision});return o.hookEvents?.resetPrune(),(o.autoStart??O)(d.startup?.launchOnLogin??!1),o.dataBus?.emit({key:"settings"}),i(r,200,w(d,o.aiKeyPath,o.decisionKeyPath)),!0}}if(s==="/fs/roots"&&a.method==="GET"){const t=o.libraries?o.libraries.list().map(n=>n.path):[],e=await _(t);return i(r,200,{roots:e}),!0}if(s==="/fs/children"&&a.method==="GET"){const t=u.searchParams.get("path");if(!t)return i(r,400,{error:'Missing "path" query parameter'}),!0;try{const e=await B(t);i(r,200,{children:e})}catch(e){i(r,400,{error:`Cannot list directory: ${String(e)}`})}return!0}const l=s.match(/^\/projects\/(\d+)\/config$/);if(l){const t=o.projects.getById(Number(l[1]));if(!t)return i(r,404,{error:"Project not found"}),!0;if(a.method==="GET")return i(r,200,await h(t.path)),!0;if(a.method==="PUT"){let e;try{e=JSON.parse(await m(a))}catch{return i(r,400,{error:"Invalid JSON body"}),!0}const n=await h(t.path),c={lastSyncAt:e.lastSyncAt??n.lastSyncAt};return await C(t.path,c),i(r,200,c),!0}}if(s==="/statusline/global"){if(a.method==="GET")return i(r,200,{config:await S()}),!0;if(a.method==="PUT"){let t;try{t=JSON.parse(await m(a))}catch{return i(r,400,{error:"Invalid JSON body"}),!0}try{await J(t);for(const e of o.projects.list()){const n=await p(e.path);n.source==="global"&&await g(e.path,n)}o.dataBus?.emit({key:"statusline"}),i(r,200,{ok:!0})}catch(e){i(r,400,{error:e instanceof Error?e.message:"Global statusline update failed"})}return!0}}if(s==="/statusline/default"&&a.method==="GET")return i(r,200,{config:F}),!0;const f=s.match(/^\/projects\/(\d+)\/statusline$/);if(f){const t=o.projects.getById(Number(f[1]));if(!t)return i(r,404,{error:"Project not found"}),!0;if(a.method==="GET"){const[e,n,c]=await Promise.all([p(t.path),v(t.path),S()]);return i(r,200,{config:e,script:n,globalConfig:c,facts:D(t.path)}),!0}if(a.method==="PUT"){let e;try{e=JSON.parse(await m(a))}catch{return i(r,400,{error:"Invalid JSON body"}),!0}try{await g(t.path,e),o.dataBus?.emit({key:"statusline",projectPath:t.path}),i(r,200,{ok:!0})}catch(n){i(r,400,{error:n instanceof Error?n.message:"Statusline update failed"})}return!0}}if(s==="/assets"&&a.method==="GET"){const t=u.searchParams.get("path");if(!t)return i(r,400,{error:'Missing "path" query parameter'}),!0;if(!o.watch)return i(r,503,{error:"Watch service unavailable"}),!0;const e=await L(t),n=o.watch.getAssets(t).map(c=>{const d=e.get(c.relPath);return d?{...c,namespace:d}:c});return i(r,200,{projectPath:t,assets:n}),!0}return s==="/global-file-assets"&&a.method==="GET"?(i(r,200,{assets:await k()}),!0):!1}
1
+ import{readBody as p,sendJson as a}from"../http.js";import{DEFAULT_AI_SETTINGS as P,DEFAULT_DECISION_SETTINGS as K,readDaemonSettings as d,writeDaemonSettings as E,terminalPresetsFor as T}from"../settings.js";import{readAiKey as N,writeAiKey as G}from"../ai-config.js";import{readDecisionKey as j,writeDecisionKey as A}from"../decision-config.js";import{accessUrls as U}from"../tls.js";import{applyLaunchOnLogin as I}from"../auto-start.js";import{closePetWindow as O,openPetWindow as C}from"../pet-window.js";import{WEAVE_VERSION as v}from"../../version.js";import{readProjectConfig as h,writeProjectConfig as D}from"../../install/project-config.js";import{readStatuslineConfig as y,readStatuslineScript as J,readStatuslineFacts as F,applyStatuslineConfig as g,readGlobalStatuslineConfig as S,writeGlobalStatuslineConfig as _}from"../../statusline/manager.js";import{DEFAULT_STATUSLINE_CONFIG as B}from"../../statusline/config.js";import{listBrowseRoots as L,listDirectoryChildren as k}from"../fs-browser.js";import{projectFileNamespaces as M}from"../../hooks/toolkit.js";import{listGlobalFileAssets as W}from"../../install/global-file-assets.js";function w(o,e,r){const c=o.ai??P,u=o.decision??K,f=N(e),m=j(r);return{...o,ai:{baseUrl:c.baseUrl,model:c.model,apiKey:f,apiKeySet:f!==null},decision:{baseUrl:u.baseUrl,model:u.model,apiKey:m,apiKeySet:m!==null}}}function b(o){if(!o)return;const{apiKey:e,...r}=o;return r}export async function handleSettingsRoutes(o,e,r,c,u){if(c==="/settings"){if(o.method==="GET")return a(e,200,{settings:w(await d(),r.aiKeyPath,r.decisionKeyPath),presets:T(process.platform),platform:process.platform,urls:U(r.port,r.tlsPort??0),version:v,repoUrl:"https://github.com/zijing66/weave"}),!0;if(o.method==="PUT"){let t;try{t=JSON.parse(await p(o))}catch{return a(e,400,{error:"Invalid JSON body"}),!0}const i=t.ai?.apiKey;i!==void 0&&G(typeof i=="string"?i:null,r.aiKeyPath);const n=t.decision?.apiKey;n!==void 0&&A(typeof n=="string"?n:null,r.decisionKeyPath);const s=await d(),l=await E({...s,...t,ai:t.ai?b(t.ai):s.ai,decision:t.decision?b(t.decision):s.decision,pet:t.pet?{...s.pet,...t.pet}:s.pet});return r.hookEvents?.resetPrune(),(r.autoStart??I)(l.startup?.launchOnLogin??!1),l.pet?.enabled?C({baseUrl:`http://localhost:${r.port}`,auth:r.auth??null}):O(),r.dataBus?.emit({key:"settings"}),a(e,200,w(l,r.aiKeyPath,r.decisionKeyPath)),!0}}if(c==="/fs/roots"&&o.method==="GET"){const t=r.libraries?r.libraries.list().map(n=>n.path):[],i=await L(t);return a(e,200,{roots:i}),!0}if(c==="/fs/children"&&o.method==="GET"){const t=u.searchParams.get("path");if(!t)return a(e,400,{error:'Missing "path" query parameter'}),!0;try{const i=await k(t);a(e,200,{children:i})}catch(i){a(e,400,{error:`Cannot list directory: ${String(i)}`})}return!0}const f=c.match(/^\/projects\/(\d+)\/config$/);if(f){const t=r.projects.getById(Number(f[1]));if(!t)return a(e,404,{error:"Project not found"}),!0;if(o.method==="GET")return a(e,200,await h(t.path)),!0;if(o.method==="PUT"){let i;try{i=JSON.parse(await p(o))}catch{return a(e,400,{error:"Invalid JSON body"}),!0}const n=await h(t.path),s={lastSyncAt:i.lastSyncAt??n.lastSyncAt};return await D(t.path,s),a(e,200,s),!0}}if(c==="/statusline/global"){if(o.method==="GET")return a(e,200,{config:await S()}),!0;if(o.method==="PUT"){let t;try{t=JSON.parse(await p(o))}catch{return a(e,400,{error:"Invalid JSON body"}),!0}try{await _(t);for(const i of r.projects.list()){const n=await y(i.path);n.source==="global"&&await g(i.path,n)}r.dataBus?.emit({key:"statusline"}),a(e,200,{ok:!0})}catch(i){a(e,400,{error:i instanceof Error?i.message:"Global statusline update failed"})}return!0}}if(c==="/statusline/default"&&o.method==="GET")return a(e,200,{config:B}),!0;const m=c.match(/^\/projects\/(\d+)\/statusline$/);if(m){const t=r.projects.getById(Number(m[1]));if(!t)return a(e,404,{error:"Project not found"}),!0;if(o.method==="GET"){const[i,n,s]=await Promise.all([y(t.path),J(t.path),S()]);return a(e,200,{config:i,script:n,globalConfig:s,facts:F(t.path)}),!0}if(o.method==="PUT"){let i;try{i=JSON.parse(await p(o))}catch{return a(e,400,{error:"Invalid JSON body"}),!0}try{await g(t.path,i),r.dataBus?.emit({key:"statusline",projectPath:t.path}),a(e,200,{ok:!0})}catch(n){a(e,400,{error:n instanceof Error?n.message:"Statusline update failed"})}return!0}}if(c==="/assets"&&o.method==="GET"){const t=u.searchParams.get("path");if(!t)return a(e,400,{error:'Missing "path" query parameter'}),!0;if(!r.watch)return a(e,503,{error:"Watch service unavailable"}),!0;const i=await M(t),n=r.watch.getAssets(t).map(s=>{const l=i.get(s.relPath);return l?{...s,namespace:l}:s});return a(e,200,{projectPath:t,assets:n}),!0}return c==="/global-file-assets"&&o.method==="GET"?(a(e,200,{assets:await W()}),!0):!1}
@@ -1 +1,2 @@
1
- import t from"node:path";import f from"node:os";import{promises as c}from"node:fs";import{HARNESS_DIRS as u,VISUALIZATION_PROTOCOL as g}from"@weavecode/core";import{sendJson as e}from"../http.js";import{isInsideDir as j}from"../../market/resolve.js";function w(s){const r=f.homedir(),o=[t.join(r,u.codex.userDir,"visualizations"),t.join(r,u.claude.userDir),t.join(r,u.codex.userDir,"plugins"),t.join(f.tmpdir(),"weave")];for(const a of s.projects.list())o.push(a.path);return o}export async function handleVisualizationRoutes(s,r,o,a,p){if(a!=="/visualizations/fragment"||s.method!=="GET")return!1;const n=p.searchParams.get("path")??"",i=t.resolve(n);if(!n||!t.isAbsolute(n))return e(r,400,{error:'Missing or relative "path" query parameter'}),!0;const l=w(o);if(!l.some(d=>j(i,d)))return e(r,403,{error:`Fragment path is outside the allowed roots: ${l.join(", ")}`}),!0;if(t.extname(i).toLowerCase()!==".html")return e(r,403,{error:"Only .html fragments are served"}),!0;let m;try{m=await c.stat(i)}catch{return e(r,404,{error:"Fragment file not found"}),!0}if(!m.isFile())return e(r,404,{error:"Fragment path is not a file"}),!0;if(m.size>g.maxFragmentBytes)return e(r,413,{error:"Fragment exceeds the 1 MB size limit"}),!0;const h=await c.readFile(i,"utf8");return r.setHeader("cache-control","no-store"),e(r,200,{html:h}),!0}
1
+ import c from"node:path";import x from"node:os";import{promises as u}from"node:fs";import{HARNESS_DIRS as w,VISUALIZATION_PROTOCOL as l}from"@weavecode/core";import{sendJson as f}from"../http.js";import{isInsideDir as O}from"../../market/resolve.js";import{getVisualizationsDir as b}from"../../db/paths.js";function y(r){return r.visualizationsDir??b()}function A(r){const t=x.homedir(),o=[c.join(t,w.codex.userDir,"visualizations"),c.join(t,w.claude.userDir),c.join(t,w.codex.userDir,"plugins"),c.join(x.tmpdir(),"weave"),y(r)];for(const n of r.projects.list())o.push(n.path);return o}const S=1440*60*1e3,P=[l.referencePrefix,...l.referencePrefixAliases],j=[l.referenceSuffix,...l.referenceSuffixAliases];function C(r){const t=[];for(const o of r.split(`
2
+ `)){const n=o.trim(),a=P.find(s=>n.startsWith(s));if(!a)continue;let e=n.slice(a.length);const i=j.find(s=>e.endsWith(s));i&&(e=e.slice(0,-i.length));try{const s=JSON.parse(e);typeof s.path=="string"&&s.path&&t.push(c.resolve(s.path))}catch{}}return t}function I(r){const t=new Set;for(const o of r.hookEvents?.conversationTextsContaining("visualize")??[])for(const n of C(o))t.add(n.toLowerCase());return t}async function R(r){const t=[],o=async n=>{let a;try{a=await u.readdir(n,{withFileTypes:!0})}catch{return}for(const e of a){const i=c.join(n,e.name);if(e.isDirectory()){await o(i);continue}if(!(!e.isFile()||c.extname(e.name).toLowerCase()!==".html"))try{const s=await u.stat(i);t.push({file:i,size:s.size,mtimeMs:s.mtimeMs})}catch{}}};return await o(r),t}async function L(r){const t=y(r),o=await R(t),n=I(r),a=Date.now()-S,e={root:t,count:o.length,bytes:0,unreferenced:{count:0,bytes:0}};for(const i of o)e.bytes+=i.size,!(n.has(i.file.toLowerCase())||i.mtimeMs>a)&&(e.unreferenced.count+=1,e.unreferenced.bytes+=i.size);return e}export async function handleVisualizationRoutes(r,t,o,n,a){if(n==="/visualizations/stats"&&r.method==="GET")return f(t,200,await L(o)),!0;if(n==="/visualizations/cleanup"&&r.method==="POST"){const p=await R(y(o)),E=I(o),M=Date.now()-S;let v=0,F=0;for(const h of p)if(!(E.has(h.file.toLowerCase())||h.mtimeMs>M))try{await u.unlink(h.file),v+=1,F+=h.size}catch{}return f(t,200,{removed:v,freedBytes:F}),!0}if(n!=="/visualizations/fragment"||r.method!=="GET")return!1;const e=a.searchParams.get("path")??"",i=c.resolve(e);if(!e||!c.isAbsolute(e))return f(t,400,{error:'Missing or relative "path" query parameter'}),!0;const s=A(o);if(!s.some(p=>O(i,p)))return f(t,403,{error:`Fragment path is outside the allowed roots: ${s.join(", ")}`}),!0;if(c.extname(i).toLowerCase()!==".html")return f(t,403,{error:"Only .html fragments are served"}),!0;let m;try{m=await u.stat(i)}catch{return f(t,404,{error:"Fragment file not found"}),!0}if(!m.isFile())return f(t,404,{error:"Fragment path is not a file"}),!0;t.setHeader("cache-control","no-store");const d=Math.floor(m.mtimeMs),g=a.searchParams.get("mtime"),z=g==null?NaN:Number(g);if(Number.isFinite(z)&&z===d)return f(t,200,{unchanged:!0,mtimeMs:d}),!0;if(m.size>l.maxFragmentBytes)return f(t,413,{error:"Fragment exceeds the 1 MB size limit"}),!0;const D=await u.readFile(i,"utf8");return f(t,200,{html:D,mtimeMs:d}),!0}
@@ -46,6 +46,8 @@ export interface WeaveServerDeps {
46
46
  watch?: WatchService;
47
47
  /** Hook event repository; optional so non-ingestion tests can omit it. */
48
48
  hookEvents?: HookEventRepository;
49
+ /** 渲染块 fragment 落点根;缺省 `<data>/visualizations`(测试注入临时目录)。 */
50
+ visualizationsDir?: string;
49
51
  /**
50
52
  * 事件接入源(批 4b:类型由 HookAdapter 放宽为结构兼容的 EventSource,
51
53
  * `HookAdapter[]` 仍可赋值);`harnesses` 存在时 POST /hooks 由其派生。
@@ -46,6 +46,8 @@ export interface DaemonSettings {
46
46
  decision?: DecisionSettings;
47
47
  /** 对话导出 HTML 的自定义头(多份保存、一份在用——读时归一化)。 */
48
48
  htmlExport?: HtmlExportSettings;
49
+ /** 桌面宠物窗(开关/选宠/提醒——读时归一化)。 */
50
+ pet?: PetSettings;
49
51
  }
50
52
  export interface HooksSettings {
51
53
  enabled: boolean;
@@ -113,6 +115,25 @@ export declare const DEFAULT_AI_SETTINGS: AiSettings;
113
115
  export declare const DEFAULT_DECISION_SETTINGS: DecisionSettings;
114
116
  /** 缺省没有头配置(导出不带自定义头)。 */
115
117
  export declare const DEFAULT_HTML_EXPORT_SETTINGS: HtmlExportSettings;
118
+ /** 桌面宠物窗:默认关、默认内置蜘蛛、提醒开、默认小号、默认右下角。 */
119
+ export interface PetSettings {
120
+ enabled: boolean;
121
+ petId: string;
122
+ notifications: boolean;
123
+ /** 窗尺寸档(S=160×192 / M=200×240 / L=280×336);右键菜单循环切换。 */
124
+ size: 'small' | 'medium' | 'large';
125
+ /** 窗屏幕坐标(拖拽后记档;缺省 = exe 落默认位——主屏右下角)。 */
126
+ pos?: {
127
+ x: number;
128
+ y: number;
129
+ };
130
+ }
131
+ export declare const DEFAULT_PET_SETTINGS: PetSettings;
132
+ /** 尺寸档 → 窗像素(宽×高;精灵单元比例约 12:13,留气泡余量)。 */
133
+ export declare const PET_SIZE_PRESETS: Record<PetSettings['size'], {
134
+ width: number;
135
+ height: number;
136
+ }>;
116
137
  export declare const DEFAULT_DAEMON_SETTINGS: DaemonSettings;
117
138
  /** Coerce a stored locale to a supported one (whitelist, never throws). */
118
139
  export declare function resolveLocale(raw: unknown): Locale;
@@ -1,2 +1,2 @@
1
- import{openDatabase as f}from"../db/db.js";import{getDbPath as g}from"../db/paths.js";import{DEFAULT_BIND_HOST as h}from"./port.js";export const SUPPORTED_LOCALES=["zh-CN","en"],DEFAULT_LOCALE="zh-CN",DEFAULT_TERMINAL_SETTINGS={preset:"auto",customCommand:""},DEFAULT_HOOKS_SETTINGS={enabled:!0},DEFAULT_EVENT_RETENTION_DAYS=90,DEFAULT_EVENTS_SETTINGS={retentionDays:DEFAULT_EVENT_RETENTION_DAYS},DEFAULT_SESSION_IDLE_DAYS=90,DEFAULT_SESSIONS_SETTINGS={idleDays:DEFAULT_SESSION_IDLE_DAYS},DEFAULT_STARTUP_SETTINGS={launchOnLogin:!1},DEFAULT_SERVER_SETTINGS={bindHost:h,tlsPort:6443},DEFAULT_AI_SETTINGS={baseUrl:"",model:""},DEFAULT_DECISION_SETTINGS={baseUrl:"",model:""},DEFAULT_HTML_EXPORT_SETTINGS={activeId:null,profiles:[]},DEFAULT_DAEMON_SETTINGS={terminal:DEFAULT_TERMINAL_SETTINGS,locale:DEFAULT_LOCALE,hooks:DEFAULT_HOOKS_SETTINGS,decision:DEFAULT_DECISION_SETTINGS,events:DEFAULT_EVENTS_SETTINGS,sessions:DEFAULT_SESSIONS_SETTINGS,startup:DEFAULT_STARTUP_SETTINGS,server:DEFAULT_SERVER_SETTINGS,ai:DEFAULT_AI_SETTINGS,htmlExport:DEFAULT_HTML_EXPORT_SETTINGS};export function resolveLocale(e){return SUPPORTED_LOCALES.includes(e)?e:DEFAULT_LOCALE}export const ALL_TERMINAL_PRESETS=["auto","wt","powershell","cmd","terminal","iterm","gnome","konsole","wezterm","ghostty","custom"];const L={auto:"\u81EA\u52A8\uFF08\u63A2\u6D4B\u53EF\u7528\u7EC8\u7AEF\uFF09",wt:"Windows Terminal",powershell:"PowerShell",cmd:"\u547D\u4EE4\u63D0\u793A\u7B26 (cmd)",terminal:"Terminal.app",iterm:"iTerm2",gnome:"gnome-terminal",konsole:"Konsole",wezterm:"WezTerm",ghostty:"Ghostty",custom:"\u81EA\u5B9A\u4E49\u547D\u4EE4"};export function terminalPresetsFor(e){return(e==="win32"?["auto","wt","wezterm","powershell","cmd","custom"]:e==="darwin"?["auto","terminal","iterm","wezterm","ghostty","custom"]:["auto","gnome","konsole","wezterm","ghostty","custom"]).map(n=>({id:n,label:L[n]}))}function v(e){return Number.isInteger(e)&&e>=0&&e<=65535?e:DEFAULT_SERVER_SETTINGS.tlsPort}const _=50,U=2e5;function I(e){const o=e??{},n=new Set,r=[];for(const l of Array.isArray(o.profiles)?o.profiles:[]){const s=l??{};if(!(typeof s.id!="string"||s.id===""||n.has(s.id))&&!(typeof s.name!="string"||typeof s.head!="string")&&(n.add(s.id),r.push({id:s.id,name:s.name.trim()||`profile-${r.length+1}`,head:s.head.slice(0,U)}),r.length>=_))break}return{activeId:typeof o.activeId=="string"&&n.has(o.activeId)?o.activeId:null,profiles:r}}function T(e){const o=e??{},n=o.terminal??{},r=o.hooks??{},i=o.events??{},l=o.sessions??{},s=o.startup??{},c=o.server??{},d=o.ai??{},u=o.decision??{},y=I(o.htmlExport),D=Number.isInteger(i.retentionDays)&&i.retentionDays>=1?i.retentionDays:DEFAULT_EVENTS_SETTINGS.retentionDays,b=Number.isInteger(l.idleDays)&&l.idleDays>=1?l.idleDays:DEFAULT_SESSIONS_SETTINGS.idleDays;return{terminal:{preset:ALL_TERMINAL_PRESETS.includes(n.preset)?n.preset:DEFAULT_TERMINAL_SETTINGS.preset,customCommand:typeof n.customCommand=="string"?n.customCommand:""},locale:resolveLocale(o.locale),hooks:{enabled:typeof r.enabled=="boolean"?r.enabled:DEFAULT_HOOKS_SETTINGS.enabled},events:{retentionDays:D},sessions:{idleDays:b},startup:{launchOnLogin:typeof s.launchOnLogin=="boolean"?s.launchOnLogin:DEFAULT_STARTUP_SETTINGS.launchOnLogin},server:{bindHost:typeof c.bindHost=="string"&&c.bindHost.trim()!==""?c.bindHost.trim():DEFAULT_SERVER_SETTINGS.bindHost,tlsPort:v(c.tlsPort)},ai:{baseUrl:typeof d.baseUrl=="string"?d.baseUrl.trim():"",model:typeof d.model=="string"?d.model.trim():""},decision:{baseUrl:typeof u.baseUrl=="string"?u.baseUrl.trim():"",model:typeof u.model=="string"?u.model.trim():""},htmlExport:y}}const t={terminalPreset:"terminal.preset",terminalCustomCommand:"terminal.customCommand",locale:"locale",hooksEnabled:"hooks.enabled",eventRetentionDays:"events.retentionDays",sessionIdleDays:"sessions.idleDays",startupLaunchOnLogin:"startup.launchOnLogin",serverBindHost:"server.bindHost",serverTlsPort:"server.tlsPort",aiBaseUrl:"ai.baseUrl",aiModel:"ai.model",decisionBaseUrl:"decision.baseUrl",decisionModel:"decision.model",htmlExport:"htmlExport"};let a=null,m=null;export function setDaemonSettingsDb(e){a=e,m=null}function p(e){if(a)return e(a);const o=f(g());try{return e(o)}finally{o.close()}}function x(e){const o=e.prepare("SELECT key, value FROM settings").all();return new Map(o.map(n=>[n.key,n.value]))}function O(e){return T({terminal:{preset:e.get(t.terminalPreset),customCommand:e.get(t.terminalCustomCommand)},locale:e.get(t.locale),...e.has(t.hooksEnabled)?{hooks:{enabled:e.get(t.hooksEnabled)==="true"}}:{},...e.has(t.eventRetentionDays)?{events:{retentionDays:Number(e.get(t.eventRetentionDays))}}:{},...e.has(t.sessionIdleDays)?{sessions:{idleDays:Number(e.get(t.sessionIdleDays))}}:{},...e.has(t.startupLaunchOnLogin)?{startup:{launchOnLogin:e.get(t.startupLaunchOnLogin)==="true"}}:{},...e.has(t.serverBindHost)||e.has(t.serverTlsPort)?{server:{...e.has(t.serverBindHost)?{bindHost:e.get(t.serverBindHost)}:{},...e.has(t.serverTlsPort)?{tlsPort:Number(e.get(t.serverTlsPort))}:{}}}:{},...e.has(t.aiBaseUrl)||e.has(t.aiModel)?{ai:{baseUrl:e.get(t.aiBaseUrl)??"",model:e.get(t.aiModel)??""}}:{},...e.has(t.decisionBaseUrl)||e.has(t.decisionModel)?{decision:{baseUrl:e.get(t.decisionBaseUrl)??"",model:e.get(t.decisionModel)??""}}:{},...S(e.get(t.htmlExport))!=null?{htmlExport:S(e.get(t.htmlExport))}:{}})}function S(e){if(!e)return null;try{const o=JSON.parse(e);return o!=null&&typeof o=="object"?o:null}catch{return null}}function N(e){return[[t.terminalPreset,e.terminal.preset],[t.terminalCustomCommand,e.terminal.customCommand],[t.locale,e.locale],[t.hooksEnabled,String(e.hooks.enabled)],[t.eventRetentionDays,String(e.events?.retentionDays??DEFAULT_EVENT_RETENTION_DAYS)],[t.sessionIdleDays,String(e.sessions?.idleDays??DEFAULT_SESSION_IDLE_DAYS)],[t.startupLaunchOnLogin,String(e.startup?.launchOnLogin??!1)],[t.serverBindHost,e.server?.bindHost??h],[t.serverTlsPort,String(e.server?.tlsPort??DEFAULT_SERVER_SETTINGS.tlsPort)],[t.aiBaseUrl,e.ai?.baseUrl??""],[t.aiModel,e.ai?.model??""],[t.decisionBaseUrl,e.decision?.baseUrl??""],[t.decisionModel,e.decision?.model??""],[t.htmlExport,JSON.stringify(e.htmlExport??DEFAULT_HTML_EXPORT_SETTINGS)]]}function A(e,o){const n=e.prepare(`INSERT INTO settings (key, value) VALUES (?, ?)
2
- ON CONFLICT(key) DO UPDATE SET value = excluded.value`);e.exec("BEGIN");try{for(const[r,i]of o)n.run(r,i);e.exec("COMMIT")}catch(r){throw e.exec("ROLLBACK"),r}}function E(){try{return p(e=>O(x(e)))}catch{return DEFAULT_DAEMON_SETTINGS}}export async function readDaemonSettings(){return E()}export function readDaemonSettingsSync(){return E()}export function readHooksEnabled(){const e=m;if(e&&e.db===a)return e.value;const o=E().hooks.enabled;return m={db:a,value:o},o}export async function writeDaemonSettings(e){const o=T(e);return p(n=>A(n,N(o))),m=null,o}
1
+ import{openDatabase as D}from"../db/db.js";import{getDbPath as L}from"../db/paths.js";import{DEFAULT_BIND_HOST as h}from"./port.js";export const SUPPORTED_LOCALES=["zh-CN","en"],DEFAULT_LOCALE="zh-CN",DEFAULT_TERMINAL_SETTINGS={preset:"auto",customCommand:""},DEFAULT_HOOKS_SETTINGS={enabled:!0},DEFAULT_EVENT_RETENTION_DAYS=90,DEFAULT_EVENTS_SETTINGS={retentionDays:DEFAULT_EVENT_RETENTION_DAYS},DEFAULT_SESSION_IDLE_DAYS=90,DEFAULT_SESSIONS_SETTINGS={idleDays:DEFAULT_SESSION_IDLE_DAYS},DEFAULT_STARTUP_SETTINGS={launchOnLogin:!1},DEFAULT_SERVER_SETTINGS={bindHost:h,tlsPort:6443},DEFAULT_AI_SETTINGS={baseUrl:"",model:""},DEFAULT_DECISION_SETTINGS={baseUrl:"",model:""},DEFAULT_HTML_EXPORT_SETTINGS={activeId:null,profiles:[]},DEFAULT_PET_SETTINGS={enabled:!1,petId:"weave-spider",notifications:!0,size:"small"},PET_SIZE_PRESETS={small:{width:160,height:192},medium:{width:200,height:240},large:{width:280,height:336}},DEFAULT_DAEMON_SETTINGS={terminal:DEFAULT_TERMINAL_SETTINGS,locale:DEFAULT_LOCALE,hooks:DEFAULT_HOOKS_SETTINGS,decision:DEFAULT_DECISION_SETTINGS,events:DEFAULT_EVENTS_SETTINGS,sessions:DEFAULT_SESSIONS_SETTINGS,startup:DEFAULT_STARTUP_SETTINGS,server:DEFAULT_SERVER_SETTINGS,ai:DEFAULT_AI_SETTINGS,htmlExport:DEFAULT_HTML_EXPORT_SETTINGS,pet:DEFAULT_PET_SETTINGS};export function resolveLocale(e){return SUPPORTED_LOCALES.includes(e)?e:DEFAULT_LOCALE}export const ALL_TERMINAL_PRESETS=["auto","wt","powershell","cmd","terminal","iterm","gnome","konsole","wezterm","ghostty","custom"];const I={auto:"\u81EA\u52A8\uFF08\u63A2\u6D4B\u53EF\u7528\u7EC8\u7AEF\uFF09",wt:"Windows Terminal",powershell:"PowerShell",cmd:"\u547D\u4EE4\u63D0\u793A\u7B26 (cmd)",terminal:"Terminal.app",iterm:"iTerm2",gnome:"gnome-terminal",konsole:"Konsole",wezterm:"WezTerm",ghostty:"Ghostty",custom:"\u81EA\u5B9A\u4E49\u547D\u4EE4"};export function terminalPresetsFor(e){return(e==="win32"?["auto","wt","wezterm","powershell","cmd","custom"]:e==="darwin"?["auto","terminal","iterm","wezterm","ghostty","custom"]:["auto","gnome","konsole","wezterm","ghostty","custom"]).map(n=>({id:n,label:I[n]}))}function v(e){return Number.isInteger(e)&&e>=0&&e<=65535?e:DEFAULT_SERVER_SETTINGS.tlsPort}const _=50,x=2e5;function U(e){const t=e??{},n=new Set,r=[];for(const l of Array.isArray(t.profiles)?t.profiles:[]){const s=l??{};if(!(typeof s.id!="string"||s.id===""||n.has(s.id))&&!(typeof s.name!="string"||typeof s.head!="string")&&(n.add(s.id),r.push({id:s.id,name:s.name.trim()||`profile-${r.length+1}`,head:s.head.slice(0,x)}),r.length>=_))break}return{activeId:typeof t.activeId=="string"&&n.has(t.activeId)?t.activeId:null,profiles:r}}function N(e){const t=e??{};return{enabled:typeof t.enabled=="boolean"?t.enabled:DEFAULT_PET_SETTINGS.enabled,petId:typeof t.petId=="string"&&/^[a-z0-9][a-z0-9-]{0,63}$/i.test(t.petId)?t.petId:DEFAULT_PET_SETTINGS.petId,notifications:typeof t.notifications=="boolean"?t.notifications:DEFAULT_PET_SETTINGS.notifications,size:t.size==="small"||t.size==="medium"||t.size==="large"?t.size:DEFAULT_PET_SETTINGS.size,pos:t.pos&&typeof t.pos=="object"&&typeof t.pos.x=="number"&&typeof t.pos.y=="number"?{x:t.pos.x,y:t.pos.y}:void 0}}function T(e){const t=e??{},n=t.terminal??{},r=t.hooks??{},i=t.events??{},l=t.sessions??{},s=t.startup??{},c=t.server??{},d=t.ai??{},u=t.decision??{},f=U(t.htmlExport),b=N(t.pet),S=Number.isInteger(i.retentionDays)&&i.retentionDays>=1?i.retentionDays:DEFAULT_EVENTS_SETTINGS.retentionDays,g=Number.isInteger(l.idleDays)&&l.idleDays>=1?l.idleDays:DEFAULT_SESSIONS_SETTINGS.idleDays;return{terminal:{preset:ALL_TERMINAL_PRESETS.includes(n.preset)?n.preset:DEFAULT_TERMINAL_SETTINGS.preset,customCommand:typeof n.customCommand=="string"?n.customCommand:""},locale:resolveLocale(t.locale),hooks:{enabled:typeof r.enabled=="boolean"?r.enabled:DEFAULT_HOOKS_SETTINGS.enabled},events:{retentionDays:S},sessions:{idleDays:g},startup:{launchOnLogin:typeof s.launchOnLogin=="boolean"?s.launchOnLogin:DEFAULT_STARTUP_SETTINGS.launchOnLogin},server:{bindHost:typeof c.bindHost=="string"&&c.bindHost.trim()!==""?c.bindHost.trim():DEFAULT_SERVER_SETTINGS.bindHost,tlsPort:v(c.tlsPort)},ai:{baseUrl:typeof d.baseUrl=="string"?d.baseUrl.trim():"",model:typeof d.model=="string"?d.model.trim():""},decision:{baseUrl:typeof u.baseUrl=="string"?u.baseUrl.trim():"",model:typeof u.model=="string"?u.model.trim():""},htmlExport:f,pet:b}}const o={terminalPreset:"terminal.preset",terminalCustomCommand:"terminal.customCommand",locale:"locale",hooksEnabled:"hooks.enabled",eventRetentionDays:"events.retentionDays",sessionIdleDays:"sessions.idleDays",startupLaunchOnLogin:"startup.launchOnLogin",serverBindHost:"server.bindHost",serverTlsPort:"server.tlsPort",aiBaseUrl:"ai.baseUrl",aiModel:"ai.model",decisionBaseUrl:"decision.baseUrl",decisionModel:"decision.model",htmlExport:"htmlExport",pet:"pet.config"};let a=null,m=null;export function setDaemonSettingsDb(e){a=e,m=null}function y(e){if(a)return e(a);const t=D(L());try{return e(t)}finally{t.close()}}function O(e){const t=e.prepare("SELECT key, value FROM settings").all();return new Map(t.map(n=>[n.key,n.value]))}function A(e){return T({terminal:{preset:e.get(o.terminalPreset),customCommand:e.get(o.terminalCustomCommand)},locale:e.get(o.locale),...e.has(o.hooksEnabled)?{hooks:{enabled:e.get(o.hooksEnabled)==="true"}}:{},...e.has(o.eventRetentionDays)?{events:{retentionDays:Number(e.get(o.eventRetentionDays))}}:{},...e.has(o.sessionIdleDays)?{sessions:{idleDays:Number(e.get(o.sessionIdleDays))}}:{},...e.has(o.startupLaunchOnLogin)?{startup:{launchOnLogin:e.get(o.startupLaunchOnLogin)==="true"}}:{},...e.has(o.serverBindHost)||e.has(o.serverTlsPort)?{server:{...e.has(o.serverBindHost)?{bindHost:e.get(o.serverBindHost)}:{},...e.has(o.serverTlsPort)?{tlsPort:Number(e.get(o.serverTlsPort))}:{}}}:{},...e.has(o.aiBaseUrl)||e.has(o.aiModel)?{ai:{baseUrl:e.get(o.aiBaseUrl)??"",model:e.get(o.aiModel)??""}}:{},...e.has(o.decisionBaseUrl)||e.has(o.decisionModel)?{decision:{baseUrl:e.get(o.decisionBaseUrl)??"",model:e.get(o.decisionModel)??""}}:{},...p(e.get(o.htmlExport))!=null?{htmlExport:p(e.get(o.htmlExport))}:{},...p(e.get(o.pet))!=null?{pet:p(e.get(o.pet))}:{}})}function p(e){if(!e)return null;try{const t=JSON.parse(e);return t!=null&&typeof t=="object"?t:null}catch{return null}}function P(e){return[[o.terminalPreset,e.terminal.preset],[o.terminalCustomCommand,e.terminal.customCommand],[o.locale,e.locale],[o.hooksEnabled,String(e.hooks.enabled)],[o.eventRetentionDays,String(e.events?.retentionDays??DEFAULT_EVENT_RETENTION_DAYS)],[o.sessionIdleDays,String(e.sessions?.idleDays??DEFAULT_SESSION_IDLE_DAYS)],[o.startupLaunchOnLogin,String(e.startup?.launchOnLogin??!1)],[o.serverBindHost,e.server?.bindHost??h],[o.serverTlsPort,String(e.server?.tlsPort??DEFAULT_SERVER_SETTINGS.tlsPort)],[o.aiBaseUrl,e.ai?.baseUrl??""],[o.aiModel,e.ai?.model??""],[o.decisionBaseUrl,e.decision?.baseUrl??""],[o.decisionModel,e.decision?.model??""],[o.htmlExport,JSON.stringify(e.htmlExport??DEFAULT_HTML_EXPORT_SETTINGS)],[o.pet,JSON.stringify(e.pet??DEFAULT_PET_SETTINGS)]]}function C(e,t){const n=e.prepare(`INSERT INTO settings (key, value) VALUES (?, ?)
2
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`);e.exec("BEGIN");try{for(const[r,i]of t)n.run(r,i);e.exec("COMMIT")}catch(r){throw e.exec("ROLLBACK"),r}}function E(){try{return y(e=>A(O(e)))}catch{return DEFAULT_DAEMON_SETTINGS}}export async function readDaemonSettings(){return E()}export function readDaemonSettingsSync(){return E()}export function readHooksEnabled(){const e=m;if(e&&e.db===a)return e.value;const t=E().hooks.enabled;return m={db:a,value:t},t}export async function writeDaemonSettings(e){const t=T(e);return y(n=>C(n,P(t))),m=null,t}
@@ -1 +1 @@
1
- import he from"node:http";import{openDatabase as we}from"../db/db.js";import{ProjectRepository as ge}from"../repositories/projects.js";import{HookEventRepository as Se}from"../repositories/hook-events.js";import{LibraryRepository as ve}from"../repositories/libraries.js";import{HookRuleRepository as ne}from"../repositories/hook-rules.js";import{HookDispatchRepository as Re}from"../repositories/hook-dispatches.js";import{PluginStateRepository as E}from"../repositories/plugin-states.js";import{SessionRepository as be}from"../repositories/sessions.js";import{createRuntimeRegistry as ye}from"@weavecode/harness";import{TERMINAL_LOCATOR_ENV_KEYS as ke,isHarness as $}from"@weavecode/core";import{messagingSurfaceFor as De,narrationSurfaceFor as Ee}from"../surfaces.js";import{syntheticSessionIds as Pe}from"../hooks/synthetic-sessions.js";import{createEdgeExtract as Te}from"../hooks/edge-extract.js";import{startSessionSweeper as Oe}from"../hooks/session-sweeper.js";import{startStatuslineCacheSweeper as Ie}from"../statusline/cache-sweeper.js";import{readStatuslineFacts as Ce}from"../statusline/manager.js";import{wireHookFilePipeline as Ae}from"./hook-pipeline.js";import{ensureBuiltinMarket as He,builtinMarketDir as _e}from"../market/builtin.js";import{HookRuleRegistry as Me}from"../hooks/registry.js";import{HookDispatcher as Be}from"../hooks/dispatcher.js";import{HookEventBus as Fe}from"../hooks/bus.js";import{ResumeRunner as Le}from"../hooks/resume-runner.js";import{HeadlessRunner as xe}from"../hooks/headless-runner.js";import{MessageDeliverer as Ne}from"../hooks/message-deliverer.js";import{QuestionTracker as Ue}from"../hooks/question-tracker.js";import{SideQuestionRepository as We}from"../repositories/side-questions.js";import{claimSideAnswer as Qe}from"../hooks/side-questions.js";import{DashboardRateCache as $e}from"../hooks/dashboard-rate.js";import{startDashboardPusher as qe}from"./dashboard-pusher.js";import{startPromptFlusher as je}from"../hooks/prompt-flusher.js";import{SessionWatchRepository as Ke}from"../repositories/session-watches.js";import{PushSubscriptionRepository as Ge}from"../repositories/push-subscriptions.js";import{UploadRepository as Je}from"../repositories/uploads.js";import{defaultUploadSessions as Ve}from"./upload-sessions.js";import{PushNotifier as Ye}from"../hooks/push-notify.js";import{OrchestrationRepository as ze,OrchestrationRunRepository as Xe}from"../repositories/orchestrations.js";import{WatchEngine as Ze}from"../hooks/watch-engine.js";import{OrchestrationEngine as es,createForkConditionJudge as ss}from"../hooks/orchestration-engine.js";import{createDecisionConditionJudge as ts}from"../hooks/decision-judge.js";import{readDecisionKey as os}from"./decision-config.js";import{createEnsureOpen as rs}from"./session-open.js";import{loadAllPlugins as ns}from"../hooks/plugin-loader.js";import{ToolkitService as is}from"../hooks/toolkit.js";import{WatchService as as}from"../watch/watch-service.js";import{SyncScheduler as ls}from"../watch/sync-scheduler.js";import{FingerprintCache as cs}from"../install/fingerprint.js";import{detectProjectUpdateCounts as ps}from"../install/updates.js";import{weaveRequestHandler as ms}from"./server.js";import{startTlsServer as us}from"./tls.js";import{DataBus as fs}from"./data-bus.js";import{TerminalTopologyRefresher as ds}from"./terminal-topology-refresher.js";import{SnapshotRefresher as q}from"./snapshot-refresher.js";import{SessionProbe as hs,dbModelFactResolver as ws,dbTranscriptPathResolver as gs}from"./session-probe.js";import{NarrationWatcher as Ss}from"./narration-watcher.js";import{InflightCountsRefresher as vs}from"./inflight-counts-refresher.js";import{ProjectUpdatesRefresher as Rs}from"./project-updates-refresher.js";import{pidAliveOf as bs}from"./claude-liveness.js";import{combinedLivenessOf as v}from"./liveness.js";import{promptTerminalChannel as ie,readTerminalCounts as ys}from"./opener.js";import{DEFAULT_BIND_HOST as ks}from"./port.js";import{readDaemonState as Ds,writeDaemonState as Es}from"./state.js";import{ensureDataLayout as Ps}from"../db/layout.js";import{pruneFileIndexes as Ts}from"./project-files.js";import{pruneInstallTmp as Os}from"../hooks/plugin-installer.js";import{readDaemonSettingsSync as R,setDaemonSettingsDb as Is,DEFAULT_SERVER_SETTINGS as Cs}from"./settings.js";import{AuthService as As}from"./dashboard-auth.js";import{syncLaunchOnLogin as Hs}from"./auto-start.js";import{resolveStaticDir as _s}from"./static.js";delete process.env.CLAUDE_CODE_CHILD_SESSION;for(const m of ke)delete process.env[m];export function startDaemon(){Ps();const m=Ds();m||(console.error("Daemon state not found. Run `weave daemon start` first."),process.exit(1));const o=we();Is(o);const b=R().server?.bindHost??ks,P=R().server?.tlsPort??Cs.tlsPort,T=new As;T.initialPassword&&console.log(`[weave] initial dashboard password: ${T.initialPassword}`);const r=new ge(o);Ts(r.list().map(e=>e.id)),Os();const l=new Se(o),p=new ve(o),d=ye(),ae=d.byCapability("events").flatMap(e=>e.events??[]),y=new Me(new ne(o)),k=new Re(o),t=new be(o),n=new Fe,O={getHandler:()=>{},getConfig:()=>({})};let f;const I={list:()=>f?.list()??[],setPluginEnabled:(e,s)=>f?.setPluginEnabled(e,s)??!1,reloadAll:async()=>{await f?.reloadAll()},rescan:async()=>{await f?.rescanRoots(r.list(),p)}},le=new is({projects:r,states:new E(o),plugins:I,libraries:p}),C={run:null},j=new Be({registry:y,dispatches:k,bus:n,projects:r,sessions:t,plugins:O,pluginStates:new E(o),classify:e=>C.run?C.run(e):Promise.resolve(null),sessionTitleOf:async e=>{const s=l.listBySession(e,1).at(-1)?.source;return $(s)?d.get(s)?.titles?.sessionTitleOf(e)??null:null}});He({libraries:p}).then(e=>(e.error?console.error(`[weave] builtin market unavailable: ${e.error}`):e.changed&&console.log(`[weave] builtin market ${e.form==="link"?"linked":"copied"} -> ${_e(p.dataRoot)}`),ns({rules:new ne(o),registry:y,states:new E(o),bus:n,libraries:p},r.list()))).then(({loader:e})=>{f=e,O.getHandler=(s,a)=>e.getHandler(s,a),O.getConfig=s=>e.getConfig(s),e.watchRoots()}).catch(e=>{console.error("[weave] plugin load failed:",e instanceof Error?e.message:e)});const D=new xe,ce=new Le({dispatches:k,sessions:t,projects:r,bus:n,resumeSpec:d.get("claude")?.resume,headless:D}),c=new Ne({sessions:t,projects:r,hookEvents:l,bus:n,headless:D,terminal:ie(()=>R().terminal),blockedByQuestion:e=>h.get(e)!=null,livenessOf:v,sideAnswerStore:{answerById:(e,s,a)=>{B.answerById(e,s,a)}}});je(c);const A=new Ke(o),H=new Ze({watches:A,deliverer:c,sessions:t,bus:n,livenessOf:v}),K=new Ge(o),_=new Je(o),pe=new Ye({subscriptions:K,sessions:t,bus:n}),M=new ze(o),G=new Xe(o),u=new hs(gs(l),ws(l,e=>t.getBySessionId(e)?.harness??null)),J=new Ss(n,e=>Ee($(e)?e:"claude"),e=>u.transcriptPathOf(e),e=>t.livenessRowOf(e)?.harness??null);J.start();const h=new Ue({sessions:t,hookEvents:l,onPending:e=>{n.emit({kind:"question.pending",sessionId:e.sessionId,harness:e.harness,count:e.questions.length,at:e.at})},interruptedAt:e=>{const s=t.getBySessionId(e);return s?u.interruptedAt(e,t.lastMainEventAtOf(e)??s.lastSeenAt):null}});h.seedFromDb();const B=new We(o),V=new $e,F=qe({rate:V,events:l,sessions:t,projects:r,bus:n}),Y={repo:B,bus:n,settle:e=>{c.interrupt(e.sessionId)}},L=new as(r);L.start();const x=new cs,i=new fs,z=new Rs(()=>ps(r.list(),p.list(),x),i,n,()=>i.hasSubscribers()),X=new ls(r,p,{cache:x,plugins:I,onSynced:()=>{z.refreshNow(!0)}});X.start();const w=new ds(async()=>({counts:await ys(r.list()),terminals:await c.sessionTerminals()}),i,{shouldRun:()=>i.hasSubscribers(),graceMs:1e4});w.start();const N=new q(()=>{const e=v(),s={};for(const a of t.listWithCounts()){const re=bs(a,e);re!==null&&(s[a.sessionId]=re)}return{alive:s}},i,{key:"sessionLiveness",shouldRun:()=>i.hasSubscribers()});N.start();const U=new q(()=>{const e={};for(const s of t.listWithCounts()){if(s.turnOpen!==!0)continue;const a=u.interruptedAt(s.sessionId,t.lastMainEventAtOf(s.sessionId)??s.lastSeenAt);a!==null&&(e[s.sessionId]=a)}return{interrupted:e}},i,{key:"sessionInterrupt",intervalMs:5e3,shouldRun:()=>i.hasSubscribers()});U.start(),new q(()=>{const e={};for(const s of r.list())e[s.id]=Ce(s.path);return e},i,{key:"statusline",intervalMs:5e3,shouldRun:()=>i.hasSubscribers(),invalidateOnly:!0}).start();const me=new vs(()=>c.listInflightCounts(),i,n);let Z=null;const g=Te({sessions:t,projects:r,harnessOf:e=>{const s=l.listBySession(e,1),a=s[s.length-1]?.source;return $(a)?a:null},surfaceFor:De,headless:D,onSyntheticChange:()=>Z?.pushSyntheticSessions(Pe())});C.run=e=>g.run(e);const ue=ts({config:async()=>{const e=R().decision;if(!e?.baseUrl||!e.model)return null;const s=os();return s?{baseUrl:e.baseUrl,model:e.model,apiKey:s}:null},fallback:ss({supports:e=>g.supports(e),extract:e=>g.run(e)})}),fe=rs({hookSessions:t,hookEvents:l,projects:r,harnesses:d,sessionProbe:u,terminalRefresher:w,livenessOf:v}),S=new es({orchestrations:M,runs:G,deliverer:c,sessions:t,bus:n,supportsExtract:e=>g.supports(e),extract:e=>g.run(e),conditionJudge:ue,deferWhenUserPresent:!0,ensureOpen:fe});S.rearm();const ee=setInterval(()=>S.cronTick(),3e4);ee.unref(),Oe({sessions:t,events:l,dispatches:k,deliverer:c,watches:A,orchestrations:M,watchEngine:H,orchestrationEngine:S,questions:h,sideQuestions:B,probe:u,uploads:_,uploadSessions:Ve,livenessOf:v}),Ie();const W=Ae({projects:r,rules:y,sessions:t,bus:n,dispatcher:j,watchEngine:H,orchestrationEngine:S,messagePipe:c,questionTracker:h,sideQuestions:{onEvent:e=>{Qe(Y,e)}},sessionProbe:u,uploads:_,dashboardRate:V,terminalTopologyKick:()=>{w.refreshNow()}});Z=W;const de=_s(),se=ms({projects:r,port:m.port,tlsPort:P,watch:L,hookEvents:l,adapters:ae,harnesses:d,libraries:p,fingerprintCache:x,staticDir:de,hookRegistry:y,hookDispatches:k,hookSessions:t,hookBus:n,dataBus:i,terminalRefresher:w,interruptRefresher:U,livenessRefresher:N,sessionProbe:u,inflightRefresher:me,updatesRefresher:z,hookDispatcher:j,hookRunner:ce,messageDeliverer:c,terminal:ie(()=>R().terminal),uploads:_,questionTracker:h,sideQuestions:Y,sessionWatches:A,watchEngine:H,orchestrations:M,orchestrationRuns:G,orchestrationEngine:S,pushSubscriptions:K,pushNotifier:pe,onAttach:F.attach,dashboardRefresh:F.attach,hookPlugins:I,hookMirror:W.mirror,pluginStates:new E(o),toolkit:le,auth:T}),Q=he.createServer(se);let te=null;us({port:P,bindHost:b,handler:se}).then(e=>{te=e});const oe=()=>{f?.stopWatching(),w.stop(),N.stop(),U.stop(),X.stop(),L.stop(),D.killAll(),clearInterval(ee),J.stop(),F.stop(),Q.close(),te?.server.close();const e=setTimeout(()=>process.exit(0),3e3);W.stop().catch(()=>{}).finally(()=>{clearTimeout(e),process.exit(0)})};process.on("SIGTERM",oe),process.on("SIGINT",oe),Q.listen(m.port,b,()=>{Es({...m,pid:process.pid,host:b,tlsPort:P}),Hs()}),Q.on("error",e=>{throw console.error(`[weave] daemon listen failed on ${b}:${m.port}: ${e.message}`),e})}
1
+ import he from"node:http";import{openDatabase as we}from"../db/db.js";import{ProjectRepository as ge}from"../repositories/projects.js";import{HookEventRepository as Se}from"../repositories/hook-events.js";import{LibraryRepository as Re}from"../repositories/libraries.js";import{HookRuleRepository as ne}from"../repositories/hook-rules.js";import{HookDispatchRepository as ve}from"../repositories/hook-dispatches.js";import{PluginStateRepository as E}from"../repositories/plugin-states.js";import{SessionRepository as be}from"../repositories/sessions.js";import{createRuntimeRegistry as ye}from"@weavecode/harness";import{TERMINAL_LOCATOR_ENV_KEYS as ke,isHarness as Q}from"@weavecode/core";import{messagingSurfaceFor as Pe,narrationSurfaceFor as De}from"../surfaces.js";import{syntheticSessionIds as Ee}from"../hooks/synthetic-sessions.js";import{createEdgeExtract as Te}from"../hooks/edge-extract.js";import{startSessionSweeper as Oe}from"../hooks/session-sweeper.js";import{startStatuslineCacheSweeper as Ae}from"../statusline/cache-sweeper.js";import{readStatuslineFacts as Ie}from"../statusline/manager.js";import{wireHookFilePipeline as Ce}from"./hook-pipeline.js";import{ensureBuiltinMarket as He,builtinMarketDir as _e}from"../market/builtin.js";import{HookRuleRegistry as Me}from"../hooks/registry.js";import{HookDispatcher as Be}from"../hooks/dispatcher.js";import{HookEventBus as Fe}from"../hooks/bus.js";import{ResumeRunner as Le}from"../hooks/resume-runner.js";import{HeadlessRunner as Ue}from"../hooks/headless-runner.js";import{MessageDeliverer as xe}from"../hooks/message-deliverer.js";import{QuestionTracker as Ne}from"../hooks/question-tracker.js";import{SideQuestionRepository as We}from"../repositories/side-questions.js";import{claimSideAnswer as $e}from"../hooks/side-questions.js";import{DashboardRateCache as Qe}from"../hooks/dashboard-rate.js";import{startDashboardPusher as qe}from"./dashboard-pusher.js";import{startPromptFlusher as je}from"../hooks/prompt-flusher.js";import{SessionWatchRepository as Ge}from"../repositories/session-watches.js";import{PushSubscriptionRepository as Ke}from"../repositories/push-subscriptions.js";import{UploadRepository as Je}from"../repositories/uploads.js";import{defaultUploadSessions as Ve}from"./upload-sessions.js";import{PushNotifier as Ye}from"../hooks/push-notify.js";import{OrchestrationRepository as ze,OrchestrationRunRepository as Xe}from"../repositories/orchestrations.js";import{WatchEngine as Ze}from"../hooks/watch-engine.js";import{OrchestrationEngine as es,createForkConditionJudge as ss}from"../hooks/orchestration-engine.js";import{createDecisionConditionJudge as ts}from"../hooks/decision-judge.js";import{readDecisionKey as os}from"./decision-config.js";import{createEnsureOpen as rs}from"./session-open.js";import{loadAllPlugins as ns}from"../hooks/plugin-loader.js";import{ToolkitService as is}from"../hooks/toolkit.js";import{WatchService as as}from"../watch/watch-service.js";import{SyncScheduler as cs}from"../watch/sync-scheduler.js";import{FingerprintCache as ls}from"../install/fingerprint.js";import{detectProjectUpdateCounts as ps}from"../install/updates.js";import{weaveRequestHandler as ms}from"./server.js";import{startTlsServer as us}from"./tls.js";import{DataBus as fs}from"./data-bus.js";import{TerminalTopologyRefresher as ds}from"./terminal-topology-refresher.js";import{SnapshotRefresher as q}from"./snapshot-refresher.js";import{SessionProbe as hs,dbModelFactResolver as ws,dbTranscriptPathResolver as gs}from"./session-probe.js";import{NarrationWatcher as Ss}from"./narration-watcher.js";import{InflightCountsRefresher as Rs}from"./inflight-counts-refresher.js";import{ProjectUpdatesRefresher as vs}from"./project-updates-refresher.js";import{pidAliveOf as bs}from"./claude-liveness.js";import{combinedLivenessOf as R}from"./liveness.js";import{promptTerminalChannel as ie,readTerminalCounts as ys}from"./opener.js";import{DEFAULT_BIND_HOST as ks}from"./port.js";import{readDaemonState as Ps,writeDaemonState as Ds}from"./state.js";import{ensureDataLayout as Es}from"../db/layout.js";import{pruneFileIndexes as Ts}from"./project-files.js";import{pruneInstallTmp as Os}from"../hooks/plugin-installer.js";import{readDaemonSettingsSync as v,setDaemonSettingsDb as As,DEFAULT_SERVER_SETTINGS as Is}from"./settings.js";import{AuthService as Cs}from"./dashboard-auth.js";import{syncLaunchOnLogin as Hs}from"./auto-start.js";import{resolveStaticDir as _s}from"./static.js";import{openPetWindow as Ms,shutdownPetWindow as Bs}from"./pet-window.js";import{seedBuiltinPets as Fs}from"./pet-seed.js";delete process.env.CLAUDE_CODE_CHILD_SESSION;for(const p of ke)delete process.env[p];export function startDaemon(){Es();const p=Ps();p||(console.error("Daemon state not found. Run `weave daemon start` first."),process.exit(1));const t=we();As(t);const b=v().server?.bindHost??ks,T=v().server?.tlsPort??Is.tlsPort,y=new Cs;y.initialPassword&&console.log(`[weave] initial dashboard password: ${y.initialPassword}`);const r=new ge(t);Ts(r.list().map(e=>e.id)),Os();const c=new Se(t),m=new Re(t),d=ye(),ae=d.byCapability("events").flatMap(e=>e.events??[]),k=new Me(new ne(t)),P=new ve(t),o=new be(t),n=new Fe,O={getHandler:()=>{},getConfig:()=>({})};let f;const A={list:()=>f?.list()??[],setPluginEnabled:(e,s)=>f?.setPluginEnabled(e,s)??!1,reloadAll:async()=>{await f?.reloadAll()},rescan:async()=>{await f?.rescanRoots(r.list(),m)}},ce=new is({projects:r,states:new E(t),plugins:A,libraries:m}),I={run:null},j=new Be({registry:k,dispatches:P,bus:n,projects:r,sessions:o,plugins:O,pluginStates:new E(t),classify:e=>I.run?I.run(e):Promise.resolve(null),sessionTitleOf:async e=>{const s=c.listBySession(e,1).at(-1)?.source;return Q(s)?d.get(s)?.titles?.sessionTitleOf(e)??null:null}});He({libraries:m}).then(e=>(e.error?console.error(`[weave] builtin market unavailable: ${e.error}`):e.changed&&console.log(`[weave] builtin market ${e.form==="link"?"linked":"copied"} -> ${_e(m.dataRoot)}`),ns({rules:new ne(t),registry:k,states:new E(t),bus:n,libraries:m},r.list()))).then(({loader:e})=>{f=e,O.getHandler=(s,a)=>e.getHandler(s,a),O.getConfig=s=>e.getConfig(s),e.watchRoots()}).catch(e=>{console.error("[weave] plugin load failed:",e instanceof Error?e.message:e)});const D=new Ue,le=new Le({dispatches:P,sessions:o,projects:r,bus:n,resumeSpec:d.get("claude")?.resume,headless:D}),l=new xe({sessions:o,projects:r,hookEvents:c,bus:n,headless:D,terminal:ie(()=>v().terminal),blockedByQuestion:e=>h.get(e)!=null,livenessOf:R,sideAnswerStore:{answerById:(e,s,a)=>{B.answerById(e,s,a)}}});je(l);const C=new Ge(t),H=new Ze({watches:C,deliverer:l,sessions:o,bus:n,livenessOf:R}),G=new Ke(t),_=new Je(t),pe=new Ye({subscriptions:G,sessions:o,bus:n}),M=new ze(t),K=new Xe(t),u=new hs(gs(c),ws(c,e=>o.getBySessionId(e)?.harness??null)),J=new Ss(n,e=>De(Q(e)?e:"claude"),e=>u.transcriptPathOf(e),e=>o.livenessRowOf(e)?.harness??null);J.start();const h=new Ne({sessions:o,hookEvents:c,onPending:e=>{n.emit({kind:"question.pending",sessionId:e.sessionId,harness:e.harness,count:e.questions.length,at:e.at})},interruptedAt:e=>{const s=o.getBySessionId(e);return s?u.interruptedAt(e,o.lastMainEventAtOf(e)??s.lastSeenAt):null}});h.seedFromDb();const B=new We(t),V=new Qe,F=qe({rate:V,events:c,sessions:o,projects:r,bus:n}),Y={repo:B,bus:n,settle:e=>{l.interrupt(e.sessionId)}},L=new as(r);L.start();const U=new ls,i=new fs,z=new vs(()=>ps(r.list(),m.list(),U),i,n,()=>i.hasSubscribers()),X=new cs(r,m,{cache:U,plugins:A,onSynced:()=>{z.refreshNow(!0)}});X.start();const w=new ds(async()=>({counts:await ys(r.list()),terminals:await l.sessionTerminals()}),i,{shouldRun:()=>i.hasSubscribers(),graceMs:1e4});w.start();const x=new q(()=>{const e=R(),s={};for(const a of o.listWithCounts()){const re=bs(a,e);re!==null&&(s[a.sessionId]=re)}return{alive:s}},i,{key:"sessionLiveness",shouldRun:()=>i.hasSubscribers()});x.start();const N=new q(()=>{const e={};for(const s of o.listWithCounts()){if(s.turnOpen!==!0)continue;const a=u.interruptedAt(s.sessionId,o.lastMainEventAtOf(s.sessionId)??s.lastSeenAt);a!==null&&(e[s.sessionId]=a)}return{interrupted:e}},i,{key:"sessionInterrupt",intervalMs:5e3,shouldRun:()=>i.hasSubscribers()});N.start(),new q(()=>{const e={};for(const s of r.list())e[s.id]=Ie(s.path);return e},i,{key:"statusline",intervalMs:5e3,shouldRun:()=>i.hasSubscribers(),invalidateOnly:!0}).start();const me=new Rs(()=>l.listInflightCounts(),i,n);let Z=null;const g=Te({sessions:o,projects:r,harnessOf:e=>{const s=c.listBySession(e,1),a=s[s.length-1]?.source;return Q(a)?a:null},surfaceFor:Pe,headless:D,onSyntheticChange:()=>Z?.pushSyntheticSessions(Ee())});I.run=e=>g.run(e);const ue=ts({config:async()=>{const e=v().decision;if(!e?.baseUrl||!e.model)return null;const s=os();return s?{baseUrl:e.baseUrl,model:e.model,apiKey:s}:null},fallback:ss({supports:e=>g.supports(e),extract:e=>g.run(e)})}),fe=rs({hookSessions:o,hookEvents:c,projects:r,harnesses:d,sessionProbe:u,terminalRefresher:w,livenessOf:R}),S=new es({orchestrations:M,runs:K,deliverer:l,sessions:o,bus:n,supportsExtract:e=>g.supports(e),extract:e=>g.run(e),conditionJudge:ue,deferWhenUserPresent:!0,ensureOpen:fe});S.rearm();const ee=setInterval(()=>S.cronTick(),3e4);ee.unref(),Oe({sessions:o,events:c,dispatches:P,deliverer:l,watches:C,orchestrations:M,watchEngine:H,orchestrationEngine:S,questions:h,sideQuestions:B,probe:u,uploads:_,uploadSessions:Ve,livenessOf:R}),Ae();const W=Ce({projects:r,rules:k,sessions:o,bus:n,dispatcher:j,watchEngine:H,orchestrationEngine:S,messagePipe:l,questionTracker:h,sideQuestions:{onEvent:e=>{$e(Y,e)}},sessionProbe:u,uploads:_,dashboardRate:V,terminalTopologyKick:()=>{w.refreshNow()}});Z=W;const de=_s(),se=ms({projects:r,port:p.port,tlsPort:T,watch:L,hookEvents:c,adapters:ae,harnesses:d,libraries:m,fingerprintCache:U,staticDir:de,hookRegistry:k,hookDispatches:P,hookSessions:o,hookBus:n,dataBus:i,terminalRefresher:w,interruptRefresher:N,livenessRefresher:x,sessionProbe:u,inflightRefresher:me,updatesRefresher:z,hookDispatcher:j,hookRunner:le,messageDeliverer:l,terminal:ie(()=>v().terminal),uploads:_,questionTracker:h,sideQuestions:Y,sessionWatches:C,watchEngine:H,orchestrations:M,orchestrationRuns:K,orchestrationEngine:S,pushSubscriptions:G,pushNotifier:pe,onAttach:F.attach,dashboardRefresh:F.attach,hookPlugins:A,hookMirror:W.mirror,pluginStates:new E(t),toolkit:ce,auth:y}),$=he.createServer(se);let te=null;us({port:T,bindHost:b,handler:se}).then(e=>{te=e});const oe=()=>{f?.stopWatching(),w.stop(),x.stop(),N.stop(),X.stop(),L.stop(),Bs(),D.killAll(),clearInterval(ee),J.stop(),F.stop(),$.close(),te?.server.close();const e=()=>{try{t.exec("PRAGMA wal_checkpoint(TRUNCATE)"),t.close()}catch{}},s=setTimeout(()=>{e(),process.exit(0)},3e3);W.stop().catch(()=>{}).finally(()=>{clearTimeout(s),e(),process.exit(0)})};process.on("SIGTERM",oe),process.on("SIGINT",oe),$.listen(p.port,b,()=>{Ds({...p,pid:process.pid,host:b,tlsPort:T}),Hs(),Fs().then(()=>{Ms({baseUrl:`http://localhost:${p.port}`,auth:y})})}),$.on("error",e=>{throw console.error(`[weave] daemon listen failed on ${b}:${p.port}: ${e.message}`),e})}
@@ -1,3 +1,6 @@
1
1
  import { DatabaseSync } from 'node:sqlite';
2
- /** Open (creating + migrating if needed) the weave database. */
2
+ /**
3
+ * Open (creating + migrating if needed) the weave database. 损坏类错误在隔离
4
+ * 重建后继续启动(见 quarantineAndRebuild),其余错误原样上抛。
5
+ */
3
6
  export declare function openDatabase(dbPath?: string): DatabaseSync;
@@ -1,4 +1,4 @@
1
- import{mkdirSync as o}from"node:fs";import N from"node:path";import{DatabaseSync as n}from"node:sqlite";import{getDbPath as r}from"./paths.js";import{projectKey as a}from"../repositories/projects.js";const L=`
1
+ import{existsSync as L,mkdirSync as a,readdirSync as _,renameSync as d,unlinkSync as A}from"node:fs";import i from"node:path";import{DatabaseSync as O}from"node:sqlite";import{getDbPath as u}from"./paths.js";import{projectKey as R}from"../repositories/projects.js";const I=`
2
2
  CREATE TABLE IF NOT EXISTS projects (
3
3
  id INTEGER PRIMARY KEY AUTOINCREMENT,
4
4
  path TEXT NOT NULL UNIQUE,
@@ -204,4 +204,4 @@ CREATE TABLE IF NOT EXISTS event_images (
204
204
  upload_id TEXT NOT NULL,
205
205
  PRIMARY KEY (event_id, upload_id)
206
206
  );
207
- `;export function openDatabase(T=r()){T!==":memory:"&&o(N.dirname(T),{recursive:!0});const e=new n(T);return e.exec("PRAGMA busy_timeout = 5000"),e.exec("PRAGMA journal_mode = WAL"),e.exec("PRAGMA foreign_keys = ON"),R(e),e.exec(L),e.exec("DROP TABLE IF EXISTS session_messages"),X(e),O(e),_(e),d(e),A(e),e}function _(T){const e=T.prepare("SELECT id, path FROM projects ORDER BY id").all(),E=new Set(e.map(s=>s.path)),i=T.prepare("UPDATE projects SET path = ? WHERE id = ?");for(const s of e){const t=a(s.path);t===s.path||E.has(t)||(E.delete(s.path),E.add(t),i.run(t,s.id))}}function d(T){const e=new Set(T.prepare("PRAGMA table_info(session_watches)").all().map(E=>String(E.name)));e.size!==0&&(e.has("on_events")||T.exec("ALTER TABLE session_watches ADD COLUMN on_events TEXT"),e.has("remaining")||(T.exec("ALTER TABLE session_watches ADD COLUMN remaining INTEGER"),T.exec("UPDATE session_watches SET remaining = 1")))}function O(T){const e=new Set(T.prepare("PRAGMA table_info(projects)").all().map(E=>String(E.name)));e.size!==0&&(e.has("sort_order")||T.exec("ALTER TABLE projects ADD COLUMN sort_order INTEGER"),e.has("archived_at")||T.exec("ALTER TABLE projects ADD COLUMN archived_at TEXT"))}function A(T){const e=new Set(T.prepare("PRAGMA table_info(uploads)").all().map(E=>String(E.name)));e.size!==0&&(e.has("dir")||T.exec("ALTER TABLE uploads ADD COLUMN dir TEXT"))}function R(T){const e=T.prepare("PRAGMA table_info(orchestrations)").all();e.length===0||e.some(E=>E.name==="enabled")||T.exec("DROP TABLE orchestrations")}function X(T){const e=new Set(T.prepare("PRAGMA table_info(hook_rules)").all().map(E=>String(E.name)));e.size!==0&&(e.has("origin")||T.exec("ALTER TABLE hook_rules ADD COLUMN origin TEXT NOT NULL DEFAULT 'user'"),e.has("plugin_id")||T.exec("ALTER TABLE hook_rules ADD COLUMN plugin_id TEXT"),T.exec("CREATE INDEX IF NOT EXISTS idx_hook_rules_plugin ON hook_rules(plugin_id)"))}
207
+ `,N=1,p=3;function X(T){const e=T instanceof Error?T.message:String(T);return/malformed database schema|database disk image is malformed|file is not a database|SQLITE_CORRUPT/i.test(e)}function l(T){const e=T.prepare("PRAGMA user_version").get();return typeof e?.user_version=="number"?e.user_version:0}function U(T,e){if(e===":memory:")return;const t=l(T);if(t>=N)return;const o=T.prepare("SELECT count(*) AS n FROM sqlite_master").get();if(!o||o.n===0)return;const s=i.join(i.dirname(e),"backups");a(s,{recursive:!0});const E=new Date().toISOString().replace(/[:.]/g,"-"),n=i.join(s,`weave-v${t}-${E}.db`);try{T.exec(`VACUUM INTO '${n.replace(/'/g,"''")}'`),console.log(`[weave] database backup before migration: ${n}`),h(s)}catch(r){console.error(`[weave] database backup failed (continuing): ${r instanceof Error?r.message:r}`)}}function h(T){try{const e=_(T).filter(t=>t.startsWith("weave-v")&&t.endsWith(".db")).sort();for(const t of e.slice(0,Math.max(0,e.length-p)))try{A(i.join(T,t))}catch{}}catch{}}function S(T,e){const t=new Date().toISOString().replace(/[:.]/g,"-"),o=`${T}.corrupt-${t}`;for(const E of["","-wal","-shm"])try{L(T+E)&&d(T+E,o+E)}catch{}const s=e instanceof Error?e.message:String(e);return console.error(`[weave] database is corrupt (${s}); moved to ${o} and starting with a fresh one. Recover the old data with: sqlite3 "${o}" ".recover" | sqlite3 "${T}"`),c(T)}export function openDatabase(T=u()){T!==":memory:"&&a(i.dirname(T),{recursive:!0});try{return c(T)}catch(e){if(!X(e))throw e;return S(T,e)}}function c(T){const e=new O(T);try{e.exec("PRAGMA busy_timeout = 5000"),e.exec("PRAGMA journal_mode = WAL"),e.exec("PRAGMA foreign_keys = ON");const t=e.prepare("PRAGMA quick_check").get();if(t?.quick_check!==void 0&&t.quick_check!=="ok")throw new Error(`malformed database schema (${t.quick_check})`);return U(e,T),g(e),e.exec(I),e.exec("DROP TABLE IF EXISTS session_messages"),k(e),C(e),m(e),f(e),D(e),e.exec(`PRAGMA user_version = ${N}`),e}catch(t){try{e.close()}catch{}throw t}}function m(T){const e=T.prepare("SELECT id, path FROM projects ORDER BY id").all(),t=new Set(e.map(s=>s.path)),o=T.prepare("UPDATE projects SET path = ? WHERE id = ?");for(const s of e){const E=R(s.path);E===s.path||t.has(E)||(t.delete(s.path),t.add(E),o.run(E,s.id))}}function f(T){const e=new Set(T.prepare("PRAGMA table_info(session_watches)").all().map(t=>String(t.name)));e.size!==0&&(e.has("on_events")||T.exec("ALTER TABLE session_watches ADD COLUMN on_events TEXT"),e.has("remaining")||(T.exec("ALTER TABLE session_watches ADD COLUMN remaining INTEGER"),T.exec("UPDATE session_watches SET remaining = 1")))}function C(T){const e=new Set(T.prepare("PRAGMA table_info(projects)").all().map(t=>String(t.name)));e.size!==0&&(e.has("sort_order")||T.exec("ALTER TABLE projects ADD COLUMN sort_order INTEGER"),e.has("archived_at")||T.exec("ALTER TABLE projects ADD COLUMN archived_at TEXT"))}function D(T){const e=new Set(T.prepare("PRAGMA table_info(uploads)").all().map(t=>String(t.name)));e.size!==0&&(e.has("dir")||T.exec("ALTER TABLE uploads ADD COLUMN dir TEXT"))}function g(T){const e=T.prepare("PRAGMA table_info(orchestrations)").all();e.length===0||e.some(t=>t.name==="enabled")||T.exec("DROP TABLE orchestrations")}function k(T){const e=new Set(T.prepare("PRAGMA table_info(hook_rules)").all().map(t=>String(t.name)));e.size!==0&&(e.has("origin")||T.exec("ALTER TABLE hook_rules ADD COLUMN origin TEXT NOT NULL DEFAULT 'user'"),e.has("plugin_id")||T.exec("ALTER TABLE hook_rules ADD COLUMN plugin_id TEXT"),T.exec("CREATE INDEX IF NOT EXISTS idx_hook_rules_plugin ON hook_rules(plugin_id)"))}
@@ -24,6 +24,10 @@ export declare function getDbPath(dir?: string): string;
24
24
  export declare function getPluginsDir(dir?: string): string;
25
25
  /** 会话图片上传的落盘根(内容寻址 `<sha256>.<ext>`;绝对路径由 harness 引用)。 */
26
26
  export declare function getUploadsDir(dir?: string): string;
27
+ /** 桌面宠物资产根(`<id>/pet.json + spritesheet.webp`;skill 生成、随数据迁移)。 */
28
+ export declare function getPetsDir(dir?: string): string;
29
+ /** 渲染块 fragment 的稳定落点(模型产物;与上传同级,随数据迁移、可在设置页清理)。 */
30
+ export declare function getVisualizationsDir(dir?: string): string;
27
31
  /** Absolute path to the daemon auth file (password hash + secrets, 0600). */
28
32
  export declare function getAuthPath(dir?: string): string;
29
33
  /** Absolute path to the one-shot initial-password marker (0600; 首个 CLI 命令领取后即删). */
@@ -1 +1 @@
1
- import o from"node:path";import{detectPlatform as n}from"@weavecode/core";export function getDataDir(){return o.join(n().configDir,"weave")}export function dataRoots(t=getDataDir()){return{data:o.join(t,"data"),local:o.join(t,"local"),cache:o.join(t,"cache")}}export function getDataRoot(t){return dataRoots(t).data}export function getDbPath(t){return o.join(dataRoots(t).data,"weave.db")}export function getPluginsDir(t){return o.join(dataRoots(t).data,"plugins")}export function getUploadsDir(t){return o.join(dataRoots(t).data,"uploads")}export function getAuthPath(t){return o.join(dataRoots(t).local,"auth.json")}export function getInitialPasswordPath(t){return o.join(dataRoots(t).local,"initial-password")}export function getAiKeyPath(t){return o.join(dataRoots(t).local,"ai.json")}export function getDecisionKeyPath(t){return o.join(dataRoots(t).local,"decision.json")}export function getPushKeysPath(t){return o.join(dataRoots(t).local,"push.json")}export function getHarnessConfigDir(t){return o.join(dataRoots(t).local,"harness-config")}export function getCertsDir(t){return o.join(dataRoots(t).local,"certs")}export function getAutoStartScriptPath(t){return o.join(dataRoots(t).local,"weave-autostart.vbs")}export function getDaemonStatePath(t){return o.join(dataRoots(t).cache,"daemon.json")}export function getLogsDir(t){return o.join(dataRoots(t).cache,"logs")}export function getApiLogsDir(t){return o.join(getLogsDir(t),"api")}export function getHooksDir(t){return o.join(dataRoots(t).cache,"hooks")}export function getStatuslineDir(t){return o.join(dataRoots(t).cache,"statusline")}export function getTmpDir(t){return o.join(dataRoots(t).cache,"tmp")}export function getIndexDir(t){return o.join(dataRoots(t).cache,"index")}
1
+ import n from"node:path";import{detectPlatform as o}from"@weavecode/core";export function getDataDir(){return n.join(o().configDir,"weave")}export function dataRoots(t=getDataDir()){return{data:n.join(t,"data"),local:n.join(t,"local"),cache:n.join(t,"cache")}}export function getDataRoot(t){return dataRoots(t).data}export function getDbPath(t){return n.join(dataRoots(t).data,"weave.db")}export function getPluginsDir(t){return n.join(dataRoots(t).data,"plugins")}export function getUploadsDir(t){return n.join(dataRoots(t).data,"uploads")}export function getPetsDir(t){return n.join(dataRoots(t).data,"pets")}export function getVisualizationsDir(t){return n.join(dataRoots(t).data,"visualizations")}export function getAuthPath(t){return n.join(dataRoots(t).local,"auth.json")}export function getInitialPasswordPath(t){return n.join(dataRoots(t).local,"initial-password")}export function getAiKeyPath(t){return n.join(dataRoots(t).local,"ai.json")}export function getDecisionKeyPath(t){return n.join(dataRoots(t).local,"decision.json")}export function getPushKeysPath(t){return n.join(dataRoots(t).local,"push.json")}export function getHarnessConfigDir(t){return n.join(dataRoots(t).local,"harness-config")}export function getCertsDir(t){return n.join(dataRoots(t).local,"certs")}export function getAutoStartScriptPath(t){return n.join(dataRoots(t).local,"weave-autostart.vbs")}export function getDaemonStatePath(t){return n.join(dataRoots(t).cache,"daemon.json")}export function getLogsDir(t){return n.join(dataRoots(t).cache,"logs")}export function getApiLogsDir(t){return n.join(getLogsDir(t),"api")}export function getHooksDir(t){return n.join(dataRoots(t).cache,"hooks")}export function getStatuslineDir(t){return n.join(dataRoots(t).cache,"statusline")}export function getTmpDir(t){return n.join(dataRoots(t).cache,"tmp")}export function getIndexDir(t){return n.join(dataRoots(t).cache,"index")}
@@ -6,7 +6,7 @@
6
6
  * surface.
7
7
  */
8
8
  export { openDatabase } from './db/db.js';
9
- export { getDataDir, getDbPath, getDaemonStatePath, getAuthPath, getInitialPasswordPath } from './db/paths.js';
9
+ export { getDataDir, getDbPath, getDaemonStatePath, getAuthPath, getInitialPasswordPath, getVisualizationsDir, } from './db/paths.js';
10
10
  export { ensureDataLayout, migrateDataLayout } from './db/layout.js';
11
11
  export type { LayoutMigration } from './db/layout.js';
12
12
  export { ProjectRepository } from './repositories/projects.js';
@@ -1 +1 @@
1
- import{existsSync as o}from"node:fs";import{fileURLToPath as r}from"node:url";export{openDatabase}from"./db/db.js";export{getDataDir,getDbPath,getDaemonStatePath,getAuthPath,getInitialPasswordPath}from"./db/paths.js";export{ensureDataLayout,migrateDataLayout}from"./db/layout.js";export{ProjectRepository}from"./repositories/projects.js";export{HookEventRepository}from"./repositories/hook-events.js";export{SessionRepository}from"./repositories/sessions.js";export{LibraryRepository}from"./repositories/libraries.js";export{DEFAULT_PORT,DAEMON_HOST,isPortFree,findFreePort}from"./daemon/port.js";export{readDaemonState,writeDaemonState,clearDaemonState}from"./daemon/state.js";export{generateToken}from"./daemon/auth.js";export{createWeaveServer,weaveRequestHandler,DAEMON_VERSION}from"./daemon/server.js";export{accessUrls,lanIps,ensureDaemonCert,startTlsServer,daemonCertsDir}from"./daemon/tls.js";export{readDaemonSettings,writeDaemonSettings,terminalPresetsFor,resolveLocale,DEFAULT_DAEMON_SETTINGS,SUPPORTED_LOCALES,DEFAULT_LOCALE}from"./daemon/settings.js";export{resolveTerminalLaunch,resolveExplorerLaunch,openInExplorer,openInTerminal,runInTerminal,defaultProjectOpener}from"./daemon/opener.js";export{resolveStaticDir}from"./daemon/static.js";export{startDaemon}from"./daemon/start.js";export{registerProject,unregisterProject}from"./registry.js";export{probeBinVersion}from"./daemon/project-harnesses.js";export{classifyAsset,normalizeRelPath}from"./watch/classifier.js";export{WatchCache}from"./watch/cache.js";export{WatchService}from"./watch/watch-service.js";export{SyncScheduler}from"./watch/sync-scheduler.js";export{ClaudeCodeAdapter}from"./hooks/adapter.js";export{drainInboxOnce,handleIngestedRecords}from"./hooks/inbox-worker.js";export{MirrorWriter,hooksRoot,hookShardId,appendOutbox}from"./hooks/mirror.js";export{scanLibrarySkills,scanLibraryMcp,scanLibraryFileAssets}from"./install/scanner.js";export{FILE_ASSET_SPECS,FILE_ASSET_CATEGORIES,fileAssetTargetDir,isFileAssetCategory}from"./install/file-assets.js";export{installSkill,uninstallSkill,installFileAsset,uninstallFileAsset,installMcp,uninstallMcp,InstallConflictError,AssetNotFoundError}from"./install/installer.js";export{readMcpServers,readMcpJson}from"./install/installer.js";export{codexConfigFile,readCodexMcpServers,writeCodexMcpServer,removeCodexMcpServer,codexMcpExists,readCodexMcpFromText,upsertCodexMcpInText,removeCodexMcpFromText,upsertCodexPluginEnabledInText,parseDottedKey,sectionHeaderKey,renderTomlHeader,renderTomlKey,renderTomlString,splitTomlSections,upsertTomlSection,removeTomlSection,parseSectionEntries,CodexTomlCorruptError}from"./install/codex-toml.js";export{buildLibraryIndex,findSkillSource,findFileAssetSource}from"./install/library-index.js";export{hashSkillDir,maxMtimeDir,hashMcpConfig,hashFile,FingerprintCache}from"./install/fingerprint.js";export{projectFileNamespaces,projectPackFiles}from"./hooks/toolkit.js";export{detectUpdates,detectSkillUpdates,detectFileAssetUpdates,detectProjectUpdateCounts}from"./install/updates.js";export{detectPluginTemplateUpdates}from"./install/plugin-templates.js";export{readProjectFile,resolveProjectFile,PathEscapeError,FileTooLargeError}from"./install/reader.js";export{readGlobalClaudeJson,readGlobalMcpServers,writeGlobalMcpServer,removeGlobalMcpServer,readGlobalSkills,installGlobalSkill,uninstallGlobalSkill,ClaudeJsonCorruptError,globalPersonalSkillRoots,resolveGlobalSkillDir,listGlobalSkillFiles,readGlobalSkillFile}from"./install/global-config.js";export{readMcpEnableMap,setMcpEnableState}from"./install/settings-mcp.js";export{mcpOverrideOf,resolveMcpEffective,setMcpEnableOverride}from"./install/settings-mcp.js";export{readMcpRows}from"./install/mcp-rows.js";export{readPluginRows}from"./install/plugin-rows.js";export{installPluginPack}from"./install/plugin-install.js";export{readProjectConfig,writeProjectConfig,markSynced,DEFAULT_PROJECT_CONFIG}from"./install/project-config.js";export{applyUpdate,syncAll,refreshStatusline}from"./install/apply-update.js";export{DEFAULT_STATUSLINE_CONFIG,POWERLINE_DEFAULT_GLYPHS,SEGMENT_ORDER,LEGACY_IDENTITY_LINE,LEGACY_METRICS_LINE,NAMED_COLORS,SEGMENT_TOKENS,SEGMENT_DEFAULT_FORMAT,CONTEXT_STYLE_FORMAT,PLAIN_STATUSLINE_CONFIG}from"./statusline/config.js";export{WEAVE_VERSION}from"./version.js";export{generateStatuslineScript,statuslineCacheDir}from"./statusline/generator.js";export{StatuslineCacheSweeper,startStatuslineCacheSweeper}from"./statusline/cache-sweeper.js";export{readStatuslineConfig,writeStatuslineConfig,readGlobalStatuslineConfig,writeGlobalStatuslineConfig,applyStatuslineConfig,ensureSettingsStatusLine,readStatuslineScript}from"./statusline/manager.js";export function resolveDaemonEntry(){const e=r(new URL("./daemon/entry.js",import.meta.url));return o(e)?{path:e,isTs:!1}:{path:r(new URL("./daemon/entry.ts",import.meta.url)),isTs:!0}}export{installPlugin,uninstallPlugin,exportPlugin,searchPlugins,globalPluginRoot,isGitSource}from"./hooks/plugin-installer.js";
1
+ import{existsSync as o}from"node:fs";import{fileURLToPath as r}from"node:url";export{openDatabase}from"./db/db.js";export{getDataDir,getDbPath,getDaemonStatePath,getAuthPath,getInitialPasswordPath,getVisualizationsDir}from"./db/paths.js";export{ensureDataLayout,migrateDataLayout}from"./db/layout.js";export{ProjectRepository}from"./repositories/projects.js";export{HookEventRepository}from"./repositories/hook-events.js";export{SessionRepository}from"./repositories/sessions.js";export{LibraryRepository}from"./repositories/libraries.js";export{DEFAULT_PORT,DAEMON_HOST,isPortFree,findFreePort}from"./daemon/port.js";export{readDaemonState,writeDaemonState,clearDaemonState}from"./daemon/state.js";export{generateToken}from"./daemon/auth.js";export{createWeaveServer,weaveRequestHandler,DAEMON_VERSION}from"./daemon/server.js";export{accessUrls,lanIps,ensureDaemonCert,startTlsServer,daemonCertsDir}from"./daemon/tls.js";export{readDaemonSettings,writeDaemonSettings,terminalPresetsFor,resolveLocale,DEFAULT_DAEMON_SETTINGS,SUPPORTED_LOCALES,DEFAULT_LOCALE}from"./daemon/settings.js";export{resolveTerminalLaunch,resolveExplorerLaunch,openInExplorer,openInTerminal,runInTerminal,defaultProjectOpener}from"./daemon/opener.js";export{resolveStaticDir}from"./daemon/static.js";export{startDaemon}from"./daemon/start.js";export{registerProject,unregisterProject}from"./registry.js";export{probeBinVersion}from"./daemon/project-harnesses.js";export{classifyAsset,normalizeRelPath}from"./watch/classifier.js";export{WatchCache}from"./watch/cache.js";export{WatchService}from"./watch/watch-service.js";export{SyncScheduler}from"./watch/sync-scheduler.js";export{ClaudeCodeAdapter}from"./hooks/adapter.js";export{drainInboxOnce,handleIngestedRecords}from"./hooks/inbox-worker.js";export{MirrorWriter,hooksRoot,hookShardId,appendOutbox}from"./hooks/mirror.js";export{scanLibrarySkills,scanLibraryMcp,scanLibraryFileAssets}from"./install/scanner.js";export{FILE_ASSET_SPECS,FILE_ASSET_CATEGORIES,fileAssetTargetDir,isFileAssetCategory}from"./install/file-assets.js";export{installSkill,uninstallSkill,installFileAsset,uninstallFileAsset,installMcp,uninstallMcp,InstallConflictError,AssetNotFoundError}from"./install/installer.js";export{readMcpServers,readMcpJson}from"./install/installer.js";export{codexConfigFile,readCodexMcpServers,writeCodexMcpServer,removeCodexMcpServer,codexMcpExists,readCodexMcpFromText,upsertCodexMcpInText,removeCodexMcpFromText,upsertCodexPluginEnabledInText,parseDottedKey,sectionHeaderKey,renderTomlHeader,renderTomlKey,renderTomlString,splitTomlSections,upsertTomlSection,removeTomlSection,parseSectionEntries,CodexTomlCorruptError}from"./install/codex-toml.js";export{buildLibraryIndex,findSkillSource,findFileAssetSource}from"./install/library-index.js";export{hashSkillDir,maxMtimeDir,hashMcpConfig,hashFile,FingerprintCache}from"./install/fingerprint.js";export{projectFileNamespaces,projectPackFiles}from"./hooks/toolkit.js";export{detectUpdates,detectSkillUpdates,detectFileAssetUpdates,detectProjectUpdateCounts}from"./install/updates.js";export{detectPluginTemplateUpdates}from"./install/plugin-templates.js";export{readProjectFile,resolveProjectFile,PathEscapeError,FileTooLargeError}from"./install/reader.js";export{readGlobalClaudeJson,readGlobalMcpServers,writeGlobalMcpServer,removeGlobalMcpServer,readGlobalSkills,installGlobalSkill,uninstallGlobalSkill,ClaudeJsonCorruptError,globalPersonalSkillRoots,resolveGlobalSkillDir,listGlobalSkillFiles,readGlobalSkillFile}from"./install/global-config.js";export{readMcpEnableMap,setMcpEnableState}from"./install/settings-mcp.js";export{mcpOverrideOf,resolveMcpEffective,setMcpEnableOverride}from"./install/settings-mcp.js";export{readMcpRows}from"./install/mcp-rows.js";export{readPluginRows}from"./install/plugin-rows.js";export{installPluginPack}from"./install/plugin-install.js";export{readProjectConfig,writeProjectConfig,markSynced,DEFAULT_PROJECT_CONFIG}from"./install/project-config.js";export{applyUpdate,syncAll,refreshStatusline}from"./install/apply-update.js";export{DEFAULT_STATUSLINE_CONFIG,POWERLINE_DEFAULT_GLYPHS,SEGMENT_ORDER,LEGACY_IDENTITY_LINE,LEGACY_METRICS_LINE,NAMED_COLORS,SEGMENT_TOKENS,SEGMENT_DEFAULT_FORMAT,CONTEXT_STYLE_FORMAT,PLAIN_STATUSLINE_CONFIG}from"./statusline/config.js";export{WEAVE_VERSION}from"./version.js";export{generateStatuslineScript,statuslineCacheDir}from"./statusline/generator.js";export{StatuslineCacheSweeper,startStatuslineCacheSweeper}from"./statusline/cache-sweeper.js";export{readStatuslineConfig,writeStatuslineConfig,readGlobalStatuslineConfig,writeGlobalStatuslineConfig,applyStatuslineConfig,ensureSettingsStatusLine,readStatuslineScript}from"./statusline/manager.js";export function resolveDaemonEntry(){const e=r(new URL("./daemon/entry.js",import.meta.url));return o(e)?{path:e,isTs:!1}:{path:r(new URL("./daemon/entry.ts",import.meta.url)),isTs:!0}}export{installPlugin,uninstallPlugin,exportPlugin,searchPlugins,globalPluginRoot,isGitSource}from"./hooks/plugin-installer.js";
@@ -89,6 +89,12 @@ export declare class HookEventRepository {
89
89
  * `ORDER BY id DESC` 倒序早停:最新对话优先,凑满 limit 即停。
90
90
  */
91
91
  searchConversationTexts(q: string, limit: number): ConversationTextHit[];
92
+ /**
93
+ * 对话正文里含 needle 的全部文本(渲染块引用收集用):事件类型与正文键同
94
+ * searchConversationTexts,但不限条数、不排序——要的是「历史上提到过的每一个
95
+ * 引用」。
96
+ */
97
+ conversationTextsContaining(needle: string): string[];
92
98
  }
93
99
  /** 一条聊天正文命中(全文随行带;命中窗口由路由层截)。 */
94
100
  export interface ConversationTextHit {
@@ -1,9 +1,12 @@
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 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
1
+ import{HARNESS_LIFECYCLE as u}from"@weavecode/core";import{readDaemonSettingsSync as _,DEFAULT_EVENT_RETENTION_DAYS as S}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 n=this.insertEvent.run(e.projectId,e.source,e.eventType,e.sessionId??null,e.payload,e.createdAt??new Date().toISOString());return Number(n.lastInsertRowid)}insertMany(e){this.pruneExpired();const n=[];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());n.push(Number(r.lastInsertRowid))}this.db.exec("COMMIT")}catch(t){throw this.db.exec("ROLLBACK"),t}return n}pruneExpired(){const e=Math.floor(Date.now()/864e5);if(e===this.lastPruneDay)return;this.lastPruneDay=e;const n=_().events?.retentionDays??S,t=new Date((e-n)*864e5).toISOString();this.pruneByCutoff.run(t)}listByProject(e,n=100){return this.db.prepare("SELECT * FROM hook_events WHERE project_id = ? ORDER BY created_at DESC LIMIT ?").all(e,n).map(t=>E(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,n){const t=this.db.prepare("SELECT COUNT(*) AS n FROM hook_events WHERE project_id = ? AND created_at >= ?");let r=0;for(const o of e)r+=Number(t.get(o,n).n);return r}seriesBySecond(e,n){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 o of e)for(const a of t.all(o,n))r.set(a.at,(r.get(a.at)??0)+Number(a.n));return[...r].map(([o,a])=>({at:o,n:a})).sort((o,a)=>o.at<a.at?-1:1)}listByTools(e,n,t,r,o){if(n.length===0)return[];const a=["session_id = ?","event_type IN ('PreToolUse','PostToolUse')",`(${n.map(()=>"payload LIKE ?").join(" OR ")})`],s=[e,...n.map(c=>`%"toolName":"${c}"%`)];return t&&(a.push("payload LIKE ?"),s.push(`%${t}%`)),o!=null&&(a.push("id > ?"),s.push(o)),this.db.prepare(`SELECT * FROM hook_events WHERE ${a.join(" AND ")} ORDER BY id DESC LIMIT ?`).all(...s,r).map(c=>E(c))}listBySession(e,n=300,t,r){const o=["session_id = ?"],a=[e];return t!=null&&(o.push("id < ?"),a.push(t)),r?.length&&(o.push(`event_type IN (${r.map(()=>"?").join(",")})`),a.push(...r)),this.db.prepare(`SELECT * FROM hook_events WHERE ${o.join(" AND ")} ORDER BY id DESC LIMIT ?`).all(...a,n).map(p=>E(p)).reverse()}searchConversationTexts(e,n){const t=new Set;for(const s of Object.values(u)){t.add(s.open);for(const p of s.close)t.add(p)}const r=[...t].map(s=>`'${s}'`).join(","),o=l(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 (${o})
5
+ WHERE event_type IN (${r})
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(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)}}
9
+ LIMIT ?`).all(o,o,n).map(s=>{const p=JSON.parse(String(s.payload)),c=d(p.raw?.prompt)??d(p.raw?.last_assistant_message)??"";return{eventId:Number(s.id),projectId:Number(s.project_id),source:String(s.source),eventType:String(s.event_type),sessionId:s.session_id==null?null:String(s.session_id),at:String(s.created_at),text:c}})}conversationTextsContaining(e){const n=new Set;for(const s of Object.values(u)){n.add(s.open);for(const p of s.close)n.add(p)}const t=[...n].map(s=>`'${s}'`).join(","),r=l(e),o=this.db.prepare(`SELECT payload FROM hook_events
10
+ WHERE event_type IN (${t})
11
+ AND (COALESCE(json_extract(payload, '$.raw.prompt'), '') LIKE '%' || ? || '%' ESCAPE '\\'
12
+ OR COALESCE(json_extract(payload, '$.raw.last_assistant_message'), '') LIKE '%' || ? || '%' ESCAPE '\\')`).all(r,r),a=[];for(const s of o){const p=JSON.parse(String(s.payload)),c=d(p.raw?.prompt)??d(p.raw?.last_assistant_message);c&&a.push(c)}return a}}function l(i){return i.replace(/[\\%_]/g,e=>`\\${e}`)}function d(i){return typeof i=="string"&&i.length>0?i:null}function E(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)}}
@@ -1,7 +1,7 @@
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)
1
+ import{HARNESS_COMPACTION as h,HARNESS_LIFECYCLE as a,HARNESS_TOOL_EVENTS as A,isHarness as p}from"@weavecode/core";import{readDaemonSettingsSync as N,DEFAULT_SESSION_IDLE_DAYS as L}from"../daemon/settings.js";export const PROMPTLESS_GRACE_MS=60*6e4;function C(){return(N().sessions?.idleDays??L)*864e5}function S(i){const e=new Set;for(const n of Object.values(a)){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(a))e.add(t.open);const s=[...e].map(t=>`'${t}'`).join(",");return`${i}.event_type IN (${s}) AND COALESCE(json_extract(${i}.payload, '$.raw.prompt'), '') NOT LIKE '<task-notification>%'`}function R(i){const e=new Set;for(const t of Object.values(A))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,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
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 ${c("e3")}) 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 ${R("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 u=r.harness,l=r.last_ups,E=r.last_close,d=r.last_tool,T=r.last_stop,O=r.last_event_type;return{..._(r),eventCount:Number(r.event_count??0),harness:p(u)?u:null,turnOpen:l!=null&&(E==null||Number(l)>Number(E))||d!=null&&(E==null||Number(d)>Number(E)),lastEventType:O??null,hasRun:l!=null||T!=null,autoDeleteAt:new Date(Date.parse(String(r.last_seen_at))+(l==null?PROMPTLESS_GRACE_MS:C())).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 ${c("e3")}) 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 ${R("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(a).map(n=>n.subagentStop))].map(n=>`'${n}'`).join(","),t=this.db.prepare(`SELECT created_at FROM hook_events
6
6
  WHERE session_id = ? AND event_type NOT IN (${s})
7
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@weavecode/server",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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.7",
25
- "@weavecode/harness": "^0.1.7",
26
- "@weavecode/templates": "^0.1.7",
24
+ "@weavecode/core": "^0.1.8",
25
+ "@weavecode/harness": "^0.1.8",
26
+ "@weavecode/templates": "^0.1.8",
27
27
  "chokidar": "^4.0.0",
28
28
  "selfsigned": "^5.5.0",
29
29
  "smol-toml": "^1.3.0",
@@ -0,0 +1 @@
1
+ import{g as p,r as u,d as a}from"./chunk-2E7WHVMD-C3UFIDyj.js";import{p as f}from"./chunk-JWPE2WC7-CEYXaZDX.js";import{_ as n,l as o}from"./mermaid.core-knGXJfjz.js";import"./main-B_0jS_Gz.js";import{M as c,b as d}from"./cynefin-EF2NZ3EQ-AFHjx2wU.js";import"./modulepreload-polyfill-B5Qt9EMX.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}},F={parser:R,db:a,renderer:u,styles:p};export{F as diagram};