@agent-spaces/server 0.3.62 → 0.3.63

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 (315) 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/codex-runtime.js +2 -2
  4. package/dist/adapters/langchain-runtime.js +2 -2
  5. package/dist/adapters/open-agent-sdk-runtime.js +2 -2
  6. package/dist/agents/commit-agent.js +1 -0
  7. package/dist/agents/issue-agent-progress.js +4 -2
  8. package/dist/agents/issue-agent-runner.js +5 -5
  9. package/dist/agents/issue-task-controller.js +95 -14
  10. package/dist/app.js +74 -5
  11. package/dist/package.json +1 -1
  12. package/dist/routes/agent-sse.js +4 -2
  13. package/dist/routes/hooks.js +88 -0
  14. package/dist/routes/issue.js +59 -1
  15. package/dist/routes/output-style.js +48 -0
  16. package/dist/routes/prompt-template.js +2 -2
  17. package/dist/routes/skill.js +86 -15
  18. package/dist/routes/task.js +13 -1
  19. package/dist/services/hook-engine.js +118 -0
  20. package/dist/services/issue.js +6 -0
  21. package/dist/services/notification-hub/bot-agent.js +1 -0
  22. package/dist/services/output-style.js +134 -0
  23. package/dist/services/prompt-template.js +2 -2
  24. package/dist/services/skill.js +148 -35
  25. package/dist/storage/hook-store.js +55 -0
  26. package/dist/web/404.html +1 -1
  27. package/dist/web/__next.__PAGE__.txt +4 -4
  28. package/dist/web/__next._full.txt +25 -24
  29. package/dist/web/__next._head.txt +4 -4
  30. package/dist/web/__next._index.txt +13 -13
  31. package/dist/web/__next._tree.txt +2 -2
  32. package/dist/web/_next/static/chunks/0-1bfvfwifh-m.js +1 -0
  33. package/dist/web/_next/static/chunks/0-f~0xmwl__u5.js +1 -0
  34. package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +1 -0
  35. package/dist/web/_next/static/chunks/002_j970b9gdx.js +1 -0
  36. package/dist/web/_next/static/chunks/014x2qbuiszni.js +3 -0
  37. package/dist/web/_next/static/chunks/01iqv28_snwus.js +1 -0
  38. package/dist/web/_next/static/chunks/02c22g~xd-y30.js +19 -0
  39. package/dist/web/_next/static/chunks/02mf61htij8g0.js +31 -0
  40. package/dist/web/_next/static/chunks/03scq1-0ykve3.js +1 -0
  41. package/dist/web/_next/static/chunks/046me66nilkff.js +1 -0
  42. package/dist/web/_next/static/chunks/04v-pqqs-2lvp.css +1 -0
  43. package/dist/web/_next/static/chunks/{0zd1o3u04~qvo.js → 05psi2gtx~bev.js} +7 -7
  44. package/dist/web/_next/static/chunks/{12odetnu-lyrr.js → 06whz1~s_7pva.js} +12 -12
  45. package/dist/web/_next/static/chunks/06w~.izyfylap.js +1 -0
  46. package/dist/web/_next/static/chunks/09t62a89~jesc.js +3 -0
  47. package/dist/web/_next/static/chunks/09y_3krccdd~u.js +1 -0
  48. package/dist/web/_next/static/chunks/{0njy89g5coeyi.js → 0_8dm7bxp18xo.js} +6 -6
  49. package/dist/web/_next/static/chunks/0_e~hmntdfop9.js +1 -0
  50. package/dist/web/_next/static/chunks/0_udc.6.tueey.js +1 -0
  51. package/dist/web/_next/static/chunks/0_vi1a~g4wx46.js +3 -0
  52. package/dist/web/_next/static/chunks/{0rke_patcovgr.js → 0aa6bcdmtpekn.js} +1 -1
  53. package/dist/web/_next/static/chunks/{0tvd~rxgf0oh_.js → 0bbmx45w_h5np.js} +1 -1
  54. package/dist/web/_next/static/chunks/0cke33d38fnby.js +90 -0
  55. package/dist/web/_next/static/chunks/{07a0rktf_nr5h.js → 0ctg5qmw7uu.1.js} +2 -2
  56. package/dist/web/_next/static/chunks/0cyq~8xb~r5fc.js +1 -0
  57. package/dist/web/_next/static/chunks/0ewceguykiut5.js +1 -0
  58. package/dist/web/_next/static/chunks/0fxa1edqr7dve.js +1 -0
  59. package/dist/web/_next/static/chunks/{0202ia13sijwb.js → 0h18ej5yf974e.js} +1 -1
  60. package/dist/web/_next/static/chunks/0hra80eyuu37u.js +1 -0
  61. package/dist/web/_next/static/chunks/0i39jifmxla7q.js +1 -0
  62. package/dist/web/_next/static/chunks/0ie7y4k2ncvnn.js +1 -0
  63. package/dist/web/_next/static/chunks/0igc~uli58ncw.js +2 -0
  64. package/dist/web/_next/static/chunks/0kof5qdg8c2-k.js +71 -0
  65. package/dist/web/_next/static/chunks/{08o-zmr-40r5g.js → 0m11vvph7q94-.js} +1 -1
  66. package/dist/web/_next/static/chunks/0msb2mi3hiu5_.js +67 -0
  67. package/dist/web/_next/static/chunks/0np.d~hc1-pmh.js +4 -0
  68. package/dist/web/_next/static/chunks/{0qpq0~_58fe9a.js → 0oaq67r7ix.vg.js} +1 -1
  69. package/dist/web/_next/static/chunks/0ogpc3f3keopc.js +3 -0
  70. package/dist/web/_next/static/chunks/{0d_dp_4ofz0l3.css → 0ojcao3hdm36s.css} +0 -1
  71. package/dist/web/_next/static/chunks/0p1n8bvfnpl41.js +1 -0
  72. package/dist/web/_next/static/chunks/{0gig.k.rq8d0x.js → 0ppr271hz0xoq.js} +1 -1
  73. package/dist/web/_next/static/chunks/0s_dva~eh2yhi.js +3 -0
  74. package/dist/web/_next/static/chunks/0typj55ox8d5i.js +1 -0
  75. package/dist/web/_next/static/chunks/0w2p4ldi2aymp.js +1 -0
  76. package/dist/web/_next/static/chunks/{0..g0jl-8qup7.js → 0xoo17yef_b8g.js} +1 -1
  77. package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +1 -0
  78. package/dist/web/_next/static/chunks/0y09i51u6ixq5.js +1 -0
  79. package/dist/web/_next/static/chunks/0za1r07-6az6w.js +1 -0
  80. package/dist/web/_next/static/chunks/0zc0xgp5ourcn.js +1 -0
  81. package/dist/web/_next/static/chunks/0zmhdridea1s5.js +90 -0
  82. package/dist/web/_next/static/chunks/0~u.5r3-t7179.js +1 -0
  83. package/dist/web/_next/static/chunks/10.alq.6stmld.js +1 -0
  84. package/dist/web/_next/static/chunks/11-czmcci_55y.js +1 -0
  85. package/dist/web/_next/static/chunks/11b3zgk1etlkw.js +7 -0
  86. package/dist/web/_next/static/chunks/11k-.49r~1mfm.js +1 -0
  87. package/dist/web/_next/static/chunks/11qp8r5dotf7d.js +1 -0
  88. package/dist/web/_next/static/chunks/{0k.8qdk7oi_os.js → 128ugqd34tr_-.js} +1 -1
  89. package/dist/web/_next/static/chunks/12mxlicp247c8.js +1 -0
  90. package/dist/web/_next/static/chunks/135w27dd8c19s.js +5 -0
  91. package/dist/web/_next/static/chunks/13~y-b.b9rrw4.js +1 -0
  92. package/dist/web/_next/static/chunks/{0jokpgh485~28.js → 14hqmid8q4apf.js} +11 -11
  93. package/dist/web/_next/static/chunks/16sg-lflc8csx.js +1 -0
  94. package/dist/web/_next/static/chunks/176dc-dtokxxi.js +16 -0
  95. package/dist/web/_next/static/chunks/17g-0pqre.anw.js +1 -0
  96. package/dist/web/_next/static/chunks/17oc2l.ekcs8b.css +1 -0
  97. package/dist/web/_next/static/chunks/{turbopack-0lrdxynxb9-1t.js → turbopack-0ndm2zc_pdptk.js} +1 -1
  98. package/dist/web/_not-found/__next._full.txt +29 -30
  99. package/dist/web/_not-found/__next._head.txt +4 -4
  100. package/dist/web/_not-found/__next._index.txt +13 -13
  101. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
  102. package/dist/web/_not-found/__next._not-found.txt +3 -3
  103. package/dist/web/_not-found/__next._tree.txt +2 -2
  104. package/dist/web/_not-found.html +1 -1
  105. package/dist/web/_not-found.txt +29 -30
  106. package/dist/web/index.html +1 -1
  107. package/dist/web/index.txt +25 -24
  108. package/dist/web/login/__next._full.txt +29 -29
  109. package/dist/web/login/__next._head.txt +4 -4
  110. package/dist/web/login/__next._index.txt +13 -13
  111. package/dist/web/login/__next._tree.txt +2 -2
  112. package/dist/web/login/__next.login.__PAGE__.txt +4 -4
  113. package/dist/web/login/__next.login.txt +3 -3
  114. package/dist/web/login.html +1 -1
  115. package/dist/web/login.txt +29 -29
  116. package/dist/web/settings/__next._full.txt +28 -28
  117. package/dist/web/settings/__next._head.txt +4 -4
  118. package/dist/web/settings/__next._index.txt +13 -13
  119. package/dist/web/settings/__next._tree.txt +2 -2
  120. package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
  121. package/dist/web/settings/__next.settings.txt +5 -5
  122. package/dist/web/settings/agents/__next._full.txt +24 -24
  123. package/dist/web/settings/agents/__next._head.txt +4 -4
  124. package/dist/web/settings/agents/__next._index.txt +13 -13
  125. package/dist/web/settings/agents/__next._tree.txt +2 -2
  126. package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
  127. package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
  128. package/dist/web/settings/agents/__next.settings.txt +5 -5
  129. package/dist/web/settings/agents.html +1 -1
  130. package/dist/web/settings/agents.txt +24 -24
  131. package/dist/web/settings/mcps/__next._full.txt +24 -24
  132. package/dist/web/settings/mcps/__next._head.txt +4 -4
  133. package/dist/web/settings/mcps/__next._index.txt +13 -13
  134. package/dist/web/settings/mcps/__next._tree.txt +2 -2
  135. package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
  136. package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
  137. package/dist/web/settings/mcps/__next.settings.txt +5 -5
  138. package/dist/web/settings/mcps.html +1 -1
  139. package/dist/web/settings/mcps.txt +24 -24
  140. package/dist/web/settings/models/__next._full.txt +24 -24
  141. package/dist/web/settings/models/__next._head.txt +4 -4
  142. package/dist/web/settings/models/__next._index.txt +13 -13
  143. package/dist/web/settings/models/__next._tree.txt +2 -2
  144. package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
  145. package/dist/web/settings/models/__next.settings.models.txt +3 -3
  146. package/dist/web/settings/models/__next.settings.txt +5 -5
  147. package/dist/web/settings/models.html +1 -1
  148. package/dist/web/settings/models.txt +24 -24
  149. package/dist/web/settings/output-styles/__next._full.txt +43 -0
  150. package/dist/web/settings/output-styles/__next._head.txt +6 -0
  151. package/dist/web/settings/output-styles/__next._index.txt +15 -0
  152. package/dist/web/settings/output-styles/__next._tree.txt +8 -0
  153. package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +9 -0
  154. package/dist/web/settings/output-styles/__next.settings.output-styles.txt +5 -0
  155. package/dist/web/settings/output-styles/__next.settings.txt +7 -0
  156. package/dist/web/settings/output-styles.html +1 -0
  157. package/dist/web/settings/output-styles.txt +43 -0
  158. package/dist/web/settings/prompts/__next._full.txt +24 -24
  159. package/dist/web/settings/prompts/__next._head.txt +4 -4
  160. package/dist/web/settings/prompts/__next._index.txt +13 -13
  161. package/dist/web/settings/prompts/__next._tree.txt +2 -2
  162. package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +4 -4
  163. package/dist/web/settings/prompts/__next.settings.prompts.txt +3 -3
  164. package/dist/web/settings/prompts/__next.settings.txt +5 -5
  165. package/dist/web/settings/prompts.html +1 -1
  166. package/dist/web/settings/prompts.txt +24 -24
  167. package/dist/web/settings/providers/__next._full.txt +24 -24
  168. package/dist/web/settings/providers/__next._head.txt +4 -4
  169. package/dist/web/settings/providers/__next._index.txt +13 -13
  170. package/dist/web/settings/providers/__next._tree.txt +2 -2
  171. package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
  172. package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
  173. package/dist/web/settings/providers/__next.settings.txt +5 -5
  174. package/dist/web/settings/providers.html +1 -1
  175. package/dist/web/settings/providers.txt +24 -24
  176. package/dist/web/settings/skills/__next._full.txt +24 -24
  177. package/dist/web/settings/skills/__next._head.txt +4 -4
  178. package/dist/web/settings/skills/__next._index.txt +13 -13
  179. package/dist/web/settings/skills/__next._tree.txt +2 -2
  180. package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
  181. package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
  182. package/dist/web/settings/skills/__next.settings.txt +5 -5
  183. package/dist/web/settings/skills.html +1 -1
  184. package/dist/web/settings/skills.txt +24 -24
  185. package/dist/web/settings.html +1 -1
  186. package/dist/web/settings.txt +28 -28
  187. package/dist/web/workflows/__next._full.txt +32 -31
  188. package/dist/web/workflows/__next._head.txt +4 -4
  189. package/dist/web/workflows/__next._index.txt +13 -13
  190. package/dist/web/workflows/__next._tree.txt +2 -2
  191. package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
  192. package/dist/web/workflows/__next.workflows.txt +3 -3
  193. package/dist/web/workflows.html +1 -1
  194. package/dist/web/workflows.txt +32 -31
  195. package/dist/web/workspace/_/__next._full.txt +30 -71
  196. package/dist/web/workspace/_/__next._head.txt +4 -4
  197. package/dist/web/workspace/_/__next._index.txt +13 -13
  198. package/dist/web/workspace/_/__next._tree.txt +2 -17
  199. package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -18
  200. package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
  201. package/dist/web/workspace/_/__next.workspace.txt +3 -3
  202. package/dist/web/workspace/_.html +1 -1
  203. package/dist/web/workspace/_.txt +30 -71
  204. package/dist/web/workspaces/__next._full.txt +31 -32
  205. package/dist/web/workspaces/__next._head.txt +4 -4
  206. package/dist/web/workspaces/__next._index.txt +13 -13
  207. package/dist/web/workspaces/__next._tree.txt +2 -2
  208. package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
  209. package/dist/web/workspaces/__next.workspaces.txt +3 -3
  210. package/dist/web/workspaces.html +1 -1
  211. package/dist/web/workspaces.txt +31 -32
  212. package/dist/ws/agent-runner.js +4 -2
  213. package/package.json +1 -1
  214. package/public/output-styles/carmack-mode.md +381 -0
  215. package/public/output-styles/codex-rigor-mode.md +114 -0
  216. package/public/output-styles/dhh-mode.md +265 -0
  217. package/public/output-styles/evan-you-mode.md +539 -0
  218. package/public/output-styles/index.json +37 -0
  219. package/public/output-styles/jobs-mode.md +369 -0
  220. package/public/output-styles/linus-mode.md +135 -0
  221. package/public/output-styles/uncle-bob-mode.md +221 -0
  222. package/public/prompt/andrej-karpathy-skills.md +65 -0
  223. package/public/prompt/claude-token-efficient-coding.md +35 -0
  224. package/public/prompt/index.json +12 -0
  225. package/public/skills/index.json +92 -0
  226. package/public/skills/planning-with-files/planning-with-files-zh/SKILL.md +243 -0
  227. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.ps1 +44 -0
  228. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.sh +46 -0
  229. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.ps1 +124 -0
  230. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.sh +124 -0
  231. package/public/skills/planning-with-files/planning-with-files-zh/scripts/session-catchup.py +438 -0
  232. package/public/skills/planning-with-files/planning-with-files-zh/templates/findings.md +29 -0
  233. package/public/skills/planning-with-files/planning-with-files-zh/templates/progress.md +40 -0
  234. package/public/skills/planning-with-files/planning-with-files-zh/templates/task_plan.md +58 -0
  235. package/public/skills/superpowers/brainstorming/SKILL.md +164 -0
  236. package/public/skills/superpowers/brainstorming/scripts/frame-template.html +214 -0
  237. package/public/skills/superpowers/brainstorming/scripts/helper.js +88 -0
  238. package/public/skills/superpowers/brainstorming/scripts/server.cjs +354 -0
  239. package/public/skills/superpowers/brainstorming/scripts/start-server.sh +148 -0
  240. package/public/skills/superpowers/brainstorming/scripts/stop-server.sh +56 -0
  241. package/public/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
  242. package/public/skills/superpowers/brainstorming/visual-companion.md +287 -0
  243. package/public/skills/superpowers/dispatching-parallel-agents/SKILL.md +182 -0
  244. package/public/skills/superpowers/executing-plans/SKILL.md +70 -0
  245. package/public/skills/superpowers/finishing-a-development-branch/SKILL.md +251 -0
  246. package/public/skills/superpowers/receiving-code-review/SKILL.md +213 -0
  247. package/public/skills/superpowers/requesting-code-review/SKILL.md +103 -0
  248. package/public/skills/superpowers/requesting-code-review/code-reviewer.md +168 -0
  249. package/public/skills/superpowers/subagent-driven-development/SKILL.md +279 -0
  250. package/public/skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +25 -0
  251. package/public/skills/superpowers/subagent-driven-development/implementer-prompt.md +113 -0
  252. package/public/skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  253. package/public/skills/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
  254. package/public/skills/superpowers/systematic-debugging/SKILL.md +296 -0
  255. package/public/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
  256. package/public/skills/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
  257. package/public/skills/superpowers/systematic-debugging/defense-in-depth.md +122 -0
  258. package/public/skills/superpowers/systematic-debugging/find-polluter.sh +63 -0
  259. package/public/skills/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
  260. package/public/skills/superpowers/systematic-debugging/test-academic.md +14 -0
  261. package/public/skills/superpowers/systematic-debugging/test-pressure-1.md +58 -0
  262. package/public/skills/superpowers/systematic-debugging/test-pressure-2.md +68 -0
  263. package/public/skills/superpowers/systematic-debugging/test-pressure-3.md +69 -0
  264. package/public/skills/superpowers/test-driven-development/SKILL.md +371 -0
  265. package/public/skills/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
  266. package/public/skills/superpowers/using-git-worktrees/SKILL.md +215 -0
  267. package/public/skills/superpowers/using-superpowers/SKILL.md +117 -0
  268. package/public/skills/superpowers/using-superpowers/references/codex-tools.md +59 -0
  269. package/public/skills/superpowers/using-superpowers/references/copilot-tools.md +42 -0
  270. package/public/skills/superpowers/using-superpowers/references/gemini-tools.md +51 -0
  271. package/public/skills/superpowers/verification-before-completion/SKILL.md +139 -0
  272. package/public/skills/superpowers/writing-plans/SKILL.md +152 -0
  273. package/public/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
  274. package/public/skills/superpowers/writing-skills/SKILL.md +655 -0
  275. package/public/skills/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
  276. package/public/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  277. package/public/skills/superpowers/writing-skills/graphviz-conventions.dot +172 -0
  278. package/public/skills/superpowers/writing-skills/persuasion-principles.md +187 -0
  279. package/public/skills/superpowers/writing-skills/render-graphs.js +168 -0
  280. package/public/skills/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
  281. package/dist/web/_next/static/chunks/0-81wi7xr2nd-.js +0 -270
  282. package/dist/web/_next/static/chunks/00lca9lsasdm7.js +0 -1
  283. package/dist/web/_next/static/chunks/01gi~q0c6ez6..js +0 -1
  284. package/dist/web/_next/static/chunks/02shswpmybici.js +0 -1
  285. package/dist/web/_next/static/chunks/05tx6hzdtkgi9.js +0 -2
  286. package/dist/web/_next/static/chunks/07nbyndvzftr1.js +0 -3
  287. package/dist/web/_next/static/chunks/0bn~onkv~9xza.js +0 -1
  288. package/dist/web/_next/static/chunks/0g-0n6glz_z6w.js +0 -1
  289. package/dist/web/_next/static/chunks/0gyede80jpy3n.js +0 -4
  290. package/dist/web/_next/static/chunks/0hrbuvzuxrjfl.js +0 -1
  291. package/dist/web/_next/static/chunks/0i51q.5s_-.vh.css +0 -1
  292. package/dist/web/_next/static/chunks/0qf163pbrwy4z.js +0 -1
  293. package/dist/web/_next/static/chunks/0rnt-f3pjxb-d.js +0 -5
  294. package/dist/web/_next/static/chunks/0tgbcgsca9mrg.js +0 -1
  295. package/dist/web/_next/static/chunks/0tyhv6.y7~yxd.js +0 -1
  296. package/dist/web/_next/static/chunks/0u7_qd9hzqwac.js +0 -1
  297. package/dist/web/_next/static/chunks/0vuvql8rloda5.js +0 -1
  298. package/dist/web/_next/static/chunks/0wv0h27jafag4.js +0 -1
  299. package/dist/web/_next/static/chunks/0wwvc4zc2q6bn.js +0 -1
  300. package/dist/web/_next/static/chunks/0xmmk3vebw8xs.js +0 -1
  301. package/dist/web/_next/static/chunks/0xwqf.llmm_u2.js +0 -31
  302. package/dist/web/_next/static/chunks/0yo22_w53mo~5.js +0 -1
  303. package/dist/web/_next/static/chunks/12c0jp0qvlr1t.js +0 -1
  304. package/dist/web/_next/static/chunks/12pg1nn3v~~5k.js +0 -1
  305. package/dist/web/_next/static/chunks/16cyr8ilpx1nn.js +0 -1
  306. package/public/avatars/1777813826407-bea0ja-minimax.svg +0 -1
  307. package/public/avatars/1777813967088-3xlvd0-minimax.svg +0 -1
  308. package/public/avatars/1777814041714-yp0qeq-minimax.svg +0 -1
  309. package/public/avatars/1777904986095-rg26je-icon.png +0 -0
  310. package/public/avatars/1778953228323-5je54x-user.jpg +0 -0
  311. package/public/avatars/1778954057880-g01q6y-user.jpg +0 -0
  312. /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → OoXAsPtrUWjC1l898FSvI}/_buildManifest.js +0 -0
  313. /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → OoXAsPtrUWjC1l898FSvI}/_clientMiddlewareManifest.js +0 -0
  314. /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → OoXAsPtrUWjC1l898FSvI}/_ssgManifest.js +0 -0
  315. /package/public/avatars/{1777815865622-08wp9m-user.jpg → user.jpg} +0 -0
@@ -1,7 +1,19 @@
1
+ import { resolveOutputStyleContent } from '../services/output-style.js';
1
2
  export function summarizeResult(text) {
2
3
  const normalized = text.trim().replace(/\s+/g, ' ');
3
4
  if (!normalized)
4
5
  return 'Completed agent execution';
5
6
  return normalized.length > 160 ? `${normalized.slice(0, 157)}...` : normalized;
6
7
  }
8
+ export function appendOutputStyleToPrompt(prompt, outputStyle) {
9
+ const style = resolveOutputStyleContent(outputStyle)?.trim();
10
+ if (!style)
11
+ return prompt;
12
+ return [
13
+ prompt.trimEnd(),
14
+ '',
15
+ 'Output style instructions:',
16
+ style,
17
+ ].join('\n');
18
+ }
7
19
  //# sourceMappingURL=agent-runtime-types.js.map
@@ -1,6 +1,7 @@
1
1
  import { join } from 'node:path';
2
2
  import { query } from '@anthropic-ai/claude-agent-sdk';
3
3
  import { summarizeResult } from '../agent-runtime-types.js';
4
+ import { prepareClaudeOutputStyleFile } from '../../services/output-style.js';
4
5
  import { normalizeAdditionalDirectories, normalizePermissionMode, normalizeSkillNames, prepareConfigDir, resolveBundledClaudeExecutable, buildEnv, normalizeMcpServers } from './sdk-config.js';
5
6
  import { startClaudeAdapterIfNeeded, getClaudeCodeModel } from './adapter-pool.js';
6
7
  import { extractThinkingEvents, extractToolUseEvents, extractToolResultEvent, logToolDebug, formatMessage, isAskUserQuestionAutoResult, countUsageTokens, formatUsageLine, normalizeUsage } from './message-format.js';
@@ -25,6 +26,7 @@ export class ClaudeCodeRuntime {
25
26
  if (configDir)
26
27
  prepareConfigDir(configDir, agentDir);
27
28
  const skillNames = normalizeSkillNames(options?.skills, configDir);
29
+ const outputStyleFile = configDir ? prepareClaudeOutputStyleFile(configDir, options?.outputStyle) : undefined;
28
30
  const claudeExecutable = resolveBundledClaudeExecutable();
29
31
  this.adapterRun = await startClaudeAdapterIfNeeded(this.config);
30
32
  const baseURL = this.adapterRun?.url ?? this.config.baseURL;
@@ -46,6 +48,7 @@ export class ClaudeCodeRuntime {
46
48
  tools: { type: 'preset', preset: 'claude_code' },
47
49
  mcpServers: sdkMcpServers,
48
50
  skills: skillNames,
51
+ outputStyle: outputStyleFile,
49
52
  managedSettings: {
50
53
  strictPluginOnlyCustomization: ['mcp'],
51
54
  },
@@ -1,7 +1,7 @@
1
1
  import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
2
2
  import { basename, extname, join } from 'node:path';
3
3
  import { Codex } from '@openai/codex-sdk';
4
- import { summarizeResult } from './agent-runtime-types.js';
4
+ import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
5
5
  /**
6
6
  * Runtime backed by OpenAI's Codex SDK.
7
7
  * Spawns the bundled Codex CLI and consumes its structured JSONL event stream.
@@ -48,7 +48,7 @@ export class CodexRuntime {
48
48
  const thread = options?.resumeSessionId
49
49
  ? codex.resumeThread(options.resumeSessionId, threadOptions)
50
50
  : codex.startThread(threadOptions);
51
- const { events } = await thread.runStreamed(prompt, {
51
+ const { events } = await thread.runStreamed(appendOutputStyleToPrompt(prompt, options?.outputStyle), {
52
52
  signal: this.abortController.signal,
53
53
  });
54
54
  let resultText = '';
@@ -1,6 +1,6 @@
1
1
  import { createAgent, initChatModel, tool } from 'langchain';
2
2
  import { z } from 'zod';
3
- import { summarizeResult } from './agent-runtime-types.js';
3
+ import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
4
4
  /**
5
5
  * Runtime backed by LangChain.js.
6
6
  * Uses LangChain's provider-neutral createAgent API and adapts Agent Spaces tools.
@@ -27,7 +27,7 @@ export class LangChainRuntime {
27
27
  tools: buildLangChainTools(options?.functionTools, output, options),
28
28
  systemPrompt: options?.systemPrompt,
29
29
  });
30
- const result = await agent.invoke({ messages: [{ role: 'user', content: prompt }] }, {
30
+ const result = await agent.invoke({ messages: [{ role: 'user', content: appendOutputStyleToPrompt(prompt, options?.outputStyle) }] }, {
31
31
  signal: this.abortController?.signal,
32
32
  recursionLimit: options?.maxTurns ? Math.max(2, options.maxTurns * 2 + 1) : undefined,
33
33
  });
@@ -1,5 +1,5 @@
1
1
  import { createAgent } from '@codeany/open-agent-sdk';
2
- import { summarizeResult } from './agent-runtime-types.js';
2
+ import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
3
3
  /**
4
4
  * Runtime backed by @codeany/open-agent-sdk.
5
5
  * Runs the agent loop in-process with the SDK's built-in tools.
@@ -35,7 +35,7 @@ export class OpenAgentSdkRuntime {
35
35
  });
36
36
  d('agent created, sending prompt...');
37
37
  d('tool debug | open-agent-sdk runtime does not expose per-tool stream events through prompt(); only final text/usage is available here');
38
- const result = await this.agent.prompt(prompt);
38
+ const result = await this.agent.prompt(appendOutputStyleToPrompt(prompt, options?.outputStyle));
39
39
  const elapsed = Date.now() - startTime;
40
40
  const inputTokens = result.usage.input_tokens;
41
41
  const outputTokens = result.usage.output_tokens;
@@ -42,6 +42,7 @@ export async function runCommitAgent(workspaceId) {
42
42
  }), workingDir, {
43
43
  maxTurns: 1,
44
44
  systemPrompt,
45
+ outputStyle: commitAgent.outputStyle,
45
46
  });
46
47
  agentService.complete(workspaceId, session.id, result.success ? undefined : result.error, {
47
48
  runtime: commitAgent.runtimeKind,
@@ -74,7 +74,9 @@ export function createIssueAgentProgress(workspaceId, issue, preset, agentSessio
74
74
  return { message, comment };
75
75
  }
76
76
  export function completeIssueAgentProgress(workspaceId, issue, progress, summary, output, metadata) {
77
- const content = output.join('\n').trim() || summary;
77
+ const parts = metadata.parts;
78
+ const finalText = [...(parts ?? [])].reverse().find((part) => part.type === 'text')?.text.trim();
79
+ const content = finalText || summary.trim() || output.join('\n').trim();
78
80
  if (!content.trim())
79
81
  return;
80
82
  const message = messageService.updateMessage(workspaceId, issue.channelId, progress.message.id, {
@@ -88,7 +90,7 @@ export function completeIssueAgentProgress(workspaceId, issue, progress, summary
88
90
  summary,
89
91
  duration: metadata.duration,
90
92
  },
91
- parts: metadata.parts,
93
+ parts,
92
94
  });
93
95
  if (message)
94
96
  broadcastToWorkspace(workspaceId, 'channel.message.updated', message);
@@ -9,6 +9,11 @@ export async function runIssueAutomation(workspaceId, issueId, ctx) {
9
9
  console.warn(`[issue-runner] issue not found workspaceId=${workspaceId} issueId=${issueId}`);
10
10
  return;
11
11
  }
12
+ const tasks = taskService.list(workspaceId, issueId);
13
+ if (tasks.length > 0) {
14
+ await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
15
+ return;
16
+ }
12
17
  // Workflow template branch
13
18
  if (issue.workflowId) {
14
19
  const template = workflowService.getWorkflow(issue.workflowId);
@@ -29,11 +34,6 @@ export async function runIssueAutomation(workspaceId, issueId, ctx) {
29
34
  return;
30
35
  }
31
36
  }
32
- const tasks = taskService.list(workspaceId, issueId);
33
- if (tasks.length > 0) {
34
- await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
35
- return;
36
- }
37
37
  console.warn(`[issue-runner] no workflow configured for issue workspaceId=${workspaceId} issueId=${issueId}`);
38
38
  }
39
39
  export function hasActiveIssueAutomation(workspaceId) {
@@ -9,7 +9,9 @@ import { createIssueFunctionTools } from '../services/builtin-tools.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, 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,8 +22,10 @@ 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';
@@ -65,6 +67,73 @@ app.use('/api', authMiddleware);
65
67
  // Serve static files from public/
66
68
  const publicDir = resolveRuntimeDir('public');
67
69
  app.use('/public', express.static(publicDir));
70
+ // Scan public/prompt/ and generate index.json for the prompt store
71
+ function scanPromptStore() {
72
+ const promptDir = join(publicDir, 'prompt');
73
+ if (!existsSync(promptDir))
74
+ return;
75
+ const files = readdirSync(promptDir).filter((f) => f.endsWith('.md'));
76
+ const index = files.map((filename) => {
77
+ const id = basename(filename, '.md');
78
+ const content = readFileSync(join(promptDir, filename), 'utf-8');
79
+ const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
80
+ const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
81
+ return { id, name, filename };
82
+ });
83
+ writeFileSync(join(promptDir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
84
+ console.log(`[prompt-store] scanned ${index.length} templates`);
85
+ }
86
+ scanPromptStore();
87
+ // Scan public/output-styles/ and generate index.json
88
+ function scanOutputStyleStore() {
89
+ const dir = join(publicDir, 'output-styles');
90
+ if (!existsSync(dir))
91
+ return;
92
+ const files = readdirSync(dir).filter((f) => f.endsWith('.md'));
93
+ const index = files.map((filename) => {
94
+ const id = basename(filename, '.md');
95
+ const content = readFileSync(join(dir, filename), 'utf-8');
96
+ const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
97
+ const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
98
+ return { id, name, filename };
99
+ });
100
+ writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
101
+ console.log(`[output-style-store] scanned ${index.length} templates`);
102
+ }
103
+ scanOutputStyleStore();
104
+ // Scan public/skills/{group}/{skill-name}/SKILL.md and generate index.json
105
+ function scanSkillStore() {
106
+ const dir = join(publicDir, 'skills');
107
+ if (!existsSync(dir))
108
+ return;
109
+ const index = [];
110
+ for (const groupEntry of readdirSync(dir, { withFileTypes: true })) {
111
+ if (!groupEntry.isDirectory())
112
+ continue;
113
+ const group = groupEntry.name;
114
+ const groupDir = join(dir, group);
115
+ for (const skillEntry of readdirSync(groupDir, { withFileTypes: true })) {
116
+ if (!skillEntry.isDirectory())
117
+ continue;
118
+ const skillName = skillEntry.name;
119
+ const skillFile = join(groupDir, skillName, 'SKILL.md');
120
+ if (!existsSync(skillFile))
121
+ continue;
122
+ const content = readFileSync(skillFile, 'utf-8');
123
+ const fm = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
124
+ let name = skillName;
125
+ if (fm) {
126
+ const nameLine = fm[1].split(/\r?\n/).find((l) => /^\s*name\s*:/i.test(l));
127
+ if (nameLine)
128
+ name = nameLine.split(':', 2)[1].trim() || skillName;
129
+ }
130
+ index.push({ id: skillName, name, group, path: `${group}/${skillName}` });
131
+ }
132
+ }
133
+ writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
134
+ console.log(`[skill-store] scanned ${index.length} skills`);
135
+ }
136
+ scanSkillStore();
68
137
  app.get('/api/health', (_req, res) => {
69
138
  res.json({ status: 'ok', timestamp: new Date().toISOString(), platform: process.platform });
70
139
  });
@@ -82,9 +151,7 @@ app.post('/api/upload/avatar', async (req, res) => {
82
151
  return;
83
152
  }
84
153
  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}`;
154
+ const name = 'user.jpg';
88
155
  const avatarsDir = join(publicDir, 'avatars');
89
156
  if (!existsSync(avatarsDir))
90
157
  mkdirSync(avatarsDir, { recursive: true });
@@ -113,6 +180,7 @@ app.use('/api/workspaces/:id/issues', issueRouter);
113
180
  app.use('/api/workflows', workflowRouter);
114
181
  app.use('/api/workspaces/:id/commands', commandRouter);
115
182
  app.use('/api/workspaces/:id/code-favorites', codeFavoritesRouter);
183
+ app.use('/api/workspaces/:id/hooks', hooksRouter);
116
184
  app.use('/api/workspaces/:id/agents', agentRouter);
117
185
  app.use('/api/workspaces/:id/tasks', taskRouter);
118
186
  app.use('/api/workspaces/:id/git', gitRouter);
@@ -144,6 +212,7 @@ app.use('/api', llmRouter);
144
212
  app.use('/api/folder', folderRouter);
145
213
  app.use('/api/skills', skillRouter);
146
214
  app.use('/api/prompt-templates', promptTemplateRouter);
215
+ app.use('/api/output-styles', outputStyleRouter);
147
216
  app.use('/api/mcps', mcpRouter);
148
217
  app.use('/api/subscriptions', subscriptionRouter);
149
218
  app.use('/api/speech-recognition', speechRecognitionRouter);
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.63",
4
4
  "type": "module",
5
5
  "main": "app.js",
6
6
  "packageManager": "pnpm@10.17.1",
@@ -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;
@@ -0,0 +1,88 @@
1
+ import { Router } from 'express';
2
+ import * as store from '../storage/hook-store.js';
3
+ const router = Router({ mergeParams: true });
4
+ router.get('/', (req, res) => {
5
+ try {
6
+ res.json(store.listHooks(req.params.id));
7
+ }
8
+ catch (error) {
9
+ res.status(500).json({ error: error.message });
10
+ }
11
+ });
12
+ router.get('/:name', (req, res) => {
13
+ try {
14
+ const hook = store.getHook(req.params.id, req.params.name);
15
+ if (!hook) {
16
+ res.status(404).json({ error: 'Hook not found' });
17
+ return;
18
+ }
19
+ res.json(hook);
20
+ }
21
+ catch (error) {
22
+ res.status(500).json({ error: error.message });
23
+ }
24
+ });
25
+ router.post('/', (req, res) => {
26
+ try {
27
+ const config = req.body;
28
+ if (!config.name) {
29
+ res.status(400).json({ error: 'name required' });
30
+ return;
31
+ }
32
+ store.saveHook(req.params.id, config);
33
+ res.status(201).json(config);
34
+ }
35
+ catch (error) {
36
+ res.status(400).json({ error: error.message });
37
+ }
38
+ });
39
+ router.put('/:name', (req, res) => {
40
+ try {
41
+ const config = req.body;
42
+ config.name = req.params.name;
43
+ store.saveHook(req.params.id, config);
44
+ res.json(config);
45
+ }
46
+ catch (error) {
47
+ res.status(400).json({ error: error.message });
48
+ }
49
+ });
50
+ router.delete('/:name', (req, res) => {
51
+ try {
52
+ store.deleteHook(req.params.id, req.params.name);
53
+ res.status(204).send();
54
+ }
55
+ catch (error) {
56
+ res.status(400).json({ error: error.message });
57
+ }
58
+ });
59
+ router.post('/upload', (req, res) => {
60
+ try {
61
+ const { content } = req.body;
62
+ if (!content || typeof content !== 'string') {
63
+ res.status(400).json({ error: 'content (string) required' });
64
+ return;
65
+ }
66
+ const config = store.uploadHook(req.params.id, content);
67
+ res.status(201).json(config);
68
+ }
69
+ catch (error) {
70
+ res.status(400).json({ error: error.message });
71
+ }
72
+ });
73
+ router.post('/:name/apply', (req, res) => {
74
+ try {
75
+ const { targetWorkspaceId } = req.body;
76
+ if (!targetWorkspaceId) {
77
+ res.status(400).json({ error: 'targetWorkspaceId required' });
78
+ return;
79
+ }
80
+ store.applyToWorkspace(req.params.id, req.params.name, targetWorkspaceId);
81
+ res.json({ ok: true });
82
+ }
83
+ catch (error) {
84
+ res.status(400).json({ error: error.message });
85
+ }
86
+ });
87
+ export default router;
88
+ //# sourceMappingURL=hooks.js.map