@jiggai/kitchen 0.3.1 → 0.3.3

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 (307) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +2 -2
  3. package/.next/server/app/_global-error.html +2 -2
  4. package/.next/server/app/_global-error.rsc +1 -1
  5. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  6. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/.next/server/app/_not-found.html +1 -1
  11. package/.next/server/app/_not-found.rsc +1 -1
  12. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  13. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  14. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  18. package/.next/server/app/channels.html +2 -2
  19. package/.next/server/app/channels.rsc +1 -1
  20. package/.next/server/app/channels.segments/_full.segment.rsc +1 -1
  21. package/.next/server/app/channels.segments/_head.segment.rsc +1 -1
  22. package/.next/server/app/channels.segments/_index.segment.rsc +1 -1
  23. package/.next/server/app/channels.segments/_tree.segment.rsc +1 -1
  24. package/.next/server/app/channels.segments/channels/__PAGE__.segment.rsc +1 -1
  25. package/.next/server/app/channels.segments/channels.segment.rsc +1 -1
  26. package/.next/server/app/cron-jobs.html +1 -1
  27. package/.next/server/app/cron-jobs.rsc +1 -1
  28. package/.next/server/app/cron-jobs.segments/_full.segment.rsc +1 -1
  29. package/.next/server/app/cron-jobs.segments/_head.segment.rsc +1 -1
  30. package/.next/server/app/cron-jobs.segments/_index.segment.rsc +1 -1
  31. package/.next/server/app/cron-jobs.segments/_tree.segment.rsc +1 -1
  32. package/.next/server/app/cron-jobs.segments/cron-jobs/__PAGE__.segment.rsc +1 -1
  33. package/.next/server/app/cron-jobs.segments/cron-jobs.segment.rsc +1 -1
  34. package/.next/server/app/goals/new.html +2 -2
  35. package/.next/server/app/goals/new.rsc +1 -1
  36. package/.next/server/app/goals/new.segments/_full.segment.rsc +1 -1
  37. package/.next/server/app/goals/new.segments/_head.segment.rsc +1 -1
  38. package/.next/server/app/goals/new.segments/_index.segment.rsc +1 -1
  39. package/.next/server/app/goals/new.segments/_tree.segment.rsc +1 -1
  40. package/.next/server/app/goals/new.segments/goals/new/__PAGE__.segment.rsc +1 -1
  41. package/.next/server/app/goals/new.segments/goals/new.segment.rsc +1 -1
  42. package/.next/server/app/goals/new.segments/goals.segment.rsc +1 -1
  43. package/.next/server/app/goals.html +1 -1
  44. package/.next/server/app/goals.rsc +1 -1
  45. package/.next/server/app/goals.segments/_full.segment.rsc +1 -1
  46. package/.next/server/app/goals.segments/_head.segment.rsc +1 -1
  47. package/.next/server/app/goals.segments/_index.segment.rsc +1 -1
  48. package/.next/server/app/goals.segments/_tree.segment.rsc +1 -1
  49. package/.next/server/app/goals.segments/goals/__PAGE__.segment.rsc +1 -1
  50. package/.next/server/app/goals.segments/goals.segment.rsc +1 -1
  51. package/.next/server/app/settings.html +1 -1
  52. package/.next/server/app/settings.rsc +1 -1
  53. package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  54. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  55. package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  56. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  57. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  58. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  59. package/.next/server/pages/404.html +1 -1
  60. package/.next/server/pages/500.html +2 -2
  61. package/package.json +1 -2
  62. package/src/app/HomeClient.tsx +0 -207
  63. package/src/app/agents/[agentId]/agent-editor-tabs.tsx +0 -298
  64. package/src/app/agents/[agentId]/agent-editor.tsx +0 -468
  65. package/src/app/agents/[agentId]/page.tsx +0 -32
  66. package/src/app/api/__tests__/agents-add-route.test.ts +0 -143
  67. package/src/app/api/__tests__/agents-file-route.test.ts +0 -117
  68. package/src/app/api/__tests__/agents-files-route.test.ts +0 -61
  69. package/src/app/api/__tests__/agents-id-route.test.ts +0 -104
  70. package/src/app/api/__tests__/agents-identity-route.test.ts +0 -92
  71. package/src/app/api/__tests__/agents-route.test.ts +0 -54
  72. package/src/app/api/__tests__/agents-skills-install-route.test.ts +0 -131
  73. package/src/app/api/__tests__/agents-skills-route.test.ts +0 -64
  74. package/src/app/api/__tests__/agents-update-route.test.ts +0 -95
  75. package/src/app/api/__tests__/channels-bindings-route.test.ts +0 -143
  76. package/src/app/api/__tests__/cron-delete-route.test.ts +0 -93
  77. package/src/app/api/__tests__/cron-job-route.test.ts +0 -78
  78. package/src/app/api/__tests__/cron-jobs-route.test.ts +0 -116
  79. package/src/app/api/__tests__/cron-recipe-installed-route.test.ts +0 -114
  80. package/src/app/api/__tests__/gateway-restart-route.test.ts +0 -36
  81. package/src/app/api/__tests__/goals-promote-route.test.ts +0 -200
  82. package/src/app/api/__tests__/goals-route.test.ts +0 -184
  83. package/src/app/api/__tests__/ids-check-route.test.ts +0 -188
  84. package/src/app/api/__tests__/marketplace-recipes-route.test.ts +0 -123
  85. package/src/app/api/__tests__/recipes-clone-route.test.ts +0 -221
  86. package/src/app/api/__tests__/recipes-delete-route.test.ts +0 -248
  87. package/src/app/api/__tests__/recipes-id-route.test.ts +0 -166
  88. package/src/app/api/__tests__/recipes-route.test.ts +0 -57
  89. package/src/app/api/__tests__/recipes-team-agents-route.test.ts +0 -135
  90. package/src/app/api/__tests__/scaffold-route.test.ts +0 -173
  91. package/src/app/api/__tests__/settings-cron-installation-route.test.ts +0 -82
  92. package/src/app/api/__tests__/skills-available-route.test.ts +0 -47
  93. package/src/app/api/__tests__/swarms-start-route.test.ts +0 -79
  94. package/src/app/api/__tests__/swarms-status-route.test.ts +0 -42
  95. package/src/app/api/__tests__/teams-file-route.test.ts +0 -129
  96. package/src/app/api/__tests__/teams-files-route.test.ts +0 -57
  97. package/src/app/api/__tests__/teams-meta-route.test.ts +0 -113
  98. package/src/app/api/__tests__/teams-orchestrator-install-route.test.ts +0 -66
  99. package/src/app/api/__tests__/teams-orchestrator-route.test.ts +0 -59
  100. package/src/app/api/__tests__/teams-remove-team-route.test.ts +0 -122
  101. package/src/app/api/__tests__/teams-skills-install-route.test.ts +0 -78
  102. package/src/app/api/__tests__/teams-skills-route.test.ts +0 -73
  103. package/src/app/api/__tests__/teams-workflow-runs-route.test.ts +0 -85
  104. package/src/app/api/__tests__/teams-workflows-route.test.ts +0 -110
  105. package/src/app/api/__tests__/tickets-move-route.test.ts +0 -60
  106. package/src/app/api/agents/[id]/route.ts +0 -83
  107. package/src/app/api/agents/add/route.ts +0 -114
  108. package/src/app/api/agents/file/route.ts +0 -45
  109. package/src/app/api/agents/files/route.ts +0 -23
  110. package/src/app/api/agents/identity/route.ts +0 -41
  111. package/src/app/api/agents/route.ts +0 -22
  112. package/src/app/api/agents/skills/install/route.ts +0 -34
  113. package/src/app/api/agents/skills/route.ts +0 -39
  114. package/src/app/api/agents/update/route.ts +0 -52
  115. package/src/app/api/channels/bindings/route.ts +0 -63
  116. package/src/app/api/cron/__tests__/helpers.test.ts +0 -164
  117. package/src/app/api/cron/delete/route.ts +0 -23
  118. package/src/app/api/cron/helpers.ts +0 -172
  119. package/src/app/api/cron/job/route.ts +0 -22
  120. package/src/app/api/cron/jobs/route.ts +0 -52
  121. package/src/app/api/cron/recipe-installed/route.ts +0 -65
  122. package/src/app/api/gateway/restart/route.ts +0 -20
  123. package/src/app/api/goals/[id]/promote/route.ts +0 -119
  124. package/src/app/api/goals/[id]/route.ts +0 -54
  125. package/src/app/api/goals/route.ts +0 -44
  126. package/src/app/api/ids/check/route.ts +0 -113
  127. package/src/app/api/marketplace/recipes/[slug]/route.ts +0 -16
  128. package/src/app/api/marketplace/recipes/route.ts +0 -22
  129. package/src/app/api/recipes/[id]/route.ts +0 -62
  130. package/src/app/api/recipes/clone/route.ts +0 -106
  131. package/src/app/api/recipes/custom-team/route.ts +0 -193
  132. package/src/app/api/recipes/delete/helpers.ts +0 -65
  133. package/src/app/api/recipes/delete/route.ts +0 -73
  134. package/src/app/api/recipes/route.ts +0 -21
  135. package/src/app/api/recipes/team-agents/__tests__/helpers.test.ts +0 -156
  136. package/src/app/api/recipes/team-agents/helpers.ts +0 -151
  137. package/src/app/api/recipes/team-agents/route.ts +0 -80
  138. package/src/app/api/scaffold/__tests__/helpers.test.ts +0 -186
  139. package/src/app/api/scaffold/helpers.ts +0 -214
  140. package/src/app/api/scaffold/route.ts +0 -95
  141. package/src/app/api/settings/cron-installation/route.ts +0 -58
  142. package/src/app/api/skills/available/route.ts +0 -23
  143. package/src/app/api/swarms/start/route.ts +0 -100
  144. package/src/app/api/swarms/status/route.ts +0 -31
  145. package/src/app/api/teams/[teamId]/tickets/assign/route.ts +0 -105
  146. package/src/app/api/teams/[teamId]/tickets/assignees/route.ts +0 -27
  147. package/src/app/api/teams/[teamId]/tickets/delete/route.ts +0 -55
  148. package/src/app/api/teams/[teamId]/tickets/move/route.ts +0 -70
  149. package/src/app/api/teams/[teamId]/tickets/move-to-goals/route.ts +0 -56
  150. package/src/app/api/teams/file/route.ts +0 -46
  151. package/src/app/api/teams/files/route.ts +0 -63
  152. package/src/app/api/teams/memory/route.ts +0 -250
  153. package/src/app/api/teams/meta/route.ts +0 -43
  154. package/src/app/api/teams/orchestrator/install/route.ts +0 -129
  155. package/src/app/api/teams/orchestrator/route.ts +0 -216
  156. package/src/app/api/teams/remove-team/route.ts +0 -37
  157. package/src/app/api/teams/skills/install/route.ts +0 -18
  158. package/src/app/api/teams/skills/route.ts +0 -25
  159. package/src/app/api/teams/workflow-runs/route.ts +0 -534
  160. package/src/app/api/teams/workflow-templates/route.ts +0 -71
  161. package/src/app/api/teams/workflows/route.ts +0 -55
  162. package/src/app/api/tickets/assign/route.ts +0 -94
  163. package/src/app/api/tickets/assignees/route.ts +0 -24
  164. package/src/app/api/tickets/move/route.ts +0 -69
  165. package/src/app/channels/channels-client.tsx +0 -271
  166. package/src/app/channels/page.tsx +0 -5
  167. package/src/app/cron-jobs/cron-jobs-client.tsx +0 -243
  168. package/src/app/cron-jobs/page.tsx +0 -34
  169. package/src/app/favicon.ico +0 -0
  170. package/src/app/global-error.tsx +0 -50
  171. package/src/app/globals.css +0 -153
  172. package/src/app/goals/[id]/goal-editor.tsx +0 -162
  173. package/src/app/goals/[id]/page.tsx +0 -6
  174. package/src/app/goals/goals-client.tsx +0 -201
  175. package/src/app/goals/new/page.tsx +0 -81
  176. package/src/app/goals/page.tsx +0 -10
  177. package/src/app/layout.tsx +0 -53
  178. package/src/app/manifest.ts +0 -15
  179. package/src/app/not-found.tsx +0 -8
  180. package/src/app/page.tsx +0 -33
  181. package/src/app/recipes/CreateAgentModal.tsx +0 -156
  182. package/src/app/recipes/CreateCustomTeamModal.tsx +0 -375
  183. package/src/app/recipes/CreateModalShell.tsx +0 -55
  184. package/src/app/recipes/CreateTeamModal.tsx +0 -91
  185. package/src/app/recipes/[id]/RecipeEditor/RecipeEditorCreateModal.tsx +0 -72
  186. package/src/app/recipes/[id]/RecipeEditor/RecipeEditorPanel.tsx +0 -216
  187. package/src/app/recipes/[id]/RecipeEditor/index.tsx +0 -271
  188. package/src/app/recipes/[id]/RecipeEditor/recipe-editor-utils.ts +0 -46
  189. package/src/app/recipes/[id]/RecipeEditor/types.ts +0 -52
  190. package/src/app/recipes/[id]/page.tsx +0 -37
  191. package/src/app/recipes/page.tsx +0 -101
  192. package/src/app/recipes/recipes-client.tsx +0 -620
  193. package/src/app/settings/page.tsx +0 -26
  194. package/src/app/settings/settings-client.tsx +0 -91
  195. package/src/app/teams/[teamId]/CloneTeamModal.tsx +0 -116
  196. package/src/app/teams/[teamId]/OrchestratorPanel.tsx +0 -255
  197. package/src/app/teams/[teamId]/OrchestratorSetupModal.tsx +0 -184
  198. package/src/app/teams/[teamId]/PublishChangesModal.tsx +0 -43
  199. package/src/app/teams/[teamId]/page.tsx +0 -49
  200. package/src/app/teams/[teamId]/team-editor/TeamAgentsTab.tsx +0 -145
  201. package/src/app/teams/[teamId]/team-editor/TeamCronTab.tsx +0 -72
  202. package/src/app/teams/[teamId]/team-editor/TeamFilesTab.tsx +0 -74
  203. package/src/app/teams/[teamId]/team-editor/TeamMemoryTab.tsx +0 -349
  204. package/src/app/teams/[teamId]/team-editor/TeamRecipeTab.tsx +0 -151
  205. package/src/app/teams/[teamId]/team-editor/TeamSkillsTab.tsx +0 -68
  206. package/src/app/teams/[teamId]/team-editor/index.tsx +0 -558
  207. package/src/app/teams/[teamId]/team-editor/team-editor-data.ts +0 -255
  208. package/src/app/teams/[teamId]/team-editor/team-editor-utils.ts +0 -78
  209. package/src/app/teams/[teamId]/team-editor/types.ts +0 -34
  210. package/src/app/teams/[teamId]/tickets/[ticket]/page.tsx +0 -35
  211. package/src/app/teams/[teamId]/tickets/page.tsx +0 -15
  212. package/src/app/teams/[teamId]/workflows/[workflowId]/WorkflowCanvas.tsx +0 -111
  213. package/src/app/teams/[teamId]/workflows/[workflowId]/page.tsx +0 -27
  214. package/src/app/teams/[teamId]/workflows/[workflowId]/workflows-editor-client.tsx +0 -1608
  215. package/src/app/teams/[teamId]/workflows/page.tsx +0 -40
  216. package/src/app/teams/[teamId]/workflows/workflows-client.tsx +0 -494
  217. package/src/app/tickets/TicketDetailClient.tsx +0 -147
  218. package/src/app/tickets/TicketsBoardClient.tsx +0 -200
  219. package/src/app/tickets/[ticket]/TicketAssignControl.tsx +0 -112
  220. package/src/app/tickets/[ticket]/page.tsx +0 -36
  221. package/src/app/tickets/page.tsx +0 -10
  222. package/src/components/AppShell.tsx +0 -286
  223. package/src/components/ConfirmationModal.tsx +0 -81
  224. package/src/components/DeleteEntityModal.tsx +0 -41
  225. package/src/components/ErrorBoundary.tsx +0 -70
  226. package/src/components/FileListWithOptionalToggle.tsx +0 -86
  227. package/src/components/GoalFormFields.tsx +0 -163
  228. package/src/components/ScaffoldOverlay.tsx +0 -78
  229. package/src/components/ThemeToggle.tsx +0 -53
  230. package/src/components/ToastProvider.tsx +0 -163
  231. package/src/components/__tests__/ConfirmationModal.test.tsx +0 -109
  232. package/src/components/__tests__/ErrorBoundary.test.tsx +0 -39
  233. package/src/components/__tests__/FileListWithOptionalToggle.test.tsx +0 -109
  234. package/src/components/__tests__/GoalFormFields.test.tsx +0 -117
  235. package/src/components/delete-modals.tsx +0 -59
  236. package/src/components/icons.tsx +0 -48
  237. package/src/lib/__tests__/agent-workspace.test.ts +0 -44
  238. package/src/lib/__tests__/agents.test.ts +0 -36
  239. package/src/lib/__tests__/api-route-helpers.test.ts +0 -188
  240. package/src/lib/__tests__/cron.test.ts +0 -45
  241. package/src/lib/__tests__/editor-utils.test.ts +0 -38
  242. package/src/lib/__tests__/errors.test.ts +0 -15
  243. package/src/lib/__tests__/exec.test.ts +0 -13
  244. package/src/lib/__tests__/fetch-json.test.ts +0 -118
  245. package/src/lib/__tests__/gateway.test.ts +0 -234
  246. package/src/lib/__tests__/goal-promote.test.ts +0 -39
  247. package/src/lib/__tests__/goals-client.test.ts +0 -26
  248. package/src/lib/__tests__/goals.test.ts +0 -275
  249. package/src/lib/__tests__/json.test.ts +0 -15
  250. package/src/lib/__tests__/kitchen-api.test.ts +0 -32
  251. package/src/lib/__tests__/marketplace.test.ts +0 -116
  252. package/src/lib/__tests__/openclaw.test.ts +0 -129
  253. package/src/lib/__tests__/paths.test.ts +0 -136
  254. package/src/lib/__tests__/poll.test.ts +0 -26
  255. package/src/lib/__tests__/recipe-clone.test.ts +0 -85
  256. package/src/lib/__tests__/recipe-team-agents.test.ts +0 -70
  257. package/src/lib/__tests__/recipes.test.ts +0 -199
  258. package/src/lib/__tests__/scaffold-client.test.ts +0 -106
  259. package/src/lib/__tests__/scaffold.test.ts +0 -64
  260. package/src/lib/__tests__/slugify.test.ts +0 -23
  261. package/src/lib/__tests__/tickets.test.ts +0 -158
  262. package/src/lib/__tests__/type-guards.test.ts +0 -18
  263. package/src/lib/__tests__/use-slugified-id.test.tsx +0 -120
  264. package/src/lib/agent-workspace.ts +0 -14
  265. package/src/lib/agents.ts +0 -17
  266. package/src/lib/api-route-helpers.ts +0 -157
  267. package/src/lib/cron.ts +0 -40
  268. package/src/lib/editor-utils.ts +0 -18
  269. package/src/lib/errors.ts +0 -7
  270. package/src/lib/exec.ts +0 -4
  271. package/src/lib/fetch-json.ts +0 -29
  272. package/src/lib/gateway.ts +0 -100
  273. package/src/lib/goal-promote.ts +0 -27
  274. package/src/lib/goals-client.ts +0 -69
  275. package/src/lib/goals.ts +0 -171
  276. package/src/lib/json.ts +0 -10
  277. package/src/lib/kitchen-api.ts +0 -19
  278. package/src/lib/marketplace.ts +0 -46
  279. package/src/lib/openclaw.ts +0 -59
  280. package/src/lib/paths.ts +0 -69
  281. package/src/lib/poll.ts +0 -18
  282. package/src/lib/recipe-clone.ts +0 -42
  283. package/src/lib/recipe-team-agents.ts +0 -30
  284. package/src/lib/recipes.ts +0 -95
  285. package/src/lib/scaffold-client.ts +0 -31
  286. package/src/lib/scaffold.ts +0 -37
  287. package/src/lib/slugify.ts +0 -25
  288. package/src/lib/swarms.ts +0 -25
  289. package/src/lib/tickets.ts +0 -192
  290. package/src/lib/type-guards.ts +0 -3
  291. package/src/lib/use-slugified-id.ts +0 -35
  292. package/src/lib/workflows/README.md +0 -11
  293. package/src/lib/workflows/__tests__/storage.test.ts +0 -129
  294. package/src/lib/workflows/__tests__/validate.test.ts +0 -92
  295. package/src/lib/workflows/api-handlers.ts +0 -35
  296. package/src/lib/workflows/readdir.ts +0 -23
  297. package/src/lib/workflows/runs-storage.ts +0 -59
  298. package/src/lib/workflows/runs-types.ts +0 -42
  299. package/src/lib/workflows/storage.ts +0 -70
  300. package/src/lib/workflows/templates/index.ts +0 -1
  301. package/src/lib/workflows/templates/marketing-cadence-v1.ts +0 -142
  302. package/src/lib/workflows/types.ts +0 -48
  303. package/src/lib/workflows/validate.ts +0 -92
  304. package/src/proxy.ts +0 -28
  305. /package/.next/static/{z86RoqzzXXrWnpi229zP6 → Jrrrm9HH5bKkSrQhe1j93}/_buildManifest.js +0 -0
  306. /package/.next/static/{z86RoqzzXXrWnpi229zP6 → Jrrrm9HH5bKkSrQhe1j93}/_clientMiddlewareManifest.json +0 -0
  307. /package/.next/static/{z86RoqzzXXrWnpi229zP6 → Jrrrm9HH5bKkSrQhe1j93}/_ssgManifest.js +0 -0
@@ -1,136 +0,0 @@
1
- import { describe, expect, it, vi, beforeEach } from "vitest";
2
- import * as path from "node:path";
3
- import fs from "node:fs/promises";
4
- import {
5
- readOpenClawConfig,
6
- getWorkspaceDir,
7
- getWorkspaceRecipesDir,
8
- getWorkspaceGoalsDir,
9
- getTeamWorkspaceDir,
10
- getBuiltinRecipesDir,
11
- teamDirFromBaseWorkspace,
12
- assertSafeRelativeFileName,
13
- } from "../paths";
14
-
15
- vi.mock("node:fs/promises", () => ({
16
- default: {
17
- readFile: vi.fn(),
18
- },
19
- }));
20
-
21
- describe("paths", () => {
22
- beforeEach(() => {
23
- vi.mocked(fs.readFile).mockReset();
24
- });
25
-
26
- describe("readOpenClawConfig", () => {
27
- it("parses config from ~/.openclaw/openclaw.json", async () => {
28
- const config = {
29
- agents: { defaults: { workspace: "/home/user/workspace" } },
30
- };
31
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(config));
32
-
33
- const result = await readOpenClawConfig();
34
- expect(result).toEqual(config);
35
- expect(fs.readFile).toHaveBeenCalledWith(
36
- path.join(process.env.HOME || "", ".openclaw", "openclaw.json"),
37
- "utf8"
38
- );
39
- });
40
- });
41
-
42
- describe("getWorkspaceDir", () => {
43
- it("returns workspace from config", async () => {
44
- vi.mocked(fs.readFile).mockResolvedValue(
45
- JSON.stringify({ agents: { defaults: { workspace: "/my/ws" } } })
46
- );
47
- expect(await getWorkspaceDir()).toBe("/my/ws");
48
- });
49
-
50
- it("throws when workspace not set", async () => {
51
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({}));
52
- await expect(getWorkspaceDir()).rejects.toThrow(
53
- "agents.defaults.workspace is not set"
54
- );
55
- });
56
- });
57
-
58
- describe("getWorkspaceRecipesDir", () => {
59
- it("joins workspace with recipes", async () => {
60
- vi.mocked(fs.readFile).mockResolvedValue(
61
- JSON.stringify({ agents: { defaults: { workspace: "/ws" } } })
62
- );
63
- expect(await getWorkspaceRecipesDir()).toBe("/ws/recipes");
64
- });
65
- });
66
-
67
- describe("getWorkspaceGoalsDir", () => {
68
- it("joins workspace with notes/goals", async () => {
69
- vi.mocked(fs.readFile).mockResolvedValue(
70
- JSON.stringify({ agents: { defaults: { workspace: "/ws" } } })
71
- );
72
- expect(await getWorkspaceGoalsDir()).toBe("/ws/notes/goals");
73
- });
74
- });
75
-
76
- describe("getTeamWorkspaceDir", () => {
77
- it("returns path for team workspace", async () => {
78
- const home = process.env.HOME || "/home/user";
79
- expect(await getTeamWorkspaceDir("my-team")).toBe(
80
- path.join(home, ".openclaw", "workspace-my-team")
81
- );
82
- });
83
- });
84
-
85
- describe("teamDirFromBaseWorkspace", () => {
86
- it("resolves team dir as sibling of base workspace", () => {
87
- expect(teamDirFromBaseWorkspace("/home/x/.openclaw/agents", "my-team")).toBe(
88
- path.join("/home/x/.openclaw", "workspace-my-team")
89
- );
90
- });
91
- });
92
-
93
- describe("assertSafeRelativeFileName", () => {
94
- it("returns name when safe", () => {
95
- expect(assertSafeRelativeFileName("TEAM.md")).toBe("TEAM.md");
96
- });
97
- it("throws on path traversal", () => {
98
- expect(() => assertSafeRelativeFileName("../etc/passwd")).toThrow("Invalid file name");
99
- });
100
- it("throws on empty or leading slash", () => {
101
- expect(() => assertSafeRelativeFileName("")).toThrow("Invalid file name");
102
- expect(() => assertSafeRelativeFileName("/absolute")).toThrow("Invalid file name");
103
- });
104
- });
105
-
106
- describe("getBuiltinRecipesDir", () => {
107
- it("uses installPath when set", async () => {
108
- vi.mocked(fs.readFile).mockResolvedValue(
109
- JSON.stringify({
110
- plugins: {
111
- installs: { recipes: { installPath: "/plugins/claw" } },
112
- },
113
- })
114
- );
115
- expect(await getBuiltinRecipesDir()).toBe("/plugins/claw/recipes/default");
116
- });
117
-
118
- it("uses sourcePath when installPath not set", async () => {
119
- vi.mocked(fs.readFile).mockResolvedValue(
120
- JSON.stringify({
121
- plugins: {
122
- installs: { recipes: { sourcePath: "/src/claw" } },
123
- },
124
- })
125
- );
126
- expect(await getBuiltinRecipesDir()).toBe("/src/claw/recipes/default");
127
- });
128
-
129
- it("throws when no recipe path configured", async () => {
130
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({}));
131
- await expect(getBuiltinRecipesDir()).rejects.toThrow(
132
- "Could not determine recipes plugin install path"
133
- );
134
- });
135
- });
136
- });
@@ -1,26 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { pollUntil } from "../poll";
3
-
4
- describe("poll", () => {
5
- describe("pollUntil", () => {
6
- it("returns result when check succeeds immediately", async () => {
7
- const result = await pollUntil(async () => "done", { timeoutMs: 1000 });
8
- expect(result).toBe("done");
9
- });
10
-
11
- it("returns result when check succeeds after retries", async () => {
12
- let attempts = 0;
13
- const result = await pollUntil(async () => {
14
- attempts++;
15
- return attempts >= 3 ? "ready" : null;
16
- }, { timeoutMs: 5000, intervalMs: 10 });
17
- expect(result).toBe("ready");
18
- expect(attempts).toBe(3);
19
- });
20
-
21
- it("returns null when timeout", async () => {
22
- const result = await pollUntil(async () => null, { timeoutMs: 50, intervalMs: 20 });
23
- expect(result).toBeNull();
24
- });
25
- });
26
- });
@@ -1,85 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { suggestIds, scaffoldCmdForKind, patchFrontmatter } from "../recipe-clone";
3
-
4
- describe("recipe-clone", () => {
5
- describe("suggestIds", () => {
6
- it("returns suggested ids for base id", () => {
7
- expect(suggestIds("my-agent")).toEqual([
8
- "custom-my-agent",
9
- "my-my-agent",
10
- "my-agent-2",
11
- "my-agent-alt",
12
- ]);
13
- });
14
-
15
- it("uses recipe when base empty", () => {
16
- expect(suggestIds("")).toEqual(["custom-recipe", "my-recipe", "recipe-2", "recipe-alt"]);
17
- });
18
- });
19
-
20
- describe("scaffoldCmdForKind", () => {
21
- it("returns team scaffold args", () => {
22
- expect(scaffoldCmdForKind("team", "my-team")).toEqual([
23
- "recipes",
24
- "scaffold-team",
25
- "my-team",
26
- "--team-id",
27
- "my-team",
28
- "--overwrite",
29
- "--overwrite-recipe",
30
- ]);
31
- });
32
-
33
- it("returns agent scaffold args", () => {
34
- expect(scaffoldCmdForKind("agent", "my-agent")).toEqual([
35
- "recipes",
36
- "scaffold",
37
- "my-agent",
38
- "--agent-id",
39
- "my-agent",
40
- "--overwrite",
41
- "--overwrite-recipe",
42
- ]);
43
- });
44
-
45
- it("returns null for unsupported kind", () => {
46
- expect(scaffoldCmdForKind("other", "x")).toBeNull();
47
- });
48
- });
49
-
50
- describe("patchFrontmatter", () => {
51
- it("patches id and optionally name for agent", () => {
52
- const md = `---
53
- id: source
54
- kind: agent
55
- name: Source Agent
56
- ---
57
- # Body`;
58
- const { next, kind } = patchFrontmatter(md, "my-agent", "My Agent");
59
- expect(kind).toBe("agent");
60
- expect(next).toContain("id: my-agent");
61
- expect(next).toContain("name: My Agent");
62
- expect(next).toContain("# Body");
63
- });
64
-
65
- it("patches teamId for team kind", () => {
66
- const md = `---
67
- id: source
68
- kind: team
69
- ---
70
- # Body`;
71
- const { next, kind } = patchFrontmatter(md, "my-team", undefined);
72
- expect(kind).toBe("team");
73
- expect(next).toContain("id: my-team");
74
- expect(next).toContain("teamId: my-team");
75
- });
76
-
77
- it("throws when frontmatter not terminated", () => {
78
- const md = `---
79
- id: x`;
80
- expect(() => patchFrontmatter(md, "y", undefined)).toThrow(
81
- "Recipe frontmatter not terminated (---)"
82
- );
83
- });
84
- });
85
- });
@@ -1,70 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { splitRecipeFrontmatter, normalizeRole, validateCreateId } from "../recipe-team-agents";
3
-
4
- describe("recipe-team-agents", () => {
5
- describe("splitRecipeFrontmatter", () => {
6
- it("returns yamlText and rest", () => {
7
- const md = `---
8
- kind: team
9
- agents: []
10
- ---
11
- # Body`;
12
- const { yamlText, rest } = splitRecipeFrontmatter(md);
13
- expect(yamlText).toContain("kind: team");
14
- expect(rest).toBe("# Body");
15
- });
16
-
17
- it("throws when not starting with ---", () => {
18
- expect(() => splitRecipeFrontmatter("no frontmatter")).toThrow(
19
- "Recipe markdown must start with YAML frontmatter (---)"
20
- );
21
- });
22
-
23
- it("throws when frontmatter not terminated", () => {
24
- expect(() => splitRecipeFrontmatter("---\nid: x")).toThrow(
25
- "Recipe frontmatter not terminated (---)"
26
- );
27
- });
28
- });
29
-
30
- describe("normalizeRole", () => {
31
- it("returns trimmed role", () => {
32
- expect(normalizeRole(" lead ")).toBe("lead");
33
- });
34
-
35
- it("throws when empty", () => {
36
- expect(() => normalizeRole("")).toThrow("role is required");
37
- });
38
-
39
- it("throws when invalid format", () => {
40
- expect(() => normalizeRole("bad!")).toThrow("role must be alphanumeric/dash");
41
- });
42
-
43
- it("accepts valid role", () => {
44
- expect(normalizeRole("qa-lead")).toBe("qa-lead");
45
- });
46
- });
47
-
48
- describe("validateCreateId", () => {
49
- const recipe = { id: "my-recipe" };
50
-
51
- it("returns null when recipe is null", () => {
52
- expect(validateCreateId(null, "team-1", "team")).toBeNull();
53
- });
54
-
55
- it("returns error when id is empty", () => {
56
- expect(validateCreateId(recipe, "", "team")).toBe("Team id is required.");
57
- expect(validateCreateId(recipe, " ", "agent")).toBe("Agent id is required.");
58
- });
59
-
60
- it("returns error when id matches recipe id", () => {
61
- expect(validateCreateId(recipe, "my-recipe", "team")).toContain("cannot be the same");
62
- expect(validateCreateId(recipe, "my-recipe", "agent")).toContain("cannot be the same");
63
- });
64
-
65
- it("returns null when valid", () => {
66
- expect(validateCreateId(recipe, "team-1", "team")).toBeNull();
67
- expect(validateCreateId(recipe, "agent-1", "agent")).toBeNull();
68
- });
69
- });
70
- });
@@ -1,199 +0,0 @@
1
- import { describe, expect, it, vi, beforeEach } from "vitest";
2
- import {
3
- findRecipeById,
4
- forceFrontmatterId,
5
- listRecipes,
6
- parseFrontmatterId,
7
- resolveRecipePath,
8
- readRecipe,
9
- writeRecipeFile,
10
- type RecipeListItem,
11
- } from "../recipes";
12
-
13
- vi.mock("../openclaw", () => ({ runOpenClaw: vi.fn() }));
14
-
15
- vi.mock("../paths", () => ({
16
- getBuiltinRecipesDir: vi.fn(),
17
- getWorkspaceRecipesDir: vi.fn(),
18
- }));
19
-
20
- vi.mock("node:fs/promises", () => ({
21
- default: {
22
- mkdir: vi.fn(),
23
- writeFile: vi.fn(),
24
- },
25
- }));
26
-
27
- import path from "node:path";
28
- import fs from "node:fs/promises";
29
- import { runOpenClaw } from "../openclaw";
30
- import { getBuiltinRecipesDir, getWorkspaceRecipesDir } from "../paths";
31
-
32
- describe("recipes", () => {
33
- beforeEach(() => {
34
- vi.mocked(runOpenClaw).mockReset();
35
- vi.mocked(getBuiltinRecipesDir).mockReset();
36
- vi.mocked(getWorkspaceRecipesDir).mockReset();
37
- vi.mocked(fs.mkdir).mockReset();
38
- vi.mocked(fs.writeFile).mockReset();
39
- });
40
-
41
- describe("listRecipes", () => {
42
- it("returns parsed list when openclaw succeeds", async () => {
43
- const items: RecipeListItem[] = [
44
- { id: "r1", name: "R1", kind: "agent", source: "workspace" },
45
- ];
46
- vi.mocked(runOpenClaw).mockResolvedValue({
47
- ok: true,
48
- exitCode: 0,
49
- stdout: JSON.stringify(items),
50
- stderr: "",
51
- });
52
- expect(await listRecipes()).toEqual(items);
53
- });
54
-
55
- it("returns empty array when openclaw fails", async () => {
56
- vi.mocked(runOpenClaw).mockResolvedValue({ ok: false, exitCode: 1, stdout: "", stderr: "err" });
57
- expect(await listRecipes()).toEqual([]);
58
- });
59
-
60
- it("returns empty array when stdout is invalid JSON", async () => {
61
- vi.mocked(runOpenClaw).mockResolvedValue({ ok: true, exitCode: 0, stdout: "not json", stderr: "" });
62
- expect(await listRecipes()).toEqual([]);
63
- });
64
- });
65
-
66
- describe("findRecipeById", () => {
67
- it("returns item when found", async () => {
68
- const item: RecipeListItem = { id: "x", name: "X", kind: "agent", source: "workspace" };
69
- vi.mocked(runOpenClaw).mockResolvedValue({
70
- ok: true,
71
- exitCode: 0,
72
- stdout: JSON.stringify([item]),
73
- stderr: "",
74
- });
75
- expect(await findRecipeById("x")).toEqual(item);
76
- });
77
-
78
- it("returns null when not found", async () => {
79
- vi.mocked(runOpenClaw).mockResolvedValue({
80
- ok: true,
81
- exitCode: 0,
82
- stdout: JSON.stringify([]),
83
- stderr: "",
84
- });
85
- expect(await findRecipeById("missing")).toBeNull();
86
- });
87
- });
88
-
89
- describe("forceFrontmatterId", () => {
90
- it("replaces existing id in frontmatter", () => {
91
- const md = "---\nid: old\nname: Foo\n---\nBody";
92
- expect(forceFrontmatterId(md, "new-id")).toContain("id: new-id");
93
- expect(forceFrontmatterId(md, "new-id")).toContain("Body");
94
- });
95
-
96
- it("adds id when missing", () => {
97
- const md = "---\nname: Foo\n---\nBody";
98
- const out = forceFrontmatterId(md, "added");
99
- expect(out).toMatch(/id:\s*added/);
100
- });
101
-
102
- it("returns md unchanged when no frontmatter", () => {
103
- const md = "No frontmatter";
104
- expect(forceFrontmatterId(md, "x")).toBe(md);
105
- });
106
- });
107
-
108
- describe("parseFrontmatterId", () => {
109
- it("returns id from valid frontmatter", () => {
110
- const md = `---
111
- id: my-recipe
112
- name: My Recipe
113
- ---
114
- # Content`;
115
- expect(parseFrontmatterId(md)).toBe("my-recipe");
116
- });
117
-
118
- it("throws when markdown does not start with ---", () => {
119
- expect(() => parseFrontmatterId("no frontmatter")).toThrow(
120
- "Recipe markdown must start with YAML frontmatter (---)"
121
- );
122
- });
123
-
124
- it("throws when frontmatter not terminated", () => {
125
- const md = `---
126
- id: x`;
127
- expect(() => parseFrontmatterId(md)).toThrow("Recipe frontmatter not terminated (---)");
128
- });
129
-
130
- it("throws when id is missing", () => {
131
- const md = `---
132
- name: Foo
133
- ---
134
- # Content`;
135
- expect(() => parseFrontmatterId(md)).toThrow("Recipe frontmatter must include id");
136
- });
137
-
138
- it("handles id with extra fields", () => {
139
- const md = `---
140
- id: agent-recipe
141
- kind: agent
142
- ---
143
- # Body`;
144
- expect(parseFrontmatterId(md)).toBe("agent-recipe");
145
- });
146
- });
147
-
148
- describe("resolveRecipePath", () => {
149
- it("returns builtin path for builtin source", async () => {
150
- vi.mocked(getBuiltinRecipesDir).mockResolvedValue("/builtin/recipes");
151
- const item: RecipeListItem = { id: "foo", name: "Foo", kind: "agent", source: "builtin" };
152
- const p = await resolveRecipePath(item);
153
- expect(p).toBe(path.join("/builtin/recipes", "foo.md"));
154
- expect(getBuiltinRecipesDir).toHaveBeenCalledOnce();
155
- });
156
-
157
- it("returns workspace path for workspace source", async () => {
158
- vi.mocked(getWorkspaceRecipesDir).mockResolvedValue("/ws/recipes");
159
- const item: RecipeListItem = { id: "bar", name: "Bar", kind: "team", source: "workspace" };
160
- const p = await resolveRecipePath(item);
161
- expect(p).toBe(path.join("/ws/recipes", "bar.md"));
162
- expect(getWorkspaceRecipesDir).toHaveBeenCalledOnce();
163
- });
164
- });
165
-
166
- describe("readRecipe", () => {
167
- it("returns detail with filePath when resolve succeeds", async () => {
168
- vi.mocked(getWorkspaceRecipesDir).mockResolvedValue("/ws/recipes");
169
- const item: RecipeListItem = { id: "r1", name: "R1", kind: "agent", source: "workspace" };
170
- const content = "# Recipe content";
171
- const result = await readRecipe(item, content);
172
- expect(result).toEqual({
173
- ...item,
174
- content,
175
- filePath: path.join("/ws/recipes", "r1.md"),
176
- });
177
- });
178
-
179
- it("returns filePath null when resolve throws", async () => {
180
- vi.mocked(getWorkspaceRecipesDir).mockRejectedValue(new Error("no config"));
181
- const item: RecipeListItem = { id: "r2", name: "R2", kind: "team", source: "workspace" };
182
- const result = await readRecipe(item, "body");
183
- expect(result.content).toBe("body");
184
- expect(result.filePath).toBeNull();
185
- });
186
- });
187
-
188
- describe("writeRecipeFile", () => {
189
- it("creates dir and writes file", async () => {
190
- vi.mocked(fs.mkdir).mockResolvedValue(undefined);
191
- vi.mocked(fs.writeFile).mockResolvedValue(undefined);
192
-
193
- await writeRecipeFile("/some/dir/recipe.md", "# Markdown");
194
-
195
- expect(fs.mkdir).toHaveBeenCalledWith("/some/dir", { recursive: true });
196
- expect(fs.writeFile).toHaveBeenCalledWith("/some/dir/recipe.md", "# Markdown", "utf8");
197
- });
198
- });
199
- });
@@ -1,106 +0,0 @@
1
- import { describe, expect, it, vi, beforeEach } from "vitest";
2
- import { fetchScaffold } from "../scaffold-client";
3
-
4
- const mockFetch = vi.hoisted(() => vi.fn());
5
-
6
- describe("scaffold-client", () => {
7
- beforeEach(() => {
8
- vi.stubGlobal("fetch", mockFetch);
9
- mockFetch.mockReset();
10
- });
11
-
12
- describe("fetchScaffold", () => {
13
- it("sends team scaffold request with correct body", async () => {
14
- mockFetch.mockResolvedValue({
15
- ok: true,
16
- json: async () => ({ ok: true }),
17
- });
18
-
19
- const { res, json } = await fetchScaffold({
20
- kind: "team",
21
- recipeId: "my-recipe",
22
- teamId: "my-team",
23
- cronInstallChoice: "yes",
24
- });
25
-
26
- expect(res.ok).toBe(true);
27
- expect(json).toEqual({ ok: true });
28
- expect(mockFetch).toHaveBeenCalledWith("/api/scaffold", {
29
- method: "POST",
30
- headers: { "content-type": "application/json" },
31
- body: JSON.stringify({
32
- kind: "team",
33
- recipeId: "my-recipe",
34
- teamId: "my-team",
35
- cronInstallChoice: "yes",
36
- applyConfig: true,
37
- overwrite: false,
38
- }),
39
- });
40
- });
41
-
42
- it("sends agent scaffold request with correct body", async () => {
43
- mockFetch.mockResolvedValue({
44
- ok: true,
45
- json: async () => ({ ok: true, stderr: "" }),
46
- });
47
-
48
- const { res, json } = await fetchScaffold({
49
- kind: "agent",
50
- recipeId: "template",
51
- agentId: "my-agent",
52
- name: "My Agent",
53
- });
54
-
55
- expect(res.ok).toBe(true);
56
- expect(json).toEqual({ ok: true, stderr: "" });
57
- expect(mockFetch).toHaveBeenCalledWith("/api/scaffold", {
58
- method: "POST",
59
- headers: { "content-type": "application/json" },
60
- body: JSON.stringify({
61
- kind: "agent",
62
- recipeId: "template",
63
- agentId: "my-agent",
64
- name: "My Agent",
65
- applyConfig: true,
66
- overwrite: false,
67
- }),
68
- });
69
- });
70
-
71
- it("always adds applyConfig and overwrite to body", async () => {
72
- mockFetch.mockResolvedValue({
73
- ok: true,
74
- json: async () => ({}),
75
- });
76
-
77
- await fetchScaffold({
78
- kind: "agent",
79
- recipeId: "r",
80
- agentId: "a",
81
- });
82
-
83
- const body = JSON.parse(mockFetch.mock.calls[0][1].body);
84
- expect(body.applyConfig).toBe(true);
85
- expect(body.overwrite).toBe(false);
86
- });
87
-
88
- it("returns res and parsed json on non-ok response", async () => {
89
- mockFetch.mockResolvedValue({
90
- ok: false,
91
- status: 500,
92
- json: async () => ({ ok: false, error: "Scaffold failed" }),
93
- });
94
-
95
- const { res, json } = await fetchScaffold({
96
- kind: "team",
97
- recipeId: "r",
98
- teamId: "t",
99
- });
100
-
101
- expect(res.ok).toBe(false);
102
- expect(res.status).toBe(500);
103
- expect(json).toEqual({ ok: false, error: "Scaffold failed" });
104
- });
105
- });
106
- });
@@ -1,64 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { buildScaffoldArgs } from "../scaffold";
3
-
4
- describe("scaffold", () => {
5
- describe("buildScaffoldArgs", () => {
6
- it("builds minimal agent args", () => {
7
- expect(
8
- buildScaffoldArgs({ kind: "agent", recipeId: "my-agent" })
9
- ).toEqual(["recipes", "scaffold", "my-agent"]);
10
- });
11
-
12
- it("builds agent args with agentId and name", () => {
13
- expect(
14
- buildScaffoldArgs({
15
- kind: "agent",
16
- recipeId: "template",
17
- agentId: "my-agent",
18
- name: "My Agent",
19
- })
20
- ).toEqual([
21
- "recipes",
22
- "scaffold",
23
- "template",
24
- "--agent-id",
25
- "my-agent",
26
- "--name",
27
- "My Agent",
28
- ]);
29
- });
30
-
31
- it("adds overwrite and applyConfig for agent", () => {
32
- expect(
33
- buildScaffoldArgs({
34
- kind: "agent",
35
- recipeId: "r",
36
- overwrite: true,
37
- applyConfig: true,
38
- })
39
- ).toEqual(["recipes", "scaffold", "r", "--overwrite", "--apply-config", "--overwrite-recipe"]);
40
- });
41
-
42
- it("builds minimal team args", () => {
43
- expect(
44
- buildScaffoldArgs({ kind: "team", recipeId: "my-team" })
45
- ).toEqual(["recipes", "scaffold-team", "my-team"]);
46
- });
47
-
48
- it("adds teamId for team", () => {
49
- expect(
50
- buildScaffoldArgs({
51
- kind: "team",
52
- recipeId: "template",
53
- teamId: "my-team",
54
- })
55
- ).toEqual([
56
- "recipes",
57
- "scaffold-team",
58
- "template",
59
- "--team-id",
60
- "my-team",
61
- ]);
62
- });
63
- });
64
- });