@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
package/src/lib/gateway.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { readOpenClawConfig } from "@/lib/paths";
|
|
2
|
-
|
|
3
|
-
type ToolsInvokeRequest = {
|
|
4
|
-
tool: string;
|
|
5
|
-
action?: string;
|
|
6
|
-
args?: Record<string, unknown>;
|
|
7
|
-
sessionKey?: string;
|
|
8
|
-
dryRun?: boolean;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type ToolsInvokeResponse = {
|
|
12
|
-
ok: boolean;
|
|
13
|
-
result?: unknown;
|
|
14
|
-
error?: { message?: string } | string;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
type GatewayConfigGetResult = {
|
|
18
|
-
path: string;
|
|
19
|
-
exists: boolean;
|
|
20
|
-
raw: string;
|
|
21
|
-
hash: string;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
type ToolTextEnvelope = {
|
|
25
|
-
ok: boolean;
|
|
26
|
-
result: GatewayConfigGetResult;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
async function getGatewayBaseUrlAndToken() {
|
|
30
|
-
// ClawKitchen runs in-process with the OpenClaw Gateway (as a plugin), so we can read
|
|
31
|
-
// the gateway port/token from the loaded config.
|
|
32
|
-
const cfg = await readOpenClawConfig();
|
|
33
|
-
const port = cfg.gateway?.port ?? 18789;
|
|
34
|
-
const token = cfg.gateway?.auth?.token;
|
|
35
|
-
if (!token) throw new Error("Missing gateway token (gateway.auth.token in ~/.openclaw/openclaw.json)");
|
|
36
|
-
|
|
37
|
-
const baseUrl = `http://127.0.0.1:${port}`;
|
|
38
|
-
return { baseUrl, token };
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export async function toolsInvoke<T = unknown>(req: ToolsInvokeRequest): Promise<T> {
|
|
42
|
-
const { baseUrl, token } = await getGatewayBaseUrlAndToken();
|
|
43
|
-
|
|
44
|
-
const res = await fetch(`${baseUrl}/tools/invoke`, {
|
|
45
|
-
method: "POST",
|
|
46
|
-
headers: {
|
|
47
|
-
"content-type": "application/json",
|
|
48
|
-
authorization: `Bearer ${token}`,
|
|
49
|
-
},
|
|
50
|
-
body: JSON.stringify(req),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const json = (await res.json()) as ToolsInvokeResponse;
|
|
54
|
-
if (!res.ok || !json.ok) {
|
|
55
|
-
const msg =
|
|
56
|
-
(typeof json.error === "object" && json.error?.message) ||
|
|
57
|
-
(typeof json.error === "string" ? json.error : null) ||
|
|
58
|
-
`tools/invoke failed (${res.status})`;
|
|
59
|
-
throw new Error(msg);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return json.result as T;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function getContentText(content: Array<{ type: string; text?: string }> | undefined): string | undefined {
|
|
66
|
-
return content?.find((c) => c.type === "text")?.text;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export async function gatewayConfigGet(): Promise<{ raw: string; hash: string }> {
|
|
70
|
-
const toolResult = await toolsInvoke<{ content: Array<{ type: string; text?: string }> }>({
|
|
71
|
-
tool: "gateway",
|
|
72
|
-
args: { action: "config.get", raw: "{}" },
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const text = getContentText(toolResult?.content);
|
|
76
|
-
if (!text) throw new Error("gateway config.get: missing text payload");
|
|
77
|
-
|
|
78
|
-
const parsed = JSON.parse(text) as ToolTextEnvelope;
|
|
79
|
-
const raw = String(parsed?.result?.raw ?? "");
|
|
80
|
-
const hash = String(parsed?.result?.hash ?? "");
|
|
81
|
-
if (!raw) throw new Error("gateway config.get: missing result.raw");
|
|
82
|
-
if (!hash) throw new Error("gateway config.get: missing result.hash");
|
|
83
|
-
return { raw, hash };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export async function gatewayConfigPatch(patch: unknown, note?: string) {
|
|
87
|
-
const { hash } = await gatewayConfigGet();
|
|
88
|
-
const raw = JSON.stringify(patch, null, 2);
|
|
89
|
-
|
|
90
|
-
return toolsInvoke({
|
|
91
|
-
tool: "gateway",
|
|
92
|
-
args: {
|
|
93
|
-
action: "config.patch",
|
|
94
|
-
raw,
|
|
95
|
-
baseHash: hash,
|
|
96
|
-
note: note ?? "ClawKitchen settings update",
|
|
97
|
-
restartDelayMs: 1000,
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
}
|
package/src/lib/goal-promote.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { slugifyId } from "./slugify";
|
|
2
|
-
|
|
3
|
-
/** Slugify for file path parts (max 80 chars). */
|
|
4
|
-
export function slugifyFilePart(input: string): string {
|
|
5
|
-
return slugifyId(input, 80);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const WORKFLOW_MARKER = "<!-- goal-workflow -->";
|
|
9
|
-
|
|
10
|
-
export function ensureWorkflowInstructions(body: string): string {
|
|
11
|
-
if (body.includes(WORKFLOW_MARKER)) return body;
|
|
12
|
-
const snippet = [
|
|
13
|
-
"",
|
|
14
|
-
"## Workflow",
|
|
15
|
-
WORKFLOW_MARKER,
|
|
16
|
-
"- Use **Promote to inbox** to send this goal to the development-team inbox for scoping.",
|
|
17
|
-
"- When promoted, set goal status to **active**.",
|
|
18
|
-
"- Track implementation work via tickets (add links/IDs under a **Tickets** section in this goal).",
|
|
19
|
-
"- When development is complete (all associated tickets marked done), set goal status to **done**.",
|
|
20
|
-
"",
|
|
21
|
-
"## Tickets",
|
|
22
|
-
"- (add ticket links/ids)",
|
|
23
|
-
"",
|
|
24
|
-
].join("\n");
|
|
25
|
-
|
|
26
|
-
return (body ?? "").trim() + snippet;
|
|
27
|
-
}
|
package/src/lib/goals-client.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useMemo, useState } from "react";
|
|
4
|
-
|
|
5
|
-
/** Client-safe goal types and utils (no node deps). */
|
|
6
|
-
|
|
7
|
-
export type GoalStatus = "planned" | "active" | "done";
|
|
8
|
-
|
|
9
|
-
export type GoalFrontmatter = {
|
|
10
|
-
id: string;
|
|
11
|
-
title: string;
|
|
12
|
-
status: GoalStatus;
|
|
13
|
-
tags: string[];
|
|
14
|
-
teams: string[];
|
|
15
|
-
updatedAt: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/** Form state shape for GoalFormFields. */
|
|
19
|
-
export type GoalFormState = {
|
|
20
|
-
title: string;
|
|
21
|
-
setTitle: (v: string) => void;
|
|
22
|
-
status: GoalStatus;
|
|
23
|
-
setStatus: (v: GoalStatus) => void;
|
|
24
|
-
tagsRaw: string;
|
|
25
|
-
setTagsRaw: (v: string) => void;
|
|
26
|
-
teamsRaw: string;
|
|
27
|
-
setTeamsRaw: (v: string) => void;
|
|
28
|
-
body: string;
|
|
29
|
-
setBody: (v: string) => void;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/** Parses comma-separated string into trimmed non-empty array. */
|
|
33
|
-
export function parseCommaList(raw: string): string[] {
|
|
34
|
-
return raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** Shared form state for goal create/edit. Returns formState for GoalFormFields and parsed tags/teams. */
|
|
38
|
-
export function useGoalFormState(initial?: Partial<GoalFormState>): {
|
|
39
|
-
formState: GoalFormState;
|
|
40
|
-
tags: string[];
|
|
41
|
-
teams: string[];
|
|
42
|
-
} {
|
|
43
|
-
const [title, setTitle] = useState(initial?.title ?? "");
|
|
44
|
-
const [status, setStatus] = useState<GoalStatus>(initial?.status ?? "planned");
|
|
45
|
-
const [tagsRaw, setTagsRaw] = useState(initial?.tagsRaw ?? "");
|
|
46
|
-
const [teamsRaw, setTeamsRaw] = useState(initial?.teamsRaw ?? "");
|
|
47
|
-
const [body, setBody] = useState(initial?.body ?? "");
|
|
48
|
-
|
|
49
|
-
const formState: GoalFormState = useMemo(
|
|
50
|
-
() => ({
|
|
51
|
-
title,
|
|
52
|
-
setTitle,
|
|
53
|
-
status,
|
|
54
|
-
setStatus,
|
|
55
|
-
tagsRaw,
|
|
56
|
-
setTagsRaw,
|
|
57
|
-
teamsRaw,
|
|
58
|
-
setTeamsRaw,
|
|
59
|
-
body,
|
|
60
|
-
setBody,
|
|
61
|
-
}),
|
|
62
|
-
[title, status, tagsRaw, teamsRaw, body]
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const tags = useMemo(() => parseCommaList(tagsRaw), [tagsRaw]);
|
|
66
|
-
const teams = useMemo(() => parseCommaList(teamsRaw), [teamsRaw]);
|
|
67
|
-
|
|
68
|
-
return { formState, tags, teams };
|
|
69
|
-
}
|
package/src/lib/goals.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { NextResponse } from "next/server";
|
|
4
|
-
import YAML from "yaml";
|
|
5
|
-
import { errorMessage } from "@/lib/errors";
|
|
6
|
-
import { getWorkspaceGoalsDir } from "@/lib/paths";
|
|
7
|
-
|
|
8
|
-
export type GoalStatus = "planned" | "active" | "done";
|
|
9
|
-
|
|
10
|
-
/** Parses comma-separated string into trimmed non-empty array. */
|
|
11
|
-
export function parseCommaList(raw: string): string[] {
|
|
12
|
-
return raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type GoalFrontmatter = {
|
|
16
|
-
id: string;
|
|
17
|
-
title: string;
|
|
18
|
-
status: GoalStatus;
|
|
19
|
-
tags: string[];
|
|
20
|
-
teams: string[];
|
|
21
|
-
updatedAt: string; // ISO
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export type GoalSummary = GoalFrontmatter & {
|
|
25
|
-
filename: string;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const ID_RE = /^[a-z0-9][a-z0-9-]{1,63}$/;
|
|
29
|
-
|
|
30
|
-
export function assertSafeGoalId(id: string) {
|
|
31
|
-
if (!ID_RE.test(id)) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`Invalid goal id "${id}". Use 2-64 chars: lowercase letters, numbers, hyphens. Example: "increase-trial-activation".`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Maps goal-related errors to HTTP status: 400 for validation, 500 for other. */
|
|
39
|
-
export function goalErrorStatus(msg: string): 400 | 500 {
|
|
40
|
-
return /Invalid goal id|Path traversal/.test(msg) ? 400 : 500;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Returns NextResponse for goal API errors. Use in catch blocks. */
|
|
44
|
-
export function goalErrorResponse(e: unknown): NextResponse {
|
|
45
|
-
const msg = errorMessage(e);
|
|
46
|
-
const status = goalErrorStatus(msg);
|
|
47
|
-
return NextResponse.json({ error: msg }, { status });
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function splitFrontmatter(md: string): { fm: unknown; body: string } {
|
|
51
|
-
if (md.startsWith("---\n")) {
|
|
52
|
-
const end = md.indexOf("\n---\n", 4);
|
|
53
|
-
if (end !== -1) {
|
|
54
|
-
const yamlText = md.slice(4, end + 1);
|
|
55
|
-
const body = md.slice(end + 5);
|
|
56
|
-
const fm = YAML.parse(yamlText) as unknown;
|
|
57
|
-
return { fm: fm ?? {}, body };
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return { fm: {}, body: md };
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function normalizeFrontmatter(input: unknown, fallbackId: string, fallbackTitle: string): GoalFrontmatter {
|
|
64
|
-
const now = new Date().toISOString();
|
|
65
|
-
const obj = (input && typeof input === "object") ? (input as Record<string, unknown>) : {};
|
|
66
|
-
const id = String(obj.id ?? fallbackId).trim();
|
|
67
|
-
const title = String(obj.title ?? fallbackTitle ?? id).trim() || id;
|
|
68
|
-
const statusRaw = String(obj.status ?? "planned").trim();
|
|
69
|
-
const status: GoalStatus = statusRaw === "active" || statusRaw === "done" ? statusRaw : "planned";
|
|
70
|
-
const tags = Array.isArray(obj.tags) ? (obj.tags as unknown[]).map(String) : [];
|
|
71
|
-
const teams = Array.isArray(obj.teams) ? (obj.teams as unknown[]).map(String) : [];
|
|
72
|
-
const updatedAt = String(obj.updatedAt ?? now);
|
|
73
|
-
|
|
74
|
-
return { id, title, status, tags, teams, updatedAt };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function ensureGoalsDir() {
|
|
78
|
-
const dir = await getWorkspaceGoalsDir();
|
|
79
|
-
await fs.mkdir(dir, { recursive: true });
|
|
80
|
-
return dir;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function goalPathForId(id: string) {
|
|
84
|
-
assertSafeGoalId(id);
|
|
85
|
-
const root = await ensureGoalsDir();
|
|
86
|
-
const full = path.join(root, `${id}.md`);
|
|
87
|
-
const normalizedRoot = path.resolve(root) + path.sep;
|
|
88
|
-
const normalizedFull = path.resolve(full);
|
|
89
|
-
if (!normalizedFull.startsWith(normalizedRoot)) throw new Error("Path traversal rejected");
|
|
90
|
-
return { root, full };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function listGoals(): Promise<GoalSummary[]> {
|
|
94
|
-
const dir = await ensureGoalsDir();
|
|
95
|
-
const files = (await fs.readdir(dir)).filter((f) => f.endsWith(".md"));
|
|
96
|
-
|
|
97
|
-
const out: GoalSummary[] = [];
|
|
98
|
-
for (const f of files) {
|
|
99
|
-
const full = path.join(dir, f);
|
|
100
|
-
const md = await fs.readFile(full, "utf8");
|
|
101
|
-
const id = f.replace(/\.md$/, "");
|
|
102
|
-
const { fm } = splitFrontmatter(md);
|
|
103
|
-
const normalized = normalizeFrontmatter(fm, id, id);
|
|
104
|
-
out.push({ ...normalized, filename: f });
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// sort: active first, then planned, then done; within status by updatedAt desc
|
|
108
|
-
const rank: Record<GoalStatus, number> = { active: 0, planned: 1, done: 2 };
|
|
109
|
-
out.sort((a, b) => {
|
|
110
|
-
const ra = rank[a.status];
|
|
111
|
-
const rb = rank[b.status];
|
|
112
|
-
if (ra !== rb) return ra - rb;
|
|
113
|
-
return String(b.updatedAt).localeCompare(String(a.updatedAt));
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return out;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export async function readGoal(id: string): Promise<{ frontmatter: GoalFrontmatter; body: string; raw: string } | null> {
|
|
120
|
-
const { full } = await goalPathForId(id);
|
|
121
|
-
try {
|
|
122
|
-
const raw = await fs.readFile(full, "utf8");
|
|
123
|
-
const { fm, body } = splitFrontmatter(raw);
|
|
124
|
-
const fmObj = (fm && typeof fm === "object") ? (fm as Record<string, unknown>) : {};
|
|
125
|
-
const frontmatter = normalizeFrontmatter(fm, id, String(fmObj.title ?? id));
|
|
126
|
-
return { frontmatter, body, raw };
|
|
127
|
-
} catch (e: unknown) {
|
|
128
|
-
if (typeof e === "object" && e && (e as { code?: string }).code === "ENOENT") return null;
|
|
129
|
-
throw e;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export async function writeGoal(params: {
|
|
134
|
-
id: string;
|
|
135
|
-
title: string;
|
|
136
|
-
status?: GoalStatus;
|
|
137
|
-
tags?: string[];
|
|
138
|
-
teams?: string[];
|
|
139
|
-
body: string;
|
|
140
|
-
}): Promise<{ frontmatter: GoalFrontmatter; raw: string }>
|
|
141
|
-
{
|
|
142
|
-
const { id } = params;
|
|
143
|
-
const { full } = await goalPathForId(id);
|
|
144
|
-
|
|
145
|
-
const updatedAt = new Date().toISOString();
|
|
146
|
-
const fm: GoalFrontmatter = {
|
|
147
|
-
id,
|
|
148
|
-
title: params.title,
|
|
149
|
-
status: params.status ?? "planned",
|
|
150
|
-
tags: params.tags ?? [],
|
|
151
|
-
teams: params.teams ?? [],
|
|
152
|
-
updatedAt,
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const raw = `---\n${YAML.stringify(fm).trim()}\n---\n\n${(params.body ?? "").trim()}\n`;
|
|
156
|
-
await fs.writeFile(full, raw, "utf8");
|
|
157
|
-
return { frontmatter: fm, raw };
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export async function deleteGoal(id: string): Promise<{ ok: true } | { ok: false; reason: "not_found" }> {
|
|
161
|
-
const { full } = await goalPathForId(id);
|
|
162
|
-
try {
|
|
163
|
-
await fs.unlink(full);
|
|
164
|
-
return { ok: true };
|
|
165
|
-
} catch (e: unknown) {
|
|
166
|
-
if (typeof e === "object" && e && (e as { code?: string }).code === "ENOENT") {
|
|
167
|
-
return { ok: false, reason: "not_found" };
|
|
168
|
-
}
|
|
169
|
-
throw e;
|
|
170
|
-
}
|
|
171
|
-
}
|
package/src/lib/json.ts
DELETED
package/src/lib/kitchen-api.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// NOTE: This file is compiled by Next.js.
|
|
2
|
-
// Do not import `openclaw/plugin-sdk` here (it is provided by the gateway runtime, not as an npm dep).
|
|
3
|
-
|
|
4
|
-
type KitchenApi = {
|
|
5
|
-
config: unknown;
|
|
6
|
-
runtime: {
|
|
7
|
-
system: { runCommandWithTimeout: (argv: string[], opts: { timeoutMs: number }) => Promise<{ stdout?: string; stderr?: string }> };
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export function getKitchenApi(): KitchenApi {
|
|
12
|
-
const api = (globalThis as unknown as { __clawkitchen_api?: KitchenApi }).__clawkitchen_api;
|
|
13
|
-
if (!api) {
|
|
14
|
-
throw new Error(
|
|
15
|
-
"ClawKitchen: OpenClaw plugin API not available. (This should only happen if Kitchen is started outside the gateway process.)",
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
return api;
|
|
19
|
-
}
|
package/src/lib/marketplace.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
export type MarketplaceRecipe = {
|
|
5
|
-
slug: string;
|
|
6
|
-
kind: "team" | "agent";
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
version: string;
|
|
10
|
-
tags: string[];
|
|
11
|
-
sourceUrl: string;
|
|
12
|
-
homepageUrl?: string;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type MarketplaceRegistry = {
|
|
16
|
-
version: number;
|
|
17
|
-
generatedAt: string;
|
|
18
|
-
recipes: MarketplaceRecipe[];
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const REGISTRY_PATH = path.join(process.cwd(), "marketplace", "registry.json");
|
|
22
|
-
|
|
23
|
-
export async function loadRegistry(): Promise<MarketplaceRegistry> {
|
|
24
|
-
const raw = await fs.readFile(REGISTRY_PATH, "utf8");
|
|
25
|
-
const data = JSON.parse(raw) as MarketplaceRegistry;
|
|
26
|
-
const obj = data as unknown as { recipes?: unknown };
|
|
27
|
-
if (!data || typeof data !== "object" || !Array.isArray(obj.recipes)) {
|
|
28
|
-
throw new Error("Invalid marketplace registry.json");
|
|
29
|
-
}
|
|
30
|
-
return data;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function search(recipes: MarketplaceRecipe[], q: string | null) {
|
|
34
|
-
const query = (q ?? "").trim().toLowerCase();
|
|
35
|
-
if (!query) return recipes;
|
|
36
|
-
|
|
37
|
-
return recipes.filter((r) => {
|
|
38
|
-
const hay = [r.slug, r.name, r.description, ...(r.tags ?? [])].join(" ").toLowerCase();
|
|
39
|
-
return hay.includes(query);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function getBySlug(recipes: MarketplaceRecipe[], slug: string) {
|
|
44
|
-
const s = slug.trim().toLowerCase();
|
|
45
|
-
return recipes.find((r) => r.slug.toLowerCase() === s) ?? null;
|
|
46
|
-
}
|
package/src/lib/openclaw.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { getKitchenApi } from "@/lib/kitchen-api";
|
|
2
|
-
|
|
3
|
-
export type OpenClawExecResult = {
|
|
4
|
-
ok: boolean;
|
|
5
|
-
exitCode: number;
|
|
6
|
-
stdout: string;
|
|
7
|
-
stderr: string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
function extractStdout(err: { stdout?: unknown }): string {
|
|
11
|
-
if (typeof err.stdout === "string") return err.stdout;
|
|
12
|
-
if (err.stdout && typeof err.stdout === "object" && "toString" in err.stdout) {
|
|
13
|
-
return String((err.stdout as { toString: () => string }).toString());
|
|
14
|
-
}
|
|
15
|
-
return "";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function resolveExitCode(res: { exitCode?: unknown; code?: unknown; status?: unknown }): number {
|
|
19
|
-
if (typeof res.exitCode === "number") return res.exitCode;
|
|
20
|
-
if (typeof res.code === "number") return res.code;
|
|
21
|
-
if (typeof res.status === "number") return res.status;
|
|
22
|
-
return 0;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function extractStderr(err: { stderr?: unknown; message?: unknown }, fallback: unknown): string {
|
|
26
|
-
if (typeof err.stderr === "string") return err.stderr;
|
|
27
|
-
if (err.stderr && typeof err.stderr === "object" && "toString" in err.stderr) {
|
|
28
|
-
return String((err.stderr as { toString: () => string }).toString());
|
|
29
|
-
}
|
|
30
|
-
if (typeof err.message === "string") return err.message;
|
|
31
|
-
return String(fallback);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function runOpenClaw(args: string[]): Promise<OpenClawExecResult> {
|
|
35
|
-
const api = getKitchenApi();
|
|
36
|
-
try {
|
|
37
|
-
const res = (await api.runtime.system.runCommandWithTimeout(["openclaw", ...args], { timeoutMs: 120000 })) as {
|
|
38
|
-
stdout?: unknown;
|
|
39
|
-
stderr?: unknown;
|
|
40
|
-
exitCode?: unknown;
|
|
41
|
-
code?: unknown;
|
|
42
|
-
status?: unknown;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const stdout = String(res.stdout ?? "");
|
|
46
|
-
const stderr = String(res.stderr ?? "");
|
|
47
|
-
const exitCode = resolveExitCode(res);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (exitCode !== 0) return { ok: false, exitCode, stdout, stderr };
|
|
51
|
-
return { ok: true, exitCode: 0, stdout, stderr };
|
|
52
|
-
} catch (e: unknown) {
|
|
53
|
-
const err = e as { code?: unknown; stdout?: unknown; stderr?: unknown; message?: unknown };
|
|
54
|
-
const exitCode = typeof err.code === "number" ? err.code : 1;
|
|
55
|
-
const stdout = extractStdout(err);
|
|
56
|
-
const stderr = extractStderr(err, e);
|
|
57
|
-
return { ok: false, exitCode, stdout, stderr };
|
|
58
|
-
}
|
|
59
|
-
}
|
package/src/lib/paths.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
|
|
5
|
-
type OpenClawConfig = {
|
|
6
|
-
agents?: { defaults?: { workspace?: string } };
|
|
7
|
-
gateway?: { port?: number; auth?: { token?: string } };
|
|
8
|
-
tools?: {
|
|
9
|
-
agentToAgent?: {
|
|
10
|
-
enabled?: boolean;
|
|
11
|
-
allow?: string[];
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
plugins?: {
|
|
15
|
-
installs?: { recipes?: { installPath?: string; sourcePath?: string } };
|
|
16
|
-
load?: { paths?: string[] };
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export async function readOpenClawConfig(): Promise<OpenClawConfig> {
|
|
21
|
-
const p = path.join(os.homedir(), ".openclaw", "openclaw.json");
|
|
22
|
-
const text = await fs.readFile(p, "utf8");
|
|
23
|
-
return JSON.parse(text) as OpenClawConfig;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export async function getWorkspaceDir() {
|
|
27
|
-
const cfg = await readOpenClawConfig();
|
|
28
|
-
const ws = cfg.agents?.defaults?.workspace;
|
|
29
|
-
if (!ws) throw new Error("agents.defaults.workspace is not set in ~/.openclaw/openclaw.json");
|
|
30
|
-
return ws;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function getWorkspaceRecipesDir() {
|
|
34
|
-
const ws = await getWorkspaceDir();
|
|
35
|
-
return path.join(ws, "recipes");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export async function getWorkspaceGoalsDir() {
|
|
39
|
-
const ws = await getWorkspaceDir();
|
|
40
|
-
return path.join(ws, "notes", "goals");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function getTeamWorkspaceDir(teamId: string) {
|
|
44
|
-
const home = os.homedir();
|
|
45
|
-
if (!home) throw new Error("Could not resolve home directory");
|
|
46
|
-
return path.join(home, ".openclaw", `workspace-${teamId}`);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Team workspace dir derived from agents.defaults.workspace (sibling: .. / workspace-{teamId}) */
|
|
50
|
-
export function teamDirFromBaseWorkspace(baseWorkspace: string, teamId: string) {
|
|
51
|
-
return path.resolve(baseWorkspace, "..", `workspace-${teamId}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Rejects path traversal and empty names; returns normalized name. */
|
|
55
|
-
export function assertSafeRelativeFileName(name: string): string {
|
|
56
|
-
const n = name.replace(/\\/g, "/");
|
|
57
|
-
if (!n || n.startsWith("/") || n.includes("..")) throw new Error("Invalid file name");
|
|
58
|
-
return n;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export async function getBuiltinRecipesDir() {
|
|
62
|
-
const cfg = await readOpenClawConfig();
|
|
63
|
-
const p =
|
|
64
|
-
cfg.plugins?.installs?.recipes?.installPath ||
|
|
65
|
-
cfg.plugins?.installs?.recipes?.sourcePath ||
|
|
66
|
-
cfg.plugins?.load?.paths?.[0];
|
|
67
|
-
if (!p) throw new Error("Could not determine recipes plugin install path from ~/.openclaw/openclaw.json");
|
|
68
|
-
return path.join(p, "recipes", "default");
|
|
69
|
-
}
|
package/src/lib/poll.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Polls until check returns a non-null value or timeout. Returns the value or null on timeout.
|
|
3
|
-
*/
|
|
4
|
-
export async function pollUntil<T>(
|
|
5
|
-
check: () => Promise<T | null>,
|
|
6
|
-
opts: { timeoutMs: number; intervalMs?: number }
|
|
7
|
-
): Promise<T | null> {
|
|
8
|
-
const intervalMs = opts.intervalMs ?? 500;
|
|
9
|
-
const started = Date.now();
|
|
10
|
-
|
|
11
|
-
while (Date.now() - started < opts.timeoutMs) {
|
|
12
|
-
const result = await check();
|
|
13
|
-
if (result !== null) return result;
|
|
14
|
-
await new Promise((r) => setTimeout(r, intervalMs));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return null;
|
|
18
|
-
}
|
package/src/lib/recipe-clone.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import YAML from "yaml";
|
|
2
|
-
|
|
3
|
-
export function suggestIds(baseId: string): string[] {
|
|
4
|
-
const b = String(baseId || "recipe").trim();
|
|
5
|
-
return [`custom-${b}`, `my-${b}`, `${b}-2`, `${b}-alt`];
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function scaffoldCmdForKind(kind: string, toId: string): string[] | null {
|
|
9
|
-
if (kind === "team") {
|
|
10
|
-
return ["recipes", "scaffold-team", toId, "--team-id", toId, "--overwrite", "--overwrite-recipe"];
|
|
11
|
-
}
|
|
12
|
-
if (kind === "agent") {
|
|
13
|
-
return ["recipes", "scaffold", toId, "--agent-id", toId, "--overwrite", "--overwrite-recipe"];
|
|
14
|
-
}
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function patchFrontmatter(
|
|
19
|
-
original: string,
|
|
20
|
-
toId: string,
|
|
21
|
-
toName: string | undefined
|
|
22
|
-
): { next: string; kind: string } {
|
|
23
|
-
const end = original.indexOf("\n---\n", 4);
|
|
24
|
-
if (end === -1) throw new Error("Recipe frontmatter not terminated (---)");
|
|
25
|
-
const yamlText = original.slice(4, end + 1);
|
|
26
|
-
const fm = (YAML.parse(yamlText) ?? {}) as Record<string, unknown>;
|
|
27
|
-
const kind = String(fm.kind ?? "").trim().toLowerCase();
|
|
28
|
-
|
|
29
|
-
const teamPatch =
|
|
30
|
-
kind === "team"
|
|
31
|
-
? {
|
|
32
|
-
team: {
|
|
33
|
-
...(typeof fm.team === "object" && fm.team ? (fm.team as Record<string, unknown>) : {}),
|
|
34
|
-
teamId: toId,
|
|
35
|
-
},
|
|
36
|
-
}
|
|
37
|
-
: {};
|
|
38
|
-
const patched: Record<string, unknown> = { ...fm, id: toId, ...(toName ? { name: toName } : {}), ...teamPatch };
|
|
39
|
-
const nextYaml = YAML.stringify(patched).trimEnd();
|
|
40
|
-
const next = `---\n${nextYaml}\n---\n${original.slice(end + 5)}`;
|
|
41
|
-
return { next, kind };
|
|
42
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export function splitRecipeFrontmatter(md: string): { yamlText: string; rest: string } {
|
|
2
|
-
if (!md.startsWith("---\n")) throw new Error("Recipe markdown must start with YAML frontmatter (---)");
|
|
3
|
-
const end = md.indexOf("\n---\n", 4);
|
|
4
|
-
if (end === -1) throw new Error("Recipe frontmatter not terminated (---)");
|
|
5
|
-
const yamlText = md.slice(4, end + 1);
|
|
6
|
-
const rest = md.slice(end + 5);
|
|
7
|
-
return { yamlText, rest };
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function normalizeRole(role: string): string {
|
|
11
|
-
const r = role.trim();
|
|
12
|
-
if (!r) throw new Error("role is required");
|
|
13
|
-
if (!/^[a-z][a-z0-9-]{0,62}$/i.test(r)) throw new Error("role must be alphanumeric/dash");
|
|
14
|
-
return r;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/** Validates create-team or create-agent id. Returns error message or null. */
|
|
18
|
-
export function validateCreateId(
|
|
19
|
-
recipe: { id: string } | null,
|
|
20
|
-
id: string,
|
|
21
|
-
entityLabel: "team" | "agent"
|
|
22
|
-
): string | null {
|
|
23
|
-
if (!recipe) return null;
|
|
24
|
-
const t = id.trim();
|
|
25
|
-
const label = entityLabel === "team" ? "Team id" : "Agent id";
|
|
26
|
-
if (!t) return `${label} is required.`;
|
|
27
|
-
if (t === recipe.id)
|
|
28
|
-
return `${label} cannot be the same as the recipe id (${recipe.id}). Choose a new ${entityLabel} id.`;
|
|
29
|
-
return null;
|
|
30
|
-
}
|