@agentplugged/claw 0.1.1 → 0.2.1

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.
Files changed (88) hide show
  1. package/dist/cli.js +3 -7
  2. package/dist/cli.js.map +1 -1
  3. package/dist/config.d.ts +1 -2
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +5 -5
  6. package/dist/config.js.map +1 -1
  7. package/dist/index.d.ts +0 -9
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +21 -40
  10. package/dist/index.js.map +1 -1
  11. package/dist/router/index.d.ts.map +1 -1
  12. package/dist/router/index.js +380 -77
  13. package/dist/router/index.js.map +1 -1
  14. package/dist/router/logger.d.ts +3 -0
  15. package/dist/router/logger.d.ts.map +1 -1
  16. package/dist/router/logger.js +8 -5
  17. package/dist/router/logger.js.map +1 -1
  18. package/dist/router/types.d.ts +6 -9
  19. package/dist/router/types.d.ts.map +1 -1
  20. package/dist/sidecar/auth.d.ts.map +1 -1
  21. package/dist/sidecar/auth.js +7 -11
  22. package/dist/sidecar/auth.js.map +1 -1
  23. package/dist/sidecar/index.js +104 -21
  24. package/dist/sidecar/index.js.map +1 -1
  25. package/dist/sidecar/routes/addons.d.ts.map +1 -1
  26. package/dist/sidecar/routes/addons.js +3 -13
  27. package/dist/sidecar/routes/addons.js.map +1 -1
  28. package/dist/sidecar/routes/api-keys.d.ts +4 -0
  29. package/dist/sidecar/routes/api-keys.d.ts.map +1 -0
  30. package/dist/sidecar/routes/api-keys.js +221 -0
  31. package/dist/sidecar/routes/api-keys.js.map +1 -0
  32. package/dist/sidecar/routes/backup.js +3 -3
  33. package/dist/sidecar/routes/backup.js.map +1 -1
  34. package/dist/sidecar/routes/bindings.d.ts +5 -0
  35. package/dist/sidecar/routes/bindings.d.ts.map +1 -0
  36. package/dist/sidecar/routes/bindings.js +64 -0
  37. package/dist/sidecar/routes/bindings.js.map +1 -0
  38. package/dist/sidecar/routes/channels.d.ts.map +1 -1
  39. package/dist/sidecar/routes/channels.js +71 -75
  40. package/dist/sidecar/routes/channels.js.map +1 -1
  41. package/dist/sidecar/routes/crons.d.ts +5 -0
  42. package/dist/sidecar/routes/crons.d.ts.map +1 -0
  43. package/dist/sidecar/routes/crons.js +81 -0
  44. package/dist/sidecar/routes/crons.js.map +1 -0
  45. package/dist/sidecar/routes/health.d.ts.map +1 -1
  46. package/dist/sidecar/routes/health.js +1 -5
  47. package/dist/sidecar/routes/health.js.map +1 -1
  48. package/dist/sidecar/routes/kitchen-proxy.d.ts +5 -0
  49. package/dist/sidecar/routes/kitchen-proxy.d.ts.map +1 -0
  50. package/dist/sidecar/routes/kitchen-proxy.js +29 -0
  51. package/dist/sidecar/routes/kitchen-proxy.js.map +1 -0
  52. package/dist/sidecar/routes/memory.d.ts +0 -2
  53. package/dist/sidecar/routes/memory.d.ts.map +1 -1
  54. package/dist/sidecar/routes/memory.js +116 -113
  55. package/dist/sidecar/routes/memory.js.map +1 -1
  56. package/dist/sidecar/routes/metrics.d.ts.map +1 -1
  57. package/dist/sidecar/routes/metrics.js +30 -1
  58. package/dist/sidecar/routes/metrics.js.map +1 -1
  59. package/dist/sidecar/routes/restart.d.ts.map +1 -1
  60. package/dist/sidecar/routes/restart.js +13 -4
  61. package/dist/sidecar/routes/restart.js.map +1 -1
  62. package/dist/sidecar/routes/router-config.d.ts +0 -1
  63. package/dist/sidecar/routes/router-config.d.ts.map +1 -1
  64. package/dist/sidecar/routes/router-config.js +2 -139
  65. package/dist/sidecar/routes/router-config.js.map +1 -1
  66. package/dist/sidecar/routes/soul.d.ts +11 -0
  67. package/dist/sidecar/routes/soul.d.ts.map +1 -1
  68. package/dist/sidecar/routes/soul.js +58 -33
  69. package/dist/sidecar/routes/soul.js.map +1 -1
  70. package/dist/sidecar/routes/system.d.ts +7 -0
  71. package/dist/sidecar/routes/system.d.ts.map +1 -0
  72. package/dist/sidecar/routes/system.js +49 -0
  73. package/dist/sidecar/routes/system.js.map +1 -0
  74. package/dist/sidecar/routes/team.d.ts.map +1 -1
  75. package/dist/sidecar/routes/team.js +121 -74
  76. package/dist/sidecar/routes/team.js.map +1 -1
  77. package/dist/sidecar/routes/update.d.ts.map +1 -1
  78. package/dist/sidecar/routes/update.js +24 -10
  79. package/dist/sidecar/routes/update.js.map +1 -1
  80. package/dist/sidecar/routes/workflow.d.ts +8 -0
  81. package/dist/sidecar/routes/workflow.d.ts.map +1 -0
  82. package/dist/sidecar/routes/workflow.js +232 -0
  83. package/dist/sidecar/routes/workflow.js.map +1 -0
  84. package/dist/sidecar/utils.d.ts +14 -0
  85. package/dist/sidecar/utils.d.ts.map +1 -1
  86. package/dist/sidecar/utils.js +35 -1
  87. package/dist/sidecar/utils.js.map +1 -1
  88. package/package.json +1 -1
@@ -1,149 +1,12 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  exports.handleGetRouterConfig = handleGetRouterConfig;
37
- exports.handleUpdateStrategy = handleUpdateStrategy;
38
- const fs = __importStar(require("fs/promises"));
39
- const path = __importStar(require("path"));
40
4
  const utils_1 = require("../utils");
41
- const VALID_STRATEGIES = ["economy", "balanced", "quality"];
42
- /**
43
- * Signal the router to reload by writing a .reload sentinel file.
44
- * The router watches this file and reloads configuration on change.
45
- */
46
- async function signalRouterReload(runtimeDir) {
47
- const reloadFile = path.join(runtimeDir, "data", ".reload");
48
- try {
49
- await fs.mkdir(path.dirname(reloadFile), { recursive: true });
50
- await fs.writeFile(reloadFile, new Date().toISOString(), "utf-8");
51
- return "reload signal sent";
52
- }
53
- catch {
54
- // Fall back to restarting the router service
55
- try {
56
- const { stdout, stderr } = await (0, utils_1.execCommand)("systemctl reload-or-restart claw-router");
57
- return stdout || stderr || "router restarted";
58
- }
59
- catch (err) {
60
- return `reload failed: ${err.message}`;
61
- }
62
- }
63
- }
64
5
  function handleGetRouterConfig(config) {
65
6
  return async (_req, res) => {
66
- // Read the config file to get the persisted strategy, if any
67
- let fileStrategy;
68
- try {
69
- const raw = await fs.readFile(config.configFile, "utf-8");
70
- const cleaned = raw
71
- .replace(/\/\/[^\n]*/g, "")
72
- .replace(/,\s*([\]}])/g, "$1");
73
- const parsed = JSON.parse(cleaned);
74
- if (typeof parsed["strategy"] === "string") {
75
- fileStrategy = parsed["strategy"];
76
- }
77
- }
78
- catch {
79
- // Config file missing or unreadable — fall back to runtime config
80
- }
81
- const strategy = fileStrategy ?? config.strategy;
82
- const providers = config.providers.map((p) => ({
83
- name: p.name,
84
- enabled: p.enabled,
85
- models: p.models.map((m) => m.id),
86
- }));
87
- (0, utils_1.sendJson)(res, 200, {
88
- strategy,
89
- providers,
90
- });
91
- };
92
- }
93
- function handleUpdateStrategy(config) {
94
- return async (req, res) => {
95
- let body;
96
- try {
97
- body = (await (0, utils_1.parseBody)(req));
98
- }
99
- catch {
100
- (0, utils_1.sendError)(res, 400, "Invalid JSON body");
101
- return;
102
- }
103
- if (!body.strategy) {
104
- (0, utils_1.sendError)(res, 422, "'strategy' field is required");
105
- return;
106
- }
107
- if (!VALID_STRATEGIES.includes(body.strategy)) {
108
- (0, utils_1.sendError)(res, 422, `Invalid strategy '${body.strategy}'. Valid values: ${VALID_STRATEGIES.join(", ")}`);
109
- return;
110
- }
111
- // Read existing config
112
- let existingConfig = {};
113
- try {
114
- const raw = await fs.readFile(config.configFile, "utf-8");
115
- // Basic JSON5 parsing — strip single-line comments and trailing commas
116
- const cleaned = raw
117
- .replace(/\/\/[^\n]*/g, "")
118
- .replace(/,\s*([\]}])/g, "$1");
119
- existingConfig = JSON.parse(cleaned);
120
- }
121
- catch (err) {
122
- const error = err;
123
- if (error.code !== "ENOENT") {
124
- (0, utils_1.sendError)(res, 500, `Failed to read config file: ${error.message}`);
125
- return;
126
- }
127
- }
128
- // Update strategy
129
- existingConfig["strategy"] = body.strategy;
130
- // Write back
131
- try {
132
- await fs.mkdir(path.dirname(config.configFile), { recursive: true });
133
- await fs.writeFile(config.configFile, JSON.stringify(existingConfig, null, 2), "utf-8");
134
- }
135
- catch (err) {
136
- (0, utils_1.sendError)(res, 500, `Failed to write config: ${err.message}`);
137
- return;
138
- }
139
- // Signal router to reload
140
- const reloadResult = await signalRouterReload(config.runtimeDir);
141
7
  (0, utils_1.sendJson)(res, 200, {
142
- updated: true,
143
- strategy: body.strategy,
144
- previousStrategy: config.strategy,
145
- configFile: config.configFile,
146
- reload: reloadResult,
8
+ mode: "passthrough",
9
+ routerPort: config.routerPort,
147
10
  });
148
11
  };
149
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"router-config.js","sourceRoot":"","sources":["../../../src/sidecar/routes/router-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router-config.js","sourceRoot":"","sources":["../../../src/sidecar/routes/router-config.ts"],"names":[],"mappings":";;AAKA,sDAOC;AAVD,oCAAoC;AAGpC,SAAgB,qBAAqB,CAAC,MAAkB;IACtD,OAAO,KAAK,EAAE,IAAqB,EAAE,GAAmB,EAAiB,EAAE;QACzE,IAAA,gBAAQ,EAAC,GAAG,EAAE,GAAG,EAAE;YACjB,IAAI,EAAE,aAAa;YACnB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -1,4 +1,15 @@
1
1
  import { ClawConfig } from "../../config";
2
2
  import { RouteHandler } from "./health";
3
+ /**
4
+ * GET /soul — Read the current persona from persona.md
5
+ */
6
+ export declare function handleGetSoul(config: ClawConfig): RouteHandler;
7
+ /**
8
+ * PUT /soul — Update the persona
9
+ *
10
+ * Accepts two formats:
11
+ * 1. Free text: { persona: "raw markdown text" }
12
+ * 2. Structured: { name, personality, language, rules, template }
13
+ */
3
14
  export declare function handleUpdateSoul(config: ClawConfig): RouteHandler;
4
15
  //# sourceMappingURL=soul.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"soul.d.ts","sourceRoot":"","sources":["../../../src/sidecar/routes/soul.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AA6CxC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CAoEjE"}
1
+ {"version":3,"file":"soul.d.ts","sourceRoot":"","sources":["../../../src/sidecar/routes/soul.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CAyB9D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CAqFjE"}
@@ -33,36 +33,38 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.handleGetSoul = handleGetSoul;
36
37
  exports.handleUpdateSoul = handleUpdateSoul;
37
38
  const fs = __importStar(require("fs/promises"));
38
39
  const path = __importStar(require("path"));
39
40
  const utils_1 = require("../utils");
40
- function buildPersonaMarkdown(soul) {
41
- const lines = [];
42
- lines.push("# Agent Persona");
43
- lines.push("");
44
- if (soul.name) {
45
- lines.push(`**Name**: ${soul.name}`);
46
- }
47
- if (soul.personality) {
48
- lines.push(`**Personality**: ${soul.personality}`);
49
- }
50
- if (soul.language) {
51
- lines.push(`**Language**: ${soul.language}`);
52
- }
53
- if (soul.template) {
54
- lines.push(`**Template**: ${soul.template}`);
55
- }
56
- if (soul.rules && soul.rules.length > 0) {
57
- lines.push("");
58
- lines.push("## Rules");
59
- for (const rule of soul.rules) {
60
- lines.push(`- ${rule}`);
41
+ /**
42
+ * GET /soul — Read the current persona from persona.md
43
+ */
44
+ function handleGetSoul(config) {
45
+ return async (_req, res) => {
46
+ const personaPath = path.join(config.runtimeDir, "workspace", "persona.md");
47
+ let persona = "";
48
+ try {
49
+ persona = await fs.readFile(personaPath, "utf-8");
61
50
  }
62
- }
63
- lines.push("");
64
- return lines.join("\n");
51
+ catch (err) {
52
+ // File doesn't exist yet — return empty persona
53
+ if (err.code !== "ENOENT") {
54
+ (0, utils_1.sendError)(res, 500, `Failed to read persona file: ${err.message}`);
55
+ return;
56
+ }
57
+ }
58
+ (0, utils_1.sendJson)(res, 200, { persona });
59
+ };
65
60
  }
61
+ /**
62
+ * PUT /soul — Update the persona
63
+ *
64
+ * Accepts two formats:
65
+ * 1. Free text: { persona: "raw markdown text" }
66
+ * 2. Structured: { name, personality, language, rules, template }
67
+ */
66
68
  function handleUpdateSoul(config) {
67
69
  return async (req, res) => {
68
70
  let body;
@@ -73,20 +75,43 @@ function handleUpdateSoul(config) {
73
75
  (0, utils_1.sendError)(res, 400, "Invalid JSON body");
74
76
  return;
75
77
  }
76
- if (!body.name &&
77
- !body.personality &&
78
- !body.language &&
79
- !body.rules &&
80
- !body.template) {
81
- (0, utils_1.sendError)(res, 422, "At least one of name, personality, language, rules, or template must be provided");
78
+ let markdown;
79
+ // Format 1: free text persona
80
+ if (typeof body.persona === "string") {
81
+ markdown = body.persona;
82
+ }
83
+ // Format 2: structured fields
84
+ else if (body.name || body.personality || body.language || body.rules || body.template) {
85
+ const lines = [];
86
+ lines.push("# Agent Persona");
87
+ lines.push("");
88
+ if (body.name)
89
+ lines.push(`**Name**: ${body.name}`);
90
+ if (body.personality)
91
+ lines.push(`**Personality**: ${body.personality}`);
92
+ if (body.language)
93
+ lines.push(`**Language**: ${body.language}`);
94
+ if (body.template)
95
+ lines.push(`**Template**: ${body.template}`);
96
+ if (Array.isArray(body.rules) && body.rules.length > 0) {
97
+ lines.push("");
98
+ lines.push("## Rules");
99
+ for (const rule of body.rules) {
100
+ lines.push(`- ${rule}`);
101
+ }
102
+ }
103
+ lines.push("");
104
+ markdown = lines.join("\n");
105
+ }
106
+ else {
107
+ (0, utils_1.sendError)(res, 422, "Provide either 'persona' (string) or at least one of: name, personality, language, rules, template");
82
108
  return;
83
109
  }
84
- if (body.rules !== undefined && !Array.isArray(body.rules)) {
110
+ if (Array.isArray(body.rules) && !body.rules.every((r) => typeof r === "string")) {
85
111
  (0, utils_1.sendError)(res, 422, "'rules' must be an array of strings");
86
112
  return;
87
113
  }
88
114
  const personaPath = path.join(config.runtimeDir, "workspace", "persona.md");
89
- const markdown = buildPersonaMarkdown(body);
90
115
  try {
91
116
  await fs.mkdir(path.dirname(personaPath), { recursive: true });
92
117
  await fs.writeFile(personaPath, markdown, "utf-8");
@@ -107,7 +132,7 @@ function handleUpdateSoul(config) {
107
132
  (0, utils_1.sendJson)(res, 200, {
108
133
  updated: true,
109
134
  personaPath,
110
- persona: body,
135
+ persona: markdown,
111
136
  restart: restartResult,
112
137
  });
113
138
  };
@@ -1 +1 @@
1
- {"version":3,"file":"soul.js","sourceRoot":"","sources":["../../../src/sidecar/routes/soul.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"soul.js","sourceRoot":"","sources":["../../../src/sidecar/routes/soul.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { RouteHandler } from "./health";
2
+ /**
3
+ * GET /system — Return CPU, RAM, and disk usage for the VPS.
4
+ * Uses standard Linux tools (top, free, df).
5
+ */
6
+ export declare function handleSystemMetrics(): RouteHandler;
7
+ //# sourceMappingURL=system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../src/sidecar/routes/system.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,YAAY,CAwDlD"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleSystemMetrics = handleSystemMetrics;
4
+ const utils_1 = require("../utils");
5
+ /**
6
+ * GET /system — Return CPU, RAM, and disk usage for the VPS.
7
+ * Uses standard Linux tools (top, free, df).
8
+ */
9
+ function handleSystemMetrics() {
10
+ return async (_req, res) => {
11
+ try {
12
+ const [cpuResult, memResult, diskResult, uptimeResult] = await Promise.all([
13
+ // CPU: use /proc/stat snapshot (idle percentage)
14
+ (0, utils_1.execCommand)("top -bn1 | grep 'Cpu(s)' | awk '{print 100 - $8}'").catch(() => ({ stdout: "0", stderr: "" })),
15
+ // RAM: free in MB
16
+ (0, utils_1.execCommand)("free -m | awk 'NR==2{printf \"%s %s\", $3, $2}'").catch(() => ({ stdout: "0 1", stderr: "" })),
17
+ // Disk: root partition usage
18
+ (0, utils_1.execCommand)("df / --output=pcent | tail -1 | tr -dc '0-9'").catch(() => ({ stdout: "0", stderr: "" })),
19
+ // Uptime in seconds
20
+ (0, utils_1.execCommand)("awk '{print $1}' /proc/uptime").catch(() => ({
21
+ stdout: "0",
22
+ stderr: "",
23
+ })),
24
+ ]);
25
+ // Parse CPU
26
+ const cpu = Math.round(parseFloat(cpuResult.stdout) || 0);
27
+ // Parse RAM
28
+ const memParts = memResult.stdout.trim().split(/\s+/);
29
+ const usedMb = parseInt(memParts[0] || "0", 10);
30
+ const totalMb = parseInt(memParts[1] || "1", 10);
31
+ const ram = totalMb > 0 ? Math.round((usedMb / totalMb) * 100) : 0;
32
+ // Parse Disk
33
+ const disk = parseInt(diskResult.stdout.trim() || "0", 10);
34
+ // Parse Uptime
35
+ const uptimeSeconds = Math.round(parseFloat(uptimeResult.stdout) || 0);
36
+ (0, utils_1.sendJson)(res, 200, {
37
+ cpu,
38
+ ram,
39
+ disk,
40
+ uptimeSeconds,
41
+ memoryMb: { used: usedMb, total: totalMb },
42
+ });
43
+ }
44
+ catch (err) {
45
+ (0, utils_1.sendError)(res, 500, `Failed to read system metrics: ${err.message}`);
46
+ }
47
+ };
48
+ }
49
+ //# sourceMappingURL=system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/sidecar/routes/system.ts"],"names":[],"mappings":";;AAQA,kDAwDC;AA/DD,oCAA4D;AAG5D;;;GAGG;AACH,SAAgB,mBAAmB;IACjC,OAAO,KAAK,EAAE,IAAqB,EAAE,GAAmB,EAAiB,EAAE;QACzE,IAAI,CAAC;YACH,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACzE,iDAAiD;gBACjD,IAAA,mBAAW,EACT,mDAAmD,CACpD,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;gBAE5C,kBAAkB;gBAClB,IAAA,mBAAW,EAAC,iDAAiD,CAAC,CAAC,KAAK,CAClE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CACtC;gBAED,6BAA6B;gBAC7B,IAAA,mBAAW,EAAC,8CAA8C,CAAC,CAAC,KAAK,CAC/D,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CACpC;gBAED,oBAAoB;gBACpB,IAAA,mBAAW,EAAC,+BAA+B,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;oBACxD,MAAM,EAAE,GAAG;oBACX,MAAM,EAAE,EAAE;iBACX,CAAC,CAAC;aACJ,CAAC,CAAC;YAEH,YAAY;YACZ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAE1D,YAAY;YACZ,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YACjD,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEnE,aAAa;YACb,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YAE3D,eAAe;YACf,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAEvE,IAAA,gBAAQ,EAAC,GAAG,EAAE,GAAG,EAAE;gBACjB,GAAG;gBACH,GAAG;gBACH,IAAI;gBACJ,aAAa;gBACb,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE;aAC3C,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAA,iBAAS,EACP,GAAG,EACH,GAAG,EACH,kCAAmC,GAAa,CAAC,OAAO,EAAE,CAC3D,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"team.d.ts","sourceRoot":"","sources":["../../../src/sidecar/routes/team.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAkDxC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CA+FjE"}
1
+ {"version":3,"file":"team.d.ts","sourceRoot":"","sources":["../../../src/sidecar/routes/team.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAiBxC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CA6KjE"}
@@ -37,26 +37,17 @@ exports.handleDeployTeam = handleDeployTeam;
37
37
  const fs = __importStar(require("fs/promises"));
38
38
  const path = __importStar(require("path"));
39
39
  const utils_1 = require("../utils");
40
- function validateFileName(name) {
41
- // Prevent path traversal
42
- return (typeof name === "string" &&
43
- name.length > 0 &&
44
- !name.includes("..") &&
45
- !name.includes("/") &&
46
- !name.includes("\\"));
47
- }
48
- async function writeFiles(dir, files, defaultExtension) {
49
- await fs.mkdir(dir, { recursive: true });
50
- const written = [];
51
- for (const file of files) {
52
- // Ensure a safe file extension
53
- const hasExtension = /\.[a-z]+$/i.test(file.name);
54
- const fileName = hasExtension ? file.name : `${file.name}${defaultExtension}`;
55
- const filePath = path.join(dir, fileName);
56
- await fs.writeFile(filePath, file.content, "utf-8");
57
- written.push(fileName);
58
- }
59
- return written;
40
+ // ---------------------------------------------------------------------------
41
+ // POST /team/deploy — deploy a team recipe via ClawRecipes CLI
42
+ //
43
+ // Receives a recipe (Markdown) from the SaaS, writes it to a temp file,
44
+ // then runs `openclaw recipes scaffold-team <file> --team-id <id> --apply-config`.
45
+ // The sidecar is a PROXY — scaffolding logic lives in ClawRecipes.
46
+ // ---------------------------------------------------------------------------
47
+ const TEAM_ID_FILE = "team-id";
48
+ async function persistTeamId(config, teamId) {
49
+ const teamIdPath = path.join(config.dataDir, TEAM_ID_FILE);
50
+ await fs.writeFile(teamIdPath, teamId, "utf-8");
60
51
  }
61
52
  function handleDeployTeam(config) {
62
53
  return async (req, res) => {
@@ -68,72 +59,128 @@ function handleDeployTeam(config) {
68
59
  (0, utils_1.sendError)(res, 400, "Invalid JSON body");
69
60
  return;
70
61
  }
71
- const skills = body.skills ?? [];
72
- const shared = body.shared ?? [];
73
- if (skills.length === 0 && shared.length === 0) {
74
- (0, utils_1.sendError)(res, 422, "At least one skill or shared file must be provided");
62
+ const recipe = body.recipe;
63
+ const teamId = body.teamId;
64
+ const skills = body.skills;
65
+ if (!recipe && (!skills || skills.length === 0)) {
66
+ (0, utils_1.sendError)(res, 422, "Either recipe (Markdown) or skills array must be provided");
75
67
  return;
76
68
  }
77
- // Validate all file names to prevent path traversal
78
- for (const skill of skills) {
79
- if (!validateFileName(skill.name)) {
80
- (0, utils_1.sendError)(res, 422, `Invalid skill name: '${skill.name}'`);
81
- return;
82
- }
83
- if (typeof skill.content !== "string") {
84
- (0, utils_1.sendError)(res, 422, `Skill '${skill.name}' must have string content`);
69
+ // -----------------------------------------------------------------------
70
+ // Path A: Recipe-based deploy via ClawRecipes CLI
71
+ // -----------------------------------------------------------------------
72
+ if (recipe) {
73
+ if (typeof recipe !== "string" || recipe.trim().length === 0) {
74
+ (0, utils_1.sendError)(res, 422, "recipe must be a non-empty Markdown string");
85
75
  return;
86
76
  }
87
- }
88
- for (const file of shared) {
89
- if (!validateFileName(file.name)) {
90
- (0, utils_1.sendError)(res, 422, `Invalid shared file name: '${file.name}'`);
91
- return;
77
+ const resolvedTeamId = teamId ?? `team-${Date.now().toString(36)}`;
78
+ // Write recipe to a temp file
79
+ const tmpDir = path.join(config.dataDir, "tmp");
80
+ await fs.mkdir(tmpDir, { recursive: true });
81
+ const recipePath = path.join(tmpDir, `recipe-${resolvedTeamId}.md`);
82
+ try {
83
+ await fs.writeFile(recipePath, recipe, "utf-8");
92
84
  }
93
- if (typeof file.content !== "string") {
94
- (0, utils_1.sendError)(res, 422, `Shared file '${file.name}' must have string content`);
85
+ catch (err) {
86
+ (0, utils_1.sendError)(res, 500, `Failed to write recipe file: ${err.message}`);
95
87
  return;
96
88
  }
97
- }
98
- const skillsDir = path.join(config.runtimeDir, "workspace", "skills");
99
- const sharedDir = path.join(config.runtimeDir, "workspace", "shared");
100
- let writtenSkills = [];
101
- let writtenShared = [];
102
- try {
103
- if (skills.length > 0) {
104
- writtenSkills = await writeFiles(skillsDir, skills, ".md");
89
+ // Run ClawRecipes scaffold-team
90
+ try {
91
+ const { stdout, stderr } = await (0, utils_1.execSafeCommand)("openclaw", [
92
+ "recipes",
93
+ "scaffold-team",
94
+ recipePath,
95
+ "--team-id",
96
+ resolvedTeamId,
97
+ "--apply-config",
98
+ ], {
99
+ env: {
100
+ ...process.env,
101
+ HOME: config.runtimeDir,
102
+ },
103
+ timeout: 120_000, // scaffolding can take time
104
+ });
105
+ // Persist teamId so other routes (workflow, etc.) can use it
106
+ await persistTeamId(config, resolvedTeamId);
107
+ // Clean up temp file (best-effort)
108
+ fs.unlink(recipePath).catch(() => { });
109
+ (0, utils_1.sendJson)(res, 201, {
110
+ deployed: true,
111
+ teamId: resolvedTeamId,
112
+ method: "clawrecipes-cli",
113
+ stdout: stdout || undefined,
114
+ stderr: stderr || undefined,
115
+ });
105
116
  }
106
- if (shared.length > 0) {
107
- writtenShared = await writeFiles(sharedDir, shared, ".md");
117
+ catch (err) {
118
+ // Clean up temp file on error too
119
+ fs.unlink(recipePath).catch(() => { });
120
+ (0, utils_1.sendError)(res, 500, `ClawRecipes scaffold-team failed: ${err.message}`);
108
121
  }
109
- }
110
- catch (err) {
111
- (0, utils_1.sendError)(res, 500, `Failed to write files: ${err.message}`);
112
122
  return;
113
123
  }
114
- // Restart openclaw to pick up the new team configuration
115
- let restartResult;
116
- try {
117
- const { stdout, stderr } = await (0, utils_1.execCommand)("sudo systemctl restart openclaw");
118
- restartResult = stdout || stderr || "restarted";
119
- }
120
- catch (err) {
121
- restartResult = `restart failed: ${err.message}`;
124
+ // -----------------------------------------------------------------------
125
+ // Path B: Direct skills push (legacy compatibility)
126
+ // Skills are written directly to the workspace, then OpenClaw is restarted.
127
+ // -----------------------------------------------------------------------
128
+ if (skills && skills.length > 0) {
129
+ const skillsDir = path.join(config.runtimeDir, "workspace", "skills");
130
+ await fs.mkdir(skillsDir, { recursive: true });
131
+ const writtenSkills = [];
132
+ for (const skill of skills) {
133
+ // Prevent path traversal
134
+ if (!skill.name ||
135
+ skill.name.includes("..") ||
136
+ skill.name.includes("/") ||
137
+ skill.name.includes("\\")) {
138
+ (0, utils_1.sendError)(res, 422, `Invalid skill name: '${skill.name}'`);
139
+ return;
140
+ }
141
+ if (typeof skill.content !== "string") {
142
+ (0, utils_1.sendError)(res, 422, `Skill '${skill.name}' must have string content`);
143
+ return;
144
+ }
145
+ const hasExtension = /\.[a-z]+$/i.test(skill.name);
146
+ const fileName = hasExtension ? skill.name : `${skill.name}.md`;
147
+ const filePath = path.join(skillsDir, fileName);
148
+ try {
149
+ await fs.writeFile(filePath, skill.content, "utf-8");
150
+ writtenSkills.push(fileName);
151
+ }
152
+ catch (err) {
153
+ (0, utils_1.sendError)(res, 500, `Failed to write skill ${fileName}: ${err.message}`);
154
+ return;
155
+ }
156
+ }
157
+ // Restart OpenClaw to pick up new skills
158
+ let restartResult;
159
+ try {
160
+ const { stdout, stderr } = await (0, utils_1.execSafeCommand)("sudo", [
161
+ "systemctl",
162
+ "restart",
163
+ "openclaw",
164
+ ]);
165
+ restartResult = stdout || stderr || "restarted";
166
+ }
167
+ catch (err) {
168
+ restartResult = `restart failed: ${err.message}`;
169
+ }
170
+ if (teamId) {
171
+ await persistTeamId(config, teamId);
172
+ }
173
+ (0, utils_1.sendJson)(res, 201, {
174
+ deployed: true,
175
+ method: "direct-skills-push",
176
+ skills: {
177
+ written: writtenSkills,
178
+ count: writtenSkills.length,
179
+ directory: skillsDir,
180
+ },
181
+ restart: restartResult,
182
+ });
122
183
  }
123
- (0, utils_1.sendJson)(res, 201, {
124
- deployed: true,
125
- skills: {
126
- written: writtenSkills,
127
- count: writtenSkills.length,
128
- directory: skillsDir,
129
- },
130
- shared: {
131
- written: writtenShared,
132
- count: writtenShared.length,
133
- directory: sharedDir,
134
- },
135
- restart: restartResult,
136
- });
137
184
  };
138
185
  }
139
186
  //# sourceMappingURL=team.js.map