@jiggai/kitchen 0.1.3 → 0.1.7

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 (389) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +2 -2
  3. package/.next/prerender-manifest.json +0 -24
  4. package/.next/server/app/_global-error/page.js +1 -1
  5. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  6. package/.next/server/app/_global-error.html +2 -2
  7. package/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page.js +1 -1
  14. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/server/app/_not-found.html +1 -1
  16. package/.next/server/app/_not-found.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/server/app/agents/[agentId]/page.js +1 -1
  24. package/.next/server/app/agents/[agentId]/page.js.nft.json +1 -1
  25. package/.next/server/app/agents/[agentId]/page_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/agents/[id]/route.js +1 -1
  27. package/.next/server/app/api/agents/[id]/route.js.nft.json +1 -1
  28. package/.next/server/app/api/agents/add/route.js +1 -1
  29. package/.next/server/app/api/agents/add/route.js.nft.json +1 -1
  30. package/.next/server/app/api/agents/file/route.js +1 -1
  31. package/.next/server/app/api/agents/file/route.js.nft.json +1 -1
  32. package/.next/server/app/api/agents/files/route.js +1 -1
  33. package/.next/server/app/api/agents/files/route.js.nft.json +1 -1
  34. package/.next/server/app/api/agents/identity/route.js +1 -1
  35. package/.next/server/app/api/agents/identity/route.js.nft.json +1 -1
  36. package/.next/server/app/api/agents/route.js +1 -1
  37. package/.next/server/app/api/agents/route.js.nft.json +1 -1
  38. package/.next/server/app/api/agents/skills/install/route.js +1 -1
  39. package/.next/server/app/api/agents/skills/install/route.js.nft.json +1 -1
  40. package/.next/server/app/api/agents/skills/route.js +1 -1
  41. package/.next/server/app/api/agents/skills/route.js.nft.json +1 -1
  42. package/.next/server/app/api/agents/update/route.js +1 -1
  43. package/.next/server/app/api/agents/update/route.js.nft.json +1 -1
  44. package/.next/server/app/api/channels/bindings/route.js +1 -1
  45. package/.next/server/app/api/channels/bindings/route.js.nft.json +1 -1
  46. package/.next/server/app/api/cron/delete/route.js +1 -1
  47. package/.next/server/app/api/cron/delete/route.js.nft.json +1 -1
  48. package/.next/server/app/api/cron/job/route.js +1 -1
  49. package/.next/server/app/api/cron/job/route.js.nft.json +1 -1
  50. package/.next/server/app/api/cron/jobs/route.js +1 -1
  51. package/.next/server/app/api/cron/jobs/route.js.nft.json +1 -1
  52. package/.next/server/app/api/cron/recipe-installed/route.js +1 -1
  53. package/.next/server/app/api/cron/recipe-installed/route.js.nft.json +1 -1
  54. package/.next/server/app/api/gateway/restart/route.js +1 -1
  55. package/.next/server/app/api/gateway/restart/route.js.nft.json +1 -1
  56. package/.next/server/app/api/goals/[id]/promote/route.js +1 -1
  57. package/.next/server/app/api/goals/[id]/promote/route.js.nft.json +1 -1
  58. package/.next/server/app/api/goals/[id]/route.js +1 -1
  59. package/.next/server/app/api/goals/[id]/route.js.nft.json +1 -1
  60. package/.next/server/app/api/goals/route.js +1 -1
  61. package/.next/server/app/api/goals/route.js.nft.json +1 -1
  62. package/.next/server/app/api/ids/check/route.js +1 -1
  63. package/.next/server/app/api/ids/check/route.js.nft.json +1 -1
  64. package/.next/server/app/api/marketplace/recipes/[slug]/route.js +1 -1
  65. package/.next/server/app/api/marketplace/recipes/[slug]/route.js.nft.json +1 -1
  66. package/.next/server/app/api/marketplace/recipes/route.js +1 -1
  67. package/.next/server/app/api/marketplace/recipes/route.js.nft.json +1 -1
  68. package/.next/server/app/api/recipes/[id]/route.js +1 -1
  69. package/.next/server/app/api/recipes/[id]/route.js.nft.json +1 -1
  70. package/.next/server/app/api/recipes/clone/route.js +1 -1
  71. package/.next/server/app/api/recipes/clone/route.js.nft.json +1 -1
  72. package/.next/server/app/api/recipes/delete/route.js +1 -1
  73. package/.next/server/app/api/recipes/delete/route.js.nft.json +1 -1
  74. package/.next/server/app/api/recipes/route.js +1 -1
  75. package/.next/server/app/api/recipes/route.js.nft.json +1 -1
  76. package/.next/server/app/api/recipes/team-agents/route.js +1 -1
  77. package/.next/server/app/api/recipes/team-agents/route.js.nft.json +1 -1
  78. package/.next/server/app/api/scaffold/route.js +2 -2
  79. package/.next/server/app/api/scaffold/route.js.nft.json +1 -1
  80. package/.next/server/app/api/settings/cron-installation/route.js +1 -1
  81. package/.next/server/app/api/settings/cron-installation/route.js.nft.json +1 -1
  82. package/.next/server/app/api/skills/available/route.js +1 -1
  83. package/.next/server/app/api/skills/available/route.js.nft.json +1 -1
  84. package/.next/server/app/api/teams/file/route.js +1 -1
  85. package/.next/server/app/api/teams/file/route.js.nft.json +1 -1
  86. package/.next/server/app/api/teams/files/route.js +1 -1
  87. package/.next/server/app/api/teams/files/route.js.nft.json +1 -1
  88. package/.next/server/app/api/teams/meta/route.js +1 -1
  89. package/.next/server/app/api/teams/meta/route.js.nft.json +1 -1
  90. package/.next/server/app/api/teams/remove-team/route.js +1 -1
  91. package/.next/server/app/api/teams/remove-team/route.js.nft.json +1 -1
  92. package/.next/server/app/api/teams/skills/install/route.js +1 -1
  93. package/.next/server/app/api/teams/skills/install/route.js.nft.json +1 -1
  94. package/.next/server/app/api/teams/skills/route.js +1 -1
  95. package/.next/server/app/api/teams/skills/route.js.nft.json +1 -1
  96. package/.next/server/app/api/tickets/move/route.js +1 -1
  97. package/.next/server/app/api/tickets/move/route.js.nft.json +1 -1
  98. package/.next/server/app/channels/page.js +1 -1
  99. package/.next/server/app/channels/page.js.nft.json +1 -1
  100. package/.next/server/app/channels.html +2 -2
  101. package/.next/server/app/channels.rsc +1 -1
  102. package/.next/server/app/channels.segments/_full.segment.rsc +1 -1
  103. package/.next/server/app/channels.segments/_head.segment.rsc +1 -1
  104. package/.next/server/app/channels.segments/_index.segment.rsc +1 -1
  105. package/.next/server/app/channels.segments/_tree.segment.rsc +1 -1
  106. package/.next/server/app/channels.segments/channels/__PAGE__.segment.rsc +1 -1
  107. package/.next/server/app/channels.segments/channels.segment.rsc +1 -1
  108. package/.next/server/app/cron-jobs/page.js +1 -1
  109. package/.next/server/app/cron-jobs/page.js.nft.json +1 -1
  110. package/.next/server/app/cron-jobs.html +1 -1
  111. package/.next/server/app/cron-jobs.rsc +1 -1
  112. package/.next/server/app/cron-jobs.segments/_full.segment.rsc +1 -1
  113. package/.next/server/app/cron-jobs.segments/_head.segment.rsc +1 -1
  114. package/.next/server/app/cron-jobs.segments/_index.segment.rsc +1 -1
  115. package/.next/server/app/cron-jobs.segments/_tree.segment.rsc +1 -1
  116. package/.next/server/app/cron-jobs.segments/cron-jobs/__PAGE__.segment.rsc +1 -1
  117. package/.next/server/app/cron-jobs.segments/cron-jobs.segment.rsc +1 -1
  118. package/.next/server/app/goals/[id]/page.js +1 -1
  119. package/.next/server/app/goals/[id]/page.js.nft.json +1 -1
  120. package/.next/server/app/goals/new/page.js +1 -1
  121. package/.next/server/app/goals/new/page.js.nft.json +1 -1
  122. package/.next/server/app/goals/new.html +2 -2
  123. package/.next/server/app/goals/new.rsc +1 -1
  124. package/.next/server/app/goals/new.segments/_full.segment.rsc +1 -1
  125. package/.next/server/app/goals/new.segments/_head.segment.rsc +1 -1
  126. package/.next/server/app/goals/new.segments/_index.segment.rsc +1 -1
  127. package/.next/server/app/goals/new.segments/_tree.segment.rsc +1 -1
  128. package/.next/server/app/goals/new.segments/goals/new/__PAGE__.segment.rsc +1 -1
  129. package/.next/server/app/goals/new.segments/goals/new.segment.rsc +1 -1
  130. package/.next/server/app/goals/new.segments/goals.segment.rsc +1 -1
  131. package/.next/server/app/goals/page.js +1 -1
  132. package/.next/server/app/goals/page.js.nft.json +1 -1
  133. package/.next/server/app/goals.html +1 -1
  134. package/.next/server/app/goals.rsc +1 -1
  135. package/.next/server/app/goals.segments/_full.segment.rsc +1 -1
  136. package/.next/server/app/goals.segments/_head.segment.rsc +1 -1
  137. package/.next/server/app/goals.segments/_index.segment.rsc +1 -1
  138. package/.next/server/app/goals.segments/_tree.segment.rsc +1 -1
  139. package/.next/server/app/goals.segments/goals/__PAGE__.segment.rsc +1 -1
  140. package/.next/server/app/goals.segments/goals.segment.rsc +1 -1
  141. package/.next/server/app/page.js +3 -3
  142. package/.next/server/app/page.js.nft.json +1 -1
  143. package/.next/server/app/recipes/[id]/page.js +4 -3
  144. package/.next/server/app/recipes/[id]/page.js.nft.json +1 -1
  145. package/.next/server/app/recipes/page.js +4 -3
  146. package/.next/server/app/recipes/page.js.nft.json +1 -1
  147. package/.next/server/app/recipes/page_client-reference-manifest.js +1 -1
  148. package/.next/server/app/settings/page.js +1 -1
  149. package/.next/server/app/settings/page.js.nft.json +1 -1
  150. package/.next/server/app/settings.html +1 -1
  151. package/.next/server/app/settings.rsc +1 -1
  152. package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  153. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  154. package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  155. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  156. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  157. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  158. package/.next/server/app/teams/[teamId]/page.js +3 -3
  159. package/.next/server/app/teams/[teamId]/page.js.nft.json +1 -1
  160. package/.next/server/app/tickets/[ticket]/page.js +2 -2
  161. package/.next/server/app/tickets/[ticket]/page.js.nft.json +1 -1
  162. package/.next/server/app/tickets/page.js +2 -2
  163. package/.next/server/app/tickets/page.js.nft.json +1 -1
  164. package/.next/server/app/tickets.html +1 -1
  165. package/.next/server/app/tickets.rsc +2 -2
  166. package/.next/server/app/tickets.segments/_full.segment.rsc +2 -2
  167. package/.next/server/app/tickets.segments/_head.segment.rsc +1 -1
  168. package/.next/server/app/tickets.segments/_index.segment.rsc +1 -1
  169. package/.next/server/app/tickets.segments/_tree.segment.rsc +1 -1
  170. package/.next/server/app/tickets.segments/tickets/__PAGE__.segment.rsc +1 -1
  171. package/.next/server/app/tickets.segments/tickets.segment.rsc +1 -1
  172. package/.next/server/chunks/[root-of-the-server]__055885ce._.js +3 -0
  173. package/.next/server/chunks/[root-of-the-server]__055885ce._.js.map +1 -0
  174. package/.next/server/chunks/[root-of-the-server]__0c01c5c7._.js +10 -0
  175. package/.next/server/chunks/[root-of-the-server]__0c01c5c7._.js.map +1 -0
  176. package/.next/server/chunks/[root-of-the-server]__1398a33a._.js +3 -0
  177. package/.next/server/chunks/[root-of-the-server]__1398a33a._.js.map +1 -0
  178. package/.next/server/chunks/[root-of-the-server]__159c002b._.js +8 -0
  179. package/.next/server/chunks/[root-of-the-server]__159c002b._.js.map +1 -0
  180. package/.next/server/chunks/[root-of-the-server]__20c60fb7._.js +3 -0
  181. package/.next/server/chunks/[root-of-the-server]__20c60fb7._.js.map +1 -0
  182. package/.next/server/chunks/[root-of-the-server]__2588560d._.js +6 -0
  183. package/.next/server/chunks/[root-of-the-server]__2588560d._.js.map +1 -0
  184. package/.next/server/chunks/[root-of-the-server]__27293e91._.js +3 -0
  185. package/.next/server/chunks/[root-of-the-server]__27293e91._.js.map +1 -0
  186. package/.next/server/chunks/[root-of-the-server]__29c85a51._.js +3 -0
  187. package/.next/server/chunks/[root-of-the-server]__29c85a51._.js.map +1 -0
  188. package/.next/server/chunks/[root-of-the-server]__29fa8108._.js +3 -0
  189. package/.next/server/chunks/[root-of-the-server]__29fa8108._.js.map +1 -0
  190. package/.next/server/chunks/[root-of-the-server]__2bd44067._.js +3 -0
  191. package/.next/server/chunks/[root-of-the-server]__2bd44067._.js.map +1 -0
  192. package/.next/server/chunks/[root-of-the-server]__2dd1afff._.js +3 -0
  193. package/.next/server/chunks/[root-of-the-server]__2dd1afff._.js.map +1 -0
  194. package/.next/server/chunks/[root-of-the-server]__401ab759._.js +3 -0
  195. package/.next/server/chunks/[root-of-the-server]__401ab759._.js.map +1 -0
  196. package/.next/server/chunks/[root-of-the-server]__422c7160._.js +3 -0
  197. package/.next/server/chunks/[root-of-the-server]__422c7160._.js.map +1 -0
  198. package/.next/server/chunks/[root-of-the-server]__4670294e._.js +3 -0
  199. package/.next/server/chunks/[root-of-the-server]__4670294e._.js.map +1 -0
  200. package/.next/server/chunks/[root-of-the-server]__4898071c._.js +1 -1
  201. package/.next/server/chunks/[root-of-the-server]__4898071c._.js.map +1 -1
  202. package/.next/server/chunks/[root-of-the-server]__4eda99a9._.js +3 -0
  203. package/.next/server/chunks/[root-of-the-server]__4eda99a9._.js.map +1 -0
  204. package/.next/server/chunks/[root-of-the-server]__54478298._.js +8 -0
  205. package/.next/server/chunks/[root-of-the-server]__54478298._.js.map +1 -0
  206. package/.next/server/chunks/[root-of-the-server]__6dbdb384._.js +3 -0
  207. package/.next/server/chunks/[root-of-the-server]__6dbdb384._.js.map +1 -0
  208. package/.next/server/chunks/{[root-of-the-server]__dc6c67a5._.js → [root-of-the-server]__74b80ca4._.js} +2 -2
  209. package/.next/server/chunks/[root-of-the-server]__94d68aa3._.js +3 -0
  210. package/.next/server/chunks/[root-of-the-server]__94d68aa3._.js.map +1 -0
  211. package/.next/server/chunks/[root-of-the-server]__9ecbb339._.js +3 -0
  212. package/.next/server/chunks/[root-of-the-server]__9ecbb339._.js.map +1 -0
  213. package/.next/server/chunks/[root-of-the-server]__a27f8405._.js +3 -0
  214. package/.next/server/chunks/[root-of-the-server]__a27f8405._.js.map +1 -0
  215. package/.next/server/chunks/[root-of-the-server]__a6ac3ddf._.js +3 -0
  216. package/.next/server/chunks/[root-of-the-server]__a6ac3ddf._.js.map +1 -0
  217. package/.next/server/chunks/[root-of-the-server]__b11231a9._.js +3 -0
  218. package/.next/server/chunks/[root-of-the-server]__b11231a9._.js.map +1 -0
  219. package/.next/server/chunks/[root-of-the-server]__b59b3cdd._.js +3 -0
  220. package/.next/server/chunks/[root-of-the-server]__b59b3cdd._.js.map +1 -0
  221. package/.next/server/chunks/{[root-of-the-server]__94ebcd84._.js → [root-of-the-server]__b5c2b370._.js} +2 -2
  222. package/.next/server/chunks/[root-of-the-server]__b955e35a._.js +3 -0
  223. package/.next/server/chunks/[root-of-the-server]__b955e35a._.js.map +1 -0
  224. package/.next/server/chunks/{[root-of-the-server]__920d7db4._.js → [root-of-the-server]__be5f57b2._.js} +2 -2
  225. package/.next/server/chunks/[root-of-the-server]__c4ff0427._.js +3 -0
  226. package/.next/server/chunks/[root-of-the-server]__c4ff0427._.js.map +1 -0
  227. package/.next/server/chunks/[root-of-the-server]__c4ffbb03._.js +3 -0
  228. package/.next/server/chunks/[root-of-the-server]__c4ffbb03._.js.map +1 -0
  229. package/.next/server/chunks/[root-of-the-server]__d737ca42._.js +3 -0
  230. package/.next/server/chunks/[root-of-the-server]__d737ca42._.js.map +1 -0
  231. package/.next/server/chunks/[root-of-the-server]__df7df3ac._.js +3 -0
  232. package/.next/server/chunks/[root-of-the-server]__df7df3ac._.js.map +1 -0
  233. package/.next/server/chunks/[root-of-the-server]__dfca6557._.js +3 -0
  234. package/.next/server/chunks/[root-of-the-server]__dfca6557._.js.map +1 -0
  235. package/.next/server/chunks/[root-of-the-server]__e6184ba3._.js +3 -0
  236. package/.next/server/chunks/[root-of-the-server]__e6184ba3._.js.map +1 -0
  237. package/.next/server/chunks/[root-of-the-server]__ed0323e9._.js +8 -0
  238. package/.next/server/chunks/[root-of-the-server]__ed0323e9._.js.map +1 -0
  239. package/.next/server/chunks/[root-of-the-server]__f585823b._.js +6 -0
  240. package/.next/server/chunks/[root-of-the-server]__f585823b._.js.map +1 -0
  241. package/.next/server/chunks/[root-of-the-server]__ff940674._.js +3 -0
  242. package/.next/server/chunks/[root-of-the-server]__ff940674._.js.map +1 -0
  243. package/.next/server/chunks/src_lib_d2210cbf._.js +3 -0
  244. package/.next/server/chunks/src_lib_d2210cbf._.js.map +1 -0
  245. package/.next/server/chunks/ssr/[root-of-the-server]__4393e897._.js +3 -0
  246. package/.next/server/chunks/ssr/[root-of-the-server]__4393e897._.js.map +1 -0
  247. package/.next/server/chunks/ssr/{[root-of-the-server]__ae77070e._.js → [root-of-the-server]__4c6cc96d._.js} +2 -2
  248. package/.next/server/chunks/ssr/[root-of-the-server]__4c6cc96d._.js.map +1 -0
  249. package/.next/server/chunks/ssr/{[root-of-the-server]__b6de1782._.js → [root-of-the-server]__507d2fc9._.js} +2 -2
  250. package/.next/server/chunks/ssr/{[root-of-the-server]__c72e7548._.js → [root-of-the-server]__7180d770._.js} +2 -2
  251. package/.next/server/chunks/ssr/[root-of-the-server]__7180d770._.js.map +1 -0
  252. package/.next/server/chunks/ssr/[root-of-the-server]__82ce3aee._.js +3 -0
  253. package/.next/server/chunks/ssr/[root-of-the-server]__82ce3aee._.js.map +1 -0
  254. package/.next/server/chunks/ssr/[root-of-the-server]__8d24c9c3._.js +3 -0
  255. package/.next/server/chunks/ssr/[root-of-the-server]__8d24c9c3._.js.map +1 -0
  256. package/.next/server/chunks/ssr/[root-of-the-server]__bc3b27b0._.js +3 -0
  257. package/.next/server/chunks/ssr/[root-of-the-server]__bc3b27b0._.js.map +1 -0
  258. package/.next/server/chunks/ssr/{[root-of-the-server]__72721a7e._.js → [root-of-the-server]__f75a61bf._.js} +2 -2
  259. package/.next/server/chunks/ssr/_1aad1d9b._.js +24 -0
  260. package/.next/server/chunks/ssr/_1aad1d9b._.js.map +1 -0
  261. package/.next/server/chunks/ssr/{node_modules_next_aefa2538._.js → _da6f800e._.js} +2 -2
  262. package/.next/server/chunks/ssr/_da6f800e._.js.map +1 -0
  263. package/.next/server/chunks/ssr/src_app_agents_[agentId]_agent-editor_tsx_f85bbe65._.js +1 -1
  264. package/.next/server/chunks/ssr/src_app_agents_[agentId]_agent-editor_tsx_f85bbe65._.js.map +1 -1
  265. package/.next/server/chunks/ssr/src_app_recipes_recipes-client_tsx_8ed3ca94._.js +1 -1
  266. package/.next/server/chunks/ssr/src_app_recipes_recipes-client_tsx_8ed3ca94._.js.map +1 -1
  267. package/.next/server/pages/404.html +1 -1
  268. package/.next/server/pages/500.html +2 -2
  269. package/.next/static/chunks/{a33f8641aafb9e7f.js → 54beb791bcc086ae.js} +1 -1
  270. package/.next/static/chunks/55866d57aa2c7a9c.js +1 -0
  271. package/openclaw/index.ts +4 -0
  272. package/openclaw.plugin.json +1 -1
  273. package/package.json +1 -1
  274. package/src/app/agents/[agentId]/agent-editor.tsx +66 -23
  275. package/src/app/api/agents/[id]/route.ts +37 -0
  276. package/src/app/api/agents/add/route.ts +7 -7
  277. package/src/app/api/agents/files/route.ts +3 -1
  278. package/src/app/api/agents/skills/install/route.ts +27 -3
  279. package/src/app/api/agents/skills/route.ts +28 -12
  280. package/src/app/api/goals/[id]/promote/route.ts +12 -18
  281. package/src/app/api/recipes/team-agents/route.ts +1 -1
  282. package/src/app/api/teams/skills/install/route.ts +3 -1
  283. package/src/app/api/tickets/move/route.ts +3 -4
  284. package/src/app/recipes/[id]/page.tsx +7 -0
  285. package/src/app/recipes/page.tsx +7 -0
  286. package/src/app/recipes/recipes-client.tsx +0 -5
  287. package/src/lib/agent-workspace.ts +14 -0
  288. package/src/lib/gateway.ts +5 -8
  289. package/src/lib/kitchen-api.ts +19 -0
  290. package/src/lib/openclaw.ts +28 -26
  291. package/src/lib/paths.ts +4 -3
  292. package/src/proxy.ts +2 -2
  293. package/.next/server/app/recipes.html +0 -1
  294. package/.next/server/app/recipes.meta +0 -15
  295. package/.next/server/app/recipes.rsc +0 -21
  296. package/.next/server/app/recipes.segments/_full.segment.rsc +0 -21
  297. package/.next/server/app/recipes.segments/_head.segment.rsc +0 -6
  298. package/.next/server/app/recipes.segments/_index.segment.rsc +0 -6
  299. package/.next/server/app/recipes.segments/_tree.segment.rsc +0 -4
  300. package/.next/server/app/recipes.segments/recipes/__PAGE__.segment.rsc +0 -10
  301. package/.next/server/app/recipes.segments/recipes.segment.rsc +0 -4
  302. package/.next/server/chunks/[root-of-the-server]__02ebb205._.js +0 -3
  303. package/.next/server/chunks/[root-of-the-server]__02ebb205._.js.map +0 -1
  304. package/.next/server/chunks/[root-of-the-server]__0761ac0a._.js +0 -3
  305. package/.next/server/chunks/[root-of-the-server]__0761ac0a._.js.map +0 -1
  306. package/.next/server/chunks/[root-of-the-server]__0a87d140._.js +0 -3
  307. package/.next/server/chunks/[root-of-the-server]__0a87d140._.js.map +0 -1
  308. package/.next/server/chunks/[root-of-the-server]__13e03a23._.js +0 -8
  309. package/.next/server/chunks/[root-of-the-server]__13e03a23._.js.map +0 -1
  310. package/.next/server/chunks/[root-of-the-server]__16252fca._.js +0 -3
  311. package/.next/server/chunks/[root-of-the-server]__16252fca._.js.map +0 -1
  312. package/.next/server/chunks/[root-of-the-server]__1ab15cc6._.js +0 -3
  313. package/.next/server/chunks/[root-of-the-server]__1ab15cc6._.js.map +0 -1
  314. package/.next/server/chunks/[root-of-the-server]__1cb96385._.js +0 -3
  315. package/.next/server/chunks/[root-of-the-server]__1cb96385._.js.map +0 -1
  316. package/.next/server/chunks/[root-of-the-server]__20cb8aee._.js +0 -3
  317. package/.next/server/chunks/[root-of-the-server]__20cb8aee._.js.map +0 -1
  318. package/.next/server/chunks/[root-of-the-server]__22a29d25._.js +0 -6
  319. package/.next/server/chunks/[root-of-the-server]__22a29d25._.js.map +0 -1
  320. package/.next/server/chunks/[root-of-the-server]__2369d373._.js +0 -3
  321. package/.next/server/chunks/[root-of-the-server]__2369d373._.js.map +0 -1
  322. package/.next/server/chunks/[root-of-the-server]__24fa7b94._.js +0 -3
  323. package/.next/server/chunks/[root-of-the-server]__24fa7b94._.js.map +0 -1
  324. package/.next/server/chunks/[root-of-the-server]__2c9b0df9._.js +0 -3
  325. package/.next/server/chunks/[root-of-the-server]__2c9b0df9._.js.map +0 -1
  326. package/.next/server/chunks/[root-of-the-server]__2ffbbf0e._.js +0 -3
  327. package/.next/server/chunks/[root-of-the-server]__2ffbbf0e._.js.map +0 -1
  328. package/.next/server/chunks/[root-of-the-server]__394097c4._.js +0 -3
  329. package/.next/server/chunks/[root-of-the-server]__394097c4._.js.map +0 -1
  330. package/.next/server/chunks/[root-of-the-server]__457a879e._.js +0 -3
  331. package/.next/server/chunks/[root-of-the-server]__457a879e._.js.map +0 -1
  332. package/.next/server/chunks/[root-of-the-server]__4ae35c7d._.js +0 -3
  333. package/.next/server/chunks/[root-of-the-server]__4ae35c7d._.js.map +0 -1
  334. package/.next/server/chunks/[root-of-the-server]__4d1845bd._.js +0 -3
  335. package/.next/server/chunks/[root-of-the-server]__4d1845bd._.js.map +0 -1
  336. package/.next/server/chunks/[root-of-the-server]__593499ba._.js +0 -3
  337. package/.next/server/chunks/[root-of-the-server]__593499ba._.js.map +0 -1
  338. package/.next/server/chunks/[root-of-the-server]__69bcd4b9._.js +0 -3
  339. package/.next/server/chunks/[root-of-the-server]__69bcd4b9._.js.map +0 -1
  340. package/.next/server/chunks/[root-of-the-server]__7f23701b._.js +0 -3
  341. package/.next/server/chunks/[root-of-the-server]__7f23701b._.js.map +0 -1
  342. package/.next/server/chunks/[root-of-the-server]__8f127b48._.js +0 -3
  343. package/.next/server/chunks/[root-of-the-server]__8f127b48._.js.map +0 -1
  344. package/.next/server/chunks/[root-of-the-server]__93e05771._.js +0 -3
  345. package/.next/server/chunks/[root-of-the-server]__93e05771._.js.map +0 -1
  346. package/.next/server/chunks/[root-of-the-server]__9a65704e._.js +0 -3
  347. package/.next/server/chunks/[root-of-the-server]__9a65704e._.js.map +0 -1
  348. package/.next/server/chunks/[root-of-the-server]__b76a826e._.js +0 -3
  349. package/.next/server/chunks/[root-of-the-server]__b76a826e._.js.map +0 -1
  350. package/.next/server/chunks/[root-of-the-server]__baf1631b._.js +0 -3
  351. package/.next/server/chunks/[root-of-the-server]__baf1631b._.js.map +0 -1
  352. package/.next/server/chunks/[root-of-the-server]__bfd1044e._.js +0 -8
  353. package/.next/server/chunks/[root-of-the-server]__bfd1044e._.js.map +0 -1
  354. package/.next/server/chunks/[root-of-the-server]__c4a25b8f._.js +0 -3
  355. package/.next/server/chunks/[root-of-the-server]__c4a25b8f._.js.map +0 -1
  356. package/.next/server/chunks/[root-of-the-server]__c4e76686._.js +0 -3
  357. package/.next/server/chunks/[root-of-the-server]__c4e76686._.js.map +0 -1
  358. package/.next/server/chunks/[root-of-the-server]__c6906128._.js +0 -3
  359. package/.next/server/chunks/[root-of-the-server]__c6906128._.js.map +0 -1
  360. package/.next/server/chunks/[root-of-the-server]__c8eb444c._.js +0 -8
  361. package/.next/server/chunks/[root-of-the-server]__c8eb444c._.js.map +0 -1
  362. package/.next/server/chunks/[root-of-the-server]__e28b8399._.js +0 -3
  363. package/.next/server/chunks/[root-of-the-server]__e28b8399._.js.map +0 -1
  364. package/.next/server/chunks/[root-of-the-server]__e31f8972._.js +0 -10
  365. package/.next/server/chunks/[root-of-the-server]__e31f8972._.js.map +0 -1
  366. package/.next/server/chunks/[root-of-the-server]__fee3f59e._.js +0 -3
  367. package/.next/server/chunks/[root-of-the-server]__fee3f59e._.js.map +0 -1
  368. package/.next/server/chunks/[root-of-the-server]__fff0b9c4._.js +0 -6
  369. package/.next/server/chunks/[root-of-the-server]__fff0b9c4._.js.map +0 -1
  370. package/.next/server/chunks/ssr/[root-of-the-server]__277a8350._.js +0 -3
  371. package/.next/server/chunks/ssr/[root-of-the-server]__277a8350._.js.map +0 -1
  372. package/.next/server/chunks/ssr/[root-of-the-server]__7458e8cf._.js +0 -3
  373. package/.next/server/chunks/ssr/[root-of-the-server]__7458e8cf._.js.map +0 -1
  374. package/.next/server/chunks/ssr/[root-of-the-server]__8aa0b951._.js +0 -3
  375. package/.next/server/chunks/ssr/[root-of-the-server]__8aa0b951._.js.map +0 -1
  376. package/.next/server/chunks/ssr/[root-of-the-server]__91b2c698._.js +0 -3
  377. package/.next/server/chunks/ssr/[root-of-the-server]__91b2c698._.js.map +0 -1
  378. package/.next/server/chunks/ssr/[root-of-the-server]__ae77070e._.js.map +0 -1
  379. package/.next/server/chunks/ssr/[root-of-the-server]__c72e7548._.js.map +0 -1
  380. package/.next/server/chunks/ssr/node_modules_next_aefa2538._.js.map +0 -1
  381. package/.next/static/chunks/4fb7740933125c6a.js +0 -1
  382. /package/.next/server/chunks/{[root-of-the-server]__dc6c67a5._.js.map → [root-of-the-server]__74b80ca4._.js.map} +0 -0
  383. /package/.next/server/chunks/{[root-of-the-server]__94ebcd84._.js.map → [root-of-the-server]__b5c2b370._.js.map} +0 -0
  384. /package/.next/server/chunks/{[root-of-the-server]__920d7db4._.js.map → [root-of-the-server]__be5f57b2._.js.map} +0 -0
  385. /package/.next/server/chunks/ssr/{[root-of-the-server]__b6de1782._.js.map → [root-of-the-server]__507d2fc9._.js.map} +0 -0
  386. /package/.next/server/chunks/ssr/{[root-of-the-server]__72721a7e._.js.map → [root-of-the-server]__f75a61bf._.js.map} +0 -0
  387. /package/.next/static/{8pxUnfVjZMQrso_jWABg7 → uZkSG3UgZ81MwaAQa74zD}/_buildManifest.js +0 -0
  388. /package/.next/static/{8pxUnfVjZMQrso_jWABg7 → uZkSG3UgZ81MwaAQa74zD}/_clientMiddlewareManifest.json +0 -0
  389. /package/.next/static/{8pxUnfVjZMQrso_jWABg7 → uZkSG3UgZ81MwaAQa74zD}/_ssgManifest.js +0 -0
@@ -2,7 +2,7 @@
2
2
  "id": "kitchen",
3
3
  "name": "ClawKitchen",
4
4
  "description": "Local UI for managing OpenClaw recipes, teams, agents, cron jobs, and skills.",
5
- "version": "0.1.0",
5
+ "version": "0.1.6",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jiggai/kitchen",
3
- "version": "0.1.3",
3
+ "version": "0.1.7",
4
4
  "private": false,
5
5
  "openclaw": {
6
6
  "extensions": [
@@ -109,7 +109,7 @@ export default function AgentEditor({ agentId, returnTo }: { agentId: string; re
109
109
  const [agentFiles, setAgentFiles] = useState<Array<FileEntry & { required?: boolean; rationale?: string }>>([]);
110
110
  const [agentFilesLoading, setAgentFilesLoading] = useState(false);
111
111
  const [showOptionalFiles, setShowOptionalFiles] = useState(false);
112
- const [fileName, setFileName] = useState<string>("IDENTITY.md");
112
+ const [fileName, setFileName] = useState<string>("SOUL.md");
113
113
  const [fileContent, setFileContent] = useState<string>("");
114
114
 
115
115
  const teamId = agentId.includes("-") ? agentId.split("-").slice(0, -1).join("-") : "";
@@ -225,8 +225,6 @@ export default function AgentEditor({ agentId, returnTo }: { agentId: string; re
225
225
  setSaving(true);
226
226
  setPageMsg("");
227
227
 
228
- // Auto-clear after a moment (non-blocking).
229
- setTimeout(() => setPageMsg(""), 6000);
230
228
  try {
231
229
  const res = await fetch("/api/agents/update", {
232
230
  method: "POST",
@@ -261,7 +259,6 @@ export default function AgentEditor({ agentId, returnTo }: { agentId: string; re
261
259
  setFileContent(String(json.content ?? ""));
262
260
  } catch (e: unknown) {
263
261
  setFileError(e instanceof Error ? e.message : String(e));
264
- setTimeout(() => setFileError(""), 12000);
265
262
  } finally {
266
263
  setLoadingFile(false);
267
264
  }
@@ -288,6 +285,29 @@ export default function AgentEditor({ agentId, returnTo }: { agentId: string; re
288
285
  // eslint-disable-next-line react-hooks/exhaustive-deps
289
286
  }, [activeTab, agentId, agentFiles.length]);
290
287
 
288
+ function defaultFileContent(name: string) {
289
+ switch (name) {
290
+ case "SOUL.md":
291
+ return "# SOUL.md\n\n";
292
+ case "AGENTS.md":
293
+ return "# AGENTS.md\n\n";
294
+ case "TOOLS.md":
295
+ return "# TOOLS.md\n\n";
296
+ case "STATUS.md":
297
+ return "# STATUS.md\n\n- (empty)\n";
298
+ case "NOTES.md":
299
+ return "# NOTES.md\n\n- (empty)\n";
300
+ case "IDENTITY.md":
301
+ return "# IDENTITY.md\n\n- **Name:**\n- **Creature:**\n- **Vibe:**\n- **Emoji:**\n- **Avatar:**\n";
302
+ case "USER.md":
303
+ return "# USER.md\n\n";
304
+ case "HEARTBEAT.md":
305
+ return "# HEARTBEAT.md\n\n# Keep this file empty (or with only comments) to skip heartbeat API calls.\n";
306
+ default:
307
+ return "";
308
+ }
309
+ }
310
+
291
311
  async function onSaveAgentFile() {
292
312
  setSaving(true);
293
313
  setFileError("");
@@ -299,15 +319,28 @@ export default function AgentEditor({ agentId, returnTo }: { agentId: string; re
299
319
  });
300
320
  const json = (await res.json()) as { ok?: boolean; error?: string };
301
321
  if (!res.ok || !json.ok) throw new Error(json.error || "Failed to save file");
322
+
323
+ // Refresh the file list so missing/mtime updates immediately.
324
+ const r = await fetch(`/api/agents/files?agentId=${encodeURIComponent(agentId)}`, { cache: "no-store" });
325
+ const j = await r.json();
326
+ if (r.ok && j.ok && Array.isArray(j.files)) {
327
+ setAgentFiles(j.files);
328
+ }
302
329
  // No-op: saving a file doesn't need a global notice.
303
330
  } catch (e: unknown) {
304
331
  setFileError(e instanceof Error ? e.message : String(e));
305
- setTimeout(() => setFileError(""), 12000);
306
332
  } finally {
307
333
  setSaving(false);
308
334
  }
309
335
  }
310
336
 
337
+ async function onCreateMissingFile(name: string) {
338
+ setFileName(name);
339
+ setFileError("");
340
+ setFileContent(defaultFileContent(name));
341
+ await onSaveAgentFile();
342
+ }
343
+
311
344
  async function onDeleteAgent() {
312
345
  setDeleteBusy(true);
313
346
  setDeleteError(null);
@@ -533,14 +566,12 @@ export default function AgentEditor({ agentId, returnTo }: { agentId: string; re
533
566
  const json = await res.json();
534
567
  if (!res.ok || !json.ok) throw new Error(json.error || "Failed to install skill");
535
568
  setSkillMsg(`Installed skill: ${selectedSkill}`);
536
- setTimeout(() => setSkillMsg(""), 8000);
537
569
  // Refresh installed list.
538
570
  const r = await fetch(`/api/agents/skills?agentId=${encodeURIComponent(agentId)}`, { cache: "no-store" });
539
571
  const j = await r.json();
540
572
  if (r.ok && j.ok) setSkillsList(Array.isArray(j.skills) ? j.skills : []);
541
573
  } catch (e: unknown) {
542
574
  setSkillError(e instanceof Error ? e.message : String(e));
543
- setTimeout(() => setSkillError(""), 12000);
544
575
  } finally {
545
576
  setInstallingSkill(false);
546
577
  }
@@ -587,22 +618,34 @@ export default function AgentEditor({ agentId, returnTo }: { agentId: string; re
587
618
  .filter((f) => (showOptionalFiles ? true : Boolean(f.required) || !f.missing))
588
619
  .map((f) => (
589
620
  <li key={f.name}>
590
- <button
591
- onClick={() => onLoadAgentFile(f.name)}
592
- className={
593
- fileName === f.name
594
- ? "w-full rounded-[var(--ck-radius-sm)] bg-white/10 px-3 py-2 text-left text-sm text-[color:var(--ck-text-primary)]"
595
- : "w-full rounded-[var(--ck-radius-sm)] px-3 py-2 text-left text-sm text-[color:var(--ck-text-secondary)] hover:bg-white/5"
596
- }
597
- >
598
- <span className={f.required ? "text-[color:var(--ck-text-primary)]" : "text-[color:var(--ck-text-secondary)]"}>
599
- {f.name}
600
- </span>
601
- <span className="ml-2 text-[10px] uppercase tracking-wide text-[color:var(--ck-text-tertiary)]">
602
- {f.required ? "required" : "optional"}
603
- </span>
604
- {f.missing ? <span className="ml-2 text-xs text-[color:var(--ck-text-tertiary)]">missing</span> : null}
605
- </button>
621
+ <div className="flex items-center gap-2">
622
+ <button
623
+ onClick={() => onLoadAgentFile(f.name)}
624
+ className={
625
+ fileName === f.name
626
+ ? "w-full rounded-[var(--ck-radius-sm)] bg-white/10 px-3 py-2 text-left text-sm text-[color:var(--ck-text-primary)]"
627
+ : "w-full rounded-[var(--ck-radius-sm)] px-3 py-2 text-left text-sm text-[color:var(--ck-text-secondary)] hover:bg-white/5"
628
+ }
629
+ >
630
+ <span className={f.required ? "text-[color:var(--ck-text-primary)]" : "text-[color:var(--ck-text-secondary)]"}>
631
+ {f.name}
632
+ </span>
633
+ <span className="ml-2 text-[10px] uppercase tracking-wide text-[color:var(--ck-text-tertiary)]">
634
+ {f.required ? "required" : "optional"}
635
+ </span>
636
+ {f.missing ? <span className="ml-2 text-xs text-[color:var(--ck-text-tertiary)]">missing</span> : null}
637
+ </button>
638
+ {f.missing ? (
639
+ <button
640
+ type="button"
641
+ disabled={saving}
642
+ onClick={() => void onCreateMissingFile(f.name)}
643
+ className="shrink-0 rounded-[var(--ck-radius-sm)] border border-white/10 bg-white/5 px-2 py-1 text-xs font-medium text-[color:var(--ck-text-primary)] hover:bg-white/10 disabled:opacity-50"
644
+ >
645
+ Create
646
+ </button>
647
+ ) : null}
648
+ </div>
606
649
  </li>
607
650
  ))}
608
651
  </ul>
@@ -1,6 +1,9 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
1
3
  import { NextResponse } from "next/server";
2
4
 
3
5
  import { runOpenClaw } from "@/lib/openclaw";
6
+ import { parseTeamRoleWorkspace } from "@/lib/agent-workspace";
4
7
 
5
8
  export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
6
9
  try {
@@ -8,6 +11,17 @@ export async function DELETE(_req: Request, { params }: { params: Promise<{ id:
8
11
  const agentId = String(id ?? "").trim();
9
12
  if (!agentId) return NextResponse.json({ ok: false, error: "agent id is required" }, { status: 400 });
10
13
 
14
+ // Resolve workspace BEFORE deleting (after deletion it may disappear from list).
15
+ let workspace: string | null = null;
16
+ try {
17
+ const { stdout } = await runOpenClaw(["agents", "list", "--json"]);
18
+ const list = JSON.parse(stdout) as Array<{ id: string; workspace?: string }>;
19
+ const agent = list.find((a) => a.id === agentId);
20
+ workspace = agent?.workspace ? String(agent.workspace) : null;
21
+ } catch {
22
+ workspace = null;
23
+ }
24
+
11
25
  const result = await runOpenClaw(["agents", "delete", agentId, "--force", "--json"]);
12
26
  if (!result.ok) {
13
27
  return NextResponse.json(
@@ -28,6 +42,29 @@ export async function DELETE(_req: Request, { params }: { params: Promise<{ id:
28
42
  parsed = null;
29
43
  }
30
44
 
45
+ // If this was a team role agent, also remove its role directory.
46
+ // Safer than rm: move to a team-local .trash folder.
47
+ if (workspace) {
48
+ const info = parseTeamRoleWorkspace(workspace);
49
+ if (info.kind === "teamRole") {
50
+ const trashDir = path.join(info.teamDir, ".trash", "roles");
51
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
52
+ const dst = path.join(trashDir, `${info.role}-${ts}`);
53
+ try {
54
+ await fs.mkdir(trashDir, { recursive: true });
55
+ // Only move if the dir exists.
56
+ await fs.rename(info.roleDir, dst);
57
+ } catch {
58
+ // If rename fails (cross-device / missing), fall back to best-effort recursive removal.
59
+ try {
60
+ await fs.rm(info.roleDir, { recursive: true, force: true });
61
+ } catch {
62
+ // ignore
63
+ }
64
+ }
65
+ }
66
+ }
67
+
31
68
  return NextResponse.json({ ok: true, result: parsed ?? result.stdout });
32
69
  } catch (err: unknown) {
33
70
  return NextResponse.json(
@@ -1,11 +1,10 @@
1
- import { execFile } from "node:child_process";
2
1
  import fs from "node:fs/promises";
2
+ import os from "node:os";
3
3
  import path from "node:path";
4
- import { promisify } from "node:util";
5
4
 
6
5
  import { NextResponse } from "next/server";
7
6
 
8
- const execFileAsync = promisify(execFile);
7
+ import { getKitchenApi } from "@/lib/kitchen-api";
9
8
 
10
9
  function normalizeAgentId(id: string) {
11
10
  const s = id.trim();
@@ -32,9 +31,9 @@ export async function POST(req: Request) {
32
31
  const newAgentId = normalizeAgentId(String(body.newAgentId ?? body.agentId ?? ""));
33
32
  const overwrite = Boolean(body.overwrite);
34
33
 
35
- const configPath = path.join(process.env.HOME || "", ".openclaw", "openclaw.json");
36
- if (!process.env.HOME) {
37
- return NextResponse.json({ ok: false, error: "HOME is not set" }, { status: 500 });
34
+ const configPath = path.join(os.homedir(), ".openclaw", "openclaw.json");
35
+ if (!configPath.trim()) {
36
+ return NextResponse.json({ ok: false, error: "Could not resolve config path" }, { status: 500 });
38
37
  }
39
38
 
40
39
  const raw = await fs.readFile(configPath, "utf8");
@@ -95,7 +94,8 @@ export async function POST(req: Request) {
95
94
  await fs.rename(tmpPath, configPath);
96
95
 
97
96
  // Restart gateway so the new agent is live.
98
- await execFileAsync("openclaw", ["gateway", "restart"], { timeout: 120000 });
97
+ const api = getKitchenApi();
98
+ await api.runtime.system.runCommandWithTimeout(["openclaw", "gateway", "restart"], { timeoutMs: 120000 });
99
99
 
100
100
  return NextResponse.json({ ok: true, agentId: newAgentId, workspace: newWorkspace, restarted: true });
101
101
  } catch (err) {
@@ -26,11 +26,13 @@ export async function GET(req: Request) {
26
26
 
27
27
  // Required vs optional classification to avoid "missing" noise.
28
28
  const candidates: Array<{ name: string; required: boolean; rationale: string }> = [
29
- { name: "IDENTITY.md", required: true, rationale: "Identity (name/emoji/avatar)" },
30
29
  { name: "SOUL.md", required: true, rationale: "Agent persona/instructions" },
31
30
  { name: "AGENTS.md", required: true, rationale: "Agent operating rules" },
32
31
  { name: "TOOLS.md", required: true, rationale: "Agent local notes" },
33
32
 
33
+ { name: "STATUS.md", required: false, rationale: "Optional current status snapshot" },
34
+ { name: "NOTES.md", required: false, rationale: "Optional scratchpad" },
35
+ { name: "IDENTITY.md", required: false, rationale: "Optional identity (name/emoji/avatar)" },
34
36
  { name: "USER.md", required: false, rationale: "Optional user profile" },
35
37
  { name: "HEARTBEAT.md", required: false, rationale: "Optional periodic checklist" },
36
38
  ];
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { runOpenClaw } from "@/lib/openclaw";
3
+ import { parseTeamRoleWorkspace } from "@/lib/agent-workspace";
3
4
 
4
5
  export async function POST(req: Request) {
5
6
  const body = (await req.json()) as { agentId?: string; skill?: string };
@@ -9,14 +10,37 @@ export async function POST(req: Request) {
9
10
  if (!agentId) return NextResponse.json({ ok: false, error: "agentId is required" }, { status: 400 });
10
11
  if (!skill) return NextResponse.json({ ok: false, error: "skill is required" }, { status: 400 });
11
12
 
12
- const args = ["recipes", "install-skill", skill, "--agent-id", agentId, "--yes"];
13
+ // For role-based team agents, install at team scope to avoid creating a separate
14
+ // workspace-<agentId> directory that diverges from roles/<role>.
15
+ let args = ["recipes", "install-skill", skill, "--agent-id", agentId, "--yes"];
16
+ try {
17
+ const { stdout } = await runOpenClaw(["agents", "list", "--json"]);
18
+ const list = JSON.parse(stdout) as Array<{ id: string; workspace?: string }>;
19
+ const agent = list.find((a) => a.id === agentId);
20
+ const ws = agent?.workspace ? String(agent.workspace) : "";
21
+ const info = parseTeamRoleWorkspace(ws);
22
+ if (info.kind === "teamRole") {
23
+ args = ["recipes", "install-skill", skill, "--team-id", info.teamId, "--yes"];
24
+ }
25
+ } catch {
26
+ // If anything goes wrong, fall back to agent scope.
27
+ }
28
+
13
29
  const res = await runOpenClaw(args);
14
30
  if (!res.ok) {
31
+ const stdout = res.stdout?.trim();
32
+ const stderr = res.stderr?.trim();
15
33
  return NextResponse.json(
16
- { ok: false, error: res.stderr.trim() || `openclaw ${args.join(" ")} failed (exit=${res.exitCode})`, stdout: res.stdout, stderr: res.stderr },
34
+ {
35
+ ok: false,
36
+ error: stderr || stdout || `openclaw ${args.join(" ")} failed (exit=${res.exitCode})`,
37
+ stdout: res.stdout,
38
+ stderr: res.stderr,
39
+ scopeArgs: args,
40
+ },
17
41
  { status: 500 },
18
42
  );
19
43
  }
20
44
 
21
- return NextResponse.json({ ok: true, agentId, skill, stdout: res.stdout, stderr: res.stderr });
45
+ return NextResponse.json({ ok: true, agentId, skill, scopeArgs: args, stdout: res.stdout, stderr: res.stderr });
22
46
  }
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { NextResponse } from "next/server";
4
4
  import { runOpenClaw } from "@/lib/openclaw";
5
+ import { parseTeamRoleWorkspace } from "@/lib/agent-workspace";
5
6
 
6
7
  type AgentListItem = { id: string; workspace?: string };
7
8
 
@@ -19,17 +20,32 @@ export async function GET(req: Request) {
19
20
  if (!agentId) return NextResponse.json({ ok: false, error: "agentId is required" }, { status: 400 });
20
21
 
21
22
  const ws = await resolveAgentWorkspace(agentId);
22
- const skillsDir = path.join(ws, "skills");
23
-
24
- try {
25
- const entries = await fs.readdir(skillsDir, { withFileTypes: true });
26
- const skills = entries
27
- .filter((e) => e.isDirectory())
28
- .map((e) => e.name)
29
- .sort((a, b) => a.localeCompare(b));
30
-
31
- return NextResponse.json({ ok: true, agentId, workspace: ws, skillsDir, skills });
32
- } catch (e: unknown) {
33
- return NextResponse.json({ ok: true, agentId, workspace: ws, skillsDir, skills: [], note: e instanceof Error ? e.message : String(e) });
23
+
24
+ const info = parseTeamRoleWorkspace(ws);
25
+ const dirs: string[] = [path.join(ws, "skills")];
26
+ if (info.kind === "teamRole") {
27
+ // If skills were installed at the team scope, surface them for the role agent too.
28
+ dirs.push(path.join(info.teamDir, "skills"));
34
29
  }
30
+
31
+ const skills = new Set<string>();
32
+ const notes: string[] = [];
33
+
34
+ for (const skillsDir of dirs) {
35
+ try {
36
+ const entries = await fs.readdir(skillsDir, { withFileTypes: true });
37
+ for (const e of entries) if (e.isDirectory()) skills.add(e.name);
38
+ } catch (e: unknown) {
39
+ notes.push(`${skillsDir}: ${e instanceof Error ? e.message : String(e)}`);
40
+ }
41
+ }
42
+
43
+ return NextResponse.json({
44
+ ok: true,
45
+ agentId,
46
+ workspace: ws,
47
+ skillsDirs: dirs,
48
+ skills: Array.from(skills).sort((a, b) => a.localeCompare(b)),
49
+ note: notes.length ? notes.join("; ") : undefined,
50
+ });
35
51
  }
@@ -1,14 +1,11 @@
1
- import { execFile } from "node:child_process";
2
1
  import fs from "node:fs/promises";
3
2
  import path from "node:path";
4
- import { promisify } from "node:util";
5
3
 
6
4
  import { NextResponse } from "next/server";
7
5
 
8
6
  import { readGoal, writeGoal } from "@/lib/goals";
9
7
  import { getTeamWorkspaceDir, readOpenClawConfig } from "@/lib/paths";
10
-
11
- const execFileAsync = promisify(execFile);
8
+ import { runOpenClaw } from "@/lib/openclaw";
12
9
 
13
10
  function slugifyFilePart(input: string) {
14
11
  return input
@@ -122,20 +119,17 @@ export async function POST(_: Request, { params }: { params: Promise<{ id: strin
122
119
  } else {
123
120
  pingAttempted = true;
124
121
  try {
125
- await execFileAsync(
126
- "openclaw",
127
- [
128
- "agent",
129
- "--agent",
130
- targetAgentId,
131
- "--message",
132
- `New goal promoted to development-team inbox: ${updated.frontmatter.title} (${goalId}). Inbox file: ${inboxPath}`,
133
- "--timeout",
134
- "60",
135
- "--json",
136
- ],
137
- { timeout: 70000 },
138
- );
122
+ const res = await runOpenClaw([
123
+ "agent",
124
+ "--agent",
125
+ targetAgentId,
126
+ "--message",
127
+ `New goal promoted to development-team inbox: ${updated.frontmatter.title} (${goalId}). Inbox file: ${inboxPath}`,
128
+ "--timeout",
129
+ "60",
130
+ "--json",
131
+ ]);
132
+ if (!res.ok) throw new Error(res.stderr || `openclaw exit ${res.exitCode}`);
139
133
  pingOk = true;
140
134
  } catch (e: unknown) {
141
135
  pingReason = e instanceof Error ? e.message : String(e);
@@ -65,7 +65,7 @@ export async function POST(req: Request) {
65
65
  templatesRaw && typeof templatesRaw === "object" && !Array.isArray(templatesRaw)
66
66
  ? (templatesRaw as Record<string, unknown>)
67
67
  : {};
68
- let nextTemplates: Record<string, unknown> = { ...templates };
68
+ const nextTemplates: Record<string, unknown> = { ...templates };
69
69
 
70
70
  if (op === "remove") {
71
71
  const role = normalizeRole(String(body.role ?? ""));
@@ -12,10 +12,12 @@ export async function POST(req: Request) {
12
12
  const args = ["recipes", "install-skill", skill, "--team-id", teamId, "--yes"];
13
13
  const res = await runOpenClaw(args);
14
14
  if (!res.ok) {
15
+ const stdout = res.stdout?.trim();
16
+ const stderr = res.stderr?.trim();
15
17
  return NextResponse.json(
16
18
  {
17
19
  ok: false,
18
- error: res.stderr.trim() || `openclaw ${args.join(" ")} failed (exit=${res.exitCode})`,
20
+ error: stderr || stdout || `openclaw ${args.join(" ")} failed (exit=${res.exitCode})`,
19
21
  stdout: res.stdout,
20
22
  stderr: res.stderr,
21
23
  },
@@ -1,8 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
- import { execFile } from "node:child_process";
3
- import { promisify } from "node:util";
4
2
 
5
- const execFileAsync = promisify(execFile);
3
+ import { runOpenClaw } from "@/lib/openclaw";
6
4
 
7
5
  export async function POST(req: Request) {
8
6
  try {
@@ -29,7 +27,8 @@ export async function POST(req: Request) {
29
27
  "--yes",
30
28
  ];
31
29
 
32
- await execFileAsync("openclaw", args, { timeout: 30_000 });
30
+ const res = await runOpenClaw(args);
31
+ if (!res.ok) throw new Error(res.stderr || `openclaw exit ${res.exitCode}`);
33
32
 
34
33
  return NextResponse.json({ ok: true });
35
34
  } catch (err: unknown) {
@@ -1,7 +1,12 @@
1
1
  import Link from "next/link";
2
+ import { unstable_noStore as noStore } from "next/cache";
3
+
2
4
  import { runOpenClaw } from "@/lib/openclaw";
3
5
  import RecipeEditor from "./RecipeEditor";
4
6
 
7
+ export const dynamic = "force-dynamic";
8
+ export const revalidate = 0;
9
+
5
10
  type RecipeListItem = {
6
11
  id: string;
7
12
  name: string;
@@ -21,6 +26,8 @@ async function getKind(id: string): Promise<"agent" | "team" | null> {
21
26
  }
22
27
 
23
28
  export default async function RecipePage({ params }: { params: Promise<{ id: string }> }) {
29
+ noStore();
30
+
24
31
  const { id } = await params;
25
32
  const kind = await getKind(id);
26
33
 
@@ -1,7 +1,12 @@
1
1
  import Link from "next/link";
2
+ import { unstable_noStore as noStore } from "next/cache";
3
+
2
4
  import { runOpenClaw } from "@/lib/openclaw";
3
5
  import RecipesClient from "./recipes-client";
4
6
 
7
+ export const dynamic = "force-dynamic";
8
+ export const revalidate = 0;
9
+
5
10
  type Recipe = {
6
11
  id: string;
7
12
  name: string;
@@ -39,6 +44,8 @@ async function getAgents(): Promise<{ agentIds: string[]; error: string | null }
39
44
  }
40
45
 
41
46
  export default async function RecipesPage() {
47
+ noStore();
48
+
42
49
  const [{ recipes, error }, { agentIds }] = await Promise.all([getRecipes(), getAgents()]);
43
50
 
44
51
  const builtin = recipes.filter((r) => r.source === "builtin");
@@ -126,7 +126,6 @@ export default function RecipesClient({
126
126
 
127
127
  const [overlayOpen, setOverlayOpen] = useState(false);
128
128
  const [overlayStep, setOverlayStep] = useState<ScaffoldOverlayStep>(1);
129
- const [overlayDetails, setOverlayDetails] = useState<string>("");
130
129
  const router = useRouter();
131
130
 
132
131
  const [deleteOpen, setDeleteOpen] = useState(false);
@@ -266,7 +265,6 @@ export default function RecipesClient({
266
265
 
267
266
  setOverlayOpen(true);
268
267
  setOverlayStep(1);
269
- setOverlayDetails("");
270
268
 
271
269
  let serveTimer: ReturnType<typeof setTimeout> | null = null;
272
270
 
@@ -295,7 +293,6 @@ export default function RecipesClient({
295
293
  }, 20_000);
296
294
 
297
295
  const stderr = typeof json.stderr === "string" ? json.stderr : "";
298
- if (stderr.trim()) setOverlayDetails(stderr.trim());
299
296
 
300
297
  // Some CLI failures currently still surface as { ok: true, stderr: "...Error: ..." }.
301
298
  // Treat those as hard failures so we don't navigate into a broken team page.
@@ -361,7 +358,6 @@ export default function RecipesClient({
361
358
 
362
359
  setOverlayOpen(true);
363
360
  setOverlayStep(1);
364
- setOverlayDetails("");
365
361
 
366
362
  let serveTimer: ReturnType<typeof setTimeout> | null = null;
367
363
 
@@ -388,7 +384,6 @@ export default function RecipesClient({
388
384
  }, 20_000);
389
385
 
390
386
  const stderr = typeof json.stderr === "string" ? json.stderr : "";
391
- if (stderr.trim()) setOverlayDetails(stderr.trim());
392
387
 
393
388
  if (/Failed to start CLI:/i.test(stderr) || /\bError: /i.test(stderr)) {
394
389
  throw new Error(stderr.trim() || "Scaffold failed");
@@ -0,0 +1,14 @@
1
+ import path from "node:path";
2
+
3
+ export function parseTeamRoleWorkspace(ws: string):
4
+ | { kind: "teamRole"; teamDir: string; teamId: string; roleDir: string; role: string }
5
+ | { kind: "other" } {
6
+ const normalized = ws.replace(/\\/g, "/");
7
+ const m = normalized.match(/^(.*\/workspace-([^\/]+))\/roles\/([^\/]+)\/?$/);
8
+ if (!m) return { kind: "other" };
9
+ const teamDir = m[1];
10
+ const teamId = m[2];
11
+ const role = m[3];
12
+ const roleDir = path.join(teamDir, "roles", role);
13
+ return { kind: "teamRole", teamDir, teamId, roleDir, role };
14
+ }
@@ -27,17 +27,14 @@ type ToolTextEnvelope = {
27
27
  };
28
28
 
29
29
  async function getGatewayBaseUrlAndToken() {
30
- // Allow running ClawKitchen on a different host than the OpenClaw gateway.
31
- // Useful for remote dev/prod deployments where the gateway lives elsewhere.
32
- const envUrl = (process.env.OPENCLAW_GATEWAY_HTTP_URL || process.env.OPENCLAW_GATEWAY_URL || "").trim();
33
- const envToken = (process.env.OPENCLAW_GATEWAY_TOKEN || "").trim();
34
-
30
+ // ClawKitchen runs in-process with the OpenClaw Gateway (as a plugin), so we can read
31
+ // the gateway port/token from the loaded config.
35
32
  const cfg = await readOpenClawConfig();
36
33
  const port = cfg.gateway?.port ?? 18789;
37
- const token = envToken || cfg.gateway?.auth?.token;
38
- if (!token) throw new Error("Missing gateway token. Set OPENCLAW_GATEWAY_TOKEN or gateway.auth.token in ~/.openclaw/openclaw.json");
34
+ const token = cfg.gateway?.auth?.token;
35
+ if (!token) throw new Error("Missing gateway token (gateway.auth.token in ~/.openclaw/openclaw.json)");
39
36
 
40
- const baseUrl = envUrl || `http://127.0.0.1:${port}`;
37
+ const baseUrl = `http://127.0.0.1:${port}`;
41
38
  return { baseUrl, token };
42
39
  }
43
40
 
@@ -0,0 +1,19 @@
1
+ // NOTE: This file is compiled by Next.js.
2
+ // Do not import `openclaw/plugin-sdk` here (it is provided by the gateway runtime, not as an npm dep).
3
+
4
+ type KitchenApi = {
5
+ config: unknown;
6
+ runtime: {
7
+ system: { runCommandWithTimeout: (argv: string[], opts: { timeoutMs: number }) => Promise<{ stdout?: string; stderr?: string }> };
8
+ };
9
+ };
10
+
11
+ export function getKitchenApi(): KitchenApi {
12
+ const api = (globalThis as unknown as { __clawkitchen_api?: KitchenApi }).__clawkitchen_api;
13
+ if (!api) {
14
+ throw new Error(
15
+ "ClawKitchen: OpenClaw plugin API not available. (This should only happen if Kitchen is started outside the gateway process.)",
16
+ );
17
+ }
18
+ return api;
19
+ }