@clawtrail/init 2.0.0 → 2.1.0
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/index.js +89 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
2
8
|
|
|
3
9
|
// src/index.ts
|
|
4
10
|
import { Command } from "commander";
|
|
@@ -9,6 +15,7 @@ import path from "path";
|
|
|
9
15
|
import os from "os";
|
|
10
16
|
import fetch from "node-fetch";
|
|
11
17
|
import JSON5 from "json5";
|
|
18
|
+
import { execSync } from "child_process";
|
|
12
19
|
var SKILL_FILES = {
|
|
13
20
|
SKILL: "https://api.clawtrail.ai/ct/api/skill/clawtrail.md",
|
|
14
21
|
HEARTBEAT: "https://api.clawtrail.ai/ct/api/skill/HEARTBEAT.md"
|
|
@@ -175,15 +182,84 @@ async function detectOpenClaw() {
|
|
|
175
182
|
return false;
|
|
176
183
|
}
|
|
177
184
|
}
|
|
185
|
+
function getHeartbeatVersion(filePath) {
|
|
186
|
+
try {
|
|
187
|
+
const content = __require("fs").readFileSync(filePath, "utf-8");
|
|
188
|
+
const match = content.match(/\*\*Version:\*\*\s+([\d.]+)/);
|
|
189
|
+
return match?.[1] ?? null;
|
|
190
|
+
} catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function isGatewayRunning() {
|
|
195
|
+
try {
|
|
196
|
+
const result = execSync("pgrep -f openclaw-gateway", { encoding: "utf-8", stdio: "pipe" });
|
|
197
|
+
return result.trim().length > 0;
|
|
198
|
+
} catch {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async function clearOpenClawSessions() {
|
|
203
|
+
const openclawDir = path.join(os.homedir(), ".openclaw");
|
|
204
|
+
const sessionsDir = path.join(openclawDir, "agents", "main", "sessions");
|
|
205
|
+
let cleared = 0;
|
|
206
|
+
try {
|
|
207
|
+
const files = await fs.readdir(sessionsDir);
|
|
208
|
+
for (const file of files) {
|
|
209
|
+
if (file.endsWith(".jsonl") || file.endsWith(".lock") || file === "sessions.json") {
|
|
210
|
+
await fs.unlink(path.join(sessionsDir, file));
|
|
211
|
+
cleared++;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} catch {
|
|
215
|
+
}
|
|
216
|
+
return cleared;
|
|
217
|
+
}
|
|
218
|
+
async function restartGateway(oldVersion, newVersion) {
|
|
219
|
+
const spinner = ora("Restarting OpenClaw gateway...").start();
|
|
220
|
+
try {
|
|
221
|
+
try {
|
|
222
|
+
execSync("pkill -f openclaw-gateway", { stdio: "pipe" });
|
|
223
|
+
} catch {
|
|
224
|
+
}
|
|
225
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
226
|
+
const cleared = await clearOpenClawSessions();
|
|
227
|
+
try {
|
|
228
|
+
const logPath = path.join(os.homedir(), "openclaw-gateway.log");
|
|
229
|
+
execSync(`nohup openclaw-gateway > ${logPath} 2>&1 &`, {
|
|
230
|
+
stdio: "pipe",
|
|
231
|
+
shell: "/bin/bash"
|
|
232
|
+
});
|
|
233
|
+
} catch {
|
|
234
|
+
}
|
|
235
|
+
await new Promise((r) => setTimeout(r, 4e3));
|
|
236
|
+
const running = isGatewayRunning();
|
|
237
|
+
if (running) {
|
|
238
|
+
const versionMsg = oldVersion && newVersion && oldVersion !== newVersion ? ` (${chalk.gray(oldVersion)} \u2192 ${chalk.cyan(newVersion)})` : newVersion ? ` (${chalk.cyan(`v${newVersion}`)})` : "";
|
|
239
|
+
spinner.succeed(
|
|
240
|
+
chalk.green(`Gateway restarted${versionMsg} \u2014 ${cleared} cached sessions cleared`)
|
|
241
|
+
);
|
|
242
|
+
return true;
|
|
243
|
+
} else {
|
|
244
|
+
spinner.warn(chalk.yellow("Gateway killed but may not have restarted \u2014 check manually"));
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
} catch (err) {
|
|
248
|
+
spinner.fail(chalk.red(`Gateway restart failed: ${err.message}`));
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
178
252
|
async function main() {
|
|
179
253
|
console.log(chalk.cyan.bold("\n ClawTrail Agent Installer\n"));
|
|
180
254
|
const program = new Command();
|
|
181
|
-
program.name("clawtrail-init").description("Install ClawTrail skill files, configure heartbeat, and optionally register an agent").version("2.
|
|
255
|
+
program.name("clawtrail-init").description("Install ClawTrail skill files, configure heartbeat, and optionally register an agent").version("2.1.0").option("-d, --dir <path>", "Download directory for skill files", "./clawtrail-skills").option("-s, --staging", "Use staging environment", false).option("--name <name>", "Register agent with this name").option("--description <desc>", "Agent description (required with --name)").option("--bio <bio>", "Agent bio").option("--agent-type <type>", "Agent type (openclaw, custom, mcp-server, a2a-agent)", "openclaw").option("--framework <fw>", "Agent framework (e.g., langchain, autogen)").option("--skills <skills>", "Comma-separated skills (e.g., coding,research,dkg)").option("--capabilities <caps>", "Comma-separated capabilities (e.g., research,analysis)").option("--api-key <key>", "Existing API key (skip registration, just configure)").option("--no-restart", "Skip gateway restart after updating files").action(async (options) => {
|
|
182
256
|
const targetDir = path.resolve(process.cwd(), options.dir);
|
|
183
257
|
const staging = options.staging;
|
|
184
258
|
const env = staging ? "staging" : "production";
|
|
185
259
|
await downloadSkillFiles(targetDir, staging);
|
|
186
260
|
const hasOpenClaw = await detectOpenClaw();
|
|
261
|
+
const heartbeatPath = path.join(os.homedir(), ".openclaw", "workspace", "HEARTBEAT.md");
|
|
262
|
+
const oldHeartbeatVersion = hasOpenClaw ? getHeartbeatVersion(heartbeatPath) : null;
|
|
187
263
|
let placedFiles = [];
|
|
188
264
|
if (hasOpenClaw) {
|
|
189
265
|
const spinner = ora("Placing files in OpenClaw directories...").start();
|
|
@@ -231,6 +307,13 @@ async function main() {
|
|
|
231
307
|
spinner.warn(chalk.yellow(`Config failed: ${err.message}`));
|
|
232
308
|
}
|
|
233
309
|
}
|
|
310
|
+
let gatewayRestarted = false;
|
|
311
|
+
if (hasOpenClaw && options.restart !== false) {
|
|
312
|
+
const newHeartbeatVersion = getHeartbeatVersion(heartbeatPath);
|
|
313
|
+
if (isGatewayRunning()) {
|
|
314
|
+
gatewayRestarted = await restartGateway(oldHeartbeatVersion, newHeartbeatVersion);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
234
317
|
if (apiKey) {
|
|
235
318
|
const envPath = path.join(process.cwd(), ".env");
|
|
236
319
|
try {
|
|
@@ -268,6 +351,11 @@ CLAWTRAIL_API_KEY=${apiKey}
|
|
|
268
351
|
console.log(chalk.white(" Verify code: ") + chalk.yellow(verificationCode));
|
|
269
352
|
console.log(chalk.gray(" (save this \u2014 shown only once)"));
|
|
270
353
|
}
|
|
354
|
+
if (gatewayRestarted) {
|
|
355
|
+
console.log(chalk.white(" Gateway: ") + chalk.green("restarted (sessions cleared, new heartbeat active)"));
|
|
356
|
+
} else if (hasOpenClaw && isGatewayRunning()) {
|
|
357
|
+
console.log(chalk.white(" Gateway: ") + chalk.yellow("running (use without --no-restart to auto-restart)"));
|
|
358
|
+
}
|
|
271
359
|
if (!hasOpenClaw) {
|
|
272
360
|
console.log(chalk.gray("\n OpenClaw not detected \u2014 skill files saved to ") + chalk.cyan(targetDir));
|
|
273
361
|
console.log(chalk.gray(" Point your agent at SKILL.md to get started."));
|