@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,94 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { NextResponse } from "next/server";
|
|
4
|
-
import { getTeamWorkspaceDir, getTicketByIdOrNumber, listTickets, stageDir, type TicketStage } from "@/lib/tickets";
|
|
5
|
-
|
|
6
|
-
type TicketFlowConfig = {
|
|
7
|
-
laneByOwner?: Record<string, TicketStage>;
|
|
8
|
-
defaultLane?: TicketStage;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
async function loadTicketFlowConfig(teamDir: string): Promise<TicketFlowConfig | null> {
|
|
12
|
-
const p = path.join(teamDir, "shared-context", "ticket-flow.json");
|
|
13
|
-
try {
|
|
14
|
-
const raw = await fs.readFile(p, "utf8");
|
|
15
|
-
const parsed = JSON.parse(raw) as TicketFlowConfig;
|
|
16
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
17
|
-
return parsed;
|
|
18
|
-
} catch {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function desiredStageForAssignee(opts: {
|
|
24
|
-
teamDir: string;
|
|
25
|
-
assignee: string | null;
|
|
26
|
-
currentStage: TicketStage;
|
|
27
|
-
}): Promise<TicketStage> {
|
|
28
|
-
const config = await loadTicketFlowConfig(opts.teamDir);
|
|
29
|
-
if (!config) return opts.currentStage;
|
|
30
|
-
|
|
31
|
-
const key = (opts.assignee ?? "").trim();
|
|
32
|
-
if (key && config.laneByOwner && typeof config.laneByOwner[key] === "string") {
|
|
33
|
-
return config.laneByOwner[key] as TicketStage;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (config.defaultLane) return config.defaultLane;
|
|
37
|
-
return opts.currentStage;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function upsertField(md: string, field: string, value: string) {
|
|
41
|
-
const re = new RegExp(`^${field}:\\s*.*$`, "mi");
|
|
42
|
-
if (re.test(md)) return md.replace(re, `${field}: ${value}`);
|
|
43
|
-
|
|
44
|
-
// Insert after the first header line, or at top if no header.
|
|
45
|
-
const lines = md.split("\n");
|
|
46
|
-
const headerIdx = lines.findIndex((l) => l.startsWith("# "));
|
|
47
|
-
const insertAt = headerIdx >= 0 ? headerIdx + 1 : 0;
|
|
48
|
-
lines.splice(insertAt, 0, `${field}: ${value}`);
|
|
49
|
-
return lines.join("\n");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function ensureDir(p: string) {
|
|
53
|
-
await fs.mkdir(p, { recursive: true });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export async function POST(req: Request) {
|
|
57
|
-
const body = (await req.json().catch(() => null)) as null | {
|
|
58
|
-
ticket: string;
|
|
59
|
-
assignee: string;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
if (!body?.ticket || !body?.assignee) {
|
|
63
|
-
return NextResponse.json({ error: "Missing ticket or assignee" }, { status: 400 });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const ticket = await getTicketByIdOrNumber(body.ticket);
|
|
67
|
-
if (!ticket) {
|
|
68
|
-
return NextResponse.json({ error: "Ticket not found" }, { status: 404 });
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const assignee = body.assignee.trim();
|
|
72
|
-
const nextStage = await desiredStageForAssignee({ teamDir: getTeamWorkspaceDir(), assignee, currentStage: ticket.stage });
|
|
73
|
-
|
|
74
|
-
const currentMd = await fs.readFile(ticket.file, "utf8");
|
|
75
|
-
let updatedMd = upsertField(currentMd, "Owner", assignee);
|
|
76
|
-
// Keep Status in sync with lane.
|
|
77
|
-
updatedMd = upsertField(updatedMd, "Status", nextStage);
|
|
78
|
-
|
|
79
|
-
const filename = path.basename(ticket.file);
|
|
80
|
-
const nextPath = path.join(stageDir(nextStage), filename);
|
|
81
|
-
|
|
82
|
-
await ensureDir(stageDir(nextStage));
|
|
83
|
-
|
|
84
|
-
if (ticket.file !== nextPath) {
|
|
85
|
-
await fs.rename(ticket.file, nextPath);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
await fs.writeFile(nextPath, updatedMd, "utf8");
|
|
89
|
-
|
|
90
|
-
// Assignment stubs are deprecated; do not create/update work/assignments/*.md.
|
|
91
|
-
|
|
92
|
-
const refreshed = (await listTickets()).find((t) => t.number === ticket.number);
|
|
93
|
-
return NextResponse.json({ ok: true, ticket: refreshed ?? null });
|
|
94
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { NextResponse } from "next/server";
|
|
4
|
-
|
|
5
|
-
import { getTeamWorkspaceDir } from "@/lib/tickets";
|
|
6
|
-
|
|
7
|
-
export async function GET() {
|
|
8
|
-
// MVP: in development-team, treat role directories as available agentIds.
|
|
9
|
-
// Future: should come from OpenClaw team config (bindings/agents) and be team-scoped.
|
|
10
|
-
const rolesDir = path.join(getTeamWorkspaceDir(), "roles");
|
|
11
|
-
|
|
12
|
-
let entries: string[] = [];
|
|
13
|
-
try {
|
|
14
|
-
entries = await fs.readdir(rolesDir);
|
|
15
|
-
} catch {
|
|
16
|
-
entries = [];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const assignees = entries
|
|
20
|
-
.filter((e) => !e.startsWith("."))
|
|
21
|
-
.sort();
|
|
22
|
-
|
|
23
|
-
return NextResponse.json({ assignees });
|
|
24
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
|
|
3
|
-
import { NextResponse } from "next/server";
|
|
4
|
-
|
|
5
|
-
import { runOpenClaw } from "@/lib/openclaw";
|
|
6
|
-
import { getTicketMarkdown } from "@/lib/tickets";
|
|
7
|
-
|
|
8
|
-
function todayUtc() {
|
|
9
|
-
return new Date().toISOString().slice(0, 10);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async function appendDoneAuditComment(ticketIdOrNumber: string) {
|
|
13
|
-
const hit = await getTicketMarkdown("development-team", ticketIdOrNumber);
|
|
14
|
-
if (!hit) return;
|
|
15
|
-
|
|
16
|
-
const line = `- ${todayUtc()} (ClawKitchen UI): Marked done from ClawKitchen UI.`;
|
|
17
|
-
if (hit.markdown.includes(line)) return;
|
|
18
|
-
|
|
19
|
-
const hasComments = /\n## Comments\n/i.test(hit.markdown) || /^## Comments\n/im.test(hit.markdown);
|
|
20
|
-
|
|
21
|
-
let next = hit.markdown;
|
|
22
|
-
if (!hasComments) {
|
|
23
|
-
next = next.replace(/\s*$/, "\n\n## Comments\n");
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Append at end; this keeps the operation simple and avoids brittle section parsing.
|
|
27
|
-
next = next.replace(/\s*$/, "\n" + line + "\n");
|
|
28
|
-
|
|
29
|
-
await fs.writeFile(hit.file, next, "utf8");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function POST(req: Request) {
|
|
33
|
-
try {
|
|
34
|
-
const body = await req.json();
|
|
35
|
-
const ticket = String(body.ticket ?? "").trim();
|
|
36
|
-
const to = String(body.to ?? "").trim();
|
|
37
|
-
|
|
38
|
-
if (!ticket) {
|
|
39
|
-
return NextResponse.json({ ok: false, error: "Missing ticket" }, { status: 400 });
|
|
40
|
-
}
|
|
41
|
-
if (!to || !["backlog", "in-progress", "testing", "done"].includes(to)) {
|
|
42
|
-
return NextResponse.json({ ok: false, error: "Invalid destination stage" }, { status: 400 });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const args = [
|
|
46
|
-
"recipes",
|
|
47
|
-
"move-ticket",
|
|
48
|
-
"--team-id",
|
|
49
|
-
"development-team",
|
|
50
|
-
"--ticket",
|
|
51
|
-
ticket,
|
|
52
|
-
"--to",
|
|
53
|
-
to,
|
|
54
|
-
"--yes",
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
const res = await runOpenClaw(args);
|
|
58
|
-
if (!res.ok) throw new Error(res.stderr || `openclaw exit ${res.exitCode}`);
|
|
59
|
-
|
|
60
|
-
if (to === "done") {
|
|
61
|
-
await appendDoneAuditComment(ticket);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return NextResponse.json({ ok: true });
|
|
65
|
-
} catch (err: unknown) {
|
|
66
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
67
|
-
return NextResponse.json({ ok: false, error: message }, { status: 500 });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
4
|
-
import { errorMessage } from "@/lib/errors";
|
|
5
|
-
import { fetchJson } from "@/lib/fetch-json";
|
|
6
|
-
import { isRecord } from "@/lib/type-guards";
|
|
7
|
-
|
|
8
|
-
type ChannelConfig = Record<string, unknown>;
|
|
9
|
-
|
|
10
|
-
type ChannelsResponse = {
|
|
11
|
-
ok: boolean;
|
|
12
|
-
channels?: Record<string, unknown>;
|
|
13
|
-
error?: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
function Button({
|
|
17
|
-
children,
|
|
18
|
-
onClick,
|
|
19
|
-
kind,
|
|
20
|
-
disabled,
|
|
21
|
-
}: {
|
|
22
|
-
children: React.ReactNode;
|
|
23
|
-
onClick: () => void;
|
|
24
|
-
kind?: "primary" | "danger";
|
|
25
|
-
disabled?: boolean;
|
|
26
|
-
}) {
|
|
27
|
-
let base = "rounded-[var(--ck-radius-sm)] px-3 py-2 text-sm font-medium transition disabled:opacity-50 ";
|
|
28
|
-
if (kind === "primary") base += "bg-[var(--ck-accent-red)] text-white";
|
|
29
|
-
else if (kind === "danger")
|
|
30
|
-
base +=
|
|
31
|
-
"border border-[color:rgba(255,59,48,0.45)] bg-[color:rgba(255,59,48,0.08)] text-[color:var(--ck-accent-red)] hover:bg-[color:rgba(255,59,48,0.12)]";
|
|
32
|
-
else base += "border border-[color:var(--ck-border-subtle)] hover:bg-[color:var(--ck-bg-glass)]";
|
|
33
|
-
return (
|
|
34
|
-
<button className={base} onClick={onClick} disabled={disabled}>
|
|
35
|
-
{children}
|
|
36
|
-
</button>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export default function ChannelsClient() {
|
|
41
|
-
const [channels, setChannels] = useState<Record<string, unknown>>({});
|
|
42
|
-
const [loading, setLoading] = useState(true);
|
|
43
|
-
const [error, setError] = useState<string | null>(null);
|
|
44
|
-
|
|
45
|
-
const [provider, setProvider] = useState<string>("telegram");
|
|
46
|
-
const [configJson, setConfigJson] = useState<string>("{\n \"enabled\": true\n}\n");
|
|
47
|
-
const [saving, setSaving] = useState(false);
|
|
48
|
-
|
|
49
|
-
async function fetchBindings(): Promise<{ ok: true; channels: Record<string, unknown> } | { ok: false; error: string }> {
|
|
50
|
-
try {
|
|
51
|
-
const data = await fetchJson<ChannelsResponse>("/api/channels/bindings", { cache: "no-store" });
|
|
52
|
-
const ch = isRecord(data.channels) ? data.channels : {};
|
|
53
|
-
return { ok: true, channels: ch };
|
|
54
|
-
} catch (e: unknown) {
|
|
55
|
-
return { ok: false, error: errorMessage(e) };
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const refresh = useCallback(async () => {
|
|
60
|
-
setLoading(true);
|
|
61
|
-
setError(null);
|
|
62
|
-
try {
|
|
63
|
-
const result = await fetchBindings();
|
|
64
|
-
if (!result.ok) {
|
|
65
|
-
setError(result.error);
|
|
66
|
-
setChannels({});
|
|
67
|
-
setLoading(false);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
setChannels(result.channels);
|
|
71
|
-
setLoading(false);
|
|
72
|
-
} catch (e: unknown) {
|
|
73
|
-
const msg = errorMessage(e);
|
|
74
|
-
setError(msg);
|
|
75
|
-
setChannels({});
|
|
76
|
-
setLoading(false);
|
|
77
|
-
}
|
|
78
|
-
}, []);
|
|
79
|
-
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
let cancelled = false;
|
|
82
|
-
(async () => {
|
|
83
|
-
await refresh();
|
|
84
|
-
if (cancelled) return;
|
|
85
|
-
})();
|
|
86
|
-
return () => {
|
|
87
|
-
cancelled = true;
|
|
88
|
-
};
|
|
89
|
-
}, [refresh]);
|
|
90
|
-
|
|
91
|
-
const providers = useMemo(() => {
|
|
92
|
-
const keys = Object.keys(channels);
|
|
93
|
-
keys.sort();
|
|
94
|
-
return keys.filter((k) => channels[k] != null);
|
|
95
|
-
}, [channels]);
|
|
96
|
-
|
|
97
|
-
function selectProvider(p: string) {
|
|
98
|
-
setProvider(p);
|
|
99
|
-
const cfg = channels[p];
|
|
100
|
-
setConfigJson(JSON.stringify(cfg ?? {}, null, 2) + "\n");
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async function mutate(
|
|
104
|
-
method: "PUT" | "DELETE",
|
|
105
|
-
body: { provider: string; config?: Record<string, unknown> }
|
|
106
|
-
): Promise<{ ok: true } | { ok: false; error: string }> {
|
|
107
|
-
try {
|
|
108
|
-
const data = await fetchJson<ChannelsResponse>("/api/channels/bindings", {
|
|
109
|
-
method,
|
|
110
|
-
headers: { "content-type": "application/json" },
|
|
111
|
-
body: JSON.stringify(body),
|
|
112
|
-
});
|
|
113
|
-
if (!data?.ok) return { ok: false, error: String(data?.error ?? `Failed to ${method === "PUT" ? "save" : "delete"}`) };
|
|
114
|
-
return { ok: true };
|
|
115
|
-
} catch (e: unknown) {
|
|
116
|
-
return { ok: false, error: errorMessage(e) };
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async function upsert() {
|
|
121
|
-
setSaving(true);
|
|
122
|
-
setError(null);
|
|
123
|
-
|
|
124
|
-
let parsed: unknown;
|
|
125
|
-
try {
|
|
126
|
-
parsed = JSON.parse(configJson);
|
|
127
|
-
} catch {
|
|
128
|
-
setError("Config must be valid JSON");
|
|
129
|
-
setSaving(false);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
if (!isRecord(parsed)) {
|
|
133
|
-
setError("Config must be a JSON object");
|
|
134
|
-
setSaving(false);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const result = await mutate("PUT", { provider: provider.trim(), config: parsed });
|
|
139
|
-
if (!result.ok) {
|
|
140
|
-
setError(result.error);
|
|
141
|
-
setSaving(false);
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
await refresh();
|
|
145
|
-
setSaving(false);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async function remove(p: string) {
|
|
149
|
-
if (!window.confirm(`Delete channel binding "${p}"?`)) return;
|
|
150
|
-
|
|
151
|
-
setSaving(true);
|
|
152
|
-
setError(null);
|
|
153
|
-
|
|
154
|
-
const result = await mutate("DELETE", { provider: p });
|
|
155
|
-
if (!result.ok) {
|
|
156
|
-
setError(result.error);
|
|
157
|
-
setSaving(false);
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
await refresh();
|
|
161
|
-
setSaving(false);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function addBinding() {
|
|
165
|
-
const p = window.prompt("Provider id (e.g. telegram)", "telegram");
|
|
166
|
-
const next = String(p ?? "").trim();
|
|
167
|
-
if (!next) return;
|
|
168
|
-
setProvider(next);
|
|
169
|
-
setConfigJson("{\n \"enabled\": true\n}\n");
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const selectedConfig = useMemo(() => {
|
|
173
|
-
const v = channels[provider];
|
|
174
|
-
return isRecord(v) ? (v as ChannelConfig) : null;
|
|
175
|
-
}, [channels, provider]);
|
|
176
|
-
|
|
177
|
-
return (
|
|
178
|
-
<div className="space-y-6">
|
|
179
|
-
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
180
|
-
<div>
|
|
181
|
-
<h1 className="text-2xl font-semibold tracking-tight">Channels</h1>
|
|
182
|
-
<p className="mt-1 text-sm text-[color:var(--ck-text-secondary)]">
|
|
183
|
-
Source of truth: OpenClaw gateway config (patched via <code className="font-mono">gateway config.patch</code>).
|
|
184
|
-
Some changes may require a gateway restart depending on provider.
|
|
185
|
-
</p>
|
|
186
|
-
</div>
|
|
187
|
-
<div className="flex items-center gap-2">
|
|
188
|
-
<Button onClick={() => void refresh()} disabled={saving}>
|
|
189
|
-
Refresh
|
|
190
|
-
</Button>
|
|
191
|
-
<Button kind="primary" onClick={addBinding} disabled={saving}>
|
|
192
|
-
Add binding
|
|
193
|
-
</Button>
|
|
194
|
-
</div>
|
|
195
|
-
</div>
|
|
196
|
-
|
|
197
|
-
{error ? <div className="ck-glass p-4 text-sm text-red-300">{error}</div> : null}
|
|
198
|
-
|
|
199
|
-
<div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
|
|
200
|
-
<div className="ck-glass p-4">
|
|
201
|
-
<div className="text-sm font-medium">Bindings</div>
|
|
202
|
-
{loading && <div className="mt-3 text-sm text-[color:var(--ck-text-secondary)]">Loading…</div>}
|
|
203
|
-
{!loading && providers.length === 0 && (
|
|
204
|
-
<div className="mt-3 text-sm text-[color:var(--ck-text-secondary)]">No bindings configured.</div>
|
|
205
|
-
)}
|
|
206
|
-
{!loading && providers.length > 0 && (
|
|
207
|
-
<div className="mt-3 space-y-2">
|
|
208
|
-
{providers.map((p) => (
|
|
209
|
-
<button
|
|
210
|
-
key={p}
|
|
211
|
-
className={
|
|
212
|
-
"flex w-full items-center justify-between rounded-[var(--ck-radius-sm)] border px-3 py-2 text-left text-sm " +
|
|
213
|
-
(p === provider
|
|
214
|
-
? "border-[var(--ck-accent-red)] bg-[color:var(--ck-bg-glass)]"
|
|
215
|
-
: "border-[color:var(--ck-border-subtle)] hover:bg-[color:var(--ck-bg-glass)]")
|
|
216
|
-
}
|
|
217
|
-
onClick={() => selectProvider(p)}
|
|
218
|
-
>
|
|
219
|
-
<span className="font-mono">{p}</span>
|
|
220
|
-
<span className="text-xs text-[color:var(--ck-text-tertiary)]">edit</span>
|
|
221
|
-
</button>
|
|
222
|
-
))}
|
|
223
|
-
</div>
|
|
224
|
-
)}
|
|
225
|
-
</div>
|
|
226
|
-
|
|
227
|
-
<div className="ck-glass p-4 lg:col-span-2">
|
|
228
|
-
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
229
|
-
<div>
|
|
230
|
-
<div className="text-sm font-medium">Edit</div>
|
|
231
|
-
<div className="mt-1 text-xs text-[color:var(--ck-text-tertiary)]">
|
|
232
|
-
Provider: <code className="font-mono">{provider}</code>
|
|
233
|
-
</div>
|
|
234
|
-
</div>
|
|
235
|
-
<div className="flex items-center gap-2">
|
|
236
|
-
<Button kind="danger" onClick={() => void remove(provider)} disabled={saving}>
|
|
237
|
-
Delete
|
|
238
|
-
</Button>
|
|
239
|
-
<Button kind="primary" onClick={() => void upsert()} disabled={saving}>
|
|
240
|
-
{saving ? "Saving…" : "Save"}
|
|
241
|
-
</Button>
|
|
242
|
-
</div>
|
|
243
|
-
</div>
|
|
244
|
-
|
|
245
|
-
<div className="mt-4">
|
|
246
|
-
<div className="text-xs text-[color:var(--ck-text-tertiary)]">Config (JSON)</div>
|
|
247
|
-
<textarea
|
|
248
|
-
value={configJson}
|
|
249
|
-
onChange={(e) => setConfigJson(e.target.value)}
|
|
250
|
-
className="mt-2 h-[420px] w-full rounded-[var(--ck-radius-sm)] border border-[color:var(--ck-border-subtle)] bg-transparent px-3 py-2 font-mono text-sm"
|
|
251
|
-
placeholder={"{\n \"enabled\": true\n}"}
|
|
252
|
-
/>
|
|
253
|
-
<div className="mt-2 text-xs text-[color:var(--ck-text-tertiary)]">
|
|
254
|
-
Validation:
|
|
255
|
-
<ul className="list-disc pl-5">
|
|
256
|
-
<li>Telegram requires <code className="font-mono">botToken</code>.</li>
|
|
257
|
-
<li>Other providers can be edited as raw JSON in v1.</li>
|
|
258
|
-
</ul>
|
|
259
|
-
</div>
|
|
260
|
-
|
|
261
|
-
{selectedConfig ? (
|
|
262
|
-
<div className="mt-3 text-xs text-[color:var(--ck-text-tertiary)]">
|
|
263
|
-
Current keys: <code className="font-mono">{Object.keys(selectedConfig).join(", ") || "(none)"}</code>
|
|
264
|
-
</div>
|
|
265
|
-
) : null}
|
|
266
|
-
</div>
|
|
267
|
-
</div>
|
|
268
|
-
</div>
|
|
269
|
-
</div>
|
|
270
|
-
);
|
|
271
|
-
}
|