@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
@@ -5,11 +5,13 @@ import * as issueService from '../services/issue.js';
5
5
  import * as taskService from '../services/task.js';
6
6
  import * as workspaceService from '../services/workspace.js';
7
7
  import { mapWorkflowToTaskDrafts, validateWorkflowForRun } from '../services/workflow.js';
8
- import { createIssueFunctionTools } from '../services/builtin-tools.js';
8
+ import { createIssueFunctionTools } from '../services/builtin-tools/index.js';
9
9
  import { getThinkingRuntimeConfig } from '../services/llm-model-config.js';
10
10
  import { prependPersistentAgentContext } from '../services/persistent-agent-context.js';
11
11
  import { completeIssueAgentProgress, createIssueAgentProgress, createIssueAgentProgressTracker } from './issue-agent-progress.js';
12
+ import { wrapOnEventWithHooks } from '../services/hook-engine.js';
12
13
  const ACTIVE_TASK_STATUSES = ['running', 'reviewing', 'retrying', 'waiting_review'];
14
+ const activeIssueRuntimes = new Map();
13
15
  export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, ctx) {
14
16
  const issue = issueService.getById(workspaceId, issueId);
15
17
  if (!issue) {
@@ -31,6 +33,7 @@ export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, c
31
33
  ctx.broadcast('agent.output', { agentId: taskSyncAgent.id, data: `Syncing issue tasks: ${issueId}` });
32
34
  const startTime = Date.now();
33
35
  const taskSyncWorkingDir = resolveIssueWorkspaceRoot(workspaceId);
36
+ const workspace = workspaceService.getById(workspaceId);
34
37
  const progress = createIssueAgentProgress(workspaceId, issue, taskSyncPreset, taskSyncAgent.id, {
35
38
  runtime: taskSyncPreset.runtimeKind,
36
39
  model: taskSyncPreset.modelId,
@@ -53,7 +56,8 @@ export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, c
53
56
  skills: [],
54
57
  configDir: agentService.getAgentConfigDir(workspaceId, taskSyncPreset),
55
58
  sandboxDirs: taskSyncPreset.sandboxDirs,
56
- onEvent: taskSyncTracker.handleEvent,
59
+ outputStyle: taskSyncPreset.outputStyle,
60
+ onEvent: wrapOnEventWithHooks(taskSyncTracker.handleEvent.bind(taskSyncTracker), workspaceId, workspace?.hooksEnabled),
57
61
  });
58
62
  if (taskSyncTracker.output.length === 0) {
59
63
  for (const line of result.output) {
@@ -101,7 +105,10 @@ export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, c
101
105
  updateIssueStatus(workspaceId, issueId, 'in_progress', ctx);
102
106
  await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
103
107
  }
104
- export async function scheduleRunnableIssueTasks(workspaceId, issueId, ctx) {
108
+ export async function scheduleRunnableIssueTasks(workspaceId, issueId, ctx, _options = {}) {
109
+ const issue = issueService.getById(workspaceId, issueId);
110
+ if (!issue)
111
+ return;
105
112
  const tasks = taskService.list(workspaceId, issueId);
106
113
  const doneIds = new Set(tasks.filter((task) => task.status === 'done').map((task) => task.id));
107
114
  const hasActive = tasks.some((task) => ACTIVE_TASK_STATUSES.includes(task.status));
@@ -113,7 +120,8 @@ export async function scheduleRunnableIssueTasks(workspaceId, issueId, ctx) {
113
120
  }
114
121
  return;
115
122
  }
116
- for (const task of runnable) {
123
+ const tasksToRun = issue.continuousRun === false ? runnable.slice(0, 1) : runnable;
124
+ for (const task of tasksToRun) {
117
125
  await runIssueTask(workspaceId, issueId, task.id, ctx);
118
126
  }
119
127
  }
@@ -129,6 +137,8 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
129
137
  }
130
138
  const taskAgentPreset = findAgentForTask(workspaceId, issue, task);
131
139
  if (!taskAgentPreset) {
140
+ if (issueService.getById(workspaceId, issueId)?.status === 'error')
141
+ return;
132
142
  const missingExecutorResult = {
133
143
  success: false,
134
144
  summary: 'No runnable agent configured in issue channel members',
@@ -161,6 +171,7 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
161
171
  broadcastTaskUpdate(ctx, runningTask, task.status);
162
172
  agentService.assignTask(workspaceId, taskAgent.id, taskId);
163
173
  const runtime = createRuntimeForPreset(taskAgentPreset);
174
+ registerActiveIssueRuntime(workspaceId, issueId, taskAgent.id, runtime);
164
175
  const agentWorkingDir = resolveIssueWorkspaceRoot(workspaceId);
165
176
  const startTime = Date.now();
166
177
  const progress = createIssueAgentProgress(workspaceId, issue, taskAgentPreset, taskAgent.id, {
@@ -180,20 +191,40 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
180
191
  ctx.broadcast('task.output', { taskId, data: line });
181
192
  },
182
193
  });
194
+ const workspace = workspaceService.getById(workspaceId);
183
195
  ctx.broadcast('agent.output', { agentId: taskAgent.id, data: `Executing task: ${runningTask.title}` });
184
196
  ctx.broadcast('agent.output', {
185
197
  agentId: taskAgent.id,
186
198
  data: `[debug] workflow agentConfigId=${taskAgentPreset.id} role=${taskAgentPreset.role} taskAgentConfigId=${runningTask.agentConfigId || '(fallback)'} runtime=${taskAgentPreset.runtimeKind ?? 'open-agent-sdk'}`,
187
199
  });
188
- const result = await runtime.execute(buildIssueAgentPrompt(workspaceId, buildTaskAgentPrompt(issue, runningTask, taskAgentPreset, agentWorkingDir), agentWorkingDir, taskAgentPreset), agentWorkingDir, {
189
- maxTurns: 100,
190
- mcpServers: agentService.getMcpServers(taskAgentPreset.mcps),
191
- functionTools: createCurrentIssueTools(workspaceId, issue, taskAgentPreset),
192
- skills: agentService.getAvailableSkillNames(agentService.getAgentConfigDir(workspaceId, taskAgentPreset), taskAgentPreset.skills),
193
- configDir: agentService.getAgentConfigDir(workspaceId, taskAgentPreset),
194
- sandboxDirs: runningTask.sandboxDirs ?? taskAgentPreset.sandboxDirs,
195
- onEvent: agentTracker.handleEvent,
196
- });
200
+ let result;
201
+ try {
202
+ result = await runtime.execute(buildIssueAgentPrompt(workspaceId, buildTaskAgentPrompt(issue, runningTask, taskAgentPreset, agentWorkingDir), agentWorkingDir, taskAgentPreset), agentWorkingDir, {
203
+ maxTurns: 100,
204
+ mcpServers: agentService.getMcpServers(taskAgentPreset.mcps),
205
+ functionTools: createCurrentIssueTools(workspaceId, issue, taskAgentPreset),
206
+ skills: agentService.getAvailableSkillNames(agentService.getAgentConfigDir(workspaceId, taskAgentPreset), taskAgentPreset.skills),
207
+ configDir: agentService.getAgentConfigDir(workspaceId, taskAgentPreset),
208
+ sandboxDirs: runningTask.sandboxDirs ?? taskAgentPreset.sandboxDirs,
209
+ outputStyle: taskAgentPreset.outputStyle,
210
+ onEvent: wrapOnEventWithHooks(agentTracker.handleEvent.bind(agentTracker), workspaceId, workspace?.hooksEnabled),
211
+ });
212
+ }
213
+ finally {
214
+ unregisterActiveIssueRuntime(workspaceId, issueId, taskAgent.id);
215
+ }
216
+ if (issueService.getById(workspaceId, issueId)?.status === 'error') {
217
+ const failedTask = taskService.updateStatus(workspaceId, taskId, 'failed', {
218
+ result: {
219
+ success: false,
220
+ summary: 'Interrupted by user',
221
+ artifacts: [],
222
+ error: 'Interrupted by user',
223
+ },
224
+ });
225
+ broadcastTaskUpdate(ctx, failedTask, 'running');
226
+ return;
227
+ }
197
228
  if (agentTracker.output.length === 0) {
198
229
  for (const line of result.output) {
199
230
  agentTracker.output.push(line);
@@ -235,10 +266,42 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
235
266
  }
236
267
  const completedTask = taskService.complete(workspaceId, taskId, result);
237
268
  broadcastTaskUpdate(ctx, completedTask, 'running');
238
- await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
269
+ if (issueService.getById(workspaceId, issueId)?.continuousRun !== false) {
270
+ await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
271
+ }
239
272
  }
240
273
  export async function continueIssueTaskScheduling(workspaceId, issueId, ctx) {
241
- await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
274
+ await scheduleRunnableIssueTasks(workspaceId, issueId, ctx, { force: true });
275
+ }
276
+ export function stopIssueAutomation(workspaceId, issueId, reason = 'Interrupted by user') {
277
+ const key = issueRunKey(workspaceId, issueId);
278
+ const runtimes = activeIssueRuntimes.get(key);
279
+ if (runtimes) {
280
+ for (const [agentId, runtime] of runtimes.entries()) {
281
+ try {
282
+ runtime.stop();
283
+ }
284
+ catch {
285
+ // Runtime may already be unwinding.
286
+ }
287
+ agentService.complete(workspaceId, agentId, reason);
288
+ }
289
+ activeIssueRuntimes.delete(key);
290
+ }
291
+ const activeTasks = taskService.list(workspaceId, issueId)
292
+ .filter((task) => ACTIVE_TASK_STATUSES.includes(task.status));
293
+ return activeTasks.map((task) => {
294
+ const from = task.status;
295
+ const failed = taskService.updateStatus(workspaceId, task.id, 'failed', {
296
+ result: {
297
+ success: false,
298
+ summary: reason,
299
+ artifacts: [],
300
+ error: reason,
301
+ },
302
+ });
303
+ return failed ? { task: failed, from } : null;
304
+ }).filter((item) => Boolean(item));
242
305
  }
243
306
  function createTaskSyncTools(workspaceId, issue, preset, ctx) {
244
307
  return [
@@ -417,6 +480,24 @@ async function handleTaskFailure(workspaceId, issueId, taskId, result, ctx) {
417
480
  ctx.broadcast('issue.status_changed', { issueId, from: issue?.status ?? 'in_progress', to: 'error' });
418
481
  ctx.broadcast('issue.updated', updated);
419
482
  }
483
+ function registerActiveIssueRuntime(workspaceId, issueId, agentId, runtime) {
484
+ const key = issueRunKey(workspaceId, issueId);
485
+ const runtimes = activeIssueRuntimes.get(key) ?? new Map();
486
+ runtimes.set(agentId, runtime);
487
+ activeIssueRuntimes.set(key, runtimes);
488
+ }
489
+ function unregisterActiveIssueRuntime(workspaceId, issueId, agentId) {
490
+ const key = issueRunKey(workspaceId, issueId);
491
+ const runtimes = activeIssueRuntimes.get(key);
492
+ if (!runtimes)
493
+ return;
494
+ runtimes.delete(agentId);
495
+ if (runtimes.size === 0)
496
+ activeIssueRuntimes.delete(key);
497
+ }
498
+ function issueRunKey(workspaceId, issueId) {
499
+ return `${workspaceId}:${issueId}`;
500
+ }
420
501
  function broadcastTaskUpdate(ctx, task, from) {
421
502
  if (!task)
422
503
  return;
package/dist/app.js CHANGED
@@ -5,9 +5,9 @@ import express from 'express';
5
5
  import cors from 'cors';
6
6
  import { createServer } from 'node:http';
7
7
  import { WebSocketServer } from 'ws';
8
- import { existsSync, mkdirSync } from 'node:fs';
8
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
9
9
  import { writeFile } from 'node:fs/promises';
10
- import { join, dirname } from 'node:path';
10
+ import { join, dirname, extname, basename } from 'node:path';
11
11
  import { fileURLToPath } from 'node:url';
12
12
  import workspaceRouter from './routes/workspace.js';
13
13
  import fileRouter from './routes/file.js';
@@ -22,14 +22,19 @@ import authRouter from './routes/auth.js';
22
22
  import folderRouter from './routes/folder.js';
23
23
  import commandRouter from './routes/command.js';
24
24
  import codeFavoritesRouter from './routes/code-favorites.js';
25
+ import hooksRouter from './routes/hooks.js';
25
26
  import skillRouter from './routes/skill.js';
26
27
  import promptTemplateRouter from './routes/prompt-template.js';
28
+ import outputStyleRouter from './routes/output-style.js';
27
29
  import mcpRouter from './routes/mcp.js';
28
30
  import subscriptionRouter from './routes/subscription.js';
29
31
  import agentSseRouter from './routes/agent-sse.js';
30
32
  import searchRouter from './routes/search.js';
31
33
  import notificationRouter from './routes/notification.js';
34
+ import databaseRouter from './routes/database.js';
35
+ import kanbanRouter from './routes/kanban.js';
32
36
  import speechRecognitionRouter, { handleSpeechStream } from './routes/speech-recognition.js';
37
+ import agentCommandsRouter from './routes/agent-commands.js';
33
38
  import { getUserSettings, setUserAvatarUrl, removeUserAvatarUrl } from './storage/user-settings-store.js';
34
39
  import { authMiddleware, verifyToken } from './middleware/auth.js';
35
40
  import { handleConnection } from './ws/handler.js';
@@ -65,6 +70,73 @@ app.use('/api', authMiddleware);
65
70
  // Serve static files from public/
66
71
  const publicDir = resolveRuntimeDir('public');
67
72
  app.use('/public', express.static(publicDir));
73
+ // Scan public/prompt/ and generate index.json for the prompt store
74
+ function scanPromptStore() {
75
+ const promptDir = join(publicDir, 'prompt');
76
+ if (!existsSync(promptDir))
77
+ return;
78
+ const files = readdirSync(promptDir).filter((f) => f.endsWith('.md'));
79
+ const index = files.map((filename) => {
80
+ const id = basename(filename, '.md');
81
+ const content = readFileSync(join(promptDir, filename), 'utf-8');
82
+ const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
83
+ const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
84
+ return { id, name, filename };
85
+ });
86
+ writeFileSync(join(promptDir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
87
+ console.log(`[prompt-store] scanned ${index.length} templates`);
88
+ }
89
+ scanPromptStore();
90
+ // Scan public/output-styles/ and generate index.json
91
+ function scanOutputStyleStore() {
92
+ const dir = join(publicDir, 'output-styles');
93
+ if (!existsSync(dir))
94
+ return;
95
+ const files = readdirSync(dir).filter((f) => f.endsWith('.md'));
96
+ const index = files.map((filename) => {
97
+ const id = basename(filename, '.md');
98
+ const content = readFileSync(join(dir, filename), 'utf-8');
99
+ const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
100
+ const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
101
+ return { id, name, filename };
102
+ });
103
+ writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
104
+ console.log(`[output-style-store] scanned ${index.length} templates`);
105
+ }
106
+ scanOutputStyleStore();
107
+ // Scan public/skills/{group}/{skill-name}/SKILL.md and generate index.json
108
+ function scanSkillStore() {
109
+ const dir = join(publicDir, 'skills');
110
+ if (!existsSync(dir))
111
+ return;
112
+ const index = [];
113
+ for (const groupEntry of readdirSync(dir, { withFileTypes: true })) {
114
+ if (!groupEntry.isDirectory())
115
+ continue;
116
+ const group = groupEntry.name;
117
+ const groupDir = join(dir, group);
118
+ for (const skillEntry of readdirSync(groupDir, { withFileTypes: true })) {
119
+ if (!skillEntry.isDirectory())
120
+ continue;
121
+ const skillName = skillEntry.name;
122
+ const skillFile = join(groupDir, skillName, 'SKILL.md');
123
+ if (!existsSync(skillFile))
124
+ continue;
125
+ const content = readFileSync(skillFile, 'utf-8');
126
+ const fm = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
127
+ let name = skillName;
128
+ if (fm) {
129
+ const nameLine = fm[1].split(/\r?\n/).find((l) => /^\s*name\s*:/i.test(l));
130
+ if (nameLine)
131
+ name = nameLine.split(':', 2)[1].trim() || skillName;
132
+ }
133
+ index.push({ id: skillName, name, group, path: `${group}/${skillName}` });
134
+ }
135
+ }
136
+ writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
137
+ console.log(`[skill-store] scanned ${index.length} skills`);
138
+ }
139
+ scanSkillStore();
68
140
  app.get('/api/health', (_req, res) => {
69
141
  res.json({ status: 'ok', timestamp: new Date().toISOString(), platform: process.platform });
70
142
  });
@@ -82,15 +154,56 @@ app.post('/api/upload/avatar', async (req, res) => {
82
154
  return;
83
155
  }
84
156
  const [, mime, base64] = match;
85
- const ext = mime === 'image/png' ? 'png' : mime === 'image/webp' ? 'webp' : 'jpg';
86
- const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
87
- const name = filename ? `${id}-${filename.replace(/[^a-zA-Z0-9._-]/g, '_')}` : `${id}.${ext}`;
157
+ const name = 'user.jpg';
88
158
  const avatarsDir = join(publicDir, 'avatars');
89
159
  if (!existsSync(avatarsDir))
90
160
  mkdirSync(avatarsDir, { recursive: true });
91
161
  await writeFile(join(avatarsDir, name), Buffer.from(base64, 'base64'));
92
162
  res.json({ url: `/static/avatars/${name}` });
93
163
  });
164
+ // Font upload
165
+ const FONT_EXTS = new Set(['.ttf', '.otf', '.woff', '.woff2']);
166
+ const fontsDir = join(publicDir, 'fonts');
167
+ if (!existsSync(fontsDir))
168
+ mkdirSync(fontsDir, { recursive: true });
169
+ app.get('/api/fonts', (_req, res) => {
170
+ if (!existsSync(fontsDir)) {
171
+ res.json([]);
172
+ return;
173
+ }
174
+ const fonts = readdirSync(fontsDir).filter(f => FONT_EXTS.has(extname(f).toLowerCase()));
175
+ res.json(fonts.map(f => ({ name: f, url: `/static/fonts/${f}` })));
176
+ });
177
+ app.post('/api/fonts/upload', async (req, res) => {
178
+ const { name, content } = req.body;
179
+ if (!name || !content) {
180
+ res.status(400).json({ error: 'name and content are required' });
181
+ return;
182
+ }
183
+ const ext = extname(name).toLowerCase();
184
+ if (!FONT_EXTS.has(ext)) {
185
+ res.status(400).json({ error: 'Unsupported font format' });
186
+ return;
187
+ }
188
+ const safeName = basename(name).replace(/[^a-zA-Z0-9._-]/g, '_');
189
+ await writeFile(join(fontsDir, safeName), Buffer.from(content, 'base64'));
190
+ res.json({ name: safeName, url: `/static/fonts/${safeName}` });
191
+ });
192
+ app.delete('/api/fonts/:name', (req, res) => {
193
+ const name = basename(req.params.name);
194
+ const ext = extname(name).toLowerCase();
195
+ if (!FONT_EXTS.has(ext)) {
196
+ res.status(400).json({ error: 'Invalid font file' });
197
+ return;
198
+ }
199
+ const filePath = join(fontsDir, name);
200
+ if (!existsSync(filePath)) {
201
+ res.status(404).json({ error: 'Font not found' });
202
+ return;
203
+ }
204
+ import('node:fs').then(fs => fs.unlinkSync(filePath));
205
+ res.json({ ok: true });
206
+ });
94
207
  // User settings
95
208
  app.get('/api/user/settings', (_req, res) => {
96
209
  const settings = getUserSettings();
@@ -113,6 +226,7 @@ app.use('/api/workspaces/:id/issues', issueRouter);
113
226
  app.use('/api/workflows', workflowRouter);
114
227
  app.use('/api/workspaces/:id/commands', commandRouter);
115
228
  app.use('/api/workspaces/:id/code-favorites', codeFavoritesRouter);
229
+ app.use('/api/workspaces/:id/hooks', hooksRouter);
116
230
  app.use('/api/workspaces/:id/agents', agentRouter);
117
231
  app.use('/api/workspaces/:id/tasks', taskRouter);
118
232
  app.use('/api/workspaces/:id/git', gitRouter);
@@ -138,15 +252,19 @@ app.post('/api/git-config', async (req, res) => {
138
252
  }
139
253
  });
140
254
  app.use('/api/workspaces/:id/search', searchRouter);
255
+ app.use('/api/workspaces/:id/database', databaseRouter);
256
+ app.use('/api/workspaces/:id/kanban', kanbanRouter);
141
257
  app.use('/api/workspaces/:id/notifications', notificationRouter);
142
258
  app.use('/api/agents', agentRouter);
143
259
  app.use('/api', llmRouter);
144
260
  app.use('/api/folder', folderRouter);
145
261
  app.use('/api/skills', skillRouter);
146
262
  app.use('/api/prompt-templates', promptTemplateRouter);
263
+ app.use('/api/output-styles', outputStyleRouter);
147
264
  app.use('/api/mcps', mcpRouter);
148
265
  app.use('/api/subscriptions', subscriptionRouter);
149
266
  app.use('/api/speech-recognition', speechRecognitionRouter);
267
+ app.use('/api/agent-commands', agentCommandsRouter);
150
268
  // Serve static web frontend in production (after API routes, before catch-all)
151
269
  const webDir = resolveRuntimeDir('web');
152
270
  if (existsSync(webDir)) {
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-spaces/server",
3
- "version": "0.3.62",
3
+ "version": "0.3.64",
4
4
  "type": "module",
5
5
  "main": "app.js",
6
6
  "packageManager": "pnpm@10.17.1",
@@ -0,0 +1,72 @@
1
+ import { Router } from 'express';
2
+ import { listAgentsWithCommands, listAllCommands, listCommands, getCommand, createCommand, updateCommand, deleteCommand, applyCommandToAgents, } from '../services/agent-commands.js';
3
+ const router = Router();
4
+ router.get('/agents', (_req, res) => {
5
+ res.json(listAgentsWithCommands());
6
+ });
7
+ router.get('/all', (_req, res) => {
8
+ res.json(listAllCommands());
9
+ });
10
+ router.get('/:agentId', (req, res) => {
11
+ const agentId = typeof req.params.agentId === 'string' ? req.params.agentId : req.params.agentId[0];
12
+ res.json(listCommands(agentId));
13
+ });
14
+ router.get('/:agentId/:name', (req, res) => {
15
+ const agentId = typeof req.params.agentId === 'string' ? req.params.agentId : req.params.agentId[0];
16
+ const name = typeof req.params.name === 'string' ? req.params.name : req.params.name[0];
17
+ const group = req.query.group;
18
+ const cmd = getCommand(agentId, name, group);
19
+ if (!cmd) {
20
+ res.status(404).json({ error: 'Command not found' });
21
+ return;
22
+ }
23
+ res.json(cmd);
24
+ });
25
+ router.post('/:agentId', (req, res) => {
26
+ const agentId = typeof req.params.agentId === 'string' ? req.params.agentId : req.params.agentId[0];
27
+ const { name, content, group } = req.body;
28
+ if (!name || !content) {
29
+ res.status(400).json({ error: 'name and content required' });
30
+ return;
31
+ }
32
+ res.json(createCommand(agentId, name, content, group));
33
+ });
34
+ router.put('/:agentId/:name', (req, res) => {
35
+ const agentId = typeof req.params.agentId === 'string' ? req.params.agentId : req.params.agentId[0];
36
+ const name = typeof req.params.name === 'string' ? req.params.name : req.params.name[0];
37
+ const { content, group } = req.body;
38
+ if (!content) {
39
+ res.status(400).json({ error: 'content required' });
40
+ return;
41
+ }
42
+ const cmd = updateCommand(agentId, name, content, group);
43
+ if (!cmd) {
44
+ res.status(404).json({ error: 'Command not found' });
45
+ return;
46
+ }
47
+ res.json(cmd);
48
+ });
49
+ router.delete('/:agentId/:name', (req, res) => {
50
+ const agentId = typeof req.params.agentId === 'string' ? req.params.agentId : req.params.agentId[0];
51
+ const name = typeof req.params.name === 'string' ? req.params.name : req.params.name[0];
52
+ const group = req.query.group;
53
+ const ok = deleteCommand(agentId, name, group);
54
+ if (!ok) {
55
+ res.status(404).json({ error: 'Command not found' });
56
+ return;
57
+ }
58
+ res.json({ success: true });
59
+ });
60
+ router.post('/:agentId/:name/apply', (req, res) => {
61
+ const agentId = typeof req.params.agentId === 'string' ? req.params.agentId : req.params.agentId[0];
62
+ const name = typeof req.params.name === 'string' ? req.params.name : req.params.name[0];
63
+ const { group, agentIds } = req.body;
64
+ if (!Array.isArray(agentIds) || agentIds.length === 0) {
65
+ res.status(400).json({ error: 'agentIds required' });
66
+ return;
67
+ }
68
+ const applied = applyCommandToAgents(agentId, name, group || '', agentIds);
69
+ res.json({ applied });
70
+ });
71
+ export default router;
72
+ //# sourceMappingURL=agent-commands.js.map
@@ -5,6 +5,7 @@ import * as agentService from '../services/agent.js';
5
5
  import * as workspaceService from '../services/workspace.js';
6
6
  import { getThinkingRuntimeConfig } from '../services/llm-model-config.js';
7
7
  import { buildAgentPrompt } from '../ws/agent-prompt.js';
8
+ import { wrapOnEventWithHooks } from '../services/hook-engine.js';
8
9
  const router = Router();
9
10
  router.post('/run', async (req, res) => {
10
11
  const body = req.body;
@@ -78,11 +79,12 @@ router.post('/run', async (req, res) => {
78
79
  skills,
79
80
  configDir,
80
81
  sandboxDirs: preset.sandboxDirs,
81
- onEvent: (event) => {
82
+ outputStyle: body.outputStyle ?? preset.outputStyle,
83
+ onEvent: wrapOnEventWithHooks((event) => {
82
84
  if (event.type === 'output')
83
85
  output.push(event.line);
84
86
  writeSse(res, event.type, serializeRuntimeEvent(event));
85
- },
87
+ }, workspaceId, workspace?.hooksEnabled),
86
88
  });
87
89
  completed = true;
88
90
  const displayOutput = output.length ? output : result.output;
@@ -141,11 +143,17 @@ function prepareSse(res) {
141
143
  res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
142
144
  res.setHeader('Cache-Control', 'no-cache, no-transform');
143
145
  res.setHeader('Connection', 'keep-alive');
146
+ res.setHeader('X-Accel-Buffering', 'no');
144
147
  res.flushHeaders?.();
148
+ res.socket?.setNoDelay?.(true);
145
149
  }
146
150
  function writeSse(res, event, data) {
147
151
  res.write(`event: ${event}\n`);
148
152
  res.write(`data: ${JSON.stringify(data)}\n\n`);
153
+ // Force flush — compression middleware and some proxies buffer small writes
154
+ const flushable = res;
155
+ if (typeof flushable.flush === 'function')
156
+ flushable.flush();
149
157
  }
150
158
  function resolveUserPrompt(body) {
151
159
  const direct = body.prompt ?? body.message;
@@ -1,6 +1,6 @@
1
1
  import { Router } from 'express';
2
2
  import * as agentService from '../services/agent.js';
3
- import { generateAgentDesign } from '../agents/agent-designer.js';
3
+ import { generateAgentDesign, optimizeAgentPrompt } from '../agents/agent-designer.js';
4
4
  const router = Router({ mergeParams: true });
5
5
  router.get('/usage/dashboard', (req, res) => {
6
6
  const days = Number(req.query.days ?? 30);
@@ -36,6 +36,20 @@ router.post('/presets/generate', async (req, res) => {
36
36
  res.status(400).json({ error: err instanceof Error ? err.message : 'agent generation failed' });
37
37
  }
38
38
  });
39
+ router.post('/presets/optimize-prompt', async (req, res) => {
40
+ const { prompt, currentPrompt } = req.body;
41
+ if (!prompt?.trim()) {
42
+ res.status(400).json({ error: 'prompt is required' });
43
+ return;
44
+ }
45
+ try {
46
+ res.json(await optimizeAgentPrompt(prompt, currentPrompt ?? ''));
47
+ }
48
+ catch (err) {
49
+ console.error('[agent-designer] optimize failed', err);
50
+ res.status(400).json({ error: err instanceof Error ? err.message : 'prompt optimization failed' });
51
+ }
52
+ });
39
53
  router.post('/presets/test-connection', async (req, res) => {
40
54
  const workspaceId = req.params.id;
41
55
  const data = req.body;