@agent-spaces/server 0.3.63 → 0.3.65

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 (334) hide show
  1. package/dist/adapters/claude-code-runtime/index.js +68 -2
  2. package/dist/adapters/claude-code-runtime/message-format.js +27 -1
  3. package/dist/adapters/claude-code-runtime/sdk-config.js +12 -0
  4. package/dist/adapters/git.js +168 -57
  5. package/dist/agents/agent-designer.js +66 -12
  6. package/dist/agents/agent-message-parts.js +1 -1
  7. package/dist/agents/commit-agent.js +4 -2
  8. package/dist/agents/issue-task-controller.js +7 -3
  9. package/dist/app.js +56 -69
  10. package/dist/package.json +1 -1
  11. package/dist/routes/agent-commands.js +72 -0
  12. package/dist/routes/agent-sse.js +7 -0
  13. package/dist/routes/agent.js +18 -1
  14. package/dist/routes/database.js +346 -0
  15. package/dist/routes/git.js +198 -267
  16. package/dist/routes/kanban.js +39 -0
  17. package/dist/routes/robot-account.js +68 -0
  18. package/dist/services/agent-commands.js +168 -0
  19. package/dist/services/agent.js +36 -2
  20. package/dist/services/builtin-tools/command-tools.js +117 -0
  21. package/dist/services/builtin-tools/database-tools.js +578 -0
  22. package/dist/services/builtin-tools/index.js +5 -0
  23. package/dist/services/builtin-tools/input-helpers.js +26 -0
  24. package/dist/services/builtin-tools/issue-tools.js +209 -0
  25. package/dist/services/builtin-tools/kanban-tools.js +281 -0
  26. package/dist/services/database-vector.js +244 -0
  27. package/dist/services/git-operation-log.js +40 -0
  28. package/dist/services/global-wechat-qr.js +72 -0
  29. package/dist/services/hook-engine.js +175 -17
  30. package/dist/services/kanban.js +50 -0
  31. package/dist/services/notification-hub/bot-agent.js +3 -1
  32. package/dist/services/notification-hub/service.js +12 -2
  33. package/dist/services/robot-account.js +34 -0
  34. package/dist/services/workspace.js +2 -0
  35. package/dist/storage/database-store.js +365 -0
  36. package/dist/storage/kanban-store.js +142 -0
  37. package/dist/storage/robot-account-store.js +39 -0
  38. package/dist/web/404.html +1 -1
  39. package/dist/web/__next.__PAGE__.txt +4 -4
  40. package/dist/web/__next._full.txt +24 -31
  41. package/dist/web/__next._head.txt +4 -4
  42. package/dist/web/__next._index.txt +14 -14
  43. package/dist/web/__next._tree.txt +3 -8
  44. package/dist/web/_next/static/chunks/0-a.-hl3wv99k.js +1 -0
  45. package/dist/web/_next/static/chunks/{0ctg5qmw7uu.1.js → 0-pi.67w.ymsr.js} +3 -3
  46. package/dist/web/_next/static/chunks/0-v_p6j5u3_9l.js +1 -0
  47. package/dist/web/_next/static/chunks/0.-x29t-8gk0r.js +1 -0
  48. package/dist/web/_next/static/chunks/0.6b64sy0g5.3.js +3 -0
  49. package/dist/web/_next/static/chunks/0.l5e8~r7_0~p.js +1 -0
  50. package/dist/web/_next/static/chunks/00-syqzi-6zxr.js +1 -0
  51. package/dist/web/_next/static/chunks/{13~y-b.b9rrw4.js → 01~quun6sefgl.js} +1 -1
  52. package/dist/web/_next/static/chunks/02802taez976w.js +67 -0
  53. package/dist/web/_next/static/chunks/02j4sr9psucf-.js +1 -0
  54. package/dist/web/_next/static/chunks/033.awk90g6eh.js +1 -0
  55. package/dist/web/_next/static/chunks/06.kdsa9rr2h1.js +1 -0
  56. package/dist/web/_next/static/chunks/{0-oog4zg4_m~m.css → 062f9zqctzg.b.css} +0 -3
  57. package/dist/web/_next/static/chunks/06si8l0doqe8p.js +1 -0
  58. package/dist/web/_next/static/chunks/08ugbvzr20drp.js +2 -0
  59. package/dist/web/_next/static/chunks/{0kof5qdg8c2-k.js → 08x85faoz58i7.js} +37 -37
  60. package/dist/web/_next/static/chunks/0_cqojbge48kq.js +5 -0
  61. package/dist/web/_next/static/chunks/0_mvduwjsm35w.js +1 -0
  62. package/dist/web/_next/static/chunks/0d6~~lv0-6kex.js +3 -0
  63. package/dist/web/_next/static/chunks/{0ogpc3f3keopc.js → 0db14450oqzhg.js} +2 -2
  64. package/dist/web/_next/static/chunks/0fttswpzu69qx.js +1 -0
  65. package/dist/web/_next/static/chunks/0gdwop9cnpmtu.js +1 -0
  66. package/dist/web/_next/static/chunks/0ghx3j_.-gdyd.js +1 -0
  67. package/dist/web/_next/static/chunks/0j-l7l_k9jt45.js +1 -0
  68. package/dist/web/_next/static/chunks/0k4zdm72k_bfy.js +1 -0
  69. package/dist/web/_next/static/chunks/0kbvoxla7f751.js +1 -0
  70. package/dist/web/_next/static/chunks/{0aa6bcdmtpekn.js → 0l2w0qz1ea7ql.js} +2 -2
  71. package/dist/web/_next/static/chunks/0p3h-h3zj5ujg.js +30 -0
  72. package/dist/web/_next/static/chunks/0paaat8y96ayc.js +7 -0
  73. package/dist/web/_next/static/chunks/0pm-un~-sy3rl.js +1 -0
  74. package/dist/web/_next/static/chunks/0pq318f8xgafg.js +1 -0
  75. package/dist/web/_next/static/chunks/0t6s8of0qr6nc.js +1 -0
  76. package/dist/web/_next/static/chunks/0u6h-hqc_i52e.js +1 -0
  77. package/dist/web/_next/static/chunks/0uxzi~9b~k4mn.js +31 -0
  78. package/dist/web/_next/static/chunks/{002-dxhags4dj.js → 0v6hte2z-32ca.js} +2 -2
  79. package/dist/web/_next/static/chunks/{014x2qbuiszni.js → 0vis~lx0nxgn-.js} +3 -3
  80. package/dist/web/_next/static/chunks/{0y09i51u6ixq5.js → 0w7.tb29958zj.js} +1 -1
  81. package/dist/web/_next/static/chunks/0xbaakj0dfc0..js +1 -0
  82. package/dist/web/_next/static/chunks/0yd.m1afqg.2t.js +3 -0
  83. package/dist/web/_next/static/chunks/0yhbr8hl09b-5.js +1 -0
  84. package/dist/web/_next/static/chunks/0zncg76rgtbm-.js +1 -0
  85. package/dist/web/_next/static/chunks/0z~vqzbm_q371.js +1 -0
  86. package/dist/web/_next/static/chunks/0~~_ltu6dx_ch.js +1 -0
  87. package/dist/web/_next/static/chunks/{02c22g~xd-y30.js → 11cchuwoupmbf.js} +2 -2
  88. package/dist/web/_next/static/chunks/12jm4gwmvq-0q.js +90 -0
  89. package/dist/web/_next/static/chunks/12oxcgyhpaxw~.js +1 -0
  90. package/dist/web/_next/static/chunks/1452eibz62gs6.css +1 -0
  91. package/dist/web/_next/static/chunks/16zlreiems5cn.js +1 -0
  92. package/dist/web/_next/static/chunks/18awqjk9-o5m0.js +1 -0
  93. package/dist/web/_next/static/chunks/18c7g84y01mj0.js +1 -0
  94. package/dist/web/_next/static/chunks/{turbopack-0ndm2zc_pdptk.js → turbopack-11qjwlynmfc-n.js} +1 -1
  95. package/dist/web/_not-found/__next._full.txt +31 -30
  96. package/dist/web/_not-found/__next._head.txt +4 -4
  97. package/dist/web/_not-found/__next._index.txt +14 -14
  98. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
  99. package/dist/web/_not-found/__next._not-found.txt +3 -3
  100. package/dist/web/_not-found/__next._tree.txt +3 -3
  101. package/dist/web/_not-found.html +1 -1
  102. package/dist/web/_not-found.txt +31 -30
  103. package/dist/web/index.html +1 -1
  104. package/dist/web/index.txt +24 -31
  105. package/dist/web/login/__next._full.txt +32 -36
  106. package/dist/web/login/__next._head.txt +4 -4
  107. package/dist/web/login/__next._index.txt +14 -14
  108. package/dist/web/login/__next._tree.txt +3 -8
  109. package/dist/web/login/__next.login.__PAGE__.txt +4 -4
  110. package/dist/web/login/__next.login.txt +3 -3
  111. package/dist/web/login.html +1 -1
  112. package/dist/web/login.txt +32 -36
  113. package/dist/web/settings/__next._full.txt +34 -38
  114. package/dist/web/settings/__next._head.txt +4 -4
  115. package/dist/web/settings/__next._index.txt +14 -14
  116. package/dist/web/settings/__next._tree.txt +3 -8
  117. package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
  118. package/dist/web/settings/__next.settings.txt +5 -5
  119. package/dist/web/settings/agents/__next._full.txt +27 -32
  120. package/dist/web/settings/agents/__next._head.txt +4 -4
  121. package/dist/web/settings/agents/__next._index.txt +14 -14
  122. package/dist/web/settings/agents/__next._tree.txt +3 -8
  123. package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
  124. package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
  125. package/dist/web/settings/agents/__next.settings.txt +5 -5
  126. package/dist/web/settings/agents.html +1 -1
  127. package/dist/web/settings/agents.txt +27 -32
  128. package/dist/web/settings/mcps/__next._full.txt +27 -32
  129. package/dist/web/settings/mcps/__next._head.txt +4 -4
  130. package/dist/web/settings/mcps/__next._index.txt +14 -14
  131. package/dist/web/settings/mcps/__next._tree.txt +3 -8
  132. package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
  133. package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
  134. package/dist/web/settings/mcps/__next.settings.txt +5 -5
  135. package/dist/web/settings/mcps.html +1 -1
  136. package/dist/web/settings/mcps.txt +27 -32
  137. package/dist/web/settings/models/__next._full.txt +27 -32
  138. package/dist/web/settings/models/__next._head.txt +4 -4
  139. package/dist/web/settings/models/__next._index.txt +14 -14
  140. package/dist/web/settings/models/__next._tree.txt +3 -8
  141. package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
  142. package/dist/web/settings/models/__next.settings.models.txt +3 -3
  143. package/dist/web/settings/models/__next.settings.txt +5 -5
  144. package/dist/web/settings/models.html +1 -1
  145. package/dist/web/settings/models.txt +27 -32
  146. package/dist/web/settings/output-styles/__next._full.txt +27 -32
  147. package/dist/web/settings/output-styles/__next._head.txt +4 -4
  148. package/dist/web/settings/output-styles/__next._index.txt +14 -14
  149. package/dist/web/settings/output-styles/__next._tree.txt +3 -8
  150. package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +4 -4
  151. package/dist/web/settings/output-styles/__next.settings.output-styles.txt +3 -3
  152. package/dist/web/settings/output-styles/__next.settings.txt +5 -5
  153. package/dist/web/settings/output-styles.html +1 -1
  154. package/dist/web/settings/output-styles.txt +27 -32
  155. package/dist/web/settings/prompts/__next._full.txt +27 -32
  156. package/dist/web/settings/prompts/__next._head.txt +4 -4
  157. package/dist/web/settings/prompts/__next._index.txt +14 -14
  158. package/dist/web/settings/prompts/__next._tree.txt +3 -8
  159. package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +4 -4
  160. package/dist/web/settings/prompts/__next.settings.prompts.txt +3 -3
  161. package/dist/web/settings/prompts/__next.settings.txt +5 -5
  162. package/dist/web/settings/prompts.html +1 -1
  163. package/dist/web/settings/prompts.txt +27 -32
  164. package/dist/web/settings/providers/__next._full.txt +27 -32
  165. package/dist/web/settings/providers/__next._head.txt +4 -4
  166. package/dist/web/settings/providers/__next._index.txt +14 -14
  167. package/dist/web/settings/providers/__next._tree.txt +3 -8
  168. package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
  169. package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
  170. package/dist/web/settings/providers/__next.settings.txt +5 -5
  171. package/dist/web/settings/providers.html +1 -1
  172. package/dist/web/settings/providers.txt +27 -32
  173. package/dist/web/settings/skills/__next._full.txt +27 -32
  174. package/dist/web/settings/skills/__next._head.txt +4 -4
  175. package/dist/web/settings/skills/__next._index.txt +14 -14
  176. package/dist/web/settings/skills/__next._tree.txt +3 -8
  177. package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
  178. package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
  179. package/dist/web/settings/skills/__next.settings.txt +5 -5
  180. package/dist/web/settings/skills.html +1 -1
  181. package/dist/web/settings/skills.txt +27 -32
  182. package/dist/web/settings/tools/__next._full.txt +38 -0
  183. package/dist/web/settings/tools/__next._head.txt +6 -0
  184. package/dist/web/settings/tools/__next._index.txt +15 -0
  185. package/dist/web/settings/tools/__next._tree.txt +3 -0
  186. package/dist/web/settings/tools/__next.settings.tools.__PAGE__.txt +9 -0
  187. package/dist/web/settings/tools/__next.settings.tools.txt +5 -0
  188. package/dist/web/settings/tools/__next.settings.txt +7 -0
  189. package/dist/web/settings/tools.html +1 -0
  190. package/dist/web/settings/tools.txt +38 -0
  191. package/dist/web/settings.html +1 -1
  192. package/dist/web/settings.txt +34 -38
  193. package/dist/web/workflows/__next._full.txt +32 -38
  194. package/dist/web/workflows/__next._head.txt +4 -4
  195. package/dist/web/workflows/__next._index.txt +14 -14
  196. package/dist/web/workflows/__next._tree.txt +3 -8
  197. package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
  198. package/dist/web/workflows/__next.workflows.txt +3 -3
  199. package/dist/web/workflows.html +1 -1
  200. package/dist/web/workflows.txt +32 -38
  201. package/dist/web/workspace/_/__next._full.txt +31 -36
  202. package/dist/web/workspace/_/__next._head.txt +4 -4
  203. package/dist/web/workspace/_/__next._index.txt +14 -14
  204. package/dist/web/workspace/_/__next._tree.txt +4 -8
  205. package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -3
  206. package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
  207. package/dist/web/workspace/_/__next.workspace.txt +3 -3
  208. package/dist/web/workspace/_.html +1 -1
  209. package/dist/web/workspace/_.txt +31 -36
  210. package/dist/web/workspaces/__next._full.txt +30 -37
  211. package/dist/web/workspaces/__next._head.txt +4 -4
  212. package/dist/web/workspaces/__next._index.txt +14 -14
  213. package/dist/web/workspaces/__next._tree.txt +3 -8
  214. package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
  215. package/dist/web/workspaces/__next.workspaces.txt +3 -3
  216. package/dist/web/workspaces.html +1 -1
  217. package/dist/web/workspaces.txt +30 -37
  218. package/dist/ws/agent-prompt.js +45 -8
  219. package/dist/ws/agent-runner.js +88 -10
  220. package/package.json +1 -1
  221. package/dist/web/_next/static/chunks/0-1bfvfwifh-m.js +0 -1
  222. package/dist/web/_next/static/chunks/02mf61htij8g0.js +0 -31
  223. package/dist/web/_next/static/chunks/046me66nilkff.js +0 -1
  224. package/dist/web/_next/static/chunks/04v-pqqs-2lvp.css +0 -1
  225. package/dist/web/_next/static/chunks/06w~.izyfylap.js +0 -1
  226. package/dist/web/_next/static/chunks/09t62a89~jesc.js +0 -3
  227. package/dist/web/_next/static/chunks/09y_3krccdd~u.js +0 -1
  228. package/dist/web/_next/static/chunks/0_e~hmntdfop9.js +0 -1
  229. package/dist/web/_next/static/chunks/0_udc.6.tueey.js +0 -1
  230. package/dist/web/_next/static/chunks/0cke33d38fnby.js +0 -90
  231. package/dist/web/_next/static/chunks/0cyq~8xb~r5fc.js +0 -1
  232. package/dist/web/_next/static/chunks/0ewceguykiut5.js +0 -1
  233. package/dist/web/_next/static/chunks/0fxa1edqr7dve.js +0 -1
  234. package/dist/web/_next/static/chunks/0hra80eyuu37u.js +0 -1
  235. package/dist/web/_next/static/chunks/0ie7y4k2ncvnn.js +0 -1
  236. package/dist/web/_next/static/chunks/0igc~uli58ncw.js +0 -2
  237. package/dist/web/_next/static/chunks/0msb2mi3hiu5_.js +0 -67
  238. package/dist/web/_next/static/chunks/0p1n8bvfnpl41.js +0 -1
  239. package/dist/web/_next/static/chunks/0ppr271hz0xoq.js +0 -1
  240. package/dist/web/_next/static/chunks/0s_dva~eh2yhi.js +0 -3
  241. package/dist/web/_next/static/chunks/0typj55ox8d5i.js +0 -1
  242. package/dist/web/_next/static/chunks/0w2p4ldi2aymp.js +0 -1
  243. package/dist/web/_next/static/chunks/0zc0xgp5ourcn.js +0 -1
  244. package/dist/web/_next/static/chunks/0zmhdridea1s5.js +0 -90
  245. package/dist/web/_next/static/chunks/10.alq.6stmld.js +0 -1
  246. package/dist/web/_next/static/chunks/11b3zgk1etlkw.js +0 -7
  247. package/dist/web/_next/static/chunks/11qp8r5dotf7d.js +0 -1
  248. package/dist/web/_next/static/chunks/12mxlicp247c8.js +0 -1
  249. package/dist/web/_next/static/chunks/135w27dd8c19s.js +0 -5
  250. package/dist/web/_next/static/chunks/176dc-dtokxxi.js +0 -16
  251. package/dist/web/_next/static/chunks/17g-0pqre.anw.js +0 -1
  252. package/dist/web/_next/static/media/0a7740363b4d4863-s.1110aazvokzp..woff2 +0 -0
  253. package/dist/web/_next/static/media/0da9c7f357bd9d4d-s.0ek5sshv8wk3m.woff2 +0 -0
  254. package/dist/web/_next/static/media/1b99372b3eaef0c8-s.p.0gx2haw2tmll8.woff2 +0 -0
  255. package/dist/web/_next/static/media/41e95f694c5c4549-s.0r1jrq7neqdsq.woff2 +0 -0
  256. package/dist/web/_next/static/media/5c285b27cdda1fe8-s.p.0yo6-5yoeeudq.woff2 +0 -0
  257. package/dist/web/_next/static/media/5f9d24ebef5d5292-s.0esuu2f5si~v8.woff2 +0 -0
  258. package/dist/web/_next/static/media/6c55a692938ebbbc-s.0g6rbszwfgn9y.woff2 +0 -0
  259. package/dist/web/_next/static/media/8e6fa89aa22d24ec-s.p.0uvzar8hswo3p.woff2 +0 -0
  260. package/dist/web/_next/static/media/a218039a3287bcfd-s.p.17-1enzs_j91b.woff2 +0 -0
  261. package/dist/web/_next/static/media/b2ea385cb5ae8625-s.0kjod.kaq1k69.woff2 +0 -0
  262. package/dist/web/_next/static/media/bdc7e24a509eb931-s.0apt5mko2.qn3.woff2 +0 -0
  263. package/dist/web/_next/static/media/c3cb240f9c892514-s.163v2i5cux7-c.woff2 +0 -0
  264. package/dist/web/_next/static/media/e2334d715941921e-s.p.12skym0rqknxy.woff2 +0 -0
  265. package/public/output-styles/carmack-mode.md +0 -381
  266. package/public/output-styles/codex-rigor-mode.md +0 -114
  267. package/public/output-styles/dhh-mode.md +0 -265
  268. package/public/output-styles/evan-you-mode.md +0 -539
  269. package/public/output-styles/index.json +0 -37
  270. package/public/output-styles/jobs-mode.md +0 -369
  271. package/public/output-styles/linus-mode.md +0 -135
  272. package/public/output-styles/uncle-bob-mode.md +0 -221
  273. package/public/prompt/andrej-karpathy-skills.md +0 -65
  274. package/public/prompt/claude-token-efficient-coding.md +0 -35
  275. package/public/prompt/index.json +0 -12
  276. package/public/skills/index.json +0 -92
  277. package/public/skills/planning-with-files/planning-with-files-zh/SKILL.md +0 -243
  278. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.ps1 +0 -44
  279. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.sh +0 -46
  280. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.ps1 +0 -124
  281. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.sh +0 -124
  282. package/public/skills/planning-with-files/planning-with-files-zh/scripts/session-catchup.py +0 -438
  283. package/public/skills/planning-with-files/planning-with-files-zh/templates/findings.md +0 -29
  284. package/public/skills/planning-with-files/planning-with-files-zh/templates/progress.md +0 -40
  285. package/public/skills/planning-with-files/planning-with-files-zh/templates/task_plan.md +0 -58
  286. package/public/skills/superpowers/brainstorming/SKILL.md +0 -164
  287. package/public/skills/superpowers/brainstorming/scripts/frame-template.html +0 -214
  288. package/public/skills/superpowers/brainstorming/scripts/helper.js +0 -88
  289. package/public/skills/superpowers/brainstorming/scripts/server.cjs +0 -354
  290. package/public/skills/superpowers/brainstorming/scripts/start-server.sh +0 -148
  291. package/public/skills/superpowers/brainstorming/scripts/stop-server.sh +0 -56
  292. package/public/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +0 -49
  293. package/public/skills/superpowers/brainstorming/visual-companion.md +0 -287
  294. package/public/skills/superpowers/dispatching-parallel-agents/SKILL.md +0 -182
  295. package/public/skills/superpowers/executing-plans/SKILL.md +0 -70
  296. package/public/skills/superpowers/finishing-a-development-branch/SKILL.md +0 -251
  297. package/public/skills/superpowers/receiving-code-review/SKILL.md +0 -213
  298. package/public/skills/superpowers/requesting-code-review/SKILL.md +0 -103
  299. package/public/skills/superpowers/requesting-code-review/code-reviewer.md +0 -168
  300. package/public/skills/superpowers/subagent-driven-development/SKILL.md +0 -279
  301. package/public/skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +0 -25
  302. package/public/skills/superpowers/subagent-driven-development/implementer-prompt.md +0 -113
  303. package/public/skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +0 -61
  304. package/public/skills/superpowers/systematic-debugging/CREATION-LOG.md +0 -119
  305. package/public/skills/superpowers/systematic-debugging/SKILL.md +0 -296
  306. package/public/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +0 -158
  307. package/public/skills/superpowers/systematic-debugging/condition-based-waiting.md +0 -115
  308. package/public/skills/superpowers/systematic-debugging/defense-in-depth.md +0 -122
  309. package/public/skills/superpowers/systematic-debugging/find-polluter.sh +0 -63
  310. package/public/skills/superpowers/systematic-debugging/root-cause-tracing.md +0 -169
  311. package/public/skills/superpowers/systematic-debugging/test-academic.md +0 -14
  312. package/public/skills/superpowers/systematic-debugging/test-pressure-1.md +0 -58
  313. package/public/skills/superpowers/systematic-debugging/test-pressure-2.md +0 -68
  314. package/public/skills/superpowers/systematic-debugging/test-pressure-3.md +0 -69
  315. package/public/skills/superpowers/test-driven-development/SKILL.md +0 -371
  316. package/public/skills/superpowers/test-driven-development/testing-anti-patterns.md +0 -299
  317. package/public/skills/superpowers/using-git-worktrees/SKILL.md +0 -215
  318. package/public/skills/superpowers/using-superpowers/SKILL.md +0 -117
  319. package/public/skills/superpowers/using-superpowers/references/codex-tools.md +0 -59
  320. package/public/skills/superpowers/using-superpowers/references/copilot-tools.md +0 -42
  321. package/public/skills/superpowers/using-superpowers/references/gemini-tools.md +0 -51
  322. package/public/skills/superpowers/verification-before-completion/SKILL.md +0 -139
  323. package/public/skills/superpowers/writing-plans/SKILL.md +0 -152
  324. package/public/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +0 -49
  325. package/public/skills/superpowers/writing-skills/SKILL.md +0 -655
  326. package/public/skills/superpowers/writing-skills/anthropic-best-practices.md +0 -1150
  327. package/public/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
  328. package/public/skills/superpowers/writing-skills/graphviz-conventions.dot +0 -172
  329. package/public/skills/superpowers/writing-skills/persuasion-principles.md +0 -187
  330. package/public/skills/superpowers/writing-skills/render-graphs.js +0 -168
  331. package/public/skills/superpowers/writing-skills/testing-skills-with-subagents.md +0 -384
  332. /package/dist/web/_next/static/{OoXAsPtrUWjC1l898FSvI → x4-CsKe6qUQyFDWVtfvUg}/_buildManifest.js +0 -0
  333. /package/dist/web/_next/static/{OoXAsPtrUWjC1l898FSvI → x4-CsKe6qUQyFDWVtfvUg}/_clientMiddlewareManifest.js +0 -0
  334. /package/dist/web/_next/static/{OoXAsPtrUWjC1l898FSvI → x4-CsKe6qUQyFDWVtfvUg}/_ssgManifest.js +0 -0
@@ -0,0 +1,244 @@
1
+ import { createHash } from 'node:crypto';
2
+ import * as databaseStore from '../storage/database-store.js';
3
+ import * as llmStore from '../storage/llm-store.js';
4
+ const INDEX_BATCH_SIZE = 16;
5
+ const MAX_INDEX_TEXT_LENGTH = 24_000;
6
+ export class DatabaseVectorError extends Error {
7
+ debug;
8
+ constructor(message, debug) {
9
+ super(message);
10
+ this.name = 'DatabaseVectorError';
11
+ this.debug = debug;
12
+ }
13
+ }
14
+ export async function indexDatabaseVectors(workspaceId, databaseId) {
15
+ const database = databaseStore.getDatabase(workspaceId, databaseId);
16
+ if (!database)
17
+ throw new Error(`Database not found: ${databaseId}`);
18
+ if (!database.embeddingModelId)
19
+ throw new Error('Embedding model is not bound to this database.');
20
+ const config = requireEmbeddingModelConfig(database.embeddingModelId);
21
+ const nodes = databaseStore.listNodes(workspaceId, databaseId).filter((node) => !node.isTrash);
22
+ const records = nodes
23
+ .map((node) => ({
24
+ node,
25
+ path: buildDatabaseNodePath(node, nodes),
26
+ text: normalizeIndexText(`${node.title}\n${stripHtml(node.content)}`),
27
+ }))
28
+ .filter((item) => item.text.length > 0);
29
+ let indexedCount = 0;
30
+ for (let index = 0; index < records.length; index += INDEX_BATCH_SIZE) {
31
+ const batch = records.slice(index, index + INDEX_BATCH_SIZE);
32
+ const batchDebug = {
33
+ batchStart: index,
34
+ batchSize: batch.length,
35
+ indexedCount,
36
+ };
37
+ console.info('[database-vector:index] embedding batch', {
38
+ workspaceId,
39
+ databaseId,
40
+ modelId: config.model.modelId,
41
+ providerName: config.provider.name,
42
+ ...batchDebug,
43
+ inputLengths: batch.map((item) => item.text.length),
44
+ });
45
+ const embeddings = await embedTexts(config, batch.map((item) => item.text), batchDebug);
46
+ embeddings.forEach((embedding, offset) => {
47
+ const item = batch[offset];
48
+ databaseStore.upsertDatabaseEmbedding(workspaceId, databaseId, {
49
+ nodeId: item.node.id,
50
+ title: item.node.title,
51
+ path: item.path,
52
+ content: item.text,
53
+ contentHash: hashText(item.text),
54
+ embedding,
55
+ modelId: config.model.modelId,
56
+ agentId: config.model.id,
57
+ });
58
+ indexedCount++;
59
+ });
60
+ }
61
+ databaseStore.deleteStaleDatabaseEmbeddings(workspaceId, databaseId, records.map((item) => item.node.id));
62
+ return {
63
+ ...databaseStore.getVectorStats(workspaceId, databaseId),
64
+ indexedCount,
65
+ skippedCount: nodes.length - records.length,
66
+ };
67
+ }
68
+ export async function searchDatabaseVectors(workspaceId, databaseId, query, limit = 5) {
69
+ const database = databaseStore.getDatabase(workspaceId, databaseId);
70
+ if (!database)
71
+ throw new Error(`Database not found: ${databaseId}`);
72
+ if (!database.embeddingModelId)
73
+ throw new Error('Embedding model is not bound to this database.');
74
+ const cleanQuery = normalizeIndexText(query);
75
+ if (!cleanQuery)
76
+ throw new Error('query is required.');
77
+ const config = requireEmbeddingModelConfig(database.embeddingModelId);
78
+ const [queryEmbedding] = await embedTexts(config, [cleanQuery]);
79
+ return databaseStore.listDatabaseEmbeddings(workspaceId, databaseId)
80
+ .map((row) => ({
81
+ nodeId: row.nodeId,
82
+ title: row.title,
83
+ path: row.path,
84
+ content: row.content,
85
+ updatedAt: row.updatedAt,
86
+ score: cosineSimilarity(queryEmbedding, row.embedding),
87
+ }))
88
+ .sort((a, b) => b.score - a.score)
89
+ .slice(0, Math.max(1, Math.min(limit, 20)));
90
+ }
91
+ function requireEmbeddingModelConfig(modelId) {
92
+ const model = llmStore.getModel(modelId);
93
+ if (!model)
94
+ throw new Error(`Embedding model not found: ${modelId}`);
95
+ if (!model.embedding)
96
+ throw new Error(`Selected model is not marked as an embedding model: ${model.name}`);
97
+ const provider = llmStore.listProviders().find((item) => item.name === model.provider);
98
+ if (!provider)
99
+ throw new Error(`Provider not found for embedding model: ${model.provider}`);
100
+ if (!provider.apiBase || !provider.apiKey || !model.modelId) {
101
+ throw new Error(`Embedding provider is missing apiBase, apiKey, or modelId: ${provider.name}`);
102
+ }
103
+ return { model, provider };
104
+ }
105
+ async function embedTexts(config, input, extraDebug = {}) {
106
+ const requestUrl = getEmbeddingsUrl(config.provider.apiBase);
107
+ const requestDebug = {
108
+ stage: 'embedding_request',
109
+ providerName: config.provider.name,
110
+ modelId: config.model.modelId,
111
+ requestUrl,
112
+ inputCount: input.length,
113
+ inputLengths: input.map((item) => item.length),
114
+ ...extraDebug,
115
+ };
116
+ console.info('[database-vector:embed] request', requestDebug);
117
+ const response = await fetch(requestUrl, {
118
+ method: 'POST',
119
+ headers: {
120
+ Authorization: `Bearer ${config.provider.apiKey}`,
121
+ 'Content-Type': 'application/json',
122
+ },
123
+ body: JSON.stringify({
124
+ model: config.model.modelId,
125
+ input,
126
+ }),
127
+ });
128
+ const responseText = await response.text();
129
+ const responseDebugBase = {
130
+ ...requestDebug,
131
+ stage: 'embedding_response',
132
+ status: response.status,
133
+ responseContentType: response.headers.get('content-type'),
134
+ };
135
+ if (!response.ok) {
136
+ const debug = {
137
+ ...responseDebugBase,
138
+ responsePreview: responseText.slice(0, 1000),
139
+ };
140
+ console.warn('[database-vector:embed] failed response', debug);
141
+ throw new DatabaseVectorError(`Embedding request failed with status ${response.status}`, debug);
142
+ }
143
+ let data;
144
+ try {
145
+ data = JSON.parse(responseText);
146
+ }
147
+ catch {
148
+ const debug = {
149
+ ...responseDebugBase,
150
+ stage: 'embedding_parse_json',
151
+ responsePreview: responseText.slice(0, 1000),
152
+ };
153
+ console.warn('[database-vector:embed] invalid json', debug);
154
+ throw new DatabaseVectorError('Embedding response is not valid JSON.', debug);
155
+ }
156
+ const responseData = isRecord(data) && Array.isArray(data.data) ? data.data : undefined;
157
+ const embeddings = responseData
158
+ ?.map((item) => isRecord(item) ? item.embedding : undefined)
159
+ .filter((item) => Array.isArray(item) && item.every((value) => typeof value === 'number'));
160
+ const debug = {
161
+ ...responseDebugBase,
162
+ responseDataCount: responseData?.length,
163
+ validEmbeddingCount: embeddings?.length ?? 0,
164
+ embeddingDimensions: embeddings?.map((embedding) => embedding.length).slice(0, 10),
165
+ responseKeys: isRecord(data) ? Object.keys(data) : undefined,
166
+ responsePreview: previewEmbeddingResponse(data),
167
+ };
168
+ console.info('[database-vector:embed] parsed response', debug);
169
+ if (!embeddings || embeddings.length !== input.length) {
170
+ throw new DatabaseVectorError(`Embedding response does not match input length. expected=${input.length}, data=${responseData?.length ?? 0}, validEmbeddings=${embeddings?.length ?? 0}`, debug);
171
+ }
172
+ return embeddings;
173
+ }
174
+ function isRecord(value) {
175
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value));
176
+ }
177
+ function previewEmbeddingResponse(value) {
178
+ if (!isRecord(value))
179
+ return value;
180
+ const data = Array.isArray(value.data)
181
+ ? value.data.slice(0, 3).map((item) => {
182
+ if (!isRecord(item))
183
+ return item;
184
+ const embedding = Array.isArray(item.embedding) ? item.embedding : undefined;
185
+ return {
186
+ ...item,
187
+ embedding: embedding ? `[number[${embedding.length}]]` : item.embedding,
188
+ };
189
+ })
190
+ : value.data;
191
+ return {
192
+ ...value,
193
+ data,
194
+ };
195
+ }
196
+ function getEmbeddingsUrl(apiBase) {
197
+ const base = apiBase.replace(/\/+$/, '');
198
+ if (base.endsWith('/embeddings'))
199
+ return base;
200
+ return `${base}/embeddings`;
201
+ }
202
+ function normalizeIndexText(text) {
203
+ return text.replace(/\s+/g, ' ').trim().slice(0, MAX_INDEX_TEXT_LENGTH);
204
+ }
205
+ function stripHtml(content) {
206
+ return content
207
+ .replace(/<style[\s\S]*?<\/style>/gi, ' ')
208
+ .replace(/<script[\s\S]*?<\/script>/gi, ' ')
209
+ .replace(/<[^>]+>/g, ' ');
210
+ }
211
+ function hashText(text) {
212
+ return createHash('sha256').update(text).digest('hex');
213
+ }
214
+ function cosineSimilarity(a, b) {
215
+ if (a.length !== b.length || a.length === 0)
216
+ return 0;
217
+ let dot = 0;
218
+ let ma = 0;
219
+ let mb = 0;
220
+ for (let index = 0; index < a.length; index++) {
221
+ dot += a[index] * b[index];
222
+ ma += a[index] * a[index];
223
+ mb += b[index] * b[index];
224
+ }
225
+ if (!ma || !mb)
226
+ return 0;
227
+ return dot / (Math.sqrt(ma) * Math.sqrt(mb));
228
+ }
229
+ function buildDatabaseNodePath(node, nodes) {
230
+ const byId = new Map(nodes.map((item) => [item.id, item]));
231
+ const parts = [node.title || node.id];
232
+ let parentId = node.parentId;
233
+ let guard = 0;
234
+ while (parentId && guard < 100) {
235
+ const parent = byId.get(parentId);
236
+ if (!parent)
237
+ break;
238
+ parts.unshift(parent.title || parent.id);
239
+ parentId = parent.parentId;
240
+ guard++;
241
+ }
242
+ return `/${parts.join('/')}`;
243
+ }
244
+ //# sourceMappingURL=database-vector.js.map
@@ -0,0 +1,40 @@
1
+ const MAX_ENTRIES = 1000;
2
+ const store = new Map();
3
+ function getList(workspaceId) {
4
+ let list = store.get(workspaceId);
5
+ if (!list) {
6
+ list = [];
7
+ store.set(workspaceId, list);
8
+ }
9
+ return list;
10
+ }
11
+ let counter = 0;
12
+ export function logGitOperation(workspaceId, operation, input, result, error, duration = 0) {
13
+ const list = getList(workspaceId);
14
+ const entry = {
15
+ id: `${Date.now()}-${++counter}`,
16
+ operation,
17
+ input,
18
+ output: truncateOutput(result),
19
+ error,
20
+ timestamp: new Date().toISOString(),
21
+ duration,
22
+ };
23
+ list.unshift(entry);
24
+ if (list.length > MAX_ENTRIES)
25
+ list.length = MAX_ENTRIES;
26
+ }
27
+ export function getGitOperations(workspaceId) {
28
+ return getList(workspaceId);
29
+ }
30
+ function truncateOutput(value) {
31
+ if (value === undefined || value === null)
32
+ return value;
33
+ if (typeof value === 'string')
34
+ return value.length > 5000 ? value.slice(0, 5000) + '...(truncated)' : value;
35
+ const s = JSON.stringify(value);
36
+ if (s && s.length > 5000)
37
+ return JSON.parse(s.slice(0, 5000) + '...(truncated)');
38
+ return value;
39
+ }
40
+ //# sourceMappingURL=git-operation-log.js.map
@@ -0,0 +1,72 @@
1
+ import { WECHAT_BASE_URL, WECHAT_BOT_TYPE, WECHAT_QR_STATUS_TIMEOUT_MS, } from './notification-hub/types.js';
2
+ import { createAccount } from './robot-account.js';
3
+ const globalSessions = new Map();
4
+ export async function getGlobalWeChatQRCode() {
5
+ // cleanup old sessions
6
+ const now = Date.now();
7
+ for (const [key, s] of globalSessions) {
8
+ if (now - s.createdAt > 5 * 60_000)
9
+ globalSessions.delete(key);
10
+ }
11
+ const res = await fetch(`${WECHAT_BASE_URL}/ilink/bot/get_bot_qrcode?bot_type=${WECHAT_BOT_TYPE}`);
12
+ if (!res.ok)
13
+ throw new Error(`Failed to get WeChat QR code: ${res.status}`);
14
+ const qr = await res.json();
15
+ const sessionId = `global-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
16
+ globalSessions.set(sessionId, {
17
+ qrcode: qr.qrcode,
18
+ qrcodeImgContent: qr.qrcode_img_content,
19
+ createdAt: now,
20
+ });
21
+ return { status: 'wait', qrcodeImgContent: qr.qrcode_img_content, sessionId };
22
+ }
23
+ export async function pollGlobalWeChatQRCode(sessionId) {
24
+ if (!sessionId)
25
+ throw new Error('sessionId is required');
26
+ const session = globalSessions.get(sessionId);
27
+ if (!session)
28
+ throw new Error('Session not found or expired');
29
+ const status = await fetchQRStatus(session.qrcode);
30
+ if (status.status === 'confirmed') {
31
+ if (!status.bot_token || !status.ilink_bot_id) {
32
+ throw new Error('WeChat login confirmed but token or bot id is missing');
33
+ }
34
+ globalSessions.delete(sessionId);
35
+ const account = createAccount({
36
+ name: `微信 ${status.ilink_bot_id}`,
37
+ type: 'wechat',
38
+ wechat: {
39
+ token: status.bot_token,
40
+ baseUrl: status.baseurl || WECHAT_BASE_URL,
41
+ accountId: status.ilink_bot_id,
42
+ userId: status.ilink_user_id,
43
+ },
44
+ });
45
+ return { status: 'confirmed', account };
46
+ }
47
+ if (status.status === 'expired') {
48
+ globalSessions.delete(sessionId);
49
+ }
50
+ return { status: status.status, qrcodeImgContent: session.qrcodeImgContent, sessionId };
51
+ }
52
+ async function fetchQRStatus(qrcode) {
53
+ const controller = new AbortController();
54
+ const timer = setTimeout(() => controller.abort(), WECHAT_QR_STATUS_TIMEOUT_MS);
55
+ try {
56
+ const res = await fetch(`${WECHAT_BASE_URL}/ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`, {
57
+ headers: { 'iLink-App-ClientVersion': '1' },
58
+ signal: controller.signal,
59
+ });
60
+ clearTimeout(timer);
61
+ if (!res.ok)
62
+ throw new Error(`Failed to poll QR status: ${res.status}`);
63
+ return await res.json();
64
+ }
65
+ catch (err) {
66
+ clearTimeout(timer);
67
+ if (err instanceof Error && err.name === 'AbortError')
68
+ return { status: 'wait' };
69
+ throw err;
70
+ }
71
+ }
72
+ //# sourceMappingURL=global-wechat-qr.js.map
@@ -1,5 +1,12 @@
1
1
  import { exec } from 'node:child_process';
2
2
  import { listHooks } from '../storage/hook-store.js';
3
+ function logDebug(message, details) {
4
+ if (details) {
5
+ console.debug(`[HookEngine] ${message}`, details);
6
+ return;
7
+ }
8
+ console.debug(`[HookEngine] ${message}`);
9
+ }
3
10
  function matchToolName(matcher, toolName) {
4
11
  if (matcher === '*')
5
12
  return true;
@@ -8,7 +15,12 @@ function matchToolName(matcher, toolName) {
8
15
  const regex = new RegExp(matcher.slice(1, -1));
9
16
  return regex.test(toolName);
10
17
  }
11
- catch {
18
+ catch (error) {
19
+ console.warn(`[HookEngine] invalid matcher regex, falling back to exact match`, {
20
+ matcher,
21
+ toolName,
22
+ error: error.message,
23
+ });
12
24
  return matcher === toolName;
13
25
  }
14
26
  }
@@ -16,7 +28,8 @@ function matchToolName(matcher, toolName) {
16
28
  }
17
29
  function executeCommand(command, env, timeout) {
18
30
  return new Promise((resolve) => {
19
- exec(command, { env: { ...process.env, ...env }, timeout: Math.min(timeout, 30000) }, (error) => {
31
+ const cappedTimeout = Math.min(timeout, 30000);
32
+ exec(command, { env: { ...process.env, ...env }, timeout: cappedTimeout }, (error) => {
20
33
  if (error)
21
34
  console.warn(`[HookEngine] command error: ${error.message}`);
22
35
  resolve();
@@ -26,43 +39,101 @@ function executeCommand(command, env, timeout) {
26
39
  async function executeWebhook(url, body, timeout) {
27
40
  try {
28
41
  const controller = new AbortController();
29
- const timer = setTimeout(() => controller.abort(), Math.min(timeout, 30000));
30
- await fetch(url, {
42
+ const cappedTimeout = Math.min(timeout, 30000);
43
+ const timer = setTimeout(() => controller.abort(), cappedTimeout);
44
+ const response = await fetch(url, {
31
45
  method: 'POST',
32
46
  headers: { 'Content-Type': 'application/json' },
33
47
  body: JSON.stringify(body),
34
48
  signal: controller.signal,
35
49
  });
36
50
  clearTimeout(timer);
51
+ if (!response.ok) {
52
+ console.warn(`[HookEngine] webhook non-2xx response`, {
53
+ url,
54
+ status: response.status,
55
+ statusText: response.statusText,
56
+ });
57
+ }
37
58
  }
38
59
  catch (error) {
39
60
  console.warn(`[HookEngine] webhook error: ${error.message}`);
40
61
  }
41
62
  }
42
- async function executeRule(rule, phase, toolName, workspaceId, context) {
63
+ async function executeRule(rule, phase, matcherValue, workspaceId, context, hookName) {
43
64
  const timeout = rule.timeout ?? 10000;
65
+ const startedAt = Date.now();
66
+ logDebug('rule start', {
67
+ workspaceId,
68
+ phase,
69
+ hookName,
70
+ matcherValue,
71
+ matcher: rule.matcher,
72
+ type: rule.type,
73
+ timeout,
74
+ });
44
75
  if (rule.type === 'command' && rule.command) {
45
76
  await executeCommand(rule.command, {
46
- HOOK_TOOL_NAME: toolName,
77
+ HOOK_NAME: hookName ?? '',
78
+ HOOK_RULE_MATCHER: rule.matcher,
79
+ HOOK_RULE_TYPE: rule.type,
80
+ HOOK_RULE_TIMEOUT: String(timeout),
81
+ HOOK_EVENT_NAME: context.eventName ?? phase,
82
+ HOOK_EVENT_PAYLOAD: JSON.stringify(context.eventPayload ?? {}),
83
+ HOOK_MATCHER_VALUE: matcherValue,
84
+ HOOK_TOOL_NAME: matcherValue,
85
+ HOOK_TOOL_USE_ID: context.toolUseId ?? '',
47
86
  HOOK_TOOL_INPUT: JSON.stringify(context.toolInput ?? {}),
48
87
  HOOK_TOOL_RESULT: JSON.stringify(context.toolResult ?? ''),
49
88
  HOOK_WORKSPACE_ID: workspaceId,
50
89
  HOOK_PHASE: phase,
90
+ HOOK_TRIGGER_CHECKED_RULES: String(context.checkedRules ?? ''),
91
+ HOOK_TRIGGER_MATCHED_RULES: String(context.matchedRules ?? ''),
92
+ HOOK_TRIGGERED_AT: new Date().toISOString(),
51
93
  }, timeout);
52
94
  }
53
95
  else if (rule.type === 'webhook' && rule.url) {
54
96
  await executeWebhook(rule.url, {
55
97
  event: phase,
56
- toolName,
98
+ toolName: matcherValue,
99
+ matcherValue,
57
100
  toolInput: context.toolInput,
58
101
  toolResult: context.toolResult ?? undefined,
102
+ payload: context.eventPayload,
59
103
  timestamp: new Date().toISOString(),
60
104
  workspaceId,
61
105
  }, timeout);
62
106
  }
63
107
  else if (rule.type === 'script') {
64
- console.warn(`[HookEngine] script type not implemented, skipping rule in ${phase}`);
108
+ console.warn(`[HookEngine] script type not implemented, skipping rule`, {
109
+ workspaceId,
110
+ phase,
111
+ hookName,
112
+ matcherValue,
113
+ matcher: rule.matcher,
114
+ });
65
115
  }
116
+ else {
117
+ console.warn(`[HookEngine] invalid rule configuration, skipping rule`, {
118
+ workspaceId,
119
+ phase,
120
+ hookName,
121
+ matcherValue,
122
+ matcher: rule.matcher,
123
+ type: rule.type,
124
+ hasCommand: Boolean(rule.command),
125
+ hasUrl: Boolean(rule.url),
126
+ });
127
+ }
128
+ logDebug('rule finished', {
129
+ workspaceId,
130
+ phase,
131
+ hookName,
132
+ matcherValue,
133
+ matcher: rule.matcher,
134
+ type: rule.type,
135
+ durationMs: Date.now() - startedAt,
136
+ });
66
137
  }
67
138
  export class HookEngine {
68
139
  hooks = [];
@@ -72,6 +143,12 @@ export class HookEngine {
72
143
  }
73
144
  load() {
74
145
  this.hooks = listHooks(this.workspaceId);
146
+ logDebug('loaded hooks', {
147
+ workspaceId: this.workspaceId,
148
+ totalHooks: this.hooks.length,
149
+ enabledHooks: this.hooks.filter(h => h.enabled).length,
150
+ hookNames: this.hooks.map(h => h.name),
151
+ });
75
152
  }
76
153
  reload() {
77
154
  this.load();
@@ -79,40 +156,121 @@ export class HookEngine {
79
156
  getHooks() {
80
157
  return this.hooks;
81
158
  }
82
- async executeHooks(phase, toolName, context) {
159
+ async executeHooks(phase, matcherValue, context) {
83
160
  const enabledHooks = this.hooks.filter(h => h.enabled);
84
161
  const promises = [];
162
+ const matchedRuleEntries = [];
163
+ let checkedRules = 0;
164
+ let matchedRules = 0;
165
+ logDebug('trigger received', {
166
+ workspaceId: this.workspaceId,
167
+ phase,
168
+ matcherValue,
169
+ totalHooks: this.hooks.length,
170
+ enabledHooks: enabledHooks.length,
171
+ hasToolInput: context.toolInput !== undefined,
172
+ hasToolResult: context.toolResult !== undefined,
173
+ });
85
174
  for (const hook of enabledHooks) {
86
175
  const rules = hook.hooks[phase];
87
176
  if (!rules)
88
177
  continue;
89
178
  for (const rule of rules) {
90
- if (matchToolName(rule.matcher, toolName)) {
91
- promises.push(executeRule(rule, phase, toolName, this.workspaceId, context));
179
+ checkedRules += 1;
180
+ if (matchToolName(rule.matcher, matcherValue)) {
181
+ matchedRules += 1;
182
+ logDebug('rule matched', {
183
+ workspaceId: this.workspaceId,
184
+ phase,
185
+ hookName: hook.name,
186
+ matcherValue,
187
+ matcher: rule.matcher,
188
+ type: rule.type,
189
+ });
190
+ matchedRuleEntries.push({ hookName: hook.name, rule });
92
191
  }
93
192
  }
94
193
  }
95
- await Promise.allSettled(promises);
194
+ for (const { hookName, rule } of matchedRuleEntries) {
195
+ promises.push(executeRule(rule, phase, matcherValue, this.workspaceId, {
196
+ ...context,
197
+ checkedRules,
198
+ matchedRules,
199
+ }, hookName));
200
+ }
201
+ const results = await Promise.allSettled(promises);
202
+ const rejectedRules = results.filter(result => result.status === 'rejected').length;
203
+ logDebug('trigger finished', {
204
+ workspaceId: this.workspaceId,
205
+ phase,
206
+ matcherValue,
207
+ checkedRules,
208
+ matchedRules,
209
+ rejectedRules,
210
+ });
96
211
  }
97
212
  }
98
213
  export function wrapOnEventWithHooks(onEvent, workspaceId, hooksEnabled) {
99
- if (!hooksEnabled)
214
+ if (!hooksEnabled) {
215
+ logDebug('hooks disabled for workspace', { workspaceId });
100
216
  return onEvent;
217
+ }
101
218
  const engine = new HookEngine(workspaceId);
102
219
  engine.load();
103
220
  const toolNameById = new Map();
221
+ let lastToolUse = null;
104
222
  return (event) => {
105
- onEvent(event);
223
+ if (event.type !== 'hook_event')
224
+ onEvent(event);
106
225
  if (event.type === 'tool_use') {
107
226
  toolNameById.set(event.id, event.name);
108
- engine.executeHooks('PreToolUse', event.name, { toolInput: event.input });
227
+ lastToolUse = { id: event.id, name: event.name };
228
+ logDebug('tool_use event mapped', {
229
+ workspaceId,
230
+ toolUseId: event.id,
231
+ toolName: event.name,
232
+ });
233
+ engine.executeHooks('PreToolUse', event.name, { toolInput: event.input, toolUseId: event.id });
109
234
  }
110
235
  if (event.type === 'tool_result') {
111
- const toolName = event.toolUseId ? (toolNameById.get(event.toolUseId) ?? '') : '';
236
+ const resolvedToolUseId = event.toolUseId || lastToolUse?.id;
237
+ const toolName = resolvedToolUseId ? (toolNameById.get(resolvedToolUseId) ?? '') : '';
112
238
  if (toolName) {
113
- engine.executeHooks('PostToolUse', toolName, { toolResult: event.result });
239
+ logDebug('tool_result event resolved', {
240
+ workspaceId,
241
+ toolUseId: resolvedToolUseId,
242
+ originalToolUseId: event.toolUseId,
243
+ toolName,
244
+ });
245
+ engine.executeHooks('PostToolUse', toolName, { toolResult: event.result, toolUseId: resolvedToolUseId });
246
+ if (isToolFailureResult(event.result)) {
247
+ engine.executeHooks('PostToolUseFailure', toolName, { toolResult: event.result, toolUseId: resolvedToolUseId });
248
+ }
249
+ }
250
+ else {
251
+ logDebug('tool_result event skipped without matching tool_use', {
252
+ workspaceId,
253
+ toolUseId: event.toolUseId,
254
+ });
114
255
  }
115
256
  }
257
+ if (event.type === 'hook_event') {
258
+ logDebug('hook_event received', {
259
+ workspaceId,
260
+ event: event.event,
261
+ matcher: event.matcher ?? '*',
262
+ });
263
+ engine.executeHooks(event.event, event.matcher ?? '*', {
264
+ eventName: event.event,
265
+ eventPayload: event.payload,
266
+ });
267
+ }
116
268
  };
117
269
  }
270
+ function isToolFailureResult(result) {
271
+ if (!result || typeof result !== 'object')
272
+ return false;
273
+ const record = result;
274
+ return record.error !== undefined || record.is_error === true || record.success === false;
275
+ }
118
276
  //# sourceMappingURL=hook-engine.js.map
@@ -0,0 +1,50 @@
1
+ import * as store from '../storage/kanban-store.js';
2
+ export function getBoard(workspaceId) {
3
+ return store.getBoard(workspaceId);
4
+ }
5
+ export function ensureBoard(workspaceId) {
6
+ let board = store.getBoard(workspaceId);
7
+ if (!board) {
8
+ board = store.createBoard(workspaceId);
9
+ const defaultColumns = [
10
+ { id: 'todo', title: 'To Do', color: 'sky', order: 0 },
11
+ { id: 'progress', title: 'In Progress', color: 'amber', order: 1 },
12
+ { id: 'done', title: 'Done', color: 'emerald', order: 2 },
13
+ { id: 'archive', title: 'Archive', color: 'slate', order: 3 },
14
+ ];
15
+ store.saveColumns(board.id, defaultColumns);
16
+ board = store.getBoard(workspaceId);
17
+ }
18
+ return board;
19
+ }
20
+ export function updateBoard(workspaceId, updates) {
21
+ return store.updateBoard(workspaceId, updates);
22
+ }
23
+ export function saveColumns(workspaceId, columns) {
24
+ const board = store.getBoard(workspaceId);
25
+ if (!board)
26
+ return null;
27
+ store.saveColumns(board.id, columns);
28
+ return store.getBoard(workspaceId);
29
+ }
30
+ export function saveTasks(workspaceId, tasks) {
31
+ const board = store.getBoard(workspaceId);
32
+ if (!board)
33
+ return null;
34
+ store.saveTasks(board.id, tasks);
35
+ return store.getBoard(workspaceId);
36
+ }
37
+ export function saveBoard(workspaceId, data) {
38
+ let board = store.getBoard(workspaceId);
39
+ if (!board)
40
+ board = store.createBoard(workspaceId);
41
+ if (data.title || data.layoutMode) {
42
+ store.updateBoard(workspaceId, { title: data.title, layoutMode: data.layoutMode });
43
+ }
44
+ if (data.columns)
45
+ store.saveColumns(board.id, data.columns);
46
+ if (data.tasks)
47
+ store.saveTasks(board.id, data.tasks);
48
+ return store.getBoard(workspaceId);
49
+ }
50
+ //# sourceMappingURL=kanban.js.map