@agent-spaces/server 0.3.61 → 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 (327) hide show
  1. package/dist/adapters/agent-runtime-types.js +12 -0
  2. package/dist/adapters/claude-code-runtime/index.js +22 -0
  3. package/dist/adapters/claude-code-runtime/sdk-config.js +34 -10
  4. package/dist/adapters/codex-runtime.js +2 -2
  5. package/dist/adapters/git.js +29 -13
  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-message-parts.js +27 -3
  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 +95 -14
  13. package/dist/app.js +74 -5
  14. package/dist/package.json +1 -1
  15. package/dist/routes/agent-sse.js +4 -2
  16. package/dist/routes/channel.js +21 -4
  17. package/dist/routes/file.js +87 -1
  18. package/dist/routes/hooks.js +88 -0
  19. package/dist/routes/issue.js +59 -1
  20. package/dist/routes/output-style.js +48 -0
  21. package/dist/routes/prompt-template.js +2 -2
  22. package/dist/routes/skill.js +97 -3
  23. package/dist/routes/task.js +13 -1
  24. package/dist/services/agent.js +45 -16
  25. package/dist/services/hook-engine.js +118 -0
  26. package/dist/services/issue.js +6 -0
  27. package/dist/services/notification-hub/bot-agent.js +1 -0
  28. package/dist/services/output-style.js +134 -0
  29. package/dist/services/persistent-agent-context.js +37 -4
  30. package/dist/services/prompt-template.js +2 -2
  31. package/dist/services/skill.js +275 -40
  32. package/dist/storage/hook-store.js +55 -0
  33. package/dist/web/404.html +1 -1
  34. package/dist/web/__next.__PAGE__.txt +4 -4
  35. package/dist/web/__next._full.txt +25 -23
  36. package/dist/web/__next._head.txt +4 -4
  37. package/dist/web/__next._index.txt +13 -13
  38. package/dist/web/__next._tree.txt +2 -2
  39. package/dist/web/_next/static/chunks/0-1bfvfwifh-m.js +1 -0
  40. package/dist/web/_next/static/chunks/0-f~0xmwl__u5.js +1 -0
  41. package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +1 -0
  42. package/dist/web/_next/static/chunks/002_j970b9gdx.js +1 -0
  43. package/dist/web/_next/static/chunks/014x2qbuiszni.js +3 -0
  44. package/dist/web/_next/static/chunks/01iqv28_snwus.js +1 -0
  45. package/dist/web/_next/static/chunks/02c22g~xd-y30.js +19 -0
  46. package/dist/web/_next/static/chunks/02mf61htij8g0.js +31 -0
  47. package/dist/web/_next/static/chunks/03scq1-0ykve3.js +1 -0
  48. package/dist/web/_next/static/chunks/046me66nilkff.js +1 -0
  49. package/dist/web/_next/static/chunks/04v-pqqs-2lvp.css +1 -0
  50. package/dist/web/_next/static/chunks/05f8cnmzqd5wb.js +1 -0
  51. package/dist/web/_next/static/chunks/{0zd1o3u04~qvo.js → 05psi2gtx~bev.js} +7 -7
  52. package/dist/web/_next/static/chunks/{12odetnu-lyrr.js → 06whz1~s_7pva.js} +12 -12
  53. package/dist/web/_next/static/chunks/06w~.izyfylap.js +1 -0
  54. package/dist/web/_next/static/chunks/08kfx8on9oty~.js +1 -0
  55. package/dist/web/_next/static/chunks/09t62a89~jesc.js +3 -0
  56. package/dist/web/_next/static/chunks/09y_3krccdd~u.js +1 -0
  57. package/dist/web/_next/static/chunks/{0njy89g5coeyi.js → 0_8dm7bxp18xo.js} +6 -6
  58. package/dist/web/_next/static/chunks/0_e~hmntdfop9.js +1 -0
  59. package/dist/web/_next/static/chunks/0_udc.6.tueey.js +1 -0
  60. package/dist/web/_next/static/chunks/0_vi1a~g4wx46.js +3 -0
  61. package/dist/web/_next/static/chunks/{05iy4.c-1cfhd.js → 0aa6bcdmtpekn.js} +1 -1
  62. package/dist/web/_next/static/chunks/{0tvd~rxgf0oh_.js → 0bbmx45w_h5np.js} +1 -1
  63. package/dist/web/_next/static/chunks/0cke33d38fnby.js +90 -0
  64. package/dist/web/_next/static/chunks/{0w1iudd1d46sw.js → 0ctg5qmw7uu.1.js} +2 -2
  65. package/dist/web/_next/static/chunks/0cyq~8xb~r5fc.js +1 -0
  66. package/dist/web/_next/static/chunks/0ewceguykiut5.js +1 -0
  67. package/dist/web/_next/static/chunks/0fxa1edqr7dve.js +1 -0
  68. package/dist/web/_next/static/chunks/{0202ia13sijwb.js → 0h18ej5yf974e.js} +1 -1
  69. package/dist/web/_next/static/chunks/0hra80eyuu37u.js +1 -0
  70. package/dist/web/_next/static/chunks/0i39jifmxla7q.js +1 -0
  71. package/dist/web/_next/static/chunks/0ie7y4k2ncvnn.js +1 -0
  72. package/dist/web/_next/static/chunks/0igc~uli58ncw.js +2 -0
  73. package/dist/web/_next/static/chunks/0kof5qdg8c2-k.js +71 -0
  74. package/dist/web/_next/static/chunks/{08o-zmr-40r5g.js → 0m11vvph7q94-.js} +1 -1
  75. package/dist/web/_next/static/chunks/0msb2mi3hiu5_.js +67 -0
  76. package/dist/web/_next/static/chunks/0np.d~hc1-pmh.js +4 -0
  77. package/dist/web/_next/static/chunks/{0qpq0~_58fe9a.js → 0oaq67r7ix.vg.js} +1 -1
  78. package/dist/web/_next/static/chunks/0ogpc3f3keopc.js +3 -0
  79. package/dist/web/_next/static/chunks/{0d_dp_4ofz0l3.css → 0ojcao3hdm36s.css} +0 -1
  80. package/dist/web/_next/static/chunks/0p1n8bvfnpl41.js +1 -0
  81. package/dist/web/_next/static/chunks/{0gig.k.rq8d0x.js → 0ppr271hz0xoq.js} +1 -1
  82. package/dist/web/_next/static/chunks/0s_dva~eh2yhi.js +3 -0
  83. package/dist/web/_next/static/chunks/0typj55ox8d5i.js +1 -0
  84. package/dist/web/_next/static/chunks/0w2p4ldi2aymp.js +1 -0
  85. package/dist/web/_next/static/chunks/{0..g0jl-8qup7.js → 0xoo17yef_b8g.js} +1 -1
  86. package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +1 -0
  87. package/dist/web/_next/static/chunks/0y09i51u6ixq5.js +1 -0
  88. package/dist/web/_next/static/chunks/0za1r07-6az6w.js +1 -0
  89. package/dist/web/_next/static/chunks/0zc0xgp5ourcn.js +1 -0
  90. package/dist/web/_next/static/chunks/0zmhdridea1s5.js +90 -0
  91. package/dist/web/_next/static/chunks/0~u.5r3-t7179.js +1 -0
  92. package/dist/web/_next/static/chunks/10.alq.6stmld.js +1 -0
  93. package/dist/web/_next/static/chunks/11-czmcci_55y.js +1 -0
  94. package/dist/web/_next/static/chunks/11b3zgk1etlkw.js +7 -0
  95. package/dist/web/_next/static/chunks/11k-.49r~1mfm.js +1 -0
  96. package/dist/web/_next/static/chunks/11qp8r5dotf7d.js +1 -0
  97. package/dist/web/_next/static/chunks/128ugqd34tr_-.js +1 -0
  98. package/dist/web/_next/static/chunks/12mxlicp247c8.js +1 -0
  99. package/dist/web/_next/static/chunks/135w27dd8c19s.js +5 -0
  100. package/dist/web/_next/static/chunks/13~y-b.b9rrw4.js +1 -0
  101. package/dist/web/_next/static/chunks/{0jokpgh485~28.js → 14hqmid8q4apf.js} +11 -11
  102. package/dist/web/_next/static/chunks/16sg-lflc8csx.js +1 -0
  103. package/dist/web/_next/static/chunks/176dc-dtokxxi.js +16 -0
  104. package/dist/web/_next/static/chunks/17g-0pqre.anw.js +1 -0
  105. package/dist/web/_next/static/chunks/17oc2l.ekcs8b.css +1 -0
  106. package/dist/web/_next/static/chunks/{turbopack-0lrdxynxb9-1t.js → turbopack-0ndm2zc_pdptk.js} +1 -1
  107. package/dist/web/_not-found/__next._full.txt +29 -30
  108. package/dist/web/_not-found/__next._head.txt +4 -4
  109. package/dist/web/_not-found/__next._index.txt +13 -13
  110. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
  111. package/dist/web/_not-found/__next._not-found.txt +3 -3
  112. package/dist/web/_not-found/__next._tree.txt +2 -2
  113. package/dist/web/_not-found.html +1 -1
  114. package/dist/web/_not-found.txt +29 -30
  115. package/dist/web/icons/file_type_audio.svg +3 -1
  116. package/dist/web/icons/file_type_video.svg +10 -1
  117. package/dist/web/index.html +1 -1
  118. package/dist/web/index.txt +25 -23
  119. package/dist/web/login/__next._full.txt +30 -28
  120. package/dist/web/login/__next._head.txt +4 -4
  121. package/dist/web/login/__next._index.txt +13 -13
  122. package/dist/web/login/__next._tree.txt +2 -2
  123. package/dist/web/login/__next.login.__PAGE__.txt +4 -4
  124. package/dist/web/login/__next.login.txt +3 -3
  125. package/dist/web/login.html +1 -1
  126. package/dist/web/login.txt +30 -28
  127. package/dist/web/settings/__next._full.txt +32 -31
  128. package/dist/web/settings/__next._head.txt +4 -4
  129. package/dist/web/settings/__next._index.txt +13 -13
  130. package/dist/web/settings/__next._tree.txt +2 -2
  131. package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
  132. package/dist/web/settings/__next.settings.txt +5 -5
  133. package/dist/web/settings/agents/__next._full.txt +35 -34
  134. package/dist/web/settings/agents/__next._head.txt +4 -4
  135. package/dist/web/settings/agents/__next._index.txt +13 -13
  136. package/dist/web/settings/agents/__next._tree.txt +2 -2
  137. package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
  138. package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
  139. package/dist/web/settings/agents/__next.settings.txt +5 -5
  140. package/dist/web/settings/agents.html +1 -1
  141. package/dist/web/settings/agents.txt +35 -34
  142. package/dist/web/settings/mcps/__next._full.txt +35 -34
  143. package/dist/web/settings/mcps/__next._head.txt +4 -4
  144. package/dist/web/settings/mcps/__next._index.txt +13 -13
  145. package/dist/web/settings/mcps/__next._tree.txt +2 -2
  146. package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
  147. package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
  148. package/dist/web/settings/mcps/__next.settings.txt +5 -5
  149. package/dist/web/settings/mcps.html +1 -1
  150. package/dist/web/settings/mcps.txt +35 -34
  151. package/dist/web/settings/models/__next._full.txt +35 -34
  152. package/dist/web/settings/models/__next._head.txt +4 -4
  153. package/dist/web/settings/models/__next._index.txt +13 -13
  154. package/dist/web/settings/models/__next._tree.txt +2 -2
  155. package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
  156. package/dist/web/settings/models/__next.settings.models.txt +3 -3
  157. package/dist/web/settings/models/__next.settings.txt +5 -5
  158. package/dist/web/settings/models.html +1 -1
  159. package/dist/web/settings/models.txt +35 -34
  160. package/dist/web/settings/output-styles/__next._full.txt +43 -0
  161. package/dist/web/settings/output-styles/__next._head.txt +6 -0
  162. package/dist/web/settings/output-styles/__next._index.txt +15 -0
  163. package/dist/web/settings/output-styles/__next._tree.txt +8 -0
  164. package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +9 -0
  165. package/dist/web/settings/output-styles/__next.settings.output-styles.txt +5 -0
  166. package/dist/web/settings/output-styles/__next.settings.txt +7 -0
  167. package/dist/web/settings/output-styles.html +1 -0
  168. package/dist/web/settings/output-styles.txt +43 -0
  169. package/dist/web/settings/prompts/__next._full.txt +35 -34
  170. package/dist/web/settings/prompts/__next._head.txt +4 -4
  171. package/dist/web/settings/prompts/__next._index.txt +13 -13
  172. package/dist/web/settings/prompts/__next._tree.txt +2 -2
  173. package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +4 -4
  174. package/dist/web/settings/prompts/__next.settings.prompts.txt +3 -3
  175. package/dist/web/settings/prompts/__next.settings.txt +5 -5
  176. package/dist/web/settings/prompts.html +1 -1
  177. package/dist/web/settings/prompts.txt +35 -34
  178. package/dist/web/settings/providers/__next._full.txt +35 -34
  179. package/dist/web/settings/providers/__next._head.txt +4 -4
  180. package/dist/web/settings/providers/__next._index.txt +13 -13
  181. package/dist/web/settings/providers/__next._tree.txt +2 -2
  182. package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
  183. package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
  184. package/dist/web/settings/providers/__next.settings.txt +5 -5
  185. package/dist/web/settings/providers.html +1 -1
  186. package/dist/web/settings/providers.txt +35 -34
  187. package/dist/web/settings/skills/__next._full.txt +35 -34
  188. package/dist/web/settings/skills/__next._head.txt +4 -4
  189. package/dist/web/settings/skills/__next._index.txt +13 -13
  190. package/dist/web/settings/skills/__next._tree.txt +2 -2
  191. package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
  192. package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
  193. package/dist/web/settings/skills/__next.settings.txt +5 -5
  194. package/dist/web/settings/skills.html +1 -1
  195. package/dist/web/settings/skills.txt +35 -34
  196. package/dist/web/settings.html +1 -1
  197. package/dist/web/settings.txt +32 -31
  198. package/dist/web/workflows/__next._full.txt +32 -30
  199. package/dist/web/workflows/__next._head.txt +4 -4
  200. package/dist/web/workflows/__next._index.txt +13 -13
  201. package/dist/web/workflows/__next._tree.txt +2 -2
  202. package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
  203. package/dist/web/workflows/__next.workflows.txt +3 -3
  204. package/dist/web/workflows.html +1 -1
  205. package/dist/web/workflows.txt +32 -30
  206. package/dist/web/workspace/_/__next._full.txt +30 -70
  207. package/dist/web/workspace/_/__next._head.txt +4 -4
  208. package/dist/web/workspace/_/__next._index.txt +13 -13
  209. package/dist/web/workspace/_/__next._tree.txt +2 -17
  210. package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -18
  211. package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
  212. package/dist/web/workspace/_/__next.workspace.txt +3 -3
  213. package/dist/web/workspace/_.html +1 -1
  214. package/dist/web/workspace/_.txt +30 -70
  215. package/dist/web/workspaces/__next._full.txt +31 -29
  216. package/dist/web/workspaces/__next._head.txt +4 -4
  217. package/dist/web/workspaces/__next._index.txt +13 -13
  218. package/dist/web/workspaces/__next._tree.txt +2 -2
  219. package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
  220. package/dist/web/workspaces/__next.workspaces.txt +3 -3
  221. package/dist/web/workspaces.html +1 -1
  222. package/dist/web/workspaces.txt +31 -29
  223. package/dist/ws/agent-runner.js +55 -33
  224. package/dist/ws/message-parts.js +61 -2
  225. package/package.json +1 -1
  226. package/public/output-styles/carmack-mode.md +381 -0
  227. package/public/output-styles/codex-rigor-mode.md +114 -0
  228. package/public/output-styles/dhh-mode.md +265 -0
  229. package/public/output-styles/evan-you-mode.md +539 -0
  230. package/public/output-styles/index.json +37 -0
  231. package/public/output-styles/jobs-mode.md +369 -0
  232. package/public/output-styles/linus-mode.md +135 -0
  233. package/public/output-styles/uncle-bob-mode.md +221 -0
  234. package/public/prompt/andrej-karpathy-skills.md +65 -0
  235. package/public/prompt/claude-token-efficient-coding.md +35 -0
  236. package/public/prompt/index.json +12 -0
  237. package/public/skills/index.json +92 -0
  238. package/public/skills/planning-with-files/planning-with-files-zh/SKILL.md +243 -0
  239. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.ps1 +44 -0
  240. package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.sh +46 -0
  241. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.ps1 +124 -0
  242. package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.sh +124 -0
  243. package/public/skills/planning-with-files/planning-with-files-zh/scripts/session-catchup.py +438 -0
  244. package/public/skills/planning-with-files/planning-with-files-zh/templates/findings.md +29 -0
  245. package/public/skills/planning-with-files/planning-with-files-zh/templates/progress.md +40 -0
  246. package/public/skills/planning-with-files/planning-with-files-zh/templates/task_plan.md +58 -0
  247. package/public/skills/superpowers/brainstorming/SKILL.md +164 -0
  248. package/public/skills/superpowers/brainstorming/scripts/frame-template.html +214 -0
  249. package/public/skills/superpowers/brainstorming/scripts/helper.js +88 -0
  250. package/public/skills/superpowers/brainstorming/scripts/server.cjs +354 -0
  251. package/public/skills/superpowers/brainstorming/scripts/start-server.sh +148 -0
  252. package/public/skills/superpowers/brainstorming/scripts/stop-server.sh +56 -0
  253. package/public/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
  254. package/public/skills/superpowers/brainstorming/visual-companion.md +287 -0
  255. package/public/skills/superpowers/dispatching-parallel-agents/SKILL.md +182 -0
  256. package/public/skills/superpowers/executing-plans/SKILL.md +70 -0
  257. package/public/skills/superpowers/finishing-a-development-branch/SKILL.md +251 -0
  258. package/public/skills/superpowers/receiving-code-review/SKILL.md +213 -0
  259. package/public/skills/superpowers/requesting-code-review/SKILL.md +103 -0
  260. package/public/skills/superpowers/requesting-code-review/code-reviewer.md +168 -0
  261. package/public/skills/superpowers/subagent-driven-development/SKILL.md +279 -0
  262. package/public/skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +25 -0
  263. package/public/skills/superpowers/subagent-driven-development/implementer-prompt.md +113 -0
  264. package/public/skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  265. package/public/skills/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
  266. package/public/skills/superpowers/systematic-debugging/SKILL.md +296 -0
  267. package/public/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
  268. package/public/skills/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
  269. package/public/skills/superpowers/systematic-debugging/defense-in-depth.md +122 -0
  270. package/public/skills/superpowers/systematic-debugging/find-polluter.sh +63 -0
  271. package/public/skills/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
  272. package/public/skills/superpowers/systematic-debugging/test-academic.md +14 -0
  273. package/public/skills/superpowers/systematic-debugging/test-pressure-1.md +58 -0
  274. package/public/skills/superpowers/systematic-debugging/test-pressure-2.md +68 -0
  275. package/public/skills/superpowers/systematic-debugging/test-pressure-3.md +69 -0
  276. package/public/skills/superpowers/test-driven-development/SKILL.md +371 -0
  277. package/public/skills/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
  278. package/public/skills/superpowers/using-git-worktrees/SKILL.md +215 -0
  279. package/public/skills/superpowers/using-superpowers/SKILL.md +117 -0
  280. package/public/skills/superpowers/using-superpowers/references/codex-tools.md +59 -0
  281. package/public/skills/superpowers/using-superpowers/references/copilot-tools.md +42 -0
  282. package/public/skills/superpowers/using-superpowers/references/gemini-tools.md +51 -0
  283. package/public/skills/superpowers/verification-before-completion/SKILL.md +139 -0
  284. package/public/skills/superpowers/writing-plans/SKILL.md +152 -0
  285. package/public/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
  286. package/public/skills/superpowers/writing-skills/SKILL.md +655 -0
  287. package/public/skills/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
  288. package/public/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  289. package/public/skills/superpowers/writing-skills/graphviz-conventions.dot +172 -0
  290. package/public/skills/superpowers/writing-skills/persuasion-principles.md +187 -0
  291. package/public/skills/superpowers/writing-skills/render-graphs.js +168 -0
  292. package/public/skills/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
  293. package/dist/web/_next/static/chunks/0-1pn22sg~67u.js +0 -2
  294. package/dist/web/_next/static/chunks/01gi~q0c6ez6..js +0 -1
  295. package/dist/web/_next/static/chunks/03me5_ir..2ix.js +0 -1
  296. package/dist/web/_next/static/chunks/05eu2fdixf7c9.js +0 -1
  297. package/dist/web/_next/static/chunks/0_-c.y2qq4ax4.js +0 -270
  298. package/dist/web/_next/static/chunks/0_g3irbniww6d.js +0 -3
  299. package/dist/web/_next/static/chunks/0cs830n97dgjy.js +0 -1
  300. package/dist/web/_next/static/chunks/0g-0n6glz_z6w.js +0 -1
  301. package/dist/web/_next/static/chunks/0gyede80jpy3n.js +0 -4
  302. package/dist/web/_next/static/chunks/0hrbuvzuxrjfl.js +0 -1
  303. package/dist/web/_next/static/chunks/0ju52ko_nh7gi.js +0 -1
  304. package/dist/web/_next/static/chunks/0mny8i81aenx3.js +0 -1
  305. package/dist/web/_next/static/chunks/0nsu~f3voe~0i.js +0 -5
  306. package/dist/web/_next/static/chunks/0sz8_nijfiz0p.js +0 -1
  307. package/dist/web/_next/static/chunks/0u7_qd9hzqwac.js +0 -1
  308. package/dist/web/_next/static/chunks/0w3o.7vi.dlm6.js +0 -1
  309. package/dist/web/_next/static/chunks/0wv0h27jafag4.js +0 -1
  310. package/dist/web/_next/static/chunks/0wwvc4zc2q6bn.js +0 -1
  311. package/dist/web/_next/static/chunks/0x4b-a2ixww6m.js +0 -1
  312. package/dist/web/_next/static/chunks/0xwqf.llmm_u2.js +0 -31
  313. package/dist/web/_next/static/chunks/0~w6ugk9s5p-h.css +0 -1
  314. package/dist/web/_next/static/chunks/125nunjfj2fj0.js +0 -1
  315. package/dist/web/_next/static/chunks/1285yqy_oirb-.js +0 -1
  316. package/dist/web/_next/static/chunks/13ess~4pdmxma.js +0 -1
  317. package/dist/web/_next/static/chunks/14n8i2xz4_y-e.js +0 -1
  318. package/public/avatars/1777813826407-bea0ja-minimax.svg +0 -1
  319. package/public/avatars/1777813967088-3xlvd0-minimax.svg +0 -1
  320. package/public/avatars/1777814041714-yp0qeq-minimax.svg +0 -1
  321. package/public/avatars/1777904986095-rg26je-icon.png +0 -0
  322. package/public/avatars/1778953228323-5je54x-user.jpg +0 -0
  323. package/public/avatars/1778954057880-g01q6y-user.jpg +0 -0
  324. /package/dist/web/_next/static/{HUlYEknPhyW7dRmJ5mFdG → OoXAsPtrUWjC1l898FSvI}/_buildManifest.js +0 -0
  325. /package/dist/web/_next/static/{HUlYEknPhyW7dRmJ5mFdG → OoXAsPtrUWjC1l898FSvI}/_clientMiddlewareManifest.js +0 -0
  326. /package/dist/web/_next/static/{HUlYEknPhyW7dRmJ5mFdG → OoXAsPtrUWjC1l898FSvI}/_ssgManifest.js +0 -0
  327. /package/public/avatars/{1777815865622-08wp9m-user.jpg → user.jpg} +0 -0
@@ -11,15 +11,23 @@ router.post('/', (req, res) => {
11
11
  res.status(400).json({ error: 'issueId and title are required' });
12
12
  return;
13
13
  }
14
+ if (typeof agentConfigId !== 'string' || !agentConfigId.trim()) {
15
+ res.status(400).json({ error: 'agentConfigId is required' });
16
+ return;
17
+ }
14
18
  const issue = issueService.getById(req.params.id, issueId);
15
19
  if (!issue) {
16
20
  res.status(404).json({ error: 'issue not found' });
17
21
  return;
18
22
  }
23
+ if (!issue.members.includes(agentConfigId)) {
24
+ res.status(400).json({ error: 'agentConfigId must be an issue member' });
25
+ return;
26
+ }
19
27
  const task = taskService.create(req.params.id, issueId, {
20
28
  title,
21
29
  description: description || '',
22
- agentConfigId,
30
+ agentConfigId: agentConfigId.trim(),
23
31
  dependsOnTaskIds,
24
32
  sandboxDirs,
25
33
  });
@@ -60,6 +68,10 @@ router.put('/:taskId', (req, res) => {
60
68
  res.status(400).json({ error: 'title, description, agentConfigId, dependsOnTaskIds, or sandboxDirs is required' });
61
69
  return;
62
70
  }
71
+ if (agentConfigId !== undefined && (typeof agentConfigId !== 'string' || !agentConfigId.trim())) {
72
+ res.status(400).json({ error: 'agentConfigId cannot be empty' });
73
+ return;
74
+ }
63
75
  const task = taskService.update(req.params.id, req.params.taskId, { title, description, agentConfigId, dependsOnTaskIds, sandboxDirs });
64
76
  if (!task) {
65
77
  res.status(404).json({ error: 'task not found or not editable (must be pending)' });
@@ -346,7 +346,13 @@ export function getAvailableSkillNames(agentDir, skills) {
346
346
  .filter((skill) => {
347
347
  if (!skill)
348
348
  return false;
349
- const skillFile = join(agentDir, 'skills', `${skill}.md`);
349
+ const skillsBase = join(agentDir, 'skills');
350
+ // Check folder structure first, then flat .md
351
+ const skillFolder = join(skillsBase, skill);
352
+ if (existsSync(skillFolder) && statSync(skillFolder).isDirectory()) {
353
+ return readdirSync(skillFolder).some((f) => f.endsWith('.md'));
354
+ }
355
+ const skillFile = join(skillsBase, `${skill}.md`);
350
356
  return existsSync(skillFile) && statSync(skillFile).size > 0;
351
357
  });
352
358
  }
@@ -448,25 +454,43 @@ function writeAgentTemplate(preset, skillInputs) {
448
454
  else if (preset.skills?.length) {
449
455
  const globalSkillsDir = join(getDataDir(), 'skills');
450
456
  const keepFiles = new Set(preset.skills.map((s) => s.endsWith('.md') ? s : `${s}.md`));
451
- // Remove skill files no longer in the list
457
+ const keepNames = new Set(preset.skills.map((s) => s.replace(/\.md$/i, '')));
458
+ // Remove skill entries no longer in the list (flat .md files and folders)
452
459
  if (existsSync(skillsDir)) {
453
460
  for (const existing of readdirSync(skillsDir)) {
454
- if (existing.endsWith('.md') && !keepFiles.has(existing)) {
455
- rmSync(join(skillsDir, existing), { force: true });
461
+ const name = existing.endsWith('.md') ? existing.replace(/\.md$/i, '') : existing;
462
+ if (!keepNames.has(name)) {
463
+ rmSync(join(skillsDir, existing), { recursive: true, force: true });
456
464
  console.log('[writeAgentTemplate] removed stale skill:', existing);
457
465
  }
458
466
  }
459
467
  }
460
- // Copy / ensure skill files
461
- for (const filename of keepFiles) {
462
- const target = join(skillsDir, filename);
463
- const globalSource = join(globalSkillsDir, filename);
464
- console.log('[writeAgentTemplate] skill:', filename, 'globalExists:', existsSync(globalSource), 'targetExists:', existsSync(target));
465
- if (existsSync(globalSource)) {
466
- copyFileSync(globalSource, target);
468
+ // Copy / ensure skill files (global skills are folders: skills/{name}/SKILL.md)
469
+ for (const skillName of keepNames) {
470
+ const globalFolder = join(globalSkillsDir, skillName);
471
+ const flatTarget = join(skillsDir, `${skillName}.md`);
472
+ const folderTarget = join(skillsDir, skillName);
473
+ console.log('[writeAgentTemplate] skill:', skillName, 'globalFolder:', globalFolder, 'globalExists:', existsSync(globalFolder) && statSync(globalFolder).isDirectory());
474
+ if (existsSync(globalFolder) && statSync(globalFolder).isDirectory()) {
475
+ // Copy entire skill folder
476
+ if (existsSync(folderTarget)) {
477
+ rmSync(folderTarget, { recursive: true, force: true });
478
+ }
479
+ cpSync(globalFolder, folderTarget, { recursive: true, force: true });
480
+ // Remove stale flat .md if it exists
481
+ if (existsSync(flatTarget)) {
482
+ rmSync(flatTarget, { force: true });
483
+ }
467
484
  }
468
- else if (!existsSync(target)) {
469
- writeFileSync(target, '', 'utf-8');
485
+ else {
486
+ // Fallback: single SKILL.md or legacy flat file
487
+ const globalSkillFile = join(globalFolder, 'SKILL.md');
488
+ if (existsSync(globalSkillFile)) {
489
+ copyFileSync(globalSkillFile, flatTarget);
490
+ }
491
+ else if (!existsSync(flatTarget) && !existsSync(folderTarget)) {
492
+ writeFileSync(flatTarget, '', 'utf-8');
493
+ }
470
494
  }
471
495
  }
472
496
  }
@@ -492,9 +516,14 @@ function copyAgentTemplateToWorkspace(agentId, agentspaceDir) {
492
516
  if (existsSync(skillsDir)) {
493
517
  const workspaceSkillsDir = join(agentspaceDir, 'skills');
494
518
  ensureDir(workspaceSkillsDir);
495
- for (const file of readdirSync(skillsDir)) {
496
- if (extname(file).toLowerCase() === '.md') {
497
- copyFileSync(join(skillsDir, file), join(workspaceSkillsDir, file));
519
+ for (const entry of readdirSync(skillsDir)) {
520
+ const source = join(skillsDir, entry);
521
+ const sourceStat = statSync(source);
522
+ if (sourceStat.isDirectory()) {
523
+ cpSync(source, join(workspaceSkillsDir, entry), { recursive: true, force: true });
524
+ }
525
+ else if (sourceStat.isFile() && extname(entry).toLowerCase() === '.md') {
526
+ copyFileSync(source, join(workspaceSkillsDir, entry));
498
527
  }
499
528
  }
500
529
  }
@@ -0,0 +1,118 @@
1
+ import { exec } from 'node:child_process';
2
+ import { listHooks } from '../storage/hook-store.js';
3
+ function matchToolName(matcher, toolName) {
4
+ if (matcher === '*')
5
+ return true;
6
+ if (matcher.startsWith('/') && matcher.endsWith('/')) {
7
+ try {
8
+ const regex = new RegExp(matcher.slice(1, -1));
9
+ return regex.test(toolName);
10
+ }
11
+ catch {
12
+ return matcher === toolName;
13
+ }
14
+ }
15
+ return matcher === toolName;
16
+ }
17
+ function executeCommand(command, env, timeout) {
18
+ return new Promise((resolve) => {
19
+ exec(command, { env: { ...process.env, ...env }, timeout: Math.min(timeout, 30000) }, (error) => {
20
+ if (error)
21
+ console.warn(`[HookEngine] command error: ${error.message}`);
22
+ resolve();
23
+ });
24
+ });
25
+ }
26
+ async function executeWebhook(url, body, timeout) {
27
+ try {
28
+ const controller = new AbortController();
29
+ const timer = setTimeout(() => controller.abort(), Math.min(timeout, 30000));
30
+ await fetch(url, {
31
+ method: 'POST',
32
+ headers: { 'Content-Type': 'application/json' },
33
+ body: JSON.stringify(body),
34
+ signal: controller.signal,
35
+ });
36
+ clearTimeout(timer);
37
+ }
38
+ catch (error) {
39
+ console.warn(`[HookEngine] webhook error: ${error.message}`);
40
+ }
41
+ }
42
+ async function executeRule(rule, phase, toolName, workspaceId, context) {
43
+ const timeout = rule.timeout ?? 10000;
44
+ if (rule.type === 'command' && rule.command) {
45
+ await executeCommand(rule.command, {
46
+ HOOK_TOOL_NAME: toolName,
47
+ HOOK_TOOL_INPUT: JSON.stringify(context.toolInput ?? {}),
48
+ HOOK_TOOL_RESULT: JSON.stringify(context.toolResult ?? ''),
49
+ HOOK_WORKSPACE_ID: workspaceId,
50
+ HOOK_PHASE: phase,
51
+ }, timeout);
52
+ }
53
+ else if (rule.type === 'webhook' && rule.url) {
54
+ await executeWebhook(rule.url, {
55
+ event: phase,
56
+ toolName,
57
+ toolInput: context.toolInput,
58
+ toolResult: context.toolResult ?? undefined,
59
+ timestamp: new Date().toISOString(),
60
+ workspaceId,
61
+ }, timeout);
62
+ }
63
+ else if (rule.type === 'script') {
64
+ console.warn(`[HookEngine] script type not implemented, skipping rule in ${phase}`);
65
+ }
66
+ }
67
+ export class HookEngine {
68
+ hooks = [];
69
+ workspaceId;
70
+ constructor(workspaceId) {
71
+ this.workspaceId = workspaceId;
72
+ }
73
+ load() {
74
+ this.hooks = listHooks(this.workspaceId);
75
+ }
76
+ reload() {
77
+ this.load();
78
+ }
79
+ getHooks() {
80
+ return this.hooks;
81
+ }
82
+ async executeHooks(phase, toolName, context) {
83
+ const enabledHooks = this.hooks.filter(h => h.enabled);
84
+ const promises = [];
85
+ for (const hook of enabledHooks) {
86
+ const rules = hook.hooks[phase];
87
+ if (!rules)
88
+ continue;
89
+ for (const rule of rules) {
90
+ if (matchToolName(rule.matcher, toolName)) {
91
+ promises.push(executeRule(rule, phase, toolName, this.workspaceId, context));
92
+ }
93
+ }
94
+ }
95
+ await Promise.allSettled(promises);
96
+ }
97
+ }
98
+ export function wrapOnEventWithHooks(onEvent, workspaceId, hooksEnabled) {
99
+ if (!hooksEnabled)
100
+ return onEvent;
101
+ const engine = new HookEngine(workspaceId);
102
+ engine.load();
103
+ const toolNameById = new Map();
104
+ return (event) => {
105
+ onEvent(event);
106
+ if (event.type === 'tool_use') {
107
+ toolNameById.set(event.id, event.name);
108
+ engine.executeHooks('PreToolUse', event.name, { toolInput: event.input });
109
+ }
110
+ if (event.type === 'tool_result') {
111
+ const toolName = event.toolUseId ? (toolNameById.get(event.toolUseId) ?? '') : '';
112
+ if (toolName) {
113
+ engine.executeHooks('PostToolUse', toolName, { toolResult: event.result });
114
+ }
115
+ }
116
+ };
117
+ }
118
+ //# sourceMappingURL=hook-engine.js.map
@@ -35,6 +35,10 @@ function ensureRetryDefaults(workspaceId, issue) {
35
35
  issue.maxRetries = 3;
36
36
  changed = true;
37
37
  }
38
+ if (issue.continuousRun === undefined) {
39
+ issue.continuousRun = true;
40
+ changed = true;
41
+ }
38
42
  if (changed)
39
43
  updateIssue({ ...issue, workspaceId });
40
44
  }
@@ -70,6 +74,7 @@ export function create(workspaceId, input) {
70
74
  tasks: [],
71
75
  members: input.members || [],
72
76
  workflowId: input.workflowId,
77
+ continuousRun: true,
73
78
  retryCount: 0,
74
79
  maxRetries: 3,
75
80
  createdAt: now,
@@ -94,6 +99,7 @@ export function createForChannel(workspaceId, channelId, input) {
94
99
  status: input.status ?? 'draft',
95
100
  tasks: [],
96
101
  members: [...issueMembers],
102
+ continuousRun: true,
97
103
  retryCount: 0,
98
104
  maxRetries: 3,
99
105
  createdAt: now,
@@ -41,6 +41,7 @@ export async function runBotAgent(workspaceId, preset, message) {
41
41
  configDir: agentService.getAgentConfigDir(workspaceId, preset),
42
42
  sandboxDirs: preset.sandboxDirs,
43
43
  systemPrompt: preset.systemPrompt,
44
+ outputStyle: preset.outputStyle,
44
45
  });
45
46
  agentService.complete(workspaceId, session.id, result.success ? undefined : result.error || result.summary, {
46
47
  runtime: preset.runtimeKind,
@@ -0,0 +1,134 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { basename, join } from 'node:path';
4
+ import { ensureDir, getDataDir } from '../storage/json-store.js';
5
+ import { listTemplates } from './agent.js';
6
+ function getDir() {
7
+ return join(getDataDir(), 'output-styles');
8
+ }
9
+ function getMetaPath() {
10
+ return join(getDir(), 'meta.json');
11
+ }
12
+ function readMeta() {
13
+ const path = getMetaPath();
14
+ if (!existsSync(path))
15
+ return { templates: [] };
16
+ try {
17
+ return JSON.parse(readFileSync(path, 'utf-8'));
18
+ }
19
+ catch {
20
+ return { templates: [] };
21
+ }
22
+ }
23
+ function writeMeta(meta) {
24
+ ensureDir(getDir());
25
+ writeFileSync(getMetaPath(), JSON.stringify(meta, null, 2), 'utf-8');
26
+ }
27
+ export function listOutputStyles() {
28
+ return readMeta().templates;
29
+ }
30
+ export function resolveOutputStyleTemplate(ref) {
31
+ const needle = sanitizeOutputStyleName(ref);
32
+ if (!needle)
33
+ return null;
34
+ return listOutputStyles().find((template) => template.id === ref?.trim()
35
+ || template.name === ref?.trim()
36
+ || sanitizeOutputStyleName(template.name) === needle) ?? null;
37
+ }
38
+ export function resolveOutputStyleContent(ref) {
39
+ const raw = ref?.trim();
40
+ if (!raw)
41
+ return undefined;
42
+ return resolveOutputStyleTemplate(raw)?.content ?? raw;
43
+ }
44
+ export function prepareClaudeOutputStyleFile(configDir, ref) {
45
+ const raw = ref?.trim();
46
+ if (!raw)
47
+ return undefined;
48
+ const template = resolveOutputStyleTemplate(raw);
49
+ const content = template?.content ?? raw;
50
+ const fileStem = sanitizeOutputStyleName(template?.name) || `output-style-${shortHash(content)}`;
51
+ if (!fileStem)
52
+ return undefined;
53
+ const dir = join(configDir, 'output_styles');
54
+ rmSync(dir, { recursive: true, force: true });
55
+ mkdirSync(dir, { recursive: true });
56
+ writeFileSync(join(dir, `${fileStem}.md`), `${content.trimEnd()}\n`, 'utf-8');
57
+ return fileStem;
58
+ }
59
+ export function createOutputStyle(name, content, storeId, description) {
60
+ const meta = readMeta();
61
+ const now = new Date().toISOString();
62
+ const id = `os-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
63
+ const tmpl = { id, name, description, content, storeId, createdAt: now, updatedAt: now };
64
+ meta.templates.push(tmpl);
65
+ writeMeta(meta);
66
+ return tmpl;
67
+ }
68
+ export function updateOutputStyle(id, data) {
69
+ const meta = readMeta();
70
+ const tmpl = meta.templates.find((t) => t.id === id);
71
+ if (!tmpl)
72
+ return null;
73
+ if (data.name !== undefined)
74
+ tmpl.name = data.name;
75
+ if (data.description !== undefined)
76
+ tmpl.description = data.description;
77
+ if (data.content !== undefined)
78
+ tmpl.content = data.content;
79
+ tmpl.updatedAt = new Date().toISOString();
80
+ writeMeta(meta);
81
+ return tmpl;
82
+ }
83
+ export function deleteOutputStyle(id) {
84
+ const meta = readMeta();
85
+ const idx = meta.templates.findIndex((t) => t.id === id);
86
+ if (idx < 0)
87
+ return false;
88
+ meta.templates.splice(idx, 1);
89
+ writeMeta(meta);
90
+ return true;
91
+ }
92
+ export function applyOutputStyleToAgents(styleId, agentIds) {
93
+ const meta = readMeta();
94
+ const tmpl = meta.templates.find((t) => t.id === styleId);
95
+ if (!tmpl)
96
+ return 0;
97
+ const agents = listTemplates();
98
+ let applied = 0;
99
+ for (const agentId of agentIds) {
100
+ const agent = agents.find((a) => a.id === agentId);
101
+ if (!agent)
102
+ continue;
103
+ const agentDir = join(getDataDir(), 'agent-templates', agent.id);
104
+ const agentPath = join(agentDir, 'agent.json');
105
+ if (!existsSync(agentPath))
106
+ continue;
107
+ const config = JSON.parse(readFileSync(agentPath, 'utf-8'));
108
+ config.outputStyle = tmpl.name;
109
+ writeFileSync(agentPath, JSON.stringify(config, null, 2), 'utf-8');
110
+ applied++;
111
+ }
112
+ return applied;
113
+ }
114
+ export function listOutputStyleAgentCandidates() {
115
+ return listTemplates()
116
+ .filter((a) => a.id !== 'agent-generator')
117
+ .map((a) => ({
118
+ id: a.id,
119
+ name: a.name || a.id,
120
+ avatarUrl: a.avatarUrl,
121
+ description: a.description,
122
+ hasOutputStyle: !!a.outputStyle,
123
+ }));
124
+ }
125
+ function sanitizeOutputStyleName(name) {
126
+ const raw = name?.trim();
127
+ if (!raw)
128
+ return '';
129
+ return basename(raw).replace(/\.md$/i, '').replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
130
+ }
131
+ function shortHash(text) {
132
+ return createHash('sha1').update(text).digest('hex').slice(0, 8);
133
+ }
134
+ //# sourceMappingURL=output-style.js.map
@@ -1,6 +1,6 @@
1
1
  import { existsSync, realpathSync, readFileSync, statSync } from 'node:fs';
2
2
  import { homedir } from 'node:os';
3
- import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
3
+ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
4
4
  import { getDataDir } from '../storage/json-store.js';
5
5
  import { readWorkspacePrompt } from './workspace-prompt.js';
6
6
  const INSTRUCTION_FILENAMES = ['CLAUDE.md', 'claude.md', 'AGENTS.md', 'agents.md'];
@@ -13,10 +13,8 @@ export function prependPersistentAgentContext(prompt, options) {
13
13
  return `${context}\n\n${prompt}`;
14
14
  }
15
15
  export function buildPersistentAgentContext(options) {
16
+ const { instructionContext } = buildPersistentAgentContextDetails(options);
16
17
  const sections = [];
17
- const instructionContext = buildInstructionFileContext(options.workingDir, options.boundDirs, {
18
- excludeNativeClaudeMd: options.excludeNativeClaudeMd,
19
- });
20
18
  if (instructionContext)
21
19
  sections.push(instructionContext);
22
20
  if (options.includeWorkspacePrompt !== false) {
@@ -30,8 +28,20 @@ export function buildPersistentAgentContext(options) {
30
28
  }
31
29
  return sections.join('\n\n');
32
30
  }
31
+ export function buildPersistentAgentContextDetails(options) {
32
+ const instructionFiles = collectInstructionFiles(options.workingDir, options.boundDirs, {
33
+ excludeNativeClaudeMd: options.excludeNativeClaudeMd,
34
+ });
35
+ return {
36
+ instructionContext: buildInstructionFileContextFromFiles(instructionFiles),
37
+ summary: buildPersistentAgentContextSummary(instructionFiles),
38
+ };
39
+ }
33
40
  function buildInstructionFileContext(workingDir, boundDirs, options = {}) {
34
41
  const files = collectInstructionFiles(workingDir, boundDirs, options);
42
+ return buildInstructionFileContextFromFiles(files);
43
+ }
44
+ function buildInstructionFileContextFromFiles(files) {
35
45
  if (files.length === 0)
36
46
  return '';
37
47
  const lines = [
@@ -51,6 +61,28 @@ function buildInstructionFileContext(workingDir, boundDirs, options = {}) {
51
61
  }
52
62
  return lines.join('\n').trim();
53
63
  }
64
+ function buildPersistentAgentContextSummary(files) {
65
+ const instructionFiles = files.map((file) => ({
66
+ path: file.path,
67
+ label: file.label,
68
+ filename: file.filename,
69
+ }));
70
+ const counts = instructionFiles.reduce((acc, file) => {
71
+ acc.total += 1;
72
+ if (file.filename === 'CLAUDE.md' || file.filename === 'claude.md') {
73
+ acc.claudeMd += 1;
74
+ }
75
+ if (file.filename === 'AGENTS.md' || file.filename === 'agents.md') {
76
+ acc.agentsMd += 1;
77
+ }
78
+ return acc;
79
+ }, {
80
+ claudeMd: 0,
81
+ agentsMd: 0,
82
+ total: 0,
83
+ });
84
+ return { instructionFiles, counts };
85
+ }
54
86
  function collectInstructionFiles(workingDir, boundDirs, options = {}) {
55
87
  const cwd = resolve(workingDir || process.cwd());
56
88
  const seen = new Set();
@@ -125,6 +157,7 @@ function addInstructionFile(files, seen, path, label) {
125
157
  files.push({
126
158
  path: realPath,
127
159
  label,
160
+ filename: basename(realPath),
128
161
  content: readFileSync(path, 'utf-8').trim(),
129
162
  });
130
163
  }
@@ -26,11 +26,11 @@ function writeMeta(meta) {
26
26
  export function listPromptTemplates() {
27
27
  return readMeta().templates;
28
28
  }
29
- export function createPromptTemplate(name, content) {
29
+ export function createPromptTemplate(name, content, storeId) {
30
30
  const meta = readMeta();
31
31
  const now = new Date().toISOString();
32
32
  const id = `prompt-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
33
- const tmpl = { id, name, content, createdAt: now, updatedAt: now };
33
+ const tmpl = { id, name, content, storeId, createdAt: now, updatedAt: now };
34
34
  meta.templates.push(tmpl);
35
35
  writeMeta(meta);
36
36
  return tmpl;