@weavecode/weave 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/node_modules/@modelcontextprotocol/sdk/node_modules/@hono/node-server/dist/index.cjs +31 -6
  2. package/node_modules/@modelcontextprotocol/sdk/node_modules/@hono/node-server/dist/index.mjs +31 -6
  3. package/node_modules/@modelcontextprotocol/sdk/node_modules/@hono/node-server/package.json +1 -1
  4. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.cjs +1 -1
  5. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/dist/index.mjs +1 -1
  6. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/node_modules/ip-address/README.md +39 -39
  7. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/node_modules/ip-address/dist/ipv6.js +1 -1
  8. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/node_modules/ip-address/package.json +1 -1
  9. package/node_modules/@modelcontextprotocol/sdk/node_modules/express-rate-limit/package.json +1 -1
  10. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +1 -1
  11. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
  12. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/context.js +1 -1
  13. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/helper/css/common.js +3 -5
  14. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/hono-base.js +4 -10
  15. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/hono.js +0 -1
  16. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/basic-auth/index.js +1 -1
  17. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/bearer-auth/index.js +1 -1
  18. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/csrf/index.js +2 -2
  19. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +2 -2
  20. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +2 -2
  21. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/middleware/mount/index.js +4 -4
  22. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +13 -11
  23. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/prepared-router.js +4 -4
  24. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +39 -51
  25. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +15 -5
  26. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/utils/jwt/jwt.js +2 -1
  27. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/utils/mount.js +35 -0
  28. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/utils/url.js +10 -0
  29. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/cjs/validator/validator.js +1 -1
  30. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/context.js +1 -1
  31. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/helper/css/common.js +3 -5
  32. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/hono-base.js +4 -10
  33. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/hono.js +0 -1
  34. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/basic-auth/index.js +1 -1
  35. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/bearer-auth/index.js +1 -1
  36. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/csrf/index.js +2 -2
  37. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/jwk/jwk.js +2 -2
  38. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/jwt/jwt.js +2 -2
  39. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/language/language.js +1 -1
  40. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/middleware/mount/index.js +4 -4
  41. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/node.js +13 -11
  42. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/prepared-router.js +5 -5
  43. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/router.js +40 -52
  44. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/router/reg-exp-router/trie.js +15 -5
  45. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/middleware/mount/index.d.ts +1 -0
  46. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +3 -3
  47. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +1 -1
  48. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/utils/mount.d.ts +4 -0
  49. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/types/utils/url.d.ts +1 -0
  50. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/utils/jwt/jwt.js +2 -1
  51. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/utils/mount.js +34 -0
  52. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/utils/url.js +10 -1
  53. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/dist/validator/validator.js +1 -1
  54. package/node_modules/@modelcontextprotocol/sdk/node_modules/hono/package.json +1 -1
  55. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/remote.js +3 -1
  56. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/deflate.js +2 -1
  57. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +2 -1
  58. package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/package.json +1 -1
  59. package/node_modules/@weavecode/cli/dist/cli.js +4 -4
  60. package/node_modules/@weavecode/cli/dist/commands/chpass.js +1 -1
  61. package/node_modules/@weavecode/cli/dist/commands/daemon-auth.js +1 -1
  62. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  63. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -2
  64. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  65. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  66. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  67. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  68. package/node_modules/@weavecode/cli/dist/commands/uninstall.js +1 -1
  69. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +3 -3
  70. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +7 -0
  71. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +3 -3
  72. package/node_modules/@weavecode/cli/dist/i18n/index.js +1 -1
  73. package/node_modules/@weavecode/cli/dist/i18n/t.js +1 -1
  74. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +5 -5
  75. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  76. package/node_modules/@weavecode/cli/dist/init/git-commit.js +2 -2
  77. package/node_modules/@weavecode/cli/dist/init/git-exclude.d.ts +20 -0
  78. package/node_modules/@weavecode/cli/dist/init/git-exclude.js +7 -0
  79. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  80. package/node_modules/@weavecode/cli/dist/init/harnesses/codex.js +1 -1
  81. package/node_modules/@weavecode/cli/dist/init/instruction-files.d.ts +14 -0
  82. package/node_modules/@weavecode/cli/dist/init/instruction-files.js +1 -0
  83. package/node_modules/@weavecode/cli/dist/init/instruction-link.js +1 -1
  84. package/node_modules/@weavecode/cli/dist/init/plugin-templates.js +1 -1
  85. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  86. package/node_modules/@weavecode/cli/dist/init/provision.js +1 -1
  87. package/node_modules/@weavecode/cli/dist/init/uninstall.js +6 -6
  88. package/node_modules/@weavecode/cli/dist/init/wiring.js +1 -1
  89. package/node_modules/@weavecode/cli/dist/parser.js +1 -1
  90. package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
  91. package/node_modules/@weavecode/cli/package.json +5 -5
  92. package/node_modules/@weavecode/core/dist/harness-checks.js +1 -1
  93. package/node_modules/@weavecode/core/dist/harness.d.ts +115 -0
  94. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  95. package/node_modules/@weavecode/core/dist/index.d.ts +1 -1
  96. package/node_modules/@weavecode/core/dist/index.js +1 -1
  97. package/node_modules/@weavecode/core/dist/platform.js +1 -1
  98. package/node_modules/@weavecode/core/dist/types.d.ts +4 -4
  99. package/node_modules/@weavecode/core/dist/types.js +1 -1
  100. package/node_modules/@weavecode/core/dist/utils/fs.js +1 -1
  101. package/node_modules/@weavecode/core/package.json +1 -1
  102. package/node_modules/@weavecode/harness/dist/claude/assets.js +3 -3
  103. package/node_modules/@weavecode/harness/dist/claude/capture.js +9 -9
  104. package/node_modules/@weavecode/harness/dist/claude/commands.d.ts +2 -0
  105. package/node_modules/@weavecode/harness/dist/claude/commands.js +3 -2
  106. package/node_modules/@weavecode/harness/dist/claude/config.js +2 -2
  107. package/node_modules/@weavecode/harness/dist/claude/detect.js +1 -1
  108. package/node_modules/@weavecode/harness/dist/claude/edits.js +1 -1
  109. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  110. package/node_modules/@weavecode/harness/dist/claude/images.js +2 -2
  111. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  112. package/node_modules/@weavecode/harness/dist/claude/liveness.js +1 -1
  113. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -1
  114. package/node_modules/@weavecode/harness/dist/claude/messaging.js +2 -2
  115. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -1
  116. package/node_modules/@weavecode/harness/dist/claude/narration.js +1 -1
  117. package/node_modules/@weavecode/harness/dist/claude/peers.js +1 -1
  118. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -1
  119. package/node_modules/@weavecode/harness/dist/claude/plugins.js +4 -4
  120. package/node_modules/@weavecode/harness/dist/claude/prompt-inbox.js +1 -1
  121. package/node_modules/@weavecode/harness/dist/claude/prompt.js +3 -3
  122. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -2
  123. package/node_modules/@weavecode/harness/dist/claude/resume.js +1 -1
  124. package/node_modules/@weavecode/harness/dist/claude/rewind.js +1 -1
  125. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -1
  126. package/node_modules/@weavecode/harness/dist/claude/side-question.js +2 -2
  127. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.d.ts +6 -0
  128. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +21 -14
  129. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -1
  130. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -2
  131. package/node_modules/@weavecode/harness/dist/claude/transcript-cursor.js +2 -2
  132. package/node_modules/@weavecode/harness/dist/claude/transcript.js +7 -7
  133. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  134. package/node_modules/@weavecode/harness/dist/codex/capture.js +2 -2
  135. package/node_modules/@weavecode/harness/dist/codex/commands.js +4 -4
  136. package/node_modules/@weavecode/harness/dist/codex/config.js +2 -2
  137. package/node_modules/@weavecode/harness/dist/codex/detect.js +1 -1
  138. package/node_modules/@weavecode/harness/dist/codex/event-source.js +2 -2
  139. package/node_modules/@weavecode/harness/dist/codex/images.js +1 -1
  140. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  141. package/node_modules/@weavecode/harness/dist/codex/liveness.js +1 -1
  142. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -1
  143. package/node_modules/@weavecode/harness/dist/codex/messaging.js +2 -2
  144. package/node_modules/@weavecode/harness/dist/codex/narration.js +1 -1
  145. package/node_modules/@weavecode/harness/dist/codex/plugin-state.js +1 -1
  146. package/node_modules/@weavecode/harness/dist/codex/plugins.js +3 -3
  147. package/node_modules/@weavecode/harness/dist/codex/provision.js +1 -1
  148. package/node_modules/@weavecode/harness/dist/codex/questions.js +2 -2
  149. package/node_modules/@weavecode/harness/dist/codex/rollout.js +5 -5
  150. package/node_modules/@weavecode/harness/dist/codex/side-question.js +4 -4
  151. package/node_modules/@weavecode/harness/dist/codex/titles.js +4 -4
  152. package/node_modules/@weavecode/harness/dist/codex/toml.js +13 -13
  153. package/node_modules/@weavecode/harness/dist/codex/transcript.js +2 -2
  154. package/node_modules/@weavecode/harness/dist/driver.d.ts +6 -0
  155. package/node_modules/@weavecode/harness/dist/driver.js +1 -1
  156. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -2
  157. package/node_modules/@weavecode/harness/dist/init/pipeline.js +1 -1
  158. package/node_modules/@weavecode/harness/dist/registry-wiring.js +1 -1
  159. package/node_modules/@weavecode/harness/dist/shared/install-link.js +1 -1
  160. package/node_modules/@weavecode/harness/dist/shared/json-cap.js +1 -1
  161. package/node_modules/@weavecode/harness/package.json +2 -2
  162. package/node_modules/@weavecode/server/dist/config/dotted.js +1 -1
  163. package/node_modules/@weavecode/server/dist/config/profiles.js +2 -2
  164. package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
  165. package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
  166. package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
  167. package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -3
  168. package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
  169. package/node_modules/@weavecode/server/dist/daemon/auto-start.js +3 -3
  170. package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
  171. package/node_modules/@weavecode/server/dist/daemon/config-routes.js +1 -1
  172. package/node_modules/@weavecode/server/dist/daemon/cron.js +1 -1
  173. package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
  174. package/node_modules/@weavecode/server/dist/daemon/dashboard-pusher.js +1 -1
  175. package/node_modules/@weavecode/server/dist/daemon/decision-config.js +2 -2
  176. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  177. package/node_modules/@weavecode/server/dist/daemon/entry.js +2 -2
  178. package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
  179. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
  180. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  181. package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
  182. package/node_modules/@weavecode/server/dist/daemon/liveness.js +1 -1
  183. package/node_modules/@weavecode/server/dist/daemon/mcp-orchestration.js +1 -1
  184. package/node_modules/@weavecode/server/dist/daemon/narration-watcher.js +2 -2
  185. package/node_modules/@weavecode/server/dist/daemon/opener/backend-ghostty.js +1 -1
  186. package/node_modules/@weavecode/server/dist/daemon/opener/backend-iterm.js +1 -1
  187. package/node_modules/@weavecode/server/dist/daemon/opener/backend-konsole.js +2 -2
  188. package/node_modules/@weavecode/server/dist/daemon/opener/backend-terminal-app.js +1 -1
  189. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wezterm.js +1 -1
  190. package/node_modules/@weavecode/server/dist/daemon/opener/backend-wt.js +1 -1
  191. package/node_modules/@weavecode/server/dist/daemon/opener/backend.js +1 -1
  192. package/node_modules/@weavecode/server/dist/daemon/opener/pty-terminals.js +1 -1
  193. package/node_modules/@weavecode/server/dist/daemon/opener/shared.js +1 -1
  194. package/node_modules/@weavecode/server/dist/daemon/opener/wezterm-mux.js +1 -1
  195. package/node_modules/@weavecode/server/dist/daemon/opener/wt.js +3 -3
  196. package/node_modules/@weavecode/server/dist/daemon/opener.js +1 -1
  197. package/node_modules/@weavecode/server/dist/daemon/pet-seed.d.ts +4 -0
  198. package/node_modules/@weavecode/server/dist/daemon/pet-seed.js +2 -0
  199. package/node_modules/@weavecode/server/dist/daemon/pet-window.d.ts +17 -0
  200. package/node_modules/@weavecode/server/dist/daemon/pet-window.js +2 -0
  201. package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
  202. package/node_modules/@weavecode/server/dist/daemon/project-files.d.ts +1 -1
  203. package/node_modules/@weavecode/server/dist/daemon/project-files.js +2 -2
  204. package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
  205. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
  206. package/node_modules/@weavecode/server/dist/daemon/prompt-images.js +1 -1
  207. package/node_modules/@weavecode/server/dist/daemon/routes/hooks-admin.js +1 -1
  208. package/node_modules/@weavecode/server/dist/daemon/routes/installations.d.ts +29 -0
  209. package/node_modules/@weavecode/server/dist/daemon/routes/installations.js +1 -0
  210. package/node_modules/@weavecode/server/dist/daemon/routes/market.js +1 -1
  211. package/node_modules/@weavecode/server/dist/daemon/routes/orchestration.js +1 -1
  212. package/node_modules/@weavecode/server/dist/daemon/routes/path-refs.js +1 -1
  213. package/node_modules/@weavecode/server/dist/daemon/routes/pets.d.ts +3 -0
  214. package/node_modules/@weavecode/server/dist/daemon/routes/pets.js +1 -0
  215. package/node_modules/@weavecode/server/dist/daemon/routes/project-files.js +1 -1
  216. package/node_modules/@weavecode/server/dist/daemon/routes/projects.js +1 -1
  217. package/node_modules/@weavecode/server/dist/daemon/routes/search.js +1 -1
  218. package/node_modules/@weavecode/server/dist/daemon/routes/session-control.js +1 -1
  219. package/node_modules/@weavecode/server/dist/daemon/routes/session-insights.js +1 -1
  220. package/node_modules/@weavecode/server/dist/daemon/routes/settings-statusline.js +1 -1
  221. package/node_modules/@weavecode/server/dist/daemon/routes/uploads.js +1 -1
  222. package/node_modules/@weavecode/server/dist/daemon/routes/visualizations.js +2 -1
  223. package/node_modules/@weavecode/server/dist/daemon/routes/watches.js +1 -1
  224. package/node_modules/@weavecode/server/dist/daemon/server.d.ts +4 -0
  225. package/node_modules/@weavecode/server/dist/daemon/server.js +8 -8
  226. package/node_modules/@weavecode/server/dist/daemon/session-open.js +1 -1
  227. package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
  228. package/node_modules/@weavecode/server/dist/daemon/settings.d.ts +21 -0
  229. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  230. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.js +1 -1
  231. package/node_modules/@weavecode/server/dist/daemon/sse-hub.js +1 -1
  232. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  233. package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
  234. package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
  235. package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.js +1 -1
  236. package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
  237. package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
  238. package/node_modules/@weavecode/server/dist/daemon/upload-sessions.js +1 -1
  239. package/node_modules/@weavecode/server/dist/db/db.d.ts +4 -1
  240. package/node_modules/@weavecode/server/dist/db/db.js +2 -2
  241. package/node_modules/@weavecode/server/dist/db/layout.d.ts +5 -0
  242. package/node_modules/@weavecode/server/dist/db/layout.js +2 -1
  243. package/node_modules/@weavecode/server/dist/db/paths.d.ts +9 -0
  244. package/node_modules/@weavecode/server/dist/db/paths.js +1 -1
  245. package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
  246. package/node_modules/@weavecode/server/dist/hooks/dashboard-rate.js +1 -1
  247. package/node_modules/@weavecode/server/dist/hooks/decision-judge.js +1 -1
  248. package/node_modules/@weavecode/server/dist/hooks/delivery/ack-gate.js +1 -1
  249. package/node_modules/@weavecode/server/dist/hooks/delivery/channels.js +1 -1
  250. package/node_modules/@weavecode/server/dist/hooks/delivery/keys.js +1 -1
  251. package/node_modules/@weavecode/server/dist/hooks/delivery/queue.js +1 -1
  252. package/node_modules/@weavecode/server/dist/hooks/delivery/relay.js +1 -1
  253. package/node_modules/@weavecode/server/dist/hooks/delivery/send.js +2 -2
  254. package/node_modules/@weavecode/server/dist/hooks/delivery/views.js +1 -1
  255. package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
  256. package/node_modules/@weavecode/server/dist/hooks/edge-extract.js +1 -1
  257. package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
  258. package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
  259. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -2
  260. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
  261. package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
  262. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +5 -5
  263. package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
  264. package/node_modules/@weavecode/server/dist/hooks/orchestration-engine.js +7 -7
  265. package/node_modules/@weavecode/server/dist/hooks/orchestration-graph.js +1 -1
  266. package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
  267. package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
  268. package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
  269. package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
  270. package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
  271. package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
  272. package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
  273. package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
  274. package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
  275. package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
  276. package/node_modules/@weavecode/server/dist/hooks/side-questions.js +1 -1
  277. package/node_modules/@weavecode/server/dist/hooks/synthetic-sessions.js +1 -1
  278. package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
  279. package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
  280. package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
  281. package/node_modules/@weavecode/server/dist/index.d.ts +1 -1
  282. package/node_modules/@weavecode/server/dist/index.js +1 -1
  283. package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
  284. package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
  285. package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
  286. package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
  287. package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
  288. package/node_modules/@weavecode/server/dist/install/global-config.js +1 -1
  289. package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
  290. package/node_modules/@weavecode/server/dist/install/init-files.d.ts +0 -9
  291. package/node_modules/@weavecode/server/dist/install/init-files.js +2 -2
  292. package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
  293. package/node_modules/@weavecode/server/dist/install/installer.js +1 -1
  294. package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
  295. package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
  296. package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
  297. package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
  298. package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
  299. package/node_modules/@weavecode/server/dist/install/project-config.js +1 -1
  300. package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
  301. package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
  302. package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
  303. package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
  304. package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
  305. package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
  306. package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
  307. package/node_modules/@weavecode/server/dist/market/import.js +2 -2
  308. package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
  309. package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
  310. package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
  311. package/node_modules/@weavecode/server/dist/registry.js +2 -2
  312. package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +4 -4
  313. package/node_modules/@weavecode/server/dist/repositories/hook-events.d.ts +6 -0
  314. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +8 -5
  315. package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
  316. package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
  317. package/node_modules/@weavecode/server/dist/repositories/orchestrations.js +7 -7
  318. package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
  319. package/node_modules/@weavecode/server/dist/repositories/projects.js +1 -1
  320. package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
  321. package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
  322. package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
  323. package/node_modules/@weavecode/server/dist/repositories/uploads.js +11 -11
  324. package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
  325. package/node_modules/@weavecode/server/dist/statusline/generator.js +1 -1
  326. package/node_modules/@weavecode/server/dist/statusline/manager.js +3 -3
  327. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  328. package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
  329. package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
  330. package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
  331. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
  332. package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
  333. package/node_modules/@weavecode/server/package.json +4 -4
  334. package/node_modules/@weavecode/server/web/dist/assets/abnfDiagram-WEYOIA3C-S1lL1V_n.js +1 -0
  335. package/node_modules/@weavecode/server/web/dist/assets/{arc-CRZTRyjb.js → arc-CoTNHyHV.js} +1 -1
  336. package/node_modules/@weavecode/server/web/dist/assets/architectureDiagram-ZHVYKT53-C6ttfnzW.js +36 -0
  337. package/node_modules/@weavecode/server/web/dist/assets/{blockDiagram-RJAE7QA3-BIH8mSIZ.js → blockDiagram-RJAE7QA3-CYr3Cpu9.js} +2 -2
  338. package/node_modules/@weavecode/server/web/dist/assets/{c4Diagram-XDPPPE54-5YoKWFOD.js → c4Diagram-XDPPPE54-BFS7PhLD.js} +2 -2
  339. package/node_modules/@weavecode/server/web/dist/assets/channel-DxQHp3Yc.js +1 -0
  340. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2E7WHVMD-B653kMXt.js → chunk-2E7WHVMD-DJ7X_Shu.js} +1 -1
  341. package/node_modules/@weavecode/server/web/dist/assets/{chunk-2Q5K7J3B-f_A4_eDz.js → chunk-2Q5K7J3B-B8nr2rdz.js} +1 -1
  342. package/node_modules/@weavecode/server/web/dist/assets/{chunk-4EMNKR2T-v5j5qNGj.js → chunk-4EMNKR2T-DmnZmUMU.js} +1 -1
  343. package/node_modules/@weavecode/server/web/dist/assets/chunk-55XCU76K-Xz9a8dmp.js +1 -0
  344. package/node_modules/@weavecode/server/web/dist/assets/{chunk-5VM5RSS4-BeROhLXN.js → chunk-5VM5RSS4-Dg9mg7pf.js} +1 -1
  345. package/node_modules/@weavecode/server/web/dist/assets/{chunk-JWPE2WC7-D6dXb_jr.js → chunk-JWPE2WC7-CmjTZO8o.js} +1 -1
  346. package/node_modules/@weavecode/server/web/dist/assets/{chunk-VQ5W62QI-CnHdSEMi.js → chunk-VQ5W62QI-D3YDdJ3E.js} +1 -1
  347. package/node_modules/@weavecode/server/web/dist/assets/chunk-XXDRQBXY-s1OG9sqW.js +1 -0
  348. package/node_modules/@weavecode/server/web/dist/assets/chunk-ZCHMQSOR-C3hINQU3.js +2 -0
  349. package/node_modules/@weavecode/server/web/dist/assets/{classDiagram-v2-4MYWR3UA-DQe1b_k8.js → classDiagram-v2-4MYWR3UA-BTsbYrVl.js} +2 -2
  350. package/node_modules/@weavecode/server/web/dist/assets/cose-bilkent-JH36ORCC-C0W8Y-jI.js +1 -0
  351. package/node_modules/@weavecode/server/web/dist/assets/{cynefin-EF2NZ3EQ-OZotFKUu.js → cynefin-EF2NZ3EQ-stAu4Rh-.js} +1 -1
  352. package/node_modules/@weavecode/server/web/dist/assets/cynefinDiagram-WF24UDRP-CqYibiiv.js +62 -0
  353. package/node_modules/@weavecode/server/web/dist/assets/dagre-NK4GIZVX-qqcoJAqB.js +4 -0
  354. package/node_modules/@weavecode/server/web/dist/assets/diagram-CBK3MWTC-D0YTopb7.js +24 -0
  355. package/node_modules/@weavecode/server/web/dist/assets/diagram-I5XIIV2D-Csvw6aYr.js +24 -0
  356. package/node_modules/@weavecode/server/web/dist/assets/{diagram-ODIL2UCW-D9A6W8oB.js → diagram-ODIL2UCW-Dl0tYLkF.js} +2 -2
  357. package/node_modules/@weavecode/server/web/dist/assets/{diagram-PFBEJUXE-PeI-eyu2.js → diagram-PFBEJUXE-BCPSWZPe.js} +2 -2
  358. package/node_modules/@weavecode/server/web/dist/assets/diagram-RJA3I4VV-ETg-BrAJ.js +41 -0
  359. package/node_modules/@weavecode/server/web/dist/assets/{diagram-TYUNFSNR-D5KieEw5.js → diagram-TYUNFSNR-_M6ZxBG7.js} +2 -2
  360. package/node_modules/@weavecode/server/web/dist/assets/ebnfDiagram-V4P3TTPT-C-e_W7qx.js +1 -0
  361. package/node_modules/@weavecode/server/web/dist/assets/{elk-QONTBCTQ-D3xrVg0U.js → elk-QONTBCTQ-B5TBharB.js} +3 -3
  362. package/node_modules/@weavecode/server/web/dist/assets/{erDiagram-KYQIGQAA-y_V1cor7.js → erDiagram-KYQIGQAA-D08rj2pv.js} +2 -2
  363. package/node_modules/@weavecode/server/web/dist/assets/{flowDiagram-IUGLLWBU-BJ8Z0MkF.js → flowDiagram-IUGLLWBU-BALTxsKh.js} +1 -1
  364. package/node_modules/@weavecode/server/web/dist/assets/ganttDiagram-R7GPNTJY-Cts193jT.js +292 -0
  365. package/node_modules/@weavecode/server/web/dist/assets/gitGraphDiagram-PDYL7XHY-L9qYUX0v.js +106 -0
  366. package/node_modules/@weavecode/server/web/dist/assets/infoDiagram-MVDRKAX5-Bv47rgU0.js +2 -0
  367. package/node_modules/@weavecode/server/web/dist/assets/{ishikawaDiagram-HPEHV2GE-ChEnND76.js → ishikawaDiagram-HPEHV2GE-Da8_s6cs.js} +2 -2
  368. package/node_modules/@weavecode/server/web/dist/assets/{journeyDiagram-BOSHW7O7-DHcNtpYF.js → journeyDiagram-BOSHW7O7-Bj3CjZOf.js} +2 -2
  369. package/node_modules/@weavecode/server/web/dist/assets/{kanban-definition-FNSA4HC5-Dft7qpW5.js → kanban-definition-FNSA4HC5-D1hicmMu.js} +2 -2
  370. package/node_modules/@weavecode/server/web/dist/assets/linear-CWQg2iA1.js +1 -0
  371. package/node_modules/@weavecode/server/web/dist/assets/main-XLn3EZFh.css +11 -0
  372. package/node_modules/@weavecode/server/web/dist/assets/main-bsb0lQoL.js +1096 -0
  373. package/node_modules/@weavecode/server/web/dist/assets/{mermaid.core-D_Dp_Kl2.js → mermaid.core-C-wP0Zg2.js} +4 -4
  374. package/node_modules/@weavecode/server/web/dist/assets/{mindmap-definition-6OY57UG3-CM6OAd_-.js → mindmap-definition-6OY57UG3-Dk0VKqre.js} +2 -2
  375. package/node_modules/@weavecode/server/web/dist/assets/modulepreload-polyfill-B5Qt9EMX.js +1 -0
  376. package/node_modules/@weavecode/server/web/dist/assets/pegDiagram-ECIUJNBX-Bp1K_F9z.js +1 -0
  377. package/node_modules/@weavecode/server/web/dist/assets/pet-J6izA90s.js +1 -0
  378. package/node_modules/@weavecode/server/web/dist/assets/pieDiagram-GNMPY74T-BZ4rGy3t.js +39 -0
  379. package/node_modules/@weavecode/server/web/dist/assets/{quadrantDiagram-D57K4MC3-D8pQ_PU2.js → quadrantDiagram-D57K4MC3-B4N5KRsR.js} +4 -4
  380. package/node_modules/@weavecode/server/web/dist/assets/railroadDiagram-Y72NRBL7-C8nx8oHf.js +1 -0
  381. package/node_modules/@weavecode/server/web/dist/assets/{requirementDiagram-EQYSW5RA-C90DU5Ny.js → requirementDiagram-EQYSW5RA-VSH57d0d.js} +2 -2
  382. package/node_modules/@weavecode/server/web/dist/assets/{sankeyDiagram-SY24JHO5-B_poYGgJ.js → sankeyDiagram-SY24JHO5-jUb1hcya.js} +2 -2
  383. package/node_modules/@weavecode/server/web/dist/assets/{sequenceDiagram-BLEHNHQU-DDW7b2Dn.js → sequenceDiagram-BLEHNHQU-E2BioCNi.js} +2 -2
  384. package/node_modules/@weavecode/server/web/dist/assets/sizeCapture-INFHLROL-BdKrbRmI.js +1 -0
  385. package/node_modules/@weavecode/server/web/dist/assets/{stateDiagram-v2-A6IESKWZ-CkVMAyxG.js → stateDiagram-v2-A6IESKWZ-tFz7uNM7.js} +2 -2
  386. package/node_modules/@weavecode/server/web/dist/assets/swimlanes-B3ENRKFQ-B9BAPDWw.js +1 -0
  387. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-DQ2NPLl9.js +8 -0
  388. package/node_modules/@weavecode/server/web/dist/assets/{timeline-definition-JXYKGLGB-DnhkRGLb.js → timeline-definition-JXYKGLGB-CofNnFTK.js} +2 -2
  389. package/node_modules/@weavecode/server/web/dist/assets/{usecaseDiagram-WPOLBNNX-_TdIjC6Z.js → usecaseDiagram-WPOLBNNX-DOvjhJjJ.js} +2 -2
  390. package/node_modules/@weavecode/server/web/dist/assets/{vennDiagram-Q3Y3IDCW-FzgsymXB.js → vennDiagram-Q3Y3IDCW-BcFHWnhS.js} +2 -2
  391. package/node_modules/@weavecode/server/web/dist/assets/{wardleyDiagram-IVAIDKWA-BwqimStC.js → wardleyDiagram-IVAIDKWA-Bz2aqRAs.js} +2 -2
  392. package/node_modules/@weavecode/server/web/dist/assets/{xychartDiagram-4URNHDU4-CFjjVPIV.js → xychartDiagram-4URNHDU4-DpNF6Vsq.js} +2 -2
  393. package/node_modules/@weavecode/server/web/dist/index.html +3 -2
  394. package/node_modules/@weavecode/server/web/dist/pet.html +130 -0
  395. package/node_modules/@weavecode/templates/dist/index.d.ts +2 -0
  396. package/node_modules/@weavecode/templates/dist/index.js +1 -1
  397. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/pet.json +7 -0
  398. package/node_modules/@weavecode/templates/dist/resources/pets/weave-spider/spritesheet.png +0 -0
  399. package/node_modules/@weavecode/templates/dist/resources/weave-market/.claude-plugin/marketplace.json +6 -0
  400. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/.claude-plugin/plugin.json +8 -0
  401. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/skills/weave-pet-hatcher/SKILL.md +121 -0
  402. 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
  403. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-pet-hatcher/weave.json +4 -0
  404. package/node_modules/@weavecode/templates/package.json +2 -2
  405. package/package.json +11 -7
  406. package/scripts/preinstall.mjs +108 -0
  407. package/node_modules/@weavecode/server/web/dist/assets/abnfDiagram-WEYOIA3C-DDeQkTf5.js +0 -1
  408. package/node_modules/@weavecode/server/web/dist/assets/architectureDiagram-ZHVYKT53-Dj54DE3O.js +0 -36
  409. package/node_modules/@weavecode/server/web/dist/assets/channel-5VM93AJ8.js +0 -1
  410. package/node_modules/@weavecode/server/web/dist/assets/chunk-55XCU76K-CgEqeP7j.js +0 -1
  411. package/node_modules/@weavecode/server/web/dist/assets/chunk-XXDRQBXY-BkG_e6PE.js +0 -1
  412. package/node_modules/@weavecode/server/web/dist/assets/chunk-ZCHMQSOR-DxR-fxzs.js +0 -2
  413. package/node_modules/@weavecode/server/web/dist/assets/cose-bilkent-JH36ORCC-DThrA8S5.js +0 -1
  414. package/node_modules/@weavecode/server/web/dist/assets/cynefinDiagram-WF24UDRP-DJjq2hfT.js +0 -62
  415. package/node_modules/@weavecode/server/web/dist/assets/dagre-NK4GIZVX-C2vH93HT.js +0 -4
  416. package/node_modules/@weavecode/server/web/dist/assets/diagram-CBK3MWTC-DrF_ScM-.js +0 -24
  417. package/node_modules/@weavecode/server/web/dist/assets/diagram-I5XIIV2D-D1qoUJ4t.js +0 -24
  418. package/node_modules/@weavecode/server/web/dist/assets/diagram-RJA3I4VV-DITY0Rd8.js +0 -41
  419. package/node_modules/@weavecode/server/web/dist/assets/ebnfDiagram-V4P3TTPT-DDylK-gz.js +0 -1
  420. package/node_modules/@weavecode/server/web/dist/assets/ganttDiagram-R7GPNTJY-C0q-CS1T.js +0 -292
  421. package/node_modules/@weavecode/server/web/dist/assets/gitGraphDiagram-PDYL7XHY-BYTComiB.js +0 -106
  422. package/node_modules/@weavecode/server/web/dist/assets/index-BKxAxaVG.js +0 -1091
  423. package/node_modules/@weavecode/server/web/dist/assets/index-C0Sd4MH7.css +0 -11
  424. package/node_modules/@weavecode/server/web/dist/assets/infoDiagram-MVDRKAX5-DtixgjLP.js +0 -2
  425. package/node_modules/@weavecode/server/web/dist/assets/linear-DEo11t-X.js +0 -1
  426. package/node_modules/@weavecode/server/web/dist/assets/pegDiagram-ECIUJNBX-_QkY0h8Q.js +0 -1
  427. package/node_modules/@weavecode/server/web/dist/assets/pieDiagram-GNMPY74T-ZGr5vtDj.js +0 -39
  428. package/node_modules/@weavecode/server/web/dist/assets/railroadDiagram-Y72NRBL7-DUIo-WmA.js +0 -1
  429. package/node_modules/@weavecode/server/web/dist/assets/sizeCapture-INFHLROL-CmKoqX6K.js +0 -1
  430. package/node_modules/@weavecode/server/web/dist/assets/swimlanes-B3ENRKFQ-Dm_Omzky.js +0 -1
  431. package/node_modules/@weavecode/server/web/dist/assets/swimlanesDiagram-AYQRV4AK-Bjj8ZA4d.js +0 -8
@@ -1,10 +1,10 @@
1
- import{existsSync as d,readdirSync as h,readFileSync as S}from"node:fs";import i from"node:path";import{builtinMarketDir as b}from"../market/builtin.js";const p=6e4,w=40,y=6;export function findDocsDir(r){let e=i.resolve(r);for(let n=0;n<y;n++){const s=i.join(e,"docs");if(d(i.join(s,"FEATURES.md")))return s;const c=i.dirname(e);if(c===e)break;e=c}return null}export function collectSkillFiles(r,e=w){const n=[],s=(c,a)=>{if(n.length>=e||a>6)return;let u;try{u=h(c,{withFileTypes:!0})}catch{return}for(const l of u){if(n.length>=e)return;const t=i.join(c,l.name);l.isDirectory()?s(t,a+1):l.name==="SKILL.md"&&n.push(t)}};return s(r,0),n.sort()}function m(r){try{return S(r,"utf8")}catch{return null}}export function buildSystemPrompt(r){const e=[],n=findDocsDir(r.cwd??process.cwd());if(n)for(const t of["ARCHITECTURE.md","FEATURES.md"]){const o=i.join(n,t);if(!d(o))continue;const f=m(o);f&&e.push({label:`docs/${t}`,text:f})}const s=b(r.dataRoot);for(const t of collectSkillFiles(s)){const o=m(t);o&&e.push({label:i.relative(s,t).split(i.sep).join("/"),text:o})}const c=["\u4F60\u662F weave \u63A7\u5236\u53F0\u5185\u7F6E\u7684 AI \u52A9\u624B\uFF0C**\u53EA\u8D1F\u8D23 weave \u672C\u8EAB**\uFF1A\u5B83\u7684\u529F\u80FD\u3001\u7528\u6CD5\u3001\u914D\u7F6E\u3001\u67B6\u6784\u3001","\u5185\u7F6E\u6280\u80FD\uFF0C\u4EE5\u53CA\u57FA\u4E8E\u4E0B\u9762\u6CE8\u5165\u8D44\u6599\u7684\u6392\u969C\u3002","","\u56DE\u7B54\u8303\u56F4\uFF08\u8D8A\u754C\u7684\u60C5\u51B5\u4E00\u5F8B\u793C\u8C8C\u62D2\u7B54\uFF1A\u7528\u4E00\u53E5\u8BDD\u8BF4\u660E\u4F60\u53EA\u804A weave\uFF0C\u7136\u540E\u628A\u8BDD\u9898\u5F15\u56DE weave\uFF09\uFF1A","- \u53EF\u4EE5\u7B54\uFF1Aweave \u7684\u80FD\u529B\u4E0E\u64CD\u4F5C\uFF08\u547D\u4EE4\u3001\u8BBE\u7F6E\u9879\u3001\u6587\u4EF6\u843D\u70B9\u3001\u63D2\u4EF6/\u6280\u80FD/\u5E02\u573A\u3001hooks\u3001\u4F1A\u8BDD\u4E0E\u4EFB\u52A1\u3001\u8BA4\u8BC1\u7B49\uFF09\uFF0C"," \u4EE5\u53CA\u6CE8\u5165\u8D44\u6599\u91CC\u80FD\u67E5\u5230\u7684\u4E8B\u5B9E\uFF1B","- \u4E0D\u8981\u7B54\uFF1A\u4E0E weave \u65E0\u5173\u7684\u901A\u7528\u7F16\u7A0B\u3001\u5199\u4F5C\u3001\u7FFB\u8BD1\u3001\u95F2\u804A\uFF0C\u5176\u5B83\u4EA7\u54C1\u6216\u670D\u52A1\uFF0C\u4EE5\u53CA\u4EFB\u4F55\u6709\u5BB3\u6216\u8D8A\u754C\u7684\u8BF7\u6C42\uFF1B","- \u8D44\u6599\u672A\u8986\u76D6\u65F6\u660E\u786E\u8BF4\u300C\u4E0D\u786E\u5B9A\u300D\uFF0C\u4E0D\u8981\u7F16\u9020 weave \u7684\u884C\u4E3A\u3001\u547D\u4EE4\u6216\u53C2\u6570\uFF1B","- \u4E0D\u7C98\u8D34\u5927\u6BB5\u6CE8\u5165\u8D44\u6599\u539F\u6587\uFF08\u7528\u6237\u70B9\u540D\u8981\u67D0\u4E00\u6BB5\u65F6\u9664\u5916\uFF09\uFF1B","- \u53EA\u505A\u53EA\u8BFB\u95EE\u7B54\uFF1A\u4E0D\u58F0\u79F0\u5DF2\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C\uFF0C\u4E5F\u4E0D\u627F\u8BFA\u4EE3\u66FF\u7528\u6237\u53BB\u6539\u6587\u4EF6\u6216\u8DD1\u547D\u4EE4\u3002","","\u56DE\u7B54\u4F7F\u7528\u4E0E\u63D0\u95EE\u76F8\u540C\u7684\u8BED\u8A00\uFF1B\u6D89\u53CA\u64CD\u4F5C\u65F6\u7ED9\u51FA\u786E\u5207\u547D\u4EE4\u4E0E\u8DEF\u5F84\u3002"].join(`
2
- `),a=[];let u=c.length;const l=[];for(const t of e){const o=`
1
+ import{existsSync as C,readdirSync as i,readFileSync as a}from"node:fs";import n from"node:path";import{builtinMarketDir as f}from"../market/builtin.js";const l=6e4,p=40,d=6;export function findDocsDir(e){let F=n.resolve(e);for(let E=0;E<d;E++){const o=n.join(F,"docs");if(C(n.join(o,"FEATURES.md")))return o;const D=n.dirname(F);if(D===F)break;F=D}return null}export function collectSkillFiles(e,F=p){const E=[],o=(D,r)=>{if(E.length>=F||r>6)return;let s;try{s=i(D,{withFileTypes:!0})}catch{return}for(const B of s){if(E.length>=F)return;const u=n.join(D,B.name);B.isDirectory()?o(u,r+1):B.name==="SKILL.md"&&E.push(u)}};return o(e,0),E.sort()}function c(e){try{return a(e,"utf8")}catch{return null}}export function buildSystemPrompt(e){const F=[],E=findDocsDir(e.cwd??process.cwd());if(E)for(const u of["ARCHITECTURE.md","FEATURES.md"]){const t=n.join(E,u);if(!C(t))continue;const A=c(t);A&&F.push({label:`docs/${u}`,text:A})}const o=f(e.dataRoot);for(const u of collectSkillFiles(o)){const t=c(u);t&&F.push({label:n.relative(o,u).split(n.sep).join("/"),text:t})}const D=["\u4F60\u662F weave \u63A7\u5236\u53F0\u5185\u7F6E\u7684 AI \u52A9\u624B\uFF0C**\u53EA\u8D1F\u8D23 weave \u672C\u8EAB**\uFF1A\u5B83\u7684\u529F\u80FD\u3001\u7528\u6CD5\u3001\u914D\u7F6E\u3001\u67B6\u6784\u3001","\u5185\u7F6E\u6280\u80FD\uFF0C\u4EE5\u53CA\u57FA\u4E8E\u4E0B\u9762\u6CE8\u5165\u8D44\u6599\u7684\u6392\u969C\u3002","","\u56DE\u7B54\u8303\u56F4\uFF08\u8D8A\u754C\u7684\u60C5\u51B5\u4E00\u5F8B\u793C\u8C8C\u62D2\u7B54\uFF1A\u7528\u4E00\u53E5\u8BDD\u8BF4\u660E\u4F60\u53EA\u804A weave\uFF0C\u7136\u540E\u628A\u8BDD\u9898\u5F15\u56DE weave\uFF09\uFF1A","- \u53EF\u4EE5\u7B54\uFF1Aweave \u7684\u80FD\u529B\u4E0E\u64CD\u4F5C\uFF08\u547D\u4EE4\u3001\u8BBE\u7F6E\u9879\u3001\u6587\u4EF6\u843D\u70B9\u3001\u63D2\u4EF6/\u6280\u80FD/\u5E02\u573A\u3001hooks\u3001\u4F1A\u8BDD\u4E0E\u4EFB\u52A1\u3001\u8BA4\u8BC1\u7B49\uFF09\uFF0C"," \u4EE5\u53CA\u6CE8\u5165\u8D44\u6599\u91CC\u80FD\u67E5\u5230\u7684\u4E8B\u5B9E\uFF1B","- \u4E0D\u8981\u7B54\uFF1A\u4E0E weave \u65E0\u5173\u7684\u901A\u7528\u7F16\u7A0B\u3001\u5199\u4F5C\u3001\u7FFB\u8BD1\u3001\u95F2\u804A\uFF0C\u5176\u5B83\u4EA7\u54C1\u6216\u670D\u52A1\uFF0C\u4EE5\u53CA\u4EFB\u4F55\u6709\u5BB3\u6216\u8D8A\u754C\u7684\u8BF7\u6C42\uFF1B","- \u8D44\u6599\u672A\u8986\u76D6\u65F6\u660E\u786E\u8BF4\u300C\u4E0D\u786E\u5B9A\u300D\uFF0C\u4E0D\u8981\u7F16\u9020 weave \u7684\u884C\u4E3A\u3001\u547D\u4EE4\u6216\u53C2\u6570\uFF1B","- \u4E0D\u7C98\u8D34\u5927\u6BB5\u6CE8\u5165\u8D44\u6599\u539F\u6587\uFF08\u7528\u6237\u70B9\u540D\u8981\u67D0\u4E00\u6BB5\u65F6\u9664\u5916\uFF09\uFF1B","- \u53EA\u505A\u53EA\u8BFB\u95EE\u7B54\uFF1A\u4E0D\u58F0\u79F0\u5DF2\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C\uFF0C\u4E5F\u4E0D\u627F\u8BFA\u4EE3\u66FF\u7528\u6237\u53BB\u6539\u6587\u4EF6\u6216\u8DD1\u547D\u4EE4\u3002","","\u56DE\u7B54\u4F7F\u7528\u4E0E\u63D0\u95EE\u76F8\u540C\u7684\u8BED\u8A00\uFF1B\u6D89\u53CA\u64CD\u4F5C\u65F6\u7ED9\u51FA\u786E\u5207\u547D\u4EE4\u4E0E\u8DEF\u5F84\u3002"].join(`
2
+ `),r=[];let s=D.length;const B=[];for(const u of F){const t=`
3
3
 
4
- ## \u6CE8\u5165\u8D44\u6599\uFF1A${t.label}
4
+ ## \u6CE8\u5165\u8D44\u6599\uFF1A${u.label}
5
5
 
6
- ${t.text}`;if(u+o.length>p){const f=p-u;f>500&&(a.push(`
6
+ ${u.text}`;if(s+t.length>l){const A=l-s;A>500&&(r.push(`
7
7
 
8
- ## \u6CE8\u5165\u8D44\u6599\uFF1A${t.label}\uFF08\u6309\u9884\u7B97\u622A\u65AD\uFF09
8
+ ## \u6CE8\u5165\u8D44\u6599\uFF1A${u.label}\uFF08\u6309\u9884\u7B97\u622A\u65AD\uFF09
9
9
 
10
- ${t.text.slice(0,f)}`),l.push(`${t.label}(\u622A\u65AD)`));break}u+=o.length,a.push(o),l.push(t.label)}return{prompt:c+a.join(""),labels:l,docsFound:n!==null}}
10
+ ${u.text.slice(0,A)}`),B.push(`${u.label}(\u622A\u65AD)`));break}s+=t.length,r.push(t),B.push(u.label)}return{prompt:D+r.join(""),labels:B,docsFound:E!==null}}
@@ -1,6 +1,6 @@
1
- import{getDataRoot as I}from"../db/paths.js";import{DEFAULT_AI_SETTINGS as v,readDaemonSettings as N}from"./settings.js";import{hasAiKey as J,readAiKey as O}from"./ai-config.js";import{buildSystemPrompt as P,findDocsDir as R}from"./ai-context.js";import{readJson as k,sendJson as f}from"./http.js";const j=12e4,z=15e3,C=500,G=40,L=2e4;export function normalizeMessages(r){if(!Array.isArray(r)||r.length===0||r.length>G)return null;const e=[];for(const t of r){const o=t;if(o?.role!=="user"&&o?.role!=="assistant")return null;const a=o.content;if(typeof a!="string"||a===""||a.length>L)return null;e.push({role:o.role,content:a})}return e}export function aiConfigured(r,e,t){return r!==""&&e!==""&&t}export async function handleAiRoutes(r,e,t,o){if(o!=="/ai"&&!o.startsWith("/ai/"))return!1;const n=(await N()).ai??v,p=J(t.aiKeyPath);if(o==="/ai/status"&&r.method==="GET")return f(e,200,{configured:aiConfigured(n.baseUrl,n.model,p),baseUrl:n.baseUrl,model:n.model,apiKeySet:p,docsFound:R(process.cwd())!==null}),!0;if(o==="/ai/models"&&r.method==="POST"){let i;try{i=await k(r)}catch{return f(e,400,{error:"Invalid JSON body"}),!0}const u=typeof i.baseUrl=="string"&&i.baseUrl.trim()!==""?i.baseUrl.trim():n.baseUrl,m=typeof i.apiKey=="string"&&i.apiKey!==""?i.apiKey:O(t.aiKeyPath);if(u===""||m===null)return f(e,409,{error:"AI assistant is not configured"}),!0;const l=await B(u,m);return l.ok?(f(e,200,{models:l.models}),!0):(f(e,502,{error:l.error}),!0)}if(o==="/ai/chat"&&r.method==="POST"){const i=O(t.aiKeyPath);if(!aiConfigured(n.baseUrl,n.model,p)||i===null)return f(e,409,{error:"AI assistant is not configured"}),!0;let u;try{u=await k(r)}catch{return f(e,400,{error:"Invalid JSON body"}),!0}const m=normalizeMessages(u.messages);if(!m)return f(e,400,{error:"Invalid messages"}),!0;const l=P({dataRoot:t.libraries?.dataRoot??I()});return await X({req:r,res:e,baseUrl:n.baseUrl,model:n.model,apiKey:i,messages:m,system:l.prompt}),!0}return f(e,404,{error:"Not found"}),!0}function A(r){const t=r?.choices?.[0],o=t?.delta?.content??t?.message?.content;return typeof o=="string"&&o!==""?o:null}export const STREAM_MEMO_TTL_MS=1440*60*1e3;const S=new Map;export function streamMemoKey(r,e){return`${r}#${e}`}export function streamSupported(r,e=Date.now()){const t=S.get(r);return!t||e-t.checkedAt>STREAM_MEMO_TTL_MS?!0:t.streaming}export function rememberStreamSupport(r,e,t=Date.now()){const o=S.get(r);o!==void 0&&o.streaming!==e&&console.log(`[weave] ai gateway ${e?"supports":"rejects"} streaming: ${r}`),S.set(r,{streaming:e,checkedAt:t})}export function resetStreamMemory(){S.clear()}async function B(r,e){try{const t=await fetch(`${r.replace(/\/+$/,"")}/models`,{headers:{authorization:`Bearer ${e}`},signal:AbortSignal.timeout(z)});if(!t.ok){const n=await t.text().catch(()=>"");return{ok:!1,error:`upstream ${t.status}${n?`: ${n.slice(0,200)}`:""}`}}const o=await t.json().catch(()=>null),a=[...new Set((o?.data??[]).map(n=>n?.id).filter(n=>typeof n=="string"&&n!==""))].sort();return a.length===0?{ok:!1,error:"upstream returned no models"}:{ok:!0,models:a.slice(0,C)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}}async function E(r){try{const e=await fetch(r.url,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${r.apiKey}`},body:JSON.stringify({model:r.model,stream:!1,messages:r.messages}),signal:r.signal});if(!e.ok){const o=await e.text().catch(()=>"");return{ok:!1,error:`upstream ${e.status}${o?`: ${o.slice(0,300)}`:""}`}}const t=A(await e.json().catch(()=>null));return t===null?{ok:!1,error:"upstream returned no content"}:{ok:!0,content:t}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}async function X(r){const{req:e,res:t,baseUrl:o,model:a,apiKey:n,messages:p,system:i}=r,u=`${o.replace(/\/+$/,"")}/chat/completions`,m=[{role:"system",content:i},...p],l=new AbortController,_=setTimeout(()=>l.abort(),j);e.on("close",()=>l.abort()),t.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-accel-buffering":"no"});let b=!1;const d=s=>{if(!b)try{t.write(`data: ${JSON.stringify(s)}
1
+ import{getDataRoot as J}from"../db/paths.js";import{DEFAULT_AI_SETTINGS as M,readDaemonSettings as P}from"./settings.js";import{hasAiKey as I,readAiKey as T}from"./ai-config.js";import{buildSystemPrompt as j,findDocsDir as R}from"./ai-context.js";import{readJson as O,sendJson as u}from"./http.js";const _=12e4,z=15e3,B=500,q=40,C=2e4;export function normalizeMessages(r){if(!Array.isArray(r)||r.length===0||r.length>q)return null;const e=[];for(const t of r){const n=t;if(n?.role!=="user"&&n?.role!=="assistant")return null;const o=n.content;if(typeof o!="string"||o===""||o.length>C)return null;e.push({role:n.role,content:o})}return e}export function aiConfigured(r,e,t){return r!==""&&e!==""&&t}export async function handleAiRoutes(r,e,t,n){if(n!=="/ai"&&!n.startsWith("/ai/"))return!1;const o=(await P()).ai??M,a=I(t.aiKeyPath);if(n==="/ai/status"&&r.method==="GET")return u(e,200,{configured:aiConfigured(o.baseUrl,o.model,a),baseUrl:o.baseUrl,model:o.model,apiKeySet:a,docsFound:R(process.cwd())!==null}),!0;if(n==="/ai/models"&&r.method==="POST"){let i;try{i=await O(r)}catch{return u(e,400,{error:"Invalid JSON body"}),!0}const d=typeof i.baseUrl=="string"&&i.baseUrl.trim()!==""?i.baseUrl.trim():o.baseUrl,l=typeof i.apiKey=="string"&&i.apiKey!==""?i.apiKey:T(t.aiKeyPath);if(d===""||l===null)return u(e,409,{error:"AI assistant is not configured"}),!0;const m=await G(d,l);return m.ok?(u(e,200,{models:m.models}),!0):(u(e,502,{error:m.error}),!0)}if(n==="/ai/chat"&&r.method==="POST"){const i=T(t.aiKeyPath);if(!aiConfigured(o.baseUrl,o.model,a)||i===null)return u(e,409,{error:"AI assistant is not configured"}),!0;let d;try{d=await O(r)}catch{return u(e,400,{error:"Invalid JSON body"}),!0}const l=normalizeMessages(d.messages);if(!l)return u(e,400,{error:"Invalid messages"}),!0;const m=j({dataRoot:t.libraries?.dataRoot??J()});return await L({req:r,res:e,baseUrl:o.baseUrl,model:o.model,apiKey:i,messages:l,system:m.prompt}),!0}return u(e,404,{error:"Not found"}),!0}function $(r){const e=r?.choices?.[0],t=e?.delta?.content??e?.message?.content;return typeof t=="string"&&t!==""?t:null}export const STREAM_MEMO_TTL_MS=1440*60*1e3;const w=new Map;export function streamMemoKey(r,e){return`${r}#${e}`}export function streamSupported(r,e=Date.now()){const t=w.get(r);return!t||e-t.checkedAt>STREAM_MEMO_TTL_MS?!0:t.streaming}export function rememberStreamSupport(r,e,t=Date.now()){const n=w.get(r);n!==void 0&&n.streaming!==e&&console.log(`[weave] ai gateway ${e?"supports":"rejects"} streaming: ${r}`),w.set(r,{streaming:e,checkedAt:t})}export function resetStreamMemory(){w.clear()}async function G(r,e){try{const t=await fetch(`${r.replace(/\/+$/,"")}/models`,{headers:{authorization:`Bearer ${e}`},signal:AbortSignal.timeout(z)});if(!t.ok){const a=await t.text().catch(()=>"");return{ok:!1,error:`upstream ${t.status}${a?`: ${a.slice(0,200)}`:""}`}}const n=await t.json().catch(()=>null),o=[...new Set((n?.data??[]).map(a=>a?.id).filter(a=>typeof a=="string"&&a!==""))].sort();return o.length===0?{ok:!1,error:"upstream returned no models"}:{ok:!0,models:o.slice(0,B)}}catch(t){return{ok:!1,error:t instanceof Error?t.message:String(t)}}}async function U(r){try{const e=await fetch(r.url,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${r.apiKey}`},body:JSON.stringify({model:r.model,stream:!1,messages:r.messages}),signal:r.signal});if(!e.ok){const n=await e.text().catch(()=>"");return{ok:!1,error:`upstream ${e.status}${n?`: ${n.slice(0,300)}`:""}`}}const t=$(await e.json().catch(()=>null));return t===null?{ok:!1,error:"upstream returned no content"}:{ok:!0,content:t}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}async function L(r){const{req:e,res:t,baseUrl:n,model:o,apiKey:a,messages:i,system:d}=r,l=`${n.replace(/\/+$/,"")}/chat/completions`,m=[{role:"system",content:d},...i],g=new AbortController,v=setTimeout(()=>g.abort(),_);e.on("close",()=>g.abort()),t.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-accel-buffering":"no"});let b=!1;const f=s=>{if(!b)try{t.write(`data: ${JSON.stringify(s)}
2
2
 
3
- `)}catch{}},K=()=>{if(!b){b=!0;try{t.write(`data: {"done":true}
3
+ `)}catch{}},D=()=>{if(!b){b=!0;try{t.write(`data: {"done":true}
4
4
 
5
- `),t.end()}catch{}}},g=streamMemoKey(u,a),M={url:u,apiKey:n,model:a,messages:m,signal:l.signal};try{if(!streamSupported(g)){const c=await E(M);c.ok?d({delta:c.content}):d({error:c.error});return}const s=await fetch(u,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${n}`},body:JSON.stringify({model:a,stream:!0,messages:m}),signal:l.signal});if(!s.ok||!s.body){const c=await s.text().catch(()=>""),h=await E(M);h.ok?(rememberStreamSupport(g,!1),d({delta:h.content})):d({error:`upstream ${s.status}${c?`: ${c.slice(0,300)}`:""}`});return}if(!(s.headers.get("content-type")??"").includes("text/event-stream")){const c=A(await s.json().catch(()=>null));rememberStreamSupport(g,!1),d(c===null?{error:"upstream returned no content"}:{delta:c});return}rememberStreamSupport(g,!0);const U=s.body.getReader(),D=new TextDecoder;let y="";for(;;){const{done:c,value:h}=await U.read();if(c)break;y+=D.decode(h,{stream:!0});let w;for(;(w=y.indexOf(`
6
- `))>=0;){const $=y.slice(0,w).trim();if(y=y.slice(w+1),!$.startsWith("data:"))continue;const T=$.slice(5).trim();if(T==="[DONE]")return;try{const x=A(JSON.parse(T));x!==null&&d({delta:x})}catch{}}}}catch(s){d({error:s instanceof Error?s.message:String(s)})}finally{clearTimeout(_),K()}}
5
+ `),t.end()}catch{}}},y=streamMemoKey(l,o),k={url:l,apiKey:a,model:o,messages:m,signal:g.signal};try{if(!streamSupported(y)){const c=await U(k);c.ok?f({delta:c.content}):f({error:c.error});return}const s=await fetch(l,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a}`},body:JSON.stringify({model:o,stream:!0,messages:m}),signal:g.signal});if(!s.ok||!s.body){const c=await s.text().catch(()=>""),h=await U(k);h.ok?(rememberStreamSupport(y,!1),f({delta:h.content})):f({error:`upstream ${s.status}${c?`: ${c.slice(0,300)}`:""}`});return}if(!(s.headers.get("content-type")??"").includes("text/event-stream")){const c=$(await s.json().catch(()=>null));rememberStreamSupport(y,!1),f(c===null?{error:"upstream returned no content"}:{delta:c});return}rememberStreamSupport(y,!0);const E=s.body.getReader(),N=new TextDecoder;let p="";for(;;){const{done:c,value:h}=await E.read();if(c)break;p+=N.decode(h,{stream:!0});let S;for(;(S=p.indexOf(`
6
+ `))>=0;){const x=p.slice(0,S).trim();if(p=p.slice(S+1),!x.startsWith("data:"))continue;const A=x.slice(5).trim();if(A==="[DONE]")return;try{const K=$(JSON.parse(A));K!==null&&f({delta:K})}catch{}}}}catch(s){f({error:s instanceof Error?s.message:String(s)})}finally{clearTimeout(v),D()}}
@@ -1,3 +1,3 @@
1
- import{appendFile as F,mkdir as L,readdir as T,readFile as N,rm as j}from"node:fs/promises";import g from"node:path";import{getApiLogsDir as x}from"../db/paths.js";const w=8*1024,C=2e3,b=50,D=6;export const MAX_LOG_FILES=24;const I=200,O=1e3,H=new Set(["password","apikey","token","secret","authorization","cookie","x-weave-local"]);function y(n,t=0){if(typeof n=="string")return n.length>C?`[truncated ${n.length} chars]`:n;if(Array.isArray(n)){if(t>=D)return"[depth-limited]";const e=n.slice(0,b).map(i=>y(i,t+1));return n.length>b&&e.push(`[truncated ${n.length-b} items]`),e}if(n&&typeof n=="object"){if(t>=D)return"[depth-limited]";const e={};for(const[i,a]of Object.entries(n))e[i]=H.has(i.toLowerCase())?"[redacted]":y(a,t+1);return e}return n}function M(n,t){if(t>w)return`[truncated body ${t} bytes]`;try{return y(JSON.parse(n))}catch{return y(n)}}export function maskPath(n){return n.replace(/^(\/webhooks\/orchestrate\/)[^?]+/,"$1[redacted]")}export function logFileFor(n,t){const e=a=>String(a).padStart(2,"0"),i=`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())}T${e(t.getHours())}`;return g.join(n,`api-${i}.jsonl`)}function _(n){const t=g.basename(n).match(/^api-(\d{4}-\d{2}-\d{2}T\d{2})\.jsonl$/);return t?t[1]:null}const $=new WeakMap;export function noteRequestBody(n,t){$.get(n)?.(t)}export class ApiLogger{dir;chain=Promise.resolve();constructor(t={}){this.dir=t.dir??x()}begin(t,e){const i=Date.now(),a=[];let u=0,c=0,d="",h=0,l=!1;$.set(t,r=>{d=r,h=Buffer.byteLength(r,"utf8")});const f=r=>{const o=Buffer.isBuffer(r)?r:Buffer.from(typeof r=="string"?r:String(r??""),"utf8");if(c+=o.length,u<w){const s=o.subarray(0,w-u);a.push(s),u+=s.length}},m=e.write.bind(e),E=e.end.bind(e);let A="";const B=e.writeHead.bind(e);e.writeHead=((...r)=>{const o=r[1];if(o&&typeof o=="object"&&!Array.isArray(o)){const s=o,p=s["content-type"]??s["Content-Type"];typeof p=="string"&&(A=p)}return B(...r)}),e.write=((r,...o)=>(f(r),m(r,...o))),e.end=((r,...o)=>(typeof r!="function"&&r!=null&&f(r),E(r,...o)));const S=()=>{if(l)return;l=!0;const o=(String(e.getHeader("content-type")??"")||A).includes("event-stream"),s={ts:new Date(i).toISOString(),method:t.method??"GET",path:maskPath(t.url??"/"),status:e.statusCode,durationMs:Date.now()-i,ip:(t.socket?.remoteAddress??"").replace(/^::ffff:/,""),resBytes:c},p=t.headers["user-agent"];typeof p=="string"&&p&&(s.ua=p.slice(0,120)),h&&(s.req=M(d,h)),o?s.stream=!0:c&&(s.res=M(Buffer.concat(a).toString("utf8"),c)),e.writableEnded||(s.aborted=!0),this.write(logFileFor(this.dir,new Date(i)),`${JSON.stringify(s)}
2
- `)};e.on("finish",S),e.on("close",S)}write(t,e){this.chain=this.chain.then(async()=>{try{await L(this.dir,{recursive:!0}),await F(t,e,"utf8"),await this.purge()}catch{}})}async purge(){const t=(await T(this.dir)).filter(e=>_(e)!=null);if(!(t.length<=MAX_LOG_FILES)){t.sort();for(const e of t.slice(0,t.length-MAX_LOG_FILES))await j(g.join(this.dir,e),{force:!0})}}onIdle(){return this.chain}async query(t){const e=(await T(this.dir).catch(()=>[])).filter(d=>_(d)!=null).sort().reverse(),i=Math.min(Math.max(t.limit??I,1),O),a=t.from?Date.parse(t.from):NaN,u=t.to?Date.parse(t.to):NaN,c=[];for(const d of e){if(c.length>=i)break;const h=await N(g.join(this.dir,d),"utf8").catch(()=>"");for(const l of h.split(`
3
- `).reverse()){if(!l.trim())continue;let f;try{f=JSON.parse(l)}catch{continue}const m=Date.parse(f.ts);if(!(Number.isFinite(a)&&m<a)&&!(Number.isFinite(u)&&m>u)&&!(t.status!=null&&f.status!==t.status)&&!(t.method&&f.method.toUpperCase()!==t.method.toUpperCase())&&!(t.path&&!f.path.includes(t.path))&&(c.push(f),c.length>=i))break}}return{entries:c,files:e.length}}}
1
+ import{appendFile as B,mkdir as v,readdir as k,readFile as L,rm as M}from"node:fs/promises";import g from"node:path";import{getApiLogsDir as O}from"../db/paths.js";const y=8*1024,C=2e3,w=50,D=6;export const MAX_LOG_FILES=24;const H=200,T=1e3,E=new Set(["password","apikey","token","secret","authorization","cookie","x-weave-local"]);function m(r,t=0){if(typeof r=="string")return r.length>C?`[truncated ${r.length} chars]`:r;if(Array.isArray(r)){if(t>=D)return"[depth-limited]";const e=r.slice(0,w).map(o=>m(o,t+1));return r.length>w&&e.push(`[truncated ${r.length-w} items]`),e}if(r&&typeof r=="object"){if(t>=D)return"[depth-limited]";const e={};for(const[o,i]of Object.entries(r))e[o]=E.has(o.toLowerCase())?"[redacted]":m(i,t+1);return e}return r}function N(r,t){if(t>y)return`[truncated body ${t} bytes]`;try{return m(JSON.parse(r))}catch{return m(r)}}export function maskPath(r){return r.replace(/^(\/webhooks\/orchestrate\/)[^?]+/,"$1[redacted]")}export function logFileFor(r,t){const e=i=>String(i).padStart(2,"0"),o=`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())}T${e(t.getHours())}`;return g.join(r,`api-${o}.jsonl`)}function j(r){const t=g.basename(r).match(/^api-(\d{4}-\d{2}-\d{2}T\d{2})\.jsonl$/);return t?t[1]:null}const A=new WeakMap;export function noteRequestBody(r,t){A.get(r)?.(t)}export class ApiLogger{dir;chain=Promise.resolve();constructor(t={}){this.dir=t.dir??O()}begin(t,e){const o=Date.now(),i=[];let f=0,a=0,h="",d=0,l=!1;A.set(t,n=>{h=n,d=Buffer.byteLength(n,"utf8")});const c=n=>{const s=Buffer.isBuffer(n)?n:Buffer.from(typeof n=="string"?n:String(n??""),"utf8");if(a+=s.length,f<y){const u=s.subarray(0,y-f);i.push(u),f+=u.length}},p=e.write.bind(e),F=e.end.bind(e);let b="";const x=e.writeHead.bind(e);e.writeHead=((...n)=>{const s=n[1];if(s&&typeof s=="object"&&!Array.isArray(s)){const u=s,$=u["content-type"]??u["Content-Type"];typeof $=="string"&&(b=$)}return x(...n)}),e.write=((n,...s)=>(c(n),p(n,...s))),e.end=((n,...s)=>(typeof n!="function"&&n!=null&&c(n),F(n,...s)));const S=()=>{if(l)return;l=!0;const n=(String(e.getHeader("content-type")??"")||b).includes("event-stream"),s={ts:new Date(o).toISOString(),method:t.method??"GET",path:maskPath(t.url??"/"),status:e.statusCode,durationMs:Date.now()-o,ip:(t.socket?.remoteAddress??"").replace(/^::ffff:/,""),resBytes:a},u=t.headers["user-agent"];typeof u=="string"&&u&&(s.ua=u.slice(0,120)),d&&(s.req=N(h,d)),n?s.stream=!0:a&&(s.res=N(Buffer.concat(i).toString("utf8"),a)),e.writableEnded||(s.aborted=!0),this.write(logFileFor(this.dir,new Date(o)),`${JSON.stringify(s)}
2
+ `)};e.on("finish",S),e.on("close",S)}write(t,e){this.chain=this.chain.then(async()=>{try{await v(this.dir,{recursive:!0}),await B(t,e,"utf8"),await this.purge()}catch{}})}async purge(){const t=(await k(this.dir)).filter(e=>j(e)!=null);if(!(t.length<=MAX_LOG_FILES)){t.sort();for(const e of t.slice(0,t.length-MAX_LOG_FILES))await M(g.join(this.dir,e),{force:!0})}}onIdle(){return this.chain}async query(t){const e=(await k(this.dir).catch(()=>[])).filter(h=>j(h)!=null).sort().reverse(),o=Math.min(Math.max(t.limit??H,1),T),i=t.from?Date.parse(t.from):NaN,f=t.to?Date.parse(t.to):NaN,a=[];for(const h of e){if(a.length>=o)break;const d=await L(g.join(this.dir,h),"utf8").catch(()=>"");for(const l of d.split(`
3
+ `).reverse()){if(!l.trim())continue;let c;try{c=JSON.parse(l)}catch{continue}const p=Date.parse(c.ts);if(!(Number.isFinite(i)&&p<i)&&!(Number.isFinite(f)&&p>f)&&!(t.status!=null&&c.status!==t.status)&&!(t.method&&c.method.toUpperCase()!==t.method.toUpperCase())&&!(t.path&&!c.path.includes(t.path))&&(a.push(c),a.length>=o))break}}return{entries:a,files:e.length}}}
@@ -1 +1 @@
1
- import{clearedSessionCookie as c,sessionCookie as h}from"./dashboard-auth.js";import{readJson as i,sendJson as r}from"./http.js";const l=300,n=6,f=e=>new Promise(t=>setTimeout(t,e));export async function handleAuthRoutes(e,t,d,u){if(u!=="/auth"&&!u.startsWith("/auth/"))return!1;const o=d.auth;if(!o)return r(t,503,{error:"Auth subsystem unavailable"}),!0;if(u==="/auth/status"&&e.method==="GET")return r(t,200,{passwordSet:o.isPasswordSet(),authenticated:o.isAuthenticated(e.headers)}),!0;if(u==="/auth/login"&&e.method==="POST"){let s;try{s=await i(e)}catch{return r(t,400,{error:"Invalid JSON body"}),!0}const a=typeof s.password=="string"?s.password:"";return!a||!o.verifyPassword(a)?(await f(l),r(t,401,{error:"Invalid password"}),!0):(t.setHeader("set-cookie",h(o.issueSession())),r(t,200,{ok:!0}),!0)}if(u==="/auth/logout"&&e.method==="POST")return t.setHeader("set-cookie",c()),r(t,200,{ok:!0}),!0;if(u==="/auth/password"&&e.method==="PUT"){if(!o.isLocallyTrusted(e.headers))return r(t,401,{error:"Unauthorized (local token required)"}),!0;let s;try{s=await i(e)}catch{return r(t,400,{error:"Invalid JSON body"}),!0}const a=typeof s.next=="string"?s.next:"";return a.length<n?(r(t,400,{error:`Password must be at least ${n} characters`}),!0):(o.setPassword(a),r(t,200,{ok:!0}),!0)}return r(t,404,{error:"Not found"}),!0}
1
+ import{clearedSessionCookie as h,sessionCookie as c}from"./dashboard-auth.js";import{readJson as i,sendJson as r}from"./http.js";const l=300,u=6,f=e=>new Promise(t=>setTimeout(t,e));export async function handleAuthRoutes(e,t,d,a){if(a!=="/auth"&&!a.startsWith("/auth/"))return!1;const o=d.auth;if(!o)return r(t,503,{error:"Auth subsystem unavailable"}),!0;if(a==="/auth/status"&&e.method==="GET")return r(t,200,{passwordSet:o.isPasswordSet(),authenticated:o.isAuthenticated(e.headers)}),!0;if(a==="/auth/login"&&e.method==="POST"){let s;try{s=await i(e)}catch{return r(t,400,{error:"Invalid JSON body"}),!0}const n=typeof s.password=="string"?s.password:"";return!n||!o.verifyPassword(n)?(await f(l),r(t,401,{error:"Invalid password"}),!0):(t.setHeader("set-cookie",c(o.issueSession())),r(t,200,{ok:!0}),!0)}if(a==="/auth/logout"&&e.method==="POST")return t.setHeader("set-cookie",h()),r(t,200,{ok:!0}),!0;if(a==="/auth/password"&&e.method==="PUT"){if(!o.isLocallyTrusted(e.headers))return r(t,401,{error:"Unauthorized (local token required)"}),!0;let s;try{s=await i(e)}catch{return r(t,400,{error:"Invalid JSON body"}),!0}const n=typeof s.next=="string"?s.next:"";return n.length<u?(r(t,400,{error:`Password must be at least ${u} characters`}),!0):(o.setPassword(n),r(t,200,{ok:!0}),!0)}return r(t,404,{error:"Not found"}),!0}
@@ -1,4 +1,4 @@
1
- import{spawnSync as l}from"node:child_process";import{fileURLToPath as m}from"node:url";import{mkdirSync as a,writeFileSync as i,unlinkSync as c}from"node:fs";import{homedir as p}from"node:os";import r from"node:path";import{getAutoStartScriptPath as s,getDataDir as f}from"../db/paths.js";import{readDaemonSettingsSync as d}from"./settings.js";const o="weave-daemon",u="HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";export function relaunchArgs(){return[process.execPath,...process.execArgv.map(t=>{if(t!=="tsx"&&!t.startsWith("tsx/"))return t;try{return m(import.meta.resolve(t))}catch{return t}}),r.resolve(process.argv[1]??process.argv[0])]}function h(t){return{platform:t.platform??process.platform,dataDir:t.dataDir??f(),home:t.home??p(),run:t.run??((e,n)=>({status:l(e,n,{stdio:"ignore"}).status}))}}function g(t){return t.map(e=>`"${e}"`).join(" ")}function y(t){const e=s(t.dataDir);a(r.dirname(e),{recursive:!0});const n=g(relaunchArgs());i(e,`' Generated by weave \u2014 daemon auto-start. Do not edit.
1
+ import{spawnSync as p}from"node:child_process";import{fileURLToPath as m}from"node:url";import{mkdirSync as a,writeFileSync as i,unlinkSync as c}from"node:fs";import{homedir as l}from"node:os";import r from"node:path";import{getAutoStartScriptPath as s,getDataDir as d}from"../db/paths.js";import{readDaemonSettingsSync as f}from"./settings.js";const o="weave-daemon",u="HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";export function relaunchArgs(){return[process.execPath,...process.execArgv.map(t=>{if(t!=="tsx"&&!t.startsWith("tsx/"))return t;try{return m(import.meta.resolve(t))}catch{return t}}),r.resolve(process.argv[1]??process.argv[0])]}function g(t){return{platform:t.platform??process.platform,dataDir:t.dataDir??d(),home:t.home??l(),run:t.run??((e,n)=>({status:p(e,n,{stdio:"ignore"}).status}))}}function h(t){return t.map(e=>`"${e}"`).join(" ")}function y(t){const e=s(t.dataDir);a(r.dirname(e),{recursive:!0});const n=h(relaunchArgs());i(e,`' Generated by weave \u2014 daemon auto-start. Do not edit.
2
2
  CreateObject("WScript.Shell").Run "${n.replace(/"/g,'""')}", 0, False
3
3
  `),t.run("reg",["add",u,"/v",o,"/t","REG_SZ","/d",`wscript.exe "${e}"`,"/f"])}function v(t){t.run("reg",["delete",u,"/v",o,"/f"]);try{c(s(t.dataDir))}catch{}}function w(t){const e=n=>n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");return`<?xml version="1.0" encoding="UTF-8"?>
4
4
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -13,5 +13,5 @@ CreateObject("WScript.Shell").Run "${n.replace(/"/g,'""')}", 0, False
13
13
  <key>RunAtLoad</key><true/>
14
14
  </dict>
15
15
  </plist>
16
- `}function L(t){const e=r.join(t.home,"Library","LaunchAgents","com.weave.daemon.plist");a(r.dirname(e),{recursive:!0}),i(e,w(relaunchArgs())),t.run("launchctl",["unload",e]),t.run("launchctl",["load",e])}function D(t){const e=r.join(t.home,"Library","LaunchAgents","com.weave.daemon.plist");t.run("launchctl",["unload",e]);try{c(e)}catch{}}function k(t){return t.map(e=>/[\s"]/.test(e)?`"${e}"`:e).join(" ")}function x(t){const e=r.join(t.home,".config","autostart",`${o}.desktop`);a(r.dirname(e),{recursive:!0}),i(e,["[Desktop Entry]","Type=Application","Name=weave daemon",`Exec=${k(relaunchArgs())}`,"X-GNOME-Autostart-enabled=true",""].join(`
17
- `))}function S(t){try{c(r.join(t.home,".config","autostart",`${o}.desktop`))}catch{}}export function applyLaunchOnLogin(t,e={}){try{const n=h(e);n.platform==="win32"?t?y(n):v(n):n.platform==="darwin"?t?L(n):D(n):t?x(n):S(n)}catch(n){console.error(`[weave] auto-start ${t?"enable":"disable"} failed:`,n)}}export function syncLaunchOnLogin(t={}){const e=d().startup;applyLaunchOnLogin(e?.launchOnLogin??!1,t)}
16
+ `}function L(t){const e=r.join(t.home,"Library","LaunchAgents","com.weave.daemon.plist");a(r.dirname(e),{recursive:!0}),i(e,w(relaunchArgs())),t.run("launchctl",["unload",e]),t.run("launchctl",["load",e])}function D(t){const e=r.join(t.home,"Library","LaunchAgents","com.weave.daemon.plist");t.run("launchctl",["unload",e]);try{c(e)}catch{}}function S(t){return t.map(e=>/[\s"]/.test(e)?`"${e}"`:e).join(" ")}function k(t){const e=r.join(t.home,".config","autostart",`${o}.desktop`);a(r.dirname(e),{recursive:!0}),i(e,["[Desktop Entry]","Type=Application","Name=weave daemon",`Exec=${S(relaunchArgs())}`,"X-GNOME-Autostart-enabled=true",""].join(`
17
+ `))}function x(t){try{c(r.join(t.home,".config","autostart",`${o}.desktop`))}catch{}}export function applyLaunchOnLogin(t,e={}){try{const n=g(e);n.platform==="win32"?t?y(n):v(n):n.platform==="darwin"?t?L(n):D(n):t?k(n):x(n)}catch(n){console.error(`[weave] auto-start ${t?"enable":"disable"} failed:`,n)}}export function syncLaunchOnLogin(t={}){const e=f().startup;applyLaunchOnLogin(e?.launchOnLogin??!1,t)}
@@ -1 +1 @@
1
- import{z as n}from"zod";import{isHarness as f}from"@weavecode/core";import{WEAVE_VERSION as p}from"../version.js";import{readJson as d,sendJson as s}from"./http.js";import{captureSurfaces as i}from"../surfaces.js";const l=n.object({harness:n.string(),enabled:n.boolean()});export async function handleCaptureRoutes(o,t,u,c){if(c!=="/capture")return!1;if(o.method==="GET"){const e=await Promise.all(i().map(async({harness:a,surface:r})=>({harness:a,...await r.readUserCapture()})));return s(t,200,{rows:e}),!0}if(o.method==="PUT"){let e;try{e=l.parse(await d(o))}catch(r){return s(t,400,{error:r instanceof Error?r.message:"Invalid body"}),!0}if(!f(e.harness))return s(t,400,{error:`Unknown harness: ${e.harness}`}),!0;const a=i().find(r=>r.harness===e.harness);if(!a)return s(t,400,{error:`No capture surface for harness: ${e.harness}`}),!0;try{if(e.enabled){await a.surface.installUserCapture({version:p});for(const r of u.projects.list())await a.surface.stripProjectCapture(r.path)}else await a.surface.uninstallUserCapture();u.dataBus?.emit({key:"capture"}),s(t,200,{harness:a.harness,...await a.surface.readUserCapture()})}catch(r){s(t,400,{error:r instanceof Error?r.message:"Capture update failed"})}return!0}return s(t,405,{error:"Method not allowed"}),!0}
1
+ import{z as o}from"zod";import{isHarness as f}from"@weavecode/core";import{WEAVE_VERSION as p}from"../version.js";import{readJson as h,sendJson as t}from"./http.js";import{captureSurfaces as u}from"../surfaces.js";const d=o.object({harness:o.string(),enabled:o.boolean()});export async function handleCaptureRoutes(n,s,i,c){if(c!=="/capture")return!1;if(n.method==="GET"){const e=await Promise.all(u().map(async({harness:a,surface:r})=>({harness:a,...await r.readUserCapture()})));return t(s,200,{rows:e}),!0}if(n.method==="PUT"){let e;try{e=d.parse(await h(n))}catch(r){return t(s,400,{error:r instanceof Error?r.message:"Invalid body"}),!0}if(!f(e.harness))return t(s,400,{error:`Unknown harness: ${e.harness}`}),!0;const a=u().find(r=>r.harness===e.harness);if(!a)return t(s,400,{error:`No capture surface for harness: ${e.harness}`}),!0;try{if(e.enabled){await a.surface.installUserCapture({version:p});for(const r of i.projects.list())await a.surface.stripProjectCapture(r.path)}else await a.surface.uninstallUserCapture();i.dataBus?.emit({key:"capture"}),t(s,200,{harness:a.harness,...await a.surface.readUserCapture()})}catch(r){t(s,400,{error:r instanceof Error?r.message:"Capture update failed"})}return!0}return t(s,405,{error:"Method not allowed"}),!0}
@@ -1 +1 @@
1
- import{homedir as J}from"node:os";import{access as K}from"node:fs/promises";import{isHarness as k}from"@weavecode/core";import{configSurfaceFor as j}from"../surfaces.js";import{baselineSnapshot as N,createProfile as E,LASTSEEN_ID as C,listBackups as L,listProfiles as m,profileKeyOf as $,readBackup as F,readSnapshot as A,removeProfile as D,renameProfile as V,pushBackup as S,saveProfile as M,setActive as R,syncBaseline as O,writeSnapshot as G}from"../config/profiles.js";import{readBody as H,sendJson as n}from"./http.js";import{getHarnessConfigDir as _}from"../db/paths.js";const z=["user","project","projectLocal","global"];function u(f,t){return $(f,t.projectId)}function T(f){return typeof f=="string"&&z.includes(f)?f:null}function g(f,t){return f.serializeRaw(t)}function W(f,t,p){const h=f.files(p).find(y=>y.id===t);return h?h.path(p):""}async function U(f){try{const t=JSON.parse(await H(f));return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:null}catch{return null}}async function Q(f){if(!f)return!1;try{return await K(f),!0}catch{return!1}}async function x(f,t,p,h,y){const s=u(h,y),o=W(p,h,y),e=await p.read(h,y),r=g(p,e),c=await m(f,t,s),i=await N(f,t,s,c);i||await G(f,t,s,C,e);const a=i?g(p,i):g(p,e);return{harness:t,file:h,path:o,exists:await Q(o),values:e,managedKeys:p.managedKeys(e),managedEntries:p.managedEntries(e),profiles:c.profiles,activeId:c.activeId,liveText:r,activeText:a,drifted:a!==r,backups:await L(f,t,s)}}function P(f,t,p){let h=null,y=null;if(t==="project"||t==="projectLocal"){const s=Number(p);if(!Number.isInteger(s)||s<=0)return"\u9700\u8981 projectId";const o=f.projects.getById(s);if(!o)return"\u9879\u76EE\u4E0D\u5B58\u5728";h=o.path,y=s}return{projectPath:h,projectId:y,homedir:J()}}export async function handleConfigRoutes(f,t,p,h,y){if(!h.startsWith("/harness-config"))return!1;const s=_();if(h==="/harness-config/catalog"&&f.method==="GET"){const o=y.searchParams.get("harness");if(!k(o))return n(t,400,{error:"Unknown harness"}),!0;const e=j(o);if(!e)return n(t,200,{supported:!1}),!0;const r=T(y.searchParams.get("file"))??"user",c={projectPath:null,projectId:null,homedir:J()},i=e.catalog(r);return n(t,200,{supported:!0,harness:o,file:r,rawFormat:e.rawFormat,files:e.files(c).map(a=>({id:a.id,profiles:a.profiles})),groups:i.groups,keys:i.keys,envVars:i.envVars}),!0}if(h==="/harness-config"&&f.method==="GET"){const o=y.searchParams.get("harness"),e=T(y.searchParams.get("file"));if(!k(o)||!e)return n(t,400,{error:"Unknown harness or file"}),!0;const r=j(o);if(!r)return n(t,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const c=P(p,e,y.searchParams.get("projectId"));return typeof c=="string"?(n(t,400,{error:c}),!0):(n(t,200,await x(s,o,r,e,c)),!0)}if(h==="/harness-config/values"&&f.method==="PUT"){const o=await U(f);if(!o)return n(t,400,{error:"Invalid JSON body"}),!0;const e=o.harness,r=T(o.file);if(!k(e)||!r)return n(t,400,{error:"Unknown harness or file"}),!0;const c=j(e);if(!c)return n(t,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const i=P(p,r,o.projectId);if(typeof i=="string")return n(t,400,{error:i}),!0;const a=o.values;if(typeof a!="object"||a===null||Array.isArray(a))return n(t,400,{error:'Missing "values"'}),!0;try{const l=await c.read(r,i);await S(s,e,u(r,i),l),await c.write(r,i,a);const b=await m(s,e,u(r,i));await O(s,e,u(r,i),b,await c.read(r,i))}catch(l){return n(t,400,{error:l.message}),!0}return n(t,200,await x(s,e,c,r,i)),!0}if(h==="/harness-config/raw"&&f.method==="PUT"){const o=await U(f);if(!o)return n(t,400,{error:"Invalid JSON body"}),!0;const e=o.harness,r=T(o.file);if(!k(e)||!r)return n(t,400,{error:"Unknown harness or file"}),!0;const c=j(e);if(!c)return n(t,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const i=P(p,r,o.projectId);if(typeof i=="string")return n(t,400,{error:i}),!0;let a;try{a=c.parseRaw(String(o.text??""))}catch(l){return n(t,400,{error:`\u4E0D\u662F\u5408\u6CD5${c.rawFormat==="toml"?" TOML":" JSON"}\uFF1A${l.message}`}),!0}try{const l=await c.read(r,i);await S(s,e,u(r,i),l),await c.write(r,i,a);const b=await m(s,e,u(r,i));await O(s,e,u(r,i),b,await c.read(r,i))}catch(l){return n(t,400,{error:l.message}),!0}return n(t,200,await x(s,e,c,r,i)),!0}if(h==="/harness-config/profile"&&f.method==="POST"){const o=await U(f);if(!o)return n(t,400,{error:"Invalid JSON body"}),!0;const e=o.harness,r=T(o.file),c=o.action;if(!k(e)||!r||typeof c!="string")return n(t,400,{error:"Unknown harness, file or action"}),!0;const i=j(e);if(!i)return n(t,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const a=P(p,r,o.projectId);if(typeof a=="string")return n(t,400,{error:a}),!0;const l=typeof o.id=="string"?o.id:"",b=typeof o.name=="string"?o.name.trim():"",B=typeof o.values=="object"&&o.values!==null&&!Array.isArray(o.values)?o.values:null;switch(c){case"list":{const d=await m(s,e,u(r,a));return n(t,200,d),!0}case"create":{const d=await m(s,e,u(r,a)),w=await E(s,e,u(r,a),b||`\u914D\u7F6E ${d.profiles.length+1}`,B??await i.read(r,a));return n(t,200,{profile:w,state:await m(s,e,u(r,a))}),!0}case"save":return(await m(s,e,u(r,a))).profiles.some(w=>w.id===l)?(await M(s,e,u(r,a),l,B??await i.read(r,a)),n(t,200,await m(s,e,u(r,a))),!0):(n(t,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0);case"compare":{const d=o.target;if(d==="live")return n(t,200,{text:g(i,await i.read(r,a))}),!0;if(d==="backup"){const v=typeof o.backupId=="string"?o.backupId:"",I=await F(s,e,u(r,a),v);return I?(n(t,200,{text:g(i,I)}),!0):(n(t,404,{error:"\u5907\u4EFD\u4E0D\u5B58\u5728"}),!0)}const w=await A(s,e,u(r,a),l);return w?(n(t,200,{text:g(i,w)}),!0):(n(t,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0)}case"duplicate":{const d=await A(s,e,u(r,a),l);if(!d)return n(t,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0;const w=await m(s,e,u(r,a)),v=await E(s,e,u(r,a),b||`\u914D\u7F6E ${w.profiles.length+1}`,d);return n(t,200,{profile:v,state:await m(s,e,u(r,a))}),!0}case"rename":return b?(await V(s,e,u(r,a),l,b),n(t,200,await m(s,e,u(r,a))),!0):(n(t,400,{error:"\u7F3A\u5C11\u540D\u79F0"}),!0);case"remove":return await D(s,e,u(r,a),l),n(t,200,await m(s,e,u(r,a))),!0;case"activate":{const d=await A(s,e,u(r,a),l);if(!d)return n(t,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0;const w=await i.read(r,a);if(o.confirm!==!0)return n(t,200,{requiresConfirm:!0,liveText:g(i,w),profileText:g(i,d)}),!0;try{await S(s,e,u(r,a),w),await i.write(r,a,d),await R(s,e,u(r,a),l)}catch(v){return n(t,400,{error:v.message}),!0}return n(t,200,await x(s,e,i,r,a)),!0}case"acceptDrift":{const d=await m(s,e,u(r,a)),w=await N(s,e,u(r,a),d);return w&&await S(s,e,u(r,a),w),await O(s,e,u(r,a),d,await i.read(r,a)),n(t,200,await x(s,e,i,r,a)),!0}case"restoreBaseline":{const d=await m(s,e,u(r,a)),w=await N(s,e,u(r,a),d);if(!w)return n(t,404,{error:"\u6CA1\u6709\u53EF\u6062\u590D\u7684\u57FA\u7EBF"}),!0;const v=await i.read(r,a);if(o.confirm!==!0)return n(t,200,{requiresConfirm:!0,liveText:g(i,v),baselineText:g(i,w)}),!0;try{await S(s,e,u(r,a),v),await i.write(r,a,w),await O(s,e,u(r,a),d,w)}catch(I){return n(t,400,{error:I.message}),!0}return n(t,200,await x(s,e,i,r,a)),!0}case"restoreBackup":{const d=typeof o.backupId=="string"?o.backupId:"",w=await F(s,e,u(r,a),d);if(!w)return n(t,404,{error:"\u5907\u4EFD\u4E0D\u5B58\u5728"}),!0;const v=await i.read(r,a);if(o.confirm!==!0)return n(t,200,{requiresConfirm:!0,liveText:g(i,v),backupText:g(i,w)}),!0;try{await S(s,e,u(r,a),v),await i.write(r,a,w);const I=await m(s,e,u(r,a));await O(s,e,u(r,a),I,w)}catch(I){return n(t,400,{error:I.message}),!0}return n(t,200,await x(s,e,i,r,a)),!0}default:return n(t,400,{error:`\u672A\u77E5\u52A8\u4F5C\uFF1A${c}`}),!0}}if(h==="/harness-config/models"&&f.method==="POST"){const o=await U(f);if(!o)return n(t,400,{error:"Invalid JSON body"}),!0;const e=o.harness,r=T(o.file)??"user";if(!k(e))return n(t,400,{error:"Unknown harness"}),!0;const c=j(e);if(!c)return n(t,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const i=P(p,r,o.projectId);if(typeof i=="string")return n(t,400,{error:i}),!0;try{const a=await c.read(r,i),l=await c.models({values:a,file:r,homedir:i.homedir,baseUrl:typeof o.baseUrl=="string"?o.baseUrl:null,apiKey:typeof o.apiKey=="string"?o.apiKey:null,authToken:typeof o.authToken=="string"?o.authToken:null});n(t,200,l)}catch(a){n(t,502,{error:a.message})}return!0}if(h==="/harness-config/preview"&&f.method==="POST"){const o=await U(f);if(!o)return n(t,400,{error:"Invalid JSON body"}),!0;const e=o.harness,r=T(o.file);if(!k(e)||!r)return n(t,400,{error:"Unknown harness or file"}),!0;const c=j(e);if(!c)return n(t,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const i=P(p,r,o.projectId);if(typeof i=="string")return n(t,400,{error:i}),!0;const a=o.values;if(typeof a!="object"||a===null||Array.isArray(a))return n(t,400,{error:'Missing "values"'}),!0;try{const l=await c.read(r,i);n(t,200,{before:g(c,l),after:g(c,a)})}catch(l){n(t,400,{error:l.message})}return!0}return n(t,404,{error:"Not found"}),!0}
1
+ import{homedir as O}from"node:os";import{access as C}from"node:fs/promises";import{isHarness as B}from"@weavecode/core";import{configSurfaceFor as D}from"../surfaces.js";import{baselineSnapshot as P,createProfile as U,LASTSEEN_ID as J,listBackups as K,listProfiles as m,profileKeyOf as $,readBackup as N,readSnapshot as S,removeProfile as L,renameProfile as q,pushBackup as k,saveProfile as M,setActive as R,syncBaseline as j,writeSnapshot as G}from"../config/profiles.js";import{readBody as H,sendJson as n}from"./http.js";import{getHarnessConfigDir as V}from"../db/paths.js";const z=["user","project","projectLocal","global"];function u(f,r){return $(f,r.projectId)}function b(f){return typeof f=="string"&&z.includes(f)?f:null}function g(f,r){return f.serializeRaw(r)}function W(f,r,p){const h=f.files(p).find(y=>y.id===r);return h?h.path(p):""}async function T(f){try{const r=JSON.parse(await H(f));return typeof r=="object"&&r!==null&&!Array.isArray(r)?r:null}catch{return null}}async function _(f){if(!f)return!1;try{return await C(f),!0}catch{return!1}}async function I(f,r,p,h,y){const o=u(h,y),i=W(p,h,y),t=await p.read(h,y),e=g(p,t),c=await m(f,r,o),s=await P(f,r,o,c);s||await G(f,r,o,J,t);const a=s?g(p,s):g(p,t);return{harness:r,file:h,path:i,exists:await _(i),values:t,managedKeys:p.managedKeys(t),managedEntries:p.managedEntries(t),profiles:c.profiles,activeId:c.activeId,liveText:e,activeText:a,drifted:a!==e,backups:await K(f,r,o)}}function A(f,r,p){let h=null,y=null;if(r==="project"||r==="projectLocal"){const o=Number(p);if(!Number.isInteger(o)||o<=0)return"\u9700\u8981 projectId";const i=f.projects.getById(o);if(!i)return"\u9879\u76EE\u4E0D\u5B58\u5728";h=i.path,y=o}return{projectPath:h,projectId:y,homedir:O()}}export async function handleConfigRoutes(f,r,p,h,y){if(!h.startsWith("/harness-config"))return!1;const o=V();if(h==="/harness-config/catalog"&&f.method==="GET"){const i=y.searchParams.get("harness");if(!B(i))return n(r,400,{error:"Unknown harness"}),!0;const t=D(i);if(!t)return n(r,200,{supported:!1}),!0;const e=b(y.searchParams.get("file"))??"user",c={projectPath:null,projectId:null,homedir:O()},s=t.catalog(e);return n(r,200,{supported:!0,harness:i,file:e,rawFormat:t.rawFormat,files:t.files(c).map(a=>({id:a.id,profiles:a.profiles})),groups:s.groups,keys:s.keys,envVars:s.envVars}),!0}if(h==="/harness-config"&&f.method==="GET"){const i=y.searchParams.get("harness"),t=b(y.searchParams.get("file"));if(!B(i)||!t)return n(r,400,{error:"Unknown harness or file"}),!0;const e=D(i);if(!e)return n(r,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const c=A(p,t,y.searchParams.get("projectId"));return typeof c=="string"?(n(r,400,{error:c}),!0):(n(r,200,await I(o,i,e,t,c)),!0)}if(h==="/harness-config/values"&&f.method==="PUT"){const i=await T(f);if(!i)return n(r,400,{error:"Invalid JSON body"}),!0;const t=i.harness,e=b(i.file);if(!B(t)||!e)return n(r,400,{error:"Unknown harness or file"}),!0;const c=D(t);if(!c)return n(r,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const s=A(p,e,i.projectId);if(typeof s=="string")return n(r,400,{error:s}),!0;const a=i.values;if(typeof a!="object"||a===null||Array.isArray(a))return n(r,400,{error:'Missing "values"'}),!0;try{const l=await c.read(e,s);await k(o,t,u(e,s),l),await c.write(e,s,a);const v=await m(o,t,u(e,s));await j(o,t,u(e,s),v,await c.read(e,s))}catch(l){return n(r,400,{error:l.message}),!0}return n(r,200,await I(o,t,c,e,s)),!0}if(h==="/harness-config/raw"&&f.method==="PUT"){const i=await T(f);if(!i)return n(r,400,{error:"Invalid JSON body"}),!0;const t=i.harness,e=b(i.file);if(!B(t)||!e)return n(r,400,{error:"Unknown harness or file"}),!0;const c=D(t);if(!c)return n(r,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const s=A(p,e,i.projectId);if(typeof s=="string")return n(r,400,{error:s}),!0;let a;try{a=c.parseRaw(String(i.text??""))}catch(l){return n(r,400,{error:`\u4E0D\u662F\u5408\u6CD5${c.rawFormat==="toml"?" TOML":" JSON"}\uFF1A${l.message}`}),!0}try{const l=await c.read(e,s);await k(o,t,u(e,s),l),await c.write(e,s,a);const v=await m(o,t,u(e,s));await j(o,t,u(e,s),v,await c.read(e,s))}catch(l){return n(r,400,{error:l.message}),!0}return n(r,200,await I(o,t,c,e,s)),!0}if(h==="/harness-config/profile"&&f.method==="POST"){const i=await T(f);if(!i)return n(r,400,{error:"Invalid JSON body"}),!0;const t=i.harness,e=b(i.file),c=i.action;if(!B(t)||!e||typeof c!="string")return n(r,400,{error:"Unknown harness, file or action"}),!0;const s=D(t);if(!s)return n(r,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const a=A(p,e,i.projectId);if(typeof a=="string")return n(r,400,{error:a}),!0;const l=typeof i.id=="string"?i.id:"",v=typeof i.name=="string"?i.name.trim():"",x=typeof i.values=="object"&&i.values!==null&&!Array.isArray(i.values)?i.values:null;switch(c){case"list":{const w=await m(o,t,u(e,a));return n(r,200,w),!0}case"create":{const w=await m(o,t,u(e,a)),d=await U(o,t,u(e,a),v||`\u914D\u7F6E ${w.profiles.length+1}`,x??await s.read(e,a));return n(r,200,{profile:d,state:await m(o,t,u(e,a))}),!0}case"save":return(await m(o,t,u(e,a))).profiles.some(w=>w.id===l)?(await M(o,t,u(e,a),l,x??await s.read(e,a)),n(r,200,await m(o,t,u(e,a))),!0):(n(r,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0);case"compare":{const w=i.target;if(w==="live")return n(r,200,{text:g(s,await s.read(e,a))}),!0;if(w==="backup"){const E=typeof i.backupId=="string"?i.backupId:"",F=await N(o,t,u(e,a),E);return F?(n(r,200,{text:g(s,F)}),!0):(n(r,404,{error:"\u5907\u4EFD\u4E0D\u5B58\u5728"}),!0)}const d=await S(o,t,u(e,a),l);return d?(n(r,200,{text:g(s,d)}),!0):(n(r,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0)}case"duplicate":{const w=await S(o,t,u(e,a),l);if(!w)return n(r,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0;const d=await m(o,t,u(e,a)),E=await U(o,t,u(e,a),v||`\u914D\u7F6E ${d.profiles.length+1}`,w);return n(r,200,{profile:E,state:await m(o,t,u(e,a))}),!0}case"rename":return v?(await q(o,t,u(e,a),l,v),n(r,200,await m(o,t,u(e,a))),!0):(n(r,400,{error:"\u7F3A\u5C11\u540D\u79F0"}),!0);case"remove":return await L(o,t,u(e,a),l),n(r,200,await m(o,t,u(e,a))),!0;case"activate":{const w=await S(o,t,u(e,a),l);if(!w)return n(r,404,{error:"\u914D\u7F6E\u4E0D\u5B58\u5728"}),!0;const d=await s.read(e,a);if(i.confirm!==!0)return n(r,200,{requiresConfirm:!0,liveText:g(s,d),profileText:g(s,w)}),!0;try{await k(o,t,u(e,a),d),await s.write(e,a,w),await R(o,t,u(e,a),l)}catch(E){return n(r,400,{error:E.message}),!0}return n(r,200,await I(o,t,s,e,a)),!0}case"acceptDrift":{const w=await m(o,t,u(e,a)),d=await P(o,t,u(e,a),w);return d&&await k(o,t,u(e,a),d),await j(o,t,u(e,a),w,await s.read(e,a)),n(r,200,await I(o,t,s,e,a)),!0}case"restoreBaseline":{const w=await m(o,t,u(e,a)),d=await P(o,t,u(e,a),w);if(!d)return n(r,404,{error:"\u6CA1\u6709\u53EF\u6062\u590D\u7684\u57FA\u7EBF"}),!0;const E=await s.read(e,a);if(i.confirm!==!0)return n(r,200,{requiresConfirm:!0,liveText:g(s,E),baselineText:g(s,d)}),!0;try{await k(o,t,u(e,a),E),await s.write(e,a,d),await j(o,t,u(e,a),w,d)}catch(F){return n(r,400,{error:F.message}),!0}return n(r,200,await I(o,t,s,e,a)),!0}case"restoreBackup":{const w=typeof i.backupId=="string"?i.backupId:"",d=await N(o,t,u(e,a),w);if(!d)return n(r,404,{error:"\u5907\u4EFD\u4E0D\u5B58\u5728"}),!0;const E=await s.read(e,a);if(i.confirm!==!0)return n(r,200,{requiresConfirm:!0,liveText:g(s,E),backupText:g(s,d)}),!0;try{await k(o,t,u(e,a),E),await s.write(e,a,d);const F=await m(o,t,u(e,a));await j(o,t,u(e,a),F,d)}catch(F){return n(r,400,{error:F.message}),!0}return n(r,200,await I(o,t,s,e,a)),!0}default:return n(r,400,{error:`\u672A\u77E5\u52A8\u4F5C\uFF1A${c}`}),!0}}if(h==="/harness-config/models"&&f.method==="POST"){const i=await T(f);if(!i)return n(r,400,{error:"Invalid JSON body"}),!0;const t=i.harness,e=b(i.file)??"user";if(!B(t))return n(r,400,{error:"Unknown harness"}),!0;const c=D(t);if(!c)return n(r,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const s=A(p,e,i.projectId);if(typeof s=="string")return n(r,400,{error:s}),!0;try{const a=await c.read(e,s),l=await c.models({values:a,file:e,homedir:s.homedir,baseUrl:typeof i.baseUrl=="string"?i.baseUrl:null,apiKey:typeof i.apiKey=="string"?i.apiKey:null,authToken:typeof i.authToken=="string"?i.authToken:null});n(r,200,l)}catch(a){n(r,502,{error:a.message})}return!0}if(h==="/harness-config/preview"&&f.method==="POST"){const i=await T(f);if(!i)return n(r,400,{error:"Invalid JSON body"}),!0;const t=i.harness,e=b(i.file);if(!B(t)||!e)return n(r,400,{error:"Unknown harness or file"}),!0;const c=D(t);if(!c)return n(r,400,{error:"\u914D\u7F6E\u9762\u672A\u5B9E\u73B0"}),!0;const s=A(p,e,i.projectId);if(typeof s=="string")return n(r,400,{error:s}),!0;const a=i.values;if(typeof a!="object"||a===null||Array.isArray(a))return n(r,400,{error:'Missing "values"'}),!0;try{const l=await c.read(e,s);n(r,200,{before:g(c,l),after:g(c,a)})}catch(l){n(r,400,{error:l.message})}return!0}return n(r,404,{error:"Not found"}),!0}
@@ -1 +1 @@
1
- const d=[{min:0,max:59},{min:0,max:23},{min:1,max:31},{min:1,max:12},{min:0,max:7}];export function parseCron(t){const n=t.trim().split(/\s+/);if(n.length!==5)return null;const e=[];for(let u=0;u<5;u++){const r=a(n[u],d[u].min,d[u].max);if(!r)return null;e.push(r)}const s=[...new Set(e[4].map(u=>u===7?0:u))].sort((u,r)=>u-r);return{minutes:e[0],hours:e[1],doms:e[2],months:e[3],dows:s,domAny:n[2]==="*",dowAny:n[4]==="*"}}function a(t,n,e){const s=new Set;for(const u of t.split(",")){const[r,m]=u.split("/");if(r===void 0)return null;const c=m===void 0?1:Number(m);if(!Number.isInteger(c)||c<1||c>e)return null;let i,o;if(r==="*")i=n,o=e;else if(r.includes("-")){const[l,g]=r.split("-");i=Number(l),o=Number(g)}else i=Number(r),o=m===void 0?i:e;if(!Number.isInteger(i)||!Number.isInteger(o)||i<n||o>e||i>o)return null;for(let l=i;l<=o;l+=c)s.add(l)}return s.size===0?null:[...s].sort((u,r)=>u-r)}function f(t,n){const e=t.doms.includes(n.getDate()),s=t.dows.includes(n.getDay());return t.domAny&&t.dowAny?!0:t.domAny?s:t.dowAny?e:e||s}export function matchesMinute(t,n){return t.minutes.includes(n.getMinutes())&&t.hours.includes(n.getHours())&&t.months.includes(n.getMonth()+1)&&f(t,n)}export function nextRunAt(t,n=new Date){const e=new Date(n.getTime());e.setSeconds(0,0),e.setMinutes(e.getMinutes()+1);const s=new Date(n.getTime()+366*864e5);for(;e<=s;){if(!t.months.includes(e.getMonth()+1)){e.setMonth(e.getMonth()+1,1),e.setHours(0,0,0,0);continue}if(!f(t,e)){e.setDate(e.getDate()+1),e.setHours(0,0,0,0);continue}if(!t.hours.includes(e.getHours())){e.setHours(e.getHours()+1,0,0,0);continue}if(!t.minutes.includes(e.getMinutes())){e.setMinutes(e.getMinutes()+1,0,0);continue}return e.toISOString()}return null}export function minuteKey(t){const n=e=>String(e).padStart(2,"0");return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}`}
1
+ const d=[{min:0,max:59},{min:0,max:23},{min:1,max:31},{min:1,max:12},{min:0,max:7}];export function parseCron(e){const n=e.trim().split(/\s+/);if(n.length!==5)return null;const t=[];for(let s=0;s<5;s++){const o=a(n[s],d[s].min,d[s].max);if(!o)return null;t.push(o)}const u=[...new Set(t[4].map(s=>s===7?0:s))].sort((s,o)=>s-o);return{minutes:t[0],hours:t[1],doms:t[2],months:t[3],dows:u,domAny:n[2]==="*",dowAny:n[4]==="*"}}function a(e,n,t){const u=new Set;for(const s of e.split(",")){const[o,c]=s.split("/");if(o===void 0)return null;const m=c===void 0?1:Number(c);if(!Number.isInteger(m)||m<1||m>t)return null;let i,r;if(o==="*")i=n,r=t;else if(o.includes("-")){const[l,f]=o.split("-");i=Number(l),r=Number(f)}else i=Number(o),r=c===void 0?i:t;if(!Number.isInteger(i)||!Number.isInteger(r)||i<n||r>t||i>r)return null;for(let l=i;l<=r;l+=m)u.add(l)}return u.size===0?null:[...u].sort((s,o)=>s-o)}function g(e,n){const t=e.doms.includes(n.getDate()),u=e.dows.includes(n.getDay());return e.domAny&&e.dowAny?!0:e.domAny?u:e.dowAny?t:t||u}export function matchesMinute(e,n){return e.minutes.includes(n.getMinutes())&&e.hours.includes(n.getHours())&&e.months.includes(n.getMonth()+1)&&g(e,n)}export function nextRunAt(e,n=new Date){const t=new Date(n.getTime());t.setSeconds(0,0),t.setMinutes(t.getMinutes()+1);const u=new Date(n.getTime()+366*864e5);for(;t<=u;){if(!e.months.includes(t.getMonth()+1)){t.setMonth(t.getMonth()+1,1),t.setHours(0,0,0,0);continue}if(!g(e,t)){t.setDate(t.getDate()+1),t.setHours(0,0,0,0);continue}if(!e.hours.includes(t.getHours())){t.setHours(t.getHours()+1,0,0,0);continue}if(!e.minutes.includes(t.getMinutes())){t.setMinutes(t.getMinutes()+1,0,0);continue}return t.toISOString()}return null}export function minuteKey(e){const n=t=>String(t).padStart(2,"0");return`${e.getFullYear()}-${n(e.getMonth()+1)}-${n(e.getDate())}T${n(e.getHours())}:${n(e.getMinutes())}`}
@@ -1,3 +1,3 @@
1
- import{createHmac as d,randomBytes as s,randomInt as m,scryptSync as o,timingSafeEqual as w}from"node:crypto";import{chmodSync as g,existsSync as p,mkdirSync as a,readFileSync as y,renameSync as P,rmSync as x,writeFileSync as c}from"node:fs";import h from"node:path";import{getAuthPath as k,getInitialPasswordPath as A}from"../db/paths.js";export const SESSION_COOKIE="weave_session",LOCAL_TOKEN_HEADER="x-weave-local",SESSION_TTL_MS=720*60*60*1e3;const u=64,T=16,l="abcdefghjkmnpqrstuvwxyz23456789";export function generatePassword(){const r=()=>Array.from({length:4},()=>l[m(l.length)]??"a").join("");return[r(),r(),r(),r()].join("-")}function f(r,t){const e=s(T).toString("hex");return{algo:"scrypt",salt:e,hash:o(r,e,u).toString("hex"),updatedAt:t}}function i(r,t){const e=Buffer.from(r),n=Buffer.from(t);return e.length===n.length&&w(e,n)}export function readCookie(r,t){if(r)for(const e of r.split(";")){const n=e.indexOf("=");if(!(n<0)&&e.slice(0,n).trim()===t)return e.slice(n+1).trim()}}export function sessionCookie(r){return`${SESSION_COOKIE}=${r}; HttpOnly; SameSite=Lax; Path=/; Max-Age=${Math.floor(SESSION_TTL_MS/1e3)}`}export function clearedSessionCookie(){return`${SESSION_COOKIE}=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`}function O(r){if(!p(r))return null;try{const t=JSON.parse(y(r,"utf8"));return t?.version!==1||typeof t.sessionSecret!="string"||typeof t.localToken!="string"?null:{version:1,password:t.password??null,sessionSecret:t.sessionSecret,localToken:t.localToken,createdAt:typeof t.createdAt=="string"?t.createdAt:new Date().toISOString()}}catch{return null}}function S(r,t){a(h.dirname(r),{recursive:!0});const e=`${r}.tmp`;c(e,`${JSON.stringify(t,null,2)}
2
- `,{encoding:"utf8",mode:384}),P(e,r);try{g(r,384)}catch{}}export class AuthService{file;authPath;markerPath;now;initialPassword;constructor(t={}){this.authPath=t.authPath??k(),this.markerPath=t.initialPasswordPath??A(),this.now=t.now??Date.now;const e=O(this.authPath);if(e){this.file=e,this.initialPassword=null;return}const n=generatePassword();this.file={version:1,password:f(n,this.nowIso()),sessionSecret:s(32).toString("hex"),localToken:s(24).toString("hex"),createdAt:this.nowIso()},S(this.authPath,this.file),this.writeMarker(n),this.initialPassword=n}isPasswordSet(){return this.file.password!==null}verifyPassword(t){const e=this.file.password;return e?i(o(t,e.salt,u).toString("hex"),e.hash):!1}setPassword(t){this.file={...this.file,password:f(t,this.nowIso()),sessionSecret:s(32).toString("hex")},S(this.authPath,this.file),x(this.markerPath,{force:!0})}getLocalToken(){return this.file.localToken}verifyLocalToken(t){return typeof t=="string"&&t!==""&&i(t,this.file.localToken)}issueSession(){const t=this.now()+SESSION_TTL_MS;return`${t}.${this.sign(t)}`}verifySession(t){if(!t)return!1;const e=t.indexOf(".");if(e<=0)return!1;const n=Number(t.slice(0,e));return!Number.isFinite(n)||n<=this.now()?!1:i(t.slice(e+1),this.sign(n))}isAuthenticated(t){return this.isLocallyTrusted(t)?!0:this.verifySession(readCookie(t.cookie,SESSION_COOKIE))}isLocallyTrusted(t){const e=t[LOCAL_TOKEN_HEADER];return this.verifyLocalToken(typeof e=="string"?e:void 0)}sign(t){return d("sha256",this.file.sessionSecret).update(`weave-session:${t}`).digest("hex")}nowIso(){return new Date(this.now()).toISOString()}writeMarker(t){a(h.dirname(this.markerPath),{recursive:!0}),c(this.markerPath,`${t}
1
+ import{createHmac as d,randomBytes as r,randomInt as m,scryptSync as o,timingSafeEqual as w}from"node:crypto";import{chmodSync as g,existsSync as p,mkdirSync as a,readFileSync as y,renameSync as P,rmSync as k,writeFileSync as c}from"node:fs";import h from"node:path";import{getAuthPath as x,getInitialPasswordPath as v}from"../db/paths.js";export const SESSION_COOKIE="weave_session",LOCAL_TOKEN_HEADER="x-weave-local",SESSION_TTL_MS=720*60*60*1e3;const l=64,O=16,u="abcdefghjkmnpqrstuvwxyz23456789";export function generatePassword(){const s=()=>Array.from({length:4},()=>u[m(u.length)]??"a").join("");return[s(),s(),s(),s()].join("-")}function f(s,t){const e=r(O).toString("hex");return{algo:"scrypt",salt:e,hash:o(s,e,l).toString("hex"),updatedAt:t}}function n(s,t){const e=Buffer.from(s),i=Buffer.from(t);return e.length===i.length&&w(e,i)}export function readCookie(s,t){if(s)for(const e of s.split(";")){const i=e.indexOf("=");if(!(i<0)&&e.slice(0,i).trim()===t)return e.slice(i+1).trim()}}export function sessionCookie(s){return`${SESSION_COOKIE}=${s}; HttpOnly; SameSite=Lax; Path=/; Max-Age=${Math.floor(SESSION_TTL_MS/1e3)}`}export function clearedSessionCookie(){return`${SESSION_COOKIE}=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`}function T(s){if(!p(s))return null;try{const t=JSON.parse(y(s,"utf8"));return t?.version!==1||typeof t.sessionSecret!="string"||typeof t.localToken!="string"?null:{version:1,password:t.password??null,sessionSecret:t.sessionSecret,localToken:t.localToken,createdAt:typeof t.createdAt=="string"?t.createdAt:new Date().toISOString()}}catch{return null}}function S(s,t){a(h.dirname(s),{recursive:!0});const e=`${s}.tmp`;c(e,`${JSON.stringify(t,null,2)}
2
+ `,{encoding:"utf8",mode:384}),P(e,s);try{g(s,384)}catch{}}export class AuthService{file;authPath;markerPath;now;initialPassword;constructor(t={}){this.authPath=t.authPath??x(),this.markerPath=t.initialPasswordPath??v(),this.now=t.now??Date.now;const e=T(this.authPath);if(e){this.file=e,this.initialPassword=null;return}const i=generatePassword();this.file={version:1,password:f(i,this.nowIso()),sessionSecret:r(32).toString("hex"),localToken:r(24).toString("hex"),createdAt:this.nowIso()},S(this.authPath,this.file),this.writeMarker(i),this.initialPassword=i}isPasswordSet(){return this.file.password!==null}verifyPassword(t){const e=this.file.password;return e?n(o(t,e.salt,l).toString("hex"),e.hash):!1}setPassword(t){this.file={...this.file,password:f(t,this.nowIso()),sessionSecret:r(32).toString("hex")},S(this.authPath,this.file),k(this.markerPath,{force:!0})}getLocalToken(){return this.file.localToken}verifyLocalToken(t){return typeof t=="string"&&t!==""&&n(t,this.file.localToken)}issueSession(){const t=this.now()+SESSION_TTL_MS;return`${t}.${this.sign(t)}`}verifySession(t){if(!t)return!1;const e=t.indexOf(".");if(e<=0)return!1;const i=Number(t.slice(0,e));return!Number.isFinite(i)||i<=this.now()?!1:n(t.slice(e+1),this.sign(i))}isAuthenticated(t){return this.isLocallyTrusted(t)?!0:this.verifySession(readCookie(t.cookie,SESSION_COOKIE))}isLocallyTrusted(t){const e=t[LOCAL_TOKEN_HEADER];return this.verifyLocalToken(typeof e=="string"?e:void 0)}sign(t){return d("sha256",this.file.sessionSecret).update(`weave-session:${t}`).digest("hex")}nowIso(){return new Date(this.now()).toISOString()}writeMarker(t){a(h.dirname(this.markerPath),{recursive:!0}),c(this.markerPath,`${t}
3
3
  `,{encoding:"utf8",mode:384})}}
@@ -1 +1 @@
1
- import{RATE_BUCKET_MS as s}from"../hooks/dashboard-rate.js";export const DASHBOARD_WINDOW_MS=36e5;const b=60,d=1e3,h=6e4;export function startDashboardPusher(t){let o=!1,i={projects:0,sessions:0},a=0;const r=()=>{i={projects:t.projects.list().length,sessions:t.sessions.countAll()},a=Date.now()},l=()=>({...i,...t.rate.totals}),m=()=>{queueMicrotask(()=>{const n=Date.now(),c=DASHBOARD_WINDOW_MS/s,u=Math.floor(n/s)*s-(c-1)*s,f=t.projects.list().map(e=>e.id);t.rate.isSeeded||(t.rate.seed(t.events.seriesBySecond(f,new Date(u).toISOString())),t.rate.seedTotals(t.events.countAll(),t.events.countSince(f,new Date(new Date(n).setHours(0,0,0,0)).toISOString())),r()),Date.now()-a>h&&r();const D=new Date(n).toISOString();t.bus.emit({kind:"dashboard.totals",at:D,totals:l()});for(let e=0;e<c;e+=b){const E=Math.min(b,c-e),_=u+e*s,I=t.rate.bucketsFor(_,E);t.bus.emit({kind:"dashboard.series",at:D,series:I.map((A,M)=>({at:new Date(_+M*s).toISOString().slice(0,19),n:A}))})}})},w=t.bus.subscribe(n=>{n.kind==="event.ingested"&&(o=!0)}),S=setInterval(()=>{o&&(o=!1,Date.now()-a>h&&r(),t.bus.emit({kind:"dashboard.delta",at:new Date().toISOString(),series:t.rate.recentBuckets(12),totals:l()}))},d);return S.unref?.(),{attach:m,stop:()=>{w(),clearInterval(S)}}}
1
+ import{RATE_BUCKET_MS as s}from"../hooks/dashboard-rate.js";export const DASHBOARD_WINDOW_MS=36e5;const p=60,f=1e3,w=6e4;export function startDashboardPusher(t){let o=!1,c={projects:0,sessions:0},a=0;const r=()=>{c={projects:t.projects.list().length,sessions:t.sessions.countAll()},a=Date.now()},l=()=>({...c,...t.rate.totals}),h=()=>{queueMicrotask(()=>{const n=Date.now(),i=DASHBOARD_WINDOW_MS/s,u=Math.floor(n/s)*s-(i-1)*s,S=t.projects.list().map(e=>e.id);t.rate.isSeeded||(t.rate.seed(t.events.seriesBySecond(S,new Date(u).toISOString())),t.rate.seedTotals(t.events.countAll(),t.events.countSince(S,new Date(new Date(n).setHours(0,0,0,0)).toISOString())),r()),Date.now()-a>w&&r();const D=new Date(n).toISOString();t.bus.emit({kind:"dashboard.totals",at:D,totals:l()});for(let e=0;e<i;e+=p){const I=Math.min(p,i-e),b=u+e*s,g=t.rate.bucketsFor(b,I);t.bus.emit({kind:"dashboard.series",at:D,series:g.map((k,O)=>({at:new Date(b+O*s).toISOString().slice(0,19),n:k}))})}})},m=t.bus.subscribe(n=>{n.kind==="event.ingested"&&(o=!0)}),d=setInterval(()=>{o&&(o=!1,Date.now()-a>w&&r(),t.bus.emit({kind:"dashboard.delta",at:new Date().toISOString(),series:t.rate.recentBuckets(12),totals:l()}))},f);return d.unref?.(),{attach:h,stop:()=>{m(),clearInterval(d)}}}
@@ -1,2 +1,2 @@
1
- import{chmodSync as o,existsSync as c,mkdirSync as i,readFileSync as u,renameSync as y,rmSync as m,writeFileSync as s}from"node:fs";import p from"node:path";import{getDecisionKeyPath as t}from"../db/paths.js";export function readDecisionKey(n=t()){if(!c(n))return null;try{const r=JSON.parse(u(n,"utf8"));return typeof r.apiKey=="string"&&r.apiKey!==""?r.apiKey:null}catch{return null}}export function writeDecisionKey(n,r=t()){if(n===null||n===""){m(r,{force:!0});return}i(p.dirname(r),{recursive:!0});const e=`${r}.tmp`;s(e,`${JSON.stringify({apiKey:n},null,2)}
2
- `,{encoding:"utf8",mode:384}),y(e,r);try{o(r,384)}catch{}}export function hasDecisionKey(n=t()){return readDecisionKey(n)!==null}
1
+ import{chmodSync as i,existsSync as c,mkdirSync as o,readFileSync as a,renameSync as s,rmSync as y,writeFileSync as u}from"node:fs";import l from"node:path";import{getDecisionKeyPath as e}from"../db/paths.js";export function readDecisionKey(r=e()){if(!c(r))return null;try{const n=JSON.parse(a(r,"utf8"));return typeof n.apiKey=="string"&&n.apiKey!==""?n.apiKey:null}catch{return null}}export function writeDecisionKey(r,n=e()){if(r===null||r===""){y(n,{force:!0});return}o(l.dirname(n),{recursive:!0});const t=`${n}.tmp`;u(t,`${JSON.stringify({apiKey:r},null,2)}
2
+ `,{encoding:"utf8",mode:384}),s(t,n);try{i(n,384)}catch{}}export function hasDecisionKey(r=e()){return readDecisionKey(r)!==null}
@@ -1 +1 @@
1
- import he from"node:http";import{openDatabase as we}from"../db/db.js";import{ProjectRepository as ge}from"../repositories/projects.js";import{HookEventRepository as ve}from"../repositories/hook-events.js";import{LibraryRepository as Se}from"../repositories/libraries.js";import{HookRuleRepository as oe}from"../repositories/hook-rules.js";import{HookDispatchRepository as be}from"../repositories/hook-dispatches.js";import{PluginStateRepository as E}from"../repositories/plugin-states.js";import{SessionRepository as Re}from"../repositories/sessions.js";import{createRuntimeRegistry as ye}from"@weavecode/harness";import{TERMINAL_LOCATOR_ENV_KEYS as ke,isHarness as U}from"@weavecode/core";import{messagingSurfaceFor as De,narrationSurfaceFor as Ee}from"../surfaces.js";import{syntheticSessionIds as Pe}from"../hooks/synthetic-sessions.js";import{createEdgeExtract as Oe}from"../hooks/edge-extract.js";import{HookRuleRegistry as Ie}from"../hooks/registry.js";import{HookDispatcher as Te}from"../hooks/dispatcher.js";import{HookEventBus as Ae}from"../hooks/bus.js";import{ResumeRunner as Ce}from"../hooks/resume-runner.js";import{HeadlessRunner as _e}from"../hooks/headless-runner.js";import{MessageDeliverer as Fe}from"../hooks/message-deliverer.js";import{QuestionTracker as He}from"../hooks/question-tracker.js";import{SideQuestionRepository as Me}from"../repositories/side-questions.js";import{claimSideAnswer as $e}from"../hooks/side-questions.js";import{DashboardRateCache as Be}from"../hooks/dashboard-rate.js";import{startDashboardPusher as Le}from"./dashboard-pusher.js";import{startPromptFlusher as Ue}from"../hooks/prompt-flusher.js";import{SessionWatchRepository as Ne}from"../repositories/session-watches.js";import{PushSubscriptionRepository as We}from"../repositories/push-subscriptions.js";import{UploadRepository as je}from"../repositories/uploads.js";import{defaultUploadSessions as xe}from"./upload-sessions.js";import{PushNotifier as Qe}from"../hooks/push-notify.js";import{OrchestrationRepository as qe,OrchestrationRunRepository as Ke}from"../repositories/orchestrations.js";import{WatchEngine as Ge}from"../hooks/watch-engine.js";import{OrchestrationEngine as Je,createForkConditionJudge as Ve}from"../hooks/orchestration-engine.js";import{createDecisionConditionJudge as Ye}from"../hooks/decision-judge.js";import{readDecisionKey as ze}from"./decision-config.js";import{createEnsureOpen as Xe}from"./session-open.js";import{loadAllPlugins as Ze}from"../hooks/plugin-loader.js";import{ensureBuiltinMarket as es,builtinMarketDir as ss}from"../market/builtin.js";import{ToolkitService as ts}from"../hooks/toolkit.js";import{startSessionSweeper as os}from"../hooks/session-sweeper.js";import{startStatuslineCacheSweeper as rs}from"../statusline/cache-sweeper.js";import{readStatuslineFacts as ns}from"../statusline/manager.js";import{WatchService as is}from"../watch/watch-service.js";import{weaveRequestHandler as as}from"./server.js";import{startTlsServer as ls}from"./tls.js";import{DataBus as cs}from"./data-bus.js";import{TerminalTopologyRefresher as ps}from"./terminal-topology-refresher.js";import{SnapshotRefresher as N}from"./snapshot-refresher.js";import{SessionProbe as ms,dbModelFactResolver as us,dbTranscriptPathResolver as ds}from"./session-probe.js";import{NarrationWatcher as fs}from"./narration-watcher.js";import{InflightCountsRefresher as hs}from"./inflight-counts-refresher.js";import{ProjectUpdatesRefresher as ws}from"./project-updates-refresher.js";import{FingerprintCache as gs}from"../install/fingerprint.js";import{detectProjectUpdateCounts as vs}from"../install/updates.js";import{pidAliveOf as Ss}from"./claude-liveness.js";import{combinedLivenessOf as b}from"./liveness.js";import{promptTerminalChannel as re,readTerminalCounts as bs}from"./opener.js";import{wireHookFilePipeline as Rs}from"./hook-pipeline.js";import{DEFAULT_PORT as W,DAEMON_HOST as ys,DEFAULT_BIND_HOST as ks,findFreePort as Ds,isPortFree as Es}from"./port.js";import{writeDaemonState as ne}from"./state.js";import{ensureDataLayout as Ps}from"../db/layout.js";import{pruneFileIndexes as Os}from"./project-files.js";import{pruneInstallTmp as Is}from"../hooks/plugin-installer.js";import{readDaemonSettingsSync as R,setDaemonSettingsDb as Ts,DEFAULT_SERVER_SETTINGS as As}from"./settings.js";import{AuthService as Cs}from"./dashboard-auth.js";import{resolveStaticDir as _s}from"./static.js";const Fs="CLAUDE_CODE_CHILD_SESSION"in process.env;delete process.env.CLAUDE_CODE_CHILD_SESSION;for(const p of ke)delete process.env[p];async function Hs(){Ps();const p=await Es(W)?W:await Ds(W+1);ne({pid:process.pid,port:p,startedAt:new Date().toISOString()});const o=we();Ts(o);const f=R().server?.bindHost??ks,P=R().server?.tlsPort??As.tlsPort,O=new Cs;O.initialPassword&&console.log(`[dev] initial dashboard password: ${O.initialPassword}`);const r=new ge(o);Os(r.list().map(e=>e.id)),Is();const a=new ve(o),u=new Se(o),h=ye(),ie=h.byCapability("events").flatMap(e=>e.events??[]),y=new Ie(new oe(o)),k=new be(o),t=new Re(o),n=new Ae;{const e=await es({libraries:u});e.error?console.error(`[dev] builtin market unavailable: ${e.error}`):e.changed&&console.log(`[dev] builtin market ${e.form==="link"?"linked":"copied"} -> ${ss(u.dataRoot)}`)}const{loader:m}=await Ze({rules:new oe(o),registry:y,states:new E(o),bus:n,libraries:u},r.list());{const e=m.list().filter(s=>s.status==="rejected");console.log(`[dev] plugins loaded: ${m.list().length} (rejected: ${e.length})`);for(const s of e)console.log(`[dev] rejected ${s.id}: ${s.error}`)}m.watchRoots();const j={list:()=>m.list(),setPluginEnabled:(e,s)=>m.setPluginEnabled(e,s),reloadAll:()=>m.reloadAll(),rescan:()=>m.rescanRoots(r.list(),u)},ae=new ts({projects:r,states:new E(o),plugins:j,libraries:u}),I={run:null},x=new Te({registry:y,dispatches:k,bus:n,projects:r,sessions:t,plugins:m,pluginStates:new E(o),classify:e=>I.run?I.run(e):Promise.resolve(null),sessionTitleOf:async e=>{const s=a.listBySession(e,1).at(-1)?.source;return U(s)?h.get(s)?.titles?.sessionTitleOf(e)??null:null}}),D=new _e,le=new Ce({dispatches:k,sessions:t,projects:r,bus:n,resumeSpec:h.get("claude")?.resume,headless:D}),c=new Fe({sessions:t,projects:r,hookEvents:a,bus:n,headless:D,terminal:re(()=>R().terminal),blockedByQuestion:e=>w.get(e)!=null,livenessOf:b,sideAnswerStore:{answerById:(e,s,l)=>{F.answerById(e,s,l)}}});Ue(c);const T=new Ne(o),A=new Ge({watches:T,deliverer:c,sessions:t,bus:n,livenessOf:b}),Q=new We(o),C=new je(o),ce=new Qe({subscriptions:Q,sessions:t,bus:n}),_=new qe(o),q=new Ke(o),d=new ms(ds(a),us(a,e=>t.getBySessionId(e)?.harness??null)),K=new fs(n,e=>Ee(U(e)?e:"claude"),e=>d.transcriptPathOf(e),e=>t.livenessRowOf(e)?.harness??null);K.start();const w=new He({sessions:t,hookEvents:a,onPending:e=>{n.emit({kind:"question.pending",sessionId:e.sessionId,harness:e.harness,count:e.questions.length,at:e.at})},interruptedAt:e=>{const s=t.getBySessionId(e);return s?d.interruptedAt(e,t.lastMainEventAtOf(e)??s.lastSeenAt):null}});w.seedFromDb();const F=new Me(o),G=new Be,H=Le({rate:G,events:a,sessions:t,projects:r,bus:n}),J={repo:F,bus:n,settle:e=>{c.interrupt(e.sessionId)}},V=new is(r);V.start();const i=new cs,g=new ps(async()=>({counts:await bs(r.list()),terminals:await c.sessionTerminals()}),i,{shouldRun:()=>i.hasSubscribers(),graceMs:1e4});g.start();const M=new N(()=>{const e=b(),s={};for(const l of t.listWithCounts()){const te=Ss(l,e);te!==null&&(s[l.sessionId]=te)}return{alive:s}},i,{key:"sessionLiveness",shouldRun:()=>i.hasSubscribers()});M.start();const $=new N(()=>{const e={};for(const s of t.listWithCounts()){if(s.turnOpen!==!0)continue;const l=d.interruptedAt(s.sessionId,t.lastMainEventAtOf(s.sessionId)??s.lastSeenAt);l!==null&&(e[s.sessionId]=l)}return{interrupted:e}},i,{key:"sessionInterrupt",intervalMs:5e3,shouldRun:()=>i.hasSubscribers()});$.start(),new N(()=>{const e={};for(const s of r.list())e[s.id]=ns(s.path);return e},i,{key:"statusline",intervalMs:5e3,shouldRun:()=>i.hasSubscribers(),invalidateOnly:!0}).start();const pe=new hs(()=>c.listInflightCounts(),i,n);let Y=null;const v=Oe({sessions:t,projects:r,harnessOf:e=>{const s=a.listBySession(e,1),l=s[s.length-1]?.source;return U(l)?l:null},surfaceFor:De,headless:D,onSyntheticChange:()=>Y?.pushSyntheticSessions(Pe())});I.run=e=>v.run(e);const me=Ye({config:async()=>{const e=R().decision;if(!e?.baseUrl||!e.model)return null;const s=ze();return s?{baseUrl:e.baseUrl,model:e.model,apiKey:s}:null},fallback:Ve({supports:e=>v.supports(e),extract:e=>v.run(e)})}),ue=Xe({hookSessions:t,hookEvents:a,projects:r,harnesses:h,sessionProbe:d,terminalRefresher:g,livenessOf:b}),S=new Je({orchestrations:_,runs:q,deliverer:c,sessions:t,bus:n,supportsExtract:e=>v.supports(e),extract:e=>v.run(e),conditionJudge:me,deferWhenUserPresent:!0,ensureOpen:ue});S.rearm();const z=setInterval(()=>S.cronTick(),3e4);z.unref();const de=new gs,fe=new ws(()=>vs(r.list(),u.list(),de),i,n,()=>i.hasSubscribers());os({sessions:t,events:a,dispatches:k,deliverer:c,watches:T,orchestrations:_,watchEngine:A,orchestrationEngine:S,questions:w,sideQuestions:F,probe:d,uploads:C,uploadSessions:xe,livenessOf:b}),rs();const B=Rs({projects:r,rules:y,sessions:t,bus:n,dispatcher:x,watchEngine:A,orchestrationEngine:S,messagePipe:c,questionTracker:w,sideQuestions:{onEvent:e=>{$e(J,e)}},sessionProbe:d,uploads:C,dashboardRate:G,terminalTopologyKick:()=>{g.refreshNow()}});Y=B;const L=_s(),X=as({projects:r,port:p,tlsPort:P,watch:V,hookEvents:a,adapters:ie,harnesses:h,libraries:u,staticDir:L,hookRegistry:y,hookDispatches:k,hookSessions:t,hookBus:n,dataBus:i,terminalRefresher:g,interruptRefresher:$,livenessRefresher:M,sessionProbe:d,inflightRefresher:pe,updatesRefresher:fe,hookDispatcher:x,hookRunner:le,messageDeliverer:c,terminal:re(()=>R().terminal),uploads:C,questionTracker:w,sideQuestions:J,sessionWatches:T,watchEngine:A,orchestrations:_,orchestrationRuns:q,orchestrationEngine:S,pushSubscriptions:Q,pushNotifier:ce,onAttach:H.attach,dashboardRefresh:H.attach,hookPlugins:j,hookMirror:B.mirror,pluginStates:new E(o),toolkit:ae,auth:O}),Z=he.createServer(X);let ee=null;ls({port:P,bindHost:f,handler:X}).then(e=>{ee=e,e&&console.log(`[dev] weave daemon tls listening on https://${f}:${e.port}`)});const se=()=>{g.stop(),M.stop(),$.stop(),D.killAll(),clearInterval(z),K.stop(),H.stop(),B.stop(),Z.close(),ee?.server.close(),process.exit(0)};process.on("SIGTERM",se),process.on("SIGINT",se),Z.listen(p,f,()=>{ne({pid:process.pid,port:p,startedAt:new Date().toISOString(),host:f,tlsPort:P}),console.log(`[dev] weave daemon listening on http://${f}:${p}`),console.log(`[dev] cli/dashboard local url: http://${ys}:${p}`),console.log(`[dev] child-session marker stripped: ${Fs}`),console.log(L?`[dev] static: ${L}`:"[dev] static: (web/dist not built \u2014 run pnpm build:web)")})}Hs();
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 vs}from"../repositories/libraries.js";import{HookRuleRepository as rs}from"../repositories/hook-rules.js";import{HookDispatchRepository as Rs}from"../repositories/hook-dispatches.js";import{PluginStateRepository as D}from"../repositories/plugin-states.js";import{SessionRepository as ys}from"../repositories/sessions.js";import{createRuntimeRegistry as ks}from"@weavecode/harness";import{TERMINAL_LOCATOR_ENV_KEYS as Es,isHarness as L}from"@weavecode/core";import{messagingSurfaceFor as Ps,narrationSurfaceFor as Ds}from"../surfaces.js";import{syntheticSessionIds as Os}from"../hooks/synthetic-sessions.js";import{createEdgeExtract as Ts}from"../hooks/edge-extract.js";import{HookRuleRegistry as Is}from"../hooks/registry.js";import{HookDispatcher as As}from"../hooks/dispatcher.js";import{HookEventBus as Cs}from"../hooks/bus.js";import{ResumeRunner as $s}from"../hooks/resume-runner.js";import{HeadlessRunner as Fs}from"../hooks/headless-runner.js";import{MessageDeliverer as Hs}from"../hooks/message-deliverer.js";import{QuestionTracker as _s}from"../hooks/question-tracker.js";import{SideQuestionRepository as js}from"../repositories/side-questions.js";import{claimSideAnswer as Ms}from"../hooks/side-questions.js";import{DashboardRateCache as Us}from"../hooks/dashboard-rate.js";import{startDashboardPusher as Bs}from"./dashboard-pusher.js";import{startPromptFlusher as Ls}from"../hooks/prompt-flusher.js";import{SessionWatchRepository as Ns}from"../repositories/session-watches.js";import{PushSubscriptionRepository as Ws}from"../repositories/push-subscriptions.js";import{UploadRepository as xs}from"../repositories/uploads.js";import{defaultUploadSessions as qs}from"./upload-sessions.js";import{PushNotifier as Qs}from"../hooks/push-notify.js";import{OrchestrationRepository as Gs,OrchestrationRunRepository as Ks}from"../repositories/orchestrations.js";import{WatchEngine as Js}from"../hooks/watch-engine.js";import{OrchestrationEngine as Vs,createForkConditionJudge as Ys}from"../hooks/orchestration-engine.js";import{createDecisionConditionJudge as zs}from"../hooks/decision-judge.js";import{readDecisionKey as Xs}from"./decision-config.js";import{createEnsureOpen as Zs}from"./session-open.js";import{loadAllPlugins as se}from"../hooks/plugin-loader.js";import{ensureBuiltinMarket as ee,builtinMarketDir as te}from"../market/builtin.js";import{ToolkitService as oe}from"../hooks/toolkit.js";import{startSessionSweeper as re}from"../hooks/session-sweeper.js";import{startStatuslineCacheSweeper as ne}from"../statusline/cache-sweeper.js";import{readStatuslineFacts as ie}from"../statusline/manager.js";import{WatchService as ae}from"../watch/watch-service.js";import{weaveRequestHandler as le}from"./server.js";import{startTlsServer as pe}from"./tls.js";import{DataBus as ce}from"./data-bus.js";import{TerminalTopologyRefresher as me}from"./terminal-topology-refresher.js";import{SnapshotRefresher as N}from"./snapshot-refresher.js";import{SessionProbe as ue,dbModelFactResolver as de,dbTranscriptPathResolver as he}from"./session-probe.js";import{NarrationWatcher as fe}from"./narration-watcher.js";import{InflightCountsRefresher as we}from"./inflight-counts-refresher.js";import{ProjectUpdatesRefresher as ge}from"./project-updates-refresher.js";import{FingerprintCache as Se}from"../install/fingerprint.js";import{detectProjectUpdateCounts as be}from"../install/updates.js";import{pidAliveOf as ve}from"./claude-liveness.js";import{combinedLivenessOf as v}from"./liveness.js";import{promptTerminalChannel as ns,readTerminalCounts as Re}from"./opener.js";import{wireHookFilePipeline as ye}from"./hook-pipeline.js";import{DEFAULT_PORT as W,DAEMON_HOST as ke,DEFAULT_BIND_HOST as Ee,findFreePort as Pe,isPortFree as De}from"./port.js";import{writeDaemonState as is}from"./state.js";import{ensureDataLayout as Oe}from"../db/layout.js";import{pruneFileIndexes as Te}from"./project-files.js";import{pruneInstallTmp as Ie}from"../hooks/plugin-installer.js";import{readDaemonSettingsSync as R,setDaemonSettingsDb as Ae,DEFAULT_SERVER_SETTINGS as Ce}from"./settings.js";import{AuthService as $e}from"./dashboard-auth.js";import{openPetWindow as Fe,shutdownPetWindow as He}from"./pet-window.js";import{seedBuiltinPets as _e}from"./pet-seed.js";import{resolveStaticDir as je}from"./static.js";const Me="CLAUDE_CODE_CHILD_SESSION"in process.env;delete process.env.CLAUDE_CODE_CHILD_SESSION;for(const p of Es)delete process.env[p];async function Ue(){Oe();const p=await De(W)?W:await Pe(W+1);is({pid:process.pid,port:p,startedAt:new Date().toISOString()});const t=gs();Ae(t);const h=R().server?.bindHost??Ee,O=R().server?.tlsPort??Ce.tlsPort,y=new $e;y.initialPassword&&console.log(`[dev] initial dashboard password: ${y.initialPassword}`);const r=new Ss(t);Te(r.list().map(s=>s.id)),Ie();const a=new bs(t),u=new vs(t),f=ks(),as=f.byCapability("events").flatMap(s=>s.events??[]),k=new Is(new rs(t)),E=new Rs(t),o=new ys(t),n=new Cs;{const s=await ee({libraries:u});s.error?console.error(`[dev] builtin market unavailable: ${s.error}`):s.changed&&console.log(`[dev] builtin market ${s.form==="link"?"linked":"copied"} -> ${te(u.dataRoot)}`)}const{loader:m}=await se({rules:new rs(t),registry:k,states:new D(t),bus:n,libraries:u},r.list());{const s=m.list().filter(e=>e.status==="rejected");console.log(`[dev] plugins loaded: ${m.list().length} (rejected: ${s.length})`);for(const e of s)console.log(`[dev] rejected ${e.id}: ${e.error}`)}m.watchRoots();const x={list:()=>m.list(),setPluginEnabled:(s,e)=>m.setPluginEnabled(s,e),reloadAll:()=>m.reloadAll(),rescan:()=>m.rescanRoots(r.list(),u)},ls=new oe({projects:r,states:new D(t),plugins:x,libraries:u}),T={run:null},q=new As({registry:k,dispatches:E,bus:n,projects:r,sessions:o,plugins:m,pluginStates:new D(t),classify:s=>T.run?T.run(s):Promise.resolve(null),sessionTitleOf:async s=>{const e=a.listBySession(s,1).at(-1)?.source;return L(e)?f.get(e)?.titles?.sessionTitleOf(s)??null:null}}),P=new Fs,ps=new $s({dispatches:E,sessions:o,projects:r,bus:n,resumeSpec:f.get("claude")?.resume,headless:P}),c=new Hs({sessions:o,projects:r,hookEvents:a,bus:n,headless:P,terminal:ns(()=>R().terminal),blockedByQuestion:s=>w.get(s)!=null,livenessOf:v,sideAnswerStore:{answerById:(s,e,l)=>{F.answerById(s,e,l)}}});Ls(c);const I=new Ns(t),A=new Js({watches:I,deliverer:c,sessions:o,bus:n,livenessOf:v}),Q=new Ws(t),C=new xs(t),cs=new Qs({subscriptions:Q,sessions:o,bus:n}),$=new Gs(t),G=new Ks(t),d=new ue(he(a),de(a,s=>o.getBySessionId(s)?.harness??null)),K=new fe(n,s=>Ds(L(s)?s:"claude"),s=>d.transcriptPathOf(s),s=>o.livenessRowOf(s)?.harness??null);K.start();const w=new _s({sessions:o,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=o.getBySessionId(s);return e?d.interruptedAt(s,o.lastMainEventAtOf(s)??e.lastSeenAt):null}});w.seedFromDb();const F=new js(t),J=new Us,H=Bs({rate:J,events:a,sessions:o,projects:r,bus:n}),V={repo:F,bus:n,settle:s=>{c.interrupt(s.sessionId)}},Y=new ae(r);Y.start();const i=new ce,g=new me(async()=>({counts:await Re(r.list()),terminals:await c.sessionTerminals()}),i,{shouldRun:()=>i.hasSubscribers(),graceMs:1e4});g.start();const _=new N(()=>{const s=v(),e={};for(const l of o.listWithCounts()){const os=ve(l,s);os!==null&&(e[l.sessionId]=os)}return{alive:e}},i,{key:"sessionLiveness",shouldRun:()=>i.hasSubscribers()});_.start();const j=new N(()=>{const s={};for(const e of o.listWithCounts()){if(e.turnOpen!==!0)continue;const l=d.interruptedAt(e.sessionId,o.lastMainEventAtOf(e.sessionId)??e.lastSeenAt);l!==null&&(s[e.sessionId]=l)}return{interrupted:s}},i,{key:"sessionInterrupt",intervalMs:5e3,shouldRun:()=>i.hasSubscribers()});j.start(),new N(()=>{const s={};for(const e of r.list())s[e.id]=ie(e.path);return s},i,{key:"statusline",intervalMs:5e3,shouldRun:()=>i.hasSubscribers(),invalidateOnly:!0}).start();const ms=new we(()=>c.listInflightCounts(),i,n);let z=null;const S=Ts({sessions:o,projects:r,harnessOf:s=>{const e=a.listBySession(s,1),l=e[e.length-1]?.source;return L(l)?l:null},surfaceFor:Ps,headless:P,onSyntheticChange:()=>z?.pushSyntheticSessions(Os())});T.run=s=>S.run(s);const us=zs({config:async()=>{const s=R().decision;if(!s?.baseUrl||!s.model)return null;const e=Xs();return e?{baseUrl:s.baseUrl,model:s.model,apiKey:e}:null},fallback:Ys({supports:s=>S.supports(s),extract:s=>S.run(s)})}),ds=Zs({hookSessions:o,hookEvents:a,projects:r,harnesses:f,sessionProbe:d,terminalRefresher:g,livenessOf:v}),b=new Vs({orchestrations:$,runs:G,deliverer:c,sessions:o,bus:n,supportsExtract:s=>S.supports(s),extract:s=>S.run(s),conditionJudge:us,deferWhenUserPresent:!0,ensureOpen:ds});b.rearm();const X=setInterval(()=>b.cronTick(),3e4);X.unref();const hs=new Se,fs=new ge(()=>be(r.list(),u.list(),hs),i,n,()=>i.hasSubscribers());re({sessions:o,events:a,dispatches:E,deliverer:c,watches:I,orchestrations:$,watchEngine:A,orchestrationEngine:b,questions:w,sideQuestions:F,probe:d,uploads:C,uploadSessions:qs,livenessOf:v}),ne();const M=ye({projects:r,rules:k,sessions:o,bus:n,dispatcher:q,watchEngine:A,orchestrationEngine:b,messagePipe:c,questionTracker:w,sideQuestions:{onEvent:s=>{Ms(V,s)}},sessionProbe:d,uploads:C,dashboardRate:J,terminalTopologyKick:()=>{g.refreshNow()}});z=M;const U=je(),Z={},ss=le({projects:r,port:p,tlsPort:O,watch:Y,hookEvents:a,adapters:as,harnesses:f,libraries:u,staticDir:U,hookRegistry:k,hookDispatches:E,hookSessions:o,hookBus:n,dataBus:i,terminalRefresher:g,interruptRefresher:j,livenessRefresher:_,sessionProbe:d,inflightRefresher:ms,updatesRefresher:fs,hookDispatcher:q,hookRunner:ps,messageDeliverer:c,terminal:ns(()=>R().terminal),uploads:C,questionTracker:w,sideQuestions:V,sessionWatches:I,watchEngine:A,orchestrations:$,orchestrationRuns:G,orchestrationEngine:b,pushSubscriptions:Q,pushNotifier:cs,onAttach:H.attach,dashboardRefresh:H.attach,hookPlugins:x,hookMirror:M.mirror,pluginStates:new D(t),toolkit:ls,auth:y,requestShutdown:()=>Z.fn?.()}),es=ws.createServer(ss);let ts=null;pe({port:O,bindHost:h,handler:ss}).then(s=>{ts=s,s&&console.log(`[dev] weave daemon tls listening on https://${h}:${s.port}`)});const B=()=>{g.stop(),_.stop(),j.stop(),He(),P.killAll(),clearInterval(X),K.stop(),H.stop(),es.close(),ts?.server.close();const s=()=>{try{t.exec("PRAGMA wal_checkpoint(TRUNCATE)"),t.close()}catch{}},e=setTimeout(()=>{s(),process.exit(0)},3e3);M.stop().catch(()=>{}).finally(()=>{clearTimeout(e),s(),process.exit(0)})};Z.fn=B,process.on("SIGTERM",B),process.on("SIGINT",B),es.listen(p,h,()=>{is({pid:process.pid,port:p,startedAt:new Date().toISOString(),host:h,tlsPort:O}),console.log(`[dev] weave daemon listening on http://${h}:${p}`),console.log(`[dev] cli/dashboard local url: http://${ke}:${p}`),console.log(`[dev] child-session marker stripped: ${Me}`),console.log(U?`[dev] static: ${U}`:"[dev] static: (web/dist not built \u2014 run pnpm build:web)"),_e().then(()=>{Fe({baseUrl:`http://localhost:${p}`,auth:y})})})}Ue();
@@ -1,7 +1,7 @@
1
- import{appendFileSync as r,mkdirSync as s}from"node:fs";import c from"node:path";import{getLogsDir as a}from"../db/paths.js";import{startDaemon as m}from"./start.js";const i=(t,o)=>{const n=o instanceof Error?o.stack??o.message:String(o);try{const e=a();s(e,{recursive:!0}),r(c.join(e,"daemon-boot.log"),`[${new Date().toISOString()}] ${t}:
1
+ import{appendFileSync as r,mkdirSync as c}from"node:fs";import s from"node:path";import{getLogsDir as a}from"../db/paths.js";import{startDaemon as m}from"./start.js";const i=(t,o)=>{const n=o instanceof Error?o.stack??o.message:String(o);try{const e=a();c(e,{recursive:!0}),r(s.join(e,"daemon-boot.log"),`[${new Date().toISOString()}] ${t}:
2
2
  ${n}
3
3
 
4
- `,"utf8")}catch{}process.exit(1)};process.on("uncaughtException",t=>i("uncaughtException",t)),process.on("unhandledRejection",t=>i("unhandledRejection",t));try{m()}catch(t){const o=t instanceof Error?t.stack??t.message:String(t);try{const n=a();s(n,{recursive:!0}),r(c.join(n,"daemon-boot.log"),`[${new Date().toISOString()}] boot crash:
4
+ `,"utf8")}catch{}process.exit(1)};process.on("uncaughtException",t=>i("uncaughtException",t)),process.on("unhandledRejection",t=>i("unhandledRejection",t));try{m()}catch(t){const o=t instanceof Error?t.stack??t.message:String(t);try{const n=a();c(n,{recursive:!0}),r(s.join(n,"daemon-boot.log"),`[${new Date().toISOString()}] boot crash:
5
5
  ${o}
6
6
 
7
7
  `,"utf8")}catch{}process.exit(1)}
@@ -1 +1 @@
1
- import{readdir as d,stat as l}from"node:fs/promises";import p from"node:os";import a from"node:path";function f(n,s){return new Promise((r,t)=>{const e=setTimeout(()=>t(new Error("timeout")),s);n.then(i=>{clearTimeout(e),r(i)},i=>{clearTimeout(e),t(i)})})}let c=null;const h=5*6e4;async function w(){if(c&&Date.now()-c.at<h)return c.drives;const n="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),r=(await Promise.all(n.map(async t=>{const e=`${t}:\\`;try{return await f(l(e),4e3),e}catch{return null}}))).filter(t=>t!==null);return c={at:Date.now(),drives:r},r}export async function listBrowseRoots(n){const s=[],r=new Set,t=(o,m)=>{r.has(o)||(r.add(o),s.push({path:o,kind:m}))},e=p.homedir();t(e,"home");const i=[["Desktop","desktop"],["Downloads","downloads"],["Documents","documents"]];for(const[o,m]of i){const u=a.join(e,o);try{await l(u),t(u,m)}catch{}}for(const o of n)typeof o=="string"&&o&&t(a.dirname(o),"library-parent");if(process.platform==="win32")for(const o of await w())t(o,"drive");else t(a.parse(e).root,"root");return s}export async function listDirectoryChildren(n){const r=(await d(n,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>({name:t.name,path:a.join(n,t.name)}));return r.sort((t,e)=>t.name.localeCompare(e.name,void 0,{numeric:!0})),r}
1
+ import{readdir as p,stat as u}from"node:fs/promises";import f from"node:os";import s from"node:path";function d(n,e){return new Promise((t,o)=>{const a=setTimeout(()=>o(new Error("timeout")),e);n.then(i=>{clearTimeout(a),t(i)},i=>{clearTimeout(a),o(i)})})}let c=null;const w=5*6e4;async function h(){if(c&&Date.now()-c.at<w)return c.drives;const n="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),e=(await Promise.all(n.map(async t=>{const o=`${t}:\\`;try{return await d(u(o),4e3),o}catch{return null}}))).filter(t=>t!==null);return c={at:Date.now(),drives:e},e}export async function listBrowseRoots(n){const e=[],t=new Set,o=(r,m)=>{t.has(r)||(t.add(r),e.push({path:r,kind:m}))},a=f.homedir();o(a,"home");const i=[["Desktop","desktop"],["Downloads","downloads"],["Documents","documents"]];for(const[r,m]of i){const l=s.join(a,r);try{await u(l),o(l,m)}catch{}}for(const r of n)typeof r=="string"&&r&&o(s.dirname(r),"library-parent");if(process.platform==="win32")for(const r of await h())o(r,"drive");else o(s.parse(a).root,"root");return e}export async function listDirectoryChildren(n){const e=(await p(n,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>({name:t.name,path:s.join(n,t.name)}));return e.sort((t,o)=>t.name.localeCompare(o.name,void 0,{numeric:!0})),e}
@@ -1 +1 @@
1
- import{readdirSync as m,unlinkSync as a}from"node:fs";import{join as c}from"node:path";import{getDbPath as h}from"../db/paths.js";import{MirrorWriter as b,hookShardId as l,hooksRoot as g,mirrorPathOf as x,outboxPathOf as k}from"../hooks/mirror.js";import{promptboxPathOf as P}from"../hooks/promptbox.js";import{messagingSurfaceFor as S}from"../surfaces.js";import{startInboxWorker as j,handleIngestedRecords as y,unparkFailedInbox as $,INBOX_CLAIM_SUFFIX as p,INBOX_FAILED_SUFFIX as u}from"../hooks/inbox-worker.js";function v(o,e){return[c(o,"inbox",`${e}.jsonl`),c(o,"inbox",`${e}${p}`),c(o,"inbox",`${e}${u}`),x(o,e),k(o,e),P(o,e)]}export function purgeProjectPipeline(o,e){for(const n of v(o,l(e)))try{a(n)}catch{}}function w(o){return(o.endsWith(".tmp")?o.slice(0,-4):o).replace(new RegExp(`(${p}|${u})$`),"").replace(/\.(jsonl|json)$/,"")}const F=/^[0-9a-f]{16}$/;export function purgeOrphanPipelineFiles(o){const e=new Set(o.projects.list().map(t=>l(t.token)));let n=0;for(const t of["inbox","mirror","outbox","promptbox"]){let i;try{i=m(c(o.hooksDir,t))}catch{continue}for(const s of i){const r=w(s);if(!(!F.test(r)||e.has(r)))try{a(c(o.hooksDir,t,s)),n++}catch{}}}return n}export function wireHookFilePipeline(o){const e=g(),n=purgeOrphanPipelineFiles({projects:o.projects,hooksDir:e});n>0&&console.log(`[weave] hook pipeline: purged ${n} orphan file(s)`);const t=$(e);t>0&&console.log(`[weave] hook pipeline: revived ${t} parked inbox file(s)`);const i=new b({projects:o.projects,rules:o.rules,sessions:o.sessions});o.rules.onChange=()=>i.syncAll(),i.attachToBus(o.bus),i.syncAll();const s=j({dbPath:h(),hooksDir:e});return s.on("message",r=>{y({projects:o.projects,hooksDir:e,bus:o.bus,dispatcher:o.dispatcher,watchEngine:o.watchEngine,orchestrationEngine:o.orchestrationEngine,messagePipe:o.messagePipe,questionTracker:o.questionTracker,sideQuestions:o.sideQuestions,dashboardRate:o.dashboardRate,sessionProbe:o.sessionProbe,uploads:o.uploads,terminalTopologyKick:o.terminalTopologyKick,paneEnvSource:f=>S(f).paneEnvSource},r)}),s.on("error",r=>console.error("[weave] inbox worker failed:",r)),{mirror:i,pushSyntheticSessions:r=>s.postMessage({type:"synthetic-sessions",ids:r}),stop:()=>s.terminate().then(()=>{})}}
1
+ import{readdirSync as m,unlinkSync as c}from"node:fs";import{join as a}from"node:path";import{getDbPath as f}from"../db/paths.js";import{MirrorWriter as d,hookShardId as p,hooksRoot as b,mirrorPathOf as g,outboxPathOf as k}from"../hooks/mirror.js";import{promptboxPathOf as x}from"../hooks/promptbox.js";import{messagingSurfaceFor as P}from"../surfaces.js";import{startInboxWorker as j,handleIngestedRecords as y,unparkFailedInbox as $,INBOX_CLAIM_SUFFIX as l,INBOX_FAILED_SUFFIX as h}from"../hooks/inbox-worker.js";function S(o,s){return[a(o,"inbox",`${s}.jsonl`),a(o,"inbox",`${s}${l}`),a(o,"inbox",`${s}${h}`),g(o,s),k(o,s),x(o,s)]}export function purgeProjectPipeline(o,s){for(const e of S(o,p(s)))try{c(e)}catch{}}function w(o){return(o.endsWith(".tmp")?o.slice(0,-4):o).replace(new RegExp(`(${l}|${h})$`),"").replace(/\.(jsonl|json)$/,"")}const F=/^[0-9a-f]{16}$/;export function purgeOrphanPipelineFiles(o){const s=new Set(o.projects.list().map(n=>p(n.token)));let e=0;for(const n of["inbox","mirror","outbox","promptbox"]){let t;try{t=m(a(o.hooksDir,n))}catch{continue}for(const i of t){const r=w(i);if(!(!F.test(r)||s.has(r)))try{c(a(o.hooksDir,n,i)),e++}catch{}}}return e}export function wireHookFilePipeline(o){const s=b(),e=purgeOrphanPipelineFiles({projects:o.projects,hooksDir:s});e>0&&console.log(`[weave] hook pipeline: purged ${e} orphan file(s)`);const n=$(s);n>0&&console.log(`[weave] hook pipeline: revived ${n} parked inbox file(s)`);const t=new d({projects:o.projects,rules:o.rules,sessions:o.sessions});o.rules.onChange=()=>t.syncAll(),t.attachToBus(o.bus),t.syncAll();const i=j({dbPath:f(),hooksDir:s});return i.on("message",r=>{y({projects:o.projects,hooksDir:s,bus:o.bus,dispatcher:o.dispatcher,watchEngine:o.watchEngine,orchestrationEngine:o.orchestrationEngine,messagePipe:o.messagePipe,questionTracker:o.questionTracker,sideQuestions:o.sideQuestions,dashboardRate:o.dashboardRate,sessionProbe:o.sessionProbe,uploads:o.uploads,terminalTopologyKick:o.terminalTopologyKick,paneEnvSource:u=>P(u).paneEnvSource},r)}),i.on("error",r=>console.error("[weave] inbox worker failed:",r)),{mirror:t,pushSyntheticSessions:r=>i.postMessage({type:"synthetic-sessions",ids:r}),stop:()=>i.terminate().then(()=>{})}}
@@ -1 +1 @@
1
- import{z as h}from"zod";import{HARNESS_SESSION_CONTROL as x,isHarness as T}from"@weavecode/core";import{aliasOfModel as O,modelAliasTargets as M}from"@weavecode/harness";import{readJson as y,sendJson as r}from"./http.js";import{purgeSession as D}from"../hooks/session-purge.js";import{readDaemonSettingsSync as A,readHooksEnabled as H}from"./settings.js";import{handleOrchestrationRoutes as W}from"./routes/orchestration.js";import{handleHookAdminRoutes as U}from"./routes/hooks-admin.js";import{handleUploadRoutes as B}from"./routes/uploads.js";import{handleSessionControlRoutes as N}from"./routes/session-control.js";import{handlePathRefRoutes as $}from"./routes/path-refs.js";import{handleVisualizationRoutes as K}from"./routes/visualizations.js";import{handleSessionInsightRoutes as G}from"./routes/session-insights.js";import{handleWatchRoutes as L}from"./routes/watches.js";import{openSessionTerminal as Q,transcriptState as V}from"./session-open.js";import{pidAliveOf as j}from"./claude-liveness.js";import{combinedLivenessOf as E}from"./liveness.js";import{captureSurfaces as _,messagingSurfaces as z,sessionTitleSurfaceFor as F}from"../surfaces.js";import{getDataDir as J}from"../db/paths.js";import{WEAVE_VERSION as X}from"../version.js";const Y=h.object({title:h.string().min(1).max(200)}),Z=h.object({text:h.string().max(2e4),fromKind:h.enum(["dashboard","session"]).optional(),fromSessionId:h.string().min(1).nullable().optional(),attachments:h.array(h.string().regex(/^[a-f0-9]{64}$/)).max(8).optional(),images:h.array(h.string().regex(/^[a-f0-9]{64}$/)).max(8).optional(),forceTerminal:h.boolean().optional()});function q(l,s){return l.queuedPrompt!==null||l.prompt!==null||s}function ee(l){const{diag:s,capture:e,eventCount:i}=l,u=[];return!e||e.source==="none"||!e.present?u.push("no-hook-script"):e.weaveOwned?!e.reportsInbox&&s?.inbox.reason!=="no-mechanism"&&u.push("hook-script-stale"):u.push("hook-script-not-weave"),i===0&&u.push("no-events"),s&&(s.alive===!1&&u.push("not-running"),s.inbox.reason==="no-credentials"&&e?.reportsInbox===!0&&u.push("no-inbox-credentials"),s.inbox.reason==="auth-token-required"&&u.push("inbox-token-required"),s.relay.reason==="no-peer-name"&&u.push("no-peer-name"),s.terminal.reason==="no-backend"&&u.push("terminal-no-backend"),s.terminal.reason==="no-pane-env"&&u.push("terminal-no-pane-env"),s.terminal.reason==="pane-env-conflict"&&u.push("terminal-pane-env-conflict"),s.pending>0&&u.push("queued"),s.stalled&&u.push("stalled")),u}export async function handleHooksRoutes(l,s,e,i,u){if(!(i.startsWith("/hooks/")||i==="/dashboard/refresh"||i==="/sessions"||i.startsWith("/sessions/")||i.startsWith("/messaging")||i.startsWith("/webhooks/orchestrate/")||i==="/uploads"||i.startsWith("/uploads/")||i.startsWith("/images/")||i==="/visualizations/fragment"))return!1;if(await U(l,s,e,i,u))return!0;if(i==="/dashboard/refresh"&&l.method==="POST")return e.dashboardRefresh?.(),r(s,200,{ok:!0}),!0;if(i==="/sessions"&&l.method==="GET"){if(!e.hookSessions)return r(s,503,{error:"Hooks subsystem unavailable"}),!0;const o=u.searchParams.get("projectId"),a=o!=null&&o!==""?Number(o):void 0,n=u.searchParams.get("ids"),d=n?n.split(",").map(t=>t.trim()).filter(Boolean).slice(0,100):void 0,m=e.hookSessions,f=m.listWithCounts(a,d),p=E(),v=e.terminalRefresher?.lastSnapshot?.terminals??{},b={};for(const t of f){const c=t.harness??"";c in b||(b[c]=M(x[t.harness]?.modelNames??[]))}return r(s,200,{sessions:f.map(t=>{const c=e.sessionProbe?.currentModel(t.sessionId)??null,g=e.sessionProbe?.transcriptPresent(t.sessionId)??null,I=T(t.harness)?e.harnesses?.get(t.harness)?.resume:void 0;return{...t,pidAlive:j(t,p),canOpenTerminal:!!(I?.supported&&I.openArgs),terminal:v[t.sessionId]??null,interruptedAt:t.turnOpen===!0?e.sessionProbe?.interruptedAt(t.sessionId,m.lastMainEventAtOf(t.sessionId)??t.lastSeenAt)??null:null,model:c,modelAlias:O(b[t.harness??""]??[],c),mode:e.sessionProbe?.currentMode(t.sessionId)??null,effort:e.sessionProbe?.currentEffort(t.sessionId)??null,contextTokens:e.sessionProbe?.currentContextTokens(t.sessionId)??null,transcriptPresent:V(g,t.hasRun)}}),modelCatalog:b}),!0}const S=i.match(/^\/sessions\/([^/]+)$/);if(S&&l.method==="PATCH"){if(!e.hookSessions)return r(s,503,{error:"Hooks subsystem unavailable"}),!0;const o=decodeURIComponent(S[1]);if(!e.hookSessions.getBySessionId(o))return r(s,404,{error:"Session not found"}),!0;try{const a=Y.parse(await y(l)),n=e.hookEvents?.listBySession(o,1),d=n?.[n.length-1]?.source,m=T(d)?F(d):null;if(m){try{await m.setSessionTitle(o,a.title)}catch(v){return r(s,502,{error:v instanceof Error?v.message:"Host rename failed"}),!0}const p=e.hookSessions.setTitle(o,a.title);return p?.projectId!=null&&e.hookMirror?.syncProject(p.projectId),r(s,200,{session:p}),!0}const f=e.hookSessions.setPendingTitle(o,a.title);f?.projectId!=null&&e.hookMirror?.syncProject(f.projectId),r(s,200,{session:f})}catch(a){r(s,400,{error:a instanceof Error?a.message:"Invalid body"})}return!0}if(S&&l.method==="DELETE"){if(!e.hookSessions||!e.hookEvents)return r(s,503,{error:"Hooks subsystem unavailable"}),!0;const o=decodeURIComponent(S[1]),a=e.hookSessions.getBySessionId(o);if(!a)return r(s,404,{error:"Session not found"}),!0;const n=D({sessions:e.hookSessions,events:e.hookEvents,dispatches:e.hookDispatches,deliverer:e.messageDeliverer,watches:e.sessionWatches,orchestrations:e.orchestrations,questions:e.questionTracker,sideQuestions:e.sideQuestions?.repo,probe:e.sessionProbe,uploads:e.uploads},o);return a.projectId!=null&&e.hookMirror?.syncProject(a.projectId),r(s,200,{ok:!0,sessionId:o,...n}),!0}const R=i.match(/^\/sessions\/([^/]+)\/open-terminal$/);if(R&&l.method==="POST"){const o=decodeURIComponent(R[1]);let a;try{const d=await y(l);typeof d?.target=="string"&&d.target&&(a=d.target)}catch{}const n=await Q(e,o,a);return n.ok?(r(s,200,{ok:!0,sessionId:n.sessionId,command:n.command,cwd:n.cwd,...n.target?{target:n.target}:{}}),!0):(r(s,n.status,{error:n.error}),!0)}if(await B(l,s,e,i,u))return!0;const w=i.match(/^\/sessions\/([^/]+)\/messages$/);if(w){const o=decodeURIComponent(w[1]);if(l.method==="GET")return e.messageDeliverer?e.hookSessions?.getBySessionId(o)?(r(s,200,{messages:e.messageDeliverer.listVisible(o)}),!0):(r(s,404,{error:"Session not found"}),!0):(r(s,503,{error:"Messaging subsystem unavailable"}),!0);if(l.method==="POST"){if(!e.messageDeliverer||!e.hookSessions)return r(s,503,{error:"Messaging subsystem unavailable"}),!0;let a;try{a=Z.parse(await y(l))}catch(f){return r(s,400,{error:f instanceof Error?f.message:"Invalid body"}),!0}const n=[...a.attachments??[],...a.images??[]];if(!a.text.trim()&&n.length===0)return r(s,400,{error:"Message is empty"}),!0;let d=[];if(n.length>0){const f=e.uploads?.refsOf(n)??null;if(!f)return r(s,404,{error:"Attachment not found"}),!0;d=f}const m=await e.messageDeliverer.send({toSessionId:o,text:a.text,...d.length>0?{attachments:d}:{},...a.forceTerminal===!0?{forceTerminal:!0}:{},mode:"prompt",fromKind:a.fromKind??"dashboard",fromSessionId:a.fromSessionId??null,oneWay:!0});return m.ok?r(s,201,{ok:!0,messageId:m.messageId,status:m.status,message:m.message}):r(s,m.status,{error:m.error}),!0}}if(await G(l,s,e,i,u)||await $(l,s,e,i,u)||await K(l,s,e,i,u))return!0;const P=i.match(/^\/sessions\/([^/]+)\/messages\/([^/]+)\/resend$/);if(P&&l.method==="POST"){if(!e.messageDeliverer)return r(s,503,{error:"Messaging subsystem unavailable"}),!0;const o=await e.messageDeliverer.resend(decodeURIComponent(P[2]));return o.ok?r(s,200,{ok:!0,messageId:o.messageId,status:o.status,message:o.message}):r(s,o.status,{error:o.error}),!0}const k=i.match(/^\/sessions\/([^/]+)\/messages\/([^/]+)\/dismiss$/);if(k&&l.method==="POST"){if(!e.messageDeliverer)return r(s,503,{error:"Messaging subsystem unavailable"}),!0;const o=e.messageDeliverer.dismiss(decodeURIComponent(k[1]),decodeURIComponent(k[2]));return o.ok?r(s,200,{ok:!0}):r(s,o.status,{error:o.error}),!0}if(await N(l,s,e,i,u)||await L(l,s,e,i)||await W(l,s,e,i,u))return!0;if(i==="/messaging/capabilities"&&l.method==="GET"){const o=e.messageDeliverer?.hasTerminalChannel()??!1;return r(s,200,{capabilities:z().map(({harness:a,surface:n})=>({harness:a,discovery:n.discovery,prompt:q(n,o),inject:n.inject!==null,headless:n.headless!==null,watch:n.idleSignals.length>0,attachKinds:n.attach?.kinds??[],pathRefs:n.pathRefs!==null,pathRefLines:n.pathRefs?.lines===!0,pathRefKinds:n.pathRefs?.kinds??[],sideQuestion:n.sideQuestion!==null,unsupportedReasons:n.unsupportedReasons??null}))}),!0}if(i==="/messaging/diagnostics"&&l.method==="GET"){if(!e.messageDeliverer||!e.hookSessions)return r(s,503,{error:"Message subsystem unavailable"}),!0;const o=u.searchParams.get("session"),a=u.searchParams.get("project"),n=_(),d=e.projects.list(),m=await Promise.all(d.map(async t=>({id:t.id,name:t.name,path:t.path,captures:await Promise.all(n.map(async({harness:c,surface:g})=>({harness:c,...await g.scriptHealth({projectPath:t.path})})))}))),f=(t,c)=>m.find(g=>g.id===t)?.captures.find(g=>g.harness===c)??null,p=E(),b=e.hookSessions.listWithCounts(o?void 0:a?Number(a):void 0).filter(t=>o?t.sessionId===o:j(t,p)!==!1).map(t=>{const c=e.messageDeliverer.diagnose(t.sessionId),g=f(t.projectId,t.harness??null),I={inbox:c.inbox,queue:c.queue,relay:c.relay,terminal:c.terminal};return{sessionId:t.sessionId,projectId:t.projectId,harness:t.harness??null,title:t.title,lastSeenAt:t.lastSeenAt,eventCount:t.eventCount??0,lastEventType:t.lastEventType??null,alive:c.alive,paneEnvReported:c.paneEnvReported,channels:I,queue:{pending:c.pending,stalled:c.stalled},reachable:Object.values(I).some(C=>C.status==="ready"),hints:ee({diag:c,capture:g,eventCount:t.eventCount??0})}});return r(s,200,{daemon:{version:X,platform:process.platform,dataDir:J(),uptimeMs:Math.round(process.uptime()*1e3),terminalPreset:A().terminal.preset,terminalTextChannel:e.messageDeliverer.hasTerminalChannel(),hooksEnabled:H()},projects:m,sessions:b}),!0}return!1}
1
+ import{z as f}from"zod";import{HARNESS_SESSION_CONTROL as j,isHarness as P}from"@weavecode/core";import{aliasOfModel as C,modelAliasTargets as O}from"@weavecode/harness";import{readJson as y,sendJson as a}from"./http.js";import{purgeSession as D}from"../hooks/session-purge.js";import{readDaemonSettingsSync as A,readHooksEnabled as M}from"./settings.js";import{handleOrchestrationRoutes as W}from"./routes/orchestration.js";import{handleHookAdminRoutes as q}from"./routes/hooks-admin.js";import{handleUploadRoutes as H}from"./routes/uploads.js";import{handleSessionControlRoutes as U}from"./routes/session-control.js";import{handlePathRefRoutes as N}from"./routes/path-refs.js";import{handleVisualizationRoutes as $}from"./routes/visualizations.js";import{handlePetRoutes as B}from"./routes/pets.js";import{handleSessionInsightRoutes as K}from"./routes/session-insights.js";import{handleWatchRoutes as G}from"./routes/watches.js";import{openSessionTerminal as L,transcriptState as Q}from"./session-open.js";import{pidAliveOf as E}from"./claude-liveness.js";import{combinedLivenessOf as x}from"./liveness.js";import{captureSurfaces as V,messagingSurfaces as z,sessionTitleSurfaceFor as _}from"../surfaces.js";import{getDataDir as J}from"../db/paths.js";import{WEAVE_VERSION as F}from"../version.js";const X=f.object({title:f.string().min(1).max(200)}),Y=f.object({text:f.string().max(2e4),fromKind:f.enum(["dashboard","session"]).optional(),fromSessionId:f.string().min(1).nullable().optional(),attachments:f.array(f.string().regex(/^[a-f0-9]{64}$/)).max(8).optional(),images:f.array(f.string().regex(/^[a-f0-9]{64}$/)).max(8).optional(),forceTerminal:f.boolean().optional()});function Z(i,s){return i.queuedPrompt!==null||i.prompt!==null||s}function ee(i){const{diag:s,capture:e,eventCount:n}=i,d=[];return!e||e.source==="none"||!e.present?d.push("no-hook-script"):e.weaveOwned?!e.reportsInbox&&s?.inbox.reason!=="no-mechanism"&&d.push("hook-script-stale"):d.push("hook-script-not-weave"),n===0&&d.push("no-events"),s&&(s.alive===!1&&d.push("not-running"),s.inbox.reason==="no-credentials"&&e?.reportsInbox===!0&&d.push("no-inbox-credentials"),s.inbox.reason==="auth-token-required"&&d.push("inbox-token-required"),s.relay.reason==="no-peer-name"&&d.push("no-peer-name"),s.terminal.reason==="no-backend"&&d.push("terminal-no-backend"),s.terminal.reason==="no-pane-env"&&d.push("terminal-no-pane-env"),s.terminal.reason==="pane-env-conflict"&&d.push("terminal-pane-env-conflict"),s.pending>0&&d.push("queued"),s.stalled&&d.push("stalled")),d}export async function handleHooksRoutes(i,s,e,n,d){if(!(n.startsWith("/hooks/")||n==="/dashboard/refresh"||n==="/sessions"||n.startsWith("/sessions/")||n.startsWith("/messaging")||n.startsWith("/webhooks/orchestrate/")||n==="/uploads"||n.startsWith("/uploads/")||n.startsWith("/images/")||n.startsWith("/visualizations/")||n==="/daemon/shutdown"||n==="/pets"||n.startsWith("/pets/")))return!1;if(await q(i,s,e,n,d))return!0;if(n==="/daemon/shutdown"&&i.method==="POST")return e.requestShutdown?(a(s,200,{ok:!0}),setTimeout(()=>e.requestShutdown?.(),0),!0):(a(s,503,{error:"Shutdown is not available"}),!0);if(n==="/dashboard/refresh"&&i.method==="POST")return e.dashboardRefresh?.(),a(s,200,{ok:!0}),!0;if(n==="/sessions"&&i.method==="GET"){if(!e.hookSessions)return a(s,503,{error:"Hooks subsystem unavailable"}),!0;const o=d.searchParams.get("projectId"),l=o!=null&&o!==""?Number(o):void 0,r=d.searchParams.get("ids"),h=r?r.split(",").map(t=>t.trim()).filter(Boolean).slice(0,100):void 0,u=e.hookSessions,c=u.listWithCounts(l,h),g=x(),v=e.terminalRefresher?.lastSnapshot?.terminals??{},m={};for(const t of c){const p=t.harness??"";p in m||(m[p]=O(j[t.harness]?.modelNames??[]))}return a(s,200,{sessions:c.map(t=>{const p=e.sessionProbe?.currentModel(t.sessionId)??null,S=e.sessionProbe?.transcriptPresent(t.sessionId)??null,k=P(t.harness)?e.harnesses?.get(t.harness)?.resume:void 0;return{...t,pidAlive:E(t,g),canOpenTerminal:!!(k?.supported&&k.openArgs),terminal:v[t.sessionId]??null,interruptedAt:t.turnOpen===!0?e.sessionProbe?.interruptedAt(t.sessionId,u.lastMainEventAtOf(t.sessionId)??t.lastSeenAt)??null:null,model:p,modelAlias:C(m[t.harness??""]??[],p),mode:e.sessionProbe?.currentMode(t.sessionId)??null,effort:e.sessionProbe?.currentEffort(t.sessionId)??null,contextTokens:e.sessionProbe?.currentContextTokens(t.sessionId)??null,transcriptPresent:Q(S,t.hasRun)}}),modelCatalog:m}),!0}const b=n.match(/^\/sessions\/([^/]+)$/);if(b&&i.method==="PATCH"){if(!e.hookSessions)return a(s,503,{error:"Hooks subsystem unavailable"}),!0;const o=decodeURIComponent(b[1]);if(!e.hookSessions.getBySessionId(o))return a(s,404,{error:"Session not found"}),!0;try{const l=X.parse(await y(i)),r=e.hookEvents?.listBySession(o,1),h=r?.[r.length-1]?.source,u=P(h)?_(h):null;if(u){try{await u.setSessionTitle(o,l.title)}catch(v){return a(s,502,{error:v instanceof Error?v.message:"Host rename failed"}),!0}const g=e.hookSessions.setTitle(o,l.title);return g?.projectId!=null&&e.hookMirror?.syncProject(g.projectId),a(s,200,{session:g}),!0}const c=e.hookSessions.setPendingTitle(o,l.title);c?.projectId!=null&&e.hookMirror?.syncProject(c.projectId),a(s,200,{session:c})}catch(l){a(s,400,{error:l instanceof Error?l.message:"Invalid body"})}return!0}if(b&&i.method==="DELETE"){if(!e.hookSessions||!e.hookEvents)return a(s,503,{error:"Hooks subsystem unavailable"}),!0;const o=decodeURIComponent(b[1]),l=e.hookSessions.getBySessionId(o);if(!l)return a(s,404,{error:"Session not found"}),!0;const r=D({sessions:e.hookSessions,events:e.hookEvents,dispatches:e.hookDispatches,deliverer:e.messageDeliverer,watches:e.sessionWatches,orchestrations:e.orchestrations,questions:e.questionTracker,sideQuestions:e.sideQuestions?.repo,probe:e.sessionProbe,uploads:e.uploads},o);return l.projectId!=null&&e.hookMirror?.syncProject(l.projectId),a(s,200,{ok:!0,sessionId:o,...r}),!0}const R=n.match(/^\/sessions\/([^/]+)\/open-terminal$/);if(R&&i.method==="POST"){const o=decodeURIComponent(R[1]);let l;try{const h=await y(i);typeof h?.target=="string"&&h.target&&(l=h.target)}catch{}const r=await L(e,o,l);return r.ok?(a(s,200,{ok:!0,sessionId:r.sessionId,command:r.command,cwd:r.cwd,...r.target?{target:r.target}:{}}),!0):(a(s,r.status,{error:r.error}),!0)}if(await H(i,s,e,n,d))return!0;const w=n.match(/^\/sessions\/([^/]+)\/messages$/);if(w){const o=decodeURIComponent(w[1]);if(i.method==="GET")return e.messageDeliverer?e.hookSessions?.getBySessionId(o)?(a(s,200,{messages:e.messageDeliverer.listVisible(o)}),!0):(a(s,404,{error:"Session not found"}),!0):(a(s,503,{error:"Messaging subsystem unavailable"}),!0);if(i.method==="POST"){if(!e.messageDeliverer||!e.hookSessions)return a(s,503,{error:"Messaging subsystem unavailable"}),!0;let l;try{l=Y.parse(await y(i))}catch(c){return a(s,400,{error:c instanceof Error?c.message:"Invalid body"}),!0}const r=[...l.attachments??[],...l.images??[]];if(!l.text.trim()&&r.length===0)return a(s,400,{error:"Message is empty"}),!0;let h=[];if(r.length>0){const c=e.uploads?.refsOf(r)??null;if(!c)return a(s,404,{error:"Attachment not found"}),!0;h=c}const u=await e.messageDeliverer.send({toSessionId:o,text:l.text,...h.length>0?{attachments:h}:{},...l.forceTerminal===!0?{forceTerminal:!0}:{},mode:"prompt",fromKind:l.fromKind??"dashboard",fromSessionId:l.fromSessionId??null,oneWay:!0});return u.ok?a(s,201,{ok:!0,messageId:u.messageId,status:u.status,message:u.message}):a(s,u.status,{error:u.error}),!0}}if(await K(i,s,e,n,d)||await N(i,s,e,n,d)||await $(i,s,e,n,d)||await B(i,s,e,n,d))return!0;const T=n.match(/^\/sessions\/([^/]+)\/messages\/([^/]+)\/resend$/);if(T&&i.method==="POST"){if(!e.messageDeliverer)return a(s,503,{error:"Messaging subsystem unavailable"}),!0;const o=await e.messageDeliverer.resend(decodeURIComponent(T[2]));return o.ok?a(s,200,{ok:!0,messageId:o.messageId,status:o.status,message:o.message}):a(s,o.status,{error:o.error}),!0}const I=n.match(/^\/sessions\/([^/]+)\/messages\/([^/]+)\/dismiss$/);if(I&&i.method==="POST"){if(!e.messageDeliverer)return a(s,503,{error:"Messaging subsystem unavailable"}),!0;const o=e.messageDeliverer.dismiss(decodeURIComponent(I[1]),decodeURIComponent(I[2]));return o.ok?a(s,200,{ok:!0}):a(s,o.status,{error:o.error}),!0}if(await U(i,s,e,n,d)||await G(i,s,e,n)||await W(i,s,e,n,d))return!0;if(n==="/messaging/capabilities"&&i.method==="GET"){const o=e.messageDeliverer?.hasTerminalChannel()??!1;return a(s,200,{capabilities:z().map(({harness:l,surface:r})=>({harness:l,discovery:r.discovery,prompt:Z(r,o),inject:r.inject!==null,headless:r.headless!==null,watch:r.idleSignals.length>0,attachKinds:r.attach?.kinds??[],pathRefs:r.pathRefs!==null,pathRefLines:r.pathRefs?.lines===!0,pathRefKinds:r.pathRefs?.kinds??[],sideQuestion:r.sideQuestion!==null,unsupportedReasons:r.unsupportedReasons??null}))}),!0}if(n==="/messaging/diagnostics"&&i.method==="GET"){if(!e.messageDeliverer||!e.hookSessions)return a(s,503,{error:"Message subsystem unavailable"}),!0;const o=d.searchParams.get("session"),l=d.searchParams.get("project"),r=V(),h=e.projects.list(),u=await Promise.all(h.map(async m=>({id:m.id,name:m.name,path:m.path,captures:await Promise.all(r.map(async({harness:t,surface:p})=>({harness:t,...await p.scriptHealth({projectPath:m.path})})))}))),c=(m,t)=>u.find(p=>p.id===m)?.captures.find(p=>p.harness===t)??null,g=x(),v=e.hookSessions.listWithCounts(o?void 0:l?Number(l):void 0).filter(m=>o?m.sessionId===o:E(m,g)!==!1).map(m=>{const t=e.messageDeliverer.diagnose(m.sessionId),p=c(m.projectId,m.harness??null),S={inbox:t.inbox,queue:t.queue,relay:t.relay,terminal:t.terminal};return{sessionId:m.sessionId,projectId:m.projectId,harness:m.harness??null,title:m.title,lastSeenAt:m.lastSeenAt,eventCount:m.eventCount??0,lastEventType:m.lastEventType??null,alive:t.alive,paneEnvReported:t.paneEnvReported,channels:S,queue:{pending:t.pending,stalled:t.stalled},reachable:Object.values(S).some(k=>k.status==="ready"),hints:ee({diag:t,capture:p,eventCount:m.eventCount??0})}});return a(s,200,{daemon:{version:F,platform:process.platform,dataDir:J(),uptimeMs:Math.round(process.uptime()*1e3),terminalPreset:A().terminal.preset,terminalTextChannel:e.messageDeliverer.hasTerminalChannel(),hooksEnabled:M()},projects:u,sessions:v}),!0}return!1}
@@ -1 +1 @@
1
- import{noteRequestBody as u}from"./api-log.js";export function readBody(n){return new Promise((t,e)=>{const r=[];n.on("data",o=>r.push(o)),n.on("end",()=>{const o=Buffer.concat(r).toString("utf8");u(n,o),t(o)}),n.on("error",e)})}export async function readJson(n){return JSON.parse(await readBody(n))}export function readRawBody(n,t){return new Promise((e,r)=>{const o=[];let a=0;n.on("data",s=>{if(a+=s.length,a>t){n.destroy(),r(new Error("body too large"));return}o.push(s)}),n.on("end",()=>e(Buffer.concat(o))),n.on("error",r)})}export function sendJson(n,t,e){n.statusCode=t,n.setHeader("content-type","application/json"),n.end(JSON.stringify(e))}
1
+ import{noteRequestBody as d}from"./api-log.js";export function readBody(n){return new Promise((t,r)=>{const o=[];n.on("data",e=>o.push(e)),n.on("end",()=>{const e=Buffer.concat(o).toString("utf8");d(n,e),t(e)}),n.on("error",r)})}export async function readJson(n){return JSON.parse(await readBody(n))}export function readRawBody(n,t){return new Promise((r,o)=>{const e=[];let a=0;n.on("data",s=>{if(a+=s.length,a>t){n.destroy(),o(new Error("body too large"));return}e.push(s)}),n.on("end",()=>r(Buffer.concat(e))),n.on("error",o)})}export function sendJson(n,t,r){n.statusCode=t,n.setHeader("content-type","application/json"),n.end(JSON.stringify(r))}
@@ -1 +1 @@
1
- import{claudeLivenessById as s}from"./claude-liveness.js";import{codexLivenessById as c}from"@weavecode/harness";const i=15e3;let o=new Map;async function a(n){try{o=await c(void 0,n)}catch{}}let e=null;function f(){e||(e=setInterval(()=>{a(Date.now())},i),e.unref())}export function combinedLivenessOf(){f();const n=s();for(const[t,r]of o)n.set(t,r);return n}export function resetCombinedLivenessForTest(){e&&(clearInterval(e),e=null),o=new Map}
1
+ import{claudeLivenessById as r}from"./claude-liveness.js";import{codexLivenessById as c}from"@weavecode/harness";const i=15e3;let t=new Map;async function a(n){try{t=await c(void 0,n)}catch{}}let e=null;function f(){e||(e=setInterval(()=>{a(Date.now())},i),e.unref())}export function combinedLivenessOf(){f();const n=r();for(const[o,s]of t)n.set(o,s);return n}export function resetCombinedLivenessForTest(){e&&(clearInterval(e),e=null),t=new Map}
@@ -1 +1 @@
1
- import{Server as b}from"@modelcontextprotocol/sdk/server/index.js";import{StreamableHTTPServerTransport as f}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as g,ListToolsRequestSchema as S}from"@modelcontextprotocol/sdk/types.js";import{readBody as j,sendJson as w}from"./http.js";async function a(t,n,e,o){const r=await fetch(`http://127.0.0.1:${t.port}/api${e}`,{method:n,headers:{...t.token?{"x-weave-local":t.token}:{},...o===void 0?{}:{"content-type":"application/json"}},...o===void 0?{}:{body:JSON.stringify(o)}}),s=await r.text(),p=(()=>{try{return JSON.parse(s)}catch{return{raw:s}}})();if(!r.ok){const l=p&&typeof p=="object"&&"error"in p?String(p.error):`HTTP ${r.status}`;throw new Error(l)}return p}const d=t=>{const n=new URLSearchParams;for(const[o,r]of Object.entries(t))r!==void 0&&r!==""&&n.set(o,String(r));const e=n.toString();return e?`?${e}`:""},u={type:"object",required:["id","kind"],properties:{id:{type:"string",description:'session id, or "w:<uuid>" for a webhook node'},kind:{type:"string",enum:["session","webhook"]},webhookToken:{type:"string"},url:{type:"string",description:"webhook exit: outbound URL"},secret:{type:"string",description:"webhook exit: optional HMAC secret"}}},m={type:"object",required:["id","from","to","text"],properties:{id:{type:"string"},from:{type:"string"},to:{type:"string"},text:{type:"string",description:"message body; {upstream}/{summary}/{session} are substituted"},extract:{type:"string",description:"optional extraction prompt for {summary}"}}},c={type:"object",additionalProperties:!0},h={type:"object",additionalProperties:!0},k=[{name:"list_orchestrations",description:"List orchestrations (optionally by project). Returns { orchestrations: OrchestrationRow[] }; each row has id/name/projectId/startText/nodes/edges/enabled/cron/nextRunAt.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{orchestrations:{type:"array",items:c}},required:["orchestrations"]}},{name:"get_orchestration",description:"Get one orchestration definition (nodes, edges, startText, cron, enabled). Returns { orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{orchestration:c},required:["orchestration"]}},{name:"create_orchestration",description:"Create an orchestration. enabled defaults to true, which makes the entry session auto-fire the graph on EVERY natural turn \u2014 pass enabled:false when the run should be triggered manually. Edges support {upstream}/{summary}/{session}; a cycle is rejected. Returns { ok, orchestration }.",inputSchema:{type:"object",required:["name","nodes","edges"],properties:{name:{type:"string"},startText:{type:"string",description:"first message for session entries (manual trigger)"},projectId:{type:"number",description:"webhook-only orchestrations"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"update_orchestration",description:"Update part of an orchestration (omit fields to keep them; changing the graph does not affect a run already in flight). Returns { ok, orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},name:{type:"string"},startText:{type:"string"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"delete_orchestration",description:"Delete a definition. Run history (orchestration_runs) is kept. Returns { ok, orchestrationId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestrationId:{type:"number"}},required:["ok","orchestrationId"]}},{name:"trigger_orchestration",description:"Start a run. Manual trigger works even when enabled=false. Optional text overrides startText; entries restricts which entry nodes run. Dead target sessions are opened automatically, and delivery waits for their SessionStart. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},text:{type:"string"},entries:{type:"array",items:{type:"string"}}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_runs",description:"List runs, newest first. Returns { runs: RunSummary[], nextBefore }. RunSummary has id/orchestrationId/name/status/deliveries/pendingCounts/createdAt.",inputSchema:{type:"object",properties:{orchestrationId:{type:"number"},projectId:{type:"number"},status:{type:"string"},limit:{type:"number"},before:{type:"number"}}},outputSchema:{type:"object",properties:{runs:{type:"array",items:h},nextBefore:{type:["number","null"]}},required:["runs"]}},{name:"get_run",description:'Get a run with state.events (deliveries and stage:"ensure" opens) and state.pending per session. Returns { run }. status becomes interrupted when the daemon restarts (runs are not resumed).',inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{run:h},required:["run"]}},{name:"cancel_run",description:"Cancel a running run. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_sessions",description:"List sessions for picking graph nodes; minimal fields only (sessionId/projectId/title/harness/lastSeenAt/turnOpen/pidAlive). Returns { sessions }.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{sessions:{type:"array",items:{type:"object",additionalProperties:!0}}},required:["sessions"]}}],i=t=>typeof t=="number"?t:void 0,y=t=>typeof t=="string"?t:void 0;async function I(t,n,e){switch(n){case"list_orchestrations":return a(t,"GET",`/messaging/orchestrations${d({projectId:i(e.projectId)})}`);case"get_orchestration":{const r=(await a(t,"GET","/messaging/orchestrations")).orchestrations.find(s=>s.id===i(e.id));if(!r)throw new Error(`Orchestration not found: ${String(e.id)}`);return{orchestration:r}}case"create_orchestration":return a(t,"POST","/messaging/orchestrations",{name:e.name,startText:e.startText,projectId:i(e.projectId),nodes:e.nodes,edges:e.edges,cron:e.cron??null,enabled:e.enabled});case"update_orchestration":{const o=i(e.id);return a(t,"PUT",`/messaging/orchestrations/${o}`,{...e.name===void 0?{}:{name:e.name},...e.startText===void 0?{}:{startText:e.startText},...e.nodes===void 0?{}:{nodes:e.nodes},...e.edges===void 0?{}:{edges:e.edges},...e.cron===void 0?{}:{cron:e.cron},...e.enabled===void 0?{}:{enabled:e.enabled}})}case"delete_orchestration":return a(t,"DELETE",`/messaging/orchestrations/${i(e.id)}`);case"trigger_orchestration":return a(t,"POST",`/messaging/orchestrations/${i(e.id)}/trigger`,{...y(e.text)?{text:e.text}:{},...Array.isArray(e.entries)?{entries:e.entries}:{}});case"list_runs":return a(t,"GET",`/messaging/orchestration-runs${d({orchestrationId:i(e.orchestrationId),projectId:i(e.projectId),status:y(e.status),limit:i(e.limit),before:i(e.before)})}`);case"get_run":return a(t,"GET",`/messaging/orchestration-runs/${i(e.id)}`);case"cancel_run":return a(t,"POST",`/messaging/orchestration-runs/${i(e.id)}/cancel`);case"list_sessions":return{sessions:(await a(t,"GET",`/sessions${d({projectId:i(e.projectId)})}`)).sessions.map(r=>({sessionId:r.sessionId,projectId:r.projectId,title:r.title,harness:r.harness,lastSeenAt:r.lastSeenAt,turnOpen:r.turnOpen,pidAlive:r.pidAlive}))};default:throw new Error(`Unknown tool: ${n}`)}}function T(t){const n=new b({name:"weave-orchestration",version:"0.1.0"},{capabilities:{tools:{}}});return n.setRequestHandler(S,async()=>({tools:k})),n.setRequestHandler(g,async e=>{const{name:o,arguments:r}=e.params;try{const s=await I(t,o,r??{});return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s}}catch(s){return{isError:!0,content:[{type:"text",text:s instanceof Error?s.message:String(s)}]}}}),n}export async function handleMcpRequest(t,n,e){const o=T(e),r=new f({sessionIdGenerator:void 0,enableJsonResponse:!0});n.on("close",()=>{r.close(),o.close()}),await o.connect(r);let s;if(t.method==="POST"){const p=await j(t);try{s=p.trim()?JSON.parse(p):void 0}catch{w(n,400,{error:"Invalid JSON body"});return}}await r.handleRequest(t,n,s)}
1
+ import{Server as g}from"@modelcontextprotocol/sdk/server/index.js";import{StreamableHTTPServerTransport as b}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as f,ListToolsRequestSchema as S}from"@modelcontextprotocol/sdk/types.js";import{readBody as j,sendJson as w}from"./http.js";async function a(t,n,e,r){const s=await fetch(`http://127.0.0.1:${t.port}/api${e}`,{method:n,headers:{...t.token?{"x-weave-local":t.token}:{},...r===void 0?{}:{"content-type":"application/json"}},...r===void 0?{}:{body:JSON.stringify(r)}}),i=await s.text(),p=(()=>{try{return JSON.parse(i)}catch{return{raw:i}}})();if(!s.ok){const l=p&&typeof p=="object"&&"error"in p?String(p.error):`HTTP ${s.status}`;throw new Error(l)}return p}const d=t=>{const n=new URLSearchParams;for(const[r,s]of Object.entries(t))s!==void 0&&s!==""&&n.set(r,String(s));const e=n.toString();return e?`?${e}`:""},u={type:"object",required:["id","kind"],properties:{id:{type:"string",description:'session id, or "w:<uuid>" for a webhook node'},kind:{type:"string",enum:["session","webhook"]},webhookToken:{type:"string"},url:{type:"string",description:"webhook exit: outbound URL"},secret:{type:"string",description:"webhook exit: optional HMAC secret"}}},m={type:"object",required:["id","from","to","text"],properties:{id:{type:"string"},from:{type:"string"},to:{type:"string"},text:{type:"string",description:"message body; {upstream}/{summary}/{session} are substituted"},extract:{type:"string",description:"optional extraction prompt for {summary}"}}},c={type:"object",additionalProperties:!0},y={type:"object",additionalProperties:!0},I=[{name:"list_orchestrations",description:"List orchestrations (optionally by project). Returns { orchestrations: OrchestrationRow[] }; each row has id/name/projectId/startText/nodes/edges/enabled/cron/nextRunAt.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{orchestrations:{type:"array",items:c}},required:["orchestrations"]}},{name:"get_orchestration",description:"Get one orchestration definition (nodes, edges, startText, cron, enabled). Returns { orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{orchestration:c},required:["orchestration"]}},{name:"create_orchestration",description:"Create an orchestration. enabled defaults to true, which makes the entry session auto-fire the graph on EVERY natural turn \u2014 pass enabled:false when the run should be triggered manually. Edges support {upstream}/{summary}/{session}; a cycle is rejected. Returns { ok, orchestration }.",inputSchema:{type:"object",required:["name","nodes","edges"],properties:{name:{type:"string"},startText:{type:"string",description:"first message for session entries (manual trigger)"},projectId:{type:"number",description:"webhook-only orchestrations"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"update_orchestration",description:"Update part of an orchestration (omit fields to keep them; changing the graph does not affect a run already in flight). Returns { ok, orchestration }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},name:{type:"string"},startText:{type:"string"},nodes:{type:"array",items:u},edges:{type:"array",items:m},cron:{type:["string","null"]},enabled:{type:"boolean"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestration:c},required:["ok","orchestration"]}},{name:"delete_orchestration",description:"Delete a definition. Run history (orchestration_runs) is kept. Returns { ok, orchestrationId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},orchestrationId:{type:"number"}},required:["ok","orchestrationId"]}},{name:"trigger_orchestration",description:"Start a run. Manual trigger works even when enabled=false. Optional text overrides startText; entries restricts which entry nodes run. Dead target sessions are opened automatically, and delivery waits for their SessionStart. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"},text:{type:"string"},entries:{type:"array",items:{type:"string"}}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_runs",description:"List runs, newest first. Returns { runs: RunSummary[], nextBefore }. RunSummary has id/orchestrationId/name/status/deliveries/pendingCounts/createdAt.",inputSchema:{type:"object",properties:{orchestrationId:{type:"number"},projectId:{type:"number"},status:{type:"string"},limit:{type:"number"},before:{type:"number"}}},outputSchema:{type:"object",properties:{runs:{type:"array",items:y},nextBefore:{type:["number","null"]}},required:["runs"]}},{name:"get_run",description:'Get a run with state.events (deliveries and stage:"ensure" opens) and state.pending per session. Returns { run }. status becomes interrupted when the daemon restarts (runs are not resumed).',inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{run:y},required:["run"]}},{name:"cancel_run",description:"Cancel a running run. Returns { ok, runId }.",inputSchema:{type:"object",required:["id"],properties:{id:{type:"number"}}},outputSchema:{type:"object",properties:{ok:{type:"boolean"},runId:{type:"number"}},required:["ok","runId"]}},{name:"list_sessions",description:"List sessions for picking graph nodes; minimal fields only (sessionId/projectId/title/harness/lastSeenAt/turnOpen/pidAlive). Returns { sessions }.",inputSchema:{type:"object",properties:{projectId:{type:"number"}}},outputSchema:{type:"object",properties:{sessions:{type:"array",items:{type:"object",additionalProperties:!0}}},required:["sessions"]}}],o=t=>typeof t=="number"?t:void 0,h=t=>typeof t=="string"?t:void 0;async function k(t,n,e){switch(n){case"list_orchestrations":return a(t,"GET",`/messaging/orchestrations${d({projectId:o(e.projectId)})}`);case"get_orchestration":{const r=(await a(t,"GET","/messaging/orchestrations")).orchestrations.find(s=>s.id===o(e.id));if(!r)throw new Error(`Orchestration not found: ${String(e.id)}`);return{orchestration:r}}case"create_orchestration":return a(t,"POST","/messaging/orchestrations",{name:e.name,startText:e.startText,projectId:o(e.projectId),nodes:e.nodes,edges:e.edges,cron:e.cron??null,enabled:e.enabled});case"update_orchestration":{const r=o(e.id);return a(t,"PUT",`/messaging/orchestrations/${r}`,{...e.name===void 0?{}:{name:e.name},...e.startText===void 0?{}:{startText:e.startText},...e.nodes===void 0?{}:{nodes:e.nodes},...e.edges===void 0?{}:{edges:e.edges},...e.cron===void 0?{}:{cron:e.cron},...e.enabled===void 0?{}:{enabled:e.enabled}})}case"delete_orchestration":return a(t,"DELETE",`/messaging/orchestrations/${o(e.id)}`);case"trigger_orchestration":return a(t,"POST",`/messaging/orchestrations/${o(e.id)}/trigger`,{...h(e.text)?{text:e.text}:{},...Array.isArray(e.entries)?{entries:e.entries}:{}});case"list_runs":return a(t,"GET",`/messaging/orchestration-runs${d({orchestrationId:o(e.orchestrationId),projectId:o(e.projectId),status:h(e.status),limit:o(e.limit),before:o(e.before)})}`);case"get_run":return a(t,"GET",`/messaging/orchestration-runs/${o(e.id)}`);case"cancel_run":return a(t,"POST",`/messaging/orchestration-runs/${o(e.id)}/cancel`);case"list_sessions":return{sessions:(await a(t,"GET",`/sessions${d({projectId:o(e.projectId)})}`)).sessions.map(r=>({sessionId:r.sessionId,projectId:r.projectId,title:r.title,harness:r.harness,lastSeenAt:r.lastSeenAt,turnOpen:r.turnOpen,pidAlive:r.pidAlive}))};default:throw new Error(`Unknown tool: ${n}`)}}function x(t){const n=new g({name:"weave-orchestration",version:"0.1.0"},{capabilities:{tools:{}}});return n.setRequestHandler(S,async()=>({tools:I})),n.setRequestHandler(f,async e=>{const{name:r,arguments:s}=e.params;try{const i=await k(t,r,s??{});return{content:[{type:"text",text:JSON.stringify(i,null,2)}],structuredContent:i}}catch(i){return{isError:!0,content:[{type:"text",text:i instanceof Error?i.message:String(i)}]}}}),n}export async function handleMcpRequest(t,n,e){const r=x(e),s=new b({sessionIdGenerator:void 0,enableJsonResponse:!0});n.on("close",()=>{s.close(),r.close()}),await r.connect(s);let i;if(t.method==="POST"){const p=await j(t);try{i=p.trim()?JSON.parse(p):void 0}catch{w(n,400,{error:"Invalid JSON body"});return}}await s.handleRequest(t,n,i)}
@@ -1,2 +1,2 @@
1
- import{openSync as p,readSync as m,closeSync as y,statSync as O}from"node:fs";const S=500;export class NarrationWatcher{bus;surfaceOf;pathOf;harnessOf;cursors=new Map;timers=new Map;off=null;constructor(t,e,o,n){this.bus=t,this.surfaceOf=e,this.pathOf=o,this.harnessOf=n}start(){this.off||(this.off=this.bus.subscribe(t=>{t.kind!=="event.ingested"||!t.sessionId||this.schedule(t.sessionId)}))}stop(){this.off?.(),this.off=null;for(const t of this.timers.values())clearTimeout(t);this.timers.clear()}schedule(t){this.timers.get(t)||this.timers.set(t,setTimeout(()=>{this.timers.delete(t),this.pump(t)},S))}pumpForTest(t="test"){return this.pump(t)}async pump(t){const e=this.harnessOf(t),n=(e?this.surfaceOf(e):null)?.lineParser,f=this.pathOf(t);if(!n||!f)return;let r;try{r=O(f).size}catch{this.cursors.delete(t);return}const s=this.cursors.get(t);if(!s||s.path!==f||r<s.offset){this.cursors.set(t,{offset:r,carry:"",path:f});return}if(r===s.offset)return;let h;const u=p(f,"r");try{const i=Buffer.alloc(r-s.offset);m(u,i,0,i.length,s.offset),h=i.toString("utf8")}catch{return}finally{y(u)}const a=(s.carry+h).split(`
2
- `);s.carry=a.pop()??"",s.offset=r;const c=[];for(const i of a){const l=n(i);l&&c.push(l)}c.length>0&&this.bus.emit({kind:"narration.updated",sessionId:t,segs:c,at:new Date().toISOString()})}}
1
+ import{openSync as l,readSync as p,closeSync as m,statSync as d}from"node:fs";const y=500;export class NarrationWatcher{bus;surfaceOf;pathOf;harnessOf;cursors=new Map;timers=new Map;off=null;constructor(t,o,n,e){this.bus=t,this.surfaceOf=o,this.pathOf=n,this.harnessOf=e}start(){this.off||(this.off=this.bus.subscribe(t=>{t.kind!=="event.ingested"||!t.sessionId||this.schedule(t.sessionId)}))}stop(){this.off?.(),this.off=null;for(const t of this.timers.values())clearTimeout(t);this.timers.clear()}schedule(t){this.timers.get(t)||this.timers.set(t,setTimeout(()=>{this.timers.delete(t),this.pump(t)},y))}pumpForTest(t="test"){return this.pump(t)}async pump(t){const o=this.harnessOf(t),n=(o?this.surfaceOf(o):null)?.lineParser,e=this.pathOf(t);if(!n||!e)return;let r;try{r=d(e).size}catch{this.cursors.delete(t);return}const s=this.cursors.get(t);if(!s||s.path!==e||r<s.offset){this.cursors.set(t,{offset:r,carry:"",path:e});return}if(r===s.offset)return;let a;const c=l(e,"r");try{const i=Buffer.alloc(r-s.offset);p(c,i,0,i.length,s.offset),a=i.toString("utf8")}catch{return}finally{m(c)}const h=(s.carry+a).split(`
2
+ `);s.carry=h.pop()??"",s.offset=r;const f=[];for(const i of h){const u=n(i);u&&f.push(u)}f.length>0&&this.bus.emit({kind:"narration.updated",sessionId:t,segs:f,at:new Date().toISOString()})}}
@@ -1 +1 @@
1
- import{captureCommand as a}from"./wezterm-mux.js";import{PRESET_CANDIDATES as s,TerminalBackend as i}from"./backend.js";export class GhosttyBackend extends i{constructor(t){super("ghostty",!1,t)}candidates(t,n){return s.ghostty(t,n,this.platform)}async openViaIpcThenStandalone(t,n){if(this.platform==="linux"){const e=["+new-window",`--working-directory=${t}`,...n.length>0?["-e",...n]:[]];if((await a("ghostty",e))?.ok)return}await this.spawnFirst(this.candidates(t,n.length>0?n:void 0),`Terminal preset "${this.preset}" is unavailable on this platform`)}open(t){return this.openViaIpcThenStandalone(t,[])}async run(t,n){return await this.openViaIpcThenStandalone(t,n),null}}
1
+ import{captureCommand as a}from"./wezterm-mux.js";import{PRESET_CANDIDATES as i,TerminalBackend as s}from"./backend.js";export class GhosttyBackend extends s{constructor(t){super("ghostty",!1,t)}candidates(t,n){return i.ghostty(t,n,this.platform)}async openViaIpcThenStandalone(t,n){if(this.platform==="linux"){const e=["+new-window",`--working-directory=${t}`,...n.length>0?["-e",...n]:[]];if((await a("ghostty",e))?.ok)return}await this.spawnFirst(this.candidates(t,n.length>0?n:void 0),`Terminal preset "${this.preset}" is unavailable on this platform`)}open(t){return this.openViaIpcThenStandalone(t,[])}async run(t,n){return await this.openViaIpcThenStandalone(t,n),null}}