@weavecode/weave 0.1.6 → 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 (435) 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/cli.js +3 -3
  51. package/node_modules/@weavecode/cli/dist/commands/chpass.js +1 -1
  52. package/node_modules/@weavecode/cli/dist/commands/daemon-auth.js +1 -1
  53. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  54. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -2
  55. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  56. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  57. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  58. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  59. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  60. package/node_modules/@weavecode/cli/dist/commands/uninstall.js +1 -1
  61. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +1 -1
  62. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +1 -0
  63. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +2 -2
  64. package/node_modules/@weavecode/cli/dist/i18n/index.js +1 -1
  65. package/node_modules/@weavecode/cli/dist/i18n/t.js +1 -1
  66. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +3 -3
  67. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  68. package/node_modules/@weavecode/cli/dist/init/git-commit.js +2 -2
  69. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  70. package/node_modules/@weavecode/cli/dist/init/harnesses/codex.js +1 -1
  71. package/node_modules/@weavecode/cli/dist/init/instruction-link.js +1 -1
  72. package/node_modules/@weavecode/cli/dist/init/plugin-templates.js +1 -1
  73. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  74. package/node_modules/@weavecode/cli/dist/init/provision.js +1 -1
  75. package/node_modules/@weavecode/cli/dist/init/uninstall.js +6 -6
  76. package/node_modules/@weavecode/cli/dist/init/wiring.js +1 -1
  77. package/node_modules/@weavecode/cli/dist/parser.js +1 -1
  78. package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
  79. package/node_modules/@weavecode/cli/package.json +5 -5
  80. package/node_modules/@weavecode/core/dist/harness-checks.js +1 -1
  81. package/node_modules/@weavecode/core/dist/harness.d.ts +89 -0
  82. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  83. package/node_modules/@weavecode/core/dist/index.d.ts +1 -1
  84. package/node_modules/@weavecode/core/dist/index.js +1 -1
  85. package/node_modules/@weavecode/core/dist/platform.js +1 -1
  86. package/node_modules/@weavecode/core/dist/types.js +1 -1
  87. package/node_modules/@weavecode/core/dist/utils/fs.js +1 -1
  88. package/node_modules/@weavecode/core/dist/utils/logger.js +1 -1
  89. package/node_modules/@weavecode/core/package.json +1 -1
  90. package/node_modules/@weavecode/harness/dist/claude/assets.js +4 -4
  91. package/node_modules/@weavecode/harness/dist/claude/capture.js +9 -9
  92. package/node_modules/@weavecode/harness/dist/claude/commands.d.ts +2 -0
  93. package/node_modules/@weavecode/harness/dist/claude/commands.js +3 -2
  94. package/node_modules/@weavecode/harness/dist/claude/config.js +2 -2
  95. package/node_modules/@weavecode/harness/dist/claude/detect.js +1 -1
  96. package/node_modules/@weavecode/harness/dist/claude/edits.js +1 -1
  97. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  98. package/node_modules/@weavecode/harness/dist/claude/images.js +2 -2
  99. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  100. package/node_modules/@weavecode/harness/dist/claude/liveness.js +1 -1
  101. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -1
  102. package/node_modules/@weavecode/harness/dist/claude/messaging.js +2 -2
  103. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -1
  104. package/node_modules/@weavecode/harness/dist/claude/narration.js +1 -1
  105. package/node_modules/@weavecode/harness/dist/claude/peers.js +1 -1
  106. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -1
  107. package/node_modules/@weavecode/harness/dist/claude/plugins.js +4 -4
  108. package/node_modules/@weavecode/harness/dist/claude/prompt-inbox.js +1 -1
  109. package/node_modules/@weavecode/harness/dist/claude/prompt.js +3 -3
  110. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -2
  111. package/node_modules/@weavecode/harness/dist/claude/resume.js +1 -1
  112. package/node_modules/@weavecode/harness/dist/claude/rewind.js +1 -1
  113. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -1
  114. package/node_modules/@weavecode/harness/dist/claude/side-question.js +2 -2
  115. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +14 -14
  116. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -1
  117. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -2
  118. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.js +2 -2
  119. package/node_modules/@weavecode/harness/dist/claude/transcript.js +7 -7
  120. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  121. package/node_modules/@weavecode/harness/dist/codex/capture.js +2 -2
  122. package/node_modules/@weavecode/harness/dist/codex/commands.js +4 -4
  123. package/node_modules/@weavecode/harness/dist/codex/config.js +2 -2
  124. package/node_modules/@weavecode/harness/dist/codex/detect.js +1 -1
  125. package/node_modules/@weavecode/harness/dist/codex/event-source.js +2 -2
  126. package/node_modules/@weavecode/harness/dist/codex/images.js +1 -1
  127. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  128. package/node_modules/@weavecode/harness/dist/codex/liveness.js +1 -1
  129. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -1
  130. package/node_modules/@weavecode/harness/dist/codex/messaging.js +2 -2
  131. package/node_modules/@weavecode/harness/dist/codex/narration.js +1 -1
  132. package/node_modules/@weavecode/harness/dist/codex/plugin-state.js +1 -1
  133. package/node_modules/@weavecode/harness/dist/codex/plugins.js +3 -3
  134. package/node_modules/@weavecode/harness/dist/codex/provision.js +1 -1
  135. package/node_modules/@weavecode/harness/dist/codex/questions.js +2 -2
  136. package/node_modules/@weavecode/harness/dist/codex/rollout.js +5 -5
  137. package/node_modules/@weavecode/harness/dist/codex/side-question.js +4 -4
  138. package/node_modules/@weavecode/harness/dist/codex/titles.js +4 -4
  139. package/node_modules/@weavecode/harness/dist/codex/toml.js +13 -13
  140. package/node_modules/@weavecode/harness/dist/codex/transcript.js +2 -2
  141. package/node_modules/@weavecode/harness/dist/driver.d.ts +13 -0
  142. package/node_modules/@weavecode/harness/dist/driver.js +1 -1
  143. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -2
  144. package/node_modules/@weavecode/harness/dist/init/pipeline.js +1 -1
  145. package/node_modules/@weavecode/harness/dist/registry-wiring.js +1 -1
  146. package/node_modules/@weavecode/harness/dist/shared/install-link.js +1 -1
  147. package/node_modules/@weavecode/harness/dist/shared/json-cap.js +1 -1
  148. package/node_modules/@weavecode/harness/package.json +2 -2
  149. package/node_modules/@weavecode/server/dist/config/dotted.js +1 -1
  150. package/node_modules/@weavecode/server/dist/config/profiles.js +2 -2
  151. package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
  152. package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
  153. package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
  154. package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -3
  155. package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
  156. package/node_modules/@weavecode/server/dist/daemon/auto-start.js +6 -6
  157. package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
  158. package/node_modules/@weavecode/server/dist/daemon/config-routes.js +1 -1
  159. package/node_modules/@weavecode/server/dist/daemon/cron.js +1 -1
  160. package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
  161. package/node_modules/@weavecode/server/dist/daemon/dashboard-pusher.js +1 -1
  162. package/node_modules/@weavecode/server/dist/daemon/data-bus.js +1 -1
  163. package/node_modules/@weavecode/server/dist/daemon/decision-config.js +2 -2
  164. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  165. package/node_modules/@weavecode/server/dist/daemon/entry.js +2 -2
  166. package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
  167. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
  168. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  169. package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
  170. package/node_modules/@weavecode/server/dist/daemon/liveness.js +1 -1
  171. package/node_modules/@weavecode/server/dist/daemon/mcp-orchestration.js +1 -1
  172. package/node_modules/@weavecode/server/dist/daemon/narration-watcher.js +2 -2
  173. package/node_modules/@weavecode/server/dist/daemon/opener/backend-ghostty.js +1 -1
  174. package/node_modules/@weavecode/server/dist/daemon/opener/backend-iterm.js +1 -1
  175. package/node_modules/@weavecode/server/dist/daemon/opener/backend-konsole.js +2 -2
  176. package/node_modules/@weavecode/server/dist/daemon/opener/backend-terminal-app.js +1 -1
  177. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wezterm.js +1 -1
  178. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wt.js +1 -1
  179. package/node_modules/@weavecode/server/dist/daemon/opener/backend.js +1 -1
  180. package/node_modules/@weavecode/server/dist/daemon/opener/pty-terminals.js +4 -4
  181. package/node_modules/@weavecode/server/dist/daemon/opener/shared.js +1 -1
  182. package/node_modules/@weavecode/server/dist/daemon/opener/wezterm-mux.js +1 -1
  183. package/node_modules/@weavecode/server/dist/daemon/opener/wt.js +3 -3
  184. package/node_modules/@weavecode/server/dist/daemon/opener.js +1 -1
  185. package/node_modules/@weavecode/server/dist/daemon/pet-seed.d.ts +6 -0
  186. package/node_modules/@weavecode/server/dist/daemon/pet-seed.js +1 -0
  187. package/node_modules/@weavecode/server/dist/daemon/pet-window.d.ts +17 -0
  188. package/node_modules/@weavecode/server/dist/daemon/pet-window.js +2 -0
  189. package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
  190. package/node_modules/@weavecode/server/dist/daemon/project-files.d.ts +1 -1
  191. package/node_modules/@weavecode/server/dist/daemon/project-files.js +2 -2
  192. package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
  193. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
  194. package/node_modules/@weavecode/server/dist/daemon/prompt-images.js +1 -1
  195. package/node_modules/@weavecode/server/dist/daemon/routes/hooks-admin.js +1 -1
  196. package/node_modules/@weavecode/server/dist/daemon/routes/market.js +1 -1
  197. package/node_modules/@weavecode/server/dist/daemon/routes/orchestration.js +1 -1
  198. package/node_modules/@weavecode/server/dist/daemon/routes/path-refs.js +1 -1
  199. package/node_modules/@weavecode/server/dist/daemon/routes/pets.d.ts +3 -0
  200. package/node_modules/@weavecode/server/dist/daemon/routes/pets.js +1 -0
  201. package/node_modules/@weavecode/server/dist/daemon/routes/project-files.js +1 -1
  202. package/node_modules/@weavecode/server/dist/daemon/routes/projects.js +1 -1
  203. package/node_modules/@weavecode/server/dist/daemon/routes/search.js +1 -1
  204. package/node_modules/@weavecode/server/dist/daemon/routes/session-control.js +1 -1
  205. package/node_modules/@weavecode/server/dist/daemon/routes/session-insights.js +1 -1
  206. package/node_modules/@weavecode/server/dist/daemon/routes/settings-statusline.js +1 -1
  207. package/node_modules/@weavecode/server/dist/daemon/routes/uploads.js +1 -1
  208. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.js +2 -1
  209. package/node_modules/@weavecode/server/dist/daemon/routes/watches.js +1 -1
  210. package/node_modules/@weavecode/server/dist/daemon/server.d.ts +2 -0
  211. package/node_modules/@weavecode/server/dist/daemon/server.js +8 -8
  212. package/node_modules/@weavecode/server/dist/daemon/session-open.d.ts +17 -0
  213. package/node_modules/@weavecode/server/dist/daemon/session-open.js +1 -1
  214. package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
  215. package/node_modules/@weavecode/server/dist/daemon/settings.d.ts +21 -0
  216. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  217. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.js +1 -1
  218. package/node_modules/@weavecode/server/dist/daemon/sse-hub.js +1 -1
  219. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  220. package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
  221. package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
  222. package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.js +1 -1
  223. package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
  224. package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
  225. package/node_modules/@weavecode/server/dist/daemon/upload-sessions.js +1 -1
  226. package/node_modules/@weavecode/server/dist/db/db.d.ts +4 -1
  227. package/node_modules/@weavecode/server/dist/db/db.js +2 -2
  228. package/node_modules/@weavecode/server/dist/db/layout.js +1 -1
  229. package/node_modules/@weavecode/server/dist/db/paths.d.ts +4 -0
  230. package/node_modules/@weavecode/server/dist/db/paths.js +1 -1
  231. package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
  232. package/node_modules/@weavecode/server/dist/hooks/bus.js +1 -1
  233. package/node_modules/@weavecode/server/dist/hooks/dashboard-rate.js +1 -1
  234. package/node_modules/@weavecode/server/dist/hooks/decision-judge.js +1 -1
  235. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.js +1 -1
  236. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.js +1 -1
  237. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.js +1 -1
  238. package/node_modules/@weavecode/server/dist/hooks/delivery/queue.js +1 -1
  239. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.js +1 -1
  240. package/node_modules/@weavecode/server/dist/hooks/delivery/send.js +2 -2
  241. package/node_modules/@weavecode/server/dist/hooks/delivery/views.d.ts +3 -1
  242. package/node_modules/@weavecode/server/dist/hooks/delivery/views.js +1 -1
  243. package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
  244. package/node_modules/@weavecode/server/dist/hooks/edge-extract.js +1 -1
  245. package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
  246. package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
  247. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -2
  248. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
  249. package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
  250. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +5 -5
  251. package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
  252. package/node_modules/@weavecode/server/dist/hooks/orchestration-engine.js +7 -7
  253. package/node_modules/@weavecode/server/dist/hooks/orchestration-graph.js +1 -1
  254. package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
  255. package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
  256. package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
  257. package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
  258. package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
  259. package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
  260. package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
  261. package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
  262. package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
  263. package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
  264. package/node_modules/@weavecode/server/dist/hooks/side-questions.js +1 -1
  265. package/node_modules/@weavecode/server/dist/hooks/synthetic-sessions.js +1 -1
  266. package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
  267. package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
  268. package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
  269. package/node_modules/@weavecode/server/dist/index.d.ts +1 -1
  270. package/node_modules/@weavecode/server/dist/index.js +1 -1
  271. package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
  272. package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
  273. package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
  274. package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
  275. package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
  276. package/node_modules/@weavecode/server/dist/install/global-config.js +1 -1
  277. package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
  278. package/node_modules/@weavecode/server/dist/install/init-files.js +2 -2
  279. package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
  280. package/node_modules/@weavecode/server/dist/install/installer.js +1 -1
  281. package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
  282. package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
  283. package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
  284. package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
  285. package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
  286. package/node_modules/@weavecode/server/dist/install/project-config.js +1 -1
  287. package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
  288. package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
  289. package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
  290. package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
  291. package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
  292. package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
  293. package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
  294. package/node_modules/@weavecode/server/dist/market/import.js +2 -2
  295. package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
  296. package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
  297. package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
  298. package/node_modules/@weavecode/server/dist/registry.js +2 -2
  299. package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +5 -5
  300. package/node_modules/@weavecode/server/dist/repositories/hook-events.d.ts +6 -0
  301. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +8 -5
  302. package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
  303. package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
  304. package/node_modules/@weavecode/server/dist/repositories/orchestrations.js +7 -7
  305. package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
  306. package/node_modules/@weavecode/server/dist/repositories/projects.js +2 -2
  307. package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
  308. package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
  309. package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
  310. package/node_modules/@weavecode/server/dist/repositories/uploads.js +11 -11
  311. package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
  312. package/node_modules/@weavecode/server/dist/statusline/generator.js +1 -1
  313. package/node_modules/@weavecode/server/dist/statusline/manager.js +3 -3
  314. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  315. package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
  316. package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
  317. package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
  318. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
  319. package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
  320. package/node_modules/@weavecode/server/package.json +4 -4
  321. package/node_modules/@weavecode/server/web/dist/assets/abnfDiagram-WEYOIA3C-t5OQjhuS.js +1 -0
  322. package/node_modules/@weavecode/server/web/dist/assets/{arc-DH8-rYAa.js → arc-De-uH_Q9.js} +1 -1
  323. package/node_modules/@weavecode/server/web/dist/assets/architectureDiagram-ZHVYKT53-ImPclD43.js +36 -0
  324. package/node_modules/@weavecode/server/web/dist/assets/{blockDiagram-RJAE7QA3-pT5eO-cB.js → blockDiagram-RJAE7QA3-B5xEQs6X.js} +2 -2
  325. package/node_modules/@weavecode/server/web/dist/assets/{c4Diagram-XDPPPE54-DHDBDMb1.js → c4Diagram-XDPPPE54-DP8MjIgJ.js} +2 -2
  326. package/node_modules/@weavecode/server/web/dist/assets/channel-C0RGiobt.js +1 -0
  327. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2E7WHVMD-CT951PH5.js → chunk-2E7WHVMD-C3UFIDyj.js} +1 -1
  328. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2Q5K7J3B-E5AD7_ZY.js → chunk-2Q5K7J3B-Bgw-3YfG.js} +1 -1
  329. package/node_modules/@weavecode/server/web/dist/assets/{chunk-4EMNKR2T-DWz9qkcy.js → chunk-4EMNKR2T-Dy_Wq9qn.js} +1 -1
  330. package/node_modules/@weavecode/server/web/dist/assets/chunk-55XCU76K-D32C0DXX.js +1 -0
  331. package/node_modules/@weavecode/server/web/dist/assets/{chunk-5VM5RSS4-ci6YzbO5.js → chunk-5VM5RSS4-Dpmi-9Gi.js} +1 -1
  332. package/node_modules/@weavecode/server/web/dist/assets/{chunk-JWPE2WC7-CY4mr2f4.js → chunk-JWPE2WC7-CEYXaZDX.js} +1 -1
  333. package/node_modules/@weavecode/server/web/dist/assets/{chunk-VQ5W62QI-CON8zyg8.js → chunk-VQ5W62QI-A616Pgzo.js} +1 -1
  334. package/node_modules/@weavecode/server/web/dist/assets/chunk-XXDRQBXY-CnxFMLWV.js +1 -0
  335. package/node_modules/@weavecode/server/web/dist/assets/chunk-ZCHMQSOR-BhjCTig8.js +2 -0
  336. package/node_modules/@weavecode/server/web/dist/assets/{classDiagram-v2-4MYWR3UA-GiWZ9xtF.js → classDiagram-v2-4MYWR3UA-rzlq5tPv.js} +2 -2
  337. package/node_modules/@weavecode/server/web/dist/assets/cose-bilkent-JH36ORCC-CxWQXzj8.js +1 -0
  338. package/node_modules/@weavecode/server/web/dist/assets/{cynefin-EF2NZ3EQ-9B__MaRM.js → cynefin-EF2NZ3EQ-AFHjx2wU.js} +1 -1
  339. package/node_modules/@weavecode/server/web/dist/assets/cynefinDiagram-WF24UDRP-Bp_Oaf9U.js +62 -0
  340. package/node_modules/@weavecode/server/web/dist/assets/dagre-NK4GIZVX-7oUPIU35.js +4 -0
  341. package/node_modules/@weavecode/server/web/dist/assets/diagram-CBK3MWTC-D_rS_rSY.js +24 -0
  342. package/node_modules/@weavecode/server/web/dist/assets/diagram-I5XIIV2D-Duc_cKMb.js +24 -0
  343. package/node_modules/@weavecode/server/web/dist/assets/{diagram-ODIL2UCW-CckywF4W.js → diagram-ODIL2UCW-DA0XFVXm.js} +2 -2
  344. package/node_modules/@weavecode/server/web/dist/assets/{diagram-PFBEJUXE-Dpjlc7Wh.js → diagram-PFBEJUXE-D1U0Xhtt.js} +2 -2
  345. package/node_modules/@weavecode/server/web/dist/assets/diagram-RJA3I4VV-CbDFY871.js +41 -0
  346. package/node_modules/@weavecode/server/web/dist/assets/{diagram-TYUNFSNR-DgRJ3zL1.js → diagram-TYUNFSNR-jPg9AxQv.js} +2 -2
  347. package/node_modules/@weavecode/server/web/dist/assets/ebnfDiagram-V4P3TTPT-ZHfGTB0N.js +1 -0
  348. package/node_modules/@weavecode/server/web/dist/assets/{elk-QONTBCTQ-Ch6Gs9G9.js → elk-QONTBCTQ-C-ESJrUi.js} +3 -3
  349. package/node_modules/@weavecode/server/web/dist/assets/{erDiagram-KYQIGQAA-COxT-Pxb.js → erDiagram-KYQIGQAA-DGK7TeHj.js} +2 -2
  350. package/node_modules/@weavecode/server/web/dist/assets/{flowDiagram-IUGLLWBU-CJVWnTBa.js → flowDiagram-IUGLLWBU-CVV4rL8v.js} +1 -1
  351. package/node_modules/@weavecode/server/web/dist/assets/ganttDiagram-R7GPNTJY-CuAwNvbm.js +292 -0
  352. package/node_modules/@weavecode/server/web/dist/assets/gitGraphDiagram-PDYL7XHY-D_15Wtf-.js +106 -0
  353. package/node_modules/@weavecode/server/web/dist/assets/infoDiagram-MVDRKAX5-ClqhbrCa.js +2 -0
  354. package/node_modules/@weavecode/server/web/dist/assets/{ishikawaDiagram-HPEHV2GE-BNjEDIZy.js → ishikawaDiagram-HPEHV2GE-CUJ891JX.js} +2 -2
  355. package/node_modules/@weavecode/server/web/dist/assets/{journeyDiagram-BOSHW7O7-Cao6h91a.js → journeyDiagram-BOSHW7O7-B4skiMu-.js} +2 -2
  356. package/node_modules/@weavecode/server/web/dist/assets/{kanban-definition-FNSA4HC5-CXIx2CHQ.js → kanban-definition-FNSA4HC5-UNGJR_y_.js} +2 -2
  357. package/node_modules/@weavecode/server/web/dist/assets/linear-BEB-UwbR.js +1 -0
  358. package/node_modules/@weavecode/server/web/dist/assets/main-B_0jS_Gz.js +1096 -0
  359. package/node_modules/@weavecode/server/web/dist/assets/main-Czzlavi4.css +11 -0
  360. package/node_modules/@weavecode/server/web/dist/assets/{mermaid.core-D39fi_iR.js → mermaid.core-knGXJfjz.js} +4 -4
  361. package/node_modules/@weavecode/server/web/dist/assets/{mindmap-definition-6OY57UG3-DHqpz_AK.js → mindmap-definition-6OY57UG3-CEldbr3a.js} +2 -2
  362. package/node_modules/@weavecode/server/web/dist/assets/modulepreload-polyfill-B5Qt9EMX.js +1 -0
  363. package/node_modules/@weavecode/server/web/dist/assets/pegDiagram-ECIUJNBX-cNCkGLx3.js +1 -0
  364. package/node_modules/@weavecode/server/web/dist/assets/pet-DJCpIDM5.js +1 -0
  365. package/node_modules/@weavecode/server/web/dist/assets/pieDiagram-GNMPY74T-CfMEFiQD.js +39 -0
  366. package/node_modules/@weavecode/server/web/dist/assets/{quadrantDiagram-D57K4MC3-zSM6o7mB.js → quadrantDiagram-D57K4MC3-knmi2rwP.js} +4 -4
  367. package/node_modules/@weavecode/server/web/dist/assets/railroadDiagram-Y72NRBL7-BJ7AzhEo.js +1 -0
  368. package/node_modules/@weavecode/server/web/dist/assets/{requirementDiagram-EQYSW5RA-CbCLBjHf.js → requirementDiagram-EQYSW5RA-Dte2LGQM.js} +2 -2
  369. package/node_modules/@weavecode/server/web/dist/assets/{sankeyDiagram-SY24JHO5-BucVk6EP.js → sankeyDiagram-SY24JHO5-3noLaWgd.js} +2 -2
  370. package/node_modules/@weavecode/server/web/dist/assets/{sequenceDiagram-BLEHNHQU-Dg8CYEnT.js → sequenceDiagram-BLEHNHQU-CclOWTTc.js} +2 -2
  371. package/node_modules/@weavecode/server/web/dist/assets/sizeCapture-INFHLROL-B82sbLhA.js +1 -0
  372. package/node_modules/@weavecode/server/web/dist/assets/{stateDiagram-v2-A6IESKWZ-BvK2l3is.js → stateDiagram-v2-A6IESKWZ-BXfVDwSN.js} +2 -2
  373. package/node_modules/@weavecode/server/web/dist/assets/swimlanes-B3ENRKFQ-D4lKZaeV.js +1 -0
  374. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-DbdFh_d6.js +8 -0
  375. package/node_modules/@weavecode/server/web/dist/assets/{timeline-definition-JXYKGLGB-CadU4Qq4.js → timeline-definition-JXYKGLGB-D6H6zP5b.js} +2 -2
  376. package/node_modules/@weavecode/server/web/dist/assets/{usecaseDiagram-WPOLBNNX-BYuZwTDZ.js → usecaseDiagram-WPOLBNNX-D2J2bKo_.js} +2 -2
  377. package/node_modules/@weavecode/server/web/dist/assets/{vennDiagram-Q3Y3IDCW-C7zgxe07.js → vennDiagram-Q3Y3IDCW-pdRbIkpB.js} +2 -2
  378. package/node_modules/@weavecode/server/web/dist/assets/{wardleyDiagram-IVAIDKWA-DA4Otf4s.js → wardleyDiagram-IVAIDKWA-Cyd2QPMf.js} +2 -2
  379. package/node_modules/@weavecode/server/web/dist/assets/{xychartDiagram-4URNHDU4-Bs5YGwMU.js → xychartDiagram-4URNHDU4-Bd4BkwVM.js} +2 -2
  380. package/node_modules/@weavecode/server/web/dist/icons/apple-touch-icon.png +0 -0
  381. package/node_modules/@weavecode/server/web/dist/icons/icon-192.png +0 -0
  382. package/node_modules/@weavecode/server/web/dist/icons/icon-512.png +0 -0
  383. package/node_modules/@weavecode/server/web/dist/icons/icon-maskable-512.png +0 -0
  384. package/node_modules/@weavecode/server/web/dist/index.html +12 -2
  385. package/node_modules/@weavecode/server/web/dist/manifest.webmanifest +16 -0
  386. package/node_modules/@weavecode/server/web/dist/pet.html +60 -0
  387. package/node_modules/@weavecode/templates/dist/index.d.ts +2 -0
  388. package/node_modules/@weavecode/templates/dist/index.js +1 -1
  389. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/pet.json +7 -0
  390. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/spritesheet.png +0 -0
  391. package/node_modules/@weavecode/templates/dist/resources/weave-market/.claude-plugin/marketplace.json +6 -0
  392. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/.claude-plugin/plugin.json +8 -0
  393. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/skills/weave-pet-hatcher/SKILL.md +121 -0
  394. 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
  395. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/weave.json +4 -0
  396. package/node_modules/@weavecode/templates/package.json +2 -2
  397. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/README.md +3 -8
  398. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/package.json +1 -1
  399. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.d.ts +4 -2
  400. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.es6.js +10 -1
  401. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.es6.mjs +10 -1
  402. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/tslib/tslib.js +10 -1
  403. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/README.md +3 -8
  404. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/package.json +1 -1
  405. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.d.ts +4 -2
  406. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.es6.js +10 -1
  407. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.es6.mjs +10 -1
  408. package/node_modules/selfsigned/node_modules/pkijs/node_modules/tslib/tslib.js +10 -1
  409. package/package.json +11 -7
  410. package/scripts/preinstall.mjs +70 -0
  411. package/node_modules/@weavecode/server/web/dist/assets/abnfDiagram-WEYOIA3C-CbIFQh0R.js +0 -1
  412. package/node_modules/@weavecode/server/web/dist/assets/architectureDiagram-ZHVYKT53-qnv6S0sc.js +0 -36
  413. package/node_modules/@weavecode/server/web/dist/assets/channel-BHPeeuzN.js +0 -1
  414. package/node_modules/@weavecode/server/web/dist/assets/chunk-55XCU76K-D-SgWD8w.js +0 -1
  415. package/node_modules/@weavecode/server/web/dist/assets/chunk-XXDRQBXY-DXXXZ4pW.js +0 -1
  416. package/node_modules/@weavecode/server/web/dist/assets/chunk-ZCHMQSOR-CukvPvkM.js +0 -2
  417. package/node_modules/@weavecode/server/web/dist/assets/cose-bilkent-JH36ORCC-D7aJ-akq.js +0 -1
  418. package/node_modules/@weavecode/server/web/dist/assets/cynefinDiagram-WF24UDRP-B2ujZh2k.js +0 -62
  419. package/node_modules/@weavecode/server/web/dist/assets/dagre-NK4GIZVX-nHaB6IWf.js +0 -4
  420. package/node_modules/@weavecode/server/web/dist/assets/diagram-CBK3MWTC-xKfjDvgr.js +0 -24
  421. package/node_modules/@weavecode/server/web/dist/assets/diagram-I5XIIV2D-BHT2-5mY.js +0 -24
  422. package/node_modules/@weavecode/server/web/dist/assets/diagram-RJA3I4VV-M6WznOaW.js +0 -41
  423. package/node_modules/@weavecode/server/web/dist/assets/ebnfDiagram-V4P3TTPT-BzzVN__a.js +0 -1
  424. package/node_modules/@weavecode/server/web/dist/assets/ganttDiagram-R7GPNTJY-BkRpWPUl.js +0 -292
  425. package/node_modules/@weavecode/server/web/dist/assets/gitGraphDiagram-PDYL7XHY-Ba8BJcvZ.js +0 -106
  426. package/node_modules/@weavecode/server/web/dist/assets/index-CtifxEiF.css +0 -11
  427. package/node_modules/@weavecode/server/web/dist/assets/index-FwH9INgS.js +0 -1090
  428. package/node_modules/@weavecode/server/web/dist/assets/infoDiagram-MVDRKAX5-HTQ5FUNK.js +0 -2
  429. package/node_modules/@weavecode/server/web/dist/assets/linear-65WmlvQb.js +0 -1
  430. package/node_modules/@weavecode/server/web/dist/assets/pegDiagram-ECIUJNBX-Cpy1nsER.js +0 -1
  431. package/node_modules/@weavecode/server/web/dist/assets/pieDiagram-GNMPY74T-B1IyNqzr.js +0 -39
  432. package/node_modules/@weavecode/server/web/dist/assets/railroadDiagram-Y72NRBL7-oM4XJIwA.js +0 -1
  433. package/node_modules/@weavecode/server/web/dist/assets/sizeCapture-INFHLROL-C51zb7Oc.js +0 -1
  434. package/node_modules/@weavecode/server/web/dist/assets/swimlanes-B3ENRKFQ-Ds7QOfXW.js +0 -1
  435. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-ByBF02UJ.js +0 -8
@@ -1 +1 @@
1
- import{readFileSync as M}from"node:fs";import F from"node:path";import{isHarness as O}from"@weavecode/core";import{sendJson as i}from"../http.js";import{blockingPromptFor as U,commandsSurfaceFor as $,editSurfaceFor as D,narrationSurfaceFor as J,rewindSurfaceFor as Q}from"../../surfaces.js";function w(s,n,t){if(!n.hookSessions||!n.hookEvents)return i(s,503,{error:"Hooks subsystem unavailable"}),null;const o=n.hookSessions.getBySessionId(t);return o?o.projectId==null?(i(s,400,{error:"Session is not bound to a project"}),null):n.projects.getById(o.projectId)||(i(s,404,{error:"Project not found"}),null):(i(s,404,{error:"Session not found"}),null)}function I(s,n){if(!s.hookEvents)return null;const t=s.hookEvents.listBySession(n,1),o=t[t.length-1]?.source;return O(o)?o:null}const B=20,z=2e3,W=200,x=new Map,q=2e5;function K(s){try{const n=JSON.parse(s);return[typeof n.toolName=="string"?n.toolName:null,n.toolInput??null,n.toolResponse??null]}catch{return[null,null,null]}}function N(s){if(!s)return null;try{const n=M(s,"utf8");return n.trim()?n:null}catch{return null}}const H=2e5,L=4e6;function V(s,n){const t=F.relative(n,s);return(t&&!t.startsWith("..")&&!F.isAbsolute(t)?t:s).split(F.sep).join("/")}function A(s){if(!s)return null;const n=Date.parse(s);return Number.isFinite(n)?n:null}function X(s,n,t){if(n===null&&t===null)return!0;if(!s)return!1;const o=Date.parse(s);return!(!Number.isFinite(o)||n!==null&&o<=n||t!==null&&o>t)}function Y(s,n){const t=[],o=new Map;let f=L,P=0,d=!1;for(const a of s){const p=a.hunk.before.slice(0,H),h=a.hunk.after.slice(0,H),b=p.length<a.hunk.before.length||h.length<a.hunk.after.length;b&&(d=!0);const E=p.length+h.length;if(E>f){d=!0;continue}f-=E;const e=V(a.path,n);let r=o.get(e);r||(r={path:e,hunks:[]},o.set(e,r),t.push(r)),r.hunks.push({before:p,after:h,at:a.at,...b?{clamped:!0}:{}}),P++}return{files:t,hunks:P,truncated:d}}export async function handleSessionInsightRoutes(s,n,t,o,f){const P=o.match(/^\/sessions\/([^/]+)\/plan$/);if(P&&s.method==="GET"){const e=decodeURIComponent(P[1]);if(!t.hookEvents)return i(n,503,{error:"Hook ingestion unavailable"}),!0;const r=t.hookEvents.listBySession(e,1),u=r[r.length-1]?.source,l=O(u)?U(u)?.plan??null:null;if(!l)return i(n,200,{plan:null}),!0;const m=c=>c.flatMap(v=>{const R=l.draftOf(...K(v.payload));return R?[{row:v,draft:R}]:[]}),g=r[r.length-1]?.id??0,S=t.hookEvents,y=x.get(e);if(y&&y.latestId===g)return i(n,200,{plan:y.plan}),!0;const T=c=>(x.size>=W&&x.clear(),x.set(e,{latestId:g,plan:c}),i(n,200,{plan:c}),!0),j=(c,v)=>{const R=S.listByTools(e,c,v,B,g-z);return R.length>0?R:S.listByTools(e,c,v,B)},[k]=m(j([l.tool],null));if(!k)return T(null);const[C]=m(j(l.writeTools,l.fileHint)).filter(c=>c.row.id<k.row.id),G=k.draft.text??N(k.draft.filePath)??C?.draft.text??N(C?.draft.filePath??null);return T(G?{eventId:k.row.id,at:k.row.createdAt,text:G.slice(0,q)}:null)}const d=o.match(/^\/sessions\/([^/]+)\/pre-question$/);if(d&&s.method==="GET"){const e=decodeURIComponent(d[1]);if(!w(n,t,e))return!0;const r=I(t,e),u=await(r?U(r):null)?.preQuestion?.(t.sessionProbe?.transcriptPathOf(e)??null);return i(n,200,{preQuestion:u??null}),!0}const a=o.match(/^\/sessions\/([^/]+)\/narration$/);if(a&&s.method==="GET"){const e=decodeURIComponent(a[1]);if(!w(n,t,e))return!0;const r=I(t,e),u=r?J(r):null;if(!u)return i(n,200,{supported:!1,narration:null}),!0;const l=await u.sessionNarration({sessionId:e,transcriptPath:t.sessionProbe?.transcriptPathOf(e)??null});return i(n,200,{supported:l!==null,narration:l}),!0}const p=o.match(/^\/sessions\/([^/]+)\/rewinds$/);if(p&&s.method==="GET"){const e=decodeURIComponent(p[1]);if(!w(n,t,e))return!0;const r=I(t,e),u=r?Q(r):null;if(!u)return i(n,200,{supported:!1,rewinds:null}),!0;const l=await u.sessionRewinds({sessionId:e,transcriptPath:t.sessionProbe?.transcriptPathOf(e)??null});return i(n,200,{supported:l!==null,rewinds:l}),!0}const h=o.match(/^\/sessions\/([^/]+)\/commands$/);if(h&&s.method==="GET"){const e=decodeURIComponent(h[1]),r=w(n,t,e);if(!r)return!0;const u=I(t,e),l=u?$(u):null;return l?(i(n,200,{supported:!0,commands:await l.list({projectPath:r.path}),inputModes:l.inputModes}),!0):(i(n,200,{supported:!1,commands:[],inputModes:[]}),!0)}const b=o.match(/^\/sessions\/([^/]+)\/command-executions$/);if(b&&s.method==="GET"){const e=decodeURIComponent(b[1]);if(!w(n,t,e))return!0;const r=I(t,e),u=r?$(r):null;if(!u)return i(n,200,{supported:!1,executions:null}),!0;const l=await u.executions(t.sessionProbe?.transcriptPathOf(e)??null);return i(n,200,{supported:l!==null,executions:l}),!0}const E=o.match(/^\/sessions\/([^/]+)\/edits$/);if(E&&s.method==="GET"){const e=decodeURIComponent(E[1]),r=w(n,t,e);if(!r)return!0;const u=I(t,e),l=u?D(u):null;if(!l)return i(n,200,{files:null,hunks:0,truncated:!1,reason:"unsupported"}),!0;const m=await l.sessionEdits({sessionId:e,transcriptPath:t.sessionProbe?.transcriptPathOf(e)??null});if(!m)return i(n,200,{files:null,hunks:0,truncated:!1,reason:"unreadable"}),!0;const g=A(f.searchParams.get("since")),S=A(f.searchParams.get("until")),y=g!==null||S!==null?m.filter(T=>X(T.at,g,S)):m;return i(n,200,Y(y,r.path)),!0}return!1}
1
+ import{readFileSync as U}from"node:fs";import T from"node:path";import{isHarness as j}from"@weavecode/core";import{sendJson as c}from"../http.js";import{blockingPromptFor as v,commandsSurfaceFor as x,editSurfaceFor as $,narrationSurfaceFor as D,rewindSurfaceFor as L}from"../../surfaces.js";function g(o,t,n){if(!t.hookSessions||!t.hookEvents)return c(o,503,{error:"Hooks subsystem unavailable"}),null;const u=t.hookSessions.getBySessionId(n);if(!u)return c(o,404,{error:"Session not found"}),null;if(u.projectId==null)return c(o,400,{error:"Session is not bound to a project"}),null;const f=t.projects.getById(u.projectId);return f||(c(o,404,{error:"Project not found"}),null)}function k(o,t){if(!o.hookEvents)return null;const n=o.hookEvents.listBySession(t,1),u=n[n.length-1]?.source;return j(u)?u:null}const F=20,X=2e3,Q=200,C=new Map,W=2e5;function z(o){try{const t=JSON.parse(o);return[typeof t.toolName=="string"?t.toolName:null,t.toolInput??null,t.toolResponse??null]}catch{return[null,null,null]}}function H(o){if(!o)return null;try{const t=U(o,"utf8");return t.trim()?t:null}catch{return null}}const B=2e5,J=4e6;function K(o,t){const n=T.relative(t,o);return(!!n&&!n.startsWith("..")&&!T.isAbsolute(n)?n:o).split(T.sep).join("/")}function G(o){if(!o)return null;const t=Date.parse(o);return Number.isFinite(t)?t:null}function V(o,t,n){if(t===null&&n===null)return!0;if(!o)return!1;const u=Date.parse(o);return!(!Number.isFinite(u)||t!==null&&u<=t||n!==null&&u>n)}function Y(o,t){const n=[],u=new Map;let f=J,w=0,d=!1;for(const l of o){const h=l.hunk.before.slice(0,B),p=l.hunk.after.slice(0,B),E=h.length<l.hunk.before.length||p.length<l.hunk.after.length;E&&(d=!0);const S=h.length+p.length;if(S>f){d=!0;continue}f-=S;const e=K(l.path,t);let s=u.get(e);s||(s={path:e,hunks:[]},u.set(e,s),n.push(s)),s.hunks.push({before:h,after:p,at:l.at,...E?{clamped:!0}:{}}),w++}return{files:n,hunks:w,truncated:d}}export async function handleSessionInsightRoutes(o,t,n,u,f){const w=u.match(/^\/sessions\/([^/]+)\/plan$/);if(w&&o.method==="GET"){const e=decodeURIComponent(w[1]);if(!n.hookEvents)return c(t,503,{error:"Hook ingestion unavailable"}),!0;const s=n.hookEvents.listBySession(e,1),i=s[s.length-1]?.source,r=j(i)?v(i)?.plan??null:null;if(!r)return c(t,200,{plan:null}),!0;const m=a=>a.flatMap(M=>{const y=r.draftOf(...z(M.payload));return y?[{row:M,draft:y}]:[]}),I=s[s.length-1]?.id??0,b=n.hookEvents,A=C.get(e);if(A&&A.latestId===I)return c(t,200,{plan:A.plan}),!0;const _=a=>(C.size>=Q&&C.clear(),C.set(e,{latestId:I,plan:a}),c(t,200,{plan:a}),!0),R=(a,M)=>{const y=b.listByTools(e,a,M,F,I-X);return y.length>0?y:b.listByTools(e,a,M,F)},[P]=m(R([r.tool],null));if(!P)return _(null);const[N]=m(R(r.writeTools,r.fileHint)).filter(a=>a.row.id<P.row.id),O=P.draft.text??H(P.draft.filePath)??N?.draft.text??H(N?.draft.filePath??null);return _(O?{eventId:P.row.id,at:P.row.createdAt,text:O.slice(0,W)}:null)}const d=u.match(/^\/sessions\/([^/]+)\/pre-question$/);if(d&&o.method==="GET"){const e=decodeURIComponent(d[1]);if(!g(t,n,e))return!0;const s=k(n,e),r=await(s?v(s):null)?.preQuestion?.(n.sessionProbe?.transcriptPathOf(e)??null);return c(t,200,{preQuestion:r??null}),!0}const l=u.match(/^\/sessions\/([^/]+)\/narration$/);if(l&&o.method==="GET"){const e=decodeURIComponent(l[1]);if(!g(t,n,e))return!0;const s=k(n,e),i=s?D(s):null;if(!i)return c(t,200,{supported:!1,narration:null}),!0;const r=await i.sessionNarration({sessionId:e,transcriptPath:n.sessionProbe?.transcriptPathOf(e)??null});return c(t,200,{supported:r!==null,narration:r}),!0}const h=u.match(/^\/sessions\/([^/]+)\/rewinds$/);if(h&&o.method==="GET"){const e=decodeURIComponent(h[1]);if(!g(t,n,e))return!0;const s=k(n,e),i=s?L(s):null;if(!i)return c(t,200,{supported:!1,rewinds:null}),!0;const r=await i.sessionRewinds({sessionId:e,transcriptPath:n.sessionProbe?.transcriptPathOf(e)??null});return c(t,200,{supported:r!==null,rewinds:r}),!0}const p=u.match(/^\/sessions\/([^/]+)\/commands$/);if(p&&o.method==="GET"){const e=decodeURIComponent(p[1]),s=g(t,n,e);if(!s)return!0;const i=k(n,e),r=i?x(i):null;return r?(c(t,200,{supported:!0,commands:await r.list({projectPath:s.path}),inputModes:r.inputModes}),!0):(c(t,200,{supported:!1,commands:[],inputModes:[]}),!0)}const E=u.match(/^\/sessions\/([^/]+)\/command-executions$/);if(E&&o.method==="GET"){const e=decodeURIComponent(E[1]);if(!g(t,n,e))return!0;const s=k(n,e),i=s?x(s):null;if(!i)return c(t,200,{supported:!1,executions:null}),!0;const r=await i.executions(n.sessionProbe?.transcriptPathOf(e)??null);return c(t,200,{supported:r!==null,executions:r}),!0}const S=u.match(/^\/sessions\/([^/]+)\/edits$/);if(S&&o.method==="GET"){const e=decodeURIComponent(S[1]),s=g(t,n,e);if(!s)return!0;const i=k(n,e),r=i?$(i):null;if(!r)return c(t,200,{files:null,hunks:0,truncated:!1,reason:"unsupported"}),!0;const m=await r.sessionEdits({sessionId:e,transcriptPath:n.sessionProbe?.transcriptPathOf(e)??null});if(!m)return c(t,200,{files:null,hunks:0,truncated:!1,reason:"unreadable"}),!0;const I=G(f.searchParams.get("since")),b=G(f.searchParams.get("until")),A=I!==null||b!==null?m.filter(_=>V(_.at,I,b)):m;return c(t,200,Y(A,s.path)),!0}return!1}
@@ -1 +1 @@
1
- import{readBody as m,sendJson as r}from"../http.js";import{DEFAULT_AI_SETTINGS as b,DEFAULT_DECISION_SETTINGS as E,readDaemonSettings as u,writeDaemonSettings as T,terminalPresetsFor as K}from"../settings.js";import{readAiKey as N,writeAiKey as G}from"../ai-config.js";import{readDecisionKey as I,writeDecisionKey as U}from"../decision-config.js";import{accessUrls as j}from"../tls.js";import{applyLaunchOnLogin as A}from"../auto-start.js";import{WEAVE_VERSION as O}from"../../version.js";import{readProjectConfig as h,writeProjectConfig as v}from"../../install/project-config.js";import{readStatuslineConfig as y,readStatuslineScript as C,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 B,listDirectoryChildren as L}from"../fs-browser.js";import{projectFileNamespaces as _}from"../../hooks/toolkit.js";import{listGlobalFileAssets as k}from"../../install/global-file-assets.js";function w(i,e,s){const n=i.ai??b,l=i.decision??E,p=N(e),d=I(s);return{...i,ai:{baseUrl:n.baseUrl,model:n.model,apiKey:p,apiKeySet:p!==null},decision:{baseUrl:l.baseUrl,model:l.model,apiKey:d,apiKeySet:d!==null}}}function P(i){if(!i)return;const{apiKey:e,...s}=i;return s}export async function handleSettingsRoutes(i,e,s,n,l){if(n==="/settings"){if(i.method==="GET")return r(e,200,{settings:w(await u(),s.aiKeyPath,s.decisionKeyPath),presets:K(process.platform),platform:process.platform,urls:j(s.port,s.tlsPort??0),version:O,repoUrl:"https://github.com/zijing66/weave"}),!0;if(i.method==="PUT"){let t;try{t=JSON.parse(await m(i))}catch{return r(e,400,{error:"Invalid JSON body"}),!0}const a=t.ai?.apiKey;a!==void 0&&G(typeof a=="string"?a:null,s.aiKeyPath);const o=t.decision?.apiKey;o!==void 0&&U(typeof o=="string"?o:null,s.decisionKeyPath);const c=await u(),f=await T({...c,...t,ai:t.ai?P(t.ai):c.ai,decision:t.decision?P(t.decision):c.decision});return s.hookEvents?.resetPrune(),(s.autoStart??A)(f.startup?.launchOnLogin??!1),s.dataBus?.emit({key:"settings"}),r(e,200,w(f,s.aiKeyPath,s.decisionKeyPath)),!0}}if(n==="/fs/roots"&&i.method==="GET"){const t=s.libraries?s.libraries.list().map(o=>o.path):[],a=await B(t);return r(e,200,{roots:a}),!0}if(n==="/fs/children"&&i.method==="GET"){const t=l.searchParams.get("path");if(!t)return r(e,400,{error:'Missing "path" query parameter'}),!0;try{const a=await L(t);r(e,200,{children:a})}catch(a){r(e,400,{error:`Cannot list directory: ${String(a)}`})}return!0}const p=n.match(/^\/projects\/(\d+)\/config$/);if(p){const t=s.projects.getById(Number(p[1]));if(!t)return r(e,404,{error:"Project not found"}),!0;if(i.method==="GET")return r(e,200,await h(t.path)),!0;if(i.method==="PUT"){let a;try{a=JSON.parse(await m(i))}catch{return r(e,400,{error:"Invalid JSON body"}),!0}const o=await h(t.path),c={lastSyncAt:a.lastSyncAt??o.lastSyncAt};return await v(t.path,c),r(e,200,c),!0}}if(n==="/statusline/global"){if(i.method==="GET")return r(e,200,{config:await S()}),!0;if(i.method==="PUT"){let t;try{t=JSON.parse(await m(i))}catch{return r(e,400,{error:"Invalid JSON body"}),!0}try{await J(t);for(const a of s.projects.list()){const o=await y(a.path);o.source==="global"&&await g(a.path,o)}s.dataBus?.emit({key:"statusline"}),r(e,200,{ok:!0})}catch(a){r(e,400,{error:a instanceof Error?a.message:"Global statusline update failed"})}return!0}}if(n==="/statusline/default"&&i.method==="GET")return r(e,200,{config:F}),!0;const d=n.match(/^\/projects\/(\d+)\/statusline$/);if(d){const t=s.projects.getById(Number(d[1]));if(!t)return r(e,404,{error:"Project not found"}),!0;if(i.method==="GET"){const[a,o,c]=await Promise.all([y(t.path),C(t.path),S()]);return r(e,200,{config:a,script:o,globalConfig:c,facts:D(t.path)}),!0}if(i.method==="PUT"){let a;try{a=JSON.parse(await m(i))}catch{return r(e,400,{error:"Invalid JSON body"}),!0}try{await g(t.path,a),s.dataBus?.emit({key:"statusline",projectPath:t.path}),r(e,200,{ok:!0})}catch(o){r(e,400,{error:o instanceof Error?o.message:"Statusline update failed"})}return!0}}if(n==="/assets"&&i.method==="GET"){const t=l.searchParams.get("path");if(!t)return r(e,400,{error:'Missing "path" query parameter'}),!0;if(!s.watch)return r(e,503,{error:"Watch service unavailable"}),!0;const a=await _(t),o=s.watch.getAssets(t).map(c=>{const f=a.get(c.relPath);return f?{...c,namespace:f}:c});return r(e,200,{projectPath:t,assets:o}),!0}return n==="/global-file-assets"&&i.method==="GET"?(r(e,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 @@
1
- import{createReadStream as w}from"node:fs";import{z as u}from"zod";import{readJson as c,readRawBody as E,sendJson as a}from"../http.js";import{isImageMediaType as I,maxUploadBytes as b}from"../../repositories/uploads.js";import{defaultUploadSessions as S}from"../upload-sessions.js";const z=u.object({name:u.string().min(1).max(200),mediaType:u.string().min(1).max(100),data:u.string().min(1),projectId:u.number().int().positive().optional()}),B=u.object({name:u.string().min(1).max(200),mediaType:u.string().min(1).max(100),size:u.number().int().positive(),projectId:u.number().int().positive().optional()});function j(o,e){return(I(e)?o?.images:o?.files)??null}const x=16*1024*1024;function f(o,e){return{id:e.id,name:e.name,mediaType:e.mediaType,size:e.size,path:o.uploads.pathOf(e)}}function g(o,e,t){if(!o.projects.getById(e))return null;const d=o.projects.getMeta(e);return j(d?.storage,t)}export async function handleUploadRoutes(o,e,t,d,h){const l=t.uploadSessions??S;if(d==="/uploads/begin"&&o.method==="POST"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;let r;try{r=B.parse(await c(o))}catch(n){return a(e,400,{error:n instanceof Error?n.message:"Invalid body"}),!0}if(r.size>b(r.mediaType))return a(e,413,{error:"File too large"}),!0;const s=r.projectId?g(t,r.projectId,r.mediaType):null,i=await l.begin({...r,dir:s});return a(e,201,{uploadId:i.id,received:0,size:i.size}),!0}const m=d.match(/^\/uploads\/([0-9a-f-]{36})\/finish$/);if(m&&o.method==="POST"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;const r=await l.finish(m[1]);if(!r)return a(e,409,{error:"Upload incomplete"}),!0;const s=await t.uploads.adoptFromFile(r);return await l.abort(m[1]),a(e,201,{upload:f(t,s)}),!0}const y=d.match(/^\/uploads\/([0-9a-f-]{36})$/);if(y){const r=y[1];if(o.method==="GET"){const s=await l.get(r);return s?(a(e,200,{received:s.received,size:s.size,name:s.name,mediaType:s.mediaType}),!0):(a(e,404,{error:"Upload not found"}),!0)}if(o.method==="PUT"){const s=Number(h.searchParams.get("offset")??"");if(!Number.isInteger(s)||s<0)return a(e,400,{error:"Invalid offset"}),!0;const i=await E(o,x).catch(()=>null);if(!i)return a(e,413,{error:"Chunk too large"}),!0;const n=await l.append(r,s,i);return n.kind==="missing"?(a(e,404,{error:"Upload not found"}),!0):n.kind==="conflict"?(a(e,409,{received:n.received}),!0):n.kind==="overflow"?(a(e,413,{received:n.received,error:"Exceeds declared size"}),!0):(a(e,200,{received:n.received}),!0)}if(o.method==="DELETE")return await l.abort(r),a(e,200,{ok:!0}),!0}if(d==="/uploads"&&o.method==="POST"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;let r;try{r=z.parse(await c(o))}catch(n){return a(e,400,{error:n instanceof Error?n.message:"Invalid body"}),!0}const s=Buffer.from(r.data,"base64");if(s.length===0)return a(e,400,{error:"Empty upload"}),!0;if(s.length>b(r.mediaType))return a(e,413,{error:"File too large"}),!0;const i=t.uploads.save({name:r.name,mediaType:r.mediaType,bytes:s,dir:r.projectId?g(t,r.projectId,r.mediaType):null});return a(e,201,{upload:f(t,i)}),!0}const p=d.match(/^\/sessions\/([^/]+)\/uploads$/);if(p&&o.method==="GET"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;const r=t.uploads.uploadsBySession(decodeURIComponent(p[1]));return a(e,200,{uploads:(r??[]).map(s=>({...f(t,s),createdAt:s.createdAt})),totalBytes:(r??[]).reduce((s,i)=>s+i.size,0)}),!0}if(p&&o.method==="DELETE"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;const r=t.uploads.uploadsBySession(decodeURIComponent(p[1]));if(!r)return a(e,200,{removed:0,freedBytes:0}),!0;const s=r.reduce((n,U)=>n+U.size,0),i=t.uploads.removeMany(r.map(n=>n.id));return t.dataBus?.emit({key:"sessions"}),a(e,200,{removed:i,freedBytes:s}),!0}if(d==="/uploads/unreferenced"&&o.method==="GET")return t.uploads?(a(e,200,t.uploads.unreferencedStats()),!0):(a(e,503,{error:"Upload subsystem unavailable"}),!0);if(d==="/uploads/overview"&&o.method==="GET")return t.uploads?(a(e,200,t.uploads.overview()),!0):(a(e,503,{error:"Upload subsystem unavailable"}),!0);const T=u.object({ids:u.array(u.string().regex(/^[a-f0-9]{64}$/)).min(1).max(500)});if(d==="/uploads/remove"&&o.method==="POST"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;let r;try{r=T.parse(await c(o))}catch(i){return a(e,400,{error:i instanceof Error?i.message:"Invalid body"}),!0}const s=t.uploads.removeMany(r.ids);return t.dataBus?.emit({key:"sessions"}),a(e,200,{removed:s}),!0}if(d==="/uploads/usage"&&o.method==="GET")return t.uploads?(a(e,200,{sessions:t.uploads.usageBySession()}),!0):(a(e,503,{error:"Upload subsystem unavailable"}),!0);if(d==="/uploads/unreferenced"&&o.method==="POST"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;let r={done:0,total:0};const s=t.uploads.cleanupUnreferenced((i,n)=>{r={done:i,total:n}});return t.dataBus?.emit({key:"sessions"}),a(e,200,{removed:s,...r}),!0}const v=d.match(/^\/images\/([a-f0-9]{64})$/);if(v&&o.method==="GET"){if(!t.uploads)return a(e,503,{error:"Upload subsystem unavailable"}),!0;const r=t.uploads.fileStatOf(v[1]);if(!r)return a(e,404,{error:"Image not found"}),!0;e.writeHead(200,{"content-type":r.row.mediaType,"content-length":String(r.size),"cache-control":"private, max-age=31536000, immutable"});const s=w(r.file);return s.on("error",()=>{typeof e.destroy=="function"&&e.destroy()}),s.pipe(e),!0}return!1}
1
+ import{createReadStream as B}from"node:fs";import{z as s}from"zod";import{readJson as p,readRawBody as E,sendJson as r}from"../http.js";import{isImageMediaType as w,maxUploadBytes as g}from"../../repositories/uploads.js";import{defaultUploadSessions as I}from"../upload-sessions.js";const S=s.object({name:s.string().min(1).max(200),mediaType:s.string().min(1).max(100),data:s.string().min(1),projectId:s.number().int().positive().optional()}),j=s.object({name:s.string().min(1).max(200),mediaType:s.string().min(1).max(100),size:s.number().int().positive(),projectId:s.number().int().positive().optional()});function z(i,e){return(w(e)?i?.images:i?.files)??null}const x=16*1024*1024;function y(i,e){return{id:e.id,name:e.name,mediaType:e.mediaType,size:e.size,path:i.uploads.pathOf(e)}}function h(i,e,o){if(!i.projects.getById(e))return null;const m=i.projects.getMeta(e);return z(m?.storage,o)}export async function handleUploadRoutes(i,e,o,d,m){const l=o.uploadSessions??I;if(d==="/uploads/begin"&&i.method==="POST"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;let t;try{t=j.parse(await p(i))}catch(n){return r(e,400,{error:n instanceof Error?n.message:"Invalid body"}),!0}if(t.size>g(t.mediaType))return r(e,413,{error:"File too large"}),!0;const a=t.projectId?h(o,t.projectId,t.mediaType):null,u=await l.begin({...t,dir:a});return r(e,201,{uploadId:u.id,received:0,size:u.size}),!0}const f=d.match(/^\/uploads\/([0-9a-f-]{36})\/finish$/);if(f&&i.method==="POST"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;const t=await l.finish(f[1]);if(!t)return r(e,409,{error:"Upload incomplete"}),!0;const a=await o.uploads.adoptFromFile(t);return await l.abort(f[1]),r(e,201,{upload:y(o,a)}),!0}const b=d.match(/^\/uploads\/([0-9a-f-]{36})$/);if(b){const t=b[1];if(i.method==="GET"){const a=await l.get(t);return a?(r(e,200,{received:a.received,size:a.size,name:a.name,mediaType:a.mediaType}),!0):(r(e,404,{error:"Upload not found"}),!0)}if(i.method==="PUT"){const a=Number(m.searchParams.get("offset")??"");if(!Number.isInteger(a)||a<0)return r(e,400,{error:"Invalid offset"}),!0;const u=await E(i,x).catch(()=>null);if(!u)return r(e,413,{error:"Chunk too large"}),!0;const n=await l.append(t,a,u);return n.kind==="missing"?(r(e,404,{error:"Upload not found"}),!0):n.kind==="conflict"?(r(e,409,{received:n.received}),!0):n.kind==="overflow"?(r(e,413,{received:n.received,error:"Exceeds declared size"}),!0):(r(e,200,{received:n.received}),!0)}if(i.method==="DELETE")return await l.abort(t),r(e,200,{ok:!0}),!0}if(d==="/uploads"&&i.method==="POST"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;let t;try{t=S.parse(await p(i))}catch(n){return r(e,400,{error:n instanceof Error?n.message:"Invalid body"}),!0}const a=Buffer.from(t.data,"base64");if(a.length===0)return r(e,400,{error:"Empty upload"}),!0;if(a.length>g(t.mediaType))return r(e,413,{error:"File too large"}),!0;const u=o.uploads.save({name:t.name,mediaType:t.mediaType,bytes:a,dir:t.projectId?h(o,t.projectId,t.mediaType):null});return r(e,201,{upload:y(o,u)}),!0}const c=d.match(/^\/sessions\/([^/]+)\/uploads$/);if(c&&i.method==="GET"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;const t=o.uploads.uploadsBySession(decodeURIComponent(c[1]));return r(e,200,{uploads:(t??[]).map(a=>({...y(o,a),createdAt:a.createdAt})),totalBytes:(t??[]).reduce((a,u)=>a+u.size,0)}),!0}if(c&&i.method==="DELETE"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;const t=o.uploads.uploadsBySession(decodeURIComponent(c[1]));if(!t)return r(e,200,{removed:0,freedBytes:0}),!0;const a=t.reduce((n,U)=>n+U.size,0),u=o.uploads.removeMany(t.map(n=>n.id));return o.dataBus?.emit({key:"sessions"}),r(e,200,{removed:u,freedBytes:a}),!0}if(d==="/uploads/unreferenced"&&i.method==="GET")return o.uploads?(r(e,200,o.uploads.unreferencedStats()),!0):(r(e,503,{error:"Upload subsystem unavailable"}),!0);if(d==="/uploads/overview"&&i.method==="GET")return o.uploads?(r(e,200,o.uploads.overview()),!0):(r(e,503,{error:"Upload subsystem unavailable"}),!0);const T=s.object({ids:s.array(s.string().regex(/^[a-f0-9]{64}$/)).min(1).max(500)});if(d==="/uploads/remove"&&i.method==="POST"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;let t;try{t=T.parse(await p(i))}catch(u){return r(e,400,{error:u instanceof Error?u.message:"Invalid body"}),!0}const a=o.uploads.removeMany(t.ids);return o.dataBus?.emit({key:"sessions"}),r(e,200,{removed:a}),!0}if(d==="/uploads/usage"&&i.method==="GET")return o.uploads?(r(e,200,{sessions:o.uploads.usageBySession()}),!0):(r(e,503,{error:"Upload subsystem unavailable"}),!0);if(d==="/uploads/unreferenced"&&i.method==="POST"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;let t={done:0,total:0};const a=o.uploads.cleanupUnreferenced((u,n)=>{t={done:u,total:n}});return o.dataBus?.emit({key:"sessions"}),r(e,200,{removed:a,...t}),!0}const v=d.match(/^\/images\/([a-f0-9]{64})$/);if(v&&i.method==="GET"){if(!o.uploads)return r(e,503,{error:"Upload subsystem unavailable"}),!0;const t=o.uploads.fileStatOf(v[1]);if(!t)return r(e,404,{error:"Image not found"}),!0;e.writeHead(200,{"content-type":t.row.mediaType,"content-length":String(t.size),"cache-control":"private, max-age=31536000, immutable"});const a=B(t.file);return a.on("error",()=>{typeof e.destroy=="function"&&e.destroy()}),a.pipe(e),!0}return!1}
@@ -1 +1,2 @@
1
- import t from"node:path";import d from"node:os";import{promises as l}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 F}from"../../market/resolve.js";function j(s){const r=d.homedir(),o=[t.join(r,u.codex.userDir,"visualizations"),t.join(r,u.claude.userDir),t.join(r,u.codex.userDir,"plugins")];for(const a of s.projects.list())o.push(a.path);return o}export async function handleVisualizationRoutes(s,r,o,a,c){if(a!=="/visualizations/fragment"||s.method!=="GET")return!1;const n=c.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 f=j(o);if(!f.some(h=>F(i,h)))return e(r,403,{error:`Fragment path is outside the allowed roots: ${f.join(", ")}`}),!0;if(t.extname(i).toLowerCase()!==".html")return e(r,403,{error:"Only .html fragments are served"}),!0;let m;try{m=await l.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 p=await l.readFile(i,"utf8");return e(r,200,{html:p}),!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}
@@ -1 +1 @@
1
- import{z as o}from"zod";import{isHarness as I}from"@weavecode/core";import{readJson as m,sendJson as e}from"../http.js";import{messagingSurfaceFor as v}from"../../surfaces.js";import{DEFAULT_WATCH_ON as E}from"../../repositories/session-watches.js";const k=o.object({watcherSessionId:o.string().min(1).nullable().optional(),notify:o.string().min(1).max(2e4).nullable().optional(),on:o.array(o.enum(["idle","turnEnd","messageFailed"])).min(1).optional(),times:o.number().int().min(1).max(100).nullable().optional()}),W=o.object({watchId:o.number().int().positive()}),T=o.object({endpoint:o.string().url(),keys:o.object({p256dh:o.string().min(1),auth:o.string().min(1)})}),B=o.object({endpoint:o.string().url()});function P(i,s){return i.queuedPrompt!==null||i.prompt!==null||s}export async function handleWatchRoutes(i,s,t,d){const f=d.match(/^\/sessions\/([^/]+)\/watch$/);if(f){const n=decodeURIComponent(f[1]);if(i.method==="POST"){if(!t.sessionWatches||!t.hookSessions||!t.hookEvents)return e(s,503,{error:"Messaging subsystem unavailable"}),!0;let r;try{r=k.parse(await m(i))}catch(u){return e(s,400,{error:u instanceof Error?u.message:"Invalid body"}),!0}if(!t.hookSessions.getBySessionId(n))return e(s,404,{error:"Session not found"}),!0;const c=t.hookEvents.listBySession(n,1),a=c[c.length-1]?.source;if(!I(a))return e(s,400,{error:"Session has no hook events to determine its harness"}),!0;const h=v(a),l=r.on??[...E];if((l.includes("idle")||l.includes("turnEnd"))&&h.idleSignals.length===0)return e(s,409,{error:h.unsupportedReasons?.watch??`Harness "${a}" does not support idle watching`}),!0;if(l.includes("messageFailed")&&!(P(h,t.messageDeliverer?.hasTerminalChannel()??!1)||h.inject!==null||h.headless!==null))return e(s,409,{error:h.unsupportedReasons?.prompt??`Harness "${a}" supports no messaging channel`}),!0;if(r.watcherSessionId){if(!t.hookSessions.getBySessionId(r.watcherSessionId))return e(s,404,{error:"Watcher session not found"}),!0;const u=t.hookEvents.listBySession(r.watcherSessionId,1),g=u[u.length-1]?.source;if(!I(g))return e(s,400,{error:"Watcher session has no hook events to determine its harness"}),!0;const w=v(g);if(!w.inject)return e(s,409,{error:w.unsupportedReasons?.inject??`Harness "${g}" cannot receive watch notifications`}),!0}const b=r.times===void 0?1:r.times,y=(r.watcherSessionId??null)===null?t.sessionWatches.listPendingByTarget(n).find(u=>u.watcherSessionId===null):void 0,S=y?t.sessionWatches.updateById(y.id,{onEvents:l,remaining:b}):void 0,p=S??t.sessionWatches.insert({watcherSessionId:r.watcherSessionId??null,targetSessionId:n,notify:r.notify??null,onEvents:l,times:b});return t.watchEngine?.created(p),e(s,S?200:201,{ok:!0,watchId:p.id,watch:p}),!0}if(i.method==="DELETE"){if(!t.sessionWatches)return e(s,503,{error:"Messaging subsystem unavailable"}),!0;let r;try{r=W.parse(await m(i))}catch(a){return e(s,400,{error:a instanceof Error?a.message:"Invalid body"}),!0}const c=t.sessionWatches.getById(r.watchId);return!c||c.targetSessionId!==n||c.firedAt!==null?(e(s,404,{error:"Watch not found"}),!0):(t.sessionWatches.deleteById(r.watchId),e(s,200,{ok:!0,watchId:r.watchId}),!0)}}if(d==="/messaging/watches"&&i.method==="GET")return t.sessionWatches?(e(s,200,{watches:t.sessionWatches.listPending()}),!0):(e(s,503,{error:"Messaging subsystem unavailable"}),!0);if(d==="/messaging/push/key"&&i.method==="GET")return t.pushNotifier?(e(s,200,{publicKey:t.pushNotifier.publicKey()}),!0):(e(s,503,{error:"Push subsystem unavailable"}),!0);if(d==="/messaging/push/subscribe"&&i.method==="POST"){if(!t.pushSubscriptions)return e(s,503,{error:"Push subsystem unavailable"}),!0;try{const n=T.parse(await m(i)),r=t.pushSubscriptions.upsert({endpoint:n.endpoint,p256dh:n.keys.p256dh,auth:n.keys.auth,userAgent:i.headers["user-agent"]??null});e(s,201,{ok:!0,subscription:r})}catch(n){e(s,400,{error:n instanceof Error?n.message:"Invalid body"})}return!0}if(d==="/messaging/push/unsubscribe"&&i.method==="POST"){if(!t.pushSubscriptions)return e(s,503,{error:"Push subsystem unavailable"}),!0;try{const n=B.parse(await m(i));t.pushSubscriptions.deleteByEndpoint(n.endpoint),e(s,200,{ok:!0})}catch(n){e(s,400,{error:n instanceof Error?n.message:"Invalid body"})}return!0}return!1}
1
+ import{z as o}from"zod";import{isHarness as E}from"@weavecode/core";import{readJson as g,sendJson as t}from"../http.js";import{messagingSurfaceFor as k}from"../../surfaces.js";import{DEFAULT_WATCH_ON as W}from"../../repositories/session-watches.js";const B=o.object({watcherSessionId:o.string().min(1).nullable().optional(),notify:o.string().min(1).max(2e4).nullable().optional(),on:o.array(o.enum(["idle","turnEnd","messageFailed"])).min(1).optional(),times:o.number().int().min(1).max(100).nullable().optional()}),P=o.object({watchId:o.number().int().positive()}),T=o.object({endpoint:o.string().url(),keys:o.object({p256dh:o.string().min(1),auth:o.string().min(1)})}),j=o.object({endpoint:o.string().url()});function C(i,e){return i.queuedPrompt!==null||i.prompt!==null||e}export async function handleWatchRoutes(i,e,n,c){const y=c.match(/^\/sessions\/([^/]+)\/watch$/);if(y){const s=decodeURIComponent(y[1]);if(i.method==="POST"){if(!n.sessionWatches||!n.hookSessions||!n.hookEvents)return t(e,503,{error:"Messaging subsystem unavailable"}),!0;let r;try{r=B.parse(await g(i))}catch(u){return t(e,400,{error:u instanceof Error?u.message:"Invalid body"}),!0}if(!n.hookSessions.getBySessionId(s))return t(e,404,{error:"Session not found"}),!0;const h=n.hookEvents.listBySession(s,1),m=h[h.length-1]?.source;if(!E(m))return t(e,400,{error:"Session has no hook events to determine its harness"}),!0;const a=k(m),l=r.on??[...W];if((l.includes("idle")||l.includes("turnEnd"))&&a.idleSignals.length===0)return t(e,409,{error:a.unsupportedReasons?.watch??`Harness "${m}" does not support idle watching`}),!0;if(l.includes("messageFailed")&&!(C(a,n.messageDeliverer?.hasTerminalChannel()??!1)||a.inject!==null||a.headless!==null))return t(e,409,{error:a.unsupportedReasons?.prompt??`Harness "${m}" supports no messaging channel`}),!0;if(r.watcherSessionId){if(!n.hookSessions.getBySessionId(r.watcherSessionId))return t(e,404,{error:"Watcher session not found"}),!0;const I=n.hookEvents.listBySession(r.watcherSessionId,1),b=I[I.length-1]?.source;if(!E(b))return t(e,400,{error:"Watcher session has no hook events to determine its harness"}),!0;const v=k(b);if(!v.inject)return t(e,409,{error:v.unsupportedReasons?.inject??`Harness "${b}" cannot receive watch notifications`}),!0}const p=r.times===void 0?1:r.times,w=(r.watcherSessionId??null)===null?n.sessionWatches.listPendingByTarget(s).find(u=>u.watcherSessionId===null):void 0,S=w?n.sessionWatches.updateById(w.id,{onEvents:l,remaining:p}):void 0,f=S??n.sessionWatches.insert({watcherSessionId:r.watcherSessionId??null,targetSessionId:s,notify:r.notify??null,onEvents:l,times:p});return n.watchEngine?.created(f),t(e,S?200:201,{ok:!0,watchId:f.id,watch:f}),!0}if(i.method==="DELETE"){if(!n.sessionWatches)return t(e,503,{error:"Messaging subsystem unavailable"}),!0;let r;try{r=P.parse(await g(i))}catch(h){return t(e,400,{error:h instanceof Error?h.message:"Invalid body"}),!0}const d=n.sessionWatches.getById(r.watchId);return!d||d.targetSessionId!==s||d.firedAt!==null?(t(e,404,{error:"Watch not found"}),!0):(n.sessionWatches.deleteById(r.watchId),t(e,200,{ok:!0,watchId:r.watchId}),!0)}}if(c==="/messaging/watches"&&i.method==="GET")return n.sessionWatches?(t(e,200,{watches:n.sessionWatches.listPending()}),!0):(t(e,503,{error:"Messaging subsystem unavailable"}),!0);if(c==="/messaging/push/key"&&i.method==="GET")return n.pushNotifier?(t(e,200,{publicKey:n.pushNotifier.publicKey()}),!0):(t(e,503,{error:"Push subsystem unavailable"}),!0);if(c==="/messaging/push/subscribe"&&i.method==="POST"){if(!n.pushSubscriptions)return t(e,503,{error:"Push subsystem unavailable"}),!0;try{const s=T.parse(await g(i)),r=n.pushSubscriptions.upsert({endpoint:s.endpoint,p256dh:s.keys.p256dh,auth:s.keys.auth,userAgent:i.headers["user-agent"]??null});t(e,201,{ok:!0,subscription:r})}catch(s){t(e,400,{error:s instanceof Error?s.message:"Invalid body"})}return!0}if(c==="/messaging/push/unsubscribe"&&i.method==="POST"){if(!n.pushSubscriptions)return t(e,503,{error:"Push subsystem unavailable"}),!0;try{const s=j.parse(await g(i));n.pushSubscriptions.deleteByEndpoint(s.endpoint),t(e,200,{ok:!0})}catch(s){t(e,400,{error:s instanceof Error?s.message:"Invalid body"})}return!0}return!1}
@@ -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 由其派生。
@@ -1,13 +1,13 @@
1
- import y from"node:http";import{WEAVE_VERSION as S}from"../version.js";import{isHarness as R}from"@weavecode/core";import h from"node:fs";import l from"node:path";import{SseHub as E}from"./sse-hub.js";import{importPromptImagesOnce as H,needsImageImport as N}from"./prompt-images.js";import{sendJson as m}from"./http.js";import{FingerprintCache as P}from"../install/fingerprint.js";import{ApiLogger as j}from"./api-log.js";import{handleHooksRoutes as k}from"./hooks-routes.js";import{handleMcpRequest as x}from"./mcp-orchestration.js";import{handleToolkitRoutes as W}from"./toolkit-routes.js";import{handleCaptureRoutes as O}from"./capture-routes.js";import{handleConfigRoutes as T}from"./config-routes.js";import{handleMarketRoutes as A}from"./routes/market.js";import{handleProjectRoutes as I}from"./routes/projects.js";import{handleSettingsRoutes as M}from"./routes/settings-statusline.js";import{handleSearchRoutes as C}from"./routes/search.js";import{handleProjectFileRoutes as D}from"./routes/project-files.js";import{DAEMON_HOST as J}from"./port.js";import{handleAuthRoutes as $}from"./auth-routes.js";import{handleAiRoutes as B}from"./ai-routes.js";export const DAEMON_VERSION=S;export function weaveRequestHandler(e){const r=e.fingerprintCache??new P,t=e.apiLog??new j,o=e.sseHub??new E(e),a={...e,fingerprintCache:r,apiLog:t,sseHub:o};return(n,i)=>{t.begin(n,i),F(n,i,a)}}export function createWeaveServer(e){return y.createServer(weaveRequestHandler(e))}async function F(e,r,t){const o=new URL(e.url??"/",`http://${J}`);let a=o.pathname;if(a.startsWith("/api/")?a=a.slice(4):a==="/api"&&(a="/"),a==="/health"&&e.method==="GET"){m(r,200,{service:"weave-daemon",version:DAEMON_VERSION,pid:process.pid,port:t.port,uptimeMs:Math.round(process.uptime()*1e3)});return}if(await $(e,r,t,a)||await B(e,r,t,a))return;if(t.auth&&!G(e,a,t)&&!t.auth.isAuthenticated(e.headers)){m(r,401,{error:"Unauthorized"});return}if(a==="/mcp"){await x(e,r,{port:t.port,token:t.auth?.getLocalToken()??null});return}if(a==="/api-logs"&&e.method==="GET"){if(!t.apiLog){m(r,503,{error:"API log unavailable"});return}const i=o.searchParams.get("status"),c=o.searchParams.get("limit"),s=await t.apiLog.query({from:o.searchParams.get("from")??void 0,to:o.searchParams.get("to")??void 0,path:o.searchParams.get("path")??void 0,method:o.searchParams.get("method")??void 0,status:i==null?void 0:Number(i),limit:c==null?void 0:Number(c)});m(r,200,s);return}if(await k(e,r,t,a,o)||await W(e,r,t,a,o)||await O(e,r,t,a)||await T(e,r,t,a,o))return;const n=a.match(/^\/projects\/(\d+)\/hooks$/);if(n&&e.method==="GET"){if(!t.hookEvents){m(r,503,{error:"Hook ingestion unavailable"});return}const i=Number(n[1]),c=K(o.searchParams.get("limit")),s=o.searchParams.get("sessionId"),f=o.searchParams.get("beforeId"),u=f?Number(f):void 0,b=(o.searchParams.get("types")??"").split(",").map(p=>p.trim()).filter(Boolean);if(s){const p=t.hookEvents.listBySession(s,c??300,u,b);let v=t.uploads?.imagesBySession(s);if(N(p,v)){const d=t.projects.getMeta(i);await H({hookEvents:t.hookEvents,uploads:t.uploads,sessionProbe:t.sessionProbe,uploadDir:d?.storage?.images??null},s,U(p))&&(v=t.uploads?.imagesBySession(s))}m(r,200,{events:p.map(d=>{const w=v?.get(d.id);return w?.length?{...d,images:w.map(g=>({id:g.id,name:g.name,mediaType:g.mediaType,size:g.size}))}:d})});return}m(r,200,{events:t.hookEvents.listByProject(i,c)});return}if(!await A(e,r,t,a,o)&&!await M(e,r,t,a,o)&&!await C(e,r,t,a,o)&&!await D(e,r,t,a,o)){if(a==="/events"&&e.method==="GET"){z(e,r,t,o);return}if(!await I(e,r,t,a)){if(e.method==="GET"&&t.staticDir){_(r,a,t.staticDir);return}m(r,404,{error:"Not found"})}}}const L=25e3;function z(e,r,t,o){const a=t.sseHub;if(!a||!t.watch&&!t.hookBus&&!t.dataBus){r.statusCode=503,r.setHeader("content-type","application/json"),r.end(JSON.stringify({error:"Event stream unavailable"}));return}const n=e.headers["last-event-id"],i=(Array.isArray(n)?n[0]:n)??o.searchParams.get("since")??null,c=a.replay(i);r.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-accel-buffering":"no"}),r.write(`: connected
1
+ import y from"node:http";import{WEAVE_VERSION as S}from"../version.js";import{isHarness as R}from"@weavecode/core";import h from"node:fs";import d from"node:path";import{SseHub as E}from"./sse-hub.js";import{importPromptImagesOnce as H,needsImageImport as N}from"./prompt-images.js";import{sendJson as u}from"./http.js";import{FingerprintCache as j}from"../install/fingerprint.js";import{ApiLogger as k}from"./api-log.js";import{handleHooksRoutes as P}from"./hooks-routes.js";import{handleMcpRequest as x}from"./mcp-orchestration.js";import{handleToolkitRoutes as I}from"./toolkit-routes.js";import{handleCaptureRoutes as W}from"./capture-routes.js";import{handleConfigRoutes as T}from"./config-routes.js";import{handleMarketRoutes as A}from"./routes/market.js";import{handleProjectRoutes as O}from"./routes/projects.js";import{handleSettingsRoutes as M}from"./routes/settings-statusline.js";import{handleSearchRoutes as C}from"./routes/search.js";import{handleProjectFileRoutes as B}from"./routes/project-files.js";import{DAEMON_HOST as J}from"./port.js";import{handleAuthRoutes as L}from"./auth-routes.js";import{handleAiRoutes as $}from"./ai-routes.js";export const DAEMON_VERSION=S;export function weaveRequestHandler(t){const n=t.fingerprintCache??new j,e=t.apiLog??new k,r=t.sseHub??new E(t),i={...t,fingerprintCache:n,apiLog:e,sseHub:r};return(s,o)=>{e.begin(s,o),D(s,o,i)}}export function createWeaveServer(t){return y.createServer(weaveRequestHandler(t))}async function D(t,n,e){const r=new URL(t.url??"/",`http://${J}`);let i=r.pathname;if(i.startsWith("/api/")?i=i.slice(4):i==="/api"&&(i="/"),i==="/health"&&t.method==="GET"){u(n,200,{service:"weave-daemon",version:DAEMON_VERSION,pid:process.pid,port:e.port,uptimeMs:Math.round(process.uptime()*1e3)});return}if(await L(t,n,e,i)||await $(t,n,e,i))return;if(e.auth&&!G(t,i,e)&&!e.auth.isAuthenticated(t.headers)){u(n,401,{error:"Unauthorized"});return}if(i==="/mcp"){await x(t,n,{port:e.port,token:e.auth?.getLocalToken()??null});return}if(i==="/api-logs"&&t.method==="GET"){if(!e.apiLog){u(n,503,{error:"API log unavailable"});return}const o=r.searchParams.get("status"),c=r.searchParams.get("limit"),a=await e.apiLog.query({from:r.searchParams.get("from")??void 0,to:r.searchParams.get("to")??void 0,path:r.searchParams.get("path")??void 0,method:r.searchParams.get("method")??void 0,status:o==null?void 0:Number(o),limit:c==null?void 0:Number(c)});u(n,200,a);return}if(await P(t,n,e,i,r)||await I(t,n,e,i,r)||await W(t,n,e,i)||await T(t,n,e,i,r))return;const s=i.match(/^\/projects\/(\d+)\/hooks$/);if(s&&t.method==="GET"){if(!e.hookEvents){u(n,503,{error:"Hook ingestion unavailable"});return}const o=Number(s[1]),c=Q(r.searchParams.get("limit")),a=r.searchParams.get("sessionId"),p=r.searchParams.get("beforeId"),m=p?Number(p):void 0,v=(r.searchParams.get("types")??"").split(",").map(f=>f.trim()).filter(Boolean);if(a){const f=e.hookEvents.listBySession(a,c??300,m,v);let b=e.uploads?.imagesBySession(a);if(N(f,b)){const l=e.projects.getMeta(o);await H({hookEvents:e.hookEvents,uploads:e.uploads,sessionProbe:e.sessionProbe,uploadDir:l?.storage?.images??null},a,K(f))&&(b=e.uploads?.imagesBySession(a))}u(n,200,{events:f.map(l=>{const w=b?.get(l.id);return w?.length?{...l,images:w.map(g=>({id:g.id,name:g.name,mediaType:g.mediaType,size:g.size}))}:l})});return}u(n,200,{events:e.hookEvents.listByProject(o,c)});return}if(!await A(t,n,e,i,r)&&!await M(t,n,e,i,r)&&!await C(t,n,e,i,r)&&!await B(t,n,e,i,r)){if(i==="/events"&&t.method==="GET"){z(t,n,e,r);return}if(!await O(t,n,e,i)){if(t.method==="GET"&&e.staticDir){V(n,i,e.staticDir);return}u(n,404,{error:"Not found"})}}}const F=25e3;function z(t,n,e,r){const i=e.sseHub;if(!i||!e.watch&&!e.hookBus&&!e.dataBus){n.statusCode=503,n.setHeader("content-type","application/json"),n.end(JSON.stringify({error:"Event stream unavailable"}));return}const s=t.headers["last-event-id"],o=(Array.isArray(s)?s[0]:s)??r.searchParams.get("since")??null,c=i.replay(o);n.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-accel-buffering":"no"}),n.write(`: connected
2
2
 
3
- `);const s=setInterval(()=>{r.writableEnded||r.write(`data: ${JSON.stringify({type:"ping"})}
3
+ `);const a=setInterval(()=>{n.writableEnded||n.write(`data: ${JSON.stringify({type:"ping"})}
4
4
 
5
- `)},L);s.unref?.(),c.gap&&r.write(`data: ${JSON.stringify({type:"resync"})}
5
+ `)},F);a.unref?.(),c.gap&&n.write(`data: ${JSON.stringify({type:"resync"})}
6
6
 
7
- `);for(const u of c.frames)r.write(`id: ${u.id}
8
- data: ${u.data}
7
+ `);for(const m of c.frames)n.write(`id: ${m.id}
8
+ data: ${m.data}
9
9
 
10
- `);const f=a.subscribe(u=>{r.write(`id: ${u.id}
11
- data: ${u.data}
10
+ `);const p=i.subscribe(m=>{n.write(`id: ${m.id}
11
+ data: ${m.data}
12
12
 
13
- `)});t.inflightRefresher?.refreshNow(),t.terminalRefresher?.onSubscriberJoin(),t.updatesRefresher?.onSubscriberJoin(),e.on("close",()=>{clearInterval(s),f()})}function G(e,r,t){if(r==="/health"||r.startsWith("/webhooks/orchestrate/"))return!0;if(e.method!=="GET")return!1;if((e.headers.accept??"").includes("text/html"))return!0;if(!t.staticDir)return!1;const o=l.normalize(r).replace(/^([/\\]\.\.[/\\])+/,""),a=l.join(t.staticDir,o);return a.startsWith(t.staticDir)&&h.existsSync(a)&&h.statSync(a).isFile()}function V(e,r){e.setHeader("cache-control",r.startsWith("/assets/")?"public, max-age=31536000, immutable":"no-cache")}function _(e,r,t){const o=l.normalize(r).replace(/^([/\\]\.\.[/\\])+/,""),a=l.join(t,o);if(!a.startsWith(t)){e.statusCode=403,e.setHeader("content-type","application/json"),e.end(JSON.stringify({error:"Forbidden"}));return}h.stat(a,(n,i)=>{if(!n&&i.isFile()){e.setHeader("content-type",q(a)),V(e,r),e.setHeader("content-length",String(i.size)),h.createReadStream(a).pipe(e);return}h.readFile(l.join(t,"index.html"),(c,s)=>{if(c){e.statusCode=404,e.setHeader("content-type","application/json"),e.end(JSON.stringify({error:"Not found"}));return}e.setHeader("content-type","text/html"),e.setHeader("cache-control","no-cache"),e.end(s)})})}function q(e){return e.endsWith(".js")?"text/javascript":e.endsWith(".css")?"text/css":e.endsWith(".html")?"text/html":e.endsWith(".svg")?"image/svg+xml":e.endsWith(".json")?"application/json":"application/octet-stream"}function U(e){for(let r=e.length-1;r>=0;r--){const t=e[r].source;if(R(t))return t}return null}function K(e){const r=Number(e??"100");return!Number.isFinite(r)||r<=0?100:Math.min(Math.floor(r),500)}
13
+ `)});e.inflightRefresher?.refreshNow(),e.terminalRefresher?.onSubscriberJoin(),e.updatesRefresher?.onSubscriberJoin(),t.on("close",()=>{clearInterval(a),p()})}function G(t,n,e){if(n==="/health"||n.startsWith("/webhooks/orchestrate/"))return!0;if(t.method!=="GET")return!1;if((t.headers.accept??"").includes("text/html"))return!0;if(!e.staticDir)return!1;const r=d.normalize(n).replace(/^([/\\]\.\.[/\\])+/,""),i=d.join(e.staticDir,r);return i.startsWith(e.staticDir)&&h.existsSync(i)&&h.statSync(i).isFile()}function _(t,n){t.setHeader("cache-control",n.startsWith("/assets/")?"public, max-age=31536000, immutable":"no-cache")}function V(t,n,e){const r=d.normalize(n).replace(/^([/\\]\.\.[/\\])+/,""),i=d.join(e,r);if(!i.startsWith(e)){t.statusCode=403,t.setHeader("content-type","application/json"),t.end(JSON.stringify({error:"Forbidden"}));return}h.stat(i,(s,o)=>{if(!s&&o.isFile()){t.setHeader("content-type",U(i)),_(t,n),t.setHeader("content-length",String(o.size)),h.createReadStream(i).pipe(t);return}h.readFile(d.join(e,"index.html"),(c,a)=>{if(c){t.statusCode=404,t.setHeader("content-type","application/json"),t.end(JSON.stringify({error:"Not found"}));return}t.setHeader("content-type","text/html"),t.setHeader("cache-control","no-cache"),t.end(a)})})}function U(t){return t.endsWith(".js")?"text/javascript":t.endsWith(".css")?"text/css":t.endsWith(".html")?"text/html":t.endsWith(".svg")?"image/svg+xml":t.endsWith(".png")?"image/png":t.endsWith(".json")?"application/json":t.endsWith(".webmanifest")?"application/manifest+json":"application/octet-stream"}function K(t){for(let n=t.length-1;n>=0;n--){const e=t[n].source;if(R(e))return e}return null}function Q(t){const n=Number(t??"100");return!Number.isFinite(n)||n<=0?100:Math.min(Math.floor(n),500)}
@@ -33,3 +33,20 @@ export declare function scheduleBootstrapInjection(deps: Pick<WeaveServerDeps, '
33
33
  * 路由与编排引擎的「目标会话没开就拉起来」共用这一份:判据、能力面取法与错误码只有一处。
34
34
  */
35
35
  export declare function openSessionTerminal(deps: SessionOpenDeps, sessionId: string, target?: string): Promise<SessionOpenResult>;
36
+ /** ensureOpen 的返回(与编排引擎 `deps.ensureOpen` 的形状逐字一致,两边共用一份)。 */
37
+ export type EnsureOpenResult = {
38
+ ok: true;
39
+ ack?: 'session-start' | 'registry';
40
+ } | {
41
+ ok: false;
42
+ error: string;
43
+ };
44
+ /**
45
+ * 「判死会话先拉起再投递」的共享工厂:`openSessionTerminal` spawn + 等「真进了
46
+ * 会话」(SessionStart 事件 id 超过拉起前基线;注册表出现 pid 只算弱信号)。
47
+ * 编排引擎的「目标会话没开就拉起来」用这一份——判据、预算、错误口径只有一处。
48
+ * **单飞**:同一会话被并发投递时只拉起一次(后到的搭同一班车的结果)。
49
+ */
50
+ export declare function createEnsureOpen(deps: SessionOpenDeps & {
51
+ livenessOf?: () => Map<string, boolean>;
52
+ }): (sessionId: string) => Promise<EnsureOpenResult>;
@@ -1 +1 @@
1
- import{stat as k}from"node:fs/promises";import{isHarness as w}from"@weavecode/core";import{readDaemonSettings as g}from"./settings.js";import{defaultProjectOpener as S,terminalBackendFor as v}from"./opener.js";import{messagingSurfaceFor as y}from"../surfaces.js";const p=8e3,T=11e3,E=14e3;export function transcriptState(e,r){return e!==!1?e:r===!0?!1:null}function h(e,r,s,t){!t||y(r).paneEnvSource!=="launch"||e.messageDeliverer?.notePaneEnv(s,t.env)}export function scheduleBootstrapInjection(e,r,s){const t=e.terminal;t&&(async()=>{await new Promise(n=>setTimeout(n,p));const i=await t.locatePane?.(r.env).catch(()=>null)??null;if(!i)return;const o=async()=>{try{await t.sendText(i,s)}catch{return}};await o(),setTimeout(()=>{t.sendKeys(i,"\r").catch(()=>{})},T-p),setTimeout(()=>{o()},E-p)})()}export async function openSessionTerminal(e,r,s){if(!e.hookSessions)return{ok:!1,status:503,error:"Hooks subsystem unavailable"};const t=e.hookSessions.getBySessionId(r);if(!t)return{ok:!1,status:404,error:"Session not found"};if(!e.hookEvents)return{ok:!1,status:503,error:"Hook ingestion unavailable"};const i=e.hookEvents.listBySession(r,1),o=i[i.length-1]?.source;if(!w(o))return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};const n=e.harnesses?.get(o)?.resume;if(!n?.supported||!n.openArgs)return{ok:!1,status:501,error:`Harness "${o}" does not support interactive resume`};if(!t.projectId)return{ok:!1,status:400,error:"Session is not bound to a project"};const u=e.projects?.getById(t.projectId);if(!u)return{ok:!1,status:404,error:"Project not found"};const f=e.sessionProbe?.transcriptPresent(r)??null;if(transcriptState(f,e.hookSessions.hasRunOf(r))===!1)return{ok:!1,status:409,error:"Session transcript is missing \u2014 nothing to resume"};const l=e.opener??S;try{if(!(await k(u.path)).isDirectory())throw new Error(`Not a directory: ${u.path}`);const a=await g(),m=[n.bin,...n.launchArgs??[],...n.openArgs(r)];if(s){if(!v(a.terminal).enumerable)throw new Error(`Terminal preset "${a.terminal.preset}" cannot attach to a chosen pane \u2014 pick wezterm, wt or Terminal.app in settings`);const c=l.runInTerminalAt;if(!c)throw new Error("Targeted attach is unavailable");const d=await c(u.path,m,s,a.terminal);h(e,o,r,d)}else{const c=await l.runInTerminal(u.path,m,a.terminal);h(e,o,r,c)}return setTimeout(()=>{e.terminalRefresher?.refreshNow()},600),{ok:!0,sessionId:r,command:m.join(" "),cwd:u.path,...s?{target:s}:{}}}catch(a){return{ok:!1,status:400,error:a instanceof Error?a.message:"Open failed"}}}
1
+ import{stat as g}from"node:fs/promises";import{isHarness as w}from"@weavecode/core";import{readDaemonSettings as S}from"./settings.js";import{defaultProjectOpener as T,terminalBackendFor as y}from"./opener.js";import{combinedLivenessOf as E}from"./liveness.js";import{messagingSurfaceFor as O}from"../surfaces.js";const h=8e3,P=11e3,b=14e3;export function transcriptState(e,r){return e!==!1?e:r===!0?!1:null}function k(e,r,s,t){!t||O(r).paneEnvSource!=="launch"||e.messageDeliverer?.notePaneEnv(s,t.env)}export function scheduleBootstrapInjection(e,r,s){const t=e.terminal;t&&(async()=>{await new Promise(a=>setTimeout(a,h));const o=await t.locatePane?.(r.env).catch(()=>null)??null;if(!o)return;const n=async()=>{try{await t.sendText(o,s)}catch{return}};await n(),setTimeout(()=>{t.sendKeys(o,"\r").catch(()=>{})},P-h),setTimeout(()=>{n()},b-h)})()}export async function openSessionTerminal(e,r,s){if(!e.hookSessions)return{ok:!1,status:503,error:"Hooks subsystem unavailable"};const t=e.hookSessions.getBySessionId(r);if(!t)return{ok:!1,status:404,error:"Session not found"};if(!e.hookEvents)return{ok:!1,status:503,error:"Hook ingestion unavailable"};const o=e.hookEvents.listBySession(r,1),n=o[o.length-1]?.source;if(!w(n))return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};const a=e.harnesses?.get(n)?.resume;if(!a?.supported||!a.openArgs)return{ok:!1,status:501,error:`Harness "${n}" does not support interactive resume`};if(!t.projectId)return{ok:!1,status:400,error:"Session is not bound to a project"};const i=e.projects?.getById(t.projectId);if(!i)return{ok:!1,status:404,error:"Project not found"};const p=e.sessionProbe?.transcriptPresent(r)??null;if(transcriptState(p,e.hookSessions.hasRunOf(r))===!1)return{ok:!1,status:409,error:"Session transcript is missing \u2014 nothing to resume"};const c=e.opener??T;try{if(!(await g(i.path)).isDirectory())throw new Error(`Not a directory: ${i.path}`);const u=await S(),m=[a.bin,...a.launchArgs??[],...a.openArgs(r)];if(s){if(!y(u.terminal).enumerable)throw new Error(`Terminal preset "${u.terminal.preset}" cannot attach to a chosen pane \u2014 pick wezterm, wt or Terminal.app in settings`);const l=c.runInTerminalAt;if(!l)throw new Error("Targeted attach is unavailable");const v=await l(i.path,m,s,u.terminal);k(e,n,r,v)}else{const l=await c.runInTerminal(i.path,m,u.terminal);k(e,n,r,l)}return setTimeout(()=>{e.terminalRefresher?.refreshNow()},600),{ok:!0,sessionId:r,command:m.join(" "),cwd:i.path,...s?{target:s}:{}}}catch(f){return{ok:!1,status:400,error:f instanceof Error?f.message:"Open failed"}}}export function createEnsureOpen(e){const r=new Map,s=async t=>{if(!e.hookEvents)return{ok:!1,error:"Hook ingestion unavailable"};const o=e.hookEvents.listBySession(t,1).at(-1)?.id??0,n=await openSessionTerminal(e,t);if(!n.ok)return{ok:!1,error:n.error};let a=!1;for(let i=0;i<60;i++){if(e.hookEvents.listBySession(t,20).some(c=>c.id>o&&c.eventType==="SessionStart"))return{ok:!0,ack:"session-start"};(e.livenessOf?.()??E()).get(t)===!0&&(a=!0),await new Promise(c=>setTimeout(c,250))}return a?{ok:!0,ack:"registry"}:{ok:!1,error:"session did not report ready within 15s"}};return t=>{const o=r.get(t);if(o)return o;const n=s(t).finally(()=>r.delete(t));return r.set(t,n),n}}
@@ -1 +1 @@
1
- import{closeSync as h,openSync as u,readSync as f,statSync as a}from"node:fs";import{bareModelName as i,codexInterruptMarkerAt as d,currentContextTokensAt as p,currentEffortAt as m,currentModelAt as k,currentModeAt as w,interruptMarkerAt as M,switchedModelOf as O}from"@weavecode/harness";import{HARNESS_SESSION_CONTROL as S,isHarness as x}from"@weavecode/core";const b=64*1024,y={model:null,mode:null,effort:null,contextTokens:null};export function readTail(l,t=b){try{const e=a(l).size,s=Math.max(0,e-t),n=u(l,"r");try{const r=Buffer.alloc(e-s);return f(n,r,0,r.length,s),r.toString("utf8")}finally{h(n)}}catch{return null}}export function dbTranscriptPathResolver(l){return t=>{try{const e=JSON.parse(l.listBySession(t,1)[0]?.payload??"");return typeof e.transcriptPath=="string"&&e.transcriptPath?e.transcriptPath:null}catch{return null}}}export function dbModelFactResolver(l,t){return e=>{const s=t(e),n=s&&x(s)?S[s].modelFactEvents:[];if(n.length===0)return null;const r=l.listBySession(e,1,void 0,n),o=r[r.length-1];if(!o)return null;try{const c=JSON.parse(o.payload).raw;return O(o.eventType,c)}catch{return null}}}function T(l){const t=M(l),e=d(l);return t===null?e:e===null?t:Math.max(t,e)}export class SessionProbe{fallbackPath;fallbackSwitch;constructor(t,e){this.fallbackPath=t,this.fallbackSwitch=e}paths=new Map;marks=new Map;known=new Map;switched=new Map;probed=new Set;efforts=new Map;modes=new Map;noteTranscript(t,e){e&&this.paths.set(t,e)}pathOf(t){const e=this.paths.get(t);if(e)return e;const s=this.fallbackPath?.(t)??null;return s&&this.paths.set(t,s),s}transcriptPathOf(t){return this.pathOf(t)}forget(t){this.paths.delete(t),this.known.delete(t),this.switched.delete(t),this.probed.delete(t),this.efforts.delete(t),this.modes.delete(t)}noteEffort(t,e){this.efforts.set(t,e)}currentEffort(t){return this.efforts.get(t)??this.latched(t).effort}currentContextTokens(t){return this.latched(t).contextTokens}noteModel(t,e){const s=this.pathOf(t);this.switched.set(t,{stale:s?this.factsOf(s).model:null,model:e})}sessionStarted(t,e){this.known.delete(t),this.switched.delete(t),this.probed.delete(t),e&&this.noteModel(t,e)}transcriptPresent(t){const e=this.pathOf(t);return e?this.factsOf(e).size>0:null}interruptedAt(t,e){const s=this.pathOf(t);if(!s)return null;const n=this.factsOf(s).markerAt;if(n===null)return null;const r=Date.parse(e);return Number.isFinite(r)&&n>r?n:null}currentModel(t){return this.latched(t).model}noteMode(t,e){this.modes.set(t,e)}currentMode(t){return this.modes.get(t)??this.latched(t).mode}latched(t){const e=this.pathOf(t),s=e?this.factsOf(e):y,n=this.known.get(t),r={model:this.switchedModel(t,s.model)??n?.model??null,mode:s.mode??n?.mode??null,effort:s.effort??n?.effort??null,contextTokens:s.contextTokens??n?.contextTokens??null};return(!n||n.model!==r.model||n.mode!==r.mode||n.effort!==r.effort||n.contextTokens!==r.contextTokens)&&this.known.set(t,r),r}switchedModel(t,e){const s=this.switchOf(t,e);return s&&e===s.stale?s.model:e}switchOf(t,e){const s=this.switched.get(t);if(s||!e||this.probed.has(t))return s;this.probed.add(t);const n=this.fallbackSwitch?.(t);if(!n||n.from===null||i(n.from)!==i(e))return;const r={stale:e,model:n.to};return this.switched.set(t,r),r}factsOf(t){let e;try{e=a(t).size}catch{return{size:-1,markerAt:null,model:null,mode:null,effort:null,contextTokens:null}}const s=this.marks.get(t);if(s&&s.size===e)return s;const n=readTail(t),r={size:e,markerAt:n===null?null:T(n),model:n===null?null:k(n),mode:n===null?null:w(n),effort:n===null?null:m(n),contextTokens:n===null?null:p(n)};return this.marks.set(t,r),r}}
1
+ import{closeSync as u,openSync as f,readSync as i,statSync as c}from"node:fs";import{bareModelName as a,codexInterruptMarkerAt as d,currentContextTokensAt as p,currentEffortAt as m,currentModelAt as k,currentModeAt as w,interruptMarkerAt as M,switchedModelOf as O}from"@weavecode/harness";import{HARNESS_SESSION_CONTROL as S,isHarness as x}from"@weavecode/core";const b=64*1024,y={model:null,mode:null,effort:null,contextTokens:null};export function readTail(o,t=b){try{const e=c(o).size,r=Math.max(0,e-t),n=f(o,"r");try{const l=Buffer.alloc(e-r);return i(n,l,0,l.length,r),l.toString("utf8")}finally{u(n)}}catch{return null}}export function dbTranscriptPathResolver(o){return t=>{try{const e=JSON.parse(o.listBySession(t,1)[0]?.payload??"");return typeof e.transcriptPath=="string"&&e.transcriptPath?e.transcriptPath:null}catch{return null}}}export function dbModelFactResolver(o,t){return e=>{const r=t(e),n=r&&x(r)?S[r].modelFactEvents:[];if(n.length===0)return null;const l=o.listBySession(e,1,void 0,n),s=l[l.length-1];if(!s)return null;try{const h=JSON.parse(s.payload).raw;return O(s.eventType,h)}catch{return null}}}function T(o){const t=M(o),e=d(o);return t===null?e:e===null?t:Math.max(t,e)}export class SessionProbe{fallbackPath;fallbackSwitch;constructor(t,e){this.fallbackPath=t,this.fallbackSwitch=e}paths=new Map;marks=new Map;known=new Map;switched=new Map;probed=new Set;efforts=new Map;modes=new Map;noteTranscript(t,e){e&&this.paths.set(t,e)}pathOf(t){const e=this.paths.get(t);if(e)return e;const r=this.fallbackPath?.(t)??null;return r&&this.paths.set(t,r),r}transcriptPathOf(t){return this.pathOf(t)}forget(t){this.paths.delete(t),this.known.delete(t),this.switched.delete(t),this.probed.delete(t),this.efforts.delete(t),this.modes.delete(t)}noteEffort(t,e){this.efforts.set(t,e)}currentEffort(t){return this.efforts.get(t)??this.latched(t).effort}currentContextTokens(t){return this.latched(t).contextTokens}noteModel(t,e){const r=this.pathOf(t);this.switched.set(t,{stale:r?this.factsOf(r).model:null,model:e})}sessionStarted(t,e){this.known.delete(t),this.switched.delete(t),this.probed.delete(t),e&&this.noteModel(t,e)}transcriptPresent(t){const e=this.pathOf(t);return e?this.factsOf(e).size>0:null}interruptedAt(t,e){const r=this.pathOf(t);if(!r)return null;const n=this.factsOf(r).markerAt;if(n===null)return null;const l=Date.parse(e);return Number.isFinite(l)&&n>l?n:null}currentModel(t){return this.latched(t).model}noteMode(t,e){this.modes.set(t,e)}currentMode(t){return this.modes.get(t)??this.latched(t).mode}latched(t){const e=this.pathOf(t),r=e?this.factsOf(e):y,n=this.known.get(t),l={model:this.switchedModel(t,r.model)??n?.model??null,mode:r.mode??n?.mode??null,effort:r.effort??n?.effort??null,contextTokens:r.contextTokens??n?.contextTokens??null};return(!n||n.model!==l.model||n.mode!==l.mode||n.effort!==l.effort||n.contextTokens!==l.contextTokens)&&this.known.set(t,l),l}switchedModel(t,e){const r=this.switchOf(t,e);return r&&e===r.stale?r.model:e}switchOf(t,e){const r=this.switched.get(t);if(r||!e||this.probed.has(t))return r;this.probed.add(t);const n=this.fallbackSwitch?.(t);if(!n||n.from===null||a(n.from)!==a(e))return;const l={stale:e,model:n.to};return this.switched.set(t,l),l}factsOf(t){let e;try{e=c(t).size}catch{return{size:-1,markerAt:null,model:null,mode:null,effort:null,contextTokens:null}}const r=this.marks.get(t);if(r&&r.size===e)return r;const n=readTail(t),l={size:e,markerAt:n===null?null:T(n),model:n===null?null:k(n),mode:n===null?null:w(n),effort:n===null?null:m(n),contextTokens:n===null?null:p(n)};return this.marks.set(t,l),l}}
@@ -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 b}from"../db/db.js";import{getDbPath as f}from"../db/paths.js";import{DEFAULT_BIND_HOST as p}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:p,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 U=50,I=2e5;function A(e){const n=e??{},o=new Set,r=[];for(const a of Array.isArray(n.profiles)?n.profiles:[]){const s=a??{};if(!(typeof s.id!="string"||s.id===""||o.has(s.id))&&!(typeof s.name!="string"||typeof s.head!="string")&&(o.add(s.id),r.push({id:s.id,name:s.name.trim()||`profile-${r.length+1}`,head:s.head.slice(0,I)}),r.length>=U))break}return{activeId:typeof n.activeId=="string"&&o.has(n.activeId)?n.activeId:null,profiles:r}}function h(e){const n=e??{},o=n.terminal??{},r=n.hooks??{},a=n.events??{},s=n.sessions??{},E=n.startup??{},l=n.server??{},u=n.ai??{},m=n.decision??{},D=A(n.htmlExport),y=Number.isInteger(a.retentionDays)&&a.retentionDays>=1?a.retentionDays:DEFAULT_EVENTS_SETTINGS.retentionDays,S=Number.isInteger(s.idleDays)&&s.idleDays>=1?s.idleDays:DEFAULT_SESSIONS_SETTINGS.idleDays;return{terminal:{preset:ALL_TERMINAL_PRESETS.includes(o.preset)?o.preset:DEFAULT_TERMINAL_SETTINGS.preset,customCommand:typeof o.customCommand=="string"?o.customCommand:""},locale:resolveLocale(n.locale),hooks:{enabled:typeof r.enabled=="boolean"?r.enabled:DEFAULT_HOOKS_SETTINGS.enabled},events:{retentionDays:y},sessions:{idleDays:S},startup:{launchOnLogin:typeof E.launchOnLogin=="boolean"?E.launchOnLogin:DEFAULT_STARTUP_SETTINGS.launchOnLogin},server:{bindHost:typeof l.bindHost=="string"&&l.bindHost.trim()!==""?l.bindHost.trim():DEFAULT_SERVER_SETTINGS.bindHost,tlsPort:v(l.tlsPort)},ai:{baseUrl:typeof u.baseUrl=="string"?u.baseUrl.trim():"",model:typeof u.model=="string"?u.model.trim():""},decision:{baseUrl:typeof m.baseUrl=="string"?m.baseUrl.trim():"",model:typeof m.model=="string"?m.model.trim():""},htmlExport:D}}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 i=null,d=null;export function setDaemonSettingsDb(e){i=e,d=null}function g(e){if(i)return e(i);const n=b(f());try{return e(n)}finally{n.close()}}function N(e){const n=e.prepare("SELECT key, value FROM settings").all();return new Map(n.map(o=>[o.key,o.value]))}function O(e){return h({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)??""}}:{},...T(e.get(t.htmlExport))!=null?{htmlExport:T(e.get(t.htmlExport))}:{}})}function T(e){if(!e)return null;try{const n=JSON.parse(e);return n!=null&&typeof n=="object"?n:null}catch{return null}}function _(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??p],[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 P(e,n){const o=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,a]of n)o.run(r,a);e.exec("COMMIT")}catch(r){throw e.exec("ROLLBACK"),r}}function c(){try{return g(e=>O(N(e)))}catch{return DEFAULT_DAEMON_SETTINGS}}export async function readDaemonSettings(){return c()}export function readDaemonSettingsSync(){return c()}export function readHooksEnabled(){const e=d;if(e&&e.db===i)return e.value;const n=c().hooks.enabled;return d={db:i,value:n},n}export async function writeDaemonSettings(e){const n=h(e);return g(o=>P(o,_(n))),d=null,n}
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
- export class SnapshotRefresher{snapshot;bus;options;timer;lastFingerprint=null;constructor(t,s,i){this.snapshot=t,this.bus=s,this.options=i}start(){this.timer||(this.timer=setInterval(()=>this.tick(),this.options.intervalMs??15e3))}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}tick(){if(!(this.options.shouldRun&&!this.options.shouldRun()))try{const t=this.snapshot(),s=JSON.stringify(t);if(s===this.lastFingerprint)return;this.lastFingerprint=s,this.bus.emit(this.options.invalidateOnly?{key:this.options.key}:{key:this.options.key,payload:t})}catch{}}}
1
+ export class SnapshotRefresher{snapshot;bus;options;timer;lastFingerprint=null;constructor(t,i,s){this.snapshot=t,this.bus=i,this.options=s}start(){this.timer||(this.timer=setInterval(()=>this.tick(),this.options.intervalMs??15e3))}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}tick(){if(!(this.options.shouldRun&&!this.options.shouldRun()))try{const t=this.snapshot(),i=JSON.stringify(t);if(i===this.lastFingerprint)return;this.lastFingerprint=i,this.bus.emit(this.options.invalidateOnly?{key:this.options.key}:{key:this.options.key,payload:t})}catch{}}}
@@ -1 +1 @@
1
- import{randomBytes as a}from"node:crypto";const u=1e3,c=6e4;export class SseHub{sources;epoch=a(4).toString("hex");seq=0;buffer=[];subs=new Set;detach=null;graceTimer=null;brokenAt=0;constructor(s){this.sources=s}subscribe(s){return this.subs.add(s),this.attach(),()=>{this.subs.delete(s),this.subs.size===0&&this.scheduleDetach()}}push(s){const r=++this.seq,i=JSON.stringify(s);this.buffer.push({seq:r,data:i}),this.buffer.length>u&&this.buffer.shift();const e={id:this.frameId(r),data:i};for(const t of this.subs)t(e)}replay(s){if(!s)return{frames:[],gap:!1};const[r,i]=s.split("-"),e=Number(i);if(r!==this.epoch||!Number.isInteger(e)||e<0)return{frames:[],gap:!0};const t=this.buffer[0]?.seq;return e<=this.brokenAt||t!==void 0&&e<t-1?{frames:[],gap:!0}:{frames:this.buffer.filter(h=>h.seq>e).map(h=>({id:this.frameId(h.seq),data:h.data})),gap:!1}}frameId(s){return`${this.epoch}-${s}`}attach(){if(this.graceTimer!==null&&(clearTimeout(this.graceTimer),this.graceTimer=null),this.detach)return;this.sources.onAttach?.();const s=[],{watch:r,hookBus:i,dataBus:e}=this.sources;r&&(s.push(r.subscribe(t=>this.push({type:"asset",...t}))),s.push(r.subscribeProjects(t=>this.push({type:"project",...t})))),i&&s.push(i.subscribe(t=>this.push({type:"hook",...t}))),e&&s.push(e.subscribe(t=>this.push({type:t.payload===void 0?"invalidate":"push",...t}))),this.detach=()=>{for(const t of s)t()}}scheduleDetach(){this.graceTimer!==null||!this.detach||(this.graceTimer=setTimeout(()=>{this.graceTimer=null,this.brokenAt=this.seq,this.detach?.(),this.detach=null},c),this.graceTimer.unref?.())}}
1
+ import{randomBytes as u}from"node:crypto";const a=1e3,c=6e4;export class SseHub{sources;epoch=u(4).toString("hex");seq=0;buffer=[];subs=new Set;detach=null;graceTimer=null;brokenAt=0;constructor(s){this.sources=s}subscribe(s){return this.subs.add(s),this.attach(),()=>{this.subs.delete(s),this.subs.size===0&&this.scheduleDetach()}}push(s){const i=++this.seq,r=JSON.stringify(s);this.buffer.push({seq:i,data:r}),this.buffer.length>a&&this.buffer.shift();const t={id:this.frameId(i),data:r};for(const e of this.subs)e(t)}replay(s){if(!s)return{frames:[],gap:!1};const[i,r]=s.split("-"),t=Number(r);if(i!==this.epoch||!Number.isInteger(t)||t<0)return{frames:[],gap:!0};const e=this.buffer[0]?.seq;return t<=this.brokenAt||e!==void 0&&t<e-1?{frames:[],gap:!0}:{frames:this.buffer.filter(h=>h.seq>t).map(h=>({id:this.frameId(h.seq),data:h.data})),gap:!1}}frameId(s){return`${this.epoch}-${s}`}attach(){if(this.graceTimer!==null&&(clearTimeout(this.graceTimer),this.graceTimer=null),this.detach)return;this.sources.onAttach?.();const s=[],{watch:i,hookBus:r,dataBus:t}=this.sources;i&&(s.push(i.subscribe(e=>this.push({type:"asset",...e}))),s.push(i.subscribeProjects(e=>this.push({type:"project",...e})))),r&&s.push(r.subscribe(e=>this.push({type:"hook",...e}))),t&&s.push(t.subscribe(e=>this.push({type:e.payload===void 0?"invalidate":"push",...e}))),this.detach=()=>{for(const e of s)e()}}scheduleDetach(){this.graceTimer!==null||!this.detach||(this.graceTimer=setTimeout(()=>{this.graceTimer=null,this.brokenAt=this.seq,this.detach?.(),this.detach=null},c),this.graceTimer.unref?.())}}
@@ -1 +1 @@
1
- import ws from"node:http";import{openDatabase as gs}from"../db/db.js";import{ProjectRepository as Ss}from"../repositories/projects.js";import{HookEventRepository as bs}from"../repositories/hook-events.js";import{LibraryRepository as ys}from"../repositories/libraries.js";import{HookRuleRepository as as}from"../repositories/hook-rules.js";import{HookDispatchRepository as vs}from"../repositories/hook-dispatches.js";import{PluginStateRepository as P}from"../repositories/plugin-states.js";import{SessionRepository as Rs}from"../repositories/sessions.js";import{createRuntimeRegistry as ks}from"@weavecode/harness";import{TERMINAL_LOCATOR_ENV_KEYS as Es,isHarness as Q}from"@weavecode/core";import{messagingSurfaceFor as Ds,narrationSurfaceFor as Ts}from"../surfaces.js";import{syntheticSessionIds as Ps}from"../hooks/synthetic-sessions.js";import{createEdgeExtract as Is}from"../hooks/edge-extract.js";import{startSessionSweeper as Os}from"../hooks/session-sweeper.js";import{startStatuslineCacheSweeper as Cs}from"../statusline/cache-sweeper.js";import{readStatuslineFacts as As}from"../statusline/manager.js";import{wireHookFilePipeline as Hs}from"./hook-pipeline.js";import{ensureBuiltinMarket as Bs,builtinMarketDir as Fs}from"../market/builtin.js";import{HookRuleRegistry as Ms}from"../hooks/registry.js";import{HookDispatcher as js}from"../hooks/dispatcher.js";import{HookEventBus as Ls}from"../hooks/bus.js";import{ResumeRunner as Ns}from"../hooks/resume-runner.js";import{HeadlessRunner as Us}from"../hooks/headless-runner.js";import{MessageDeliverer as _s}from"../hooks/message-deliverer.js";import{QuestionTracker as xs}from"../hooks/question-tracker.js";import{SideQuestionRepository as Ws}from"../repositories/side-questions.js";import{claimSideAnswer as $s}from"../hooks/side-questions.js";import{DashboardRateCache as qs}from"../hooks/dashboard-rate.js";import{startDashboardPusher as Qs}from"./dashboard-pusher.js";import{startPromptFlusher as Ks}from"../hooks/prompt-flusher.js";import{SessionWatchRepository as Gs}from"../repositories/session-watches.js";import{PushSubscriptionRepository as Js}from"../repositories/push-subscriptions.js";import{UploadRepository as Vs}from"../repositories/uploads.js";import{defaultUploadSessions as Ys}from"./upload-sessions.js";import{PushNotifier as zs}from"../hooks/push-notify.js";import{OrchestrationRepository as Xs,OrchestrationRunRepository as Zs}from"../repositories/orchestrations.js";import{WatchEngine as se}from"../hooks/watch-engine.js";import{OrchestrationEngine as ee,createForkConditionJudge as re}from"../hooks/orchestration-engine.js";import{createDecisionConditionJudge as oe}from"../hooks/decision-judge.js";import{readDecisionKey as te}from"./decision-config.js";import{openSessionTerminal as ne}from"./session-open.js";import{loadAllPlugins as ie}from"../hooks/plugin-loader.js";import{ToolkitService as ae}from"../hooks/toolkit.js";import{WatchService as le}from"../watch/watch-service.js";import{SyncScheduler as pe}from"../watch/sync-scheduler.js";import{FingerprintCache as me}from"../install/fingerprint.js";import{detectProjectUpdateCounts as ce}from"../install/updates.js";import{weaveRequestHandler as ue}from"./server.js";import{startTlsServer as fe}from"./tls.js";import{DataBus as de}from"./data-bus.js";import{TerminalTopologyRefresher as he}from"./terminal-topology-refresher.js";import{SnapshotRefresher as K}from"./snapshot-refresher.js";import{SessionProbe as we,dbModelFactResolver as ge,dbTranscriptPathResolver as Se}from"./session-probe.js";import{NarrationWatcher as be}from"./narration-watcher.js";import{InflightCountsRefresher as ye}from"./inflight-counts-refresher.js";import{ProjectUpdatesRefresher as ve}from"./project-updates-refresher.js";import{pidAliveOf as Re}from"./claude-liveness.js";import{combinedLivenessOf as y}from"./liveness.js";import{promptTerminalChannel as ls,readTerminalCounts as ke}from"./opener.js";import{DEFAULT_BIND_HOST as Ee}from"./port.js";import{readDaemonState as De,writeDaemonState as Te}from"./state.js";import{ensureDataLayout as Pe}from"../db/layout.js";import{pruneFileIndexes as Ie}from"./project-files.js";import{pruneInstallTmp as Oe}from"../hooks/plugin-installer.js";import{readDaemonSettingsSync as v,setDaemonSettingsDb as Ce,DEFAULT_SERVER_SETTINGS as Ae}from"./settings.js";import{AuthService as He}from"./dashboard-auth.js";import{syncLaunchOnLogin as Be}from"./auto-start.js";import{resolveStaticDir as Fe}from"./static.js";delete process.env.CLAUDE_CODE_CHILD_SESSION;for(const c of Es)delete process.env[c];export function startDaemon(){Pe();const c=De();c||(console.error("Daemon state not found. Run `weave daemon start` first."),process.exit(1));const o=gs();Ce(o);const R=v().server?.bindHost??Ee,I=v().server?.tlsPort??Ae.tlsPort,O=new He;O.initialPassword&&console.log(`[weave] initial dashboard password: ${O.initialPassword}`);const t=new Ss(o);Ie(t.list().map(s=>s.id)),Oe();const a=new bs(o),m=new ys(o),d=ks(),ps=d.byCapability("events").flatMap(s=>s.events??[]),k=new Ms(new as(o)),E=new vs(o),r=new Rs(o),n=new Ls,C={getHandler:()=>{},getConfig:()=>({})};let f;const A={list:()=>f?.list()??[],setPluginEnabled:(s,e)=>f?.setPluginEnabled(s,e)??!1,reloadAll:async()=>{await f?.reloadAll()},rescan:async()=>{await f?.rescanRoots(t.list(),m)}},ms=new ae({projects:t,states:new P(o),plugins:A,libraries:m}),H={run:null},G=new js({registry:k,dispatches:E,bus:n,projects:t,sessions:r,plugins:C,pluginStates:new P(o),classify:s=>H.run?H.run(s):Promise.resolve(null),sessionTitleOf:async s=>{const e=a.listBySession(s,1).at(-1)?.source;return Q(e)?d.get(e)?.titles?.sessionTitleOf(s)??null:null}});Bs({libraries:m}).then(s=>(s.error?console.error(`[weave] builtin market unavailable: ${s.error}`):s.changed&&console.log(`[weave] builtin market ${s.form==="link"?"linked":"copied"} -> ${Fs(m.dataRoot)}`),ie({rules:new as(o),registry:k,states:new P(o),bus:n,libraries:m},t.list()))).then(({loader:s})=>{f=s,C.getHandler=(e,i)=>s.getHandler(e,i),C.getConfig=e=>s.getConfig(e),s.watchRoots()}).catch(s=>{console.error("[weave] plugin load failed:",s instanceof Error?s.message:s)});const D=new Us,cs=new Ns({dispatches:E,sessions:r,projects:t,bus:n,resumeSpec:d.get("claude")?.resume,headless:D}),p=new _s({sessions:r,projects:t,hookEvents:a,bus:n,headless:D,terminal:ls(()=>v().terminal),blockedByQuestion:s=>h.get(s)!=null,livenessOf:y,sideAnswerStore:{answerById:(s,e,i)=>{L.answerById(s,e,i)}}});Ks(p);const B=new Gs(o),F=new se({watches:B,deliverer:p,sessions:r,bus:n,livenessOf:y}),J=new Js(o),M=new Vs(o),us=new zs({subscriptions:J,sessions:r,bus:n}),j=new Xs(o),V=new Zs(o),u=new we(Se(a),ge(a,s=>r.getBySessionId(s)?.harness??null)),Y=new be(n,s=>Ts(Q(s)?s:"claude"),s=>u.transcriptPathOf(s),s=>r.livenessRowOf(s)?.harness??null);Y.start();const h=new xs({sessions:r,hookEvents:a,onPending:s=>{n.emit({kind:"question.pending",sessionId:s.sessionId,harness:s.harness,count:s.questions.length,at:s.at})},interruptedAt:s=>{const e=r.getBySessionId(s);return e?u.interruptedAt(s,r.lastMainEventAtOf(s)??e.lastSeenAt):null}});h.seedFromDb();const L=new Ws(o),z=new qs,N=Qs({rate:z,events:a,sessions:r,projects:t,bus:n}),X={repo:L,bus:n,settle:s=>{p.interrupt(s.sessionId)}},U=new le(t);U.start();const _=new me,l=new de,Z=new ve(()=>ce(t.list(),m.list(),_),l,n,()=>l.hasSubscribers()),ss=new pe(t,m,{cache:_,plugins:A,onSynced:()=>{Z.refreshNow(!0)}});ss.start();const w=new he(async()=>({counts:await ke(t.list()),terminals:await p.sessionTerminals()}),l,{shouldRun:()=>l.hasSubscribers(),graceMs:1e4});w.start();const x=new K(()=>{const s=y(),e={};for(const i of r.listWithCounts()){const b=Re(i,s);b!==null&&(e[i.sessionId]=b)}return{alive:e}},l,{key:"sessionLiveness",shouldRun:()=>l.hasSubscribers()});x.start();const W=new K(()=>{const s={};for(const e of r.listWithCounts()){if(e.turnOpen!==!0)continue;const i=u.interruptedAt(e.sessionId,r.lastMainEventAtOf(e.sessionId)??e.lastSeenAt);i!==null&&(s[e.sessionId]=i)}return{interrupted:s}},l,{key:"sessionInterrupt",intervalMs:5e3,shouldRun:()=>l.hasSubscribers()});W.start(),new K(()=>{const s={};for(const e of t.list())s[e.id]=As(e.path);return s},l,{key:"statusline",intervalMs:5e3,shouldRun:()=>l.hasSubscribers(),invalidateOnly:!0}).start();const fs=new ye(()=>p.listInflightCounts(),l,n);let es=null;const g=Is({sessions:r,projects:t,harnessOf:s=>{const e=a.listBySession(s,1),i=e[e.length-1]?.source;return Q(i)?i:null},surfaceFor:Ds,headless:D,onSyntheticChange:()=>es?.pushSyntheticSessions(Ps())});H.run=s=>g.run(s);const ds=oe({config:async()=>{const s=v().decision;if(!s?.baseUrl||!s.model)return null;const e=te();return e?{baseUrl:s.baseUrl,model:s.model,apiKey:e}:null},fallback:re({supports:s=>g.supports(s),extract:s=>g.run(s)})}),S=new ee({orchestrations:j,runs:V,deliverer:p,sessions:r,bus:n,supportsExtract:s=>g.supports(s),extract:s=>g.run(s),conditionJudge:ds,deferWhenUserPresent:!0,ensureOpen:async s=>{const e=a.listBySession(s,1).at(-1)?.id??0,i=await ne({hookSessions:r,hookEvents:a,projects:t,harnesses:d,sessionProbe:u,terminalRefresher:w},s);if(!i.ok)return i;let b=!1;for(let is=0;is<60;is++){if(a.listBySession(s,20).some(T=>T.id>e&&T.eventType==="SessionStart"))return{ok:!0,ack:"session-start"};y().get(s)===!0&&(b=!0),await new Promise(T=>setTimeout(T,250))}return b?{ok:!0,ack:"registry"}:{ok:!1,error:"session did not report ready within 15s"}}});S.rearm();const rs=setInterval(()=>S.cronTick(),3e4);rs.unref(),Os({sessions:r,events:a,dispatches:E,deliverer:p,watches:B,orchestrations:j,watchEngine:F,orchestrationEngine:S,questions:h,sideQuestions:L,probe:u,uploads:M,uploadSessions:Ys,livenessOf:y}),Cs();const $=Hs({projects:t,rules:k,sessions:r,bus:n,dispatcher:G,watchEngine:F,orchestrationEngine:S,messagePipe:p,questionTracker:h,sideQuestions:{onEvent:s=>{$s(X,s)}},sessionProbe:u,uploads:M,dashboardRate:z,terminalTopologyKick:()=>{w.refreshNow()}});es=$;const hs=Fe(),os=ue({projects:t,port:c.port,tlsPort:I,watch:U,hookEvents:a,adapters:ps,harnesses:d,libraries:m,fingerprintCache:_,staticDir:hs,hookRegistry:k,hookDispatches:E,hookSessions:r,hookBus:n,dataBus:l,terminalRefresher:w,interruptRefresher:W,livenessRefresher:x,sessionProbe:u,inflightRefresher:fs,updatesRefresher:Z,hookDispatcher:G,hookRunner:cs,messageDeliverer:p,terminal:ls(()=>v().terminal),uploads:M,questionTracker:h,sideQuestions:X,sessionWatches:B,watchEngine:F,orchestrations:j,orchestrationRuns:V,orchestrationEngine:S,pushSubscriptions:J,pushNotifier:us,onAttach:N.attach,dashboardRefresh:N.attach,hookPlugins:A,hookMirror:$.mirror,pluginStates:new P(o),toolkit:ms,auth:O}),q=ws.createServer(os);let ts=null;fe({port:I,bindHost:R,handler:os}).then(s=>{ts=s});const ns=()=>{f?.stopWatching(),w.stop(),x.stop(),W.stop(),ss.stop(),U.stop(),D.killAll(),clearInterval(rs),Y.stop(),N.stop(),q.close(),ts?.server.close();const s=setTimeout(()=>process.exit(0),3e3);$.stop().catch(()=>{}).finally(()=>{clearTimeout(s),process.exit(0)})};process.on("SIGTERM",ns),process.on("SIGINT",ns),q.listen(c.port,R,()=>{Te({...c,pid:process.pid,host:R,tlsPort:I}),Be()}),q.on("error",s=>{throw console.error(`[weave] daemon listen failed on ${R}:${c.port}: ${s.message}`),s})}
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,2 +1,2 @@
1
- import{existsSync as n,mkdirSync as a,readFileSync as o,rmSync as i,writeFileSync as c}from"node:fs";import m from"node:path";import{getDaemonStatePath as r}from"../db/paths.js";export function readDaemonState(){const t=r();if(!n(t))return null;try{return JSON.parse(o(t,"utf-8"))}catch{return null}}export function writeDaemonState(t){const e=r();a(m.dirname(e),{recursive:!0}),c(e,JSON.stringify(t,null,2)+`
2
- `,"utf-8")}export function clearDaemonState(){const t=r();n(t)&&i(t)}
1
+ import{existsSync as n,mkdirSync as o,readFileSync as i,rmSync as a,writeFileSync as c}from"node:fs";import m from"node:path";import{getDaemonStatePath as r}from"../db/paths.js";export function readDaemonState(){const t=r();if(!n(t))return null;try{return JSON.parse(i(t,"utf-8"))}catch{return null}}export function writeDaemonState(t){const e=r();o(m.dirname(e),{recursive:!0}),c(e,JSON.stringify(t,null,2)+`
2
+ `,"utf-8")}export function clearDaemonState(){const t=r();n(t)&&a(t)}
@@ -1 +1 @@
1
- import{existsSync as i}from"node:fs";import{fileURLToPath as e}from"node:url";import o from"node:path";export function resolveStaticDir(){const t=o.dirname(e(import.meta.url)),r=o.resolve(t,"../../web/dist");return i(r)?r:void 0}
1
+ import{existsSync as o}from"node:fs";import{fileURLToPath as i}from"node:url";import t from"node:path";export function resolveStaticDir(){const e=t.dirname(i(import.meta.url)),r=t.resolve(e,"../../web/dist");return o(r)?r:void 0}
@@ -1 +1 @@
1
- export class TerminalTopologyRefresher{snapshot;bus;options;timer;running=!1;last=null;lastFingerprint=null;startedAt=0;constructor(t,i,s={}){this.snapshot=t,this.bus=i,this.options=s}get lastSnapshot(){return this.last}start(){this.timer||(this.startedAt=Date.now(),this.timer=setInterval(()=>{this.tick()},this.options.intervalMs??3e4))}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}async refreshNow(){await this.run(!0,!0)}onSubscriberJoin(){this.last!==null&&(this.lastFingerprint=JSON.stringify(this.last),this.bus.emit({key:"terminalTopology",payload:this.last})),this.tick()}async tick(t=!1){await this.run(t,!1)}async run(t,i){if(this.running)return;const s=this.options.shouldRun;if(!(!t&&s&&!s())&&!(!i&&Date.now()-this.startedAt<(this.options.graceMs??0))){this.running=!0;try{const r=await this.snapshot(),a={...this.last?.terminals};for(const[h,o]of Object.entries(r.terminals))o!==void 0&&(a[h]=o);const n={counts:r.counts,terminals:a};this.last=n;const e=JSON.stringify(n);if(e===this.lastFingerprint)return;this.lastFingerprint=e,this.bus.emit({key:"terminalTopology",payload:n})}catch{}finally{this.running=!1}}}}
1
+ export class TerminalTopologyRefresher{snapshot;bus;options;timer;running=!1;last=null;lastFingerprint=null;startedAt=0;constructor(t,i,s={}){this.snapshot=t,this.bus=i,this.options=s}get lastSnapshot(){return this.last}start(){this.timer||(this.startedAt=Date.now(),this.timer=setInterval(()=>{this.tick()},this.options.intervalMs??3e4))}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}async refreshNow(){await this.run(!0,!0)}onSubscriberJoin(){this.last!==null&&(this.lastFingerprint=JSON.stringify(this.last),this.bus.emit({key:"terminalTopology",payload:this.last})),this.tick()}async tick(t=!1){await this.run(t,!1)}async run(t,i){if(this.running)return;const s=this.options.shouldRun;if(!(!t&&s&&!s())&&!(!i&&Date.now()-this.startedAt<(this.options.graceMs??0))){this.running=!0;try{const r=await this.snapshot(),e={...this.last?.terminals};for(const[l,o]of Object.entries(r.terminals))o!==void 0&&(e[l]=o);const n={counts:r.counts,terminals:e};this.last=n;const a=JSON.stringify(n);if(a===this.lastFingerprint)return;this.lastFingerprint=a,this.bus.emit({key:"terminalTopology",payload:n})}catch{}finally{this.running=!1}}}}
@@ -1 +1 @@
1
- import v from"node:https";import m from"node:os";import u from"node:path";import{existsSync as f,mkdirSync as w,readFileSync as l,writeFileSync as h}from"node:fs";import{X509Certificate as S,createPrivateKey as k}from"node:crypto";import{generate as $}from"selfsigned";import{getCertsDir as D}from"../db/paths.js";export function daemonCertsDir(){return D()}export function lanIps(){const e=new Set;for(const t of Object.values(m.networkInterfaces()))for(const r of t??[])r.family==="IPv4"&&!r.internal&&e.add(r.address);return[...e].sort()}export function accessUrls(e,t){const r=[{url:`http://localhost:${e}`,protocol:"http",scope:"local"}];t>0&&r.push({url:`https://localhost:${t}`,protocol:"https",scope:"local"});for(const o of lanIps())r.push({url:`http://${o}:${e}`,protocol:"http",scope:"lan"}),t>0&&r.push({url:`https://${o}:${t}`,protocol:"https",scope:"lan"});return r}function x(e){const t=e.subjectAltName??"",r=new Set;for(const o of t.split(",")){const n=o.trim().match(/^IP Address:(.+)$/);n&&r.add(n[1])}return r}export async function ensureDaemonCert(e=daemonCertsDir(),t={}){const r=t.ips??["127.0.0.1",...lanIps()],o=t.hostname??m.hostname(),n=t.now??new Date,s=u.join(e,"host.key"),a=u.join(e,"host.crt");if(f(s)&&f(a))try{const i=l(s,"utf-8"),p=new S(l(a,"utf-8")),y=r.every(d=>x(p).has(d));if(p.checkPrivateKey(k(i))&&Date.parse(p.validTo)>n.getTime()+7*864e5&&y)return{key:i,cert:l(a,"utf-8")}}catch{}const c=await $([{name:"commonName",value:"weave-daemon"}],{keySize:2048,notAfterDate:new Date(n.getTime()+825*864e5),extensions:[{name:"subjectAltName",altNames:[{type:2,value:"localhost"},{type:2,value:o},...r.map(i=>({type:7,ip:i}))]}]});return w(e,{recursive:!0}),h(s,c.private,{mode:384}),h(a,c.cert),{key:c.private,cert:c.cert}}export async function startTlsServer(e){if(e.port<=0)return null;try{const{key:t,cert:r}=await ensureDaemonCert(e.certDir),o=v.createServer({key:t,cert:r},e.handler);return await new Promise((n,s)=>{o.once("error",s),o.listen(e.port,e.bindHost,()=>{o.off("error",s),n()})}),{server:o,port:e.port}}catch(t){return console.warn(`[weave] https listener disabled (port ${e.port}): ${t instanceof Error?t.message:String(t)}`),null}}
1
+ import w from"node:https";import m from"node:os";import f from"node:path";import{existsSync as u,mkdirSync as d,readFileSync as l,writeFileSync as h}from"node:fs";import{X509Certificate as S,createPrivateKey as k}from"node:crypto";import{generate as $}from"selfsigned";import{getCertsDir as x}from"../db/paths.js";export function daemonCertsDir(){return x()}export function lanIps(){const t=new Set;for(const e of Object.values(m.networkInterfaces()))for(const r of e??[])r.family==="IPv4"&&!r.internal&&t.add(r.address);return[...t].sort()}export function accessUrls(t,e){const r=[{url:`http://localhost:${t}`,protocol:"http",scope:"local"}];e>0&&r.push({url:`https://localhost:${e}`,protocol:"https",scope:"local"});for(const o of lanIps())r.push({url:`http://${o}:${t}`,protocol:"http",scope:"lan"}),e>0&&r.push({url:`https://${o}:${e}`,protocol:"https",scope:"lan"});return r}function D(t){const e=t.subjectAltName??"",r=new Set;for(const o of e.split(",")){const n=o.trim().match(/^IP Address:(.+)$/);n&&r.add(n[1])}return r}export async function ensureDaemonCert(t=daemonCertsDir(),e={}){const r=e.ips??["127.0.0.1",...lanIps()],o=e.hostname??m.hostname(),n=e.now??new Date,s=f.join(t,"host.key"),c=f.join(t,"host.crt");if(u(s)&&u(c))try{const i=l(s,"utf-8"),p=new S(l(c,"utf-8")),y=r.every(v=>D(p).has(v));if(p.checkPrivateKey(k(i))&&Date.parse(p.validTo)>n.getTime()+7*864e5&&y)return{key:i,cert:l(c,"utf-8")}}catch{}const a=await $([{name:"commonName",value:"weave-daemon"}],{keySize:2048,notAfterDate:new Date(n.getTime()+825*864e5),extensions:[{name:"subjectAltName",altNames:[{type:2,value:"localhost"},{type:2,value:o},...r.map(i=>({type:7,ip:i}))]}]});return d(t,{recursive:!0}),h(s,a.private,{mode:384}),h(c,a.cert),{key:a.private,cert:a.cert}}export async function startTlsServer(t){if(t.port<=0)return null;try{const{key:e,cert:r}=await ensureDaemonCert(t.certDir),o=w.createServer({key:e,cert:r},t.handler);return await new Promise((n,s)=>{o.once("error",s),o.listen(t.port,t.bindHost,()=>{o.off("error",s),n()})}),{server:o,port:t.port}}catch(e){return console.warn(`[weave] https listener disabled (port ${t.port}): ${e instanceof Error?e.message:String(e)}`),null}}
@@ -1 +1 @@
1
- import{sendJson as e}from"./http.js";import{ToolkitError as h}from"../hooks/toolkit.js";export async function handleToolkitRoutes(n,o,r,a,f){if(!a.includes("/toolkit"))return!1;if(!r.toolkit)return e(o,503,{error:"Toolkit unavailable"}),!0;const l=t=>{if(t instanceof h){e(o,t.code==="not-found"?404:400,{error:t.message,code:t.code});return}e(o,400,{error:t instanceof Error?t.message:"Toolkit operation failed"})},u=a.match(/^\/projects\/(\d+)\/toolkit$/);if(u){if(n.method!=="GET")return e(o,405,{error:"Method not allowed"}),!0;try{e(o,200,await r.toolkit.list(Number(u[1])))}catch(t){l(t)}return!0}const i=a.match(/^\/projects\/(\d+)\/toolkit\/([^/]+)\/(enable|disable|uninstall)$/);if(i){if(n.method!=="POST")return e(o,405,{error:"Method not allowed"}),!0;const t=Number(i[1]),s=decodeURIComponent(i[2]),m=i[3],c=f.searchParams.get("source");try{const d=m==="enable"?await r.toolkit.enable(t,s,c??void 0):m==="disable"?await r.toolkit.disable(t,s,c??void 0):await r.toolkit.uninstall(t,s,c??void 0);r.dataBus?.emit({key:"toolkit"}),e(o,200,d)}catch(d){l(d)}return!0}const k=a.match(/^\/projects\/(\d+)\/toolkit\/legacy-copies\/cleanup$/);if(k){if(n.method!=="POST")return e(o,405,{error:"Method not allowed"}),!0;try{const t=await r.toolkit.cleanupLegacyCopies(Number(k[1]));r.dataBus?.emit({key:"toolkit"}),e(o,200,t)}catch(t){l(t)}return!0}return!1}
1
+ import{sendJson as e}from"./http.js";import{ToolkitError as h}from"../hooks/toolkit.js";export async function handleToolkitRoutes(a,o,r,i,m){if(!i.includes("/toolkit"))return!1;if(!r.toolkit)return e(o,503,{error:"Toolkit unavailable"}),!0;const l=t=>{if(t instanceof h){e(o,t.code==="not-found"?404:400,{error:t.message,code:t.code});return}e(o,400,{error:t instanceof Error?t.message:"Toolkit operation failed"})},s=i.match(/^\/projects\/(\d+)\/toolkit$/);if(s){if(a.method!=="GET")return e(o,405,{error:"Method not allowed"}),!0;try{e(o,200,await r.toolkit.list(Number(s[1])))}catch(t){l(t)}return!0}const n=i.match(/^\/projects\/(\d+)\/toolkit\/([^/]+)\/(enable|disable|uninstall)$/);if(n){if(a.method!=="POST")return e(o,405,{error:"Method not allowed"}),!0;const t=Number(n[1]),c=decodeURIComponent(n[2]),k=n[3],u=m.searchParams.get("source");try{const d=k==="enable"?await r.toolkit.enable(t,c,u??void 0):k==="disable"?await r.toolkit.disable(t,c,u??void 0):await r.toolkit.uninstall(t,c,u??void 0);r.dataBus?.emit({key:"toolkit"}),e(o,200,d)}catch(d){l(d)}return!0}const f=i.match(/^\/projects\/(\d+)\/toolkit\/legacy-copies\/cleanup$/);if(f){if(a.method!=="POST")return e(o,405,{error:"Method not allowed"}),!0;try{const t=await r.toolkit.cleanupLegacyCopies(Number(f[1]));r.dataBus?.emit({key:"toolkit"}),e(o,200,t)}catch(t){l(t)}return!0}return!1}
@@ -1 +1 @@
1
- import{randomUUID as p}from"node:crypto";import{open as o,mkdir as u,readFile as f,readdir as w,rm as c,stat as m,writeFile as l}from"node:fs/promises";import n from"node:path";import{getTmpDir as y}from"../db/paths.js";export const UPLOAD_SESSION_MAX_AGE_MS=1440*6e4;const d=/^[0-9a-f-]{36}$/;export class UploadSessions{dir;handles=new Map;constructor(e=n.join(y(),"uploads")){this.dir=e}part(e){return n.join(this.dir,`${e}.part`)}meta(e){return n.join(this.dir,`${e}.json`)}async begin(e){await u(this.dir,{recursive:!0});const t=p();await l(this.meta(t),JSON.stringify({name:e.name,mediaType:e.mediaType,size:e.size,received:0,dir:e.dir??null}),"utf8");const a=await o(this.part(t),"w");return await a.truncate(e.size),this.handles.set(t,a),{id:t,...e,received:0}}async get(e){if(!d.test(e))return null;try{const t=JSON.parse(await f(this.meta(e),"utf8"));if(typeof t.name!="string"||typeof t.mediaType!="string"||typeof t.size!="number")return null;const a=typeof t.received=="number"?t.received:(await m(this.part(e))).size;return{id:e,name:t.name,mediaType:t.mediaType,size:t.size,received:a,dir:typeof t.dir=="string"?t.dir:null}}catch{return null}}async append(e,t,a){const i=await this.get(e);if(!i)return{kind:"missing"};if(t!==i.received)return{kind:"conflict",received:i.received};if(i.received+a.length>i.size)return{kind:"overflow",received:i.received};let r=this.handles.get(e);r||(r=await o(this.part(e),"r+"),this.handles.set(e,r));const s=i.received+a.length;return await r.write(a,0,a.length,t),await r.truncate(s),await l(this.meta(e),JSON.stringify({name:i.name,mediaType:i.mediaType,size:i.size,received:s,dir:i.dir??null}),"utf8"),{kind:"ok",received:s}}async finish(e){const t=await this.get(e);return!t||t.received!==t.size?null:{name:t.name,mediaType:t.mediaType,file:this.part(e),size:t.size,dir:t.dir}}async abort(e){d.test(e)&&(await this.handles.get(e)?.close().catch(()=>{}),this.handles.delete(e),await c(this.part(e),{force:!0}),await c(this.meta(e),{force:!0}))}async sweep(e=UPLOAD_SESSION_MAX_AGE_MS,t=Date.now()){let a;try{a=await w(this.dir)}catch{return 0}let i=0;for(const r of a){if(!r.endsWith(".json"))continue;const s=r.slice(0,-5);if(d.test(s))try{const h=await m(this.meta(s));if(t-h.mtimeMs<e)continue;await this.abort(s),i++}catch{}}return i}}export const defaultUploadSessions=new UploadSessions;
1
+ import{randomUUID as u}from"node:crypto";import{open as o,mkdir as f,readFile as p,readdir as w,rm as d,stat as m,writeFile as l}from"node:fs/promises";import s from"node:path";import{getTmpDir as y}from"../db/paths.js";export const UPLOAD_SESSION_MAX_AGE_MS=1440*6e4;const c=/^[0-9a-f-]{36}$/;export class UploadSessions{dir;handles=new Map;constructor(e=s.join(y(),"uploads")){this.dir=e}part(e){return s.join(this.dir,`${e}.part`)}meta(e){return s.join(this.dir,`${e}.json`)}async begin(e){await f(this.dir,{recursive:!0});const t=u();await l(this.meta(t),JSON.stringify({name:e.name,mediaType:e.mediaType,size:e.size,received:0,dir:e.dir??null}),"utf8");const r=await o(this.part(t),"w");return await r.truncate(e.size),this.handles.set(t,r),{id:t,...e,received:0}}async get(e){if(!c.test(e))return null;try{const t=JSON.parse(await p(this.meta(e),"utf8"));if(typeof t.name!="string"||typeof t.mediaType!="string"||typeof t.size!="number")return null;const r=typeof t.received=="number"?t.received:(await m(this.part(e))).size;return{id:e,name:t.name,mediaType:t.mediaType,size:t.size,received:r,dir:typeof t.dir=="string"?t.dir:null}}catch{return null}}async append(e,t,r){const i=await this.get(e);if(!i)return{kind:"missing"};if(t!==i.received)return{kind:"conflict",received:i.received};if(i.received+r.length>i.size)return{kind:"overflow",received:i.received};let a=this.handles.get(e);a||(a=await o(this.part(e),"r+"),this.handles.set(e,a));const n=i.received+r.length;return await a.write(r,0,r.length,t),await a.truncate(n),await l(this.meta(e),JSON.stringify({name:i.name,mediaType:i.mediaType,size:i.size,received:n,dir:i.dir??null}),"utf8"),{kind:"ok",received:n}}async finish(e){const t=await this.get(e);return!t||t.received!==t.size?null:{name:t.name,mediaType:t.mediaType,file:this.part(e),size:t.size,dir:t.dir}}async abort(e){c.test(e)&&(await this.handles.get(e)?.close().catch(()=>{}),this.handles.delete(e),await d(this.part(e),{force:!0}),await d(this.meta(e),{force:!0}))}async sweep(e=UPLOAD_SESSION_MAX_AGE_MS,t=Date.now()){let r;try{r=await w(this.dir)}catch{return 0}let i=0;for(const a of r){if(!a.endsWith(".json"))continue;const n=a.slice(0,-5);if(c.test(n))try{const h=await m(this.meta(n));if(t-h.mtimeMs<e)continue;await this.abort(n),i++}catch{}}return i}}export const defaultUploadSessions=new UploadSessions;
@@ -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;