@jiggai/kitchen 0.1.8 → 0.1.10-canary.0
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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +5 -0
- package/.next/build-manifest.json +6 -6
- package/.next/prerender-manifest.json +3 -27
- package/.next/required-server-files.js +4 -4
- package/.next/required-server-files.json +4 -4
- package/.next/routes-manifest.json +30 -0
- package/.next/server/app/_global-error/page/build-manifest.json +4 -4
- package/.next/server/app/_global-error/page.js +2 -2
- package/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +2 -2
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page/build-manifest.json +4 -4
- package/.next/server/app/_not-found/page.js +10 -9
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +4 -4
- package/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/agents/[agentId]/page/build-manifest.json +4 -4
- package/.next/server/app/agents/[agentId]/page.js +7 -7
- package/.next/server/app/agents/[agentId]/page.js.nft.json +1 -1
- package/.next/server/app/agents/[agentId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/add/route.js +1 -1
- package/.next/server/app/api/agents/add/route.js.nft.json +1 -1
- package/.next/server/app/api/agents/files/route.js.nft.json +1 -1
- package/.next/server/app/api/agents/identity/route.js +1 -1
- package/.next/server/app/api/agents/identity/route.js.nft.json +1 -1
- package/.next/server/app/api/agents/route.js +1 -1
- package/.next/server/app/api/agents/route.js.nft.json +1 -1
- package/.next/server/app/api/gateway/restart/route.js +1 -1
- package/.next/server/app/api/gateway/restart/route.js.nft.json +1 -1
- package/.next/server/app/api/goals/[id]/promote/route.js.nft.json +1 -1
- package/.next/server/app/api/goals/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/goals/route.js.nft.json +1 -1
- package/.next/server/app/api/recipes/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/recipes/clone/route.js.nft.json +1 -1
- package/.next/server/app/api/recipes/delete/route.js.nft.json +1 -1
- package/.next/server/app/api/recipes/route.js +1 -1
- package/.next/server/app/api/recipes/route.js.nft.json +1 -1
- package/.next/server/app/api/recipes/team-agents/route.js.nft.json +1 -1
- package/.next/server/app/api/scaffold/route.js.nft.json +1 -1
- package/.next/server/app/api/swarms/start/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/swarms/start/route/build-manifest.json +11 -0
- package/.next/server/app/api/swarms/start/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/swarms/start/route.js +6 -0
- package/.next/server/app/api/swarms/start/route.js.map +5 -0
- package/.next/server/app/api/swarms/start/route.js.nft.json +1 -0
- package/.next/server/app/api/swarms/start/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/swarms/status/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/swarms/status/route/build-manifest.json +11 -0
- package/.next/server/app/api/swarms/status/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/swarms/status/route.js +6 -0
- package/.next/server/app/api/swarms/status/route.js.map +5 -0
- package/.next/server/app/api/swarms/status/route.js.nft.json +1 -0
- package/.next/server/app/api/swarms/status/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/teams/orchestrator/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/teams/orchestrator/route/build-manifest.json +11 -0
- package/.next/server/app/api/teams/orchestrator/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/teams/orchestrator/route.js +6 -0
- package/.next/server/app/api/teams/orchestrator/route.js.map +5 -0
- package/.next/server/app/api/teams/orchestrator/route.js.nft.json +1 -0
- package/.next/server/app/api/teams/orchestrator/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/teams/remove-team/route.js +1 -1
- package/.next/server/app/api/teams/remove-team/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/skills/install/route.js +1 -1
- package/.next/server/app/api/teams/skills/install/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/workflow-runs/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/teams/workflow-runs/route/build-manifest.json +11 -0
- package/.next/server/app/api/teams/workflow-runs/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/teams/workflow-runs/route.js +7 -0
- package/.next/server/app/api/teams/workflow-runs/route.js.map +5 -0
- package/.next/server/app/api/teams/workflow-runs/route.js.nft.json +1 -0
- package/.next/server/app/api/teams/workflow-runs/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/teams/workflows/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/teams/workflows/route/build-manifest.json +11 -0
- package/.next/server/app/api/teams/workflows/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/teams/workflows/route.js +6 -0
- package/.next/server/app/api/teams/workflows/route.js.map +5 -0
- package/.next/server/app/api/teams/workflows/route.js.nft.json +1 -0
- package/.next/server/app/api/teams/workflows/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/tickets/move/route.js +1 -1
- package/.next/server/app/api/tickets/move/route.js.nft.json +1 -1
- package/.next/server/app/channels/page/build-manifest.json +4 -4
- package/.next/server/app/channels/page.js +7 -7
- package/.next/server/app/channels/page.js.nft.json +1 -1
- package/.next/server/app/channels/page_client-reference-manifest.js +1 -1
- package/.next/server/app/channels.html +2 -2
- package/.next/server/app/channels.rsc +5 -5
- package/.next/server/app/channels.segments/_full.segment.rsc +5 -5
- package/.next/server/app/channels.segments/_head.segment.rsc +1 -1
- package/.next/server/app/channels.segments/_index.segment.rsc +3 -3
- package/.next/server/app/channels.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/channels.segments/channels/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/channels.segments/channels.segment.rsc +1 -1
- package/.next/server/app/cron-jobs/page/build-manifest.json +4 -4
- package/.next/server/app/cron-jobs/page.js +7 -7
- package/.next/server/app/cron-jobs/page.js.nft.json +1 -1
- package/.next/server/app/cron-jobs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/cron-jobs.html +1 -1
- package/.next/server/app/cron-jobs.rsc +6 -6
- package/.next/server/app/cron-jobs.segments/_full.segment.rsc +6 -6
- package/.next/server/app/cron-jobs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/cron-jobs.segments/_index.segment.rsc +3 -3
- package/.next/server/app/cron-jobs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/cron-jobs.segments/cron-jobs/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/cron-jobs.segments/cron-jobs.segment.rsc +1 -1
- package/.next/server/app/goals/[id]/page/build-manifest.json +4 -4
- package/.next/server/app/goals/[id]/page.js +7 -7
- package/.next/server/app/goals/[id]/page.js.nft.json +1 -1
- package/.next/server/app/goals/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/goals/new/page/build-manifest.json +4 -4
- package/.next/server/app/goals/new/page.js +7 -7
- package/.next/server/app/goals/new/page.js.nft.json +1 -1
- package/.next/server/app/goals/new/page_client-reference-manifest.js +1 -1
- package/.next/server/app/goals/new.html +2 -2
- package/.next/server/app/goals/new.rsc +5 -5
- package/.next/server/app/goals/new.segments/_full.segment.rsc +5 -5
- package/.next/server/app/goals/new.segments/_head.segment.rsc +1 -1
- package/.next/server/app/goals/new.segments/_index.segment.rsc +3 -3
- package/.next/server/app/goals/new.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/goals/new.segments/goals/new/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/goals/new.segments/goals/new.segment.rsc +1 -1
- package/.next/server/app/goals/new.segments/goals.segment.rsc +1 -1
- package/.next/server/app/goals/page/build-manifest.json +4 -4
- package/.next/server/app/goals/page.js +7 -7
- package/.next/server/app/goals/page.js.nft.json +1 -1
- package/.next/server/app/goals/page_client-reference-manifest.js +1 -1
- package/.next/server/app/goals.html +1 -1
- package/.next/server/app/goals.rsc +5 -5
- package/.next/server/app/goals.segments/_full.segment.rsc +5 -5
- package/.next/server/app/goals.segments/_head.segment.rsc +1 -1
- package/.next/server/app/goals.segments/_index.segment.rsc +3 -3
- package/.next/server/app/goals.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/goals.segments/goals/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/goals.segments/goals.segment.rsc +1 -1
- package/.next/server/app/page/build-manifest.json +4 -4
- package/.next/server/app/page.js +7 -7
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/recipes/[id]/page/build-manifest.json +4 -4
- package/.next/server/app/recipes/[id]/page.js +8 -8
- package/.next/server/app/recipes/[id]/page.js.nft.json +1 -1
- package/.next/server/app/recipes/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/recipes/page/build-manifest.json +4 -4
- package/.next/server/app/recipes/page.js +8 -8
- package/.next/server/app/recipes/page.js.nft.json +1 -1
- package/.next/server/app/recipes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/page/build-manifest.json +4 -4
- package/.next/server/app/settings/page.js +7 -7
- package/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +5 -5
- package/.next/server/app/settings.segments/_full.segment.rsc +5 -5
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +3 -3
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/teams/[teamId]/page/build-manifest.json +4 -4
- package/.next/server/app/teams/[teamId]/page.js +8 -8
- package/.next/server/app/teams/[teamId]/page.js.nft.json +1 -1
- package/.next/server/app/teams/[teamId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tickets/[ticket]/page/build-manifest.json +4 -4
- package/.next/server/app/tickets/[ticket]/page.js +7 -7
- package/.next/server/app/tickets/[ticket]/page.js.nft.json +1 -1
- package/.next/server/app/tickets/[ticket]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tickets/page/build-manifest.json +4 -4
- package/.next/server/app/tickets/page.js +7 -7
- package/.next/server/app/tickets/page.js.nft.json +1 -1
- package/.next/server/app/tickets/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +5 -0
- package/.next/server/chunks/[root-of-the-server]__065a27a4._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__065a27a4._.js.map +1 -0
- package/.next/server/chunks/{[root-of-the-server]__94d68aa3._.js → [root-of-the-server]__1989d64f._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__94d68aa3._.js.map → [root-of-the-server]__1989d64f._.js.map} +1 -1
- package/.next/server/chunks/{[root-of-the-server]__c4ffbb03._.js → [root-of-the-server]__21b72903._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__c4ffbb03._.js.map → [root-of-the-server]__21b72903._.js.map} +1 -1
- package/.next/server/chunks/{[root-of-the-server]__0c01c5c7._.js → [root-of-the-server]__262d8a6e._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__0c01c5c7._.js.map → [root-of-the-server]__262d8a6e._.js.map} +1 -1
- package/.next/server/chunks/{[root-of-the-server]__b11231a9._.js → [root-of-the-server]__2f2c799d._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__b11231a9._.js.map → [root-of-the-server]__2f2c799d._.js.map} +1 -1
- package/.next/server/chunks/[root-of-the-server]__6f85770b._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__6f85770b._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__7cf49621._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__7cf49621._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__a27f8405._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__a27f8405._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__a5226713._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__a5226713._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__c7f92fce._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__c7f92fce._.js.map +1 -0
- package/.next/server/chunks/{[root-of-the-server]__d737ca42._.js → [root-of-the-server]__e8bfeaba._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__d737ca42._.js.map → [root-of-the-server]__e8bfeaba._.js.map} +1 -1
- package/.next/server/chunks/{[root-of-the-server]__4eda99a9._.js → [root-of-the-server]__ebaa0038._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__4eda99a9._.js.map → [root-of-the-server]__ebaa0038._.js.map} +1 -1
- package/.next/server/chunks/{[root-of-the-server]__b59b3cdd._.js → [root-of-the-server]__f5546a39._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__b59b3cdd._.js.map → [root-of-the-server]__f5546a39._.js.map} +1 -1
- package/.next/server/chunks/{[root-of-the-server]__e6184ba3._.js → [root-of-the-server]__fdda9176._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__e6184ba3._.js.map → [root-of-the-server]__fdda9176._.js.map} +1 -1
- package/.next/server/chunks/_next-internal_server_app_api_swarms_start_route_actions_b79e9029.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_swarms_start_route_actions_b79e9029.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_swarms_status_route_actions_54826df0.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_swarms_status_route_actions_54826df0.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_teams_orchestrator_route_actions_1949c463.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_teams_orchestrator_route_actions_1949c463.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_teams_workflow-runs_route_actions_8327ac7d.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_teams_workflow-runs_route_actions_8327ac7d.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_teams_workflows_route_actions_43dd6e07.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_teams_workflows_route_actions_43dd6e07.js.map +1 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_1fe98a49.js +14 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_1fe98a49.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0d4cb2ba._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0fd02d84._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__4393e897._.js.map → [root-of-the-server]__0fd02d84._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__285ae6b7._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__46e08d44._.js.map → [root-of-the-server]__285ae6b7._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__2bef6884._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__15600e29._.js.map → [root-of-the-server]__2bef6884._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__3efd25c4._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__2a6f1e3e._.js.map → [root-of-the-server]__3efd25c4._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__491e06fa._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__491e06fa._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__550d78f8._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__bc3b27b0._.js.map → [root-of-the-server]__550d78f8._.js.map} +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__e2e52c6e._.js → [root-of-the-server]__78cdd31e._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__8ecc89e4._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__507d2fc9._.js.map → [root-of-the-server]__8ecc89e4._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__92524828._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__247198dc._.js.map → [root-of-the-server]__92524828._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__9e1ab064._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__9e1ab064._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__a36a058d._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__8d24c9c3._.js.map → [root-of-the-server]__a36a058d._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__a8eca9e1._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__82ce3aee._.js.map → [root-of-the-server]__a8eca9e1._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__aa8e2649._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__f75a61bf._.js.map → [root-of-the-server]__aa8e2649._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__b2617fbf._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__fd669584._.js.map → [root-of-the-server]__b2617fbf._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__b5f65083._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__b5f65083._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__e5d416d5._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__3ad3e5b1._.js.map → [root-of-the-server]__e5d416d5._.js.map} +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__b9356576._.js → [root-of-the-server]__f62d412e._.js} +2 -2
- package/.next/server/chunks/ssr/{[root-of-the-server]__b9356576._.js.map → [root-of-the-server]__f62d412e._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__fbe5ff69._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__3575e6da._.js.map → [root-of-the-server]__fbe5ff69._.js.map} +1 -1
- package/.next/server/chunks/ssr/{_8c45edba._.js → _0bdae23a._.js} +3 -3
- package/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_68c68167.js.map → _0bdae23a._.js.map} +1 -1
- package/.next/server/chunks/ssr/{_0808c2b9._.js → _347e2d56._.js} +3 -3
- package/.next/server/chunks/ssr/_347e2d56._.js.map +1 -0
- package/.next/server/chunks/ssr/{_68793c1f._.js → _49fb12c2._.js} +3 -3
- package/.next/server/chunks/ssr/_49fb12c2._.js.map +1 -0
- package/.next/server/chunks/ssr/{_3c8b2df6._.js → _536983a4._.js} +3 -3
- package/.next/server/chunks/ssr/_536983a4._.js.map +1 -0
- package/.next/server/chunks/ssr/{_cd23c5af._.js → _5b282394._.js} +3 -3
- package/.next/server/chunks/ssr/_5b282394._.js.map +1 -0
- package/.next/server/chunks/ssr/{_6e70b5a4._.js → _5cc24343._.js} +3 -3
- package/.next/server/chunks/ssr/_5cc24343._.js.map +1 -0
- package/.next/server/chunks/ssr/{_92140ca3._.js → _7eac37fb._.js} +3 -3
- package/.next/server/chunks/ssr/_7eac37fb._.js.map +1 -0
- package/.next/server/chunks/ssr/{_8c8207c1._.js → _8062e992._.js} +3 -3
- package/.next/server/chunks/ssr/_8062e992._.js.map +1 -0
- package/.next/server/chunks/ssr/{_25e6aab8._.js → _99994c05._.js} +3 -3
- package/.next/server/chunks/ssr/_99994c05._.js.map +1 -0
- package/.next/server/chunks/ssr/{_b5e9afcc._.js → _aafc99aa._.js} +3 -3
- package/.next/server/chunks/ssr/_aafc99aa._.js.map +1 -0
- package/.next/server/chunks/ssr/{_39e6e769._.js → _b7f3caf7._.js} +3 -3
- package/.next/server/chunks/ssr/_b7f3caf7._.js.map +1 -0
- package/.next/server/chunks/ssr/_c2041f88._.js +4 -0
- package/.next/server/chunks/ssr/_c2041f88._.js.map +1 -0
- package/.next/server/chunks/ssr/{_3158c108._.js → _f4d8af3b._.js} +3 -3
- package/.next/server/chunks/ssr/_f4d8af3b._.js.map +1 -0
- package/.next/server/chunks/ssr/{node_modules_next_dist_12287b3d._.js → node_modules_next_dist_8a37abed._.js} +2 -2
- package/.next/server/chunks/ssr/{node_modules_next_dist_12287b3d._.js.map → node_modules_next_dist_8a37abed._.js.map} +1 -1
- package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_9774470f._.js → node_modules_next_dist_client_components_2fffaa3a._.js} +2 -2
- package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_9774470f._.js.map → node_modules_next_dist_client_components_2fffaa3a._.js.map} +1 -1
- package/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_68c68167.js → node_modules_next_dist_esm_build_templates_app-page_b5ef32b4.js} +3 -3
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_b5ef32b4.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_HomeClient_tsx_f9f7568d._.js +1 -1
- package/.next/server/chunks/ssr/src_app_HomeClient_tsx_f9f7568d._.js.map +1 -1
- package/.next/server/chunks/ssr/src_app_global-error_tsx_aa661ba4._.js +3 -0
- package/.next/server/chunks/ssr/src_app_global-error_tsx_aa661ba4._.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_not-found_tsx_3f23d179._.js +3 -0
- package/.next/server/chunks/ssr/src_app_not-found_tsx_3f23d179._.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_teams_[teamId]_team-editor_tsx_2900b91d._.js +2 -2
- package/.next/server/chunks/ssr/src_app_teams_[teamId]_team-editor_tsx_2900b91d._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +4 -4
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +2 -2
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{40f7fde35327d214.js → 423ca3a7f09c1470.js} +1 -1
- package/.next/static/chunks/{82abf2d65f5428ae.js → 68a088aa49e6124a.js} +3 -3
- package/.next/static/chunks/96b0d0ef92ef0eca.css +3 -0
- package/.next/static/chunks/a92e9d0c91b71b55.js +1 -0
- package/.next/static/chunks/bd3fcd39d918f9b4.js +10 -0
- package/.next/static/chunks/c84580993f22c17a.js +1 -0
- package/.next/static/chunks/f3e3461eda4a8d62.js +1 -0
- package/.next/static/chunks/{turbopack-ae1340e658f67df8.js → turbopack-6c658f991a22d28a.js} +1 -1
- package/package.json +2 -2
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/chef.jpg +0 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/src/app/HomeClient.tsx +1 -1
- package/src/app/api/cron/jobs/route.ts +12 -4
- package/src/app/api/swarms/start/route.ts +118 -0
- package/src/app/api/swarms/status/route.ts +50 -0
- package/src/app/api/teams/orchestrator/route.ts +218 -0
- package/src/app/api/teams/workflow-runs/route.ts +431 -0
- package/src/app/api/teams/workflows/route.ts +88 -0
- package/src/app/cron-jobs/page.tsx +1 -1
- package/src/app/global-error.tsx +50 -0
- package/src/app/not-found.tsx +8 -0
- package/src/app/recipes/page.tsx +1 -1
- package/src/app/settings/page.tsx +1 -1
- package/src/app/teams/[teamId]/OrchestratorPanel.tsx +228 -0
- package/src/app/teams/[teamId]/page.tsx +25 -29
- package/src/app/teams/[teamId]/team-editor.tsx +1656 -8
- package/src/app/tickets/[ticket]/page.tsx +3 -0
- package/src/app/tickets/page.tsx +3 -0
- package/src/components/AppShell.tsx +245 -31
- package/src/lib/workflows/README.md +11 -0
- package/src/lib/workflows/runs-storage.ts +71 -0
- package/src/lib/workflows/runs-types.ts +32 -0
- package/src/lib/workflows/storage.ts +82 -0
- package/src/lib/workflows/types.ts +50 -0
- package/src/lib/workflows/validate.ts +70 -0
- package/.next/server/app/tickets.html +0 -1
- package/.next/server/app/tickets.meta +0 -15
- package/.next/server/app/tickets.rsc +0 -19
- package/.next/server/app/tickets.segments/_full.segment.rsc +0 -19
- package/.next/server/app/tickets.segments/_head.segment.rsc +0 -6
- package/.next/server/app/tickets.segments/_index.segment.rsc +0 -6
- package/.next/server/app/tickets.segments/_tree.segment.rsc +0 -4
- package/.next/server/app/tickets.segments/tickets/__PAGE__.segment.rsc +0 -8
- package/.next/server/app/tickets.segments/tickets.segment.rsc +0 -4
- package/.next/server/chunks/ssr/[root-of-the-server]__15600e29._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__247198dc._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__2a6f1e3e._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__346f79e5._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__346f79e5._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__3575e6da._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__3ad3e5b1._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__3bc7ad0a._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__4393e897._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__46e08d44._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__507d2fc9._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__82ce3aee._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__8d24c9c3._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__a457c799._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__a457c799._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__bc3b27b0._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__f75a61bf._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__fd669584._.js +0 -3
- package/.next/server/chunks/ssr/_0808c2b9._.js.map +0 -1
- package/.next/server/chunks/ssr/_25e6aab8._.js.map +0 -1
- package/.next/server/chunks/ssr/_3158c108._.js.map +0 -1
- package/.next/server/chunks/ssr/_39e6e769._.js.map +0 -1
- package/.next/server/chunks/ssr/_3c8b2df6._.js.map +0 -1
- package/.next/server/chunks/ssr/_68793c1f._.js.map +0 -1
- package/.next/server/chunks/ssr/_6e70b5a4._.js.map +0 -1
- package/.next/server/chunks/ssr/_8c45edba._.js.map +0 -1
- package/.next/server/chunks/ssr/_8c8207c1._.js.map +0 -1
- package/.next/server/chunks/ssr/_92140ca3._.js.map +0 -1
- package/.next/server/chunks/ssr/_b5e9afcc._.js.map +0 -1
- package/.next/server/chunks/ssr/_cd23c5af._.js.map +0 -1
- package/.next/server/chunks/ssr/_d27483a1._.js +0 -4
- package/.next/server/chunks/ssr/_d27483a1._.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_45780354.js +0 -3
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_45780354.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_ece394eb.js +0 -3
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_ece394eb.js.map +0 -1
- package/.next/static/chunks/8484c54dc9a377e8.js +0 -10
- package/.next/static/chunks/8662fcc3cdff66f3.js +0 -1
- package/.next/static/chunks/a4e69b85b74277a7.css +0 -3
- package/.next/static/chunks/a9ed074e89b16a5e.js +0 -1
- /package/.next/server/chunks/ssr/{[root-of-the-server]__3bc7ad0a._.js.map → [root-of-the-server]__0d4cb2ba._.js.map} +0 -0
- /package/.next/server/chunks/ssr/{[root-of-the-server]__e2e52c6e._.js.map → [root-of-the-server]__78cdd31e._.js.map} +0 -0
- /package/.next/static/{2hgbnJUmLMe9COlc5rJd3 → LkBl31uBDAuYl-0TzH69D}/_buildManifest.js +0 -0
- /package/.next/static/{2hgbnJUmLMe9COlc5rJd3 → LkBl31uBDAuYl-0TzH69D}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{2hgbnJUmLMe9COlc5rJd3 → LkBl31uBDAuYl-0TzH69D}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
import { NextResponse } from "next/server";
|
|
6
|
+
|
|
7
|
+
import { getKitchenApi } from "@/lib/kitchen-api";
|
|
8
|
+
|
|
9
|
+
function normalizeId(kind: string, id: string) {
|
|
10
|
+
const s = String(id ?? "").trim();
|
|
11
|
+
if (!s) throw new Error(`${kind} is required`);
|
|
12
|
+
if (!/^[a-z0-9][a-z0-9-]{0,62}$/i.test(s)) {
|
|
13
|
+
throw new Error(`${kind} must match /^[a-z0-9][a-z0-9-]{0,62}$/i`);
|
|
14
|
+
}
|
|
15
|
+
return s;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function resolveOrchestratorWorkspace(orchestratorAgentId: string) {
|
|
19
|
+
const cfgPath = path.join(os.homedir(), ".openclaw", "openclaw.json");
|
|
20
|
+
const raw = await fs.readFile(cfgPath, "utf8");
|
|
21
|
+
const cfg = JSON.parse(raw) as { agents?: { defaults?: { workspace?: string } } };
|
|
22
|
+
|
|
23
|
+
const baseWorkspace = String(cfg?.agents?.defaults?.workspace ?? "").trim();
|
|
24
|
+
if (!baseWorkspace) throw new Error("agents.defaults.workspace not set");
|
|
25
|
+
|
|
26
|
+
return path.resolve(baseWorkspace, "..", `workspace-${orchestratorAgentId}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function GET(req: Request) {
|
|
30
|
+
try {
|
|
31
|
+
const url = new URL(req.url);
|
|
32
|
+
const orchestratorAgentId = normalizeId(
|
|
33
|
+
"orchestratorAgentId",
|
|
34
|
+
url.searchParams.get("orchestratorAgentId") || url.searchParams.get("agentId") || "",
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const orchestratorWs = await resolveOrchestratorWorkspace(orchestratorAgentId);
|
|
38
|
+
const cliPath = path.join(orchestratorWs, ".clawdbot", "task.sh");
|
|
39
|
+
await fs.access(cliPath);
|
|
40
|
+
|
|
41
|
+
const api = getKitchenApi();
|
|
42
|
+
const res = await api.runtime.system.runCommandWithTimeout(["bash", cliPath, "status"], { timeoutMs: 30000 });
|
|
43
|
+
|
|
44
|
+
return NextResponse.json({ ok: true, orchestratorWorkspace: orchestratorWs, stdout: res.stdout, stderr: res.stderr });
|
|
45
|
+
} catch (err) {
|
|
46
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
47
|
+
const status = /required|match \//i.test(msg) ? 400 : 500;
|
|
48
|
+
return NextResponse.json({ ok: false, error: msg }, { status });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { NextResponse } from "next/server";
|
|
4
|
+
|
|
5
|
+
import { runOpenClaw } from "@/lib/openclaw";
|
|
6
|
+
import { getKitchenApi } from "@/lib/kitchen-api";
|
|
7
|
+
|
|
8
|
+
type AgentListItem = {
|
|
9
|
+
id: string;
|
|
10
|
+
identityName?: string;
|
|
11
|
+
workspace?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type TmuxSession = {
|
|
15
|
+
name: string;
|
|
16
|
+
attached: boolean;
|
|
17
|
+
windows?: number;
|
|
18
|
+
created?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type GitWorktree = {
|
|
22
|
+
path: string;
|
|
23
|
+
branch?: string;
|
|
24
|
+
sha?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
async function listAgents(): Promise<AgentListItem[]> {
|
|
28
|
+
const res = await runOpenClaw(["agents", "list", "--json"]);
|
|
29
|
+
if (!res.ok) throw new Error(res.stderr || "Failed to list agents");
|
|
30
|
+
return JSON.parse(res.stdout) as AgentListItem[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function pickOrchestratorAgentId(teamId: string, agents: AgentListItem[]) {
|
|
34
|
+
const candidates = [
|
|
35
|
+
`${teamId}-swarm-orchestrator`,
|
|
36
|
+
`${teamId}-orchestrator`,
|
|
37
|
+
"swarm-orchestrator",
|
|
38
|
+
"orchestrator",
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
for (const id of candidates) {
|
|
42
|
+
const match = agents.find((a) => a.id === id);
|
|
43
|
+
if (match) return match;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Heuristic fallback: any agent id containing "orchestrator" whose workspace path mentions the teamId.
|
|
47
|
+
const heuristic = agents.find((a) => {
|
|
48
|
+
const id = String(a.id ?? "");
|
|
49
|
+
const ws = String(a.workspace ?? "");
|
|
50
|
+
return id.includes("orchestrator") && (ws.includes(`/workspace-${teamId}`) || ws.includes(teamId));
|
|
51
|
+
});
|
|
52
|
+
return heuristic ?? null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function runCommand(argv: string[], timeoutMs = 8000) {
|
|
56
|
+
const api = getKitchenApi();
|
|
57
|
+
const res = (await api.runtime.system.runCommandWithTimeout(argv, { timeoutMs })) as {
|
|
58
|
+
stdout?: unknown;
|
|
59
|
+
stderr?: unknown;
|
|
60
|
+
};
|
|
61
|
+
return { stdout: String(res.stdout ?? ""), stderr: String(res.stderr ?? "") };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function parseTmuxList(stdout: string): TmuxSession[] {
|
|
65
|
+
const lines = stdout
|
|
66
|
+
.split("\n")
|
|
67
|
+
.map((l) => l.trimEnd())
|
|
68
|
+
.filter(Boolean);
|
|
69
|
+
|
|
70
|
+
// Expected format:
|
|
71
|
+
// name\tattached\twindows\tcreated
|
|
72
|
+
return lines.map((line) => {
|
|
73
|
+
const [name, attached, windows, created] = line.split("\t");
|
|
74
|
+
return {
|
|
75
|
+
name: String(name ?? "").trim(),
|
|
76
|
+
attached: String(attached ?? "0").trim() === "1",
|
|
77
|
+
windows: windows ? Number(windows) : undefined,
|
|
78
|
+
created: created ? String(created) : undefined,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function parseWorktreePorcelain(stdout: string): GitWorktree[] {
|
|
84
|
+
// `git worktree list --porcelain` is a list of blocks separated by blank lines.
|
|
85
|
+
const blocks = stdout
|
|
86
|
+
.split(/\n\s*\n/g)
|
|
87
|
+
.map((b) => b.trim())
|
|
88
|
+
.filter(Boolean);
|
|
89
|
+
|
|
90
|
+
return blocks
|
|
91
|
+
.map((block) => {
|
|
92
|
+
const wt: GitWorktree = { path: "" };
|
|
93
|
+
for (const rawLine of block.split("\n")) {
|
|
94
|
+
const line = rawLine.trim();
|
|
95
|
+
if (line.startsWith("worktree ")) wt.path = line.slice("worktree ".length).trim();
|
|
96
|
+
else if (line.startsWith("HEAD ")) wt.sha = line.slice("HEAD ".length).trim();
|
|
97
|
+
else if (line.startsWith("branch ")) wt.branch = line.slice("branch ".length).trim();
|
|
98
|
+
}
|
|
99
|
+
return wt.path ? wt : null;
|
|
100
|
+
})
|
|
101
|
+
.filter((x): x is GitWorktree => Boolean(x));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function firstExistingJsonFile(absCandidates: string[]) {
|
|
105
|
+
for (const p of absCandidates) {
|
|
106
|
+
try {
|
|
107
|
+
const stat = await fs.stat(p);
|
|
108
|
+
if (stat.isFile()) return p;
|
|
109
|
+
} catch {
|
|
110
|
+
// ignore
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function GET(req: Request) {
|
|
117
|
+
const { searchParams } = new URL(req.url);
|
|
118
|
+
const teamId = String(searchParams.get("teamId") ?? "").trim();
|
|
119
|
+
if (!teamId) return NextResponse.json({ ok: false, error: "teamId is required" }, { status: 400 });
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const agents = await listAgents();
|
|
123
|
+
const match = pickOrchestratorAgentId(teamId, agents);
|
|
124
|
+
|
|
125
|
+
if (!match || !match.workspace) {
|
|
126
|
+
return NextResponse.json({
|
|
127
|
+
ok: true,
|
|
128
|
+
teamId,
|
|
129
|
+
present: false,
|
|
130
|
+
reason:
|
|
131
|
+
"No orchestrator agent detected. Expected an agent id like <teamId>-swarm-orchestrator (or swarm-orchestrator).",
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const workspace = match.workspace;
|
|
136
|
+
|
|
137
|
+
// tmux sessions (best-effort)
|
|
138
|
+
let tmuxSessions: TmuxSession[] = [];
|
|
139
|
+
try {
|
|
140
|
+
const { stdout } = await runCommand([
|
|
141
|
+
"tmux",
|
|
142
|
+
"ls",
|
|
143
|
+
"-F",
|
|
144
|
+
"#S\t#{session_attached}\t#{session_windows}\t#{session_created_string}",
|
|
145
|
+
]);
|
|
146
|
+
tmuxSessions = parseTmuxList(stdout);
|
|
147
|
+
} catch {
|
|
148
|
+
tmuxSessions = [];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// git worktrees (best-effort)
|
|
152
|
+
let worktrees: GitWorktree[] = [];
|
|
153
|
+
try {
|
|
154
|
+
const { stdout } = await runCommand(["git", "-C", workspace, "worktree", "list", "--porcelain"], 12000);
|
|
155
|
+
worktrees = parseWorktreePorcelain(stdout);
|
|
156
|
+
} catch {
|
|
157
|
+
worktrees = [];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// active tasks (best-effort)
|
|
161
|
+
const activeTasksPath = await firstExistingJsonFile([
|
|
162
|
+
path.join(workspace, "active-tasks.json"),
|
|
163
|
+
path.join(workspace, ".clawdbot", "active-tasks.json"),
|
|
164
|
+
path.join(workspace, "notes", "active-tasks.json"),
|
|
165
|
+
]);
|
|
166
|
+
|
|
167
|
+
let activeTasksSummary: { path: string; taskCount?: number; rawType?: string } | null = null;
|
|
168
|
+
if (activeTasksPath) {
|
|
169
|
+
try {
|
|
170
|
+
const raw = await fs.readFile(activeTasksPath, "utf8");
|
|
171
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
172
|
+
if (Array.isArray(parsed)) {
|
|
173
|
+
activeTasksSummary = { path: activeTasksPath, taskCount: parsed.length, rawType: "array" };
|
|
174
|
+
} else if (parsed && typeof parsed === "object") {
|
|
175
|
+
const obj = parsed as { tasks?: unknown };
|
|
176
|
+
const tasks = Array.isArray(obj.tasks) ? obj.tasks : null;
|
|
177
|
+
activeTasksSummary = {
|
|
178
|
+
path: activeTasksPath,
|
|
179
|
+
taskCount: tasks ? tasks.length : undefined,
|
|
180
|
+
rawType: "object",
|
|
181
|
+
};
|
|
182
|
+
} else {
|
|
183
|
+
activeTasksSummary = { path: activeTasksPath, rawType: typeof parsed };
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
activeTasksSummary = { path: activeTasksPath };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const settingsPaths = [
|
|
191
|
+
path.join(workspace, ".env"),
|
|
192
|
+
path.join(workspace, ".clawdbot", "README.md"),
|
|
193
|
+
path.join(workspace, ".clawdbot", "CONVENTIONS.md"),
|
|
194
|
+
path.join(workspace, ".clawdbot", "PROMPT_TEMPLATE.md"),
|
|
195
|
+
path.join(workspace, ".clawdbot", "TEMPLATE.md"),
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
return NextResponse.json({
|
|
199
|
+
ok: true,
|
|
200
|
+
teamId,
|
|
201
|
+
present: true,
|
|
202
|
+
agent: {
|
|
203
|
+
id: match.id,
|
|
204
|
+
identityName: match.identityName,
|
|
205
|
+
workspace,
|
|
206
|
+
},
|
|
207
|
+
tmuxSessions,
|
|
208
|
+
worktrees,
|
|
209
|
+
activeTasksSummary,
|
|
210
|
+
settingsPaths,
|
|
211
|
+
});
|
|
212
|
+
} catch (e: unknown) {
|
|
213
|
+
return NextResponse.json(
|
|
214
|
+
{ ok: false, error: e instanceof Error ? e.message : String(e) },
|
|
215
|
+
{ status: 500 },
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import { listWorkflowRuns, readWorkflowRun, writeWorkflowRun } from "@/lib/workflows/runs-storage";
|
|
4
|
+
import type { WorkflowRunFileV1, WorkflowRunNodeResultV1 } from "@/lib/workflows/runs-types";
|
|
5
|
+
import { readWorkflow } from "@/lib/workflows/storage";
|
|
6
|
+
import type { WorkflowFileV1 } from "@/lib/workflows/types";
|
|
7
|
+
import { toolsInvoke } from "@/lib/gateway";
|
|
8
|
+
|
|
9
|
+
function errMessage(err: unknown) {
|
|
10
|
+
return err instanceof Error ? err.message : String(err);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function nowIso() {
|
|
14
|
+
return new Date().toISOString();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isRecord(v: unknown): v is Record<string, unknown> {
|
|
18
|
+
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function formatApprovalPacketMessage(workflow: WorkflowFileV1, run: WorkflowRunFileV1, approvalNodeId: string): string {
|
|
22
|
+
const title = `${workflow.name || workflow.id} — Approval needed`;
|
|
23
|
+
const runLine = `Run: ${run.id}`;
|
|
24
|
+
|
|
25
|
+
const approvalNode = Array.isArray(run.nodes) ? run.nodes.find((n) => n.nodeId === approvalNodeId) : undefined;
|
|
26
|
+
const out = isRecord(approvalNode?.output) ? approvalNode.output : {};
|
|
27
|
+
const packet = isRecord(out.packet) ? out.packet : null;
|
|
28
|
+
const platforms = packet && isRecord(packet.platforms) ? (packet.platforms as Record<string, unknown>) : null;
|
|
29
|
+
|
|
30
|
+
let body = `${title}\n${runLine}\n\n`;
|
|
31
|
+
|
|
32
|
+
if (packet && typeof packet.note === "string" && packet.note.trim()) {
|
|
33
|
+
body += `${packet.note.trim()}\n\n`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (platforms) {
|
|
37
|
+
body += "Drafts:\n";
|
|
38
|
+
for (const [k, v] of Object.entries(platforms)) {
|
|
39
|
+
if (!v) continue;
|
|
40
|
+
const p = isRecord(v) ? v : { value: v };
|
|
41
|
+
const hook = typeof p.hook === "string" ? p.hook.trim() : "";
|
|
42
|
+
const text = typeof p.body === "string" ? p.body.trim() : "";
|
|
43
|
+
const script = typeof p.script === "string" ? p.script.trim() : "";
|
|
44
|
+
const notes = typeof p.assetNotes === "string" ? p.assetNotes.trim() : "";
|
|
45
|
+
|
|
46
|
+
body += `\n— ${k.toUpperCase()} —\n`;
|
|
47
|
+
if (hook) body += `Hook: ${hook}\n`;
|
|
48
|
+
if (text) body += `Body: ${text}\n`;
|
|
49
|
+
if (script) body += `Script: ${script}\n`;
|
|
50
|
+
if (notes) body += `Notes: ${notes}\n`;
|
|
51
|
+
}
|
|
52
|
+
body += "\n";
|
|
53
|
+
} else {
|
|
54
|
+
body += "(No structured approval packet found in run file.)\n\n";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
body += "Reply in ClawKitchen: Approve / Request changes / Cancel.";
|
|
58
|
+
return body;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function maybeSendApprovalRequest({
|
|
62
|
+
teamId,
|
|
63
|
+
workflow,
|
|
64
|
+
run,
|
|
65
|
+
approvalNodeId,
|
|
66
|
+
}: {
|
|
67
|
+
teamId: string;
|
|
68
|
+
workflow: WorkflowFileV1;
|
|
69
|
+
run: WorkflowRunFileV1;
|
|
70
|
+
approvalNodeId: string;
|
|
71
|
+
}) {
|
|
72
|
+
const meta = isRecord(workflow.meta) ? workflow.meta : {};
|
|
73
|
+
const provider = String(meta.approvalProvider ?? "telegram").trim() || "telegram";
|
|
74
|
+
const target = String(meta.approvalTarget ?? "").trim();
|
|
75
|
+
if (!target) return;
|
|
76
|
+
|
|
77
|
+
const message = formatApprovalPacketMessage(workflow, run, approvalNodeId);
|
|
78
|
+
|
|
79
|
+
// Best-effort: message delivery failures should not block file-first persistence.
|
|
80
|
+
await toolsInvoke({
|
|
81
|
+
tool: "message",
|
|
82
|
+
args: {
|
|
83
|
+
action: "send",
|
|
84
|
+
channel: provider,
|
|
85
|
+
target,
|
|
86
|
+
message,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Writeback of delivery info happens in the caller (so we can record errors too).
|
|
91
|
+
void teamId;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function GET(req: Request) {
|
|
95
|
+
const { searchParams } = new URL(req.url);
|
|
96
|
+
const teamId = String(searchParams.get("teamId") ?? "").trim();
|
|
97
|
+
const workflowId = String(searchParams.get("workflowId") ?? "").trim();
|
|
98
|
+
const runId = String(searchParams.get("runId") ?? "").trim();
|
|
99
|
+
|
|
100
|
+
if (!teamId) return NextResponse.json({ ok: false, error: "teamId is required" }, { status: 400 });
|
|
101
|
+
if (!workflowId) return NextResponse.json({ ok: false, error: "workflowId is required" }, { status: 400 });
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
if (runId) {
|
|
105
|
+
const r = await readWorkflowRun(teamId, workflowId, runId);
|
|
106
|
+
const { ok, ...rest } = r;
|
|
107
|
+
void ok;
|
|
108
|
+
return NextResponse.json({ ok: true, ...rest });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const r = await listWorkflowRuns(teamId, workflowId);
|
|
112
|
+
const { ok, ...rest } = r;
|
|
113
|
+
void ok;
|
|
114
|
+
return NextResponse.json({ ok: true, ...rest });
|
|
115
|
+
} catch (err: unknown) {
|
|
116
|
+
return NextResponse.json({ ok: false, error: errMessage(err) }, { status: 500 });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export async function POST(req: Request) {
|
|
121
|
+
let body: unknown;
|
|
122
|
+
try {
|
|
123
|
+
body = await req.json();
|
|
124
|
+
} catch {
|
|
125
|
+
return NextResponse.json({ ok: false, error: "Invalid JSON" }, { status: 400 });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const o = body && typeof body === "object" ? (body as Record<string, unknown>) : {};
|
|
129
|
+
const teamId = String(o.teamId ?? "").trim();
|
|
130
|
+
const workflowId = String(o.workflowId ?? "").trim();
|
|
131
|
+
const mode = String(o.mode ?? "").trim();
|
|
132
|
+
const action = String(o.action ?? "").trim();
|
|
133
|
+
const runIdFromBody = String(o.runId ?? "").trim();
|
|
134
|
+
const note = typeof o.note === "string" ? o.note : undefined;
|
|
135
|
+
|
|
136
|
+
if (!teamId) return NextResponse.json({ ok: false, error: "teamId is required" }, { status: 400 });
|
|
137
|
+
if (!workflowId) return NextResponse.json({ ok: false, error: "workflowId is required" }, { status: 400 });
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
// Action mode: approve/request_changes/cancel (file-first) updates an existing run.
|
|
141
|
+
if (action) {
|
|
142
|
+
if (!runIdFromBody) return NextResponse.json({ ok: false, error: "runId is required for action" }, { status: 400 });
|
|
143
|
+
if (!["approve", "request_changes", "cancel"].includes(action)) {
|
|
144
|
+
return NextResponse.json({ ok: false, error: `Unsupported action: ${action}` }, { status: 400 });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const existing = await readWorkflowRun(teamId, workflowId, runIdFromBody);
|
|
148
|
+
const run = existing.run;
|
|
149
|
+
|
|
150
|
+
const approvalNodeId = run.approval?.nodeId || (Array.isArray(run.nodes) ? run.nodes.find((n) => n.status === "waiting")?.nodeId : undefined);
|
|
151
|
+
if (!approvalNodeId) {
|
|
152
|
+
return NextResponse.json({ ok: false, error: "Run is not awaiting approval" }, { status: 400 });
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const decidedAt = nowIso();
|
|
156
|
+
const nextState = action === "approve" ? "approved" : action === "request_changes" ? "changes_requested" : "canceled";
|
|
157
|
+
|
|
158
|
+
const nextStatus: WorkflowRunFileV1["status"] =
|
|
159
|
+
nextState === "approved" ? "success" : nextState === "canceled" ? "canceled" : "waiting_for_approval";
|
|
160
|
+
|
|
161
|
+
const nextNodes: WorkflowRunNodeResultV1[] = Array.isArray(run.nodes)
|
|
162
|
+
? run.nodes.map((n) => {
|
|
163
|
+
if (n.nodeId === approvalNodeId) {
|
|
164
|
+
const existingOutput = typeof n.output === "object" && n.output ? (n.output as Record<string, unknown>) : {};
|
|
165
|
+
return {
|
|
166
|
+
...n,
|
|
167
|
+
status: nextState === "approved" ? "success" : nextState === "canceled" ? "error" : "waiting",
|
|
168
|
+
endedAt: nextState === "changes_requested" ? n.endedAt : decidedAt,
|
|
169
|
+
output: {
|
|
170
|
+
...existingOutput,
|
|
171
|
+
decision: nextState,
|
|
172
|
+
note,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// For approve/cancel, resolve any remaining pending nodes so the run detail view is coherent.
|
|
178
|
+
if (nextState === "approved" && n.status === "pending") {
|
|
179
|
+
return {
|
|
180
|
+
...n,
|
|
181
|
+
status: "success",
|
|
182
|
+
startedAt: n.startedAt ?? decidedAt,
|
|
183
|
+
endedAt: decidedAt,
|
|
184
|
+
output: n.output ?? { note: "(execution engine not yet wired)" },
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (nextState === "canceled" && n.status === "pending") {
|
|
189
|
+
return {
|
|
190
|
+
...n,
|
|
191
|
+
status: "skipped",
|
|
192
|
+
startedAt: n.startedAt ?? decidedAt,
|
|
193
|
+
endedAt: decidedAt,
|
|
194
|
+
output: n.output ?? { note: "skipped due to cancel" },
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return n;
|
|
199
|
+
})
|
|
200
|
+
: [];
|
|
201
|
+
|
|
202
|
+
const nextRun: WorkflowRunFileV1 = {
|
|
203
|
+
...run,
|
|
204
|
+
status: nextStatus,
|
|
205
|
+
endedAt: nextStatus === "success" || nextStatus === "canceled" ? decidedAt : run.endedAt,
|
|
206
|
+
approval: {
|
|
207
|
+
nodeId: approvalNodeId,
|
|
208
|
+
state: nextState,
|
|
209
|
+
requestedAt: run.approval?.requestedAt,
|
|
210
|
+
decidedAt: nextState === "changes_requested" ? undefined : decidedAt,
|
|
211
|
+
note,
|
|
212
|
+
},
|
|
213
|
+
nodes: nextNodes,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const wr = await writeWorkflowRun(teamId, workflowId, nextRun);
|
|
217
|
+
const { ok, ...rest } = wr;
|
|
218
|
+
void ok;
|
|
219
|
+
return NextResponse.json({ ok: true, runId: run.id, ...rest });
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Create mode
|
|
223
|
+
const runId = `run-${nowIso().replace(/[:.]/g, "-")}-${crypto.randomBytes(3).toString("hex")}`.toLowerCase();
|
|
224
|
+
|
|
225
|
+
const run: WorkflowRunFileV1 =
|
|
226
|
+
mode === "sample"
|
|
227
|
+
? await (async () => {
|
|
228
|
+
const wf = (await readWorkflow(teamId, workflowId)).workflow;
|
|
229
|
+
const t0 = Date.now();
|
|
230
|
+
|
|
231
|
+
const templateId =
|
|
232
|
+
wf.meta && typeof wf.meta === "object" && "templateId" in wf.meta ? (wf.meta as Record<string, unknown>).templateId : undefined;
|
|
233
|
+
const isMarketingCadence = templateId === "marketing-cadence-v1";
|
|
234
|
+
|
|
235
|
+
const marketingDrafts = isMarketingCadence
|
|
236
|
+
? {
|
|
237
|
+
x: {
|
|
238
|
+
hook: "Stop losing hours to repetitive agent setup.",
|
|
239
|
+
body: "ClawRecipes scaffolds entire teams of agents in one command — workflows, roles, conventions, and a human-approval gate before posting.",
|
|
240
|
+
},
|
|
241
|
+
instagram: {
|
|
242
|
+
hook: "Ship agent workflows faster.",
|
|
243
|
+
body: "From idea → drafted assets → brand QC → approval → posting. File-first workflows you can export and version.",
|
|
244
|
+
assetNotes: "Square image: diagram of workflow nodes + approval gate.",
|
|
245
|
+
},
|
|
246
|
+
tiktok: {
|
|
247
|
+
hook: "POV: you stop copy/pasting prompts.",
|
|
248
|
+
script: "Today I’m building a marketing cadence workflow that researches, drafts, QC’s, then waits for human approval before it posts. File-first. Portable. No magic.",
|
|
249
|
+
assetNotes: "15–25s screen recording of the canvas + approval buttons.",
|
|
250
|
+
},
|
|
251
|
+
youtube: {
|
|
252
|
+
hook: "Build a marketing cadence workflow (with human approval) in 2 minutes.",
|
|
253
|
+
script: "We’ll wire research → drafts → QC → approval → post nodes, and persist the whole thing to shared-context/workflows/*.workflow.json so it’s portable.",
|
|
254
|
+
assetNotes: "Thumbnail: workflow canvas with 'Approve & Post' highlighted.",
|
|
255
|
+
},
|
|
256
|
+
}
|
|
257
|
+
: null;
|
|
258
|
+
|
|
259
|
+
const approvalIdx = wf.nodes.findIndex((n) => n.type === "human_approval");
|
|
260
|
+
const approvalNodeId = approvalIdx >= 0 ? wf.nodes[approvalIdx]?.id : undefined;
|
|
261
|
+
|
|
262
|
+
const nodeResults: WorkflowRunNodeResultV1[] = wf.nodes.map((n, idx) => {
|
|
263
|
+
const startedAt = new Date(t0 + idx * 350).toISOString();
|
|
264
|
+
const endedAt = new Date(t0 + idx * 350 + 200).toISOString();
|
|
265
|
+
|
|
266
|
+
const beforeApproval = approvalIdx < 0 ? true : idx < approvalIdx;
|
|
267
|
+
const isApproval = approvalNodeId ? n.id === approvalNodeId : false;
|
|
268
|
+
const afterApproval = approvalIdx >= 0 && idx > approvalIdx;
|
|
269
|
+
|
|
270
|
+
const base: WorkflowRunNodeResultV1 = {
|
|
271
|
+
nodeId: n.id,
|
|
272
|
+
status: beforeApproval ? "success" : afterApproval ? "pending" : isApproval ? "waiting" : "success",
|
|
273
|
+
startedAt,
|
|
274
|
+
endedAt: beforeApproval ? endedAt : undefined,
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
if (n.type === "llm") {
|
|
278
|
+
const marketingOutput =
|
|
279
|
+
beforeApproval && isMarketingCadence
|
|
280
|
+
? n.id === "research"
|
|
281
|
+
? {
|
|
282
|
+
model: "(sample)",
|
|
283
|
+
kind: "research",
|
|
284
|
+
bullets: [
|
|
285
|
+
"New agent teams are compelling when they’re portable + file-first.",
|
|
286
|
+
"Human approval gates are mandatory for auto-post workflows.",
|
|
287
|
+
"Cron triggers need timezone + preset suggestions.",
|
|
288
|
+
],
|
|
289
|
+
}
|
|
290
|
+
: n.id === "draft_assets"
|
|
291
|
+
? {
|
|
292
|
+
model: "(sample)",
|
|
293
|
+
kind: "draft_assets",
|
|
294
|
+
drafts: marketingDrafts,
|
|
295
|
+
}
|
|
296
|
+
: n.id === "qc_brand"
|
|
297
|
+
? {
|
|
298
|
+
model: "(sample)",
|
|
299
|
+
kind: "qc_brand",
|
|
300
|
+
notes: [
|
|
301
|
+
"Keep claims concrete (no ‘magic’).",
|
|
302
|
+
"Mention ClawRecipes before OpenClaw.",
|
|
303
|
+
"Explicitly state: no posting without approval.",
|
|
304
|
+
],
|
|
305
|
+
}
|
|
306
|
+
: {
|
|
307
|
+
model: "(sample)",
|
|
308
|
+
text: `Sample output for ${n.id}`,
|
|
309
|
+
}
|
|
310
|
+
: null;
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
...base,
|
|
314
|
+
output: beforeApproval
|
|
315
|
+
? marketingOutput ?? {
|
|
316
|
+
model: "(sample)",
|
|
317
|
+
text: `Sample output for ${n.id}`,
|
|
318
|
+
}
|
|
319
|
+
: undefined,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (n.type === "tool") {
|
|
324
|
+
const toolVal = n.config && typeof n.config === "object" ? (n.config as Record<string, unknown>).tool : undefined;
|
|
325
|
+
const tool = typeof toolVal === "string" && toolVal.trim() ? toolVal.trim() : "(unknown)";
|
|
326
|
+
return {
|
|
327
|
+
...base,
|
|
328
|
+
output: beforeApproval
|
|
329
|
+
? {
|
|
330
|
+
tool,
|
|
331
|
+
result: "(sample tool result)",
|
|
332
|
+
}
|
|
333
|
+
: undefined,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (n.type === "human_approval") {
|
|
338
|
+
const approvalPacket = isMarketingCadence
|
|
339
|
+
? {
|
|
340
|
+
channel: "(sample)",
|
|
341
|
+
decision: "pending",
|
|
342
|
+
options: ["approve", "request_changes", "cancel"],
|
|
343
|
+
packet: {
|
|
344
|
+
templateId: "marketing-cadence-v1",
|
|
345
|
+
note: "Per-platform drafts (sample) — approve to post, request changes to loop, or cancel.",
|
|
346
|
+
platforms: {
|
|
347
|
+
x: marketingDrafts?.x,
|
|
348
|
+
instagram: marketingDrafts?.instagram,
|
|
349
|
+
tiktok: marketingDrafts?.tiktok,
|
|
350
|
+
youtube: marketingDrafts?.youtube,
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
}
|
|
354
|
+
: {
|
|
355
|
+
channel: "(sample)",
|
|
356
|
+
decision: "pending",
|
|
357
|
+
options: ["approve", "request_changes", "cancel"],
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
return {
|
|
361
|
+
...base,
|
|
362
|
+
output: approvalPacket,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return base;
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const status: WorkflowRunFileV1["status"] = approvalNodeId ? "waiting_for_approval" : "success";
|
|
370
|
+
|
|
371
|
+
const baseRun: WorkflowRunFileV1 = {
|
|
372
|
+
schema: "clawkitchen.workflow-run.v1",
|
|
373
|
+
id: runId,
|
|
374
|
+
workflowId,
|
|
375
|
+
startedAt: new Date(t0).toISOString(),
|
|
376
|
+
endedAt: approvalNodeId ? undefined : new Date(t0 + wf.nodes.length * 350 + 200).toISOString(),
|
|
377
|
+
status,
|
|
378
|
+
summary: approvalNodeId
|
|
379
|
+
? "Sample run (awaiting approval)"
|
|
380
|
+
: "Sample run (generated by ClawKitchen UI)",
|
|
381
|
+
nodes: nodeResults,
|
|
382
|
+
approval: approvalNodeId
|
|
383
|
+
? {
|
|
384
|
+
nodeId: approvalNodeId,
|
|
385
|
+
state: "pending",
|
|
386
|
+
requestedAt: new Date(t0 + approvalIdx * 350).toISOString(),
|
|
387
|
+
}
|
|
388
|
+
: undefined,
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
if (approvalNodeId) {
|
|
392
|
+
const meta = isRecord(wf.meta) ? wf.meta : {};
|
|
393
|
+
const provider = String(meta.approvalProvider ?? "telegram").trim() || "telegram";
|
|
394
|
+
const target = String(meta.approvalTarget ?? "").trim();
|
|
395
|
+
|
|
396
|
+
if (target) {
|
|
397
|
+
try {
|
|
398
|
+
await maybeSendApprovalRequest({ teamId, workflow: wf, run: baseRun, approvalNodeId });
|
|
399
|
+
baseRun.approval = {
|
|
400
|
+
...baseRun.approval,
|
|
401
|
+
outbound: { provider, target, sentAt: nowIso() },
|
|
402
|
+
} as WorkflowRunFileV1["approval"];
|
|
403
|
+
} catch (e: unknown) {
|
|
404
|
+
baseRun.approval = {
|
|
405
|
+
...baseRun.approval,
|
|
406
|
+
outbound: { provider, target, error: errMessage(e), attemptedAt: nowIso() },
|
|
407
|
+
} as WorkflowRunFileV1["approval"];
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return baseRun satisfies WorkflowRunFileV1;
|
|
413
|
+
})()
|
|
414
|
+
: {
|
|
415
|
+
schema: "clawkitchen.workflow-run.v1",
|
|
416
|
+
id: runId,
|
|
417
|
+
workflowId,
|
|
418
|
+
startedAt: nowIso(),
|
|
419
|
+
status: "running",
|
|
420
|
+
summary: "Run created (execution engine not yet wired)",
|
|
421
|
+
nodes: [],
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
const r = await writeWorkflowRun(teamId, workflowId, run);
|
|
425
|
+
const { ok, ...rest } = r;
|
|
426
|
+
void ok;
|
|
427
|
+
return NextResponse.json({ ok: true, runId, ...rest });
|
|
428
|
+
} catch (err: unknown) {
|
|
429
|
+
return NextResponse.json({ ok: false, error: errMessage(err) }, { status: 500 });
|
|
430
|
+
}
|
|
431
|
+
}
|