@jiggai/kitchen 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +2 -2
- 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.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- 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 +1 -1
- package/.next/server/app/channels.html +2 -2
- package/.next/server/app/channels.rsc +1 -1
- package/.next/server/app/channels.segments/_full.segment.rsc +1 -1
- package/.next/server/app/channels.segments/_head.segment.rsc +1 -1
- package/.next/server/app/channels.segments/_index.segment.rsc +1 -1
- package/.next/server/app/channels.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/channels.segments/channels/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/channels.segments/channels.segment.rsc +1 -1
- package/.next/server/app/cron-jobs.html +1 -1
- package/.next/server/app/cron-jobs.rsc +1 -1
- package/.next/server/app/cron-jobs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/cron-jobs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/cron-jobs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/cron-jobs.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/cron-jobs.segments/cron-jobs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/cron-jobs.segments/cron-jobs.segment.rsc +1 -1
- package/.next/server/app/goals/new.html +2 -2
- package/.next/server/app/goals/new.rsc +1 -1
- package/.next/server/app/goals/new.segments/_full.segment.rsc +1 -1
- package/.next/server/app/goals/new.segments/_head.segment.rsc +1 -1
- package/.next/server/app/goals/new.segments/_index.segment.rsc +1 -1
- package/.next/server/app/goals/new.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/goals/new.segments/goals/new/__PAGE__.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/goals.rsc +1 -1
- package/.next/server/app/goals.segments/_full.segment.rsc +1 -1
- package/.next/server/app/goals.segments/_head.segment.rsc +1 -1
- package/.next/server/app/goals.segments/_index.segment.rsc +1 -1
- package/.next/server/app/goals.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/goals.segments/goals/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/goals.segments/goals.segment.rsc +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +1 -1
- package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +2 -2
- package/package.json +1 -2
- package/src/app/HomeClient.tsx +0 -207
- package/src/app/agents/[agentId]/agent-editor-tabs.tsx +0 -298
- package/src/app/agents/[agentId]/agent-editor.tsx +0 -468
- package/src/app/agents/[agentId]/page.tsx +0 -32
- package/src/app/api/__tests__/agents-add-route.test.ts +0 -143
- package/src/app/api/__tests__/agents-file-route.test.ts +0 -117
- package/src/app/api/__tests__/agents-files-route.test.ts +0 -61
- package/src/app/api/__tests__/agents-id-route.test.ts +0 -104
- package/src/app/api/__tests__/agents-identity-route.test.ts +0 -92
- package/src/app/api/__tests__/agents-route.test.ts +0 -54
- package/src/app/api/__tests__/agents-skills-install-route.test.ts +0 -131
- package/src/app/api/__tests__/agents-skills-route.test.ts +0 -64
- package/src/app/api/__tests__/agents-update-route.test.ts +0 -95
- package/src/app/api/__tests__/channels-bindings-route.test.ts +0 -143
- package/src/app/api/__tests__/cron-delete-route.test.ts +0 -93
- package/src/app/api/__tests__/cron-job-route.test.ts +0 -78
- package/src/app/api/__tests__/cron-jobs-route.test.ts +0 -116
- package/src/app/api/__tests__/cron-recipe-installed-route.test.ts +0 -114
- package/src/app/api/__tests__/gateway-restart-route.test.ts +0 -36
- package/src/app/api/__tests__/goals-promote-route.test.ts +0 -200
- package/src/app/api/__tests__/goals-route.test.ts +0 -184
- package/src/app/api/__tests__/ids-check-route.test.ts +0 -188
- package/src/app/api/__tests__/marketplace-recipes-route.test.ts +0 -123
- package/src/app/api/__tests__/recipes-clone-route.test.ts +0 -221
- package/src/app/api/__tests__/recipes-delete-route.test.ts +0 -248
- package/src/app/api/__tests__/recipes-id-route.test.ts +0 -166
- package/src/app/api/__tests__/recipes-route.test.ts +0 -57
- package/src/app/api/__tests__/recipes-team-agents-route.test.ts +0 -135
- package/src/app/api/__tests__/scaffold-route.test.ts +0 -173
- package/src/app/api/__tests__/settings-cron-installation-route.test.ts +0 -82
- package/src/app/api/__tests__/skills-available-route.test.ts +0 -47
- package/src/app/api/__tests__/swarms-start-route.test.ts +0 -79
- package/src/app/api/__tests__/swarms-status-route.test.ts +0 -42
- package/src/app/api/__tests__/teams-file-route.test.ts +0 -129
- package/src/app/api/__tests__/teams-files-route.test.ts +0 -57
- package/src/app/api/__tests__/teams-meta-route.test.ts +0 -113
- package/src/app/api/__tests__/teams-orchestrator-install-route.test.ts +0 -66
- package/src/app/api/__tests__/teams-orchestrator-route.test.ts +0 -59
- package/src/app/api/__tests__/teams-remove-team-route.test.ts +0 -122
- package/src/app/api/__tests__/teams-skills-install-route.test.ts +0 -78
- package/src/app/api/__tests__/teams-skills-route.test.ts +0 -73
- package/src/app/api/__tests__/teams-workflow-runs-route.test.ts +0 -85
- package/src/app/api/__tests__/teams-workflows-route.test.ts +0 -110
- package/src/app/api/__tests__/tickets-move-route.test.ts +0 -60
- package/src/app/api/agents/[id]/route.ts +0 -83
- package/src/app/api/agents/add/route.ts +0 -114
- package/src/app/api/agents/file/route.ts +0 -45
- package/src/app/api/agents/files/route.ts +0 -23
- package/src/app/api/agents/identity/route.ts +0 -41
- package/src/app/api/agents/route.ts +0 -22
- package/src/app/api/agents/skills/install/route.ts +0 -34
- package/src/app/api/agents/skills/route.ts +0 -39
- package/src/app/api/agents/update/route.ts +0 -52
- package/src/app/api/channels/bindings/route.ts +0 -63
- package/src/app/api/cron/__tests__/helpers.test.ts +0 -164
- package/src/app/api/cron/delete/route.ts +0 -23
- package/src/app/api/cron/helpers.ts +0 -172
- package/src/app/api/cron/job/route.ts +0 -22
- package/src/app/api/cron/jobs/route.ts +0 -52
- package/src/app/api/cron/recipe-installed/route.ts +0 -65
- package/src/app/api/gateway/restart/route.ts +0 -20
- package/src/app/api/goals/[id]/promote/route.ts +0 -119
- package/src/app/api/goals/[id]/route.ts +0 -54
- package/src/app/api/goals/route.ts +0 -44
- package/src/app/api/ids/check/route.ts +0 -113
- package/src/app/api/marketplace/recipes/[slug]/route.ts +0 -16
- package/src/app/api/marketplace/recipes/route.ts +0 -22
- package/src/app/api/recipes/[id]/route.ts +0 -62
- package/src/app/api/recipes/clone/route.ts +0 -106
- package/src/app/api/recipes/custom-team/route.ts +0 -193
- package/src/app/api/recipes/delete/helpers.ts +0 -65
- package/src/app/api/recipes/delete/route.ts +0 -73
- package/src/app/api/recipes/route.ts +0 -21
- package/src/app/api/recipes/team-agents/__tests__/helpers.test.ts +0 -156
- package/src/app/api/recipes/team-agents/helpers.ts +0 -151
- package/src/app/api/recipes/team-agents/route.ts +0 -80
- package/src/app/api/scaffold/__tests__/helpers.test.ts +0 -186
- package/src/app/api/scaffold/helpers.ts +0 -214
- package/src/app/api/scaffold/route.ts +0 -95
- package/src/app/api/settings/cron-installation/route.ts +0 -58
- package/src/app/api/skills/available/route.ts +0 -23
- package/src/app/api/swarms/start/route.ts +0 -100
- package/src/app/api/swarms/status/route.ts +0 -31
- package/src/app/api/teams/[teamId]/tickets/assign/route.ts +0 -105
- package/src/app/api/teams/[teamId]/tickets/assignees/route.ts +0 -27
- package/src/app/api/teams/[teamId]/tickets/delete/route.ts +0 -55
- package/src/app/api/teams/[teamId]/tickets/move/route.ts +0 -70
- package/src/app/api/teams/[teamId]/tickets/move-to-goals/route.ts +0 -56
- package/src/app/api/teams/file/route.ts +0 -46
- package/src/app/api/teams/files/route.ts +0 -63
- package/src/app/api/teams/memory/route.ts +0 -250
- package/src/app/api/teams/meta/route.ts +0 -43
- package/src/app/api/teams/orchestrator/install/route.ts +0 -129
- package/src/app/api/teams/orchestrator/route.ts +0 -216
- package/src/app/api/teams/remove-team/route.ts +0 -37
- package/src/app/api/teams/skills/install/route.ts +0 -18
- package/src/app/api/teams/skills/route.ts +0 -25
- package/src/app/api/teams/workflow-runs/route.ts +0 -534
- package/src/app/api/teams/workflow-templates/route.ts +0 -71
- package/src/app/api/teams/workflows/route.ts +0 -55
- package/src/app/api/tickets/assign/route.ts +0 -94
- package/src/app/api/tickets/assignees/route.ts +0 -24
- package/src/app/api/tickets/move/route.ts +0 -69
- package/src/app/channels/channels-client.tsx +0 -271
- package/src/app/channels/page.tsx +0 -5
- package/src/app/cron-jobs/cron-jobs-client.tsx +0 -243
- package/src/app/cron-jobs/page.tsx +0 -34
- package/src/app/favicon.ico +0 -0
- package/src/app/global-error.tsx +0 -50
- package/src/app/globals.css +0 -153
- package/src/app/goals/[id]/goal-editor.tsx +0 -162
- package/src/app/goals/[id]/page.tsx +0 -6
- package/src/app/goals/goals-client.tsx +0 -201
- package/src/app/goals/new/page.tsx +0 -81
- package/src/app/goals/page.tsx +0 -10
- package/src/app/layout.tsx +0 -53
- package/src/app/manifest.ts +0 -15
- package/src/app/not-found.tsx +0 -8
- package/src/app/page.tsx +0 -33
- package/src/app/recipes/CreateAgentModal.tsx +0 -156
- package/src/app/recipes/CreateCustomTeamModal.tsx +0 -375
- package/src/app/recipes/CreateModalShell.tsx +0 -55
- package/src/app/recipes/CreateTeamModal.tsx +0 -91
- package/src/app/recipes/[id]/RecipeEditor/RecipeEditorCreateModal.tsx +0 -72
- package/src/app/recipes/[id]/RecipeEditor/RecipeEditorPanel.tsx +0 -216
- package/src/app/recipes/[id]/RecipeEditor/index.tsx +0 -271
- package/src/app/recipes/[id]/RecipeEditor/recipe-editor-utils.ts +0 -46
- package/src/app/recipes/[id]/RecipeEditor/types.ts +0 -52
- package/src/app/recipes/[id]/page.tsx +0 -37
- package/src/app/recipes/page.tsx +0 -101
- package/src/app/recipes/recipes-client.tsx +0 -620
- package/src/app/settings/page.tsx +0 -26
- package/src/app/settings/settings-client.tsx +0 -91
- package/src/app/teams/[teamId]/CloneTeamModal.tsx +0 -116
- package/src/app/teams/[teamId]/OrchestratorPanel.tsx +0 -255
- package/src/app/teams/[teamId]/OrchestratorSetupModal.tsx +0 -184
- package/src/app/teams/[teamId]/PublishChangesModal.tsx +0 -43
- package/src/app/teams/[teamId]/page.tsx +0 -49
- package/src/app/teams/[teamId]/team-editor/TeamAgentsTab.tsx +0 -145
- package/src/app/teams/[teamId]/team-editor/TeamCronTab.tsx +0 -72
- package/src/app/teams/[teamId]/team-editor/TeamFilesTab.tsx +0 -74
- package/src/app/teams/[teamId]/team-editor/TeamMemoryTab.tsx +0 -349
- package/src/app/teams/[teamId]/team-editor/TeamRecipeTab.tsx +0 -151
- package/src/app/teams/[teamId]/team-editor/TeamSkillsTab.tsx +0 -68
- package/src/app/teams/[teamId]/team-editor/index.tsx +0 -558
- package/src/app/teams/[teamId]/team-editor/team-editor-data.ts +0 -255
- package/src/app/teams/[teamId]/team-editor/team-editor-utils.ts +0 -78
- package/src/app/teams/[teamId]/team-editor/types.ts +0 -34
- package/src/app/teams/[teamId]/tickets/[ticket]/page.tsx +0 -35
- package/src/app/teams/[teamId]/tickets/page.tsx +0 -15
- package/src/app/teams/[teamId]/workflows/[workflowId]/WorkflowCanvas.tsx +0 -111
- package/src/app/teams/[teamId]/workflows/[workflowId]/page.tsx +0 -27
- package/src/app/teams/[teamId]/workflows/[workflowId]/workflows-editor-client.tsx +0 -1608
- package/src/app/teams/[teamId]/workflows/page.tsx +0 -40
- package/src/app/teams/[teamId]/workflows/workflows-client.tsx +0 -494
- package/src/app/tickets/TicketDetailClient.tsx +0 -147
- package/src/app/tickets/TicketsBoardClient.tsx +0 -200
- package/src/app/tickets/[ticket]/TicketAssignControl.tsx +0 -112
- package/src/app/tickets/[ticket]/page.tsx +0 -36
- package/src/app/tickets/page.tsx +0 -10
- package/src/components/AppShell.tsx +0 -286
- package/src/components/ConfirmationModal.tsx +0 -81
- package/src/components/DeleteEntityModal.tsx +0 -41
- package/src/components/ErrorBoundary.tsx +0 -70
- package/src/components/FileListWithOptionalToggle.tsx +0 -86
- package/src/components/GoalFormFields.tsx +0 -163
- package/src/components/ScaffoldOverlay.tsx +0 -78
- package/src/components/ThemeToggle.tsx +0 -53
- package/src/components/ToastProvider.tsx +0 -163
- package/src/components/__tests__/ConfirmationModal.test.tsx +0 -109
- package/src/components/__tests__/ErrorBoundary.test.tsx +0 -39
- package/src/components/__tests__/FileListWithOptionalToggle.test.tsx +0 -109
- package/src/components/__tests__/GoalFormFields.test.tsx +0 -117
- package/src/components/delete-modals.tsx +0 -59
- package/src/components/icons.tsx +0 -48
- package/src/lib/__tests__/agent-workspace.test.ts +0 -44
- package/src/lib/__tests__/agents.test.ts +0 -36
- package/src/lib/__tests__/api-route-helpers.test.ts +0 -188
- package/src/lib/__tests__/cron.test.ts +0 -45
- package/src/lib/__tests__/editor-utils.test.ts +0 -38
- package/src/lib/__tests__/errors.test.ts +0 -15
- package/src/lib/__tests__/exec.test.ts +0 -13
- package/src/lib/__tests__/fetch-json.test.ts +0 -118
- package/src/lib/__tests__/gateway.test.ts +0 -234
- package/src/lib/__tests__/goal-promote.test.ts +0 -39
- package/src/lib/__tests__/goals-client.test.ts +0 -26
- package/src/lib/__tests__/goals.test.ts +0 -275
- package/src/lib/__tests__/json.test.ts +0 -15
- package/src/lib/__tests__/kitchen-api.test.ts +0 -32
- package/src/lib/__tests__/marketplace.test.ts +0 -116
- package/src/lib/__tests__/openclaw.test.ts +0 -129
- package/src/lib/__tests__/paths.test.ts +0 -136
- package/src/lib/__tests__/poll.test.ts +0 -26
- package/src/lib/__tests__/recipe-clone.test.ts +0 -85
- package/src/lib/__tests__/recipe-team-agents.test.ts +0 -70
- package/src/lib/__tests__/recipes.test.ts +0 -199
- package/src/lib/__tests__/scaffold-client.test.ts +0 -106
- package/src/lib/__tests__/scaffold.test.ts +0 -64
- package/src/lib/__tests__/slugify.test.ts +0 -23
- package/src/lib/__tests__/tickets.test.ts +0 -158
- package/src/lib/__tests__/type-guards.test.ts +0 -18
- package/src/lib/__tests__/use-slugified-id.test.tsx +0 -120
- package/src/lib/agent-workspace.ts +0 -14
- package/src/lib/agents.ts +0 -17
- package/src/lib/api-route-helpers.ts +0 -157
- package/src/lib/cron.ts +0 -40
- package/src/lib/editor-utils.ts +0 -18
- package/src/lib/errors.ts +0 -7
- package/src/lib/exec.ts +0 -4
- package/src/lib/fetch-json.ts +0 -29
- package/src/lib/gateway.ts +0 -100
- package/src/lib/goal-promote.ts +0 -27
- package/src/lib/goals-client.ts +0 -69
- package/src/lib/goals.ts +0 -171
- package/src/lib/json.ts +0 -10
- package/src/lib/kitchen-api.ts +0 -19
- package/src/lib/marketplace.ts +0 -46
- package/src/lib/openclaw.ts +0 -59
- package/src/lib/paths.ts +0 -69
- package/src/lib/poll.ts +0 -18
- package/src/lib/recipe-clone.ts +0 -42
- package/src/lib/recipe-team-agents.ts +0 -30
- package/src/lib/recipes.ts +0 -95
- package/src/lib/scaffold-client.ts +0 -31
- package/src/lib/scaffold.ts +0 -37
- package/src/lib/slugify.ts +0 -25
- package/src/lib/swarms.ts +0 -25
- package/src/lib/tickets.ts +0 -192
- package/src/lib/type-guards.ts +0 -3
- package/src/lib/use-slugified-id.ts +0 -35
- package/src/lib/workflows/README.md +0 -11
- package/src/lib/workflows/__tests__/storage.test.ts +0 -129
- package/src/lib/workflows/__tests__/validate.test.ts +0 -92
- package/src/lib/workflows/api-handlers.ts +0 -35
- package/src/lib/workflows/readdir.ts +0 -23
- package/src/lib/workflows/runs-storage.ts +0 -59
- package/src/lib/workflows/runs-types.ts +0 -42
- package/src/lib/workflows/storage.ts +0 -70
- package/src/lib/workflows/templates/index.ts +0 -1
- package/src/lib/workflows/templates/marketing-cadence-v1.ts +0 -142
- package/src/lib/workflows/types.ts +0 -48
- package/src/lib/workflows/validate.ts +0 -92
- package/src/proxy.ts +0 -28
- /package/.next/static/{z86RoqzzXXrWnpi229zP6 → Jrrrm9HH5bKkSrQhe1j93}/_buildManifest.js +0 -0
- /package/.next/static/{z86RoqzzXXrWnpi229zP6 → Jrrrm9HH5bKkSrQhe1j93}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{z86RoqzzXXrWnpi229zP6 → Jrrrm9HH5bKkSrQhe1j93}/_ssgManifest.js +0 -0
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import type { ReactNode } from "react";
|
|
4
|
-
import { expectedFilesForRole, templateKeyToFileName } from "./recipe-editor-utils";
|
|
5
|
-
import type { AgentRecipeFrontmatter, TeamRecipeFrontmatter } from "./types";
|
|
6
|
-
|
|
7
|
-
function RecipePanelCard({
|
|
8
|
-
title,
|
|
9
|
-
description,
|
|
10
|
-
buttonLabel,
|
|
11
|
-
onButtonClick,
|
|
12
|
-
error,
|
|
13
|
-
children,
|
|
14
|
-
}: {
|
|
15
|
-
title: string;
|
|
16
|
-
description: ReactNode;
|
|
17
|
-
buttonLabel: string;
|
|
18
|
-
onButtonClick: () => void;
|
|
19
|
-
error?: string;
|
|
20
|
-
children: ReactNode;
|
|
21
|
-
}) {
|
|
22
|
-
return (
|
|
23
|
-
<div className="ck-glass-strong p-4">
|
|
24
|
-
<div className="flex items-start justify-between gap-3">
|
|
25
|
-
<div>
|
|
26
|
-
<div className="text-sm font-medium text-[color:var(--ck-text-primary)]">{title}</div>
|
|
27
|
-
<div className="mt-1 text-xs text-[color:var(--ck-text-tertiary)]">{description}</div>
|
|
28
|
-
</div>
|
|
29
|
-
<button
|
|
30
|
-
type="button"
|
|
31
|
-
onClick={onButtonClick}
|
|
32
|
-
className="shrink-0 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)] transition-colors hover:bg-[var(--ck-accent-red-hover)] active:bg-[var(--ck-accent-red-active)]"
|
|
33
|
-
>
|
|
34
|
-
{buttonLabel}
|
|
35
|
-
</button>
|
|
36
|
-
</div>
|
|
37
|
-
{error ? (
|
|
38
|
-
<div className="mt-4 rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-3 text-xs text-[color:var(--ck-text-primary)]">
|
|
39
|
-
Frontmatter parse error: {error}
|
|
40
|
-
</div>
|
|
41
|
-
) : null}
|
|
42
|
-
{children}
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function TeamRecipeDetails({ fm, recipe }: { fm: TeamRecipeFrontmatter | null; recipe: { id: string } }) {
|
|
48
|
-
return (
|
|
49
|
-
<div className="mt-4 space-y-3">
|
|
50
|
-
<details className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/15 p-3" open>
|
|
51
|
-
<summary className="cursor-pointer text-sm font-medium text-[color:var(--ck-text-primary)]">Recipe information</summary>
|
|
52
|
-
<div className="mt-2 space-y-1 text-xs text-[color:var(--ck-text-secondary)]">
|
|
53
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Recipe id:</span> {fm?.id ?? recipe.id}</div>
|
|
54
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Version:</span> {fm?.version ?? "(unknown)"}</div>
|
|
55
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Team id:</span> {fm?.team?.teamId ?? "(not set)"}</div>
|
|
56
|
-
{fm?.description ? <div className="whitespace-pre-wrap">{fm.description}</div> : null}
|
|
57
|
-
</div>
|
|
58
|
-
</details>
|
|
59
|
-
<TeamAgentsDetails fm={fm} />
|
|
60
|
-
<TeamCronDetails fm={fm} />
|
|
61
|
-
</div>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function TeamAgentsDetails({ fm }: { fm: TeamRecipeFrontmatter | null }) {
|
|
66
|
-
return (
|
|
67
|
-
<details className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/15 p-3">
|
|
68
|
-
<summary className="cursor-pointer text-sm font-medium text-[color:var(--ck-text-primary)]">
|
|
69
|
-
Agents ({fm?.agents?.length ?? 0})
|
|
70
|
-
</summary>
|
|
71
|
-
<div className="mt-2 space-y-2">
|
|
72
|
-
{(fm?.agents ?? []).map((a, idx) => (
|
|
73
|
-
<details key={`${a.role ?? "agent"}:${idx}`} className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-3">
|
|
74
|
-
<summary className="cursor-pointer text-sm text-[color:var(--ck-text-primary)]">
|
|
75
|
-
<span className="font-medium">{a.name ?? a.role ?? "(unnamed)"}</span>
|
|
76
|
-
{a.role ? <span className="text-[color:var(--ck-text-tertiary)]"> — {a.role}</span> : null}
|
|
77
|
-
</summary>
|
|
78
|
-
<div className="mt-2 space-y-1 text-xs text-[color:var(--ck-text-secondary)]">
|
|
79
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Role:</span> {a.role ?? "(none)"}</div>
|
|
80
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Tools profile:</span> {a.tools?.profile ?? "(default)"}</div>
|
|
81
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Allow:</span> {(a.tools?.allow ?? []).length ? (a.tools?.allow ?? []).join(", ") : "(none)"}</div>
|
|
82
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Deny:</span> {(a.tools?.deny ?? []).length ? (a.tools?.deny ?? []).join(", ") : "(none)"}</div>
|
|
83
|
-
<div className="pt-1">
|
|
84
|
-
<span className="text-[color:var(--ck-text-tertiary)]">Expected files:</span>{" "}
|
|
85
|
-
{expectedFilesForRole(fm, a.role).length ? expectedFilesForRole(fm, a.role).join(", ") : "(not listed)"}
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
</details>
|
|
89
|
-
))}
|
|
90
|
-
{(!fm?.agents || fm.agents.length === 0) ? (
|
|
91
|
-
<div className="text-xs text-[color:var(--ck-text-tertiary)]">(No agents listed in frontmatter)</div>
|
|
92
|
-
) : null}
|
|
93
|
-
</div>
|
|
94
|
-
</details>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function TeamCronDetails({ fm }: { fm: TeamRecipeFrontmatter | null }) {
|
|
99
|
-
return (
|
|
100
|
-
<details className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/15 p-3">
|
|
101
|
-
<summary className="cursor-pointer text-sm font-medium text-[color:var(--ck-text-primary)]">
|
|
102
|
-
Cron jobs ({fm?.cronJobs?.length ?? 0})
|
|
103
|
-
</summary>
|
|
104
|
-
<div className="mt-2 space-y-2">
|
|
105
|
-
{(fm?.cronJobs ?? []).map((c, idx) => (
|
|
106
|
-
<details key={`${c.id ?? "cron"}:${idx}`} className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-3">
|
|
107
|
-
<summary className="cursor-pointer text-sm text-[color:var(--ck-text-primary)]">
|
|
108
|
-
<span className="font-medium">{c.name ?? c.id ?? "(unnamed)"}</span>
|
|
109
|
-
{c.schedule ? <span className="text-[color:var(--ck-text-tertiary)]"> — {c.schedule}</span> : null}
|
|
110
|
-
</summary>
|
|
111
|
-
<div className="mt-2 space-y-1 text-xs text-[color:var(--ck-text-secondary)]">
|
|
112
|
-
{c.agentId ? <div><span className="text-[color:var(--ck-text-tertiary)]">Agent:</span> {c.agentId}</div> : null}
|
|
113
|
-
{c.channel ? <div><span className="text-[color:var(--ck-text-tertiary)]">Channel:</span> {c.channel}</div> : null}
|
|
114
|
-
{typeof c.enabledByDefault === "boolean" ? (
|
|
115
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Enabled by default:</span> {c.enabledByDefault ? "yes" : "no"}</div>
|
|
116
|
-
) : null}
|
|
117
|
-
{c.message ? (
|
|
118
|
-
<div className="mt-2 whitespace-pre-wrap rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-2 text-[11px] text-[color:var(--ck-text-primary)]">{c.message}</div>
|
|
119
|
-
) : null}
|
|
120
|
-
</div>
|
|
121
|
-
</details>
|
|
122
|
-
))}
|
|
123
|
-
{(!fm?.cronJobs || fm.cronJobs.length === 0) ? (
|
|
124
|
-
<div className="text-xs text-[color:var(--ck-text-tertiary)]">(No cron jobs listed in frontmatter)</div>
|
|
125
|
-
) : null}
|
|
126
|
-
</div>
|
|
127
|
-
</details>
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function TeamRecipePanelContent({
|
|
132
|
-
recipe,
|
|
133
|
-
fm,
|
|
134
|
-
fmErr,
|
|
135
|
-
onOpenCreateTeam,
|
|
136
|
-
}: {
|
|
137
|
-
recipe: { id: string };
|
|
138
|
-
fm: TeamRecipeFrontmatter | null;
|
|
139
|
-
fmErr?: string;
|
|
140
|
-
onOpenCreateTeam: () => void;
|
|
141
|
-
}) {
|
|
142
|
-
return (
|
|
143
|
-
<RecipePanelCard
|
|
144
|
-
title="Team recipe"
|
|
145
|
-
description={
|
|
146
|
-
<>
|
|
147
|
-
Create a team from this recipe. Creating a Team runs <code>openclaw recipes scaffold-team</code> with{" "}
|
|
148
|
-
<code>--apply-config</code>.
|
|
149
|
-
</>
|
|
150
|
-
}
|
|
151
|
-
buttonLabel="Create Team"
|
|
152
|
-
onButtonClick={onOpenCreateTeam}
|
|
153
|
-
error={fmErr}
|
|
154
|
-
>
|
|
155
|
-
<TeamRecipeDetails fm={fm} recipe={recipe} />
|
|
156
|
-
</RecipePanelCard>
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export function AgentRecipePanelContent({
|
|
161
|
-
recipe,
|
|
162
|
-
afm,
|
|
163
|
-
afmErr,
|
|
164
|
-
onOpenCreateAgent,
|
|
165
|
-
}: {
|
|
166
|
-
recipe: { id: string };
|
|
167
|
-
afm: AgentRecipeFrontmatter | null;
|
|
168
|
-
afmErr?: string;
|
|
169
|
-
onOpenCreateAgent: () => void;
|
|
170
|
-
}) {
|
|
171
|
-
return (
|
|
172
|
-
<RecipePanelCard
|
|
173
|
-
title="Agent recipe"
|
|
174
|
-
description={
|
|
175
|
-
<>
|
|
176
|
-
Create an agent from this recipe. Creating an Agent runs <code>openclaw recipes scaffold</code> with{" "}
|
|
177
|
-
<code>--apply-config</code>.
|
|
178
|
-
</>
|
|
179
|
-
}
|
|
180
|
-
buttonLabel="Create Agent"
|
|
181
|
-
onButtonClick={onOpenCreateAgent}
|
|
182
|
-
error={afmErr}
|
|
183
|
-
>
|
|
184
|
-
<div className="mt-4 space-y-3">
|
|
185
|
-
<details className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/15 p-3" open>
|
|
186
|
-
<summary className="cursor-pointer text-sm font-medium text-[color:var(--ck-text-primary)]">Recipe information</summary>
|
|
187
|
-
<div className="mt-2 space-y-1 text-xs text-[color:var(--ck-text-secondary)]">
|
|
188
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Recipe id:</span> {afm?.id ?? recipe.id}</div>
|
|
189
|
-
<div><span className="text-[color:var(--ck-text-tertiary)]">Version:</span> {afm?.version ?? "(unknown)"}</div>
|
|
190
|
-
{afm?.description ? <div className="whitespace-pre-wrap">{afm.description}</div> : null}
|
|
191
|
-
</div>
|
|
192
|
-
</details>
|
|
193
|
-
<details className="rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/15 p-3">
|
|
194
|
-
<summary className="cursor-pointer text-sm font-medium text-[color:var(--ck-text-primary)]">
|
|
195
|
-
Files ({Object.keys(afm?.templates ?? {}).length})
|
|
196
|
-
</summary>
|
|
197
|
-
<div className="mt-2 space-y-1 text-xs text-[color:var(--ck-text-secondary)]">
|
|
198
|
-
{Object.keys(afm?.templates ?? {}).length ? (
|
|
199
|
-
<ul className="list-disc space-y-1 pl-5">
|
|
200
|
-
{Object.keys(afm?.templates ?? {}).map((k) => (
|
|
201
|
-
<li key={k}>
|
|
202
|
-
<span className="font-mono text-[11px]">{k}</span>
|
|
203
|
-
<span className="text-[color:var(--ck-text-tertiary)]"> → </span>
|
|
204
|
-
<span className="font-mono text-[11px]">{templateKeyToFileName(k)}</span>
|
|
205
|
-
</li>
|
|
206
|
-
))}
|
|
207
|
-
</ul>
|
|
208
|
-
) : (
|
|
209
|
-
<div className="text-[color:var(--ck-text-tertiary)]">(No templates listed in frontmatter)</div>
|
|
210
|
-
)}
|
|
211
|
-
</div>
|
|
212
|
-
</details>
|
|
213
|
-
</div>
|
|
214
|
-
</RecipePanelCard>
|
|
215
|
-
);
|
|
216
|
-
}
|
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useEffect, useMemo, useState } from "react";
|
|
4
|
-
import { useRouter } from "next/navigation";
|
|
5
|
-
import { errorMessage } from "@/lib/errors";
|
|
6
|
-
import { fetchJson } from "@/lib/fetch-json";
|
|
7
|
-
import { validateCreateId } from "@/lib/recipe-team-agents";
|
|
8
|
-
import { fetchScaffold } from "@/lib/scaffold-client";
|
|
9
|
-
import type { AgentRecipeFrontmatter, Recipe, TeamRecipeFrontmatter } from "./types";
|
|
10
|
-
import { parseFrontmatter } from "./recipe-editor-utils";
|
|
11
|
-
import { TeamRecipePanelContent, AgentRecipePanelContent } from "./RecipeEditorPanel";
|
|
12
|
-
import { RecipeEditorCreateModal } from "./RecipeEditorCreateModal";
|
|
13
|
-
|
|
14
|
-
type CreateModalKind = "team" | "agent" | null;
|
|
15
|
-
|
|
16
|
-
export default function RecipeEditor({ recipeId }: { recipeId: string }) {
|
|
17
|
-
const router = useRouter();
|
|
18
|
-
|
|
19
|
-
const [loading, setLoading] = useState(true);
|
|
20
|
-
const [saving, setSaving] = useState(false);
|
|
21
|
-
const [recipe, setRecipe] = useState<Recipe | null>(null);
|
|
22
|
-
const [content, setContent] = useState<string>("");
|
|
23
|
-
const [message, setMessage] = useState<string>("");
|
|
24
|
-
|
|
25
|
-
const [createModalKind, setCreateModalKind] = useState<CreateModalKind>(null);
|
|
26
|
-
const [createId, setCreateId] = useState("");
|
|
27
|
-
const [createName, setCreateName] = useState("");
|
|
28
|
-
const [cronInstallChoice, setCronInstallChoice] = useState<"yes" | "no">("no");
|
|
29
|
-
const [createBusy, setCreateBusy] = useState(false);
|
|
30
|
-
const [createError, setCreateError] = useState("");
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
(async () => {
|
|
34
|
-
setLoading(true);
|
|
35
|
-
setMessage("");
|
|
36
|
-
try {
|
|
37
|
-
const json = await fetchJson<{ recipe: Recipe }>(
|
|
38
|
-
`/api/recipes/${encodeURIComponent(recipeId)}`,
|
|
39
|
-
{ cache: "no-store" }
|
|
40
|
-
);
|
|
41
|
-
const r = json.recipe;
|
|
42
|
-
setRecipe(r);
|
|
43
|
-
setContent(r.content);
|
|
44
|
-
} catch (e: unknown) {
|
|
45
|
-
setMessage(errorMessage(e));
|
|
46
|
-
} finally {
|
|
47
|
-
setLoading(false);
|
|
48
|
-
}
|
|
49
|
-
})();
|
|
50
|
-
}, [recipeId]);
|
|
51
|
-
|
|
52
|
-
const canSave = useMemo(() => {
|
|
53
|
-
if (!recipe) return false;
|
|
54
|
-
return recipe.filePath !== null;
|
|
55
|
-
}, [recipe]);
|
|
56
|
-
|
|
57
|
-
const teamFrontmatter = useMemo(() => {
|
|
58
|
-
if (!recipe || recipe.kind !== "team") return { fm: null as TeamRecipeFrontmatter | null, error: undefined as string | undefined };
|
|
59
|
-
return parseFrontmatter(content);
|
|
60
|
-
}, [recipe, content]);
|
|
61
|
-
|
|
62
|
-
const agentFrontmatter = useMemo(() => {
|
|
63
|
-
if (!recipe || recipe.kind !== "agent") return { fm: null as AgentRecipeFrontmatter | null, error: undefined as string | undefined };
|
|
64
|
-
return parseFrontmatter(content);
|
|
65
|
-
}, [recipe, content]);
|
|
66
|
-
|
|
67
|
-
async function onSave() {
|
|
68
|
-
setSaving(true);
|
|
69
|
-
setMessage("");
|
|
70
|
-
try {
|
|
71
|
-
const json = await fetchJson<{ filePath: string }>(
|
|
72
|
-
`/api/recipes/${encodeURIComponent(recipeId)}`,
|
|
73
|
-
{
|
|
74
|
-
method: "PUT",
|
|
75
|
-
headers: { "content-type": "application/json" },
|
|
76
|
-
body: JSON.stringify({ content }),
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
setMessage(`Saved to ${json.filePath}`);
|
|
80
|
-
} catch (e: unknown) {
|
|
81
|
-
setMessage(errorMessage(e));
|
|
82
|
-
} finally {
|
|
83
|
-
setSaving(false);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function openCreateTeam() {
|
|
88
|
-
setCreateError("");
|
|
89
|
-
setCreateId("");
|
|
90
|
-
setCronInstallChoice("no");
|
|
91
|
-
setCreateModalKind("team");
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function openCreateAgent() {
|
|
95
|
-
setCreateError("");
|
|
96
|
-
setCreateId("");
|
|
97
|
-
setCreateName((agentFrontmatter.fm?.name || recipe?.name || "").trim());
|
|
98
|
-
setCreateModalKind("agent");
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function onSubmitCreate() {
|
|
102
|
-
if (!recipe || !createModalKind) return;
|
|
103
|
-
const kind = createModalKind;
|
|
104
|
-
const err = validateCreateId(recipe, createId, kind);
|
|
105
|
-
if (err) {
|
|
106
|
-
setCreateError(err);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const id = createId.trim();
|
|
111
|
-
setCreateBusy(true);
|
|
112
|
-
setCreateError("");
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
if (kind === "team") {
|
|
116
|
-
const { res, json } = await fetchScaffold({
|
|
117
|
-
kind: "team",
|
|
118
|
-
recipeId: recipe.id,
|
|
119
|
-
teamId: id,
|
|
120
|
-
cronInstallChoice,
|
|
121
|
-
});
|
|
122
|
-
if (!res.ok) throw new Error((json as { error?: string }).error || "Create Team failed");
|
|
123
|
-
setCreateModalKind(null);
|
|
124
|
-
router.push(`/teams/${encodeURIComponent(id)}`);
|
|
125
|
-
} else {
|
|
126
|
-
const { res, json } = await fetchScaffold({
|
|
127
|
-
kind: "agent",
|
|
128
|
-
recipeId: recipe.id,
|
|
129
|
-
agentId: id,
|
|
130
|
-
name: createName.trim() || undefined,
|
|
131
|
-
});
|
|
132
|
-
if (!res.ok) throw new Error((json as { error?: string }).error || "Create Agent failed");
|
|
133
|
-
setCreateModalKind(null);
|
|
134
|
-
router.push(`/agents/${encodeURIComponent(id)}`);
|
|
135
|
-
}
|
|
136
|
-
router.refresh();
|
|
137
|
-
} catch (e: unknown) {
|
|
138
|
-
setCreateError(errorMessage(e));
|
|
139
|
-
} finally {
|
|
140
|
-
setCreateBusy(false);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (loading) return <div className="ck-glass mx-auto max-w-4xl p-6">Loading</div>;
|
|
145
|
-
if (!recipe) return <div className="ck-glass mx-auto max-w-4xl p-6">Not found.</div>;
|
|
146
|
-
|
|
147
|
-
const fm = recipe.kind === "team" ? teamFrontmatter.fm : null;
|
|
148
|
-
const fmErr = recipe.kind === "team" ? teamFrontmatter.error : undefined;
|
|
149
|
-
|
|
150
|
-
const afm = recipe.kind === "agent" ? agentFrontmatter.fm : null;
|
|
151
|
-
const afmErr = recipe.kind === "agent" ? agentFrontmatter.error : undefined;
|
|
152
|
-
|
|
153
|
-
return (
|
|
154
|
-
<div className="ck-glass mx-auto max-w-6xl p-6 sm:p-8">
|
|
155
|
-
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between sm:gap-6">
|
|
156
|
-
<div className="min-w-0">
|
|
157
|
-
<h1 className="truncate text-2xl font-semibold tracking-tight">{recipe.name}</h1>
|
|
158
|
-
<div className="mt-1 text-xs text-[color:var(--ck-text-secondary)]">
|
|
159
|
-
{recipe.id} • {recipe.kind} • {recipe.source}
|
|
160
|
-
</div>
|
|
161
|
-
<div className="mt-1 text-xs text-[color:var(--ck-text-tertiary)]">
|
|
162
|
-
Path: {recipe.filePath ?? "(unknown / not writable)"}
|
|
163
|
-
</div>
|
|
164
|
-
</div>
|
|
165
|
-
|
|
166
|
-
<div className="flex gap-2">
|
|
167
|
-
<button
|
|
168
|
-
disabled={!canSave || saving}
|
|
169
|
-
onClick={onSave}
|
|
170
|
-
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)] transition-colors hover:bg-[var(--ck-accent-red-hover)] active:bg-[var(--ck-accent-red-active)] disabled:opacity-50"
|
|
171
|
-
>
|
|
172
|
-
{saving ? "Saving" : "Save"}
|
|
173
|
-
</button>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
|
|
177
|
-
{message ? (
|
|
178
|
-
<div className="mt-4 rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/20 p-3 text-sm text-[color:var(--ck-text-primary)]">
|
|
179
|
-
{message}
|
|
180
|
-
</div>
|
|
181
|
-
) : null}
|
|
182
|
-
|
|
183
|
-
<div className="mt-6 grid grid-cols-1 gap-4 lg:grid-cols-2">
|
|
184
|
-
<div className="ck-glass-strong p-4">
|
|
185
|
-
<div className="text-sm font-medium text-[color:var(--ck-text-primary)]">Recipe markdown</div>
|
|
186
|
-
<textarea
|
|
187
|
-
value={content}
|
|
188
|
-
onChange={(e) => setContent(e.target.value)}
|
|
189
|
-
className="mt-2 h-[70vh] w-full resize-none rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 p-3 font-mono text-xs text-[color:var(--ck-text-primary)] placeholder:text-[color:var(--ck-text-tertiary)]"
|
|
190
|
-
spellCheck={false}
|
|
191
|
-
/>
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
{recipe.kind === "team" ? (
|
|
195
|
-
<TeamRecipePanelContent recipe={recipe} fm={fm as TeamRecipeFrontmatter | null} fmErr={fmErr} onOpenCreateTeam={openCreateTeam} />
|
|
196
|
-
) : (
|
|
197
|
-
<AgentRecipePanelContent recipe={recipe} afm={afm as AgentRecipeFrontmatter | null} afmErr={afmErr} onOpenCreateAgent={openCreateAgent} />
|
|
198
|
-
)}
|
|
199
|
-
</div>
|
|
200
|
-
|
|
201
|
-
<RecipeEditorCreateModal
|
|
202
|
-
open={createModalKind !== null}
|
|
203
|
-
title={createModalKind === "team" ? "Create Team" : "Create Agent"}
|
|
204
|
-
recipeId={recipe.id}
|
|
205
|
-
busy={createBusy}
|
|
206
|
-
error={createError || undefined}
|
|
207
|
-
onClose={() => setCreateModalKind(null)}
|
|
208
|
-
onConfirm={onSubmitCreate}
|
|
209
|
-
confirmLabel={createModalKind === "team" ? "Create Team" : "Create Agent"}
|
|
210
|
-
>
|
|
211
|
-
{createModalKind === "team" ? (
|
|
212
|
-
<>
|
|
213
|
-
<label className="block">
|
|
214
|
-
<div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Team id</div>
|
|
215
|
-
<input
|
|
216
|
-
value={createId}
|
|
217
|
-
onChange={(e) => setCreateId(e.target.value)}
|
|
218
|
-
placeholder="e.g. acme"
|
|
219
|
-
className="mt-2 w-full rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]"
|
|
220
|
-
disabled={createBusy}
|
|
221
|
-
/>
|
|
222
|
-
</label>
|
|
223
|
-
<label className="block">
|
|
224
|
-
<div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Install cron jobs</div>
|
|
225
|
-
<select
|
|
226
|
-
value={cronInstallChoice}
|
|
227
|
-
onChange={(e) => setCronInstallChoice(e.target.value as "yes" | "no")}
|
|
228
|
-
className="mt-2 w-full rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]"
|
|
229
|
-
disabled={createBusy}
|
|
230
|
-
>
|
|
231
|
-
<option value="no">No (recommended)</option>
|
|
232
|
-
<option value="yes">Yes</option>
|
|
233
|
-
</select>
|
|
234
|
-
<div className="mt-1 text-xs text-[color:var(--ck-text-tertiary)]">
|
|
235
|
-
Kitchen scaffolds non-interactively; this controls the one-time cron install choice for this run.
|
|
236
|
-
</div>
|
|
237
|
-
</label>
|
|
238
|
-
</>
|
|
239
|
-
) : (
|
|
240
|
-
<>
|
|
241
|
-
<label className="block">
|
|
242
|
-
<div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Agent id</div>
|
|
243
|
-
<input
|
|
244
|
-
value={createId}
|
|
245
|
-
onChange={(e) => setCreateId(e.target.value)}
|
|
246
|
-
placeholder="e.g. larry"
|
|
247
|
-
className="mt-2 w-full rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]"
|
|
248
|
-
disabled={createBusy}
|
|
249
|
-
/>
|
|
250
|
-
</label>
|
|
251
|
-
<label className="block">
|
|
252
|
-
<div className="text-xs font-medium text-[color:var(--ck-text-secondary)]">Name (optional)</div>
|
|
253
|
-
<input
|
|
254
|
-
value={createName}
|
|
255
|
-
onChange={(e) => setCreateName(e.target.value)}
|
|
256
|
-
placeholder="e.g. Larry"
|
|
257
|
-
className="mt-2 w-full rounded-[var(--ck-radius-sm)] border border-white/10 bg-black/25 px-3 py-2 text-sm text-[color:var(--ck-text-primary)]"
|
|
258
|
-
disabled={createBusy}
|
|
259
|
-
/>
|
|
260
|
-
</label>
|
|
261
|
-
</>
|
|
262
|
-
)}
|
|
263
|
-
</RecipeEditorCreateModal>
|
|
264
|
-
|
|
265
|
-
<p className="mt-6 text-xs text-[color:var(--ck-text-tertiary)]">
|
|
266
|
-
This page edits the recipe markdown and previews what will be created when you click{" "}
|
|
267
|
-
{recipe.kind === "team" ? "Create Team" : "Create Agent"}.
|
|
268
|
-
</p>
|
|
269
|
-
</div>
|
|
270
|
-
);
|
|
271
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { parse as parseYaml } from "yaml";
|
|
2
|
-
import { errorMessage } from "@/lib/errors";
|
|
3
|
-
import type { AgentRecipeFrontmatter, TeamRecipeFrontmatter } from "./types";
|
|
4
|
-
|
|
5
|
-
export function parseFrontmatter(raw: string): { fm: TeamRecipeFrontmatter | AgentRecipeFrontmatter | null; error?: string } {
|
|
6
|
-
const start = raw.indexOf("---\n");
|
|
7
|
-
if (start !== 0) return { fm: null };
|
|
8
|
-
const end = raw.indexOf("\n---\n", 4);
|
|
9
|
-
if (end === -1) return { fm: null };
|
|
10
|
-
const yamlText = raw.slice(4, end);
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
const fm = parseYaml(yamlText) as TeamRecipeFrontmatter | AgentRecipeFrontmatter;
|
|
14
|
-
if (!fm || typeof fm !== "object") return { fm: null };
|
|
15
|
-
return { fm };
|
|
16
|
-
} catch (e) {
|
|
17
|
-
return { fm: null, error: errorMessage(e) };
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function templateKeyToFileName(key: string, stripRolePrefix?: boolean): string {
|
|
22
|
-
const suffix = stripRolePrefix ? key.split(".").slice(1).join(".") : key;
|
|
23
|
-
switch (suffix) {
|
|
24
|
-
case "soul":
|
|
25
|
-
return "SOUL.md";
|
|
26
|
-
case "agents":
|
|
27
|
-
return "AGENTS.md";
|
|
28
|
-
case "tools":
|
|
29
|
-
return "TOOLS.md";
|
|
30
|
-
case "identity":
|
|
31
|
-
return "IDENTITY.md";
|
|
32
|
-
case "install":
|
|
33
|
-
return "INSTALL.md";
|
|
34
|
-
case "status":
|
|
35
|
-
return "STATUS.md";
|
|
36
|
-
default:
|
|
37
|
-
return suffix ? `${suffix.toUpperCase()}` : key;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function expectedFilesForRole(fm: TeamRecipeFrontmatter | null, role: string | undefined): string[] {
|
|
42
|
-
if (!fm || !role || !fm.templates) return [];
|
|
43
|
-
const keys = Object.keys(fm.templates).filter((k) => k.startsWith(`${role}.`));
|
|
44
|
-
const files = keys.map((k) => templateKeyToFileName(k, true));
|
|
45
|
-
return [...new Set(files)];
|
|
46
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
export type Recipe = {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
kind: "agent" | "team";
|
|
5
|
-
source: "builtin" | "workspace";
|
|
6
|
-
content: string;
|
|
7
|
-
filePath: string | null;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type TeamRecipeFrontmatter = {
|
|
11
|
-
id?: string;
|
|
12
|
-
name?: string;
|
|
13
|
-
version?: string;
|
|
14
|
-
description?: string;
|
|
15
|
-
kind?: "team";
|
|
16
|
-
source?: string;
|
|
17
|
-
cronJobs?: Array<{
|
|
18
|
-
id?: string;
|
|
19
|
-
name?: string;
|
|
20
|
-
schedule?: string;
|
|
21
|
-
timezone?: string;
|
|
22
|
-
agentId?: string;
|
|
23
|
-
channel?: string;
|
|
24
|
-
to?: string;
|
|
25
|
-
description?: string;
|
|
26
|
-
message?: string;
|
|
27
|
-
enabledByDefault?: boolean;
|
|
28
|
-
}>;
|
|
29
|
-
agents?: Array<{
|
|
30
|
-
role?: string;
|
|
31
|
-
name?: string;
|
|
32
|
-
tools?: {
|
|
33
|
-
profile?: string;
|
|
34
|
-
allow?: string[];
|
|
35
|
-
deny?: string[];
|
|
36
|
-
};
|
|
37
|
-
}>;
|
|
38
|
-
team?: {
|
|
39
|
-
teamId?: string;
|
|
40
|
-
};
|
|
41
|
-
templates?: Record<string, string>;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export type AgentRecipeFrontmatter = {
|
|
45
|
-
id?: string;
|
|
46
|
-
name?: string;
|
|
47
|
-
version?: string;
|
|
48
|
-
description?: string;
|
|
49
|
-
kind?: "agent";
|
|
50
|
-
source?: string;
|
|
51
|
-
templates?: Record<string, string>;
|
|
52
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import Link from "next/link";
|
|
2
|
-
import { unstable_noStore as noStore } from "next/cache";
|
|
3
|
-
|
|
4
|
-
import { listRecipes } from "@/lib/recipes";
|
|
5
|
-
import RecipeEditor from "./RecipeEditor";
|
|
6
|
-
|
|
7
|
-
export const dynamic = "force-dynamic";
|
|
8
|
-
export const revalidate = 0;
|
|
9
|
-
|
|
10
|
-
async function getKind(id: string): Promise<"agent" | "team" | null> {
|
|
11
|
-
const recipes = await listRecipes();
|
|
12
|
-
return recipes.find((r) => r.id === id)?.kind ?? null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default async function RecipePage({ params }: { params: Promise<{ id: string }> }) {
|
|
16
|
-
noStore();
|
|
17
|
-
|
|
18
|
-
const { id } = await params;
|
|
19
|
-
await getKind(id); // Resolved for future redirect logic; kept for cache consistency
|
|
20
|
-
|
|
21
|
-
// NOTE: We do NOT redirect team recipes to /teams/<id>.
|
|
22
|
-
// /recipes/<id> is the recipe editor/preview surface; /teams/<id> is the installed team editor.
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<main className="min-h-screen p-8">
|
|
26
|
-
<div className="mx-auto mb-4 max-w-6xl">
|
|
27
|
-
<Link
|
|
28
|
-
href="/recipes"
|
|
29
|
-
className="text-sm font-medium text-[color:var(--ck-text-secondary)] transition-colors hover:text-[color:var(--ck-text-primary)]"
|
|
30
|
-
>
|
|
31
|
-
← Back to recipes
|
|
32
|
-
</Link>
|
|
33
|
-
</div>
|
|
34
|
-
<RecipeEditor recipeId={id} />
|
|
35
|
-
</main>
|
|
36
|
-
);
|
|
37
|
-
}
|