@agent-spaces/server 0.3.62 → 0.3.64

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 (367) hide show
  1. package/dist/adapters/agent-runtime-types.js +12 -0
  2. package/dist/adapters/claude-code-runtime/index.js +3 -0
  3. package/dist/adapters/claude-code-runtime/message-format.js +1 -1
  4. package/dist/adapters/codex-runtime.js +2 -2
  5. package/dist/adapters/git.js +161 -57
  6. package/dist/adapters/langchain-runtime.js +2 -2
  7. package/dist/adapters/open-agent-sdk-runtime.js +2 -2
  8. package/dist/agents/agent-designer.js +66 -12
  9. package/dist/agents/commit-agent.js +1 -0
  10. package/dist/agents/issue-agent-progress.js +4 -2
  11. package/dist/agents/issue-agent-runner.js +5 -5
  12. package/dist/agents/issue-task-controller.js +96 -15
  13. package/dist/app.js +123 -5
  14. package/dist/package.json +1 -1
  15. package/dist/routes/agent-commands.js +72 -0
  16. package/dist/routes/agent-sse.js +10 -2
  17. package/dist/routes/agent.js +15 -1
  18. package/dist/routes/database.js +345 -0
  19. package/dist/routes/git.js +52 -1
  20. package/dist/routes/hooks.js +88 -0
  21. package/dist/routes/issue.js +59 -1
  22. package/dist/routes/kanban.js +39 -0
  23. package/dist/routes/output-style.js +48 -0
  24. package/dist/routes/prompt-template.js +2 -2
  25. package/dist/routes/skill.js +86 -15
  26. package/dist/routes/task.js +13 -1
  27. package/dist/services/agent-commands.js +168 -0
  28. package/dist/services/builtin-tools/command-tools.js +117 -0
  29. package/dist/services/builtin-tools/database-tools.js +578 -0
  30. package/dist/services/builtin-tools/index.js +5 -0
  31. package/dist/services/builtin-tools/input-helpers.js +26 -0
  32. package/dist/services/builtin-tools/issue-tools.js +209 -0
  33. package/dist/services/builtin-tools/kanban-tools.js +277 -0
  34. package/dist/services/database-vector.js +244 -0
  35. package/dist/services/hook-engine.js +118 -0
  36. package/dist/services/issue.js +6 -0
  37. package/dist/services/kanban.js +50 -0
  38. package/dist/services/notification-hub/bot-agent.js +1 -0
  39. package/dist/services/output-style.js +134 -0
  40. package/dist/services/prompt-template.js +2 -2
  41. package/dist/services/skill.js +148 -35
  42. package/dist/storage/database-store.js +365 -0
  43. package/dist/storage/hook-store.js +55 -0
  44. package/dist/storage/kanban-store.js +142 -0
  45. package/dist/web/404.html +1 -1
  46. package/dist/web/__next.__PAGE__.txt +4 -4
  47. package/dist/web/__next._full.txt +26 -30
  48. package/dist/web/__next._head.txt +4 -4
  49. package/dist/web/__next._index.txt +14 -14
  50. package/dist/web/__next._tree.txt +3 -8
  51. package/dist/web/_next/static/chunks/0-9194nbxy_6d.js +1 -0
  52. package/dist/web/_next/static/chunks/0-f~0xmwl__u5.js +1 -0
  53. package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +1 -0
  54. package/dist/web/_next/static/chunks/002_j970b9gdx.js +1 -0
  55. package/dist/web/_next/static/chunks/01iqv28_snwus.js +1 -0
  56. package/dist/web/_next/static/chunks/01~quun6sefgl.js +1 -0
  57. package/dist/web/_next/static/chunks/02mf61htij8g0.js +31 -0
  58. package/dist/web/_next/static/chunks/03scq1-0ykve3.js +1 -0
  59. package/dist/web/_next/static/chunks/04a4vsq2wknm4.js +1 -0
  60. package/dist/web/_next/static/chunks/04dg4l4hv11q2.js +3 -0
  61. package/dist/web/_next/static/chunks/04fxddw-y20~-.js +7 -0
  62. package/dist/web/_next/static/chunks/04w7~5ooz_pwm.js +1 -0
  63. package/dist/web/_next/static/chunks/05oc21sj24wtq.js +1 -0
  64. package/dist/web/_next/static/chunks/{0zd1o3u04~qvo.js → 05psi2gtx~bev.js} +7 -7
  65. package/dist/web/_next/static/chunks/{0-oog4zg4_m~m.css → 062f9zqctzg.b.css} +0 -3
  66. package/dist/web/_next/static/chunks/{12odetnu-lyrr.js → 06whz1~s_7pva.js} +12 -12
  67. package/dist/web/_next/static/chunks/08ckpwmmwlors.js +3 -0
  68. package/dist/web/_next/static/chunks/08k~meqbd8d6v.js +1 -0
  69. package/dist/web/_next/static/chunks/099h96wjsdb25.js +2 -0
  70. package/dist/web/_next/static/chunks/09h23logvq65m.js +1 -0
  71. package/dist/web/_next/static/chunks/{0njy89g5coeyi.js → 0_8dm7bxp18xo.js} +6 -6
  72. package/dist/web/_next/static/chunks/0_mvduwjsm35w.js +1 -0
  73. package/dist/web/_next/static/chunks/0_vi1a~g4wx46.js +3 -0
  74. package/dist/web/_next/static/chunks/0a5y-vhf4i5id.js +3 -0
  75. package/dist/web/_next/static/chunks/0ake2f3x2uan4.js +24 -0
  76. package/dist/web/_next/static/chunks/{0tvd~rxgf0oh_.js → 0bbmx45w_h5np.js} +1 -1
  77. package/dist/web/_next/static/chunks/0ck8dw_9-1cdx.js +1 -0
  78. package/dist/web/_next/static/chunks/{07a0rktf_nr5h.js → 0ctg5qmw7uu.1.js} +2 -2
  79. package/dist/web/_next/static/chunks/0ewceguykiut5.js +1 -0
  80. package/dist/web/_next/static/chunks/0f7cb9li~3jra.js +67 -0
  81. package/dist/web/_next/static/chunks/0fttswpzu69qx.js +1 -0
  82. package/dist/web/_next/static/chunks/0ghs9on7wodrm.js +1 -0
  83. package/dist/web/_next/static/chunks/0ghx3j_.-gdyd.js +1 -0
  84. package/dist/web/_next/static/chunks/{0202ia13sijwb.js → 0h18ej5yf974e.js} +1 -1
  85. package/dist/web/_next/static/chunks/0h9cu-k6z5o08.js +1 -0
  86. package/dist/web/_next/static/chunks/0i39jifmxla7q.js +1 -0
  87. package/dist/web/_next/static/chunks/0iuf30t0rjsjv.js +19 -0
  88. package/dist/web/_next/static/chunks/0jb4~3qqkw2ps.js +1 -0
  89. package/dist/web/_next/static/chunks/0k4zdm72k_bfy.js +1 -0
  90. package/dist/web/_next/static/chunks/{08o-zmr-40r5g.js → 0m11vvph7q94-.js} +1 -1
  91. package/dist/web/_next/static/chunks/0n6_4so_afuwk.js +71 -0
  92. package/dist/web/_next/static/chunks/0nb8.iteznuvx.js +1 -0
  93. package/dist/web/_next/static/chunks/0np.d~hc1-pmh.js +4 -0
  94. package/dist/web/_next/static/chunks/{0qpq0~_58fe9a.js → 0oaq67r7ix.vg.js} +1 -1
  95. package/dist/web/_next/static/chunks/{0d_dp_4ofz0l3.css → 0ojcao3hdm36s.css} +0 -1
  96. package/dist/web/_next/static/chunks/0os58q93stt7j.js +3 -0
  97. package/dist/web/_next/static/chunks/{0gig.k.rq8d0x.js → 0ppr271hz0xoq.js} +1 -1
  98. package/dist/web/_next/static/chunks/0s9lmk8iauou3.js +1 -0
  99. package/dist/web/_next/static/chunks/0sp_zbx~w0am7.js +1 -0
  100. package/dist/web/_next/static/chunks/0tel~zsv4z8l_.js +1 -0
  101. package/dist/web/_next/static/chunks/0twamv4wr_dbv.js +1 -0
  102. package/dist/web/_next/static/chunks/0uhol5wafdbl~.js +1 -0
  103. package/dist/web/_next/static/chunks/0v3a_x4vt42kx.js +5 -0
  104. package/dist/web/_next/static/chunks/{002-dxhags4dj.js → 0v6hte2z-32ca.js} +2 -2
  105. package/dist/web/_next/static/chunks/0v7q4mys.mnm..css +1 -0
  106. package/dist/web/_next/static/chunks/0vbqaynjq8ga..js +3 -0
  107. package/dist/web/_next/static/chunks/0xbaakj0dfc0..js +1 -0
  108. package/dist/web/_next/static/chunks/{0..g0jl-8qup7.js → 0xoo17yef_b8g.js} +1 -1
  109. package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +1 -0
  110. package/dist/web/_next/static/chunks/0za1r07-6az6w.js +1 -0
  111. package/dist/web/_next/static/chunks/0z~vqzbm_q371.js +1 -0
  112. package/dist/web/_next/static/chunks/0~3xm80~j9ddg.js +1 -0
  113. package/dist/web/_next/static/chunks/0~u.5r3-t7179.js +1 -0
  114. package/dist/web/_next/static/chunks/10l-9myrdo3x9.js +1 -0
  115. package/dist/web/_next/static/chunks/11-czmcci_55y.js +1 -0
  116. package/dist/web/_next/static/chunks/11k-.49r~1mfm.js +1 -0
  117. package/dist/web/_next/static/chunks/{0k.8qdk7oi_os.js → 128ugqd34tr_-.js} +1 -1
  118. package/dist/web/_next/static/chunks/12jm4gwmvq-0q.js +90 -0
  119. package/dist/web/_next/static/chunks/{0rke_patcovgr.js → 1442stwa0gbxe.js} +1 -1
  120. package/dist/web/_next/static/chunks/{0jokpgh485~28.js → 14hqmid8q4apf.js} +11 -11
  121. package/dist/web/_next/static/chunks/14s37n6h0_q3x.js +16 -0
  122. package/dist/web/_next/static/chunks/161ik5kfyuwtd.js +1 -0
  123. package/dist/web/_next/static/chunks/16sg-lflc8csx.js +1 -0
  124. package/dist/web/_next/static/chunks/17k~zbv0_4rep.js +1 -0
  125. package/dist/web/_next/static/chunks/17oc2l.ekcs8b.css +1 -0
  126. package/dist/web/_next/static/chunks/{turbopack-0lrdxynxb9-1t.js → turbopack-0ndm2zc_pdptk.js} +1 -1
  127. package/dist/web/_not-found/__next._full.txt +30 -31
  128. package/dist/web/_not-found/__next._head.txt +4 -4
  129. package/dist/web/_not-found/__next._index.txt +14 -14
  130. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
  131. package/dist/web/_not-found/__next._not-found.txt +3 -3
  132. package/dist/web/_not-found/__next._tree.txt +3 -3
  133. package/dist/web/_not-found.html +1 -1
  134. package/dist/web/_not-found.txt +30 -31
  135. package/dist/web/index.html +1 -1
  136. package/dist/web/index.txt +26 -30
  137. package/dist/web/login/__next._full.txt +32 -36
  138. package/dist/web/login/__next._head.txt +4 -4
  139. package/dist/web/login/__next._index.txt +14 -14
  140. package/dist/web/login/__next._tree.txt +3 -8
  141. package/dist/web/login/__next.login.__PAGE__.txt +4 -4
  142. package/dist/web/login/__next.login.txt +3 -3
  143. package/dist/web/login.html +1 -1
  144. package/dist/web/login.txt +32 -36
  145. package/dist/web/settings/__next._full.txt +29 -34
  146. package/dist/web/settings/__next._head.txt +4 -4
  147. package/dist/web/settings/__next._index.txt +14 -14
  148. package/dist/web/settings/__next._tree.txt +3 -8
  149. package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
  150. package/dist/web/settings/__next.settings.txt +5 -5
  151. package/dist/web/settings/agents/__next._full.txt +27 -32
  152. package/dist/web/settings/agents/__next._head.txt +4 -4
  153. package/dist/web/settings/agents/__next._index.txt +14 -14
  154. package/dist/web/settings/agents/__next._tree.txt +3 -8
  155. package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
  156. package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
  157. package/dist/web/settings/agents/__next.settings.txt +5 -5
  158. package/dist/web/settings/agents.html +1 -1
  159. package/dist/web/settings/agents.txt +27 -32
  160. package/dist/web/settings/mcps/__next._full.txt +27 -32
  161. package/dist/web/settings/mcps/__next._head.txt +4 -4
  162. package/dist/web/settings/mcps/__next._index.txt +14 -14
  163. package/dist/web/settings/mcps/__next._tree.txt +3 -8
  164. package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
  165. package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
  166. package/dist/web/settings/mcps/__next.settings.txt +5 -5
  167. package/dist/web/settings/mcps.html +1 -1
  168. package/dist/web/settings/mcps.txt +27 -32
  169. package/dist/web/settings/models/__next._full.txt +27 -32
  170. package/dist/web/settings/models/__next._head.txt +4 -4
  171. package/dist/web/settings/models/__next._index.txt +14 -14
  172. package/dist/web/settings/models/__next._tree.txt +3 -8
  173. package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
  174. package/dist/web/settings/models/__next.settings.models.txt +3 -3
  175. package/dist/web/settings/models/__next.settings.txt +5 -5
  176. package/dist/web/settings/models.html +1 -1
  177. package/dist/web/settings/models.txt +27 -32
  178. package/dist/web/settings/output-styles/__next._full.txt +38 -0
  179. package/dist/web/settings/output-styles/__next._head.txt +6 -0
  180. package/dist/web/settings/output-styles/__next._index.txt +15 -0
  181. package/dist/web/settings/output-styles/__next._tree.txt +3 -0
  182. package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +9 -0
  183. package/dist/web/settings/output-styles/__next.settings.output-styles.txt +5 -0
  184. package/dist/web/settings/output-styles/__next.settings.txt +7 -0
  185. package/dist/web/settings/output-styles.html +1 -0
  186. package/dist/web/settings/output-styles.txt +38 -0
  187. package/dist/web/settings/prompts/__next._full.txt +27 -32
  188. package/dist/web/settings/prompts/__next._head.txt +4 -4
  189. package/dist/web/settings/prompts/__next._index.txt +14 -14
  190. package/dist/web/settings/prompts/__next._tree.txt +3 -8
  191. package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +4 -4
  192. package/dist/web/settings/prompts/__next.settings.prompts.txt +3 -3
  193. package/dist/web/settings/prompts/__next.settings.txt +5 -5
  194. package/dist/web/settings/prompts.html +1 -1
  195. package/dist/web/settings/prompts.txt +27 -32
  196. package/dist/web/settings/providers/__next._full.txt +27 -32
  197. package/dist/web/settings/providers/__next._head.txt +4 -4
  198. package/dist/web/settings/providers/__next._index.txt +14 -14
  199. package/dist/web/settings/providers/__next._tree.txt +3 -8
  200. package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
  201. package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
  202. package/dist/web/settings/providers/__next.settings.txt +5 -5
  203. package/dist/web/settings/providers.html +1 -1
  204. package/dist/web/settings/providers.txt +27 -32
  205. package/dist/web/settings/skills/__next._full.txt +27 -32
  206. package/dist/web/settings/skills/__next._head.txt +4 -4
  207. package/dist/web/settings/skills/__next._index.txt +14 -14
  208. package/dist/web/settings/skills/__next._tree.txt +3 -8
  209. package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
  210. package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
  211. package/dist/web/settings/skills/__next.settings.txt +5 -5
  212. package/dist/web/settings/skills.html +1 -1
  213. package/dist/web/settings/skills.txt +27 -32
  214. package/dist/web/settings/tools/__next._full.txt +38 -0
  215. package/dist/web/settings/tools/__next._head.txt +6 -0
  216. package/dist/web/settings/tools/__next._index.txt +15 -0
  217. package/dist/web/settings/tools/__next._tree.txt +3 -0
  218. package/dist/web/settings/tools/__next.settings.tools.__PAGE__.txt +9 -0
  219. package/dist/web/settings/tools/__next.settings.tools.txt +5 -0
  220. package/dist/web/settings/tools/__next.settings.txt +7 -0
  221. package/dist/web/settings/tools.html +1 -0
  222. package/dist/web/settings/tools.txt +38 -0
  223. package/dist/web/settings.html +1 -1
  224. package/dist/web/settings.txt +29 -34
  225. package/dist/web/workflows/__next._full.txt +34 -37
  226. package/dist/web/workflows/__next._head.txt +4 -4
  227. package/dist/web/workflows/__next._index.txt +14 -14
  228. package/dist/web/workflows/__next._tree.txt +3 -8
  229. package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
  230. package/dist/web/workflows/__next.workflows.txt +3 -3
  231. package/dist/web/workflows.html +1 -1
  232. package/dist/web/workflows.txt +34 -37
  233. package/dist/web/workspace/_/__next._full.txt +32 -77
  234. package/dist/web/workspace/_/__next._head.txt +4 -4
  235. package/dist/web/workspace/_/__next._index.txt +14 -14
  236. package/dist/web/workspace/_/__next._tree.txt +4 -23
  237. package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -18
  238. package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
  239. package/dist/web/workspace/_/__next.workspace.txt +3 -3
  240. package/dist/web/workspace/_.html +1 -1
  241. package/dist/web/workspace/_.txt +32 -77
  242. package/dist/web/workspaces/__next._full.txt +32 -38
  243. package/dist/web/workspaces/__next._head.txt +4 -4
  244. package/dist/web/workspaces/__next._index.txt +14 -14
  245. package/dist/web/workspaces/__next._tree.txt +3 -8
  246. package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
  247. package/dist/web/workspaces/__next.workspaces.txt +3 -3
  248. package/dist/web/workspaces.html +1 -1
  249. package/dist/web/workspaces.txt +32 -38
  250. package/dist/ws/agent-prompt.js +45 -8
  251. package/dist/ws/agent-runner.js +10 -6
  252. package/package.json +11 -10
  253. package/public/output-styles/carmack-mode.md +381 -0
  254. package/public/output-styles/codex-rigor-mode.md +114 -0
  255. package/public/output-styles/dhh-mode.md +265 -0
  256. package/public/output-styles/evan-you-mode.md +539 -0
  257. package/public/output-styles/index.json +37 -0
  258. package/public/output-styles/jobs-mode.md +369 -0
  259. package/public/output-styles/linus-mode.md +135 -0
  260. package/public/output-styles/uncle-bob-mode.md +221 -0
  261. package/public/prompt/andrej-karpathy-skills.md +65 -0
  262. package/public/prompt/claude-token-efficient-coding.md +35 -0
  263. package/public/prompt/index.json +12 -0
  264. package/public/skills/index.json +92 -0
  265. package/public/skills/planning-with-files/planning-with-files-zh/SKILL.md +243 -0
  266. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.ps1 +44 -0
  267. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.sh +46 -0
  268. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.ps1 +124 -0
  269. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.sh +124 -0
  270. package/public/skills/planning-with-files/planning-with-files-zh/scripts/session-catchup.py +438 -0
  271. package/public/skills/planning-with-files/planning-with-files-zh/templates/findings.md +29 -0
  272. package/public/skills/planning-with-files/planning-with-files-zh/templates/progress.md +40 -0
  273. package/public/skills/planning-with-files/planning-with-files-zh/templates/task_plan.md +58 -0
  274. package/public/skills/superpowers/brainstorming/SKILL.md +164 -0
  275. package/public/skills/superpowers/brainstorming/scripts/frame-template.html +214 -0
  276. package/public/skills/superpowers/brainstorming/scripts/helper.js +88 -0
  277. package/public/skills/superpowers/brainstorming/scripts/server.cjs +354 -0
  278. package/public/skills/superpowers/brainstorming/scripts/start-server.sh +148 -0
  279. package/public/skills/superpowers/brainstorming/scripts/stop-server.sh +56 -0
  280. package/public/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
  281. package/public/skills/superpowers/brainstorming/visual-companion.md +287 -0
  282. package/public/skills/superpowers/dispatching-parallel-agents/SKILL.md +182 -0
  283. package/public/skills/superpowers/executing-plans/SKILL.md +70 -0
  284. package/public/skills/superpowers/finishing-a-development-branch/SKILL.md +251 -0
  285. package/public/skills/superpowers/receiving-code-review/SKILL.md +213 -0
  286. package/public/skills/superpowers/requesting-code-review/SKILL.md +103 -0
  287. package/public/skills/superpowers/requesting-code-review/code-reviewer.md +168 -0
  288. package/public/skills/superpowers/subagent-driven-development/SKILL.md +279 -0
  289. package/public/skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +25 -0
  290. package/public/skills/superpowers/subagent-driven-development/implementer-prompt.md +113 -0
  291. package/public/skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  292. package/public/skills/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
  293. package/public/skills/superpowers/systematic-debugging/SKILL.md +296 -0
  294. package/public/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
  295. package/public/skills/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
  296. package/public/skills/superpowers/systematic-debugging/defense-in-depth.md +122 -0
  297. package/public/skills/superpowers/systematic-debugging/find-polluter.sh +63 -0
  298. package/public/skills/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
  299. package/public/skills/superpowers/systematic-debugging/test-academic.md +14 -0
  300. package/public/skills/superpowers/systematic-debugging/test-pressure-1.md +58 -0
  301. package/public/skills/superpowers/systematic-debugging/test-pressure-2.md +68 -0
  302. package/public/skills/superpowers/systematic-debugging/test-pressure-3.md +69 -0
  303. package/public/skills/superpowers/test-driven-development/SKILL.md +371 -0
  304. package/public/skills/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
  305. package/public/skills/superpowers/using-git-worktrees/SKILL.md +215 -0
  306. package/public/skills/superpowers/using-superpowers/SKILL.md +117 -0
  307. package/public/skills/superpowers/using-superpowers/references/codex-tools.md +59 -0
  308. package/public/skills/superpowers/using-superpowers/references/copilot-tools.md +42 -0
  309. package/public/skills/superpowers/using-superpowers/references/gemini-tools.md +51 -0
  310. package/public/skills/superpowers/verification-before-completion/SKILL.md +139 -0
  311. package/public/skills/superpowers/writing-plans/SKILL.md +152 -0
  312. package/public/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
  313. package/public/skills/superpowers/writing-skills/SKILL.md +655 -0
  314. package/public/skills/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
  315. package/public/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  316. package/public/skills/superpowers/writing-skills/graphviz-conventions.dot +172 -0
  317. package/public/skills/superpowers/writing-skills/persuasion-principles.md +187 -0
  318. package/public/skills/superpowers/writing-skills/render-graphs.js +168 -0
  319. package/public/skills/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
  320. package/dist/web/_next/static/chunks/0-81wi7xr2nd-.js +0 -270
  321. package/dist/web/_next/static/chunks/00lca9lsasdm7.js +0 -1
  322. package/dist/web/_next/static/chunks/01gi~q0c6ez6..js +0 -1
  323. package/dist/web/_next/static/chunks/02shswpmybici.js +0 -1
  324. package/dist/web/_next/static/chunks/05tx6hzdtkgi9.js +0 -2
  325. package/dist/web/_next/static/chunks/07nbyndvzftr1.js +0 -3
  326. package/dist/web/_next/static/chunks/0bn~onkv~9xza.js +0 -1
  327. package/dist/web/_next/static/chunks/0g-0n6glz_z6w.js +0 -1
  328. package/dist/web/_next/static/chunks/0gyede80jpy3n.js +0 -4
  329. package/dist/web/_next/static/chunks/0hrbuvzuxrjfl.js +0 -1
  330. package/dist/web/_next/static/chunks/0i51q.5s_-.vh.css +0 -1
  331. package/dist/web/_next/static/chunks/0qf163pbrwy4z.js +0 -1
  332. package/dist/web/_next/static/chunks/0rnt-f3pjxb-d.js +0 -5
  333. package/dist/web/_next/static/chunks/0tgbcgsca9mrg.js +0 -1
  334. package/dist/web/_next/static/chunks/0tyhv6.y7~yxd.js +0 -1
  335. package/dist/web/_next/static/chunks/0u7_qd9hzqwac.js +0 -1
  336. package/dist/web/_next/static/chunks/0vuvql8rloda5.js +0 -1
  337. package/dist/web/_next/static/chunks/0wv0h27jafag4.js +0 -1
  338. package/dist/web/_next/static/chunks/0wwvc4zc2q6bn.js +0 -1
  339. package/dist/web/_next/static/chunks/0xmmk3vebw8xs.js +0 -1
  340. package/dist/web/_next/static/chunks/0xwqf.llmm_u2.js +0 -31
  341. package/dist/web/_next/static/chunks/0yo22_w53mo~5.js +0 -1
  342. package/dist/web/_next/static/chunks/12c0jp0qvlr1t.js +0 -1
  343. package/dist/web/_next/static/chunks/12pg1nn3v~~5k.js +0 -1
  344. package/dist/web/_next/static/chunks/16cyr8ilpx1nn.js +0 -1
  345. package/dist/web/_next/static/media/0a7740363b4d4863-s.1110aazvokzp..woff2 +0 -0
  346. package/dist/web/_next/static/media/0da9c7f357bd9d4d-s.0ek5sshv8wk3m.woff2 +0 -0
  347. package/dist/web/_next/static/media/1b99372b3eaef0c8-s.p.0gx2haw2tmll8.woff2 +0 -0
  348. package/dist/web/_next/static/media/41e95f694c5c4549-s.0r1jrq7neqdsq.woff2 +0 -0
  349. package/dist/web/_next/static/media/5c285b27cdda1fe8-s.p.0yo6-5yoeeudq.woff2 +0 -0
  350. package/dist/web/_next/static/media/5f9d24ebef5d5292-s.0esuu2f5si~v8.woff2 +0 -0
  351. package/dist/web/_next/static/media/6c55a692938ebbbc-s.0g6rbszwfgn9y.woff2 +0 -0
  352. package/dist/web/_next/static/media/8e6fa89aa22d24ec-s.p.0uvzar8hswo3p.woff2 +0 -0
  353. package/dist/web/_next/static/media/a218039a3287bcfd-s.p.17-1enzs_j91b.woff2 +0 -0
  354. package/dist/web/_next/static/media/b2ea385cb5ae8625-s.0kjod.kaq1k69.woff2 +0 -0
  355. package/dist/web/_next/static/media/bdc7e24a509eb931-s.0apt5mko2.qn3.woff2 +0 -0
  356. package/dist/web/_next/static/media/c3cb240f9c892514-s.163v2i5cux7-c.woff2 +0 -0
  357. package/dist/web/_next/static/media/e2334d715941921e-s.p.12skym0rqknxy.woff2 +0 -0
  358. package/public/avatars/1777813826407-bea0ja-minimax.svg +0 -1
  359. package/public/avatars/1777813967088-3xlvd0-minimax.svg +0 -1
  360. package/public/avatars/1777814041714-yp0qeq-minimax.svg +0 -1
  361. package/public/avatars/1777904986095-rg26je-icon.png +0 -0
  362. package/public/avatars/1778953228323-5je54x-user.jpg +0 -0
  363. package/public/avatars/1778954057880-g01q6y-user.jpg +0 -0
  364. /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → e8w3vd9Eov_LDYWj_0zsE}/_buildManifest.js +0 -0
  365. /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → e8w3vd9Eov_LDYWj_0zsE}/_clientMiddlewareManifest.js +0 -0
  366. /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → e8w3vd9Eov_LDYWj_0zsE}/_ssgManifest.js +0 -0
  367. /package/public/avatars/{1777815865622-08wp9m-user.jpg → user.jpg} +0 -0
@@ -1,5 +1,8 @@
1
1
  import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
2
2
  import { basename, join } from 'node:path';
3
+ import { tmpdir } from 'node:os';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { execFileSync } from 'node:child_process';
3
6
  import { ensureDir, getDataDir } from '../storage/json-store.js';
4
7
  import { listTemplates } from './agent.js';
5
8
  const SKILL_FILE = 'SKILL.md';
@@ -12,17 +15,16 @@ function getSkillMetaPath() {
12
15
  function readMeta() {
13
16
  const path = getSkillMetaPath();
14
17
  if (!existsSync(path))
15
- return { favorites: [], groups: {}, disabled: [] };
18
+ return { favorites: [], groups: {} };
16
19
  try {
17
20
  const raw = JSON.parse(readFileSync(path, 'utf-8'));
18
21
  return {
19
22
  favorites: raw.favorites || [],
20
23
  groups: raw.groups || {},
21
- disabled: raw.disabled || [],
22
24
  };
23
25
  }
24
26
  catch {
25
- return { favorites: [], groups: {}, disabled: [] };
27
+ return { favorites: [], groups: {} };
26
28
  }
27
29
  }
28
30
  function writeMeta(meta) {
@@ -84,7 +86,6 @@ export function listSkills() {
84
86
  filename: `${folderName}/${SKILL_FILE}`,
85
87
  content,
86
88
  favorited: meta.favorites.includes(folderName),
87
- enabled: !meta.disabled.includes(folderName),
88
89
  group: meta.groups[folderName] || '',
89
90
  boundAgents,
90
91
  };
@@ -133,7 +134,6 @@ export function importSkill(filename, content, group) {
133
134
  filename: `${folderName}/${SKILL_FILE}`,
134
135
  content,
135
136
  favorited: false,
136
- enabled: true,
137
137
  group: group || '',
138
138
  boundAgents: [],
139
139
  };
@@ -153,7 +153,6 @@ export function importSkillsBatch(items) {
153
153
  filename: `${folderName}/${SKILL_FILE}`,
154
154
  content: item.content,
155
155
  favorited: false,
156
- enabled: true,
157
156
  group: item.group || '',
158
157
  boundAgents: [],
159
158
  });
@@ -161,6 +160,50 @@ export function importSkillsBatch(items) {
161
160
  writeMeta(meta);
162
161
  return results;
163
162
  }
163
+ export function importSkillFromStore(storePath, group) {
164
+ // storePath is like "group-name/skill-name", relative to public/skills/
165
+ const publicSkillsDir = join(getDataDir(), '..', 'public', 'skills');
166
+ // Try relative to package first
167
+ let srcDir = null;
168
+ const candidates = [
169
+ join(process.cwd(), 'public', 'skills', storePath),
170
+ join(import.meta.dirname ?? '', '..', 'public', 'skills', storePath),
171
+ ];
172
+ for (const c of candidates) {
173
+ if (existsSync(c) && statSync(c).isDirectory()) {
174
+ srcDir = c;
175
+ break;
176
+ }
177
+ }
178
+ if (!srcDir)
179
+ return null;
180
+ const skillName = basename(storePath);
181
+ const skillsDir = getSkillsDir();
182
+ const destDir = join(skillsDir, skillName);
183
+ // Copy entire folder
184
+ if (existsSync(destDir))
185
+ rmSync(destDir, { recursive: true, force: true });
186
+ cpSync(srcDir, destDir, { recursive: true, force: true });
187
+ // Set group in meta
188
+ if (group) {
189
+ const meta = readMeta();
190
+ meta.groups[skillName] = group;
191
+ writeMeta(meta);
192
+ }
193
+ // Read content for return
194
+ const skillFile = join(destDir, SKILL_FILE);
195
+ const content = existsSync(skillFile) ? readFileSync(skillFile, 'utf-8') : '';
196
+ const fm = parseFrontmatter(content);
197
+ return {
198
+ name: skillName,
199
+ description: fm.description || '',
200
+ filename: `${skillName}/${SKILL_FILE}`,
201
+ content,
202
+ favorited: false,
203
+ group,
204
+ boundAgents: [],
205
+ };
206
+ }
164
207
  export function toggleFavorite(name) {
165
208
  const meta = readMeta();
166
209
  const idx = meta.favorites.indexOf(name);
@@ -173,31 +216,6 @@ export function toggleFavorite(name) {
173
216
  writeMeta(meta);
174
217
  return idx < 0;
175
218
  }
176
- export function toggleEnabled(name) {
177
- const meta = readMeta();
178
- const idx = meta.disabled.indexOf(name);
179
- if (idx >= 0) {
180
- meta.disabled.splice(idx, 1);
181
- }
182
- else {
183
- meta.disabled.push(name);
184
- }
185
- writeMeta(meta);
186
- return idx >= 0; // true = now enabled
187
- }
188
- export function toggleAllEnabled(names, enabled) {
189
- const meta = readMeta();
190
- if (enabled) {
191
- meta.disabled = meta.disabled.filter((n) => !names.includes(n));
192
- }
193
- else {
194
- const set = new Set(meta.disabled);
195
- for (const n of names)
196
- set.add(n);
197
- meta.disabled = [...set];
198
- }
199
- writeMeta(meta);
200
- }
201
219
  export function updateSkillContent(name, content) {
202
220
  const skillsDir = getSkillsDir();
203
221
  const filePath = join(skillsDir, name, SKILL_FILE);
@@ -216,7 +234,6 @@ export function deleteSkill(name) {
216
234
  const meta = readMeta();
217
235
  meta.favorites = meta.favorites.filter((n) => n !== name);
218
236
  delete meta.groups[name];
219
- meta.disabled = meta.disabled.filter((n) => n !== name);
220
237
  writeMeta(meta);
221
238
  return true;
222
239
  }
@@ -238,7 +255,10 @@ export function checkSkillSync() {
238
255
  const agentFile = join(agentSkillsDir, `${skillName}.md`);
239
256
  if (!existsSync(globalFolder) || !statSync(globalFolder).isDirectory())
240
257
  continue;
241
- const globalStat = statSync(globalFolder);
258
+ // Use SKILL.md file mtime — directory mtime is unreliable on Windows
259
+ if (!existsSync(globalSkillFile))
260
+ continue;
261
+ const globalStat = statSync(globalSkillFile);
242
262
  const agentExists = existsSync(agentFolder) || existsSync(agentFile);
243
263
  if (!agentExists) {
244
264
  // Agent skill missing — needs sync
@@ -251,8 +271,13 @@ export function checkSkillSync() {
251
271
  });
252
272
  continue;
253
273
  }
254
- const agentPath = existsSync(agentFolder) ? agentFolder : agentFile;
255
- const agentStat = statSync(agentPath);
274
+ // Find the actual agent SKILL.md path
275
+ const agentSkillFile = existsSync(agentFolder)
276
+ ? join(agentFolder, SKILL_FILE)
277
+ : agentFile;
278
+ if (!existsSync(agentSkillFile))
279
+ continue;
280
+ const agentStat = statSync(agentSkillFile);
256
281
  if (globalStat.mtimeMs > agentStat.mtimeMs) {
257
282
  result.push({
258
283
  agentId: agent.id,
@@ -290,4 +315,92 @@ export function syncSkills(items) {
290
315
  }
291
316
  return synced;
292
317
  }
318
+ export function listSkillFiles(name) {
319
+ const skillsDir = getSkillsDir();
320
+ const folderPath = join(skillsDir, name);
321
+ if (!existsSync(folderPath) || !statSync(folderPath).isDirectory())
322
+ return [];
323
+ function walk(dir, prefix) {
324
+ const entries = readdirSync(dir, { withFileTypes: true });
325
+ const result = [];
326
+ for (const entry of entries) {
327
+ if (entry.name.startsWith('_') || entry.name === '.DS_Store')
328
+ continue;
329
+ const fullPath = join(dir, entry.name);
330
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
331
+ if (entry.isDirectory()) {
332
+ result.push({ name: entry.name, path: relativePath, isDirectory: true });
333
+ result.push(...walk(fullPath, relativePath));
334
+ }
335
+ else {
336
+ result.push({ name: entry.name, path: relativePath, isDirectory: false });
337
+ }
338
+ }
339
+ return result;
340
+ }
341
+ return walk(folderPath, '');
342
+ }
343
+ export function readSkillFile(name, filePath) {
344
+ const skillsDir = getSkillsDir();
345
+ const fullPath = join(skillsDir, name, filePath);
346
+ // Prevent path traversal
347
+ if (!fullPath.startsWith(join(skillsDir, name)))
348
+ return null;
349
+ if (!existsSync(fullPath) || !statSync(fullPath).isFile())
350
+ return null;
351
+ return readFileSync(fullPath, 'utf-8');
352
+ }
353
+ export function writeSkillFile(name, filePath, content) {
354
+ const skillsDir = getSkillsDir();
355
+ const fullPath = join(skillsDir, name, filePath);
356
+ // Prevent path traversal
357
+ if (!fullPath.startsWith(join(skillsDir, name)))
358
+ return false;
359
+ const dir = join(fullPath, '..');
360
+ ensureDir(dir);
361
+ writeFileSync(fullPath, content, 'utf-8');
362
+ return true;
363
+ }
364
+ export function importSkillsFromGit(gitUrl) {
365
+ const cloneDir = join(tmpdir(), `agent-spaces-git-${randomUUID()}`);
366
+ try {
367
+ execFileSync('git', ['clone', '--depth', '1', gitUrl, cloneDir], {
368
+ timeout: 60_000,
369
+ stdio: 'pipe',
370
+ });
371
+ const results = [];
372
+ function walk(dir) {
373
+ const entries = readdirSync(dir, { withFileTypes: true });
374
+ for (const entry of entries) {
375
+ if (entry.name.startsWith('.') || entry.name === 'node_modules')
376
+ continue;
377
+ const full = join(dir, entry.name);
378
+ if (entry.isDirectory()) {
379
+ walk(full);
380
+ }
381
+ else if (entry.name === SKILL_FILE || entry.name.endsWith('.md')) {
382
+ const folderName = basename(dir);
383
+ if (folderName === basename(cloneDir))
384
+ continue; // skip repo root
385
+ const existing = results.find((r) => r.name === folderName);
386
+ // Prefer SKILL.md over generic .md
387
+ if (!existing || (entry.name === SKILL_FILE && existing.content)) {
388
+ const content = readFileSync(full, 'utf-8');
389
+ if (!existing) {
390
+ results.push({ name: folderName, content });
391
+ }
392
+ else {
393
+ existing.content = content;
394
+ }
395
+ }
396
+ }
397
+ }
398
+ }
399
+ walk(cloneDir);
400
+ return results;
401
+ }
402
+ finally {
403
+ rmSync(cloneDir, { recursive: true, force: true });
404
+ }
405
+ }
293
406
  //# sourceMappingURL=skill.js.map
@@ -0,0 +1,365 @@
1
+ import { join } from 'node:path';
2
+ import { DatabaseSync } from 'node:sqlite';
3
+ import { createHash } from 'node:crypto';
4
+ import { v4 as uuid } from 'uuid';
5
+ import { getDataDir, ensureDir } from './json-store.js';
6
+ let db = null;
7
+ function openDb() {
8
+ if (db)
9
+ return db;
10
+ const dir = join(getDataDir(), 'database');
11
+ ensureDir(dir);
12
+ db = new DatabaseSync(join(dir, 'database.sqlite'));
13
+ const hasDocNodes = Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'doc_nodes'").get());
14
+ const hasDatabaseId = hasDocNodes
15
+ && db.prepare('PRAGMA table_info(doc_nodes)').all()
16
+ .some((column) => column.name === 'database_id');
17
+ if (hasDocNodes && !hasDatabaseId) {
18
+ db.exec('DROP TABLE IF EXISTS doc_nodes; DROP TABLE IF EXISTS databases;');
19
+ }
20
+ db.exec(`
21
+ CREATE TABLE IF NOT EXISTS databases (
22
+ id TEXT PRIMARY KEY,
23
+ workspace_id TEXT NOT NULL,
24
+ name TEXT NOT NULL DEFAULT '',
25
+ description TEXT NOT NULL DEFAULT '',
26
+ embedding_model_id TEXT,
27
+ created_at INTEGER NOT NULL,
28
+ updated_at INTEGER NOT NULL
29
+ );
30
+
31
+ CREATE TABLE IF NOT EXISTS doc_nodes (
32
+ id TEXT PRIMARY KEY,
33
+ workspace_id TEXT NOT NULL,
34
+ database_id TEXT NOT NULL,
35
+ title TEXT NOT NULL DEFAULT '',
36
+ icon TEXT NOT NULL DEFAULT '',
37
+ cover TEXT NOT NULL DEFAULT '',
38
+ content TEXT NOT NULL DEFAULT '',
39
+ parent_id TEXT,
40
+ is_trash INTEGER NOT NULL DEFAULT 0,
41
+ created_at INTEGER NOT NULL,
42
+ updated_at INTEGER NOT NULL
43
+ );
44
+
45
+ CREATE TABLE IF NOT EXISTS database_embeddings (
46
+ workspace_id TEXT NOT NULL,
47
+ database_id TEXT NOT NULL,
48
+ node_id TEXT NOT NULL,
49
+ title TEXT NOT NULL DEFAULT '',
50
+ path TEXT NOT NULL DEFAULT '',
51
+ content TEXT NOT NULL DEFAULT '',
52
+ content_hash TEXT NOT NULL,
53
+ embedding TEXT NOT NULL,
54
+ model_id TEXT NOT NULL DEFAULT '',
55
+ agent_id TEXT NOT NULL DEFAULT '',
56
+ updated_at INTEGER NOT NULL,
57
+ PRIMARY KEY (workspace_id, database_id, node_id)
58
+ );
59
+
60
+ CREATE TABLE IF NOT EXISTS doc_node_versions (
61
+ id TEXT PRIMARY KEY,
62
+ workspace_id TEXT NOT NULL,
63
+ database_id TEXT NOT NULL,
64
+ node_id TEXT NOT NULL,
65
+ title TEXT NOT NULL DEFAULT '',
66
+ patch_json TEXT NOT NULL,
67
+ old_hash TEXT NOT NULL,
68
+ new_hash TEXT NOT NULL,
69
+ created_at INTEGER NOT NULL
70
+ );
71
+
72
+ CREATE INDEX IF NOT EXISTS idx_databases_workspace ON databases(workspace_id);
73
+ CREATE INDEX IF NOT EXISTS idx_doc_nodes_workspace ON doc_nodes(workspace_id);
74
+ CREATE INDEX IF NOT EXISTS idx_doc_nodes_database ON doc_nodes(workspace_id, database_id);
75
+ CREATE INDEX IF NOT EXISTS idx_doc_nodes_parent ON doc_nodes(workspace_id, database_id, parent_id);
76
+ CREATE INDEX IF NOT EXISTS idx_database_embeddings_database ON database_embeddings(workspace_id, database_id);
77
+ CREATE INDEX IF NOT EXISTS idx_doc_node_versions_node ON doc_node_versions(workspace_id, database_id, node_id, created_at DESC);
78
+ `);
79
+ ensureColumn('databases', 'embedding_model_id', 'TEXT');
80
+ migrateEmbeddingModelColumn();
81
+ return db;
82
+ }
83
+ function ensureColumn(table, column, type) {
84
+ const database = db;
85
+ const exists = database.prepare(`PRAGMA table_info(${table})`).all()
86
+ .some((item) => item.name === column);
87
+ if (!exists)
88
+ database.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
89
+ }
90
+ function migrateEmbeddingModelColumn() {
91
+ const database = db;
92
+ const columns = database.prepare('PRAGMA table_info(databases)').all();
93
+ const hasLegacyAgentColumn = columns.some((item) => item.name === 'embedding_agent_id');
94
+ if (!hasLegacyAgentColumn)
95
+ return;
96
+ database.exec(`
97
+ UPDATE databases
98
+ SET embedding_model_id = COALESCE(embedding_model_id, embedding_agent_id)
99
+ WHERE embedding_agent_id IS NOT NULL AND embedding_agent_id != ''
100
+ `);
101
+ }
102
+ function rowToDatabase(row) {
103
+ return {
104
+ id: row.id,
105
+ workspaceId: row.workspace_id,
106
+ name: row.name,
107
+ description: row.description,
108
+ embeddingModelId: row.embedding_model_id || undefined,
109
+ createdAt: row.created_at,
110
+ updatedAt: row.updated_at,
111
+ };
112
+ }
113
+ function rowToNode(row) {
114
+ return {
115
+ id: row.id,
116
+ databaseId: row.database_id,
117
+ title: row.title,
118
+ icon: row.icon,
119
+ cover: row.cover,
120
+ content: row.content,
121
+ parentId: row.parent_id || null,
122
+ isTrash: !!row.is_trash,
123
+ createdAt: row.created_at,
124
+ updatedAt: row.updated_at,
125
+ };
126
+ }
127
+ function rowToVersionRow(row) {
128
+ return {
129
+ id: row.id,
130
+ nodeId: row.node_id,
131
+ databaseId: row.database_id,
132
+ title: row.title,
133
+ patch: JSON.parse(row.patch_json),
134
+ oldHash: row.old_hash,
135
+ newHash: row.new_hash,
136
+ createdAt: row.created_at,
137
+ };
138
+ }
139
+ export function listDatabases(workspaceId) {
140
+ const database = openDb();
141
+ const rows = database.prepare('SELECT * FROM databases WHERE workspace_id = ? ORDER BY created_at ASC').all(workspaceId);
142
+ return rows.map(rowToDatabase);
143
+ }
144
+ export function getDatabase(workspaceId, databaseId) {
145
+ const database = openDb();
146
+ const row = database.prepare('SELECT * FROM databases WHERE workspace_id = ? AND id = ?').get(workspaceId, databaseId);
147
+ return row ? rowToDatabase(row) : null;
148
+ }
149
+ export function getDefaultDatabase(workspaceId) {
150
+ const existing = listDatabases(workspaceId)[0];
151
+ if (existing)
152
+ return existing;
153
+ return createDatabase(workspaceId, { name: 'Default Database' });
154
+ }
155
+ export function createDatabase(workspaceId, input) {
156
+ const database = openDb();
157
+ const id = input.id || uuid();
158
+ const now = Date.now();
159
+ database.prepare(`INSERT INTO databases (id, workspace_id, name, description, created_at, updated_at)
160
+ VALUES (?, ?, ?, ?, ?, ?)`).run(id, workspaceId, input.name?.trim() || 'Untitled Database', input.description || '', now, now);
161
+ return getDatabase(workspaceId, id);
162
+ }
163
+ export function updateDatabase(workspaceId, databaseId, updates) {
164
+ const existing = getDatabase(workspaceId, databaseId);
165
+ if (!existing)
166
+ return null;
167
+ const database = openDb();
168
+ const merged = { ...existing, ...updates, updatedAt: Date.now() };
169
+ database.prepare('UPDATE databases SET name = ?, description = ?, embedding_model_id = ?, updated_at = ? WHERE workspace_id = ? AND id = ?').run(merged.name.trim() || 'Untitled Database', merged.description, merged.embeddingModelId ?? null, merged.updatedAt, workspaceId, databaseId);
170
+ return getDatabase(workspaceId, databaseId);
171
+ }
172
+ export function deleteDatabase(workspaceId, databaseId) {
173
+ const database = openDb();
174
+ database.prepare('DELETE FROM doc_nodes WHERE workspace_id = ? AND database_id = ?').run(workspaceId, databaseId);
175
+ database.prepare('DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ?').run(workspaceId, databaseId);
176
+ const result = database.prepare('DELETE FROM databases WHERE workspace_id = ? AND id = ?').run(workspaceId, databaseId);
177
+ if (result.changes > 0 && listDatabases(workspaceId).length === 0)
178
+ getDefaultDatabase(workspaceId);
179
+ return result.changes > 0;
180
+ }
181
+ export function listNodes(workspaceId, databaseId) {
182
+ const database = openDb();
183
+ const activeDatabaseId = databaseId ?? getDefaultDatabase(workspaceId).id;
184
+ const rows = database.prepare('SELECT * FROM doc_nodes WHERE workspace_id = ? AND database_id = ? ORDER BY created_at ASC').all(workspaceId, activeDatabaseId);
185
+ return rows.map(rowToNode);
186
+ }
187
+ export function getNode(workspaceId, nodeId, databaseId) {
188
+ const database = openDb();
189
+ const row = databaseId
190
+ ? database.prepare('SELECT * FROM doc_nodes WHERE workspace_id = ? AND database_id = ? AND id = ?').get(workspaceId, databaseId, nodeId)
191
+ : database.prepare('SELECT * FROM doc_nodes WHERE workspace_id = ? AND id = ?').get(workspaceId, nodeId);
192
+ return row ? rowToNode(row) : null;
193
+ }
194
+ export function createNode(workspaceId, node) {
195
+ const database = openDb();
196
+ const databaseId = node.databaseId || getDefaultDatabase(workspaceId).id;
197
+ if (!getDatabase(workspaceId, databaseId))
198
+ throw new Error(`Database not found: ${databaseId}`);
199
+ const id = node.id || uuid();
200
+ const now = Date.now();
201
+ database.prepare(`INSERT INTO doc_nodes (id, workspace_id, database_id, title, icon, cover, content, parent_id, is_trash, created_at, updated_at)
202
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, workspaceId, databaseId, node.title || 'Untitled Document', node.icon || '\u{1F4DD}', node.cover || '', node.content || '', node.parentId ?? null, node.isTrash ? 1 : 0, node.createdAt || now, node.updatedAt || now);
203
+ return getNode(workspaceId, id, databaseId);
204
+ }
205
+ export function updateNode(workspaceId, nodeId, updates, databaseId) {
206
+ const existing = getNode(workspaceId, nodeId, databaseId);
207
+ if (!existing)
208
+ return null;
209
+ const database = openDb();
210
+ const merged = { ...existing, ...updates, updatedAt: Date.now() };
211
+ if (Object.hasOwn(updates, 'content') && merged.content !== existing.content) {
212
+ insertNodeVersion(database, workspaceId, existing, merged.content);
213
+ }
214
+ database.prepare(`UPDATE doc_nodes SET title = ?, icon = ?, cover = ?, content = ?, parent_id = ?, is_trash = ?, updated_at = ?
215
+ WHERE workspace_id = ? AND database_id = ? AND id = ?`).run(merged.title, merged.icon, merged.cover, merged.content, merged.parentId, merged.isTrash ? 1 : 0, merged.updatedAt, workspaceId, existing.databaseId, nodeId);
216
+ return getNode(workspaceId, nodeId, existing.databaseId);
217
+ }
218
+ export function listNodeVersions(workspaceId, nodeId, databaseId, limit = 50) {
219
+ const node = getNode(workspaceId, nodeId, databaseId);
220
+ if (!node)
221
+ return [];
222
+ const database = openDb();
223
+ const normalizedLimit = Number.isFinite(limit) ? Math.max(1, Math.min(100, Math.trunc(limit))) : 50;
224
+ const rows = database.prepare(`SELECT * FROM doc_node_versions
225
+ WHERE workspace_id = ? AND database_id = ? AND node_id = ?
226
+ ORDER BY created_at DESC
227
+ LIMIT ?`).all(workspaceId, node.databaseId, nodeId, normalizedLimit);
228
+ const stored = rows.map(rowToVersionRow);
229
+ let after = node.content;
230
+ return stored.map((item) => {
231
+ const before = applyReversePatch(after, item.patch);
232
+ const version = {
233
+ id: item.id,
234
+ nodeId: item.nodeId,
235
+ databaseId: item.databaseId,
236
+ title: item.title,
237
+ patch: item.patch,
238
+ oldContent: before,
239
+ newContent: after,
240
+ createdAt: item.createdAt,
241
+ };
242
+ after = before;
243
+ return version;
244
+ });
245
+ }
246
+ export function deleteNode(workspaceId, nodeId, databaseId) {
247
+ const database = openDb();
248
+ const existing = getNode(workspaceId, nodeId, databaseId);
249
+ if (!existing)
250
+ return false;
251
+ database.prepare('DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ? AND node_id = ?')
252
+ .run(workspaceId, existing.databaseId, nodeId);
253
+ database.prepare('DELETE FROM doc_node_versions WHERE workspace_id = ? AND database_id = ? AND node_id = ?')
254
+ .run(workspaceId, existing.databaseId, nodeId);
255
+ const result = database.prepare('DELETE FROM doc_nodes WHERE workspace_id = ? AND database_id = ? AND id = ?').run(workspaceId, existing.databaseId, nodeId);
256
+ return result.changes > 0;
257
+ }
258
+ function insertNodeVersion(database, workspaceId, existing, nextContent) {
259
+ const patch = createContentPatch(existing.content, nextContent);
260
+ database.prepare(`INSERT INTO doc_node_versions
261
+ (id, workspace_id, database_id, node_id, title, patch_json, old_hash, new_hash, created_at)
262
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(uuid(), workspaceId, existing.databaseId, existing.id, existing.title, JSON.stringify(patch), hashContent(existing.content), hashContent(nextContent), Date.now());
263
+ }
264
+ function createContentPatch(oldContent, newContent) {
265
+ let start = 0;
266
+ while (start < oldContent.length
267
+ && start < newContent.length
268
+ && oldContent[start] === newContent[start]) {
269
+ start++;
270
+ }
271
+ let oldEnd = oldContent.length;
272
+ let newEnd = newContent.length;
273
+ while (oldEnd > start
274
+ && newEnd > start
275
+ && oldContent[oldEnd - 1] === newContent[newEnd - 1]) {
276
+ oldEnd--;
277
+ newEnd--;
278
+ }
279
+ return {
280
+ start,
281
+ deleteText: oldContent.slice(start, oldEnd),
282
+ insertText: newContent.slice(start, newEnd),
283
+ };
284
+ }
285
+ function applyReversePatch(content, patch) {
286
+ const insertEnd = patch.start + patch.insertText.length;
287
+ return `${content.slice(0, patch.start)}${patch.deleteText}${content.slice(insertEnd)}`;
288
+ }
289
+ function hashContent(content) {
290
+ return createHash('sha256').update(content).digest('hex');
291
+ }
292
+ export function moveNode(workspaceId, nodeId, newParentId, databaseId) {
293
+ return updateNode(workspaceId, nodeId, { parentId: newParentId }, databaseId);
294
+ }
295
+ export function trashNode(workspaceId, nodeId, databaseId) {
296
+ return updateNode(workspaceId, nodeId, { isTrash: true }, databaseId);
297
+ }
298
+ export function restoreNode(workspaceId, nodeId, databaseId) {
299
+ const node = getNode(workspaceId, nodeId, databaseId);
300
+ if (!node)
301
+ return null;
302
+ if (node.parentId) {
303
+ const parent = getNode(workspaceId, node.parentId, node.databaseId);
304
+ if (parent && parent.isTrash) {
305
+ return updateNode(workspaceId, nodeId, { isTrash: false, parentId: null }, node.databaseId);
306
+ }
307
+ }
308
+ return updateNode(workspaceId, nodeId, { isTrash: false }, node.databaseId);
309
+ }
310
+ export function getVectorStats(workspaceId, databaseId) {
311
+ const database = openDb();
312
+ const meta = getDatabase(workspaceId, databaseId);
313
+ const indexed = database.prepare('SELECT COUNT(*) AS count, MAX(updated_at) AS last_indexed_at FROM database_embeddings WHERE workspace_id = ? AND database_id = ?').get(workspaceId, databaseId);
314
+ const nodes = database.prepare('SELECT COUNT(*) AS count FROM doc_nodes WHERE workspace_id = ? AND database_id = ? AND is_trash = 0').get(workspaceId, databaseId);
315
+ return {
316
+ databaseId,
317
+ embeddingModelId: meta?.embeddingModelId ?? null,
318
+ indexedCount: indexed.count,
319
+ nodeCount: nodes.count,
320
+ lastIndexedAt: indexed.last_indexed_at,
321
+ };
322
+ }
323
+ export function setDatabaseEmbeddingModel(workspaceId, databaseId, embeddingModelId) {
324
+ return updateDatabase(workspaceId, databaseId, { embeddingModelId: embeddingModelId ?? undefined });
325
+ }
326
+ export function upsertDatabaseEmbedding(workspaceId, databaseId, record) {
327
+ const database = openDb();
328
+ database.prepare(`INSERT INTO database_embeddings
329
+ (workspace_id, database_id, node_id, title, path, content, content_hash, embedding, model_id, agent_id, updated_at)
330
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
331
+ ON CONFLICT(workspace_id, database_id, node_id) DO UPDATE SET
332
+ title = excluded.title,
333
+ path = excluded.path,
334
+ content = excluded.content,
335
+ content_hash = excluded.content_hash,
336
+ embedding = excluded.embedding,
337
+ model_id = excluded.model_id,
338
+ agent_id = excluded.agent_id,
339
+ updated_at = excluded.updated_at`).run(workspaceId, databaseId, record.nodeId, record.title, record.path, record.content, record.contentHash, JSON.stringify(record.embedding), record.modelId, record.agentId, Date.now());
340
+ }
341
+ export function deleteStaleDatabaseEmbeddings(workspaceId, databaseId, activeNodeIds) {
342
+ const database = openDb();
343
+ if (activeNodeIds.length === 0) {
344
+ const result = database.prepare('DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ?')
345
+ .run(workspaceId, databaseId);
346
+ return result.changes;
347
+ }
348
+ const placeholders = activeNodeIds.map(() => '?').join(',');
349
+ const result = database.prepare(`DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ? AND node_id NOT IN (${placeholders})`).run(workspaceId, databaseId, ...activeNodeIds);
350
+ return result.changes;
351
+ }
352
+ export function listDatabaseEmbeddings(workspaceId, databaseId) {
353
+ const database = openDb();
354
+ const rows = database.prepare('SELECT node_id, title, path, content, embedding, updated_at FROM database_embeddings WHERE workspace_id = ? AND database_id = ?').all(workspaceId, databaseId);
355
+ return rows.map((row) => ({
356
+ nodeId: row.node_id,
357
+ title: row.title,
358
+ path: row.path,
359
+ content: row.content,
360
+ score: 0,
361
+ updatedAt: row.updated_at,
362
+ embedding: JSON.parse(row.embedding),
363
+ }));
364
+ }
365
+ //# sourceMappingURL=database-store.js.map
@@ -0,0 +1,55 @@
1
+ import { join } from 'node:path';
2
+ import { readdirSync } from 'node:fs';
3
+ import { getDataDir, ensureDir, readJsonFile, writeJsonFile, deleteFile } from './json-store.js';
4
+ function workspaceDir(id) {
5
+ return join(getDataDir(), 'workspaces', id);
6
+ }
7
+ function hooksDir(wsId) {
8
+ return join(workspaceDir(wsId), 'hooks');
9
+ }
10
+ function hookPath(wsId, name) {
11
+ return join(hooksDir(wsId), `${name}.hook.json`);
12
+ }
13
+ export function listHooks(wsId) {
14
+ const dir = hooksDir(wsId);
15
+ try {
16
+ const files = readdirSync(dir);
17
+ return files
18
+ .filter(f => f.endsWith('.hook.json'))
19
+ .map(f => readJsonFile(join(dir, f)))
20
+ .filter((h) => h !== null);
21
+ }
22
+ catch {
23
+ return [];
24
+ }
25
+ }
26
+ export function getHook(wsId, name) {
27
+ return readJsonFile(hookPath(wsId, name));
28
+ }
29
+ export function saveHook(wsId, config) {
30
+ ensureDir(hooksDir(wsId));
31
+ writeJsonFile(hookPath(wsId, config.name), config);
32
+ }
33
+ export function deleteHook(wsId, name) {
34
+ deleteFile(hookPath(wsId, name));
35
+ }
36
+ export function uploadHook(wsId, jsonString) {
37
+ const parsed = JSON.parse(jsonString);
38
+ if (!parsed.name || typeof parsed.name !== 'string') {
39
+ throw new Error('Hook must have a "name" string field');
40
+ }
41
+ if (!parsed.hooks || typeof parsed.hooks !== 'object') {
42
+ parsed.hooks = { PreToolUse: [], PostToolUse: [] };
43
+ }
44
+ if (parsed.enabled === undefined)
45
+ parsed.enabled = true;
46
+ saveHook(wsId, parsed);
47
+ return parsed;
48
+ }
49
+ export function applyToWorkspace(sourceWsId, name, targetWsId) {
50
+ const config = getHook(sourceWsId, name);
51
+ if (!config)
52
+ throw new Error(`Hook "${name}" not found in workspace ${sourceWsId}`);
53
+ saveHook(targetWsId, config);
54
+ }
55
+ //# sourceMappingURL=hook-store.js.map