@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,35 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { withStorageError } from "@/lib/api-route-helpers";
|
|
3
|
-
|
|
4
|
-
function params(req: Request) {
|
|
5
|
-
const { searchParams } = new URL(req.url);
|
|
6
|
-
return {
|
|
7
|
-
teamId: String(searchParams.get("teamId") ?? "").trim(),
|
|
8
|
-
id: String(searchParams.get("id") ?? "").trim(),
|
|
9
|
-
workflowId: String(searchParams.get("workflowId") ?? "").trim(),
|
|
10
|
-
runId: String(searchParams.get("runId") ?? "").trim(),
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** GET handler for /api/teams/workflows. */
|
|
15
|
-
export async function handleWorkflowsGet(
|
|
16
|
-
req: Request,
|
|
17
|
-
readOne: (teamId: string, id: string) => Promise<{ ok: boolean }>,
|
|
18
|
-
listAll: (teamId: string) => Promise<{ ok: boolean }>
|
|
19
|
-
): Promise<NextResponse> {
|
|
20
|
-
const { teamId, id } = params(req);
|
|
21
|
-
if (!teamId) return NextResponse.json({ ok: false, error: "teamId is required" }, { status: 400 });
|
|
22
|
-
return withStorageError(() => (id ? readOne(teamId, id) : listAll(teamId)));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** GET handler for /api/teams/workflow-runs. */
|
|
26
|
-
export async function handleWorkflowRunsGet(
|
|
27
|
-
req: Request,
|
|
28
|
-
readOne: (teamId: string, workflowId: string, runId: string) => Promise<{ ok: boolean }>,
|
|
29
|
-
listAll: (teamId: string, workflowId: string) => Promise<{ ok: boolean }>
|
|
30
|
-
): Promise<NextResponse> {
|
|
31
|
-
const { teamId, workflowId, runId } = params(req);
|
|
32
|
-
if (!teamId) return NextResponse.json({ ok: false, error: "teamId is required" }, { status: 400 });
|
|
33
|
-
if (!workflowId) return NextResponse.json({ ok: false, error: "workflowId is required" }, { status: 400 });
|
|
34
|
-
return withStorageError(() => (runId ? readOne(teamId, workflowId, runId) : listAll(teamId, workflowId)));
|
|
35
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
|
|
3
|
-
/** Reads dir with optional suffix filter and reverse sort. Returns { ok, dir, files } or { ok, dir, files: [] } on ENOENT. */
|
|
4
|
-
export async function readdirFiles(
|
|
5
|
-
dir: string,
|
|
6
|
-
suffix: string,
|
|
7
|
-
reverse = false
|
|
8
|
-
): Promise<{ ok: true; dir: string; files: string[] }> {
|
|
9
|
-
try {
|
|
10
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
11
|
-
let files = entries
|
|
12
|
-
.filter((e) => e.isFile() && e.name.endsWith(suffix))
|
|
13
|
-
.map((e) => e.name)
|
|
14
|
-
.sort();
|
|
15
|
-
if (reverse) files = files.reverse();
|
|
16
|
-
return { ok: true as const, dir, files };
|
|
17
|
-
} catch (err: unknown) {
|
|
18
|
-
if (err && typeof err === "object" && (err as { code?: unknown }).code === "ENOENT") {
|
|
19
|
-
return { ok: true as const, dir, files: [] as string[] };
|
|
20
|
-
}
|
|
21
|
-
throw err;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { getTeamWorkspaceDir } from "@/lib/paths";
|
|
4
|
-
import { readdirFiles } from "@/lib/workflows/readdir";
|
|
5
|
-
import { assertSafeWorkflowId } from "@/lib/workflows/storage";
|
|
6
|
-
import type { WorkflowRunFileV1 } from "@/lib/workflows/runs-types";
|
|
7
|
-
|
|
8
|
-
const RUNS_DIR = path.join("shared-context", "workflow-runs");
|
|
9
|
-
|
|
10
|
-
export function assertSafeRunId(runId: string) {
|
|
11
|
-
const id = String(runId ?? "").trim();
|
|
12
|
-
if (!id) throw new Error("run id is required");
|
|
13
|
-
if (!/^[a-z0-9][a-z0-9-]{0,80}$/.test(id)) {
|
|
14
|
-
throw new Error("Invalid run id. Use lowercase letters, numbers, and dashes (max 81 chars).");
|
|
15
|
-
}
|
|
16
|
-
return id;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function getWorkflowRunsDir(teamId: string, workflowId: string) {
|
|
20
|
-
const wfId = assertSafeWorkflowId(workflowId);
|
|
21
|
-
const teamDir = await getTeamWorkspaceDir(teamId);
|
|
22
|
-
return path.join(teamDir, RUNS_DIR, wfId);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function workflowRunFileName(runId: string) {
|
|
26
|
-
return `${runId}.run.json`;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function listWorkflowRuns(teamId: string, workflowId: string) {
|
|
30
|
-
const dir = await getWorkflowRunsDir(teamId, workflowId);
|
|
31
|
-
return readdirFiles(dir, ".run.json", true);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function readWorkflowRun(teamId: string, workflowId: string, runId: string) {
|
|
35
|
-
const wfId = assertSafeWorkflowId(workflowId);
|
|
36
|
-
const rId = assertSafeRunId(runId);
|
|
37
|
-
const dir = await getWorkflowRunsDir(teamId, wfId);
|
|
38
|
-
const p = path.join(dir, workflowRunFileName(rId));
|
|
39
|
-
const raw = await fs.readFile(p, "utf8");
|
|
40
|
-
const parsed = JSON.parse(raw) as WorkflowRunFileV1;
|
|
41
|
-
return { ok: true as const, path: p, run: parsed };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function writeWorkflowRun(teamId: string, workflowId: string, run: WorkflowRunFileV1) {
|
|
45
|
-
const wfId = assertSafeWorkflowId(workflowId);
|
|
46
|
-
const rId = assertSafeRunId(run.id);
|
|
47
|
-
const dir = await getWorkflowRunsDir(teamId, wfId);
|
|
48
|
-
await fs.mkdir(dir, { recursive: true });
|
|
49
|
-
const p = path.join(dir, workflowRunFileName(rId));
|
|
50
|
-
const toWrite: WorkflowRunFileV1 = {
|
|
51
|
-
...run,
|
|
52
|
-
schema: "clawkitchen.workflow-run.v1",
|
|
53
|
-
id: rId,
|
|
54
|
-
workflowId: wfId,
|
|
55
|
-
teamId,
|
|
56
|
-
};
|
|
57
|
-
await fs.writeFile(p, JSON.stringify(toWrite, null, 2) + "\n", "utf8");
|
|
58
|
-
return { ok: true as const, path: p };
|
|
59
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export type WorkflowRunNodeResultV1 = {
|
|
2
|
-
nodeId: string;
|
|
3
|
-
status: "pending" | "running" | "waiting" | "success" | "error" | "skipped";
|
|
4
|
-
startedAt?: string;
|
|
5
|
-
endedAt?: string;
|
|
6
|
-
output?: unknown;
|
|
7
|
-
error?: { message: string; stack?: string } | string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type WorkflowRunApprovalV1 = {
|
|
11
|
-
nodeId: string;
|
|
12
|
-
state: "pending" | "approved" | "changes_requested" | "canceled";
|
|
13
|
-
requestedAt?: string;
|
|
14
|
-
decidedAt?: string;
|
|
15
|
-
/** Freeform notes from the approver (optional) */
|
|
16
|
-
note?: string;
|
|
17
|
-
/** Who made the decision (MVP: typically "ClawKitchen UI" or channel metadata) */
|
|
18
|
-
decidedBy?: string;
|
|
19
|
-
/** Outbound delivery metadata for the approval request (best-effort) */
|
|
20
|
-
outbound?: {
|
|
21
|
-
provider: string;
|
|
22
|
-
target: string;
|
|
23
|
-
sentAt?: string;
|
|
24
|
-
attemptedAt?: string;
|
|
25
|
-
error?: string;
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export type WorkflowRunFileV1 = {
|
|
30
|
-
schema: "clawkitchen.workflow-run.v1";
|
|
31
|
-
id: string;
|
|
32
|
-
workflowId: string;
|
|
33
|
-
teamId?: string;
|
|
34
|
-
startedAt: string;
|
|
35
|
-
endedAt?: string;
|
|
36
|
-
status: "running" | "waiting_for_approval" | "success" | "error" | "canceled";
|
|
37
|
-
/** Optional high-level summary */
|
|
38
|
-
summary?: string;
|
|
39
|
-
nodes?: WorkflowRunNodeResultV1[];
|
|
40
|
-
approval?: WorkflowRunApprovalV1;
|
|
41
|
-
meta?: Record<string, unknown>;
|
|
42
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { getTeamWorkspaceDir } from "@/lib/paths";
|
|
4
|
-
import { readdirFiles } from "@/lib/workflows/readdir";
|
|
5
|
-
import type { WorkflowFileV1 } from "@/lib/workflows/types";
|
|
6
|
-
|
|
7
|
-
const WORKFLOWS_DIR = path.join("shared-context", "workflows");
|
|
8
|
-
|
|
9
|
-
export function workflowFileName(workflowId: string) {
|
|
10
|
-
return `${workflowId}.workflow.json`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function assertSafeWorkflowId(workflowId: string) {
|
|
14
|
-
const id = String(workflowId ?? "").trim();
|
|
15
|
-
if (!id) throw new Error("workflow id is required");
|
|
16
|
-
if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(id)) {
|
|
17
|
-
throw new Error(
|
|
18
|
-
"Invalid workflow id. Use lowercase letters, numbers, and dashes (max 63 chars), e.g. marketing-cadence-v1"
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
return id;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function getTeamWorkflowsDir(teamId: string) {
|
|
25
|
-
const teamDir = await getTeamWorkspaceDir(teamId);
|
|
26
|
-
return path.join(teamDir, WORKFLOWS_DIR);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function listWorkflows(teamId: string) {
|
|
30
|
-
const dir = await getTeamWorkflowsDir(teamId);
|
|
31
|
-
return readdirFiles(dir, ".workflow.json");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function readWorkflow(teamId: string, workflowId: string) {
|
|
35
|
-
const id = assertSafeWorkflowId(workflowId);
|
|
36
|
-
const dir = await getTeamWorkflowsDir(teamId);
|
|
37
|
-
const p = path.join(dir, workflowFileName(id));
|
|
38
|
-
const raw = await fs.readFile(p, "utf8");
|
|
39
|
-
const parsed = JSON.parse(raw) as WorkflowFileV1;
|
|
40
|
-
return { ok: true as const, path: p, workflow: parsed };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function writeWorkflow(teamId: string, workflow: WorkflowFileV1) {
|
|
44
|
-
const id = assertSafeWorkflowId(workflow.id);
|
|
45
|
-
const dir = await getTeamWorkflowsDir(teamId);
|
|
46
|
-
await fs.mkdir(dir, { recursive: true });
|
|
47
|
-
const p = path.join(dir, workflowFileName(id));
|
|
48
|
-
const toWrite: WorkflowFileV1 = {
|
|
49
|
-
...workflow,
|
|
50
|
-
schema: "clawkitchen.workflow.v1",
|
|
51
|
-
id,
|
|
52
|
-
};
|
|
53
|
-
await fs.writeFile(p, JSON.stringify(toWrite, null, 2) + "\n", "utf8");
|
|
54
|
-
return { ok: true as const, path: p };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export async function deleteWorkflow(teamId: string, workflowId: string) {
|
|
58
|
-
const id = assertSafeWorkflowId(workflowId);
|
|
59
|
-
const dir = await getTeamWorkflowsDir(teamId);
|
|
60
|
-
const p = path.join(dir, workflowFileName(id));
|
|
61
|
-
try {
|
|
62
|
-
await fs.unlink(p);
|
|
63
|
-
} catch (err: unknown) {
|
|
64
|
-
if (err && typeof err === "object" && (err as { code?: unknown }).code === "ENOENT") {
|
|
65
|
-
return { ok: true as const, path: p, existed: false as const };
|
|
66
|
-
}
|
|
67
|
-
throw err;
|
|
68
|
-
}
|
|
69
|
-
return { ok: true as const, path: p, existed: true as const };
|
|
70
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { marketingCadenceWorkflowV1 } from "@/lib/workflows/templates/marketing-cadence-v1";
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import type { WorkflowFileV1 } from "@/lib/workflows/types";
|
|
2
|
-
|
|
3
|
-
export function marketingCadenceWorkflowV1(opts?: { id?: string; approvalProvider?: string; approvalTarget?: string }): WorkflowFileV1 {
|
|
4
|
-
const id = String(opts?.id ?? "marketing-cadence-v1").trim() || "marketing-cadence-v1";
|
|
5
|
-
const approvalProvider = String(opts?.approvalProvider ?? "telegram").trim() || "telegram";
|
|
6
|
-
const approvalTarget = String(opts?.approvalTarget ?? "").trim();
|
|
7
|
-
|
|
8
|
-
return {
|
|
9
|
-
schema: "clawkitchen.workflow.v1",
|
|
10
|
-
id,
|
|
11
|
-
name: "Marketing Cadence (v1)",
|
|
12
|
-
version: 1,
|
|
13
|
-
timezone: "America/New_York",
|
|
14
|
-
triggers: [
|
|
15
|
-
{
|
|
16
|
-
kind: "cron",
|
|
17
|
-
id: "t-weekdays-9",
|
|
18
|
-
name: "Weekdays 09:00",
|
|
19
|
-
enabled: true,
|
|
20
|
-
expr: "0 9 * * 1-5",
|
|
21
|
-
tz: "America/New_York",
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
meta: {
|
|
25
|
-
templateId: "marketing-cadence-v1",
|
|
26
|
-
approvalProvider,
|
|
27
|
-
approvalTarget,
|
|
28
|
-
writeback: {
|
|
29
|
-
postLogPath: "shared-context/marketing/POST_LOG.md",
|
|
30
|
-
learningsJsonlPath: "shared-context/memory/marketing_learnings.jsonl",
|
|
31
|
-
},
|
|
32
|
-
platforms: ["x", "instagram", "tiktok", "youtube"],
|
|
33
|
-
},
|
|
34
|
-
nodes: [
|
|
35
|
-
{ id: "start", type: "start", name: "Start", x: 60, y: 120, config: {} },
|
|
36
|
-
{
|
|
37
|
-
id: "research",
|
|
38
|
-
type: "llm",
|
|
39
|
-
name: "Research + idea",
|
|
40
|
-
x: 300,
|
|
41
|
-
y: 80,
|
|
42
|
-
config: {
|
|
43
|
-
agentId: "marketing-research",
|
|
44
|
-
promptTemplate:
|
|
45
|
-
"Do competitive + trend research. Produce: 5 angles + supporting bullets. Output JSON: {angles:[...], sources:[...]}" as string,
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
id: "draft_assets",
|
|
50
|
-
type: "llm",
|
|
51
|
-
name: "Draft platform assets",
|
|
52
|
-
x: 560,
|
|
53
|
-
y: 80,
|
|
54
|
-
config: {
|
|
55
|
-
agentId: "marketing-writer",
|
|
56
|
-
promptTemplate:
|
|
57
|
-
"Using the research output, draft platform-specific variants for X/Instagram/TikTok/YouTube. Output JSON: {platforms:{x:{hook,body},instagram:{hook,body,assetNotes},tiktok:{hook,script,assetNotes},youtube:{hook,script,assetNotes}}}" as string,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
id: "qc_brand",
|
|
62
|
-
type: "llm",
|
|
63
|
-
name: "QC / brand consistency",
|
|
64
|
-
x: 820,
|
|
65
|
-
y: 80,
|
|
66
|
-
config: {
|
|
67
|
-
agentId: "brand-qc",
|
|
68
|
-
promptTemplate:
|
|
69
|
-
"Review drafts for consistency. Apply corrections. Ensure: mention ClawRecipes before OpenClaw; no posting without approval. Output JSON: {platforms:{...}, notes:[...]}" as string,
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
id: "approval",
|
|
74
|
-
type: "human_approval",
|
|
75
|
-
name: "Human approval",
|
|
76
|
-
x: 1080,
|
|
77
|
-
y: 80,
|
|
78
|
-
config: {
|
|
79
|
-
provider: approvalProvider,
|
|
80
|
-
target: approvalTarget || "(set in UI)",
|
|
81
|
-
messageTemplate:
|
|
82
|
-
"{{workflow.name}} — Approval needed\nRun: {{run.id}}\n\n{{packet.note}}" as string,
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: "post_to_platforms",
|
|
87
|
-
type: "tool",
|
|
88
|
-
name: "Post (after approval)",
|
|
89
|
-
x: 1340,
|
|
90
|
-
y: 80,
|
|
91
|
-
config: {
|
|
92
|
-
tool: "marketing.post_all",
|
|
93
|
-
args: {
|
|
94
|
-
platforms: ["x", "instagram", "tiktok", "youtube"],
|
|
95
|
-
draftsFromNode: "qc_brand",
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
id: "write_post_log",
|
|
101
|
-
type: "tool",
|
|
102
|
-
name: "Append POST_LOG.md",
|
|
103
|
-
x: 1600,
|
|
104
|
-
y: 60,
|
|
105
|
-
config: {
|
|
106
|
-
tool: "fs.append",
|
|
107
|
-
args: {
|
|
108
|
-
path: "shared-context/marketing/POST_LOG.md",
|
|
109
|
-
content: "- {{date}} {{platforms}} posted. Run={{run.id}}\\n" as string,
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
id: "write_learnings",
|
|
115
|
-
type: "tool",
|
|
116
|
-
name: "Append marketing_learnings.jsonl",
|
|
117
|
-
x: 1600,
|
|
118
|
-
y: 140,
|
|
119
|
-
config: {
|
|
120
|
-
tool: "fs.append",
|
|
121
|
-
args: {
|
|
122
|
-
path: "shared-context/memory/marketing_learnings.jsonl",
|
|
123
|
-
content:
|
|
124
|
-
"{\"ts\":\"{{date}}\",\"runId\":\"{{run.id}}\",\"notes\":{{qc_brand.notes_json}}}\\n" as string,
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
{ id: "end", type: "end", name: "End", x: 1860, y: 120, config: {} },
|
|
129
|
-
],
|
|
130
|
-
edges: [
|
|
131
|
-
{ id: "e-start-research", from: "start", to: "research" },
|
|
132
|
-
{ id: "e-research-draft", from: "research", to: "draft_assets" },
|
|
133
|
-
{ id: "e-draft-qc", from: "draft_assets", to: "qc_brand" },
|
|
134
|
-
{ id: "e-qc-approval", from: "qc_brand", to: "approval" },
|
|
135
|
-
{ id: "e-approval-post", from: "approval", to: "post_to_platforms" },
|
|
136
|
-
{ id: "e-post-log", from: "post_to_platforms", to: "write_post_log" },
|
|
137
|
-
{ id: "e-post-learnings", from: "post_to_platforms", to: "write_learnings" },
|
|
138
|
-
{ id: "e-log-end", from: "write_post_log", to: "end" },
|
|
139
|
-
{ id: "e-learnings-end", from: "write_learnings", to: "end" },
|
|
140
|
-
],
|
|
141
|
-
};
|
|
142
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
export type WorkflowTriggerCronV1 = {
|
|
2
|
-
kind: "cron";
|
|
3
|
-
id: string;
|
|
4
|
-
name?: string;
|
|
5
|
-
enabled?: boolean;
|
|
6
|
-
/** Standard 5-field cron expression */
|
|
7
|
-
expr: string;
|
|
8
|
-
/** IANA timezone, e.g. America/New_York */
|
|
9
|
-
tz?: string;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export type WorkflowNodeV1 = {
|
|
13
|
-
id: string;
|
|
14
|
-
type:
|
|
15
|
-
| "start"
|
|
16
|
-
| "end"
|
|
17
|
-
| "llm"
|
|
18
|
-
| "tool"
|
|
19
|
-
| "condition"
|
|
20
|
-
| "delay"
|
|
21
|
-
| "human_approval";
|
|
22
|
-
name?: string;
|
|
23
|
-
/** UI layout hints (optional) */
|
|
24
|
-
x?: number;
|
|
25
|
-
y?: number;
|
|
26
|
-
/** Node-type-specific config */
|
|
27
|
-
config?: Record<string, unknown>;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export type WorkflowEdgeV1 = {
|
|
31
|
-
id: string;
|
|
32
|
-
from: string;
|
|
33
|
-
to: string;
|
|
34
|
-
/** Optional edge label/condition */
|
|
35
|
-
label?: string;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export type WorkflowFileV1 = {
|
|
39
|
-
schema: "clawkitchen.workflow.v1";
|
|
40
|
-
id: string;
|
|
41
|
-
name: string;
|
|
42
|
-
version?: number;
|
|
43
|
-
timezone?: string;
|
|
44
|
-
triggers?: WorkflowTriggerCronV1[];
|
|
45
|
-
nodes: WorkflowNodeV1[];
|
|
46
|
-
edges: WorkflowEdgeV1[];
|
|
47
|
-
meta?: Record<string, unknown>;
|
|
48
|
-
};
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import type { WorkflowEdgeV1, WorkflowFileV1, WorkflowNodeV1, WorkflowTriggerCronV1 } from "@/lib/workflows/types";
|
|
2
|
-
|
|
3
|
-
export type WorkflowValidationResult = {
|
|
4
|
-
errors: string[];
|
|
5
|
-
warnings: string[];
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
function isFiveFieldCron(expr: string) {
|
|
9
|
-
const parts = String(expr || "")
|
|
10
|
-
.trim()
|
|
11
|
-
.split(/\s+/)
|
|
12
|
-
.filter(Boolean);
|
|
13
|
-
return parts.length === 5;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function uniqCount(values: string[]) {
|
|
17
|
-
const set = new Set<string>();
|
|
18
|
-
for (const v of values) set.add(v);
|
|
19
|
-
return set.size;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function validateWorkflowFileV1(wf: WorkflowFileV1): WorkflowValidationResult {
|
|
23
|
-
const errors: string[] = [];
|
|
24
|
-
const warnings: string[] = [];
|
|
25
|
-
|
|
26
|
-
if (wf.schema !== "clawkitchen.workflow.v1") errors.push(`schema must be clawkitchen.workflow.v1 (got ${String(wf.schema)})`);
|
|
27
|
-
if (!String(wf.id || "").trim()) errors.push("id is required");
|
|
28
|
-
if (!String(wf.name || "").trim()) errors.push("name is required");
|
|
29
|
-
|
|
30
|
-
const nodes: WorkflowNodeV1[] = Array.isArray(wf.nodes) ? wf.nodes : [];
|
|
31
|
-
const edges: WorkflowEdgeV1[] = Array.isArray(wf.edges) ? wf.edges : [];
|
|
32
|
-
const triggers: WorkflowTriggerCronV1[] = Array.isArray(wf.triggers) ? wf.triggers : [];
|
|
33
|
-
|
|
34
|
-
const nodeIds = nodes.map((n) => String(n?.id ?? "").trim()).filter(Boolean);
|
|
35
|
-
if (nodeIds.length !== nodes.length) errors.push("all nodes must have a non-empty id");
|
|
36
|
-
if (uniqCount(nodeIds) !== nodeIds.length) errors.push("node ids must be unique");
|
|
37
|
-
|
|
38
|
-
const edgeIds = edges.map((e) => String(e?.id ?? "").trim()).filter(Boolean);
|
|
39
|
-
if (edgeIds.length !== edges.length) errors.push("all edges must have a non-empty id");
|
|
40
|
-
if (uniqCount(edgeIds) !== edgeIds.length) errors.push("edge ids must be unique");
|
|
41
|
-
|
|
42
|
-
const nodeIdSet = new Set(nodeIds);
|
|
43
|
-
for (const e of edges) {
|
|
44
|
-
const from = String(e?.from ?? "").trim();
|
|
45
|
-
const to = String(e?.to ?? "").trim();
|
|
46
|
-
if (!from || !to) {
|
|
47
|
-
errors.push(`edge ${String(e?.id ?? "(missing id)")} must have from/to`);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
if (!nodeIdSet.has(from)) errors.push(`edge ${String(e.id)} references missing from node: ${from}`);
|
|
51
|
-
if (!nodeIdSet.has(to)) errors.push(`edge ${String(e.id)} references missing to node: ${to}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const starts = nodes.filter((n) => n.type === "start");
|
|
55
|
-
const ends = nodes.filter((n) => n.type === "end");
|
|
56
|
-
if (!starts.length) warnings.push("no start node found");
|
|
57
|
-
if (starts.length > 1) warnings.push("multiple start nodes found (MVP supports this, but execution semantics may be ambiguous)");
|
|
58
|
-
if (!ends.length) warnings.push("no end node found");
|
|
59
|
-
|
|
60
|
-
for (const t of triggers) {
|
|
61
|
-
if (t.kind === "cron") {
|
|
62
|
-
if (!String(t.id || "").trim()) errors.push("cron trigger missing id");
|
|
63
|
-
if (!String(t.expr || "").trim()) errors.push(`cron trigger ${String(t.id || "(missing id)")} missing expr`);
|
|
64
|
-
else if (!isFiveFieldCron(t.expr)) warnings.push(`cron trigger ${String(t.id)} expr is not 5-field: ${String(t.expr)}`);
|
|
65
|
-
const tz = t.tz ? String(t.tz).trim() : "";
|
|
66
|
-
// NOTE: We commonly use "UTC" as a default, and it is widely accepted even though it isn't in the
|
|
67
|
-
// classic Region/City IANA format. Treat it as valid to avoid noisy validation warnings.
|
|
68
|
-
if (tz && tz !== "UTC" && !tz.includes("/")) {
|
|
69
|
-
warnings.push(`cron trigger ${String(t.id)} tz doesn't look like an IANA timezone: ${String(t.tz)}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Human approval node sanity checks (MVP)
|
|
75
|
-
const meta = wf.meta && typeof wf.meta === "object" && !Array.isArray(wf.meta) ? (wf.meta as Record<string, unknown>) : {};
|
|
76
|
-
const defaultTarget = String(meta.approvalTarget ?? "").trim();
|
|
77
|
-
for (const n of nodes) {
|
|
78
|
-
if (n.type !== "human_approval") continue;
|
|
79
|
-
const cfg = n.config && typeof n.config === "object" && !Array.isArray(n.config) ? (n.config as Record<string, unknown>) : {};
|
|
80
|
-
const target = String(cfg.target ?? cfg.chatId ?? "").trim();
|
|
81
|
-
const provider = String(cfg.provider ?? cfg.channel ?? "").trim();
|
|
82
|
-
|
|
83
|
-
if (!target && !defaultTarget) {
|
|
84
|
-
warnings.push(`human_approval node ${String(n.id)} has no target (set node.config.target or workflow.meta.approvalTarget)`);
|
|
85
|
-
}
|
|
86
|
-
if (target && !provider && !String(meta.approvalProvider ?? "").trim()) {
|
|
87
|
-
warnings.push(`human_approval node ${String(n.id)} has a target but no provider (set node.config.provider or workflow.meta.approvalProvider)`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return { errors, warnings };
|
|
92
|
-
}
|
package/src/proxy.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
|
|
3
|
-
// Kitchen is a local operator console whose data can change outside Next.js (CLI actions,
|
|
4
|
-
// config edits, gateway restarts). We should never serve cached HTML/data for app routes.
|
|
5
|
-
//
|
|
6
|
-
// NOTE: In Next.js 16, middleware has been renamed to `proxy`.
|
|
7
|
-
export function proxy() {
|
|
8
|
-
const res = NextResponse.next();
|
|
9
|
-
|
|
10
|
-
// Prevent browser/proxy caching of HTML and route responses.
|
|
11
|
-
// (Static assets under /_next/static remain cacheable and are excluded by matcher below.)
|
|
12
|
-
res.headers.set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
|
|
13
|
-
res.headers.set("Pragma", "no-cache");
|
|
14
|
-
res.headers.set("Expires", "0");
|
|
15
|
-
|
|
16
|
-
// Some proxies/CDNs respect this.
|
|
17
|
-
res.headers.set("Surrogate-Control", "no-store");
|
|
18
|
-
|
|
19
|
-
// Vary on auth-related headers to avoid cross-user cache confusion if a proxy exists.
|
|
20
|
-
res.headers.set("Vary", "Authorization, Cookie");
|
|
21
|
-
|
|
22
|
-
return res;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const config = {
|
|
26
|
-
// Exclude Next static assets and favicon.
|
|
27
|
-
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
|
|
28
|
-
};
|
|
File without changes
|
/package/.next/static/{z86RoqzzXXrWnpi229zP6 → Jrrrm9HH5bKkSrQhe1j93}/_clientMiddlewareManifest.json
RENAMED
|
File without changes
|
|
File without changes
|