@jiggai/kitchen 0.3.10 → 0.3.12
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/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- 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.js +1 -1
- 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.js +1 -1
- 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.nft.json +1 -1
- package/.next/server/app/api/agents/file/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/skills/install/route.js.nft.json +1 -1
- package/.next/server/app/api/agents/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/agents/update/route.js.nft.json +1 -1
- package/.next/server/app/api/cron/delete/route.js.nft.json +1 -1
- package/.next/server/app/api/cron/jobs/route.js.nft.json +1 -1
- package/.next/server/app/api/cron/recipe-installed/route.js.nft.json +1 -1
- package/.next/server/app/api/cron/worker/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/ids/check/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/custom-team/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/local-agent-catalog/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/settings/cron-installation/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/[teamId]/tickets/assign/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/[teamId]/tickets/assignees/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/[teamId]/tickets/comment/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/[teamId]/tickets/delete/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/[teamId]/tickets/move/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/[teamId]/tickets/move-to-goals/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/file/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/files/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/memory/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/meta/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/orchestrator/route.js.nft.json +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.nft.json +1 -1
- package/.next/server/app/api/teams/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/workflow-runs/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/workflow-templates/route.js.nft.json +1 -1
- package/.next/server/app/api/teams/workflows/route.js.nft.json +1 -1
- package/.next/server/app/api/tickets/assign/route.js.nft.json +1 -1
- package/.next/server/app/api/tickets/assignees/route.js.nft.json +1 -1
- package/.next/server/app/api/tickets/move/route.js.nft.json +1 -1
- package/.next/server/app/channels/page.js +1 -1
- 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.js +1 -1
- 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/goals/[id]/page.js +1 -1
- 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.js +1 -1
- 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.js +1 -1
- 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.js +3 -3
- 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.js +4 -4
- 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.js +3 -3
- 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/runs/page.js +4 -4
- package/.next/server/app/runs/page.js.nft.json +1 -1
- package/.next/server/app/runs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/page.js +1 -1
- 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.js +4 -4
- 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/teams/[teamId]/runs/[workflowId]/[runId]/page.js +3 -3
- package/.next/server/app/teams/[teamId]/runs/[workflowId]/[runId]/page.js.nft.json +1 -1
- package/.next/server/app/teams/[teamId]/runs/[workflowId]/[runId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/teams/[teamId]/runs/page.js +1 -1
- package/.next/server/app/teams/[teamId]/runs/page.js.nft.json +1 -1
- package/.next/server/app/teams/[teamId]/runs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/teams/[teamId]/tickets/[ticket]/page.js +1 -1
- package/.next/server/app/teams/[teamId]/tickets/[ticket]/page.js.nft.json +1 -1
- package/.next/server/app/teams/[teamId]/tickets/[ticket]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/teams/[teamId]/tickets/page.js +2 -2
- package/.next/server/app/teams/[teamId]/tickets/page.js.nft.json +1 -1
- package/.next/server/app/teams/[teamId]/tickets/page_client-reference-manifest.js +1 -1
- package/.next/server/app/teams/[teamId]/workflows/[workflowId]/page.js +4 -4
- package/.next/server/app/teams/[teamId]/workflows/[workflowId]/page.js.nft.json +1 -1
- package/.next/server/app/teams/[teamId]/workflows/[workflowId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/teams/[teamId]/workflows/page.js +3 -3
- package/.next/server/app/teams/[teamId]/workflows/page.js.nft.json +1 -1
- package/.next/server/app/teams/[teamId]/workflows/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tickets/[ticket]/page.js +1 -1
- 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.js +2 -2
- 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/chunks/[root-of-the-server]__01863a8b._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__01863a8b._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__04f289da._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__04f289da._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__05f5e243._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__05f5e243._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0c4fc3d3._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0c4fc3d3._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__1311d7a3._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1311d7a3._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__1c6c2e43._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1c6c2e43._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__3cfdf0b3._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__3cfdf0b3._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__3fdbc43e._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__3fdbc43e._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__453333f5._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__453333f5._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__47eb3111._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__47eb3111._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__502825d0._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__502825d0._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__50fe6ff8._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__50fe6ff8._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__51198e25._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__51198e25._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__542a081b._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__542a081b._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__5ceff0f3._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__5ceff0f3._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__5ea38a67._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__5ea38a67._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__698cf062._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__698cf062._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__69be1758._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__69be1758._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__69c45937._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__69c45937._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__6f4e90a0._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__6f4e90a0._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__7459129e._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__7459129e._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__7a331e51._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__7a331e51._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__7bf889c1._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__7bf889c1._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__864a08dd._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__864a08dd._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__89605574._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__89605574._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__8e27e9f7._.js +3 -3
- package/.next/server/chunks/[root-of-the-server]__8e27e9f7._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__95ddb81a._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__95ddb81a._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__99b12bcb._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__99b12bcb._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__9d0ea07b._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__9d0ea07b._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__a49c534d._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__a49c534d._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__a74a32d5._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__a74a32d5._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__b002764e._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__b002764e._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__b64936a3._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__b64936a3._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__bbdb6dcb._.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__bbdb6dcb._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__bccfb2c0._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__bccfb2c0._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__d924e5ac._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__d924e5ac._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__e063a986._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__e063a986._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__e40409a2._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__e40409a2._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__e478ef0d._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__e478ef0d._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__fef7183d._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__fef7183d._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__ff69832c._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__ff69832c._.js.map +1 -1
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_1fe98a49.js +1 -1
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_1fe98a49.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__02e6ccaa._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__02e6ccaa._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0df430db._.js +3 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__76f9757d._.js.map → [root-of-the-server]__0df430db._.js.map} +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__162d7d9d._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__162d7d9d._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__17b046ea._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__17b046ea._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__255506f2._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__255506f2._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__3b880807._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__3b880807._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__471bc2e7._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__471bc2e7._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__49281b4c._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__49281b4c._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__4981f370._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__4981f370._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__4c66998a._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__4c66998a._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__8756d76d._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__8756d76d._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__8a588fad._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__8a588fad._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__9a7d79aa._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__9a7d79aa._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__ad4e8478._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__ad4e8478._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__c777e326._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__c777e326._.js.map +1 -0
- package/.next/server/chunks/ssr/_018dfe6b._.js +1 -1
- package/.next/server/chunks/ssr/_018dfe6b._.js.map +1 -1
- package/.next/server/chunks/ssr/{node_modules_next_10fb6ad9._.js → _7f9e89d2._.js} +2 -2
- package/.next/server/chunks/ssr/_7f9e89d2._.js.map +1 -0
- package/.next/server/chunks/ssr/b1a17_app_teams_[teamId]_workflows_[workflowId]_workflows-editor-client_tsx_5e714aa2._.js +1 -1
- package/.next/server/chunks/ssr/b1a17_app_teams_[teamId]_workflows_[workflowId]_workflows-editor-client_tsx_5e714aa2._.js.map +1 -1
- package/.next/server/chunks/ssr/src_59477309._.js +1 -1
- package/.next/server/chunks/ssr/src_59477309._.js.map +1 -1
- 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_teams_[teamId]_workflows_workflows-client_tsx_12742cc9._.js +3 -0
- package/.next/server/chunks/ssr/src_app_teams_[teamId]_workflows_workflows-client_tsx_12742cc9._.js.map +1 -0
- package/.next/server/chunks/ssr/src_lib_errors_ts_f440efeb._.js +3 -0
- package/.next/server/chunks/ssr/src_lib_errors_ts_f440efeb._.js.map +1 -0
- 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/3e0d3a43014c0ad2.css +3 -0
- package/.next/static/chunks/43d0024279c6160e.js +1 -0
- package/.next/static/chunks/{ecdc9465f0e4d954.js → 4d4876ec71727e38.js} +1 -1
- package/.next/static/chunks/4f5e02a609758a0b.js +1 -0
- package/.next/static/chunks/5e3b1d0f61a651bf.js +1 -0
- package/.next/static/chunks/be12a66bd736fad8.js +1 -0
- package/.next/static/chunks/f179280598d329b2.js +1 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/public/images/clawkitchen/home.png +0 -0
- package/public/images/clawkitchen/recipes.png +0 -0
- package/public/images/clawkitchen/runs.png +0 -0
- package/public/images/clawkitchen/team.png +0 -0
- package/public/images/clawkitchen/tickets.png +0 -0
- package/public/images/clawkitchen/workflows.png +0 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1d65fddf._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1d65fddf._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__28f5d174._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__28f5d174._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__450d6006._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__450d6006._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__6bd48d33._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__6bd48d33._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__76f9757d._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__78972f52._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__78972f52._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__9ffebe91._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__9ffebe91._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__a26db919._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__a26db919._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__afaa71fe._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__afaa71fe._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__b577b475._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__b577b475._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__e94ab521._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__e94ab521._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__fb6781d4._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__fb6781d4._.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_10fb6ad9._.js.map +0 -1
- package/.next/server/chunks/ssr/src_e54f24fb._.js +0 -3
- package/.next/server/chunks/ssr/src_e54f24fb._.js.map +0 -1
- package/.next/static/chunks/42b3230688d0834c.js +0 -1
- package/.next/static/chunks/7495459fdf300bf9.js +0 -1
- package/.next/static/chunks/821af975ccc1f8d5.js +0 -1
- package/.next/static/chunks/be874907adf946fd.js +0 -1
- package/.next/static/chunks/e397a21bf5f13650.js +0 -1
- package/.next/static/chunks/f5d0d403c0fecb7f.css +0 -3
- /package/.next/static/{0PWp2TzSmiSf_Pf9YHES- → hUvZJdetkFjI4DzH44gs9}/_buildManifest.js +0 -0
- /package/.next/static/{0PWp2TzSmiSf_Pf9YHES- → hUvZJdetkFjI4DzH44gs9}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{0PWp2TzSmiSf_Pf9YHES- → hUvZJdetkFjI4DzH44gs9}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports=[74621,a=>{"use strict";function b(a){return a instanceof Error?a.message:String(a)}a.s(["errorMessage",()=>b])},16627,a=>{"use strict";var b=a.i(87924),c=a.i(38246),d=a.i(50944),e=a.i(72131),f=a.i(61889),g=a.i(74621),h=a.i(51200);function i({teamId:a,ticket:c,currentOwner:f}){let g=(0,d.useRouter)(),[h,i]=(0,e.useState)([]),[j,k]=(0,e.useState)(f??""),[l,m]=(0,e.useState)(!1),[n,o]=(0,e.useState)(null);(0,e.useEffect)(()=>{let b=!1;return(async()=>{try{let c=a?`/api/teams/${encodeURIComponent(a)}/tickets/assignees`:"/api/tickets/assignees",d=await fetch(c,{cache:"no-store"}),e=await d.json();if(b)return;i(Array.isArray(e.assignees)?e.assignees:[])}catch{if(b)return;i([])}})(),()=>{b=!0}},[]);let p=(0,e.useMemo)(()=>{let a=new Set(h);return f&&a.add(f),Array.from(a).sort()},[h,f]);async function q(){m(!0),o(null);try{let b=a?`/api/teams/${encodeURIComponent(a)}/tickets/assign`:"/api/tickets/assign",d=await fetch(b,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:c,assignee:j})}),e=await d.json();if(!d.ok)return void o(e.error||"Assign failed");g.refresh()}catch{o("Assign failed")}finally{m(!1)}}return(0,b.jsxs)("div",{className:"ck-glass p-4",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-tertiary)]",children:"Assignee"}),(0,b.jsxs)("select",{className:"rounded-md border border-white/10 bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]",value:j,onChange:a=>k(a.target.value),children:[(0,b.jsx)("option",{value:"",disabled:!0,children:"Select…"}),p.map(a=>(0,b.jsx)("option",{value:a,children:a},a))]}),(0,b.jsx)("button",{type:"button",onClick:q,disabled:l||!j||j===(f??""),className:"rounded-md bg-emerald-600 px-3 py-2 text-sm font-semibold text-white hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-50",children:l?"Assigning…":"Assign"}),f?(0,b.jsxs)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:["Currently: ",f]}):null]}),n?(0,b.jsx)("div",{className:"mt-2 text-xs text-red-300",children:n}):null]})}function j(a,b){return b||0==a.trim().length}function k(a){let k=(0,d.useRouter)(),l=(0,f.useToast)(),[m,n]=(0,e.useTransition)(),[o,p]=(0,e.useState)(null),[q,r]=(0,e.useState)(null),s=(0,e.useMemo)(()=>(function(a){let b=function(a){let b=/^## Comments\s*$/gim.exec(a);if(!b)return null;let c=b.index+b[0].length,d=a.slice(c).search(/^##\s+/m),e=-1===d?a.length:c+d;return{start:c,end:e}}(a);if(!b)return[];let c=a.slice(b.start,b.end).replace(/^\s+/,"").split("\n"),d=[],e=null,f=/^- \*\*(.+?)\*\*\s+—\s+(.*)$/;for(let a of c){let b=a.replace(/\r$/,""),c=b.match(f);if(c){e&&d.push({...e,body:e.body.trimEnd()});let a=c[1].trim(),b=c[2].trim(),f=b.indexOf(":"),g=(f>=0?b.slice(0,f):b).trim()||"unknown",h=f>=0?b.slice(f+1).trimStart():"";e={timestamp:a,author:g,body:h?h+"\n":""};continue}e&&(e.body+=b.replace(/^\s{0,2}/,"")+"\n")}return e&&d.push({...e,body:e.body.trimEnd()}),d})(a.markdown),[a.markdown]),[t,u]=(0,e.useState)(""),[v,w]=(0,e.useState)("");async function x(){p(null),await (0,h.fetchJson)(`/api/teams/${encodeURIComponent(a.teamId)}/tickets/move-to-goals`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:a.ticketId})})}async function y(){p(null),await (0,h.fetchJson)(`/api/teams/${encodeURIComponent(a.teamId)}/tickets/delete`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:a.ticketId})})}async function z(){p(null);let b=v.trim();if(!b)throw Error("Comment cannot be empty.");await (0,h.fetchJson)(`/api/teams/${encodeURIComponent(a.teamId)}/tickets/comment`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:a.ticketId,author:t.trim()||void 0,comment:b})}),w(""),l.push({kind:"success",message:"Comment added."}),k.refresh()}return(0,b.jsxs)("div",{className:"space-y-4",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)(c.default,{href:a.backHref??"/tickets",className:"text-sm font-medium hover:underline",children:"← Back"}),(0,b.jsx)("span",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:a.file})]}),o?(0,b.jsx)("div",{className:"ck-glass border border-[color:var(--ck-border-strong)] p-3 text-sm text-[color:var(--ck-text-primary)]",children:o}):null,void 0!==a.currentOwner?(0,b.jsx)(i,{teamId:a.teamId,ticket:a.ticketId,currentOwner:a.currentOwner??null}):null,(0,b.jsx)("div",{className:"ck-glass p-4",children:(0,b.jsxs)("div",{className:"flex flex-wrap items-center justify-end gap-2",children:[(0,b.jsx)("button",{className:"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-text-secondary)] hover:border-[color:var(--ck-border-strong)]",onClick:()=>r({kind:"goals"}),disabled:m,children:"Move to Goals"}),(0,b.jsx)("button",{className:"rounded border border-[color:var(--ck-accent-red)] bg-[color:var(--ck-accent-red-soft)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-accent-red)] hover:bg-[color:var(--ck-accent-red-soft-strong)]",onClick:()=>r({kind:"delete"}),disabled:m,children:"Delete Ticket"})]})}),(0,b.jsxs)("div",{className:"ck-glass p-6",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)("div",{className:"text-sm font-semibold text-[color:var(--ck-text-primary)]",children:"Comments"}),(0,b.jsx)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:s.length})]}),s.length?(0,b.jsx)("div",{className:"mt-3 space-y-3",children:s.map((a,c)=>(0,b.jsxs)("div",{className:"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-black/10 p-3",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-baseline justify-between gap-2",children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-primary)]",children:a.author}),(0,b.jsx)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:a.timestamp})]}),(0,b.jsx)("div",{className:"mt-2 whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-secondary)]",children:a.body})]},`${a.timestamp}-${c}`))}):(0,b.jsx)("div",{className:"mt-3 text-sm text-[color:var(--ck-text-secondary)]",children:"No comments yet."}),(0,b.jsxs)("div",{className:"mt-4 border-t border-[color:var(--ck-border-subtle)] pt-4",children:[(0,b.jsx)("div",{className:"text-sm font-semibold text-[color:var(--ck-text-primary)]",children:"Add comment"}),(0,b.jsxs)("div",{className:"mt-3 grid gap-3",children:[(0,b.jsxs)("div",{className:"grid gap-1",children:[(0,b.jsx)("label",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",htmlFor:"ck-comment-author",children:"Author (optional)"}),(0,b.jsx)("input",{id:"ck-comment-author",value:t,onChange:a=>u(a.target.value),placeholder:"unknown",className:"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]",disabled:m})]}),(0,b.jsxs)("div",{className:"grid gap-1",children:[(0,b.jsx)("label",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",htmlFor:"ck-comment-body",children:"Comment"}),(0,b.jsx)("textarea",{id:"ck-comment-body",value:v,onChange:a=>w(a.target.value),rows:4,className:"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]",disabled:m})]}),(0,b.jsx)("div",{className:"flex items-center justify-end",children:(0,b.jsx)("button",{type:"button","aria-busy":m,className:"rounded-[var(--ck-radius-sm)] bg-[color:var(--ck-accent)] px-3 py-2 text-xs font-semibold text-black transition hover:brightness-110 active:brightness-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--ck-border-strong)] focus-visible:ring-offset-2 focus-visible:ring-offset-black/30 disabled:cursor-not-allowed disabled:border disabled:border-[color:var(--ck-border-subtle)] disabled:bg-[color:var(--ck-bg-glass)] disabled:text-[color:var(--ck-text-tertiary)]",onClick:()=>{n(()=>{z().catch(a=>p((0,g.errorMessage)(a)))})},disabled:j(v,m),children:m?"Posting…":"Post comment"})})]})]})]}),(0,b.jsx)("div",{className:"ck-glass p-6",children:(0,b.jsx)("pre",{className:"whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-primary)]",children:a.markdown})}),q?(0,b.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",children:(0,b.jsxs)("div",{className:"ck-glass w-full max-w-lg rounded-[var(--ck-radius-md)] border border-[color:var(--ck-border-strong)] p-4",children:[(0,b.jsx)("div",{className:"text-sm font-semibold text-[color:var(--ck-text-primary)]",children:"goals"===q.kind?"Move to Goals":"Delete ticket"}),(0,b.jsx)("div",{className:"mt-2 text-sm text-[color:var(--ck-text-secondary)]",children:"goals"===q.kind?(0,b.jsxs)(b.Fragment,{children:["This will move the ticket out of the work lanes into ",(0,b.jsx)("code",{children:"work/goals/"})," so it won’t be picked up by automation."]}):(0,b.jsx)(b.Fragment,{children:"This will permanently remove the ticket markdown file. Assignment stubs (if any) will be archived."})}),(0,b.jsxs)("div",{className:"mt-4 flex items-center justify-end gap-2",children:[(0,b.jsx)("button",{className:"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs text-[color:var(--ck-text-secondary)]",onClick:()=>r(null),disabled:m,children:"Cancel"}),(0,b.jsx)("button",{className:"delete"===q.kind?"rounded bg-[color:var(--ck-accent-red)] px-3 py-1.5 text-xs font-medium text-white":"rounded bg-[color:var(--ck-accent)] px-3 py-1.5 text-xs font-medium text-black",onClick:()=>{let b=q.kind;r(null),n(()=>{("goals"===b?x():y()).then(()=>{l.push({kind:"success",message:"delete"===b?"Ticket deleted.":"Moved to Goals."}),"delete"===b?k.push(a.backHref??"/tickets"):k.refresh()}).catch(a=>p((0,g.errorMessage)(a)))})},disabled:m,children:"Confirm"})]})]})}):null]})}a.s(["TicketDetailClient",()=>k,"isPostCommentDisabled",()=>j],16627)}];
|
|
1
|
+
module.exports=[74621,a=>{"use strict";function b(a){return a instanceof Error?a.message:String(a)}a.s(["errorMessage",()=>b])},16627,a=>{"use strict";var b=a.i(87924),c=a.i(38246),d=a.i(50944),e=a.i(72131),f=a.i(61889),g=a.i(74621),h=a.i(51200);let i=new Set(["lead","dev","qa","tester","agent","system"]);function j({teamId:a,ticket:c,currentOwner:f}){let g=(0,d.useRouter)(),[h,i]=(0,e.useState)([]),[j,k]=(0,e.useState)(f??""),[l,m]=(0,e.useState)(!1),[n,o]=(0,e.useState)(null);(0,e.useEffect)(()=>{let b=!1;return(async()=>{try{let c=a?`/api/teams/${encodeURIComponent(a)}/tickets/assignees`:"/api/tickets/assignees",d=await fetch(c,{cache:"no-store"}),e=await d.json();if(b)return;i(Array.isArray(e.assignees)?e.assignees:[])}catch{if(b)return;i([])}})(),()=>{b=!0}},[]);let p=(0,e.useMemo)(()=>{let a=new Set(h);return f&&a.add(f),Array.from(a).sort()},[h,f]);async function q(){m(!0),o(null);try{let b=a?`/api/teams/${encodeURIComponent(a)}/tickets/assign`:"/api/tickets/assign",d=await fetch(b,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:c,assignee:j})}),e=await d.json();if(!d.ok)return void o(e.error||"Assign failed");g.refresh()}catch{o("Assign failed")}finally{m(!1)}}return(0,b.jsxs)("div",{className:"ck-glass p-4",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-tertiary)]",children:"Assignee"}),(0,b.jsxs)("select",{className:"rounded-md border border-white/10 bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]",value:j,onChange:a=>k(a.target.value),children:[(0,b.jsx)("option",{value:"",disabled:!0,children:"Select…"}),p.map(a=>(0,b.jsx)("option",{value:a,children:a},a))]}),(0,b.jsx)("button",{type:"button",onClick:q,disabled:l||!j||j===(f??""),className:"rounded-md bg-emerald-600 px-3 py-2 text-sm font-semibold text-white hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-50",children:l?"Assigning…":"Assign"}),f?(0,b.jsxs)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:["Currently: ",f]}):null]}),n?(0,b.jsx)("div",{className:"mt-2 text-xs text-red-300",children:n}):null]})}function k(a,b){return b||0==a.trim().length}function l(a){let l=(0,d.useRouter)(),m=(0,f.useToast)(),[n,o]=(0,e.useTransition)(),[p,q]=(0,e.useState)(null),[r,s]=(0,e.useState)(null),t=(0,e.useMemo)(()=>(function(a){let b=function(a){let b=/^## Comments\s*$/gim.exec(a);if(!b)return null;let c=b.index+b[0].length,d=a.slice(c).search(/^##\s+/m),e=-1===d?a.length:c+d;return{start:c,end:e}}(a);if(!b)return[];let c=a.slice(b.start,b.end).replace(/^\s+/,"").split("\n"),d=[],e=null,f=/^- \*\*(.+?)\*\*\s+—\s+(.*)$/;for(let a of c){let b=a.replace(/\r$/,""),c=b.match(f);if(c){e&&d.push({...e,body:e.body.trimEnd()});let a=c[1].trim(),b=c[2].trim(),f=b.indexOf(":"),g=(f>=0?b.slice(0,f):b).trim()||"unknown",h=f>=0?b.slice(f+1).trimStart():"",j=function(a){let b=a?.trim()||"unknown",c=b.match(/^(.*?)\s*\((.*?)\)\s*$/);if(c){let a=c[1].trim()||"unknown",d=c[2].trim();return{name:a,role:d&&d.toLowerCase()!=a.toLowerCase()?d:void 0,raw:b}}for(let a of[" — "," - "," | "]){if(!b.includes(a))continue;let[c,d]=b.split(a).map(a=>a.trim()).filter(Boolean);if(!c||!d)break;let e=i.has(c.toLowerCase()),f=i.has(d.toLowerCase());if(e&&!f)return{name:d,role:c,raw:b};return{name:c,role:d,raw:b}}return{name:b,raw:b}}(g);e={timestamp:a,authorName:j.name,authorRole:j.role,authorRaw:j.raw,body:h?h+"\n":""};continue}e&&(e.body+=b.replace(/^\s{0,2}/,"")+"\n")}return e&&d.push({...e,body:e.body.trimEnd()}),d})(a.markdown),[a.markdown]),[u,v]=(0,e.useState)(""),[w,x]=(0,e.useState)("");async function y(){q(null),await (0,h.fetchJson)(`/api/teams/${encodeURIComponent(a.teamId)}/tickets/move-to-goals`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:a.ticketId})})}async function z(){q(null),await (0,h.fetchJson)(`/api/teams/${encodeURIComponent(a.teamId)}/tickets/delete`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:a.ticketId})})}async function A(b){q(null),await (0,h.fetchJson)(`/api/teams/${encodeURIComponent(a.teamId)}/tickets/move`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:a.ticketId,to:b})})}async function B(){q(null);let b=w.trim();if(!b)throw Error("Comment cannot be empty.");await (0,h.fetchJson)(`/api/teams/${encodeURIComponent(a.teamId)}/tickets/comment`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ticket:a.ticketId,author:u.trim()||void 0,comment:b})}),x(""),m.push({kind:"success",message:"Comment added."}),l.refresh()}return(0,b.jsxs)("div",{className:"space-y-4",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)(c.default,{href:a.backHref??"/tickets",className:"text-sm font-medium hover:underline",children:"← Back"}),(0,b.jsx)("span",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:a.file})]}),p?(0,b.jsx)("div",{className:"ck-glass border border-[color:var(--ck-border-strong)] p-3 text-sm text-[color:var(--ck-text-primary)]",children:p}):null,(0,b.jsxs)("div",{className:"ck-glass p-6",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,b.jsx)("div",{className:"text-sm font-semibold text-[color:var(--ck-text-primary)]",children:"Ticket"}),(0,b.jsxs)("div",{className:"flex flex-wrap items-center justify-end gap-2",children:[(0,b.jsxs)("label",{className:"flex items-center gap-2 text-xs text-[color:var(--ck-text-secondary)]",children:[(0,b.jsx)("span",{children:"Status"}),(0,b.jsxs)("select",{className:"rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-2 py-1 text-xs text-[color:var(--ck-text-primary)]",disabled:n,value:a.stage,onChange:b=>{let c=b.target.value;if(c!==a.stage){if("done"===c&&!window.confirm("Mark this ticket done? This will move the file to work/done and add an audit comment."))return;o(()=>{A(c).then(()=>{m.push({kind:"success",message:`Status updated to ${c}.`}),l.refresh()}).catch(a=>q((0,g.errorMessage)(a)))})}},children:[(0,b.jsx)("option",{value:"backlog",children:"backlog"}),(0,b.jsx)("option",{value:"in-progress",children:"in-progress"}),(0,b.jsx)("option",{value:"testing",children:"testing"}),(0,b.jsx)("option",{value:"done",children:"done"})]})]}),(0,b.jsx)("button",{className:"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-text-secondary)] hover:border-[color:var(--ck-border-strong)]",onClick:()=>s({kind:"goals"}),disabled:n,children:"Move to Goals"}),(0,b.jsx)("button",{className:"rounded border border-[color:var(--ck-accent-red)] bg-[color:var(--ck-accent-red-soft)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-accent-red)] hover:bg-[color:var(--ck-accent-red-soft-strong)]",onClick:()=>s({kind:"delete"}),disabled:n,children:"Delete Ticket"})]})]}),void 0!==a.currentOwner?(0,b.jsx)("div",{className:"mt-4",children:(0,b.jsx)(j,{teamId:a.teamId,ticket:a.ticketId,currentOwner:a.currentOwner??null})}):null,(0,b.jsxs)("div",{className:"mt-6 border-t border-[color:var(--ck-border-subtle)] pt-6",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)("div",{className:"text-sm font-semibold text-[color:var(--ck-text-primary)]",children:"Comments"}),(0,b.jsx)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:t.length})]}),t.length?(0,b.jsx)("div",{className:"mt-3 space-y-3",children:t.map((a,c)=>(0,b.jsxs)("div",{className:"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-black/10 p-3",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-baseline justify-between gap-2",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-baseline gap-2",children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-primary)]",children:a.authorName}),a.authorRole?(0,b.jsx)("div",{className:"rounded border border-[color:var(--ck-border-subtle)] bg-black/10 px-1.5 py-0.5 text-[10px] font-medium text-[color:var(--ck-text-tertiary)]",children:a.authorRole}):null]}),(0,b.jsx)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:a.timestamp})]}),(0,b.jsx)("div",{className:"mt-2 whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-secondary)]",children:a.body})]},`${a.timestamp}-${c}`))}):(0,b.jsx)("div",{className:"mt-3 text-sm text-[color:var(--ck-text-secondary)]",children:"No comments yet."}),(0,b.jsxs)("div",{className:"mt-4 border-t border-[color:var(--ck-border-subtle)] pt-4",children:[(0,b.jsx)("div",{className:"text-sm font-semibold text-[color:var(--ck-text-primary)]",children:"Add comment"}),(0,b.jsxs)("div",{className:"mt-3 grid gap-3",children:[(0,b.jsxs)("div",{className:"grid gap-1",children:[(0,b.jsx)("label",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",htmlFor:"ck-comment-author",children:"Author (optional)"}),(0,b.jsx)("input",{id:"ck-comment-author",value:u,onChange:a=>v(a.target.value),placeholder:"unknown",className:"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]",disabled:n})]}),(0,b.jsxs)("div",{className:"grid gap-1",children:[(0,b.jsx)("label",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",htmlFor:"ck-comment-body",children:"Comment"}),(0,b.jsx)("textarea",{id:"ck-comment-body",value:w,onChange:a=>x(a.target.value),rows:4,className:"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]",disabled:n})]}),(0,b.jsx)("div",{className:"flex items-center justify-end",children:(0,b.jsx)("button",{type:"button","aria-busy":n,className:"rounded-[var(--ck-radius-sm)] bg-[color:var(--ck-accent)] px-3 py-2 text-xs font-semibold text-black transition hover:brightness-110 active:brightness-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--ck-border-strong)] focus-visible:ring-offset-2 focus-visible:ring-offset-black/30 disabled:cursor-not-allowed disabled:border disabled:border-[color:var(--ck-border-subtle)] disabled:bg-[color:var(--ck-bg-glass)] disabled:text-[color:var(--ck-text-tertiary)]",onClick:()=>{o(()=>{B().catch(a=>q((0,g.errorMessage)(a)))})},disabled:k(w,n),children:n?"Posting…":"Post comment"})})]})]})]})]}),(0,b.jsx)("div",{className:"ck-glass p-6",children:(0,b.jsx)("pre",{className:"whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-primary)]",children:a.markdown})}),r?(0,b.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",children:(0,b.jsxs)("div",{className:"ck-glass w-full max-w-lg rounded-[var(--ck-radius-md)] border border-[color:var(--ck-border-strong)] p-4",children:[(0,b.jsx)("div",{className:"text-sm font-semibold text-[color:var(--ck-text-primary)]",children:"goals"===r.kind?"Move to Goals":"Delete ticket"}),(0,b.jsx)("div",{className:"mt-2 text-sm text-[color:var(--ck-text-secondary)]",children:"goals"===r.kind?(0,b.jsxs)(b.Fragment,{children:["This will move the ticket out of the work lanes into ",(0,b.jsx)("code",{children:"work/goals/"})," so it won’t be picked up by automation."]}):(0,b.jsx)(b.Fragment,{children:"This will permanently remove the ticket markdown file. Assignment stubs (if any) will be archived."})}),(0,b.jsxs)("div",{className:"mt-4 flex items-center justify-end gap-2",children:[(0,b.jsx)("button",{className:"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs text-[color:var(--ck-text-secondary)]",onClick:()=>s(null),disabled:n,children:"Cancel"}),(0,b.jsx)("button",{className:"delete"===r.kind?"rounded bg-[color:var(--ck-accent-red)] px-3 py-1.5 text-xs font-medium text-white":"rounded bg-[color:var(--ck-accent)] px-3 py-1.5 text-xs font-medium text-black",onClick:()=>{let b=r.kind;s(null),o(()=>{("goals"===b?y():z()).then(()=>{m.push({kind:"success",message:"delete"===b?"Ticket deleted.":"Moved to Goals."}),"delete"===b?l.push(a.backHref??"/tickets"):l.refresh()}).catch(a=>q((0,g.errorMessage)(a)))})},disabled:n,children:"Confirm"})]})]})}):null]})}a.s(["TicketDetailClient",()=>l,"isPostCommentDisabled",()=>k],16627)}];
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=src_59477309._.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/errors.ts","../../../../src/app/tickets/TicketDetailClient.tsx","../../../../src/lib/ticket-comments.ts","../../../../src/app/tickets/%5Bticket%5D/TicketAssignControl.tsx"],"sourcesContent":["/**\n * Extracts a string message from an unknown error value.\n * Used consistently across API routes and client components.\n */\nexport function errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n","\"use client\";\n\nimport Link from \"next/link\";\nimport { useRouter } from \"next/navigation\";\nimport { useMemo, useState, useTransition } from \"react\";\n\nimport { useToast } from \"@/components/ToastProvider\";\nimport { errorMessage } from \"@/lib/errors\";\nimport { fetchJson } from \"@/lib/fetch-json\";\nimport { parseTicketComments } from \"@/lib/ticket-comments\";\nimport { TicketAssignControl } from \"@/app/tickets/[ticket]/TicketAssignControl\";\n\nexport function isPostCommentDisabled(commentBody: string, isPending: boolean) {\n return isPending || commentBody.trim().length == 0;\n}\n\nexport function TicketDetailClient(props: {\n teamId: string;\n ticketId: string;\n file: string;\n markdown: string;\n backHref?: string;\n currentOwner?: string | null;\n}) {\n const router = useRouter();\n const toast = useToast();\n const [isPending, startTransition] = useTransition();\n const [error, setError] = useState<string | null>(null);\n const [confirm, setConfirm] = useState<null | { kind: \"goals\" | \"delete\" }>(null);\n\n const comments = useMemo(() => parseTicketComments(props.markdown), [props.markdown]);\n\n const [commentAuthor, setCommentAuthor] = useState<string>(\"\");\n const [commentBody, setCommentBody] = useState<string>(\"\");\n\n async function moveToGoals() {\n setError(null);\n await fetchJson(`/api/teams/${encodeURIComponent(props.teamId)}/tickets/move-to-goals`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ticket: props.ticketId }),\n });\n }\n\n async function deleteTicket() {\n setError(null);\n await fetchJson(`/api/teams/${encodeURIComponent(props.teamId)}/tickets/delete`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ticket: props.ticketId }),\n });\n }\n\n async function submitComment() {\n setError(null);\n const body = commentBody.trim();\n if (!body) throw new Error(\"Comment cannot be empty.\");\n\n await fetchJson(`/api/teams/${encodeURIComponent(props.teamId)}/tickets/comment`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n ticket: props.ticketId,\n author: commentAuthor.trim() || undefined,\n comment: body,\n }),\n });\n\n setCommentBody(\"\");\n toast.push({ kind: \"success\", message: \"Comment added.\" });\n router.refresh();\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <Link href={props.backHref ?? \"/tickets\"} className=\"text-sm font-medium hover:underline\">\n ← Back\n </Link>\n <span className=\"text-xs text-[color:var(--ck-text-tertiary)]\">{props.file}</span>\n </div>\n\n {error ? (\n <div className=\"ck-glass border border-[color:var(--ck-border-strong)] p-3 text-sm text-[color:var(--ck-text-primary)]\">\n {error}\n </div>\n ) : null}\n\n {props.currentOwner !== undefined ? (\n <TicketAssignControl teamId={props.teamId} ticket={props.ticketId} currentOwner={props.currentOwner ?? null} />\n ) : null}\n\n <div className=\"ck-glass p-4\">\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n <button\n className=\"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-text-secondary)] hover:border-[color:var(--ck-border-strong)]\"\n onClick={() => setConfirm({ kind: \"goals\" })}\n disabled={isPending}\n >\n Move to Goals\n </button>\n <button\n className=\"rounded border border-[color:var(--ck-accent-red)] bg-[color:var(--ck-accent-red-soft)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-accent-red)] hover:bg-[color:var(--ck-accent-red-soft-strong)]\"\n onClick={() => setConfirm({ kind: \"delete\" })}\n disabled={isPending}\n >\n Delete Ticket\n </button>\n </div>\n </div>\n\n <div className=\"ck-glass p-6\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"text-sm font-semibold text-[color:var(--ck-text-primary)]\">Comments</div>\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">{comments.length}</div>\n </div>\n\n {comments.length ? (\n <div className=\"mt-3 space-y-3\">\n {comments.map((c, idx) => (\n <div\n key={`${c.timestamp}-${idx}`}\n className=\"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-black/10 p-3\"\n >\n <div className=\"flex flex-wrap items-baseline justify-between gap-2\">\n <div className=\"text-xs font-medium text-[color:var(--ck-text-primary)]\">{c.author}</div>\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">{c.timestamp}</div>\n </div>\n <div className=\"mt-2 whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-secondary)]\">\n {c.body}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"mt-3 text-sm text-[color:var(--ck-text-secondary)]\">No comments yet.</div>\n )}\n\n <div className=\"mt-4 border-t border-[color:var(--ck-border-subtle)] pt-4\">\n <div className=\"text-sm font-semibold text-[color:var(--ck-text-primary)]\">Add comment</div>\n\n <div className=\"mt-3 grid gap-3\">\n <div className=\"grid gap-1\">\n <label className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\" htmlFor=\"ck-comment-author\">\n Author (optional)\n </label>\n <input\n id=\"ck-comment-author\"\n value={commentAuthor}\n onChange={(e) => setCommentAuthor(e.target.value)}\n placeholder=\"unknown\"\n className=\"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]\"\n disabled={isPending}\n />\n </div>\n\n <div className=\"grid gap-1\">\n <label className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\" htmlFor=\"ck-comment-body\">\n Comment\n </label>\n <textarea\n id=\"ck-comment-body\"\n value={commentBody}\n onChange={(e) => setCommentBody(e.target.value)}\n rows={4}\n className=\"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]\"\n disabled={isPending}\n />\n </div>\n\n <div className=\"flex items-center justify-end\">\n <button\n type=\"button\"\n aria-busy={isPending}\n className={\n \"rounded-[var(--ck-radius-sm)] bg-[color:var(--ck-accent)] px-3 py-2 text-xs font-semibold text-black transition \" +\n \"hover:brightness-110 active:brightness-95 \" +\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--ck-border-strong)] focus-visible:ring-offset-2 focus-visible:ring-offset-black/30 \" +\n \"disabled:cursor-not-allowed disabled:border disabled:border-[color:var(--ck-border-subtle)] disabled:bg-[color:var(--ck-bg-glass)] disabled:text-[color:var(--ck-text-tertiary)]\"\n }\n onClick={() => {\n startTransition(() => {\n submitComment().catch((e: unknown) => setError(errorMessage(e)));\n });\n }}\n disabled={isPostCommentDisabled(commentBody, isPending)}\n >\n {isPending ? \"Posting…\" : \"Post comment\"}\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"ck-glass p-6\">\n <pre className=\"whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-primary)]\">\n {props.markdown}\n </pre>\n </div>\n\n {confirm ? (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4\">\n <div className=\"ck-glass w-full max-w-lg rounded-[var(--ck-radius-md)] border border-[color:var(--ck-border-strong)] p-4\">\n <div className=\"text-sm font-semibold text-[color:var(--ck-text-primary)]\">\n {confirm.kind === \"goals\" ? \"Move to Goals\" : \"Delete ticket\"}\n </div>\n\n <div className=\"mt-2 text-sm text-[color:var(--ck-text-secondary)]\">\n {confirm.kind === \"goals\" ? (\n <>\n This will move the ticket out of the work lanes into <code>work/goals/</code> so it won’t be picked up by\n automation.\n </>\n ) : (\n <>This will permanently remove the ticket markdown file. Assignment stubs (if any) will be archived.</>\n )}\n </div>\n\n <div className=\"mt-4 flex items-center justify-end gap-2\">\n <button\n className=\"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs text-[color:var(--ck-text-secondary)]\"\n onClick={() => setConfirm(null)}\n disabled={isPending}\n >\n Cancel\n </button>\n <button\n className={\n confirm.kind === \"delete\"\n ? \"rounded bg-[color:var(--ck-accent-red)] px-3 py-1.5 text-xs font-medium text-white\"\n : \"rounded bg-[color:var(--ck-accent)] px-3 py-1.5 text-xs font-medium text-black\"\n }\n onClick={() => {\n const kind = confirm.kind;\n setConfirm(null);\n startTransition(() => {\n const op = kind === \"goals\" ? moveToGoals() : deleteTicket();\n op\n .then(() => {\n toast.push({\n kind: \"success\",\n message: kind === \"delete\" ? \"Ticket deleted.\" : \"Moved to Goals.\",\n });\n if (kind === \"delete\") {\n router.push(props.backHref ?? \"/tickets\");\n } else {\n router.refresh();\n }\n })\n .catch((e: unknown) => setError(errorMessage(e)));\n });\n }}\n disabled={isPending}\n >\n Confirm\n </button>\n </div>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n","export type TicketComment = {\n timestamp: string;\n author: string;\n body: string;\n};\n\nfunction findCommentsSection(md: string): { start: number; end: number } | null {\n const headerRe = /^## Comments\\s*$/gim;\n const m = headerRe.exec(md);\n if (!m) return null;\n\n const start = m.index + m[0].length;\n\n // Find next heading of same or higher level.\n const rest = md.slice(start);\n const nextHeading = rest.search(/^##\\s+/m);\n const end = nextHeading === -1 ? md.length : start + nextHeading;\n return { start, end };\n}\n\nexport function parseTicketComments(md: string): TicketComment[] {\n const section = findCommentsSection(md);\n if (!section) return [];\n\n const body = md.slice(section.start, section.end).replace(/^\\s+/, \"\");\n const lines = body.split(\"\\n\");\n\n const out: TicketComment[] = [];\n let current: TicketComment | null = null;\n\n const header = /^- \\*\\*(.+?)\\*\\*\\s+—\\s+(.*)$/;\n\n for (const rawLine of lines) {\n const line = rawLine.replace(/\\r$/, \"\");\n const m = line.match(header);\n if (m) {\n if (current) out.push({ ...current, body: current.body.trimEnd() });\n const timestamp = m[1].trim();\n const rest = m[2].trim();\n // Support either \"author: first line\" or just \"author\".\n const colonIdx = rest.indexOf(\":\");\n const author = (colonIdx >= 0 ? rest.slice(0, colonIdx) : rest).trim() || \"unknown\";\n const firstBody = colonIdx >= 0 ? rest.slice(colonIdx + 1).trimStart() : \"\";\n current = { timestamp, author, body: firstBody ? firstBody + \"\\n\" : \"\" };\n continue;\n }\n\n if (!current) continue;\n\n // Allow list paragraph indentation, but keep it simple.\n current.body += line.replace(/^\\s{0,2}/, \"\") + \"\\n\";\n }\n\n if (current) out.push({ ...current, body: current.body.trimEnd() });\n return out;\n}\n\nexport function formatTicketCommentMarkdown(args: {\n timestamp: string;\n author: string;\n body: string;\n}): string {\n const body = args.body.trim().replace(/\\r\\n/g, \"\\n\");\n const indented = body\n .split(\"\\n\")\n .map((l) => ` ${l}`)\n .join(\"\\n\");\n\n const author = args.author?.trim() || \"unknown\";\n return `\\n- **${args.timestamp}** — ${author}:\\n${indented}\\n`;\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\n\nexport function TicketAssignControl({\n teamId,\n ticket,\n currentOwner,\n}: {\n teamId?: string | null;\n ticket: string;\n currentOwner: string | null;\n}) {\n const router = useRouter();\n const [assignees, setAssignees] = useState<string[]>([]);\n const [selected, setSelected] = useState<string>(currentOwner ?? \"\");\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const url = teamId\n ? `/api/teams/${encodeURIComponent(teamId)}/tickets/assignees`\n : \"/api/tickets/assignees\";\n const res = await fetch(url, { cache: \"no-store\" });\n const json = (await res.json()) as { assignees?: string[] };\n if (cancelled) return;\n setAssignees(Array.isArray(json.assignees) ? json.assignees : []);\n } catch {\n if (cancelled) return;\n setAssignees([]);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const options = useMemo(() => {\n const base = new Set(assignees);\n if (currentOwner) base.add(currentOwner);\n return Array.from(base).sort();\n }, [assignees, currentOwner]);\n\n async function onAssign() {\n setLoading(true);\n setError(null);\n try {\n const url = teamId\n ? `/api/teams/${encodeURIComponent(teamId)}/tickets/assign`\n : \"/api/tickets/assign\";\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ticket, assignee: selected }),\n });\n\n const json = (await res.json()) as { error?: string };\n if (!res.ok) {\n setError(json.error || \"Assign failed\");\n return;\n }\n\n router.refresh();\n } catch {\n setError(\"Assign failed\");\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className=\"ck-glass p-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"text-xs font-medium text-[color:var(--ck-text-tertiary)]\">Assignee</div>\n <select\n className=\"rounded-md border border-white/10 bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]\"\n value={selected}\n onChange={(e) => setSelected(e.target.value)}\n >\n <option value=\"\" disabled>\n Select…\n </option>\n {options.map((a) => (\n <option key={a} value={a}>\n {a}\n </option>\n ))}\n </select>\n\n <button\n type=\"button\"\n onClick={onAssign}\n disabled={loading || !selected || selected === (currentOwner ?? \"\")}\n className=\"rounded-md bg-emerald-600 px-3 py-2 text-sm font-semibold text-white hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {loading ? \"Assigning…\" : \"Assign\"}\n </button>\n\n {currentOwner ? (\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">Currently: {currentOwner}</div>\n ) : null}\n </div>\n\n {error ? <div className=\"mt-2 text-xs text-red-300\">{error}</div> : null}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/errors.ts","../../../../src/app/tickets/TicketDetailClient.tsx","../../../../src/lib/ticket-comments.ts","../../../../src/app/tickets/%5Bticket%5D/TicketAssignControl.tsx"],"sourcesContent":["/**\n * Extracts a string message from an unknown error value.\n * Used consistently across API routes and client components.\n */\nexport function errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n","\"use client\";\n\nimport Link from \"next/link\";\nimport { useRouter } from \"next/navigation\";\nimport { useMemo, useState, useTransition } from \"react\";\n\nimport { useToast } from \"@/components/ToastProvider\";\nimport { errorMessage } from \"@/lib/errors\";\nimport { fetchJson } from \"@/lib/fetch-json\";\nimport type { TicketStage } from \"@/lib/tickets\";\nimport { parseTicketComments } from \"@/lib/ticket-comments\";\nimport { TicketAssignControl } from \"@/app/tickets/[ticket]/TicketAssignControl\";\n\nexport function isPostCommentDisabled(commentBody: string, isPending: boolean) {\n return isPending || commentBody.trim().length == 0;\n}\n\nexport function TicketDetailClient(props: {\n teamId: string;\n ticketId: string;\n file: string;\n markdown: string;\n stage: TicketStage;\n backHref?: string;\n currentOwner?: string | null;\n}) {\n const router = useRouter();\n const toast = useToast();\n const [isPending, startTransition] = useTransition();\n const [error, setError] = useState<string | null>(null);\n const [confirm, setConfirm] = useState<null | { kind: \"goals\" | \"delete\" }>(null);\n\n const comments = useMemo(() => parseTicketComments(props.markdown), [props.markdown]);\n\n const [commentAuthor, setCommentAuthor] = useState<string>(\"\");\n const [commentBody, setCommentBody] = useState<string>(\"\");\n\n async function moveToGoals() {\n setError(null);\n await fetchJson(`/api/teams/${encodeURIComponent(props.teamId)}/tickets/move-to-goals`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ticket: props.ticketId }),\n });\n }\n\n async function deleteTicket() {\n setError(null);\n await fetchJson(`/api/teams/${encodeURIComponent(props.teamId)}/tickets/delete`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ticket: props.ticketId }),\n });\n }\n\n async function moveTicket(to: TicketStage) {\n setError(null);\n await fetchJson(`/api/teams/${encodeURIComponent(props.teamId)}/tickets/move`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ticket: props.ticketId, to }),\n });\n }\n\n async function submitComment() {\n setError(null);\n const body = commentBody.trim();\n if (!body) throw new Error(\"Comment cannot be empty.\");\n\n await fetchJson(`/api/teams/${encodeURIComponent(props.teamId)}/tickets/comment`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n ticket: props.ticketId,\n author: commentAuthor.trim() || undefined,\n comment: body,\n }),\n });\n\n setCommentBody(\"\");\n toast.push({ kind: \"success\", message: \"Comment added.\" });\n router.refresh();\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <Link href={props.backHref ?? \"/tickets\"} className=\"text-sm font-medium hover:underline\">\n ← Back\n </Link>\n <span className=\"text-xs text-[color:var(--ck-text-tertiary)]\">{props.file}</span>\n </div>\n\n {error ? (\n <div className=\"ck-glass border border-[color:var(--ck-border-strong)] p-3 text-sm text-[color:var(--ck-text-primary)]\">\n {error}\n </div>\n ) : null}\n\n <div className=\"ck-glass p-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"text-sm font-semibold text-[color:var(--ck-text-primary)]\">Ticket</div>\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n <label className=\"flex items-center gap-2 text-xs text-[color:var(--ck-text-secondary)]\">\n <span>Status</span>\n <select\n className=\"rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-2 py-1 text-xs text-[color:var(--ck-text-primary)]\"\n disabled={isPending}\n value={props.stage}\n onChange={(e) => {\n const next = e.target.value as TicketStage;\n if (next === props.stage) return;\n\n if (next === \"done\") {\n const ok = window.confirm(\n \"Mark this ticket done? This will move the file to work/done and add an audit comment.\",\n );\n if (!ok) return;\n }\n\n startTransition(() => {\n moveTicket(next)\n .then(() => {\n toast.push({ kind: \"success\", message: `Status updated to ${next}.` });\n router.refresh();\n })\n .catch((err: unknown) => setError(errorMessage(err)));\n });\n }}\n >\n <option value=\"backlog\">backlog</option>\n <option value=\"in-progress\">in-progress</option>\n <option value=\"testing\">testing</option>\n <option value=\"done\">done</option>\n </select>\n </label>\n\n <button\n className=\"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-text-secondary)] hover:border-[color:var(--ck-border-strong)]\"\n onClick={() => setConfirm({ kind: \"goals\" })}\n disabled={isPending}\n >\n Move to Goals\n </button>\n <button\n className=\"rounded border border-[color:var(--ck-accent-red)] bg-[color:var(--ck-accent-red-soft)] px-3 py-1.5 text-xs font-medium text-[color:var(--ck-accent-red)] hover:bg-[color:var(--ck-accent-red-soft-strong)]\"\n onClick={() => setConfirm({ kind: \"delete\" })}\n disabled={isPending}\n >\n Delete Ticket\n </button>\n </div>\n </div>\n\n {props.currentOwner !== undefined ? (\n <div className=\"mt-4\">\n <TicketAssignControl teamId={props.teamId} ticket={props.ticketId} currentOwner={props.currentOwner ?? null} />\n </div>\n ) : null}\n\n <div className=\"mt-6 border-t border-[color:var(--ck-border-subtle)] pt-6\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"text-sm font-semibold text-[color:var(--ck-text-primary)]\">Comments</div>\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">{comments.length}</div>\n </div>\n\n {comments.length ? (\n <div className=\"mt-3 space-y-3\">\n {comments.map((c, idx) => (\n <div\n key={`${c.timestamp}-${idx}`}\n className=\"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-black/10 p-3\"\n >\n <div className=\"flex flex-wrap items-baseline justify-between gap-2\">\n <div className=\"flex flex-wrap items-baseline gap-2\">\n <div className=\"text-xs font-medium text-[color:var(--ck-text-primary)]\">{c.authorName}</div>\n {c.authorRole ? (\n <div className=\"rounded border border-[color:var(--ck-border-subtle)] bg-black/10 px-1.5 py-0.5 text-[10px] font-medium text-[color:var(--ck-text-tertiary)]\">\n {c.authorRole}\n </div>\n ) : null}\n </div>\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">{c.timestamp}</div>\n </div>\n <div className=\"mt-2 whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-secondary)]\">\n {c.body}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"mt-3 text-sm text-[color:var(--ck-text-secondary)]\">No comments yet.</div>\n )}\n\n <div className=\"mt-4 border-t border-[color:var(--ck-border-subtle)] pt-4\">\n <div className=\"text-sm font-semibold text-[color:var(--ck-text-primary)]\">Add comment</div>\n\n <div className=\"mt-3 grid gap-3\">\n <div className=\"grid gap-1\">\n <label className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\" htmlFor=\"ck-comment-author\">\n Author (optional)\n </label>\n <input\n id=\"ck-comment-author\"\n value={commentAuthor}\n onChange={(e) => setCommentAuthor(e.target.value)}\n placeholder=\"unknown\"\n className=\"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]\"\n disabled={isPending}\n />\n </div>\n\n <div className=\"grid gap-1\">\n <label className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\" htmlFor=\"ck-comment-body\">\n Comment\n </label>\n <textarea\n id=\"ck-comment-body\"\n value={commentBody}\n onChange={(e) => setCommentBody(e.target.value)}\n rows={4}\n className=\"w-full rounded border border-[color:var(--ck-border-subtle)] bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)] outline-none focus:border-[color:var(--ck-border-strong)]\"\n disabled={isPending}\n />\n </div>\n\n <div className=\"flex items-center justify-end\">\n <button\n type=\"button\"\n aria-busy={isPending}\n className={\n \"rounded-[var(--ck-radius-sm)] bg-[color:var(--ck-accent)] px-3 py-2 text-xs font-semibold text-black transition \" +\n \"hover:brightness-110 active:brightness-95 \" +\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--ck-border-strong)] focus-visible:ring-offset-2 focus-visible:ring-offset-black/30 \" +\n \"disabled:cursor-not-allowed disabled:border disabled:border-[color:var(--ck-border-subtle)] disabled:bg-[color:var(--ck-bg-glass)] disabled:text-[color:var(--ck-text-tertiary)]\"\n }\n onClick={() => {\n startTransition(() => {\n submitComment().catch((e: unknown) => setError(errorMessage(e)));\n });\n }}\n disabled={isPostCommentDisabled(commentBody, isPending)}\n >\n {isPending ? \"Posting…\" : \"Post comment\"}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"ck-glass p-6\">\n <pre className=\"whitespace-pre-wrap break-words text-sm leading-6 text-[color:var(--ck-text-primary)]\">\n {props.markdown}\n </pre>\n </div>\n\n {confirm ? (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4\">\n <div className=\"ck-glass w-full max-w-lg rounded-[var(--ck-radius-md)] border border-[color:var(--ck-border-strong)] p-4\">\n <div className=\"text-sm font-semibold text-[color:var(--ck-text-primary)]\">\n {confirm.kind === \"goals\" ? \"Move to Goals\" : \"Delete ticket\"}\n </div>\n\n <div className=\"mt-2 text-sm text-[color:var(--ck-text-secondary)]\">\n {confirm.kind === \"goals\" ? (\n <>\n This will move the ticket out of the work lanes into <code>work/goals/</code> so it won’t be picked up by\n automation.\n </>\n ) : (\n <>This will permanently remove the ticket markdown file. Assignment stubs (if any) will be archived.</>\n )}\n </div>\n\n <div className=\"mt-4 flex items-center justify-end gap-2\">\n <button\n className=\"rounded border border-[color:var(--ck-border-subtle)] px-3 py-1.5 text-xs text-[color:var(--ck-text-secondary)]\"\n onClick={() => setConfirm(null)}\n disabled={isPending}\n >\n Cancel\n </button>\n <button\n className={\n confirm.kind === \"delete\"\n ? \"rounded bg-[color:var(--ck-accent-red)] px-3 py-1.5 text-xs font-medium text-white\"\n : \"rounded bg-[color:var(--ck-accent)] px-3 py-1.5 text-xs font-medium text-black\"\n }\n onClick={() => {\n const kind = confirm.kind;\n setConfirm(null);\n startTransition(() => {\n const op = kind === \"goals\" ? moveToGoals() : deleteTicket();\n op\n .then(() => {\n toast.push({\n kind: \"success\",\n message: kind === \"delete\" ? \"Ticket deleted.\" : \"Moved to Goals.\",\n });\n if (kind === \"delete\") {\n router.push(props.backHref ?? \"/tickets\");\n } else {\n router.refresh();\n }\n })\n .catch((e: unknown) => setError(errorMessage(e)));\n });\n }}\n disabled={isPending}\n >\n Confirm\n </button>\n </div>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n","export type TicketComment = {\n timestamp: string;\n authorName: string;\n authorRole?: string;\n authorRaw: string;\n body: string;\n};\n\nfunction findCommentsSection(md: string): { start: number; end: number } | null {\n const headerRe = /^## Comments\\s*$/gim;\n const m = headerRe.exec(md);\n if (!m) return null;\n\n const start = m.index + m[0].length;\n\n // Find next heading of same or higher level.\n const rest = md.slice(start);\n const nextHeading = rest.search(/^##\\s+/m);\n const end = nextHeading === -1 ? md.length : start + nextHeading;\n return { start, end };\n}\n\nconst ROLE_HINTS = new Set([\"lead\", \"dev\", \"qa\", \"tester\", \"agent\", \"system\"]);\n\nfunction parseAuthor(rawAuthor: string): { name: string; role?: string; raw: string } {\n const raw = rawAuthor?.trim() || \"\";\n const normalized = raw || \"unknown\";\n\n // Pattern: \"RJ (lead)\"\n const paren = normalized.match(/^(.*?)\\s*\\((.*?)\\)\\s*$/);\n if (paren) {\n const name = paren[1].trim() || \"unknown\";\n const role = paren[2].trim();\n return { name, role: role && role.toLowerCase() != name.toLowerCase() ? role : undefined, raw: normalized };\n }\n\n // Pattern: \"lead — RJ\" / \"RJ — lead\" / \"lead | RJ\" / \"RJ | lead\"\n for (const sep of [\" — \", \" - \", \" | \"] as const) {\n if (!normalized.includes(sep)) continue;\n const [a, b] = normalized.split(sep).map((s) => s.trim()).filter(Boolean);\n if (!a || !b) break;\n\n const aIsRole = ROLE_HINTS.has(a.toLowerCase());\n const bIsRole = ROLE_HINTS.has(b.toLowerCase());\n\n if (aIsRole && !bIsRole) return { name: b, role: a, raw: normalized };\n if (bIsRole && !aIsRole) return { name: a, role: b, raw: normalized };\n\n // Otherwise, treat the left as the primary author label and right as secondary detail.\n return { name: a, role: b, raw: normalized };\n }\n\n return { name: normalized, raw: normalized };\n}\n\nexport function parseTicketComments(md: string): TicketComment[] {\n const section = findCommentsSection(md);\n if (!section) return [];\n\n const body = md.slice(section.start, section.end).replace(/^\\s+/, \"\");\n const lines = body.split(\"\\n\");\n\n const out: TicketComment[] = [];\n let current: TicketComment | null = null;\n\n const header = /^- \\*\\*(.+?)\\*\\*\\s+—\\s+(.*)$/;\n\n for (const rawLine of lines) {\n const line = rawLine.replace(/\\r$/, \"\");\n const m = line.match(header);\n if (m) {\n if (current) out.push({ ...current, body: current.body.trimEnd() });\n const timestamp = m[1].trim();\n const rest = m[2].trim();\n // Support either \"author: first line\" or just \"author\".\n const colonIdx = rest.indexOf(\":\");\n const authorRaw = (colonIdx >= 0 ? rest.slice(0, colonIdx) : rest).trim() || \"unknown\";\n const firstBody = colonIdx >= 0 ? rest.slice(colonIdx + 1).trimStart() : \"\";\n const author = parseAuthor(authorRaw);\n current = {\n timestamp,\n authorName: author.name,\n authorRole: author.role,\n authorRaw: author.raw,\n body: firstBody ? firstBody + \"\\n\" : \"\",\n };\n continue;\n }\n\n if (!current) continue;\n\n // Allow list paragraph indentation, but keep it simple.\n current.body += line.replace(/^\\s{0,2}/, \"\") + \"\\n\";\n }\n\n if (current) out.push({ ...current, body: current.body.trimEnd() });\n return out;\n}\n\nexport function formatTicketCommentMarkdown(args: { timestamp: string; author: string; body: string }): string {\n const body = args.body.trim().replace(/\\r\\n/g, \"\\n\");\n const indented = body\n .split(\"\\n\")\n .map((l) => ` ${l}`)\n .join(\"\\n\");\n\n const author = args.author?.trim() || \"unknown\";\n return `\\n- **${args.timestamp}** — ${author}:\\n${indented}\\n`;\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\n\nexport function TicketAssignControl({\n teamId,\n ticket,\n currentOwner,\n}: {\n teamId?: string | null;\n ticket: string;\n currentOwner: string | null;\n}) {\n const router = useRouter();\n const [assignees, setAssignees] = useState<string[]>([]);\n const [selected, setSelected] = useState<string>(currentOwner ?? \"\");\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const url = teamId\n ? `/api/teams/${encodeURIComponent(teamId)}/tickets/assignees`\n : \"/api/tickets/assignees\";\n const res = await fetch(url, { cache: \"no-store\" });\n const json = (await res.json()) as { assignees?: string[] };\n if (cancelled) return;\n setAssignees(Array.isArray(json.assignees) ? json.assignees : []);\n } catch {\n if (cancelled) return;\n setAssignees([]);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const options = useMemo(() => {\n const base = new Set(assignees);\n if (currentOwner) base.add(currentOwner);\n return Array.from(base).sort();\n }, [assignees, currentOwner]);\n\n async function onAssign() {\n setLoading(true);\n setError(null);\n try {\n const url = teamId\n ? `/api/teams/${encodeURIComponent(teamId)}/tickets/assign`\n : \"/api/tickets/assign\";\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ ticket, assignee: selected }),\n });\n\n const json = (await res.json()) as { error?: string };\n if (!res.ok) {\n setError(json.error || \"Assign failed\");\n return;\n }\n\n router.refresh();\n } catch {\n setError(\"Assign failed\");\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className=\"ck-glass p-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"text-xs font-medium text-[color:var(--ck-text-tertiary)]\">Assignee</div>\n <select\n className=\"rounded-md border border-white/10 bg-black/20 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]\"\n value={selected}\n onChange={(e) => setSelected(e.target.value)}\n >\n <option value=\"\" disabled>\n Select…\n </option>\n {options.map((a) => (\n <option key={a} value={a}>\n {a}\n </option>\n ))}\n </select>\n\n <button\n type=\"button\"\n onClick={onAssign}\n disabled={loading || !selected || selected === (currentOwner ?? \"\")}\n className=\"rounded-md bg-emerald-600 px-3 py-2 text-sm font-semibold text-white hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {loading ? \"Assigning…\" : \"Assign\"}\n </button>\n\n {currentOwner ? (\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">Currently: {currentOwner}</div>\n ) : null}\n </div>\n\n {error ? <div className=\"mt-2 text-xs text-red-300\">{error}</div> : null}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports=[48208,a=>{"use strict";var b=a.i(87924),c=a.i(38246),d=a.i(72131),e=a.i(20471);function f({agents:a,teamNames:f}){let
|
|
1
|
+
module.exports=[48208,a=>{"use strict";var b=a.i(87924),c=a.i(38246),d=a.i(72131),e=a.i(20471);function f({agents:a,teamNames:f,appVersion:g}){let h=(0,e.useSelectedTeamId)()||"all",i=(0,d.useMemo)(()=>{let b=new Map;for(let c of a){let a=function(a){if(!a)return null;let b=a.split("/").filter(Boolean).find(a=>a.startsWith("workspace-"))??"";return b&&b.slice(10)||null}(c.workspace)??"personal";if("all"!==h&&a!==h)continue;let d=b.get(a)??[];d.push(c),b.set(a,d)}return Array.from(b.keys()).sort((a,b)=>"personal"===a?1:"personal"===b?-1:a.localeCompare(b)).map(a=>{let c,d,e="personal"===a?"Personal / Unassigned":(c=a.endsWith("-team")?a.slice(0,-5):a,f[a]||f[c]||((d=c.replace(/[-_]+/g," ").replace(/\s+/g," ").trim())?d.split(" ").map(a=>/^(ai|api|cli|ui|ux|sre|qa|devops)$/i.test(a)?a.toUpperCase():a.slice(0,1).toUpperCase()+a.slice(1)).join(" "):c));return{key:a,title:e,subtitle:"personal"===a?null:`workspace-${a}`,agents:(b.get(a)??[]).slice().sort((a,b)=>a.id.localeCompare(b.id)),isTeam:"personal"!==a}})},[a,h,f]);return(0,b.jsxs)("div",{className:"ck-glass w-full p-6 sm:p-8",children:[(0,b.jsxs)("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",children:[(0,b.jsxs)("div",{children:[(0,b.jsxs)("h1",{className:"text-3xl font-semibold tracking-tight",children:["ClawKitchen"," ",(0,b.jsxs)("span",{className:"text-sm align-middle text-[color:var(--ck-text-secondary)]",children:["(",g,"-beta)"]})]}),(0,b.jsx)("p",{className:"mt-2 max-w-prose text-[color:var(--ck-text-secondary)]",children:"Installed agents on this machine, grouped by team workspace when available."})]}),(0,b.jsxs)("div",{className:"flex flex-col items-start gap-2 sm:items-end",children:[(0,b.jsx)(c.default,{href:"/recipes?createCustomTeam=1",className:"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] px-3 py-1.5 text-sm font-medium text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]",children:"Create team"}),(0,b.jsx)(c.default,{href:"/recipes",className:"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]",children:"Recipes"}),(0,b.jsx)(c.default,{href:"/tickets",className:"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]",children:"Tickets"}),(0,b.jsx)(c.default,{href:"/channels",className:"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]",children:"Channels / Bindings"}),(0,b.jsx)(c.default,{href:"/settings",className:"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]",children:"Settings"})]})]}),(0,b.jsx)("div",{className:"mt-8 space-y-8",children:i.map(a=>(0,b.jsxs)("section",{children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-4",children:[(0,b.jsxs)("div",{className:"min-w-0",children:[(0,b.jsx)("h2",{className:"truncate text-lg font-semibold tracking-tight text-[color:var(--ck-text-primary)]",children:a.title}),a.subtitle?(0,b.jsx)("div",{className:"mt-0.5 truncate text-xs text-[color:var(--ck-text-secondary)]",children:a.subtitle}):null]}),a.isTeam?(0,b.jsx)(c.default,{href:`/teams/${encodeURIComponent(a.key)}`,className:"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] px-3 py-1.5 text-sm font-medium text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]",children:"Edit"}):null]}),(0,b.jsx)("div",{className:"mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3",children:a.agents.map(a=>(0,b.jsxs)(c.default,{href:`/agents/${encodeURIComponent(a.id)}`,className:"ck-glass block px-4 py-3 transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]",children:[(0,b.jsx)("div",{className:"truncate font-medium text-[color:var(--ck-text-primary)]",children:a.identityName||a.id}),(0,b.jsxs)("div",{className:"mt-1 text-xs text-[color:var(--ck-text-secondary)]",children:[a.id,a.isDefault?" • default":""]}),a.model?(0,b.jsx)("div",{className:"mt-1 truncate text-xs text-[color:var(--ck-text-tertiary)]",children:a.model}):null]},a.id))})]},a.key))}),(0,b.jsxs)("p",{className:"mt-10 text-xs text-[color:var(--ck-text-tertiary)]",children:["Note: Team detection currently uses the convention ",(0,b.jsx)("code",{children:"~/.openclaw/workspace-<teamId>"}),"."]})]})}a.s(["default",()=>f])}];
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=src_app_HomeClient_tsx_f9f7568d._.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app/HomeClient.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"next/link\";\nimport { useMemo } from \"react\";\nimport { useSelectedTeamId } from \"@/lib/selected-team\";\nimport type { AgentListItem } from \"@/lib/agents\";\n\nfunction inferTeamIdFromWorkspace(workspace: string | undefined) {\n if (!workspace) return null;\n const parts = workspace.split(\"/\").filter(Boolean);\n // Team workspaces are typically ~/.openclaw/workspace-<teamId>/..., so the workspace- segment\n // is not always the last path component.\n const wsPart = parts.find((p) => p.startsWith(\"workspace-\")) ?? \"\";\n if (!wsPart) return null;\n const team = wsPart.slice(\"workspace-\".length);\n return team || null;\n}\n\nfunction normalizeTeamId(teamId: string) {\n // Support legacy workspaces that used a \"-team\" suffix.\n return teamId.endsWith(\"-team\") ? teamId.slice(0, -\"-team\".length) : teamId;\n}\n\nexport default function HomeClient({\n agents,\n teamNames,\n}: {\n agents: AgentListItem[];\n teamNames: Record<string, string>;\n}) {\n\n const selectedTeamId = useSelectedTeamId();\n const teamFilter = selectedTeamId || \"all\";\n\n const grouped = useMemo(() => {\n const groups = new Map<string, AgentListItem[]>();\n\n function titleCaseId(id: string) {\n const s = id\n .replace(/[-_]+/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n if (!s) return id;\n return s\n .split(\" \")\n .map((w) => {\n if (/^(ai|api|cli|ui|ux|sre|qa|devops)$/i.test(w)) return w.toUpperCase();\n return w.slice(0, 1).toUpperCase() + w.slice(1);\n })\n .join(\" \");\n }\n\n function displayNameFor(teamId: string) {\n const normalized = normalizeTeamId(teamId);\n return teamNames[teamId] || teamNames[normalized] || titleCaseId(normalized);\n }\n\n for (const a of agents) {\n const teamId = inferTeamIdFromWorkspace(a.workspace) ?? \"personal\";\n if (teamFilter !== \"all\" && teamId !== teamFilter) continue;\n const key = teamId;\n const list = groups.get(key) ?? [];\n list.push(a);\n groups.set(key, list);\n }\n\n // Stable ordering: teams first (alphabetical), then personal.\n const keys = Array.from(groups.keys()).sort((a, b) => {\n if (a === \"personal\") return 1;\n if (b === \"personal\") return -1;\n return a.localeCompare(b);\n });\n\n return keys.map((k) => {\n const display = k === \"personal\" ? \"Personal / Unassigned\" : displayNameFor(k);\n return {\n key: k,\n title: display,\n // Keep the raw id visible, but deemphasize it.\n subtitle: k === \"personal\" ? null : `workspace-${k}`,\n agents: (groups.get(k) ?? []).slice().sort((a, b) => a.id.localeCompare(b.id)),\n isTeam: k !== \"personal\",\n };\n });\n }, [agents, teamFilter, teamNames]);\n\n return (\n <div className=\"ck-glass w-full p-6 sm:p-8\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h1 className=\"text-3xl font-semibold tracking-tight\">\n Claw Kitchen{\" \"}\n <span className=\"text-sm align-middle text-[color:var(--ck-text-secondary)]\">(v2)</span>\n </h1>\n <p className=\"mt-2 max-w-prose text-[color:var(--ck-text-secondary)]\">\n Installed agents on this machine, grouped by team workspace when available.\n </p>\n </div>\n\n <div className=\"flex flex-col items-start gap-2 sm:items-end\">\n <Link\n href=\"/recipes?createCustomTeam=1\"\n className=\"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] px-3 py-1.5 text-sm font-medium text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]\"\n >\n Create team\n </Link>\n <Link\n href=\"/recipes\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Recipes\n </Link>\n <Link\n href=\"/tickets\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Tickets\n </Link>\n <Link\n href=\"/channels\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Channels / Bindings\n </Link>\n <Link\n href=\"/settings\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Settings\n </Link>\n </div>\n </div>\n\n\n \n\n <div className=\"mt-8 space-y-8\">\n {grouped.map((g) => (\n <section key={g.key}>\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-lg font-semibold tracking-tight text-[color:var(--ck-text-primary)]\">{g.title}</h2>\n {g.subtitle ? (\n <div className=\"mt-0.5 truncate text-xs text-[color:var(--ck-text-secondary)]\">{g.subtitle}</div>\n ) : null}\n </div>\n {g.isTeam ? (\n <Link\n href={`/teams/${encodeURIComponent(g.key)}`}\n className=\"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] px-3 py-1.5 text-sm font-medium text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]\"\n >\n Edit\n </Link>\n ) : null}\n </div>\n\n <div className=\"mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {g.agents.map((a) => (\n <Link\n key={a.id}\n href={`/agents/${encodeURIComponent(a.id)}`}\n className=\"ck-glass block px-4 py-3 transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]\"\n >\n <div className=\"truncate font-medium text-[color:var(--ck-text-primary)]\">\n {a.identityName || a.id}\n </div>\n <div className=\"mt-1 text-xs text-[color:var(--ck-text-secondary)]\">\n {a.id}\n {a.isDefault ? \" • default\" : \"\"}\n </div>\n {a.model ? (\n <div className=\"mt-1 truncate text-xs text-[color:var(--ck-text-tertiary)]\">{a.model}</div>\n ) : null}\n </Link>\n ))}\n </div>\n </section>\n ))}\n </div>\n\n <p className=\"mt-10 text-xs text-[color:var(--ck-text-tertiary)]\">\n Note: Team detection currently uses the convention <code>~/.openclaw/workspace-<teamId></code>.\n </p>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/HomeClient.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"next/link\";\nimport { useMemo } from \"react\";\nimport { useSelectedTeamId } from \"@/lib/selected-team\";\nimport type { AgentListItem } from \"@/lib/agents\";\n\nfunction inferTeamIdFromWorkspace(workspace: string | undefined) {\n if (!workspace) return null;\n const parts = workspace.split(\"/\").filter(Boolean);\n // Team workspaces are typically ~/.openclaw/workspace-<teamId>/..., so the workspace- segment\n // is not always the last path component.\n const wsPart = parts.find((p) => p.startsWith(\"workspace-\")) ?? \"\";\n if (!wsPart) return null;\n const team = wsPart.slice(\"workspace-\".length);\n return team || null;\n}\n\nfunction normalizeTeamId(teamId: string) {\n // Support legacy workspaces that used a \"-team\" suffix.\n return teamId.endsWith(\"-team\") ? teamId.slice(0, -\"-team\".length) : teamId;\n}\n\nexport default function HomeClient({\n agents,\n teamNames,\n appVersion,\n}: {\n agents: AgentListItem[];\n teamNames: Record<string, string>;\n appVersion: string;\n}) {\n const selectedTeamId = useSelectedTeamId();\n const teamFilter = selectedTeamId || \"all\";\n\n const grouped = useMemo(() => {\n const groups = new Map<string, AgentListItem[]>();\n\n function titleCaseId(id: string) {\n const s = id\n .replace(/[-_]+/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n if (!s) return id;\n return s\n .split(\" \")\n .map((w) => {\n if (/^(ai|api|cli|ui|ux|sre|qa|devops)$/i.test(w)) return w.toUpperCase();\n return w.slice(0, 1).toUpperCase() + w.slice(1);\n })\n .join(\" \");\n }\n\n function displayNameFor(teamId: string) {\n const normalized = normalizeTeamId(teamId);\n return teamNames[teamId] || teamNames[normalized] || titleCaseId(normalized);\n }\n\n for (const a of agents) {\n const teamId = inferTeamIdFromWorkspace(a.workspace) ?? \"personal\";\n if (teamFilter !== \"all\" && teamId !== teamFilter) continue;\n const key = teamId;\n const list = groups.get(key) ?? [];\n list.push(a);\n groups.set(key, list);\n }\n\n // Stable ordering: teams first (alphabetical), then personal.\n const keys = Array.from(groups.keys()).sort((a, b) => {\n if (a === \"personal\") return 1;\n if (b === \"personal\") return -1;\n return a.localeCompare(b);\n });\n\n return keys.map((k) => {\n const display = k === \"personal\" ? \"Personal / Unassigned\" : displayNameFor(k);\n return {\n key: k,\n title: display,\n // Keep the raw id visible, but deemphasize it.\n subtitle: k === \"personal\" ? null : `workspace-${k}`,\n agents: (groups.get(k) ?? []).slice().sort((a, b) => a.id.localeCompare(b.id)),\n isTeam: k !== \"personal\",\n };\n });\n }, [agents, teamFilter, teamNames]);\n\n return (\n <div className=\"ck-glass w-full p-6 sm:p-8\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h1 className=\"text-3xl font-semibold tracking-tight\">\n ClawKitchen{\" \"}\n <span className=\"text-sm align-middle text-[color:var(--ck-text-secondary)]\">({appVersion}-beta)</span>\n </h1>\n <p className=\"mt-2 max-w-prose text-[color:var(--ck-text-secondary)]\">\n Installed agents on this machine, grouped by team workspace when available.\n </p>\n </div>\n\n <div className=\"flex flex-col items-start gap-2 sm:items-end\">\n <Link\n href=\"/recipes?createCustomTeam=1\"\n className=\"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] px-3 py-1.5 text-sm font-medium text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]\"\n >\n Create team\n </Link>\n <Link\n href=\"/recipes\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Recipes\n </Link>\n <Link\n href=\"/tickets\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Tickets\n </Link>\n <Link\n href=\"/channels\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Channels / Bindings\n </Link>\n <Link\n href=\"/settings\"\n className=\"text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]\"\n >\n Settings\n </Link>\n </div>\n </div>\n\n\n \n\n <div className=\"mt-8 space-y-8\">\n {grouped.map((g) => (\n <section key={g.key}>\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-lg font-semibold tracking-tight text-[color:var(--ck-text-primary)]\">{g.title}</h2>\n {g.subtitle ? (\n <div className=\"mt-0.5 truncate text-xs text-[color:var(--ck-text-secondary)]\">{g.subtitle}</div>\n ) : null}\n </div>\n {g.isTeam ? (\n <Link\n href={`/teams/${encodeURIComponent(g.key)}`}\n className=\"rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] px-3 py-1.5 text-sm font-medium text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]\"\n >\n Edit\n </Link>\n ) : null}\n </div>\n\n <div className=\"mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {g.agents.map((a) => (\n <Link\n key={a.id}\n href={`/agents/${encodeURIComponent(a.id)}`}\n className=\"ck-glass block px-4 py-3 transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]\"\n >\n <div className=\"truncate font-medium text-[color:var(--ck-text-primary)]\">\n {a.identityName || a.id}\n </div>\n <div className=\"mt-1 text-xs text-[color:var(--ck-text-secondary)]\">\n {a.id}\n {a.isDefault ? \" • default\" : \"\"}\n </div>\n {a.model ? (\n <div className=\"mt-1 truncate text-xs text-[color:var(--ck-text-tertiary)]\">{a.model}</div>\n ) : null}\n </Link>\n ))}\n </div>\n </section>\n ))}\n </div>\n\n <p className=\"mt-10 text-xs text-[color:var(--ck-text-tertiary)]\">\n Note: Team detection currently uses the convention <code>~/.openclaw/workspace-<teamId></code>.\n </p>\n </div>\n );\n}\n"],"names":[],"mappings":"wDAEA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAmBe,SAAS,EAAW,QACjC,CAAM,WACN,CAAS,YACT,CAAU,CAKX,EAEC,IAAM,EADiB,AACJ,CADI,EAAA,EAAA,iBAAA,AAAiB,KACH,MAE/B,EAAU,CAAA,EAAA,EAAA,OAAA,AAAO,EAAC,KACtB,IAAM,EAAS,IAAI,IAsBnB,IAAK,IAAM,KAAK,EAAQ,CACtB,IAAM,EAAS,AApDrB,SAAS,AAAyB,CAA6B,EAC7D,GAAI,CAAC,EAAW,OAAO,KAIvB,IAAM,EAAS,AAHD,EAAU,KAAK,CAAC,KAAK,MAAM,CAAC,SAGrB,IAAI,CAAC,AAAC,GAAM,EAAE,UAAU,CAAC,gBAAkB,UAC3D,AAAL,GACa,CADT,CACgB,GADP,EACY,CAAC,IADN,CAEL,IACjB,EA2C8C,EA7CL,AA6CO,MA7CD,GA6CU,GAAK,WACxD,GAAmB,QAAf,GAAwB,IAAW,EAAY,SAEnD,IAAM,EAAO,EAAO,GAAG,CAAC,IAAQ,EAAE,CAClC,EAAK,IAAI,CAAC,GACV,EAAO,GAAG,CAAC,AAHC,EAGI,EAClB,CASA,OANa,AAMN,MANY,IAAI,CAAC,EAAO,IAAI,IAAI,IAAI,CAAC,CAAC,EAAG,IACpC,AAAV,YAAsB,CAAlB,EAAyB,EACnB,YAAY,CAAlB,EAAyB,CAAC,EACvB,EAAE,aAAa,CAAC,IAGb,GAAG,CAAC,AAAC,YACT,EAAgB,aAAN,EAAmB,yBArB7B,CAqBuD,CAvD1D,EAAO,QAAQ,CAAC,AAkCA,SAlCW,EAAO,KAkCF,AAlCO,CAAC,EAAG,CAAC,GAuD6B,EApBrE,CAAS,CAAC,CAnCsC,CAmC/B,EAAI,CAAS,CAAC,CAnCuB,CAmCZ,GAnCgB,CAmCZ,AAhB/C,EAAI,EACP,OAAO,CAAC,SAAU,KAClB,OAAO,CAAC,OAAQ,KAChB,IAAI,IAEA,EACJ,KAAK,CAAC,KACN,GAAG,CAAC,AAAC,GACA,AAAJ,sCAA0C,IAAI,CAAC,GAAW,CAAP,CAAS,WAAW,GAChE,EAAE,KAAK,CAAC,EAAG,GAAG,WAAW,GAAK,EAAE,KAAK,CAAC,IAE9C,IAAI,CAAC,KAKyD,IAqBjE,MAAO,CACL,IAAK,EACL,MAAO,EAEP,SAAgB,aAAN,EAAmB,KAAO,CAAC,UAAU,EAAE,EAAA,CAAG,CACpD,OAAQ,CAAC,EAAO,GAAG,CAAC,IAAM,EAAE,AAAF,EAAI,KAAK,GAAG,IAAI,CAAC,CAAC,EAAG,IAAM,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,GAC5E,OAAc,aAAN,CACV,CACF,EACF,EAAG,CAAC,EAAQ,EAAY,EAAU,EAElC,MACE,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAI,UAAU,uCACb,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAI,UAAU,8EACb,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,WACC,CAAA,EAAA,EAAA,IAAA,EAAC,KAAA,CAAG,UAAU,kDAAwC,cACxC,IACZ,CAAA,EAAA,EAAA,IAAA,EAAC,OAAA,CAAK,UAAU,uEAA6D,IAAE,EAAW,eAE5F,CAAA,EAAA,EAAA,GAAA,EAAC,IAAA,CAAE,UAAU,kEAAyD,mFAKxE,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAI,UAAU,yDACb,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,OAAI,CAAA,CACH,KAAK,8BACL,UAAU,kRACX,gBAGD,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,OAAI,CAAA,CACH,KAAK,WACL,UAAU,iIACX,YAGD,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,OAAI,CAAA,CACH,KAAK,WACL,UAAU,iIACX,YAGD,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,OAAI,CAAA,CACH,KAAK,YACL,UAAU,iIACX,wBAGD,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,OAAI,CAAA,CACH,KAAK,YACL,UAAU,iIACX,mBASL,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAI,UAAU,0BACZ,EAAQ,GAAG,CAAC,AAAC,GACZ,CAAA,EAAA,EAAA,IAAA,EAAC,UAAA,WACC,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAI,UAAU,oDACb,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAI,UAAU,oBACb,CAAA,EAAA,EAAA,GAAA,EAAC,KAAA,CAAG,UAAU,6FAAqF,EAAE,KAAK,GACzG,EAAE,QAAQ,CACT,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAI,UAAU,yEAAiE,EAAE,QAAQ,GACxF,QAEL,EAAE,MAAM,CACP,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,OAAI,CAAA,CACH,KAAM,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAA,CAAG,CAC3C,UAAU,kRACX,SAGC,QAGN,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAI,UAAU,qEACZ,EAAE,MAAM,CAAC,GAAG,CAAC,AAAC,GACb,CAAA,EAAA,EAAA,IAAA,EAAC,EAAA,OAAI,CAAA,CAEH,KAAM,CAAC,QAAQ,EAAE,mBAAmB,EAAE,EAAE,EAAA,CAAG,CAC3C,UAAU,kGAEV,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAI,UAAU,oEACZ,EAAE,YAAY,EAAI,EAAE,EAAE,GAEzB,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAI,UAAU,+DACZ,EAAE,EAAE,CACJ,EAAE,SAAS,CAAG,aAAe,MAE/B,EAAE,KAAK,CACN,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAI,UAAU,sEAA8D,EAAE,KAAK,GAClF,OAbC,EAAE,EAAE,OArBH,EAAE,GAAG,KA0CvB,CAAA,EAAA,EAAA,IAAA,EAAC,IAAA,CAAE,UAAU,+DAAqD,sDACb,CAAA,EAAA,EAAA,GAAA,EAAC,OAAA,UAAK,mCAA2C,SAI5G"}
|
package/.next/server/chunks/ssr/src_app_teams_[teamId]_workflows_workflows-client_tsx_12742cc9._.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
module.exports=[83856,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(38246),e=a.i(50944),f=a.i(51200),g=a.i(74621);function h(a){return!!a&&"object"==typeof a&&!Array.isArray(a)}function i({teamId:a,llmTaskEnabled:i}){let j=(0,e.useRouter)(),[k,l]=(0,c.useState)([]),[m,n]=(0,c.useState)(!0),[o,p]=(0,c.useState)(!1),[q,r]=(0,c.useState)(""),[s,t]=(0,c.useState)(""),[u,v]=(0,c.useState)({}),[w,x]=(0,c.useState)({}),[y,z]=(0,c.useState)(""),[A,B]=(0,c.useState)(""),[C,D]=(0,c.useState)(null),[E,F]=(0,c.useState)(""),[G,H]=(0,c.useState)(""),[I,J]=(0,c.useState)(!1),K=(0,c.useCallback)(async b=>{let c=!!b?.quiet;r(""),c||n(!0);try{let b=await (0,f.fetchJson)(`/api/teams/workflows?teamId=${encodeURIComponent(a)}`,{cache:"no-store"});if(!b.ok)throw Error("Failed to load workflows");let c=(Array.isArray(b.files)?b.files:[]).map(a=>a.endsWith(".workflow.json")?a.slice(0,-14):null).filter(a=>!!a);l(c.map(a=>({id:a,name:a})))}catch(a){r((0,g.errorMessage)(a))}finally{c||n(!1)}},[a]);async function L(){p(!0);try{await K({quiet:!0})}finally{p(!1)}}async function M(b){if(confirm(`Delete workflow “${b}”? This removes the .workflow.json file from the team workspace.`)){r("");try{let c=await (0,f.fetchJson)(`/api/teams/workflows?teamId=${encodeURIComponent(a)}&id=${encodeURIComponent(b)}`,{method:"DELETE"});if(!c.ok)throw Error(c.error||"Failed to delete workflow");await K({quiet:!0}),s===b&&(t(""),z(""),D(null))}catch(a){r((0,g.errorMessage)(a))}}}async function N(b){x(a=>({...a,[b]:!0})),F("");try{let c=await (0,f.fetchJson)(`/api/teams/workflow-runs?teamId=${encodeURIComponent(a)}&workflowId=${encodeURIComponent(b)}`,{cache:"no-store"});if(!c.ok)throw Error(c.error||"Failed to load runs");let d=Array.isArray(c.runIds)?c.runIds.map(a=>String(a||"").trim()).filter(Boolean):Array.isArray(c.files)?c.files.map(a=>"string"==typeof a&&a.endsWith(".run.json")?a.slice(0,-9):null).filter(a=>!!a):[];v(a=>({...a,[b]:d}))}catch(a){F((0,g.errorMessage)(a)),v(a=>({...a,[b]:[]}))}finally{x(a=>({...a,[b]:!1}))}}async function O(b,c){B(b),z(c),D(null),F(""),H("");try{let d=await (0,f.fetchJson)(`/api/teams/workflow-runs?teamId=${encodeURIComponent(a)}&workflowId=${encodeURIComponent(b)}&runId=${encodeURIComponent(c)}`,{cache:"no-store"});if(!d.ok)throw Error(d.error||"Failed to load run");let e=h(d.run)?d.run:null;if(!e)throw Error("Invalid run format");D({id:String(e.id??c),status:"string"==typeof e.status?e.status:void 0,startedAt:"string"==typeof e.startedAt?e.startedAt:void 0,finishedAt:"string"==typeof e.finishedAt?String(e.finishedAt):void 0,meta:e.meta,memoryUsed:e.memoryUsed,approval:e.approval,raw:e})}catch(a){F((0,g.errorMessage)(a)),D(null)}}async function P(b){if(confirm(`Add workflow from template “${b}”?`)){r("");try{let c=await (0,f.fetchJson)("/api/teams/workflow-templates",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({teamId:a,templateId:b})});if(!c.ok)throw Error(c.error||"Failed to apply template");let d=String(c.workflowId??"").trim();if(!d)throw Error("Template applied but workflowId missing");await K({quiet:!0}),j.push(`/teams/${encodeURIComponent(a)}/workflows/${encodeURIComponent(d)}`)}catch(a){r((0,g.errorMessage)(a))}}}(0,c.useEffect)(()=>{K()},[K]);let Q=(0,c.useMemo)(()=>{if(!C)return[];let a=C.memoryUsed??(h(C.meta)?C.meta.memoryUsed:void 0);return Array.isArray(a)?a.map(a=>h(a)?a:null).filter(Boolean).map(a=>({ts:String(a.ts??"").trim(),author:String(a.author??"").trim(),type:String(a.type??"").trim(),content:String(a.content??"").trim(),source:a.source})).filter(a=>a.ts&&a.author&&a.type&&a.content):[]},[C]);if(m)return(0,b.jsx)("div",{className:"ck-glass p-4",children:"Loading workflows…"});let R=!1===i?(0,b.jsxs)("div",{className:"rounded-[var(--ck-radius-sm)] border border-amber-500/30 bg-amber-500/10 p-4 text-sm",children:[(0,b.jsx)("div",{className:"font-medium text-amber-200",children:"LLM support is not enabled"}),(0,b.jsxs)("div",{className:"mt-1 text-[color:var(--ck-text-secondary)]",children:["Workflow LLM nodes require the optional built-in ",(0,b.jsx)("code",{className:"px-1",children:"llm-task"})," plugin."]}),(0,b.jsxs)("div",{className:"mt-2 text-[color:var(--ck-text-secondary)]",children:["Enable it with: ",(0,b.jsx)("code",{className:"px-1",children:"openclaw plugins enable llm-task"})," then run"," ",(0,b.jsx)("code",{className:"px-1",children:"openclaw gateway restart"}),"."]}),(0,b.jsx)("div",{className:"mt-2 text-xs text-[color:var(--ck-text-tertiary)]",children:"If you’re doing a non-interactive install, keep this command in your setup docs as a fallback."})]}):null;return(0,b.jsxs)("div",{className:"ck-glass p-6",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h2",{className:"text-lg font-semibold",children:"Workflows (file-first)"}),(0,b.jsxs)("p",{className:"mt-1 text-sm text-[color:var(--ck-text-secondary)]",children:["Stored in ",(0,b.jsx)("code",{children:"shared-context/workflows/<id>.workflow.json"})," inside the team workspace."]}),R,(0,b.jsxs)("div",{className:"mt-3 flex flex-wrap items-center justify-start gap-2",children:[(0,b.jsx)("button",{type:"button",onClick:()=>{let b=`new-${Date.now()}`;j.push(`/teams/${encodeURIComponent(a)}/workflows/${encodeURIComponent(b)}?draft=1`)},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)]",children:"Add workflow"}),(0,b.jsx)("button",{type:"button",onClick:()=>void P("marketing-cadence-v1"),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",children:"Add example template"}),(0,b.jsx)("button",{type:"button",onClick:L,disabled:o,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",children:o?"Refreshing…":"Refresh"})]})]}),q?(0,b.jsx)("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",children:q}):null,0===k.length?(0,b.jsx)("p",{className:"mt-4 text-sm text-[color:var(--ck-text-secondary)]",children:"No workflows yet."}):(0,b.jsx)("ul",{className:"mt-4 divide-y divide-white/10 overflow-hidden rounded-[var(--ck-radius-sm)] border border-white/10",children:k.map(c=>{let e=s===c.id,f=u[c.id]??[],i=!!w[c.id];return(0,b.jsxs)("li",{className:"bg-white/5",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3 px-4 py-3",children:[(0,b.jsxs)("button",{type:"button",onClick:async()=>{let a=e?"":c.id;t(a),z(""),D(null),F(""),a&&await N(a)},className:"min-w-0 flex-1 text-left",children:[(0,b.jsx)("div",{className:"truncate text-sm font-medium text-[color:var(--ck-text-primary)]",children:c.name||c.id}),(0,b.jsx)("div",{className:"truncate text-xs text-[color:var(--ck-text-tertiary)]",children:c.id}),(0,b.jsxs)("div",{className:"mt-1 text-[10px] text-[color:var(--ck-text-tertiary)]",children:["Click to ",e?"collapse":"expand"," run details"]})]}),(0,b.jsxs)("div",{className:"flex shrink-0 items-center gap-2",children:[(0,b.jsx)(d.default,{href:`/teams/${encodeURIComponent(a)}/workflows/${encodeURIComponent(c.id)}`,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",children:"Edit"}),(0,b.jsx)("button",{type:"button",onClick:()=>void M(c.id),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)]",children:"Delete"})]})]}),e?(0,b.jsxs)("div",{className:"border-t border-white/10 bg-black/20 px-4 py-3",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",children:"Runs"}),(0,b.jsx)("button",{type:"button",disabled:i,onClick:()=>void N(c.id),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",children:i?"Loading…":"Refresh runs"})]}),E?(0,b.jsx)("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",children:E}):null,(0,b.jsxs)("div",{className:"mt-2 grid grid-cols-1 gap-3 lg:grid-cols-2",children:[(0,b.jsx)("div",{className:"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-2",children:f.length?(0,b.jsx)("div",{className:"space-y-1",children:f.slice(0,8).map(a=>{let d=y===a;return(0,b.jsx)("button",{type:"button",onClick:()=>void O(c.id,a),className:d?"w-full rounded-[var(--ck-radius-sm)] bg-white/10 px-2 py-1 text-left text-[11px] text-[color:var(--ck-text-primary)]":"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",children:(0,b.jsx)("span",{className:"font-mono",children:a})},a)})}):(0,b.jsx)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:"No runs yet."})}),(0,b.jsx)("div",{className:"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-3",children:C?(0,b.jsxs)("div",{className:"space-y-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",children:"Run detail"}),(0,b.jsxs)("div",{className:"mt-1 text-[11px] text-[color:var(--ck-text-tertiary)]",children:[(0,b.jsx)("span",{className:"font-mono",children:C.id}),C.status?(0,b.jsxs)("span",{children:[" • ",C.status]}):null]})]}),(0,b.jsxs)("div",{className:"border-t border-white/10 pt-3",children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",children:"Approval"}),(()=>{let c=C.approval;if(!h(c))return(0,b.jsx)("div",{className:"mt-2 text-xs text-[color:var(--ck-text-tertiary)]",children:"(No approval info recorded.)"});let d=String(c.state??"").trim(),e="string"==typeof c.requestedAt?c.requestedAt:"",f="string"==typeof c.decidedAt?c.decidedAt:"",i="string"==typeof c.decidedBy?c.decidedBy:"",j="string"==typeof c.note?c.note:"",k=h(c.outbound)?c.outbound:null,l="pending"===d||"waiting_for_approval"===C.status;return(0,b.jsxs)("div",{className:"mt-2 space-y-2",children:[(0,b.jsxs)("div",{className:"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-2 text-[11px] text-[color:var(--ck-text-secondary)]",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("span",{className:"font-mono",children:"state"}),": ",(0,b.jsx)("span",{className:"font-mono text-[color:var(--ck-text-primary)]",children:d||"(unknown)"})]}),e?(0,b.jsxs)("div",{children:[(0,b.jsx)("span",{className:"font-mono",children:"requestedAt"}),": ",(0,b.jsx)("span",{className:"font-mono",children:e})]}):null,f?(0,b.jsxs)("div",{children:[(0,b.jsx)("span",{className:"font-mono",children:"decidedAt"}),": ",(0,b.jsx)("span",{className:"font-mono",children:f})]}):null,i?(0,b.jsxs)("div",{children:[(0,b.jsx)("span",{className:"font-mono",children:"decidedBy"}),": ",(0,b.jsx)("span",{className:"font-mono",children:i})]}):null,j?(0,b.jsx)("div",{className:"mt-1 whitespace-pre-wrap text-xs text-[color:var(--ck-text-primary)]",children:j}):null,k?(0,b.jsxs)("div",{className:"mt-2 rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/30 p-2 text-[10px]",children:[(0,b.jsx)("div",{className:"text-[color:var(--ck-text-tertiary)]",children:"Outbound"}),(0,b.jsx)("pre",{className:"mt-1 overflow-auto whitespace-pre-wrap",children:JSON.stringify(k,null,2)})]}):null]}),l?(0,b.jsxs)("div",{className:"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-2",children:[(0,b.jsx)("div",{className:"text-[10px] uppercase tracking-wide text-[color:var(--ck-text-tertiary)]",children:"approval note (optional)"}),(0,b.jsx)("textarea",{value:G,onChange:a=>H(a.target.value),rows:3,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)]",placeholder:"e.g. Ship it / please tweak hook"}),(0,b.jsx)("div",{className:"mt-2 flex flex-wrap gap-2",children:[{action:"approve",label:"Approve"},{action:"request_changes",label:"Request changes"},{action:"cancel",label:"Cancel"}].map(c=>(0,b.jsx)("button",{type:"button",disabled:I,onClick:async()=>{if(A&&y&&confirm(`${c.label} run ${y}?`)){J(!0),F("");try{let b=await fetch("/api/teams/workflow-runs",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({teamId:a,workflowId:A,runId:y,action:c.action,note:G||void 0,decidedBy:"ClawKitchen UI"})}),d=await b.json();if(!b.ok||!d.ok)throw Error(d.error||"Failed to apply approval action");await O(A,y)}catch(a){F((0,g.errorMessage)(a))}finally{J(!1)}}},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",children:c.label},c.action))})]}):null]})})()]}),(0,b.jsxs)("div",{className:"border-t border-white/10 pt-3",children:[(0,b.jsx)("div",{className:"text-xs font-medium text-[color:var(--ck-text-secondary)]",children:"Memory used in this run"}),Q.length?(0,b.jsx)("div",{className:"mt-2 space-y-2",children:Q.slice(0,20).map((a,c)=>(0,b.jsxs)("div",{className:"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-2",children:[(0,b.jsxs)("div",{className:"text-[10px] text-[color:var(--ck-text-tertiary)]",children:[(0,b.jsx)("span",{className:"font-mono",children:a.ts})," • ",(0,b.jsx)("span",{className:"font-mono",children:a.type})," • ",(0,b.jsx)("span",{className:"font-mono",children:a.author})]}),(0,b.jsx)("div",{className:"mt-1 whitespace-pre-wrap text-xs text-[color:var(--ck-text-primary)]",children:a.content}),void 0!==a.source?(0,b.jsx)("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)]",children:JSON.stringify(a.source,null,2)}):null]},`${a.ts}-${c}`))}):(0,b.jsxs)("div",{className:"mt-2 text-xs text-[color:var(--ck-text-tertiary)]",children:["(None recorded yet.)",(0,b.jsxs)("div",{className:"mt-1",children:["Next step: have the workflow runner write an explicit ",(0,b.jsx)("span",{className:"font-mono",children:"memoryUsed[]"})," list into the run file."]})]})]})]}):y?(0,b.jsx)("div",{className:"text-xs text-[color:var(--ck-text-secondary)]",children:"Loading run…"}):(0,b.jsx)("div",{className:"text-xs text-[color:var(--ck-text-tertiary)]",children:"Select a run to see details."})})]})]}):null]},c.id)})})]})}a.s(["default",()=>i])}];
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=src_app_teams_%5BteamId%5D_workflows_workflows-client_tsx_12742cc9._.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/teams/%5BteamId%5D/workflows/workflows-client.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport Link from \"next/link\";\nimport { useRouter } from \"next/navigation\";\nimport { fetchJson } from \"@/lib/fetch-json\";\nimport { errorMessage } from \"@/lib/errors\";\n\ntype RunDetail = {\n id: string;\n status?: string;\n startedAt?: string;\n finishedAt?: string;\n meta?: unknown;\n memoryUsed?: unknown;\n approval?: unknown;\n raw?: Record<string, unknown>;\n};\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return Boolean(v) && typeof v === \"object\" && !Array.isArray(v);\n}\n\nexport default function WorkflowsClient({ teamId, llmTaskEnabled }: { teamId: string; llmTaskEnabled?: boolean }) {\n const router = useRouter();\n const [workflows, setWorkflows] = useState<Array<{ id: string; name?: string }>>([]);\n const [loading, setLoading] = useState(true);\n const [refreshing, setRefreshing] = useState(false);\n const [error, setError] = useState<string>(\"\");\n\n const [expandedWorkflowId, setExpandedWorkflowId] = useState<string>(\"\");\n const [runsByWorkflow, setRunsByWorkflow] = useState<Record<string, string[]>>({});\n const [runsLoading, setRunsLoading] = useState<Record<string, boolean>>({});\n const [selectedRunId, setSelectedRunId] = useState<string>(\"\");\n const [selectedWorkflowId, setSelectedWorkflowId] = useState<string>(\"\");\n const [selectedRun, setSelectedRun] = useState<RunDetail | null>(null);\n const [runError, setRunError] = useState<string>(\"\");\n const [approvalNote, setApprovalNote] = useState<string>(\"\");\n const [approvalBusy, setApprovalBusy] = useState<boolean>(false);\n\n const load = useCallback(\n async (opts?: { quiet?: boolean }) => {\n const quiet = Boolean(opts?.quiet);\n setError(\"\");\n if (!quiet) setLoading(true);\n try {\n const json = await fetchJson<{ ok?: boolean; files?: string[] }>(\n `/api/teams/workflows?teamId=${encodeURIComponent(teamId)}`,\n { cache: \"no-store\" }\n );\n if (!json.ok) throw new Error(\"Failed to load workflows\");\n const files = Array.isArray(json.files) ? json.files : [];\n const ids = files\n .map((f) => (f.endsWith(\".workflow.json\") ? f.slice(0, -\".workflow.json\".length) : null))\n .filter((id): id is string => Boolean(id));\n setWorkflows(ids.map((id) => ({ id, name: id })));\n } catch (e: unknown) {\n setError(errorMessage(e));\n } finally {\n if (!quiet) setLoading(false);\n }\n },\n [teamId]\n );\n\n useEffect(() => {\n void load();\n }, [load]);\n\n async function onRefresh() {\n setRefreshing(true);\n try {\n await load({ quiet: true });\n } finally {\n setRefreshing(false);\n }\n }\n\n async function onDelete(id: string) {\n if (!confirm(`Delete workflow “${id}”? This removes the .workflow.json file from the team workspace.`)) return;\n setError(\"\");\n try {\n const json = await fetchJson<{ ok?: boolean; error?: string }>(\n `/api/teams/workflows?teamId=${encodeURIComponent(teamId)}&id=${encodeURIComponent(id)}`,\n { method: \"DELETE\" }\n );\n if (!json.ok) throw new Error(json.error || \"Failed to delete workflow\");\n await load({ quiet: true });\n if (expandedWorkflowId === id) {\n setExpandedWorkflowId(\"\");\n setSelectedRunId(\"\");\n setSelectedRun(null);\n }\n } catch (e: unknown) {\n setError(errorMessage(e));\n }\n }\n\n async function loadRunsForWorkflow(workflowId: string) {\n setRunsLoading((s) => ({ ...s, [workflowId]: true }));\n setRunError(\"\");\n try {\n const json = await fetchJson<{ ok?: boolean; runIds?: string[]; files?: string[]; error?: string }>(\n `/api/teams/workflow-runs?teamId=${encodeURIComponent(teamId)}&workflowId=${encodeURIComponent(workflowId)}`,\n { cache: \"no-store\" }\n );\n if (!json.ok) throw new Error(json.error || \"Failed to load runs\");\n\n // New API: runIds (directory-per-run layout). Back-compat: files[] of *.run.json.\n const runIds = Array.isArray(json.runIds)\n ? json.runIds.map((x) => String(x || \"\").trim()).filter(Boolean)\n : Array.isArray(json.files)\n ? json.files\n .map((f) => (typeof f === \"string\" && f.endsWith(\".run.json\") ? f.slice(0, -\".run.json\".length) : null))\n .filter((x): x is string => Boolean(x))\n : [];\n\n setRunsByWorkflow((s) => ({ ...s, [workflowId]: runIds }));\n } catch (e: unknown) {\n setRunError(errorMessage(e));\n setRunsByWorkflow((s) => ({ ...s, [workflowId]: [] }));\n } finally {\n setRunsLoading((s) => ({ ...s, [workflowId]: false }));\n }\n }\n\n async function loadRunDetail(workflowId: string, runId: string) {\n setSelectedWorkflowId(workflowId);\n setSelectedRunId(runId);\n setSelectedRun(null);\n setRunError(\"\");\n setApprovalNote(\"\");\n try {\n const json = await fetchJson<{ ok?: boolean; run?: unknown; error?: string }>(\n `/api/teams/workflow-runs?teamId=${encodeURIComponent(teamId)}&workflowId=${encodeURIComponent(workflowId)}&runId=${encodeURIComponent(runId)}`,\n { cache: \"no-store\" }\n );\n if (!json.ok) throw new Error(json.error || \"Failed to load run\");\n const run = isRecord(json.run) ? json.run : null;\n if (!run) throw new Error(\"Invalid run format\");\n setSelectedRun({\n id: String(run.id ?? runId),\n status: typeof run.status === \"string\" ? run.status : undefined,\n startedAt: typeof run.startedAt === \"string\" ? run.startedAt : undefined,\n finishedAt: typeof (run as Record<string, unknown>).finishedAt === \"string\" ? String((run as Record<string, unknown>).finishedAt) : undefined,\n meta: (run as Record<string, unknown>).meta,\n memoryUsed: (run as Record<string, unknown>).memoryUsed,\n approval: (run as Record<string, unknown>).approval,\n raw: run,\n });\n } catch (e: unknown) {\n setRunError(errorMessage(e));\n setSelectedRun(null);\n }\n }\n\n async function onAddTemplate(templateId: string) {\n if (!confirm(`Add workflow from template “${templateId}”?`)) return;\n setError(\"\");\n try {\n const json = await fetchJson<{ ok?: boolean; workflowId?: string; error?: string }>(\"/api/teams/workflow-templates\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ teamId, templateId }),\n });\n if (!json.ok) throw new Error(json.error || \"Failed to apply template\");\n const workflowId = String(json.workflowId ?? \"\").trim();\n if (!workflowId) throw new Error(\"Template applied but workflowId missing\");\n await load({ quiet: true });\n router.push(`/teams/${encodeURIComponent(teamId)}/workflows/${encodeURIComponent(workflowId)}`);\n } catch (e: unknown) {\n setError(errorMessage(e));\n }\n }\n const memoryUsedItems = useMemo(() => {\n const run = selectedRun;\n if (!run) return [] as Array<{ ts: string; author: string; type: string; content: string; source?: unknown }>;\n\n const raw = run.memoryUsed ?? (isRecord(run.meta) ? (run.meta as Record<string, unknown>).memoryUsed : undefined);\n if (!Array.isArray(raw)) return [];\n\n return raw\n .map((x) => (isRecord(x) ? x : null))\n .filter(Boolean)\n .map((o) => ({\n ts: String((o as Record<string, unknown>).ts ?? \"\").trim(),\n author: String((o as Record<string, unknown>).author ?? \"\").trim(),\n type: String((o as Record<string, unknown>).type ?? \"\").trim(),\n content: String((o as Record<string, unknown>).content ?? \"\").trim(),\n source: (o as Record<string, unknown>).source,\n }))\n .filter((it) => it.ts && it.author && it.type && it.content);\n }, [selectedRun]);\n\n if (loading) {\n return <div className=\"ck-glass p-4\">Loading workflows…</div>;\n }\n\n const llmHelp = llmTaskEnabled === false ? (\n <div className=\"rounded-[var(--ck-radius-sm)] border border-amber-500/30 bg-amber-500/10 p-4 text-sm\">\n <div className=\"font-medium text-amber-200\">LLM support is not enabled</div>\n <div className=\"mt-1 text-[color:var(--ck-text-secondary)]\">\n Workflow LLM nodes require the optional built-in <code className=\"px-1\">llm-task</code> plugin.\n </div>\n <div className=\"mt-2 text-[color:var(--ck-text-secondary)]\">\n Enable it with: <code className=\"px-1\">openclaw plugins enable llm-task</code> then run{' '}\n <code className=\"px-1\">openclaw gateway restart</code>.\n </div>\n <div className=\"mt-2 text-xs text-[color:var(--ck-text-tertiary)]\">\n If you’re doing a non-interactive install, keep this command in your setup docs as a fallback.\n </div>\n </div>\n ) : null;\n\n return (\n <div className=\"ck-glass p-6\">\n <div>\n <h2 className=\"text-lg font-semibold\">Workflows (file-first)</h2>\n <p className=\"mt-1 text-sm text-[color:var(--ck-text-secondary)]\">\n Stored in <code>shared-context/workflows/<id>.workflow.json</code> inside the team workspace.\n </p>\n\n {llmHelp}\n\n <div className=\"mt-3 flex flex-wrap items-center justify-start gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n const id = `new-${Date.now()}`;\n router.push(`/teams/${encodeURIComponent(teamId)}/workflows/${encodeURIComponent(id)}?draft=1`);\n }}\n 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)]\"\n >\n Add workflow\n </button>\n\n\n <button\n type=\"button\"\n onClick={() => void onAddTemplate(\"marketing-cadence-v1\")}\n 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\"\n >\n Add example template\n </button>\n\n <button\n type=\"button\"\n onClick={onRefresh}\n disabled={refreshing}\n 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\"\n >\n {refreshing ? \"Refreshing…\" : \"Refresh\"}\n </button>\n </div>\n </div>\n\n {error ? (\n <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\">\n {error}\n </div>\n ) : null}\n\n {workflows.length === 0 ? (\n <p className=\"mt-4 text-sm text-[color:var(--ck-text-secondary)]\">No workflows yet.</p>\n ) : (\n <ul className=\"mt-4 divide-y divide-white/10 overflow-hidden rounded-[var(--ck-radius-sm)] border border-white/10\">\n {workflows.map((w) => {\n const expanded = expandedWorkflowId === w.id;\n const runs = runsByWorkflow[w.id] ?? [];\n const isLoadingRuns = Boolean(runsLoading[w.id]);\n\n return (\n <li key={w.id} className=\"bg-white/5\">\n <div className=\"flex items-center justify-between gap-3 px-4 py-3\">\n <button\n type=\"button\"\n onClick={async () => {\n const next = expanded ? \"\" : w.id;\n setExpandedWorkflowId(next);\n setSelectedRunId(\"\");\n setSelectedRun(null);\n setRunError(\"\");\n if (next) await loadRunsForWorkflow(next);\n }}\n className=\"min-w-0 flex-1 text-left\"\n >\n <div className=\"truncate text-sm font-medium text-[color:var(--ck-text-primary)]\">{w.name || w.id}</div>\n <div className=\"truncate text-xs text-[color:var(--ck-text-tertiary)]\">{w.id}</div>\n <div className=\"mt-1 text-[10px] text-[color:var(--ck-text-tertiary)]\">\n Click to {expanded ? \"collapse\" : \"expand\"} run details\n </div>\n </button>\n\n <div className=\"flex shrink-0 items-center gap-2\">\n <Link\n href={`/teams/${encodeURIComponent(teamId)}/workflows/${encodeURIComponent(w.id)}`}\n 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\"\n >\n Edit\n </Link>\n <button\n type=\"button\"\n onClick={() => void onDelete(w.id)}\n 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)]\"\n >\n Delete\n </button>\n </div>\n </div>\n\n {expanded ? (\n <div className=\"border-t border-white/10 bg-black/20 px-4 py-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\">Runs</div>\n <button\n type=\"button\"\n disabled={isLoadingRuns}\n onClick={() => void loadRunsForWorkflow(w.id)}\n 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\"\n >\n {isLoadingRuns ? \"Loading…\" : \"Refresh runs\"}\n </button>\n </div>\n\n {runError ? (\n <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>\n ) : null}\n\n <div className=\"mt-2 grid grid-cols-1 gap-3 lg:grid-cols-2\">\n <div className=\"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-2\">\n {runs.length ? (\n <div className=\"space-y-1\">\n {runs.slice(0, 8).map((runId) => {\n const selected = selectedRunId === runId;\n return (\n <button\n key={runId}\n type=\"button\"\n onClick={() => void loadRunDetail(w.id, runId)}\n className={\n selected\n ? \"w-full rounded-[var(--ck-radius-sm)] bg-white/10 px-2 py-1 text-left text-[11px] text-[color:var(--ck-text-primary)]\"\n : \"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\"\n }\n >\n <span className=\"font-mono\">{runId}</span>\n </button>\n );\n })}\n </div>\n ) : (\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">No runs yet.</div>\n )}\n </div>\n\n <div className=\"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-3\">\n {selectedRun ? (\n <div className=\"space-y-3\">\n <div>\n <div className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\">Run detail</div>\n <div className=\"mt-1 text-[11px] text-[color:var(--ck-text-tertiary)]\">\n <span className=\"font-mono\">{selectedRun.id}</span>\n {selectedRun.status ? <span> • {selectedRun.status}</span> : null}\n </div>\n </div>\n\n <div className=\"border-t border-white/10 pt-3\">\n <div className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\">Approval</div>\n {(() => {\n const approval = selectedRun.approval;\n if (!isRecord(approval)) {\n return <div className=\"mt-2 text-xs text-[color:var(--ck-text-tertiary)]\">(No approval info recorded.)</div>;\n }\n\n const state = String(approval.state ?? \"\").trim();\n const requestedAt = typeof approval.requestedAt === \"string\" ? approval.requestedAt : \"\";\n const decidedAt = typeof approval.decidedAt === \"string\" ? approval.decidedAt : \"\";\n const decidedBy = typeof approval.decidedBy === \"string\" ? approval.decidedBy : \"\";\n const note = typeof approval.note === \"string\" ? approval.note : \"\";\n const outbound = isRecord(approval.outbound) ? approval.outbound : null;\n\n const canAct = state === \"pending\" || selectedRun.status === \"waiting_for_approval\";\n\n return (\n <div className=\"mt-2 space-y-2\">\n <div className=\"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-2 text-[11px] text-[color:var(--ck-text-secondary)]\">\n <div>\n <span className=\"font-mono\">state</span>: <span className=\"font-mono text-[color:var(--ck-text-primary)]\">{state || \"(unknown)\"}</span>\n </div>\n {requestedAt ? (\n <div>\n <span className=\"font-mono\">requestedAt</span>: <span className=\"font-mono\">{requestedAt}</span>\n </div>\n ) : null}\n {decidedAt ? (\n <div>\n <span className=\"font-mono\">decidedAt</span>: <span className=\"font-mono\">{decidedAt}</span>\n </div>\n ) : null}\n {decidedBy ? (\n <div>\n <span className=\"font-mono\">decidedBy</span>: <span className=\"font-mono\">{decidedBy}</span>\n </div>\n ) : null}\n {note ? (\n <div className=\"mt-1 whitespace-pre-wrap text-xs text-[color:var(--ck-text-primary)]\">{note}</div>\n ) : null}\n {outbound ? (\n <div className=\"mt-2 rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/30 p-2 text-[10px]\">\n <div className=\"text-[color:var(--ck-text-tertiary)]\">Outbound</div>\n <pre className=\"mt-1 overflow-auto whitespace-pre-wrap\">{JSON.stringify(outbound, null, 2)}</pre>\n </div>\n ) : null}\n </div>\n\n {canAct ? (\n <div className=\"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-2\">\n <div className=\"text-[10px] uppercase tracking-wide text-[color:var(--ck-text-tertiary)]\">approval note (optional)</div>\n <textarea\n value={approvalNote}\n onChange={(e) => setApprovalNote(e.target.value)}\n rows={3}\n 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)]\"\n placeholder=\"e.g. Ship it / please tweak hook\"\n />\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {([\n { action: \"approve\", label: \"Approve\" },\n { action: \"request_changes\", label: \"Request changes\" },\n { action: \"cancel\", label: \"Cancel\" },\n ] as const).map((btn) => (\n <button\n key={btn.action}\n type=\"button\"\n disabled={approvalBusy}\n onClick={async () => {\n if (!selectedWorkflowId || !selectedRunId) return;\n if (!confirm(`${btn.label} run ${selectedRunId}?`)) return;\n setApprovalBusy(true);\n setRunError(\"\");\n try {\n const res = await fetch(\"/api/teams/workflow-runs\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n teamId,\n workflowId: selectedWorkflowId,\n runId: selectedRunId,\n action: btn.action,\n note: approvalNote || undefined,\n decidedBy: \"ClawKitchen UI\",\n }),\n });\n const json = await res.json();\n if (!res.ok || !json.ok) throw new Error(json.error || \"Failed to apply approval action\");\n await loadRunDetail(selectedWorkflowId, selectedRunId);\n } catch (e: unknown) {\n setRunError(errorMessage(e));\n } finally {\n setApprovalBusy(false);\n }\n }}\n 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\"\n >\n {btn.label}\n </button>\n ))}\n </div>\n </div>\n ) : null}\n </div>\n );\n })()}\n </div>\n\n <div className=\"border-t border-white/10 pt-3\">\n <div className=\"text-xs font-medium text-[color:var(--ck-text-secondary)]\">Memory used in this run</div>\n {memoryUsedItems.length ? (\n <div className=\"mt-2 space-y-2\">\n {memoryUsedItems.slice(0, 20).map((m, idx) => (\n <div key={`${m.ts}-${idx}`} className=\"rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-2\">\n <div className=\"text-[10px] text-[color:var(--ck-text-tertiary)]\">\n <span className=\"font-mono\">{m.ts}</span> • <span className=\"font-mono\">{m.type}</span> • <span className=\"font-mono\">{m.author}</span>\n </div>\n <div className=\"mt-1 whitespace-pre-wrap text-xs text-[color:var(--ck-text-primary)]\">{m.content}</div>\n {m.source !== undefined ? (\n <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)]\">\n {JSON.stringify(m.source, null, 2)}\n </pre>\n ) : null}\n </div>\n ))}\n </div>\n ) : (\n <div className=\"mt-2 text-xs text-[color:var(--ck-text-tertiary)]\">\n (None recorded yet.)\n <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>\n </div>\n )}\n </div>\n </div>\n ) : selectedRunId ? (\n <div className=\"text-xs text-[color:var(--ck-text-secondary)]\">Loading run…</div>\n ) : (\n <div className=\"text-xs text-[color:var(--ck-text-tertiary)]\">Select a run to see details.</div>\n )}\n </div>\n </div>\n </div>\n ) : null}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/errors.ts"],"sourcesContent":["/**\n * Extracts a string message from an unknown error value.\n * Used consistently across API routes and client components.\n */\nexport function errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n"],"names":[],"mappings":"uCAIO,SAAS,EAAa,CAAU,EACrC,OAAO,aAAa,MAAQ,EAAE,OAAO,CAAG,OAAO,EACjD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--0PWp2TzSmiSf_Pf9YHES_--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/f5d0d403c0fecb7f.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/93719e85369dd453.js"/><script src="/_next/static/chunks/68a088aa49e6124a.js" async=""></script><script src="/_next/static/chunks/f2f58a7e93290fbb.js" async=""></script><script src="/_next/static/chunks/0edab8a24d59a626.js" async=""></script><script src="/_next/static/chunks/turbopack-0236a74c4f471967.js" async=""></script><script src="/_next/static/chunks/ecdc9465f0e4d954.js" async=""></script><script src="/_next/static/chunks/ff1a16fafef87110.js" async=""></script><script src="/_next/static/chunks/d2be314c3ece3fbe.js" async=""></script><script src="/_next/static/chunks/c84580993f22c17a.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>Claw Kitchen</title><meta name="description" content="Local-first UI for authoring ClawRecipes recipes and scaffolding agents/teams."/><link rel="manifest" href="/manifest.webmanifest"/><link rel="icon" href="/favicon.ico?favicon.0b3bf435.ico" sizes="256x256" type="image/x-icon"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script>(function(){try{var t=localStorage.getItem('ck-theme');var theme=(t==='light')?'light':'dark';document.documentElement.dataset.theme=theme;}catch(e){document.documentElement.dataset.theme='dark';}})();</script><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased"><div hidden=""><!--$--><!--/$--></div><div class="flex h-dvh w-dvw overflow-hidden"><aside class="flex shrink-0 flex-col border-r border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] backdrop-blur-[var(--ck-glass-blur)] w-72"><div class="flex h-14 items-center justify-between gap-2 border-b border-[color:var(--ck-border-subtle)] px-3"><a class="text-sm font-semibold tracking-tight" title="Home" href="/">Claw Kitchen</a><button class="rounded-[var(--ck-radius-sm)] px-2 py-1 text-sm text-[color:var(--ck-text-secondary)] hover:bg-white/5 hover:text-[color:var(--ck-text-primary)]" title="Collapse">«</button></div><div class="border-b border-[color:var(--ck-border-subtle)] p-2"><div class="flex flex-col gap-1"><div class="px-2 pt-1 text-xs font-semibold uppercase tracking-wide text-[color:var(--ck-text-tertiary)]">Team</div><select class="w-full rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 px-2 py-2 text-sm text-[color:var(--ck-text-primary)]"><option value="" selected="">All teams</option></select></div></div><nav class="min-h-0 flex-1 overflow-auto p-2"><div class="mt-2 px-2 pb-2 pt-2"></div><a title="Agents" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 11l9-8 9 8"></path><path d="M5 10v10h14V10"></path></svg></span></span><span>Agents</span></a><a title="Recipes" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/recipes"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 4h12v16H6z"></path><path d="M9 8h6"></path><path d="M9 12h6"></path></svg></span></span><span>Recipes</span></a><a title="Tickets" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/tickets"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16v4a2 2 0 0 1 0 4v4H4v-4a2 2 0 0 0 0-4z"></path></svg></span></span><span>Tickets</span></a><a title="Channels" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/channels"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16"></path><path d="M4 12h16"></path><path d="M4 18h16"></path><path d="M7 9h0"></path></svg></span></span><span>Channels</span></a><a title="Goals" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/goals"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5l3 3"></path></svg></span></span><span>Goals</span></a><a title="Cron jobs" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/cron-jobs"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5"></path></svg></span></span><span>Cron jobs</span></a><a title="Runs" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/runs"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19h16"></path><path d="M6 16l4-4 3 3 5-7"></path><circle cx="10" cy="12" r="1"></circle><circle cx="13" cy="15" r="1"></circle><circle cx="18" cy="8" r="1"></circle></svg></span></span><span>Runs</span></a><a title="Settings" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/settings"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z"></path><path d="M19.4 15a7.9 7.9 0 0 0 .1-1l2-1.5-2-3.5-2.4.5a7.8 7.8 0 0 0-1.7-1L13.5 3h-4L8.6 6.5a7.8 7.8 0 0 0-1.7 1L4.5 7l-2 3.5 2 1.5a7.9 7.9 0 0 0 .1 1l-2 1.5 2 3.5 2.4-.5a7.8 7.8 0 0 0 1.7 1L10.5 21h4l.9-3.5a7.8 7.8 0 0 0 1.7-1l2.4.5 2-3.5-2-1.5Z"></path></svg></span></span><span>Settings</span></a></nav><div class="flex items-center justify-between gap-2 border-t border-[color:var(--ck-border-subtle)] p-2"><a href="https://github.com/JIGGAI/ClawRecipes/tree/main/docs" target="_blank" rel="noreferrer" class="rounded-[var(--ck-radius-sm)] px-3 py-2 text-sm font-medium text-[color:var(--ck-text-secondary)] hover:bg-white/5 hover:text-[color:var(--ck-text-primary)]" title="Docs">Docs</a><button type="button" class="grid h-9 w-9 place-items-center rounded-full border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]" aria-label="Switch to light mode" title="Switch to light mode"><span class="sr-only">Switch to light mode</span><svg class="h-4.5 w-4.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 14.2A7.8 7.8 0 0 1 9.8 3a7 7 0 1 0 11.2 11.2Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"></path></svg></button></div></aside><div class="min-w-0 flex-1"><main class="h-full overflow-auto p-4 md:p-6"><div class="mx-auto max-w-2xl px-6 py-12"><h1 class="text-xl font-semibold">Page not found</h1><p class="mt-2 text-sm text-[color:var(--ck-text-secondary)]">The page you requested does not exist.</p></div><!--$--><!--/$--></main></div></div><div aria-live="assertive" class="pointer-events-none fixed inset-0 z-[100] flex items-end px-4 py-6 sm:p-6"><div class="flex w-full flex-col items-start space-y-4"></div></div><script src="/_next/static/chunks/93719e85369dd453.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[49830,[\"/_next/static/chunks/ecdc9465f0e4d954.js\"],\"AppShell\"]\n3:I[39756,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"default\"]\n4:I[37457,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"default\"]\n5:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"OutletBoundary\"]\n6:\"$Sreact.suspense\"\n8:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"ViewportBoundary\"]\na:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"MetadataBoundary\"]\nc:I[63491,[\"/_next/static/chunks/c84580993f22c17a.js\"],\"default\"]\n:HL[\"/_next/static/chunks/f5d0d403c0fecb7f.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"0PWp2TzSmiSf_Pf9YHES-\",\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/f5d0d403c0fecb7f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/ecdc9465f0e4d954.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"script\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"(function(){try{var t=localStorage.getItem('ck-theme');var theme=(t==='light')?'light':'dark';document.documentElement.dataset.theme=theme;}catch(e){document.documentElement.dataset.theme='dark';}})();\"}}]}],[\"$\",\"body\",null,{\"suppressHydrationWarning\":true,\"className\":\"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased\",\"children\":[\"$\",\"$L2\",null,{\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-2xl px-6 py-12\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-xl font-semibold\",\"children\":\"Page not found\"}],[\"$\",\"p\",null,{\"className\":\"mt-2 text-sm text-[color:var(--ck-text-secondary)]\",\"children\":\"The page you requested does not exist.\"}]]}],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-2xl px-6 py-12\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-xl font-semibold\",\"children\":\"Page not found\"}],[\"$\",\"p\",null,{\"className\":\"mt-2 text-sm text-[color:var(--ck-text-secondary)]\",\"children\":\"The page you requested does not exist.\"}]]}],null,[\"$\",\"$L5\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@7\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"d:I[27201,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"IconMark\"]\n7:null\nb:[[\"$\",\"title\",\"0\",{\"children\":\"Claw Kitchen\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Local-first UI for authoring ClawRecipes recipes and scaffolding agents/teams.\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/manifest.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0b3bf435.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"7\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$Ld\",\"8\",{}]]\n"])</script></body></html>
|
|
1
|
+
<!DOCTYPE html><!--hUvZJdetkFjI4DzH44gs9--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/3e0d3a43014c0ad2.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/93719e85369dd453.js"/><script src="/_next/static/chunks/68a088aa49e6124a.js" async=""></script><script src="/_next/static/chunks/f2f58a7e93290fbb.js" async=""></script><script src="/_next/static/chunks/0edab8a24d59a626.js" async=""></script><script src="/_next/static/chunks/turbopack-0236a74c4f471967.js" async=""></script><script src="/_next/static/chunks/4d4876ec71727e38.js" async=""></script><script src="/_next/static/chunks/ff1a16fafef87110.js" async=""></script><script src="/_next/static/chunks/d2be314c3ece3fbe.js" async=""></script><script src="/_next/static/chunks/c84580993f22c17a.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>ClawKitchen (0.3.11-beta)</title><meta name="description" content="Local-first UI for authoring ClawRecipes recipes and scaffolding agents/teams."/><link rel="manifest" href="/manifest.webmanifest"/><link rel="icon" href="/favicon.ico?favicon.0b3bf435.ico" sizes="256x256" type="image/x-icon"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script>(function(){try{var t=localStorage.getItem('ck-theme');var theme=(t==='light')?'light':'dark';document.documentElement.dataset.theme=theme;}catch(e){document.documentElement.dataset.theme='dark';}})();</script><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased"><div hidden=""><!--$--><!--/$--></div><div class="flex h-dvh w-dvw overflow-hidden"><aside class="flex shrink-0 flex-col border-r border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] backdrop-blur-[var(--ck-glass-blur)] w-72"><div class="flex h-14 items-center justify-between gap-2 border-b border-[color:var(--ck-border-subtle)] px-3"><a class="text-sm font-semibold tracking-tight" title="Home" href="/">Claw Kitchen</a><button class="rounded-[var(--ck-radius-sm)] px-2 py-1 text-sm text-[color:var(--ck-text-secondary)] hover:bg-white/5 hover:text-[color:var(--ck-text-primary)]" title="Collapse">«</button></div><div class="border-b border-[color:var(--ck-border-subtle)] p-2"><div class="flex flex-col gap-1"><div class="px-2 pt-1 text-xs font-semibold uppercase tracking-wide text-[color:var(--ck-text-tertiary)]">Team</div><select class="w-full rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 px-2 py-2 text-sm text-[color:var(--ck-text-primary)]"><option value="" selected="">All teams</option></select></div></div><nav class="min-h-0 flex-1 overflow-auto p-2"><div class="mt-2 px-2 pb-2 pt-2"></div><a title="Agents" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 11l9-8 9 8"></path><path d="M5 10v10h14V10"></path></svg></span></span><span>Agents</span></a><a title="Recipes" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/recipes"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 4h12v16H6z"></path><path d="M9 8h6"></path><path d="M9 12h6"></path></svg></span></span><span>Recipes</span></a><a title="Tickets" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/tickets"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16v4a2 2 0 0 1 0 4v4H4v-4a2 2 0 0 0 0-4z"></path></svg></span></span><span>Tickets</span></a><a title="Channels" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/channels"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16"></path><path d="M4 12h16"></path><path d="M4 18h16"></path><path d="M7 9h0"></path></svg></span></span><span>Channels</span></a><a title="Goals" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/goals"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5l3 3"></path></svg></span></span><span>Goals</span></a><a title="Cron jobs" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/cron-jobs"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5"></path></svg></span></span><span>Cron jobs</span></a><a title="Runs" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/runs"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19h16"></path><path d="M6 16l4-4 3 3 5-7"></path><circle cx="10" cy="12" r="1"></circle><circle cx="13" cy="15" r="1"></circle><circle cx="18" cy="8" r="1"></circle></svg></span></span><span>Runs</span></a><a title="Settings" class="flex items-center rounded-[var(--ck-radius-sm)] text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:bg-white/5 hover:text-[color:var(--ck-text-primary)] gap-4 px-4 py-3" href="/settings"><span aria-hidden="true"><span class="grid size-7 place-items-center text-[color:var(--ck-text-secondary)]" aria-hidden="true"><svg viewBox="0 0 24 24" class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z"></path><path d="M19.4 15a7.9 7.9 0 0 0 .1-1l2-1.5-2-3.5-2.4.5a7.8 7.8 0 0 0-1.7-1L13.5 3h-4L8.6 6.5a7.8 7.8 0 0 0-1.7 1L4.5 7l-2 3.5 2 1.5a7.9 7.9 0 0 0 .1 1l-2 1.5 2 3.5 2.4-.5a7.8 7.8 0 0 0 1.7 1L10.5 21h4l.9-3.5a7.8 7.8 0 0 0 1.7-1l2.4.5 2-3.5-2-1.5Z"></path></svg></span></span><span>Settings</span></a></nav><div class="flex items-center justify-between gap-2 border-t border-[color:var(--ck-border-subtle)] p-2"><a href="https://github.com/JIGGAI/ClawRecipes/tree/main/docs" target="_blank" rel="noreferrer" class="rounded-[var(--ck-radius-sm)] px-3 py-2 text-sm font-medium text-[color:var(--ck-text-secondary)] hover:bg-white/5 hover:text-[color:var(--ck-text-primary)]" title="Docs">Docs</a><button type="button" class="grid h-9 w-9 place-items-center rounded-full border border-[color:var(--ck-border-subtle)] bg-[color:var(--ck-bg-glass)] text-[color:var(--ck-text-primary)] shadow-[var(--ck-shadow-1)] transition-colors hover:bg-[color:var(--ck-bg-glass-strong)]" aria-label="Switch to light mode" title="Switch to light mode"><span class="sr-only">Switch to light mode</span><svg class="h-4.5 w-4.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 14.2A7.8 7.8 0 0 1 9.8 3a7 7 0 1 0 11.2 11.2Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"></path></svg></button></div></aside><div class="min-w-0 flex-1"><main class="h-full overflow-auto p-4 md:p-6"><div class="mx-auto max-w-2xl px-6 py-12"><h1 class="text-xl font-semibold">Page not found</h1><p class="mt-2 text-sm text-[color:var(--ck-text-secondary)]">The page you requested does not exist.</p></div><!--$--><!--/$--></main></div></div><div aria-live="assertive" class="pointer-events-none fixed inset-0 z-[100] flex items-end px-4 py-6 sm:p-6"><div class="flex w-full flex-col items-start space-y-4"></div></div><script src="/_next/static/chunks/93719e85369dd453.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[49830,[\"/_next/static/chunks/4d4876ec71727e38.js\"],\"AppShell\"]\n3:I[39756,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"default\"]\n4:I[37457,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"default\"]\n5:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"OutletBoundary\"]\n6:\"$Sreact.suspense\"\n8:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"ViewportBoundary\"]\na:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"MetadataBoundary\"]\nc:I[63491,[\"/_next/static/chunks/c84580993f22c17a.js\"],\"default\"]\n:HL[\"/_next/static/chunks/3e0d3a43014c0ad2.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"hUvZJdetkFjI4DzH44gs9\",\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/3e0d3a43014c0ad2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/4d4876ec71727e38.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"script\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"(function(){try{var t=localStorage.getItem('ck-theme');var theme=(t==='light')?'light':'dark';document.documentElement.dataset.theme=theme;}catch(e){document.documentElement.dataset.theme='dark';}})();\"}}]}],[\"$\",\"body\",null,{\"suppressHydrationWarning\":true,\"className\":\"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable antialiased\",\"children\":[\"$\",\"$L2\",null,{\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-2xl px-6 py-12\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-xl font-semibold\",\"children\":\"Page not found\"}],[\"$\",\"p\",null,{\"className\":\"mt-2 text-sm text-[color:var(--ck-text-secondary)]\",\"children\":\"The page you requested does not exist.\"}]]}],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-2xl px-6 py-12\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-xl font-semibold\",\"children\":\"Page not found\"}],[\"$\",\"p\",null,{\"className\":\"mt-2 text-sm text-[color:var(--ck-text-secondary)]\",\"children\":\"The page you requested does not exist.\"}]]}],null,[\"$\",\"$L5\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@7\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"d:I[27201,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"IconMark\"]\n7:null\nb:[[\"$\",\"title\",\"0\",{\"children\":\"ClawKitchen (0.3.11-beta)\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Local-first UI for authoring ClawRecipes recipes and scaffolding agents/teams.\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/manifest.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0b3bf435.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"7\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$Ld\",\"8\",{}]]\n"])</script></body></html>
|