@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.
- package/dist/cli.js +3 -7
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -5
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -40
- package/dist/index.js.map +1 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +380 -77
- package/dist/router/index.js.map +1 -1
- package/dist/router/logger.d.ts +3 -0
- package/dist/router/logger.d.ts.map +1 -1
- package/dist/router/logger.js +8 -5
- package/dist/router/logger.js.map +1 -1
- package/dist/router/types.d.ts +6 -9
- package/dist/router/types.d.ts.map +1 -1
- package/dist/sidecar/auth.d.ts.map +1 -1
- package/dist/sidecar/auth.js +7 -11
- package/dist/sidecar/auth.js.map +1 -1
- package/dist/sidecar/index.js +104 -21
- package/dist/sidecar/index.js.map +1 -1
- package/dist/sidecar/routes/addons.d.ts.map +1 -1
- package/dist/sidecar/routes/addons.js +3 -13
- package/dist/sidecar/routes/addons.js.map +1 -1
- package/dist/sidecar/routes/api-keys.d.ts +4 -0
- package/dist/sidecar/routes/api-keys.d.ts.map +1 -0
- package/dist/sidecar/routes/api-keys.js +221 -0
- package/dist/sidecar/routes/api-keys.js.map +1 -0
- package/dist/sidecar/routes/backup.js +3 -3
- package/dist/sidecar/routes/backup.js.map +1 -1
- package/dist/sidecar/routes/bindings.d.ts +5 -0
- package/dist/sidecar/routes/bindings.d.ts.map +1 -0
- package/dist/sidecar/routes/bindings.js +64 -0
- package/dist/sidecar/routes/bindings.js.map +1 -0
- package/dist/sidecar/routes/channels.d.ts.map +1 -1
- package/dist/sidecar/routes/channels.js +71 -75
- package/dist/sidecar/routes/channels.js.map +1 -1
- package/dist/sidecar/routes/crons.d.ts +5 -0
- package/dist/sidecar/routes/crons.d.ts.map +1 -0
- package/dist/sidecar/routes/crons.js +81 -0
- package/dist/sidecar/routes/crons.js.map +1 -0
- package/dist/sidecar/routes/health.d.ts.map +1 -1
- package/dist/sidecar/routes/health.js +1 -5
- package/dist/sidecar/routes/health.js.map +1 -1
- package/dist/sidecar/routes/kitchen-proxy.d.ts +5 -0
- package/dist/sidecar/routes/kitchen-proxy.d.ts.map +1 -0
- package/dist/sidecar/routes/kitchen-proxy.js +29 -0
- package/dist/sidecar/routes/kitchen-proxy.js.map +1 -0
- package/dist/sidecar/routes/memory.d.ts +0 -2
- package/dist/sidecar/routes/memory.d.ts.map +1 -1
- package/dist/sidecar/routes/memory.js +116 -113
- package/dist/sidecar/routes/memory.js.map +1 -1
- package/dist/sidecar/routes/metrics.d.ts.map +1 -1
- package/dist/sidecar/routes/metrics.js +30 -1
- package/dist/sidecar/routes/metrics.js.map +1 -1
- package/dist/sidecar/routes/restart.d.ts.map +1 -1
- package/dist/sidecar/routes/restart.js +13 -4
- package/dist/sidecar/routes/restart.js.map +1 -1
- package/dist/sidecar/routes/router-config.d.ts +0 -1
- package/dist/sidecar/routes/router-config.d.ts.map +1 -1
- package/dist/sidecar/routes/router-config.js +2 -139
- package/dist/sidecar/routes/router-config.js.map +1 -1
- package/dist/sidecar/routes/soul.d.ts +11 -0
- package/dist/sidecar/routes/soul.d.ts.map +1 -1
- package/dist/sidecar/routes/soul.js +58 -33
- package/dist/sidecar/routes/soul.js.map +1 -1
- package/dist/sidecar/routes/system.d.ts +7 -0
- package/dist/sidecar/routes/system.d.ts.map +1 -0
- package/dist/sidecar/routes/system.js +49 -0
- package/dist/sidecar/routes/system.js.map +1 -0
- package/dist/sidecar/routes/team.d.ts.map +1 -1
- package/dist/sidecar/routes/team.js +121 -74
- package/dist/sidecar/routes/team.js.map +1 -1
- package/dist/sidecar/routes/update.d.ts.map +1 -1
- package/dist/sidecar/routes/update.js +24 -10
- package/dist/sidecar/routes/update.js.map +1 -1
- package/dist/sidecar/routes/workflow.d.ts +8 -0
- package/dist/sidecar/routes/workflow.d.ts.map +1 -0
- package/dist/sidecar/routes/workflow.js +232 -0
- package/dist/sidecar/routes/workflow.js.map +1 -0
- package/dist/sidecar/utils.d.ts +14 -0
- package/dist/sidecar/utils.d.ts.map +1 -1
- package/dist/sidecar/utils.js +35 -1
- package/dist/sidecar/utils.js.map +1 -1
- 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
|
-
|
|
143
|
-
|
|
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":"
|
|
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;
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
64
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
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:
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"soul.js","sourceRoot":"","sources":["../../../src/sidecar/routes/soul.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
async function
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
94
|
-
(0, utils_1.sendError)(res,
|
|
85
|
+
catch (err) {
|
|
86
|
+
(0, utils_1.sendError)(res, 500, `Failed to write recipe file: ${err.message}`);
|
|
95
87
|
return;
|
|
96
88
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
107
|
-
|
|
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
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|