@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,40 +0,0 @@
1
- import Link from "next/link";
2
- import { unstable_noStore as noStore } from "next/cache";
3
-
4
- import { getTeamDisplayName } from "@/lib/recipes";
5
- import WorkflowsClient from "./workflows-client";
6
-
7
- export const dynamic = "force-dynamic";
8
- export const revalidate = 0;
9
-
10
- export default async function WorkflowsPage({
11
- params,
12
- }: {
13
- params: Promise<{ teamId: string }>;
14
- }) {
15
- noStore();
16
-
17
- const { teamId } = await params;
18
- const name = await getTeamDisplayName(teamId);
19
-
20
- return (
21
- <div className="space-y-4 p-6">
22
- <div className="flex flex-wrap items-start justify-between gap-4">
23
- <div>
24
- <Link
25
- href={`/teams/${encodeURIComponent(teamId)}`}
26
- className="text-sm font-medium text-[color:var(--ck-text-secondary)] hover:underline"
27
- >
28
- ← {name || teamId}
29
- </Link>
30
- <h1 className="mt-2 text-2xl font-semibold tracking-tight">Workflows</h1>
31
- <p className="mt-1 text-sm text-[color:var(--ck-text-secondary)]">
32
- Create and edit workflow definitions for this team.
33
- </p>
34
- </div>
35
- </div>
36
-
37
- <WorkflowsClient teamId={teamId} />
38
- </div>
39
- );
40
- }
@@ -1,494 +0,0 @@
1
- "use client";
2
-
3
- import { useCallback, useEffect, useMemo, useState } from "react";
4
- import Link from "next/link";
5
- import { useRouter } from "next/navigation";
6
- import { fetchJson } from "@/lib/fetch-json";
7
- import { errorMessage } from "@/lib/errors";
8
-
9
- type RunDetail = {
10
- id: string;
11
- status?: string;
12
- startedAt?: string;
13
- finishedAt?: string;
14
- meta?: unknown;
15
- memoryUsed?: unknown;
16
- approval?: unknown;
17
- raw?: Record<string, unknown>;
18
- };
19
-
20
- function isRecord(v: unknown): v is Record<string, unknown> {
21
- return Boolean(v) && typeof v === "object" && !Array.isArray(v);
22
- }
23
-
24
- export default function WorkflowsClient({ teamId }: { teamId: string }) {
25
- const router = useRouter();
26
- const [workflows, setWorkflows] = useState<Array<{ id: string; name?: string }>>([]);
27
- const [loading, setLoading] = useState(true);
28
- const [refreshing, setRefreshing] = useState(false);
29
- const [error, setError] = useState<string>("");
30
-
31
- const [expandedWorkflowId, setExpandedWorkflowId] = useState<string>("");
32
- const [runsByWorkflow, setRunsByWorkflow] = useState<Record<string, string[]>>({});
33
- const [runsLoading, setRunsLoading] = useState<Record<string, boolean>>({});
34
- const [selectedRunId, setSelectedRunId] = useState<string>("");
35
- const [selectedWorkflowId, setSelectedWorkflowId] = useState<string>("");
36
- const [selectedRun, setSelectedRun] = useState<RunDetail | null>(null);
37
- const [runError, setRunError] = useState<string>("");
38
- const [approvalNote, setApprovalNote] = useState<string>("");
39
- const [approvalBusy, setApprovalBusy] = useState<boolean>(false);
40
-
41
- const load = useCallback(
42
- async (opts?: { quiet?: boolean }) => {
43
- const quiet = Boolean(opts?.quiet);
44
- setError("");
45
- if (!quiet) setLoading(true);
46
- try {
47
- const json = await fetchJson<{ ok?: boolean; files?: string[] }>(
48
- `/api/teams/workflows?teamId=${encodeURIComponent(teamId)}`,
49
- { cache: "no-store" }
50
- );
51
- if (!json.ok) throw new Error("Failed to load workflows");
52
- const files = Array.isArray(json.files) ? json.files : [];
53
- const ids = files
54
- .map((f) => (f.endsWith(".workflow.json") ? f.slice(0, -".workflow.json".length) : null))
55
- .filter((id): id is string => Boolean(id));
56
- setWorkflows(ids.map((id) => ({ id, name: id })));
57
- } catch (e: unknown) {
58
- setError(errorMessage(e));
59
- } finally {
60
- if (!quiet) setLoading(false);
61
- }
62
- },
63
- [teamId]
64
- );
65
-
66
- useEffect(() => {
67
- void load();
68
- }, [load]);
69
-
70
- async function onRefresh() {
71
- setRefreshing(true);
72
- try {
73
- await load({ quiet: true });
74
- } finally {
75
- setRefreshing(false);
76
- }
77
- }
78
-
79
- async function onDelete(id: string) {
80
- if (!confirm(`Delete workflow “${id}”? This removes the .workflow.json file from the team workspace.`)) return;
81
- setError("");
82
- try {
83
- const json = await fetchJson<{ ok?: boolean; error?: string }>(
84
- `/api/teams/workflows?teamId=${encodeURIComponent(teamId)}&id=${encodeURIComponent(id)}`,
85
- { method: "DELETE" }
86
- );
87
- if (!json.ok) throw new Error(json.error || "Failed to delete workflow");
88
- await load({ quiet: true });
89
- if (expandedWorkflowId === id) {
90
- setExpandedWorkflowId("");
91
- setSelectedRunId("");
92
- setSelectedRun(null);
93
- }
94
- } catch (e: unknown) {
95
- setError(errorMessage(e));
96
- }
97
- }
98
-
99
- async function loadRunsForWorkflow(workflowId: string) {
100
- setRunsLoading((s) => ({ ...s, [workflowId]: true }));
101
- setRunError("");
102
- try {
103
- const json = await fetchJson<{ ok?: boolean; files?: string[]; error?: string }>(
104
- `/api/teams/workflow-runs?teamId=${encodeURIComponent(teamId)}&workflowId=${encodeURIComponent(workflowId)}`,
105
- { cache: "no-store" }
106
- );
107
- if (!json.ok) throw new Error(json.error || "Failed to load runs");
108
- const files = Array.isArray(json.files) ? json.files : [];
109
- const runIds = files
110
- .map((f) => (typeof f === "string" && f.endsWith(".run.json") ? f.slice(0, -".run.json".length) : null))
111
- .filter((x): x is string => Boolean(x));
112
- setRunsByWorkflow((s) => ({ ...s, [workflowId]: runIds }));
113
- } catch (e: unknown) {
114
- setRunError(errorMessage(e));
115
- setRunsByWorkflow((s) => ({ ...s, [workflowId]: [] }));
116
- } finally {
117
- setRunsLoading((s) => ({ ...s, [workflowId]: false }));
118
- }
119
- }
120
-
121
- async function loadRunDetail(workflowId: string, runId: string) {
122
- setSelectedWorkflowId(workflowId);
123
- setSelectedRunId(runId);
124
- setSelectedRun(null);
125
- setRunError("");
126
- setApprovalNote("");
127
- try {
128
- const json = await fetchJson<{ ok?: boolean; run?: unknown; error?: string }>(
129
- `/api/teams/workflow-runs?teamId=${encodeURIComponent(teamId)}&workflowId=${encodeURIComponent(workflowId)}&runId=${encodeURIComponent(runId)}`,
130
- { cache: "no-store" }
131
- );
132
- if (!json.ok) throw new Error(json.error || "Failed to load run");
133
- const run = isRecord(json.run) ? json.run : null;
134
- if (!run) throw new Error("Invalid run format");
135
- setSelectedRun({
136
- id: String(run.id ?? runId),
137
- status: typeof run.status === "string" ? run.status : undefined,
138
- startedAt: typeof run.startedAt === "string" ? run.startedAt : undefined,
139
- finishedAt: typeof (run as Record<string, unknown>).finishedAt === "string" ? String((run as Record<string, unknown>).finishedAt) : undefined,
140
- meta: (run as Record<string, unknown>).meta,
141
- memoryUsed: (run as Record<string, unknown>).memoryUsed,
142
- approval: (run as Record<string, unknown>).approval,
143
- raw: run,
144
- });
145
- } catch (e: unknown) {
146
- setRunError(errorMessage(e));
147
- setSelectedRun(null);
148
- }
149
- }
150
-
151
- async function onAddTemplate(templateId: string) {
152
- if (!confirm(`Add workflow from template “${templateId}”?`)) return;
153
- setError("");
154
- try {
155
- const json = await fetchJson<{ ok?: boolean; workflowId?: string; error?: string }>("/api/teams/workflow-templates", {
156
- method: "POST",
157
- headers: { "content-type": "application/json" },
158
- body: JSON.stringify({ teamId, templateId }),
159
- });
160
- if (!json.ok) throw new Error(json.error || "Failed to apply template");
161
- const workflowId = String(json.workflowId ?? "").trim();
162
- if (!workflowId) throw new Error("Template applied but workflowId missing");
163
- await load({ quiet: true });
164
- router.push(`/teams/${encodeURIComponent(teamId)}/workflows/${encodeURIComponent(workflowId)}`);
165
- } catch (e: unknown) {
166
- setError(errorMessage(e));
167
- }
168
- }
169
- const memoryUsedItems = useMemo(() => {
170
- const run = selectedRun;
171
- if (!run) return [] as Array<{ ts: string; author: string; type: string; content: string; source?: unknown }>;
172
-
173
- const raw = run.memoryUsed ?? (isRecord(run.meta) ? (run.meta as Record<string, unknown>).memoryUsed : undefined);
174
- if (!Array.isArray(raw)) return [];
175
-
176
- return raw
177
- .map((x) => (isRecord(x) ? x : null))
178
- .filter(Boolean)
179
- .map((o) => ({
180
- ts: String((o as Record<string, unknown>).ts ?? "").trim(),
181
- author: String((o as Record<string, unknown>).author ?? "").trim(),
182
- type: String((o as Record<string, unknown>).type ?? "").trim(),
183
- content: String((o as Record<string, unknown>).content ?? "").trim(),
184
- source: (o as Record<string, unknown>).source,
185
- }))
186
- .filter((it) => it.ts && it.author && it.type && it.content);
187
- }, [selectedRun]);
188
-
189
- if (loading) {
190
- return <div className="ck-glass p-4">Loading workflows…</div>;
191
- }
192
-
193
- return (
194
- <div className="ck-glass p-6">
195
- <div>
196
- <h2 className="text-lg font-semibold">Workflows (file-first)</h2>
197
- <p className="mt-1 text-sm text-[color:var(--ck-text-secondary)]">
198
- Stored in <code>shared-context/workflows/&lt;id&gt;.workflow.json</code> inside the team workspace.
199
- </p>
200
-
201
- <div className="mt-3 flex flex-wrap items-center justify-start gap-2">
202
- <button
203
- type="button"
204
- onClick={() => {
205
- const id = `new-${Date.now()}`;
206
- router.push(`/teams/${encodeURIComponent(teamId)}/workflows/${encodeURIComponent(id)}?draft=1`);
207
- }}
208
- className="rounded-[var(--ck-radius-sm)] bg-[var(--ck-accent-red)] px-3 py-2 text-sm font-medium text-white shadow-[var(--ck-shadow-1)]"
209
- >
210
- Add workflow
211
- </button>
212
-
213
-
214
- <button
215
- type="button"
216
- onClick={() => void onAddTemplate("marketing-cadence-v1")}
217
- className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-white/5 px-3 py-2 text-sm font-medium text-[color:var(--ck-text-primary)] hover:bg-white/10"
218
- >
219
- Add Marketing Cadence template
220
- </button>
221
-
222
- <button
223
- type="button"
224
- onClick={onRefresh}
225
- disabled={refreshing}
226
- className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-white/5 px-3 py-2 text-sm font-medium text-[color:var(--ck-text-primary)] hover:bg-white/10 disabled:opacity-60"
227
- >
228
- {refreshing ? "Refreshing…" : "Refresh"}
229
- </button>
230
- </div>
231
- </div>
232
-
233
- {error ? (
234
- <div className="mt-4 rounded-[var(--ck-radius-sm)] border border-red-400/30 bg-red-500/10 p-4 text-sm text-red-100">
235
- {error}
236
- </div>
237
- ) : null}
238
-
239
- {workflows.length === 0 ? (
240
- <p className="mt-4 text-sm text-[color:var(--ck-text-secondary)]">No workflows yet.</p>
241
- ) : (
242
- <ul className="mt-4 divide-y divide-white/10 overflow-hidden rounded-[var(--ck-radius-sm)] border border-white/10">
243
- {workflows.map((w) => {
244
- const expanded = expandedWorkflowId === w.id;
245
- const runs = runsByWorkflow[w.id] ?? [];
246
- const isLoadingRuns = Boolean(runsLoading[w.id]);
247
-
248
- return (
249
- <li key={w.id} className="bg-white/5">
250
- <div className="flex items-center justify-between gap-3 px-4 py-3">
251
- <button
252
- type="button"
253
- onClick={async () => {
254
- const next = expanded ? "" : w.id;
255
- setExpandedWorkflowId(next);
256
- setSelectedRunId("");
257
- setSelectedRun(null);
258
- setRunError("");
259
- if (next) await loadRunsForWorkflow(next);
260
- }}
261
- className="min-w-0 flex-1 text-left"
262
- >
263
- <div className="truncate text-sm font-medium text-[color:var(--ck-text-primary)]">{w.name || w.id}</div>
264
- <div className="truncate text-xs text-[color:var(--ck-text-tertiary)]">{w.id}</div>
265
- <div className="mt-1 text-[10px] text-[color:var(--ck-text-tertiary)]">
266
- Click to {expanded ? "collapse" : "expand"} run details
267
- </div>
268
- </button>
269
-
270
- <div className="flex shrink-0 items-center gap-2">
271
- <Link
272
- href={`/teams/${encodeURIComponent(teamId)}/workflows/${encodeURIComponent(w.id)}`}
273
- className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-white/5 px-3 py-1.5 text-sm font-medium text-[color:var(--ck-text-primary)] hover:bg-white/10"
274
- >
275
- Edit
276
- </Link>
277
- <button
278
- type="button"
279
- onClick={() => void onDelete(w.id)}
280
- className="rounded-[var(--ck-radius-sm)] border border-[color:rgba(255,59,48,0.45)] bg-[color:rgba(255,59,48,0.08)] px-3 py-1.5 text-sm font-medium text-[color:var(--ck-accent-red)] transition-colors hover:bg-[color:rgba(255,59,48,0.12)]"
281
- >
282
- Delete
283
- </button>
284
- </div>
285
- </div>
286
-
287
- {expanded ? (
288
- <div className="border-t border-white/10 bg-black/20 px-4 py-3">
289
- <div className="flex flex-wrap items-center justify-between gap-2">
290
- <div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Runs</div>
291
- <button
292
- type="button"
293
- disabled={isLoadingRuns}
294
- onClick={() => void loadRunsForWorkflow(w.id)}
295
- className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-white/5 px-2 py-1 text-[11px] font-medium text-[color:var(--ck-text-primary)] hover:bg-white/10 disabled:opacity-60"
296
- >
297
- {isLoadingRuns ? "Loading…" : "Refresh runs"}
298
- </button>
299
- </div>
300
-
301
- {runError ? (
302
- <div className="mt-2 rounded-[var(--ck-radius-sm)] border border-red-400/30 bg-red-500/10 p-2 text-xs text-red-100">{runError}</div>
303
- ) : null}
304
-
305
- <div className="mt-2 grid grid-cols-1 gap-3 lg:grid-cols-2">
306
- <div className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-2">
307
- {runs.length ? (
308
- <div className="space-y-1">
309
- {runs.slice(0, 8).map((runId) => {
310
- const selected = selectedRunId === runId;
311
- return (
312
- <button
313
- key={runId}
314
- type="button"
315
- onClick={() => void loadRunDetail(w.id, runId)}
316
- className={
317
- selected
318
- ? "w-full rounded-[var(--ck-radius-sm)] bg-white/10 px-2 py-1 text-left text-[11px] text-[color:var(--ck-text-primary)]"
319
- : "w-full rounded-[var(--ck-radius-sm)] px-2 py-1 text-left text-[11px] text-[color:var(--ck-text-secondary)] hover:bg-white/5"
320
- }
321
- >
322
- <span className="font-mono">{runId}</span>
323
- </button>
324
- );
325
- })}
326
- </div>
327
- ) : (
328
- <div className="text-xs text-[color:var(--ck-text-tertiary)]">No runs yet.</div>
329
- )}
330
- </div>
331
-
332
- <div className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-3">
333
- {selectedRun ? (
334
- <div className="space-y-3">
335
- <div>
336
- <div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Run detail</div>
337
- <div className="mt-1 text-[11px] text-[color:var(--ck-text-tertiary)]">
338
- <span className="font-mono">{selectedRun.id}</span>
339
- {selectedRun.status ? <span> • {selectedRun.status}</span> : null}
340
- </div>
341
- </div>
342
-
343
- <div className="border-t border-white/10 pt-3">
344
- <div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Approval</div>
345
- {(() => {
346
- const approval = selectedRun.approval;
347
- if (!isRecord(approval)) {
348
- return <div className="mt-2 text-xs text-[color:var(--ck-text-tertiary)]">(No approval info recorded.)</div>;
349
- }
350
-
351
- const state = String(approval.state ?? "").trim();
352
- const requestedAt = typeof approval.requestedAt === "string" ? approval.requestedAt : "";
353
- const decidedAt = typeof approval.decidedAt === "string" ? approval.decidedAt : "";
354
- const decidedBy = typeof approval.decidedBy === "string" ? approval.decidedBy : "";
355
- const note = typeof approval.note === "string" ? approval.note : "";
356
- const outbound = isRecord(approval.outbound) ? approval.outbound : null;
357
-
358
- const canAct = state === "pending" || selectedRun.status === "waiting_for_approval";
359
-
360
- return (
361
- <div className="mt-2 space-y-2">
362
- <div className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-2 text-[11px] text-[color:var(--ck-text-secondary)]">
363
- <div>
364
- <span className="font-mono">state</span>: <span className="font-mono text-[color:var(--ck-text-primary)]">{state || "(unknown)"}</span>
365
- </div>
366
- {requestedAt ? (
367
- <div>
368
- <span className="font-mono">requestedAt</span>: <span className="font-mono">{requestedAt}</span>
369
- </div>
370
- ) : null}
371
- {decidedAt ? (
372
- <div>
373
- <span className="font-mono">decidedAt</span>: <span className="font-mono">{decidedAt}</span>
374
- </div>
375
- ) : null}
376
- {decidedBy ? (
377
- <div>
378
- <span className="font-mono">decidedBy</span>: <span className="font-mono">{decidedBy}</span>
379
- </div>
380
- ) : null}
381
- {note ? (
382
- <div className="mt-1 whitespace-pre-wrap text-xs text-[color:var(--ck-text-primary)]">{note}</div>
383
- ) : null}
384
- {outbound ? (
385
- <div className="mt-2 rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/30 p-2 text-[10px]">
386
- <div className="text-[color:var(--ck-text-tertiary)]">Outbound</div>
387
- <pre className="mt-1 overflow-auto whitespace-pre-wrap">{JSON.stringify(outbound, null, 2)}</pre>
388
- </div>
389
- ) : null}
390
- </div>
391
-
392
- {canAct ? (
393
- <div className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-2">
394
- <div className="text-[10px] uppercase tracking-wide text-[color:var(--ck-text-tertiary)]">approval note (optional)</div>
395
- <textarea
396
- value={approvalNote}
397
- onChange={(e) => setApprovalNote(e.target.value)}
398
- rows={3}
399
- className="mt-1 w-full rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 px-2 py-1 text-xs text-[color:var(--ck-text-primary)]"
400
- placeholder="e.g. Ship it / please tweak hook"
401
- />
402
- <div className="mt-2 flex flex-wrap gap-2">
403
- {([
404
- { action: "approve", label: "Approve" },
405
- { action: "request_changes", label: "Request changes" },
406
- { action: "cancel", label: "Cancel" },
407
- ] as const).map((btn) => (
408
- <button
409
- key={btn.action}
410
- type="button"
411
- disabled={approvalBusy}
412
- onClick={async () => {
413
- if (!selectedWorkflowId || !selectedRunId) return;
414
- if (!confirm(`${btn.label} run ${selectedRunId}?`)) return;
415
- setApprovalBusy(true);
416
- setRunError("");
417
- try {
418
- const res = await fetch("/api/teams/workflow-runs", {
419
- method: "POST",
420
- headers: { "content-type": "application/json" },
421
- body: JSON.stringify({
422
- teamId,
423
- workflowId: selectedWorkflowId,
424
- runId: selectedRunId,
425
- action: btn.action,
426
- note: approvalNote || undefined,
427
- decidedBy: "ClawKitchen UI",
428
- }),
429
- });
430
- const json = await res.json();
431
- if (!res.ok || !json.ok) throw new Error(json.error || "Failed to apply approval action");
432
- await loadRunDetail(selectedWorkflowId, selectedRunId);
433
- } catch (e: unknown) {
434
- setRunError(errorMessage(e));
435
- } finally {
436
- setApprovalBusy(false);
437
- }
438
- }}
439
- className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-white/5 px-2 py-1 text-[11px] font-medium text-[color:var(--ck-text-primary)] hover:bg-white/10 disabled:opacity-60"
440
- >
441
- {btn.label}
442
- </button>
443
- ))}
444
- </div>
445
- </div>
446
- ) : null}
447
- </div>
448
- );
449
- })()}
450
- </div>
451
-
452
- <div className="border-t border-white/10 pt-3">
453
- <div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Memory used in this run</div>
454
- {memoryUsedItems.length ? (
455
- <div className="mt-2 space-y-2">
456
- {memoryUsedItems.slice(0, 20).map((m, idx) => (
457
- <div key={`${m.ts}-${idx}`} className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-2">
458
- <div className="text-[10px] text-[color:var(--ck-text-tertiary)]">
459
- <span className="font-mono">{m.ts}</span> • <span className="font-mono">{m.type}</span> • <span className="font-mono">{m.author}</span>
460
- </div>
461
- <div className="mt-1 whitespace-pre-wrap text-xs text-[color:var(--ck-text-primary)]">{m.content}</div>
462
- {m.source !== undefined ? (
463
- <pre className="mt-2 overflow-auto rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/30 p-2 text-[10px] text-[color:var(--ck-text-secondary)]">
464
- {JSON.stringify(m.source, null, 2)}
465
- </pre>
466
- ) : null}
467
- </div>
468
- ))}
469
- </div>
470
- ) : (
471
- <div className="mt-2 text-xs text-[color:var(--ck-text-tertiary)]">
472
- (None recorded yet.)
473
- <div className="mt-1">Next step: have the workflow runner write an explicit <span className="font-mono">memoryUsed[]</span> list into the run file.</div>
474
- </div>
475
- )}
476
- </div>
477
- </div>
478
- ) : selectedRunId ? (
479
- <div className="text-xs text-[color:var(--ck-text-secondary)]">Loading run…</div>
480
- ) : (
481
- <div className="text-xs text-[color:var(--ck-text-tertiary)]">Select a run to see details.</div>
482
- )}
483
- </div>
484
- </div>
485
- </div>
486
- ) : null}
487
- </li>
488
- );
489
- })}
490
- </ul>
491
- )}
492
- </div>
493
- );
494
- }