@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,275 +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
- assertSafeGoalId,
6
- splitFrontmatter,
7
- normalizeFrontmatter,
8
- listGoals,
9
- readGoal,
10
- writeGoal,
11
- deleteGoal,
12
- goalErrorStatus,
13
- parseCommaList,
14
- } from "../goals";
15
- import { getWorkspaceGoalsDir } from "@/lib/paths";
16
-
17
- vi.mock("node:fs/promises", () => ({
18
- default: {
19
- mkdir: vi.fn(),
20
- readdir: vi.fn(),
21
- readFile: vi.fn(),
22
- writeFile: vi.fn(),
23
- unlink: vi.fn(),
24
- },
25
- }));
26
-
27
- vi.mock("@/lib/paths", () => ({
28
- getWorkspaceGoalsDir: vi.fn(),
29
- }));
30
-
31
- describe("goals", () => {
32
- describe("assertSafeGoalId", () => {
33
- it("accepts valid ids", () => {
34
- expect(() => assertSafeGoalId("ab")).not.toThrow();
35
- expect(() => assertSafeGoalId("my-goal-123")).not.toThrow();
36
- expect(() => assertSafeGoalId("increase-trial-activation")).not.toThrow();
37
- });
38
-
39
- it("rejects invalid ids", () => {
40
- expect(() => assertSafeGoalId("")).toThrow("Invalid goal id");
41
- expect(() => assertSafeGoalId("A")).toThrow("Invalid goal id");
42
- expect(() => assertSafeGoalId("invalid_id")).toThrow("Invalid goal id");
43
- expect(() => assertSafeGoalId("no spaces")).toThrow("Invalid goal id");
44
- expect(() => assertSafeGoalId("-leading")).toThrow("Invalid goal id");
45
- expect(() => assertSafeGoalId("a".repeat(65))).toThrow("Invalid goal id");
46
- });
47
- });
48
-
49
- describe("parseCommaList", () => {
50
- it("parses comma-separated values", () => {
51
- expect(parseCommaList("a, b, c")).toEqual(["a", "b", "c"]);
52
- expect(parseCommaList("development-team, marketing-team")).toEqual(["development-team", "marketing-team"]);
53
- });
54
- it("trims and filters empty", () => {
55
- expect(parseCommaList(" a , , b ")).toEqual(["a", "b"]);
56
- expect(parseCommaList("")).toEqual([]);
57
- });
58
- });
59
-
60
- describe("goalErrorStatus", () => {
61
- it("returns 400 for validation errors", () => {
62
- expect(goalErrorStatus("Invalid goal id")).toBe(400);
63
- expect(goalErrorStatus("Path traversal rejected")).toBe(400);
64
- });
65
- it("returns 500 for other errors", () => {
66
- expect(goalErrorStatus("fs error")).toBe(500);
67
- });
68
- });
69
-
70
- describe("splitFrontmatter", () => {
71
- it("parses valid frontmatter", () => {
72
- const md = `---
73
- id: foo
74
- title: My Goal
75
- status: active
76
- ---
77
- Body here`;
78
- const { fm, body } = splitFrontmatter(md);
79
- expect(fm).toEqual({ id: "foo", title: "My Goal", status: "active" });
80
- expect(body.trim()).toBe("Body here");
81
- });
82
-
83
- it("returns empty fm and full body when no frontmatter", () => {
84
- const md = "# Just markdown\n\nNo frontmatter";
85
- const { fm, body } = splitFrontmatter(md);
86
- expect(fm).toEqual({});
87
- expect(body).toBe("# Just markdown\n\nNo frontmatter");
88
- });
89
-
90
- it("handles empty frontmatter", () => {
91
- const md = `---
92
- ---
93
- Body`;
94
- const { fm, body } = splitFrontmatter(md);
95
- expect(fm).toEqual({});
96
- // Implementation returns full md when closing --- not found from position 4
97
- expect(body).toContain("Body");
98
- });
99
- });
100
-
101
- describe("normalizeFrontmatter", () => {
102
- it("normalizes full input", () => {
103
- const input = {
104
- id: "my-goal",
105
- title: "My Goal",
106
- status: "active",
107
- tags: ["a", "b"],
108
- teams: ["team1"],
109
- updatedAt: "2026-01-01T00:00:00Z",
110
- };
111
- const result = normalizeFrontmatter(input, "fallback-id", "Fallback Title");
112
- expect(result).toEqual({
113
- id: "my-goal",
114
- title: "My Goal",
115
- status: "active",
116
- tags: ["a", "b"],
117
- teams: ["team1"],
118
- updatedAt: "2026-01-01T00:00:00Z",
119
- });
120
- });
121
-
122
- it("uses fallbacks for missing fields", () => {
123
- const result = normalizeFrontmatter({}, "fb-id", "Fallback");
124
- expect(result.id).toBe("fb-id");
125
- expect(result.title).toBe("Fallback");
126
- expect(result.status).toBe("planned");
127
- expect(result.tags).toEqual([]);
128
- expect(result.teams).toEqual([]);
129
- expect(result.updatedAt).toBeDefined();
130
- });
131
-
132
- it("normalizes status to planned when invalid", () => {
133
- const result = normalizeFrontmatter({ status: "invalid" }, "id", "Title");
134
- expect(result.status).toBe("planned");
135
- });
136
-
137
- it("accepts active and done status", () => {
138
- expect(normalizeFrontmatter({ status: "active" }, "id", "").status).toBe("active");
139
- expect(normalizeFrontmatter({ status: "done" }, "id", "").status).toBe("done");
140
- });
141
-
142
- it("handles non-object input", () => {
143
- const result = normalizeFrontmatter(null, "id", "t");
144
- expect(result.id).toBe("id");
145
- expect(result.title).toBe("t");
146
- });
147
- });
148
-
149
- describe("listGoals", () => {
150
- beforeEach(() => {
151
- vi.mocked(getWorkspaceGoalsDir).mockResolvedValue("/mock-workspace/goals");
152
- vi.mocked(fs.mkdir).mockResolvedValue(undefined);
153
- });
154
-
155
- it("returns sorted goals", async () => {
156
- vi.mocked(fs.readdir).mockResolvedValue(["goal-b.md", "goal-a.md"]);
157
- vi.mocked(fs.readFile)
158
- .mockResolvedValueOnce(`---
159
- id: goal-b
160
- title: B
161
- status: done
162
- tags: []
163
- teams: []
164
- updatedAt: 2026-01-02T00:00:00Z
165
- ---
166
- Body B`)
167
- .mockResolvedValueOnce(`---
168
- id: goal-a
169
- title: A
170
- status: active
171
- tags: []
172
- teams: []
173
- updatedAt: 2026-01-01T00:00:00Z
174
- ---
175
- Body A`);
176
-
177
- const result = await listGoals();
178
- expect(result).toHaveLength(2);
179
- expect(result[0].id).toBe("goal-a");
180
- expect(result[0].status).toBe("active");
181
- expect(result[1].id).toBe("goal-b");
182
- expect(result[1].status).toBe("done");
183
- });
184
-
185
- it("returns empty array when no files", async () => {
186
- vi.mocked(fs.readdir).mockResolvedValue([]);
187
- const result = await listGoals();
188
- expect(result).toEqual([]);
189
- });
190
- });
191
-
192
- describe("readGoal", () => {
193
- beforeEach(() => {
194
- vi.mocked(getWorkspaceGoalsDir).mockResolvedValue("/mock-workspace/goals");
195
- vi.mocked(fs.mkdir).mockResolvedValue(undefined);
196
- });
197
-
198
- it("returns goal when exists", async () => {
199
- vi.mocked(fs.readFile).mockResolvedValue(`---
200
- id: my-goal
201
- title: My Goal
202
- status: active
203
- ---
204
- Body text`);
205
-
206
- const result = await readGoal("my-goal");
207
- expect(result).not.toBeNull();
208
- expect(result!.frontmatter.id).toBe("my-goal");
209
- expect(result!.frontmatter.title).toBe("My Goal");
210
- expect(result!.body.trim()).toBe("Body text");
211
- });
212
-
213
- it("returns null when file not found", async () => {
214
- vi.mocked(fs.readFile).mockRejectedValue({ code: "ENOENT" });
215
- const result = await readGoal("missing-goal");
216
- expect(result).toBeNull();
217
- });
218
-
219
- it("throws on invalid id", async () => {
220
- await expect(readGoal("")).rejects.toThrow("Invalid goal id");
221
- });
222
- });
223
-
224
- describe("writeGoal", () => {
225
- beforeEach(() => {
226
- vi.mocked(getWorkspaceGoalsDir).mockResolvedValue("/mock-workspace/goals");
227
- vi.mocked(fs.mkdir).mockResolvedValue(undefined);
228
- vi.mocked(fs.writeFile).mockResolvedValue(undefined);
229
- });
230
-
231
- it("writes goal and returns frontmatter", async () => {
232
- const result = await writeGoal({
233
- id: "new-goal",
234
- title: "New Goal",
235
- body: "Content",
236
- });
237
- expect(result.frontmatter.id).toBe("new-goal");
238
- expect(result.frontmatter.title).toBe("New Goal");
239
- expect(fs.writeFile).toHaveBeenCalledWith(
240
- path.join("/mock-workspace/goals", "new-goal.md"),
241
- expect.stringContaining("New Goal"),
242
- "utf8"
243
- );
244
- });
245
-
246
- it("throws on invalid id", async () => {
247
- await expect(writeGoal({ id: "bad id", title: "X", body: "" })).rejects.toThrow("Invalid goal id");
248
- });
249
- });
250
-
251
- describe("deleteGoal", () => {
252
- beforeEach(() => {
253
- vi.mocked(getWorkspaceGoalsDir).mockResolvedValue("/mock-workspace/goals");
254
- vi.mocked(fs.mkdir).mockResolvedValue(undefined);
255
- vi.mocked(fs.unlink).mockResolvedValue(undefined);
256
- });
257
-
258
- it("returns ok when deleted", async () => {
259
- const result = await deleteGoal("my-goal");
260
- expect(result).toEqual({ ok: true });
261
- expect(fs.unlink).toHaveBeenCalledWith(path.join("/mock-workspace/goals", "my-goal.md"));
262
- });
263
-
264
- it("returns not_found when file missing", async () => {
265
- vi.mocked(fs.unlink).mockRejectedValue({ code: "ENOENT" });
266
- const result = await deleteGoal("missing");
267
- expect(result).toEqual({ ok: false, reason: "not_found" });
268
- });
269
-
270
- it("throws on other errors", async () => {
271
- vi.mocked(fs.unlink).mockRejectedValue(new Error("Permission denied"));
272
- await expect(deleteGoal("my-goal")).rejects.toThrow("Permission denied");
273
- });
274
- });
275
- });
@@ -1,15 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { safeJsonParse } from "../json";
3
-
4
- describe("safeJsonParse", () => {
5
- it("parses valid JSON", () => {
6
- expect(safeJsonParse('{"a":1}')).toEqual({ a: 1 });
7
- expect(safeJsonParse("[1,2]")).toEqual([1, 2]);
8
- expect(safeJsonParse('"hi"')).toBe("hi");
9
- });
10
-
11
- it("returns null for invalid JSON", () => {
12
- expect(safeJsonParse("not json")).toBeNull();
13
- expect(safeJsonParse("{")).toBeNull();
14
- });
15
- });
@@ -1,32 +0,0 @@
1
- import { describe, expect, it, beforeEach, afterEach } from "vitest";
2
- import { getKitchenApi } from "../kitchen-api";
3
-
4
- describe("kitchen-api", () => {
5
- beforeEach(() => {
6
- delete (globalThis as unknown as { __clawkitchen_api?: unknown }).__clawkitchen_api;
7
- });
8
-
9
- afterEach(() => {
10
- delete (globalThis as unknown as { __clawkitchen_api?: unknown }).__clawkitchen_api;
11
- });
12
-
13
- it("throws when __clawkitchen_api is missing", () => {
14
- expect(() => getKitchenApi()).toThrow(
15
- "ClawKitchen: OpenClaw plugin API not available"
16
- );
17
- });
18
-
19
- it("returns api when __clawkitchen_api is set", () => {
20
- const mockApi = {
21
- config: {},
22
- runtime: {
23
- system: {
24
- runCommandWithTimeout: async () => ({ stdout: "", stderr: "" }),
25
- },
26
- },
27
- };
28
- (globalThis as unknown as { __clawkitchen_api?: unknown }).__clawkitchen_api = mockApi;
29
-
30
- expect(getKitchenApi()).toBe(mockApi);
31
- });
32
- });
@@ -1,116 +0,0 @@
1
- import { describe, expect, it, vi, beforeEach } from "vitest";
2
- import { loadRegistry, search, getBySlug, type MarketplaceRecipe } from "../marketplace";
3
-
4
- vi.mock("node:fs/promises", () => ({
5
- default: { readFile: vi.fn() },
6
- }));
7
-
8
- import fs from "node:fs/promises";
9
-
10
- describe("marketplace", () => {
11
- const sampleRecipes: MarketplaceRecipe[] = [
12
- {
13
- slug: "my-agent",
14
- kind: "agent",
15
- name: "My Agent",
16
- description: "Does stuff with AI",
17
- version: "1.0.0",
18
- tags: ["agent", "ai"],
19
- sourceUrl: "https://example.com/repo",
20
- },
21
- {
22
- slug: "team-template",
23
- kind: "team",
24
- name: "Team Template",
25
- description: "Multi-agent collaboration",
26
- version: "0.1.0",
27
- tags: ["team", "collab"],
28
- sourceUrl: "https://example.com/team",
29
- },
30
- ];
31
-
32
- beforeEach(() => {
33
- vi.mocked(fs.readFile).mockReset();
34
- });
35
-
36
- describe("loadRegistry", () => {
37
- it("returns parsed registry when valid", async () => {
38
- const reg = {
39
- version: 1,
40
- generatedAt: "2025-01-01T00:00:00Z",
41
- recipes: sampleRecipes,
42
- };
43
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(reg));
44
-
45
- const result = await loadRegistry();
46
- expect(result.version).toBe(1);
47
- expect(result.recipes).toHaveLength(2);
48
- expect(result.recipes[0].slug).toBe("my-agent");
49
- });
50
-
51
- it("throws when registry is invalid (no recipes array)", async () => {
52
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({ version: 1 }));
53
-
54
- await expect(loadRegistry()).rejects.toThrow("Invalid marketplace registry.json");
55
- });
56
-
57
- it("throws when recipes is not array", async () => {
58
- vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({ version: 1, recipes: "bad" }));
59
-
60
- await expect(loadRegistry()).rejects.toThrow("Invalid marketplace registry.json");
61
- });
62
- });
63
-
64
- describe("search", () => {
65
- it("returns all when query is null or empty", () => {
66
- expect(search(sampleRecipes, null)).toEqual(sampleRecipes);
67
- expect(search(sampleRecipes, "")).toEqual(sampleRecipes);
68
- expect(search(sampleRecipes, " ")).toEqual(sampleRecipes);
69
- });
70
-
71
- it("filters by name match", () => {
72
- const r = search(sampleRecipes, "template");
73
- expect(r).toHaveLength(1);
74
- expect(r[0].name).toBe("Team Template");
75
- });
76
-
77
- it("filters by slug match", () => {
78
- const r = search(sampleRecipes, "team-template");
79
- expect(r).toHaveLength(1);
80
- expect(r[0].slug).toBe("team-template");
81
- });
82
-
83
- it("filters by description", () => {
84
- const r = search(sampleRecipes, "collaboration");
85
- expect(r).toHaveLength(1);
86
- expect(r[0].name).toBe("Team Template");
87
- });
88
-
89
- it("is case insensitive", () => {
90
- const r = search(sampleRecipes, "COLLAB");
91
- expect(r).toHaveLength(1);
92
- });
93
- });
94
-
95
- describe("getBySlug", () => {
96
- it("returns recipe when slug matches", () => {
97
- const r = getBySlug(sampleRecipes, "my-agent");
98
- expect(r).not.toBeNull();
99
- expect(r!.slug).toBe("my-agent");
100
- });
101
-
102
- it("returns null when slug not found", () => {
103
- expect(getBySlug(sampleRecipes, "nonexistent")).toBeNull();
104
- });
105
-
106
- it("is case insensitive", () => {
107
- const r = getBySlug(sampleRecipes, "MY-AGENT");
108
- expect(r?.slug).toBe("my-agent");
109
- });
110
-
111
- it("trims query", () => {
112
- const r = getBySlug(sampleRecipes, " my-agent ");
113
- expect(r?.slug).toBe("my-agent");
114
- });
115
- });
116
- });
@@ -1,129 +0,0 @@
1
- import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
2
- import { runOpenClaw } from "../openclaw";
3
-
4
- const mockRunCommand = vi.hoisted(() => vi.fn());
5
-
6
- describe("openclaw", () => {
7
- beforeEach(() => {
8
- mockRunCommand.mockReset();
9
- (globalThis as unknown as { __clawkitchen_api?: unknown }).__clawkitchen_api = {
10
- runtime: {
11
- system: {
12
- runCommandWithTimeout: mockRunCommand,
13
- },
14
- },
15
- };
16
- });
17
-
18
- afterEach(() => {
19
- delete (globalThis as unknown as { __clawkitchen_api?: unknown }).__clawkitchen_api;
20
- });
21
-
22
- describe("runOpenClaw", () => {
23
- it("returns ok true when exit is 0", async () => {
24
- mockRunCommand.mockResolvedValue({
25
- stdout: "stdout\n",
26
- stderr: "stderr",
27
- exitCode: 0,
28
- });
29
-
30
- const result = await runOpenClaw(["recipes", "list"]);
31
- expect(result.ok).toBe(true);
32
- expect(result.exitCode).toBe(0);
33
- expect(result.stdout).toBe("stdout\n");
34
- expect(result.stderr).toBe("stderr");
35
- });
36
-
37
- it("returns ok false with stdout/stderr on non-zero exit", async () => {
38
- const err = new Error("Command failed") as Error & { code?: number; stdout?: string; stderr?: string };
39
- err.code = 1;
40
- err.stdout = "out";
41
- err.stderr = "err";
42
-
43
- mockRunCommand.mockRejectedValue(err);
44
-
45
- const result = await runOpenClaw(["bad", "cmd"]);
46
- expect(result.ok).toBe(false);
47
- expect(result.exitCode).toBe(1);
48
- expect(result.stdout).toBe("out");
49
- expect(result.stderr).toBe("err");
50
- });
51
-
52
- it("uses err.message as stderr fallback when stderr missing", async () => {
53
- const err = new Error("Something went wrong") as Error & { code?: number };
54
- err.code = 2;
55
-
56
- mockRunCommand.mockRejectedValue(err);
57
-
58
- const result = await runOpenClaw(["fail"]);
59
- expect(result.ok).toBe(false);
60
- expect(result.exitCode).toBe(2);
61
- expect(result.stderr).toBe("Something went wrong");
62
- });
63
-
64
- it("uses numeric code from error", async () => {
65
- const err = new Error("fail") as Error & { code?: number };
66
- err.code = 42;
67
-
68
- mockRunCommand.mockRejectedValue(err);
69
-
70
- const result = await runOpenClaw(["x"]);
71
- expect(result.exitCode).toBe(42);
72
- });
73
-
74
- it("defaults exitCode to 1 when code not numeric", async () => {
75
- const err = new Error("fail");
76
-
77
- mockRunCommand.mockRejectedValue(err);
78
-
79
- const result = await runOpenClaw(["x"]);
80
- expect(result.exitCode).toBe(1);
81
- });
82
-
83
- it("extracts stdout from object with toString when rejected", async () => {
84
- const err = new Error("fail") as Error & { code?: number; stdout?: unknown };
85
- err.code = 1;
86
- err.stdout = { toString: () => "custom-out" };
87
-
88
- mockRunCommand.mockRejectedValue(err);
89
-
90
- const result = await runOpenClaw(["x"]);
91
- expect(result.stdout).toBe("custom-out");
92
- });
93
-
94
- it("extracts stderr from object with toString when rejected", async () => {
95
- const err = new Error("fail") as Error & { code?: number; stderr?: unknown };
96
- err.code = 1;
97
- err.stderr = { toString: () => "custom-err" };
98
-
99
- mockRunCommand.mockRejectedValue(err);
100
-
101
- const result = await runOpenClaw(["x"]);
102
- expect(result.stderr).toBe("custom-err");
103
- });
104
-
105
- it("uses code from result when exitCode missing", async () => {
106
- mockRunCommand.mockResolvedValue({
107
- stdout: "",
108
- stderr: "",
109
- code: 2,
110
- });
111
-
112
- const result = await runOpenClaw(["x"]);
113
- expect(result.ok).toBe(false);
114
- expect(result.exitCode).toBe(2);
115
- });
116
-
117
- it("uses status from result when exitCode and code missing", async () => {
118
- mockRunCommand.mockResolvedValue({
119
- stdout: "",
120
- stderr: "",
121
- status: 3,
122
- });
123
-
124
- const result = await runOpenClaw(["x"]);
125
- expect(result.ok).toBe(false);
126
- expect(result.exitCode).toBe(3);
127
- });
128
- });
129
- });