nextclaw 0.4.5 → 0.4.7
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/index.js +129 -159
- package/package.json +5 -4
package/dist/cli/index.js
CHANGED
|
@@ -43,21 +43,20 @@ import {
|
|
|
43
43
|
rmSync as rmSync2,
|
|
44
44
|
writeFileSync as writeFileSync2
|
|
45
45
|
} from "fs";
|
|
46
|
-
import { dirname, join as
|
|
46
|
+
import { dirname, join as join3, resolve as resolve4 } from "path";
|
|
47
47
|
import { spawn as spawn2, spawnSync as spawnSync3 } from "child_process";
|
|
48
48
|
import { createInterface } from "readline";
|
|
49
49
|
import { createRequire } from "module";
|
|
50
|
-
import { fileURLToPath as
|
|
50
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
51
51
|
import chokidar from "chokidar";
|
|
52
52
|
|
|
53
53
|
// src/cli/gateway/controller.ts
|
|
54
54
|
import { createHash } from "crypto";
|
|
55
55
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
56
|
-
import { spawnSync } from "child_process";
|
|
57
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
58
|
-
import { join as join2, resolve as resolve2 } from "path";
|
|
59
56
|
import {
|
|
60
|
-
|
|
57
|
+
buildConfigSchema,
|
|
58
|
+
ConfigSchema,
|
|
59
|
+
redactConfigObject
|
|
61
60
|
} from "nextclaw-core";
|
|
62
61
|
|
|
63
62
|
// src/cli/utils.ts
|
|
@@ -66,7 +65,7 @@ import { join, resolve } from "path";
|
|
|
66
65
|
import { spawn } from "child_process";
|
|
67
66
|
import { createServer } from "net";
|
|
68
67
|
import { fileURLToPath } from "url";
|
|
69
|
-
import { getDataDir } from "nextclaw-core";
|
|
68
|
+
import { getDataDir, getPackageVersion } from "nextclaw-core";
|
|
70
69
|
function resolveUiConfig(config, overrides) {
|
|
71
70
|
const base = config.ui ?? { enabled: false, host: "127.0.0.1", port: 18791, open: false };
|
|
72
71
|
return { ...base, ...overrides ?? {} };
|
|
@@ -207,17 +206,6 @@ function openBrowser(url) {
|
|
|
207
206
|
const child = spawn(command, args, { stdio: "ignore", detached: true });
|
|
208
207
|
child.unref();
|
|
209
208
|
}
|
|
210
|
-
function getPackageVersion() {
|
|
211
|
-
try {
|
|
212
|
-
const cliDir = resolve(fileURLToPath(new URL(".", import.meta.url)));
|
|
213
|
-
const pkgPath = resolve(cliDir, "..", "..", "package.json");
|
|
214
|
-
const raw = readFileSync(pkgPath, "utf-8");
|
|
215
|
-
const parsed = JSON.parse(raw);
|
|
216
|
-
return typeof parsed.version === "string" ? parsed.version : "0.0.0";
|
|
217
|
-
} catch {
|
|
218
|
-
return "0.0.0";
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
209
|
function which(binary) {
|
|
222
210
|
const paths = (process.env.PATH ?? "").split(":");
|
|
223
211
|
for (const dir of paths) {
|
|
@@ -297,26 +285,52 @@ async function prompt(rl, question) {
|
|
|
297
285
|
});
|
|
298
286
|
}
|
|
299
287
|
|
|
300
|
-
// src/cli/
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
288
|
+
// src/cli/update/runner.ts
|
|
289
|
+
import { spawnSync } from "child_process";
|
|
290
|
+
import { resolve as resolve2 } from "path";
|
|
291
|
+
var DEFAULT_TIMEOUT_MS = 20 * 6e4;
|
|
292
|
+
function runSelfUpdate(options = {}) {
|
|
293
|
+
const steps = [];
|
|
294
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
295
|
+
const updateCommand = options.updateCommand ?? process.env.NEXTCLAW_UPDATE_COMMAND?.trim();
|
|
296
|
+
const packageName = options.packageName ?? "nextclaw";
|
|
297
|
+
const runStep = (cmd, args, cwd) => {
|
|
298
|
+
const result = spawnSync(cmd, args, {
|
|
299
|
+
cwd,
|
|
300
|
+
encoding: "utf-8",
|
|
301
|
+
timeout: timeoutMs,
|
|
302
|
+
stdio: "pipe"
|
|
303
|
+
});
|
|
304
|
+
steps.push({
|
|
305
|
+
cmd,
|
|
306
|
+
args,
|
|
307
|
+
cwd,
|
|
308
|
+
code: result.status,
|
|
309
|
+
stdout: (result.stdout ?? "").toString().slice(0, 4e3),
|
|
310
|
+
stderr: (result.stderr ?? "").toString().slice(0, 4e3)
|
|
311
|
+
});
|
|
312
|
+
return { ok: result.status === 0, code: result.status };
|
|
313
|
+
};
|
|
314
|
+
if (updateCommand) {
|
|
315
|
+
const cwd = options.cwd ? resolve2(options.cwd) : process.cwd();
|
|
316
|
+
const ok = runStep("sh", ["-c", updateCommand], cwd);
|
|
317
|
+
if (!ok.ok) {
|
|
318
|
+
return { ok: false, error: "update command failed", strategy: "command", steps };
|
|
319
|
+
}
|
|
320
|
+
return { ok: true, strategy: "command", steps };
|
|
308
321
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
output[key] = val ? "***" : val;
|
|
314
|
-
continue;
|
|
322
|
+
if (which("npm")) {
|
|
323
|
+
const ok = runStep("npm", ["i", "-g", packageName], process.cwd());
|
|
324
|
+
if (!ok.ok) {
|
|
325
|
+
return { ok: false, error: `npm install -g ${packageName} failed`, strategy: "npm", steps };
|
|
315
326
|
}
|
|
316
|
-
|
|
327
|
+
return { ok: true, strategy: "npm", steps };
|
|
317
328
|
}
|
|
318
|
-
return
|
|
319
|
-
}
|
|
329
|
+
return { ok: false, error: "no update strategy available", strategy: "none", steps };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/cli/gateway/controller.ts
|
|
333
|
+
var hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
|
|
320
334
|
var readConfigSnapshot = (getConfigPath2) => {
|
|
321
335
|
const path = getConfigPath2();
|
|
322
336
|
let raw = "";
|
|
@@ -341,9 +355,14 @@ var readConfigSnapshot = (getConfigPath2) => {
|
|
|
341
355
|
raw = JSON.stringify(config, null, 2);
|
|
342
356
|
}
|
|
343
357
|
const hash = hashRaw(raw);
|
|
344
|
-
const
|
|
358
|
+
const schema = buildConfigSchema({ version: getPackageVersion() });
|
|
359
|
+
const redacted = redactConfigObject(config, schema.uiHints);
|
|
345
360
|
return { raw: valid ? JSON.stringify(redacted, null, 2) : null, hash: valid ? hash : null, config, redacted, valid };
|
|
346
361
|
};
|
|
362
|
+
var redactValue = (value) => {
|
|
363
|
+
const schema = buildConfigSchema({ version: getPackageVersion() });
|
|
364
|
+
return redactConfigObject(value, schema.uiHints);
|
|
365
|
+
};
|
|
347
366
|
var mergeDeep = (base, patch) => {
|
|
348
367
|
const next = { ...base };
|
|
349
368
|
for (const [key, value] of Object.entries(patch)) {
|
|
@@ -360,29 +379,6 @@ var mergeDeep = (base, patch) => {
|
|
|
360
379
|
}
|
|
361
380
|
return next;
|
|
362
381
|
};
|
|
363
|
-
var buildSchemaFromValue = (value) => {
|
|
364
|
-
if (Array.isArray(value)) {
|
|
365
|
-
const item = value.length ? buildSchemaFromValue(value[0]) : { type: "string" };
|
|
366
|
-
return { type: "array", items: item };
|
|
367
|
-
}
|
|
368
|
-
if (value && typeof value === "object") {
|
|
369
|
-
const props = {};
|
|
370
|
-
for (const [key, val] of Object.entries(value)) {
|
|
371
|
-
props[key] = buildSchemaFromValue(val);
|
|
372
|
-
}
|
|
373
|
-
return { type: "object", properties: props };
|
|
374
|
-
}
|
|
375
|
-
if (typeof value === "number") {
|
|
376
|
-
return { type: "number" };
|
|
377
|
-
}
|
|
378
|
-
if (typeof value === "boolean") {
|
|
379
|
-
return { type: "boolean" };
|
|
380
|
-
}
|
|
381
|
-
if (value === null) {
|
|
382
|
-
return { type: ["null", "string"] };
|
|
383
|
-
}
|
|
384
|
-
return { type: "string" };
|
|
385
|
-
};
|
|
386
382
|
var scheduleRestart = (delayMs, reason) => {
|
|
387
383
|
const delay = typeof delayMs === "number" && Number.isFinite(delayMs) ? Math.max(0, delayMs) : 100;
|
|
388
384
|
console.log(`Gateway restart requested via tool${reason ? ` (${reason})` : ""}.`);
|
|
@@ -421,17 +417,7 @@ var GatewayControllerImpl = class {
|
|
|
421
417
|
};
|
|
422
418
|
}
|
|
423
419
|
async getConfigSchema() {
|
|
424
|
-
|
|
425
|
-
return {
|
|
426
|
-
schema: {
|
|
427
|
-
...buildSchemaFromValue(base),
|
|
428
|
-
title: "NextClawConfig",
|
|
429
|
-
description: "NextClaw config schema (simplified)"
|
|
430
|
-
},
|
|
431
|
-
uiHints: {},
|
|
432
|
-
version: getPackageVersion(),
|
|
433
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
434
|
-
};
|
|
420
|
+
return buildConfigSchema({ version: getPackageVersion() });
|
|
435
421
|
}
|
|
436
422
|
async applyConfig(params) {
|
|
437
423
|
const snapshot = readConfigSnapshot(this.deps.getConfigPath);
|
|
@@ -463,7 +449,7 @@ var GatewayControllerImpl = class {
|
|
|
463
449
|
ok: true,
|
|
464
450
|
note: params.note ?? null,
|
|
465
451
|
path: this.deps.getConfigPath(),
|
|
466
|
-
config:
|
|
452
|
+
config: redactValue(validated),
|
|
467
453
|
restart: { scheduled: true, delayMs }
|
|
468
454
|
};
|
|
469
455
|
}
|
|
@@ -498,67 +484,14 @@ var GatewayControllerImpl = class {
|
|
|
498
484
|
ok: true,
|
|
499
485
|
note: params.note ?? null,
|
|
500
486
|
path: this.deps.getConfigPath(),
|
|
501
|
-
config:
|
|
487
|
+
config: redactValue(validated),
|
|
502
488
|
restart: { scheduled: true, delayMs }
|
|
503
489
|
};
|
|
504
490
|
}
|
|
505
491
|
async updateRun(params) {
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
const pkgRoot = resolve2(cliDir, "..", "..");
|
|
510
|
-
const repoRoot = existsSync2(join2(pkgRoot, ".git")) ? pkgRoot : resolve2(pkgRoot, "..", "..");
|
|
511
|
-
const steps = [];
|
|
512
|
-
const runStep = (cmd, args, cwd) => {
|
|
513
|
-
const result = spawnSync(cmd, args, {
|
|
514
|
-
cwd,
|
|
515
|
-
encoding: "utf-8",
|
|
516
|
-
timeout: timeoutMs,
|
|
517
|
-
stdio: "pipe"
|
|
518
|
-
});
|
|
519
|
-
const step = {
|
|
520
|
-
cmd,
|
|
521
|
-
args,
|
|
522
|
-
cwd,
|
|
523
|
-
code: result.status,
|
|
524
|
-
stdout: (result.stdout ?? "").toString().slice(0, 4e3),
|
|
525
|
-
stderr: (result.stderr ?? "").toString().slice(0, 4e3)
|
|
526
|
-
};
|
|
527
|
-
steps.push(step);
|
|
528
|
-
return { ok: result.status === 0, code: result.status };
|
|
529
|
-
};
|
|
530
|
-
const updateCommand = process.env.NEXTCLAW_UPDATE_COMMAND?.trim();
|
|
531
|
-
if (updateCommand) {
|
|
532
|
-
const ok = runStep("sh", ["-c", updateCommand], process.cwd());
|
|
533
|
-
if (!ok.ok) {
|
|
534
|
-
return { ok: false, error: "update command failed", steps };
|
|
535
|
-
}
|
|
536
|
-
} else if (existsSync2(join2(repoRoot, ".git"))) {
|
|
537
|
-
if (!which("git")) {
|
|
538
|
-
return { ok: false, error: "git not found for repo update", steps };
|
|
539
|
-
}
|
|
540
|
-
const ok = runStep("git", ["-C", repoRoot, "pull", "--rebase"], repoRoot);
|
|
541
|
-
if (!ok.ok) {
|
|
542
|
-
return { ok: false, error: "git pull failed", steps };
|
|
543
|
-
}
|
|
544
|
-
if (existsSync2(join2(repoRoot, "pnpm-lock.yaml")) && which("pnpm")) {
|
|
545
|
-
const installOk = runStep("pnpm", ["install"], repoRoot);
|
|
546
|
-
if (!installOk.ok) {
|
|
547
|
-
return { ok: false, error: "pnpm install failed", steps };
|
|
548
|
-
}
|
|
549
|
-
} else if (existsSync2(join2(repoRoot, "package.json")) && which("npm")) {
|
|
550
|
-
const installOk = runStep("npm", ["install"], repoRoot);
|
|
551
|
-
if (!installOk.ok) {
|
|
552
|
-
return { ok: false, error: "npm install failed", steps };
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
} else if (which("npm")) {
|
|
556
|
-
const ok = runStep("npm", ["i", "-g", "nextclaw"], process.cwd());
|
|
557
|
-
if (!ok.ok) {
|
|
558
|
-
return { ok: false, error: "npm install -g nextclaw failed", steps };
|
|
559
|
-
}
|
|
560
|
-
} else {
|
|
561
|
-
return { ok: false, error: "no update strategy available", steps };
|
|
492
|
+
const result = runSelfUpdate({ timeoutMs: params.timeoutMs });
|
|
493
|
+
if (!result.ok) {
|
|
494
|
+
return { ok: false, error: result.error ?? "update failed", steps: result.steps };
|
|
562
495
|
}
|
|
563
496
|
const delayMs = params.restartDelayMs ?? 0;
|
|
564
497
|
scheduleRestart(delayMs, "update.run");
|
|
@@ -566,7 +499,8 @@ var GatewayControllerImpl = class {
|
|
|
566
499
|
ok: true,
|
|
567
500
|
note: params.note ?? null,
|
|
568
501
|
restart: { scheduled: true, delayMs },
|
|
569
|
-
|
|
502
|
+
strategy: result.strategy,
|
|
503
|
+
steps: result.steps
|
|
570
504
|
};
|
|
571
505
|
}
|
|
572
506
|
};
|
|
@@ -574,7 +508,7 @@ var GatewayControllerImpl = class {
|
|
|
574
508
|
// src/cli/skills/clawhub.ts
|
|
575
509
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
576
510
|
import { existsSync as existsSync3 } from "fs";
|
|
577
|
-
import { isAbsolute, join as
|
|
511
|
+
import { isAbsolute, join as join2, resolve as resolve3 } from "path";
|
|
578
512
|
async function installClawHubSkill(options) {
|
|
579
513
|
const slug = options.slug.trim();
|
|
580
514
|
if (!slug) {
|
|
@@ -586,7 +520,7 @@ async function installClawHubSkill(options) {
|
|
|
586
520
|
}
|
|
587
521
|
const dirName = options.dir?.trim() || "skills";
|
|
588
522
|
const destinationDir = isAbsolute(dirName) ? resolve3(dirName, slug) : resolve3(workdir, dirName, slug);
|
|
589
|
-
const skillFile =
|
|
523
|
+
const skillFile = join2(destinationDir, "SKILL.md");
|
|
590
524
|
if (!options.force && existsSync3(destinationDir)) {
|
|
591
525
|
if (existsSync3(skillFile)) {
|
|
592
526
|
return {
|
|
@@ -776,7 +710,7 @@ var CliRuntime = class {
|
|
|
776
710
|
}
|
|
777
711
|
const config = loadConfig();
|
|
778
712
|
const workspaceSetting = config.agents.defaults.workspace;
|
|
779
|
-
const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ?
|
|
713
|
+
const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join3(getDataDir2(), DEFAULT_WORKSPACE_DIR) : expandHome(workspaceSetting);
|
|
780
714
|
const workspaceExisted = existsSync4(workspacePath);
|
|
781
715
|
mkdirSync2(workspacePath, { recursive: true });
|
|
782
716
|
const templateResult = this.createWorkspaceTemplates(workspacePath, { force });
|
|
@@ -941,7 +875,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
941
875
|
}
|
|
942
876
|
console.log(`${this.logo} Interactive mode (type exit or Ctrl+C to quit)
|
|
943
877
|
`);
|
|
944
|
-
const historyFile =
|
|
878
|
+
const historyFile = join3(getDataDir2(), "history", "cli_history");
|
|
945
879
|
const historyDir = resolve4(historyFile, "..");
|
|
946
880
|
mkdirSync2(historyDir, { recursive: true });
|
|
947
881
|
const history = existsSync4(historyFile) ? readFileSync3(historyFile, "utf-8").split("\n").filter(Boolean) : [];
|
|
@@ -970,6 +904,41 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
970
904
|
printAgentResponse(response);
|
|
971
905
|
}
|
|
972
906
|
}
|
|
907
|
+
async update(opts) {
|
|
908
|
+
let timeoutMs;
|
|
909
|
+
if (opts.timeout !== void 0) {
|
|
910
|
+
const parsed = Number(opts.timeout);
|
|
911
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
912
|
+
console.error("Invalid --timeout value. Provide milliseconds (e.g. 1200000).");
|
|
913
|
+
process.exit(1);
|
|
914
|
+
}
|
|
915
|
+
timeoutMs = parsed;
|
|
916
|
+
}
|
|
917
|
+
const result = runSelfUpdate({ timeoutMs, cwd: process.cwd() });
|
|
918
|
+
const printSteps = () => {
|
|
919
|
+
for (const step of result.steps) {
|
|
920
|
+
console.log(`- ${step.cmd} ${step.args.join(" ")} (code ${step.code ?? "?"})`);
|
|
921
|
+
if (step.stderr) {
|
|
922
|
+
console.log(` stderr: ${step.stderr}`);
|
|
923
|
+
}
|
|
924
|
+
if (step.stdout) {
|
|
925
|
+
console.log(` stdout: ${step.stdout}`);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
if (!result.ok) {
|
|
930
|
+
console.error(`Update failed: ${result.error ?? "unknown error"}`);
|
|
931
|
+
if (result.steps.length > 0) {
|
|
932
|
+
printSteps();
|
|
933
|
+
}
|
|
934
|
+
process.exit(1);
|
|
935
|
+
}
|
|
936
|
+
console.log(`\u2713 Update complete (${result.strategy})`);
|
|
937
|
+
const state = readServiceState();
|
|
938
|
+
if (state && isProcessRunning(state.pid)) {
|
|
939
|
+
console.log(`Tip: restart ${APP_NAME} to apply the update.`);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
973
942
|
async skillsInstall(options) {
|
|
974
943
|
const workdir = options.workdir ? expandHome(options.workdir) : getWorkspacePath();
|
|
975
944
|
const result = await installClawHubSkill({
|
|
@@ -1012,7 +981,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1012
981
|
}
|
|
1013
982
|
}
|
|
1014
983
|
cronList(opts) {
|
|
1015
|
-
const storePath =
|
|
984
|
+
const storePath = join3(getDataDir2(), "cron", "jobs.json");
|
|
1016
985
|
const service = new CronService(storePath);
|
|
1017
986
|
const jobs = service.listJobs(Boolean(opts.all));
|
|
1018
987
|
if (!jobs.length) {
|
|
@@ -1032,7 +1001,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1032
1001
|
}
|
|
1033
1002
|
}
|
|
1034
1003
|
cronAdd(opts) {
|
|
1035
|
-
const storePath =
|
|
1004
|
+
const storePath = join3(getDataDir2(), "cron", "jobs.json");
|
|
1036
1005
|
const service = new CronService(storePath);
|
|
1037
1006
|
let schedule = null;
|
|
1038
1007
|
if (opts.every) {
|
|
@@ -1057,7 +1026,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1057
1026
|
console.log(`\u2713 Added job '${job.name}' (${job.id})`);
|
|
1058
1027
|
}
|
|
1059
1028
|
cronRemove(jobId) {
|
|
1060
|
-
const storePath =
|
|
1029
|
+
const storePath = join3(getDataDir2(), "cron", "jobs.json");
|
|
1061
1030
|
const service = new CronService(storePath);
|
|
1062
1031
|
if (service.removeJob(jobId)) {
|
|
1063
1032
|
console.log(`\u2713 Removed job ${jobId}`);
|
|
@@ -1066,7 +1035,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1066
1035
|
}
|
|
1067
1036
|
}
|
|
1068
1037
|
cronEnable(jobId, opts) {
|
|
1069
|
-
const storePath =
|
|
1038
|
+
const storePath = join3(getDataDir2(), "cron", "jobs.json");
|
|
1070
1039
|
const service = new CronService(storePath);
|
|
1071
1040
|
const job = service.enableJob(jobId, !opts.disable);
|
|
1072
1041
|
if (job) {
|
|
@@ -1076,7 +1045,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1076
1045
|
}
|
|
1077
1046
|
}
|
|
1078
1047
|
async cronRun(jobId, opts) {
|
|
1079
|
-
const storePath =
|
|
1048
|
+
const storePath = join3(getDataDir2(), "cron", "jobs.json");
|
|
1080
1049
|
const service = new CronService(storePath);
|
|
1081
1050
|
const ok = await service.runJob(jobId, Boolean(opts.force));
|
|
1082
1051
|
console.log(ok ? "\u2713 Job executed" : `Failed to run job ${jobId}`);
|
|
@@ -1108,7 +1077,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1108
1077
|
const provider = options.allowMissingProvider === true ? this.makeProvider(config, { allowMissing: true }) : this.makeProvider(config);
|
|
1109
1078
|
const providerManager = provider ? new ProviderManager(provider) : null;
|
|
1110
1079
|
const sessionManager = new SessionManager(getWorkspacePath(config.agents.defaults.workspace));
|
|
1111
|
-
const cronStorePath =
|
|
1080
|
+
const cronStorePath = join3(getDataDir2(), "cron", "jobs.json");
|
|
1112
1081
|
const cron2 = new CronService(cronStorePath);
|
|
1113
1082
|
const uiConfig = resolveUiConfig(config, options.uiOverrides);
|
|
1114
1083
|
const uiStaticDir = options.uiStaticDir === void 0 ? resolveUiStaticDir() : options.uiStaticDir;
|
|
@@ -1382,11 +1351,11 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1382
1351
|
{ source: "memory/MEMORY.md", target: "memory/MEMORY.md" }
|
|
1383
1352
|
];
|
|
1384
1353
|
for (const entry of templateFiles) {
|
|
1385
|
-
const filePath =
|
|
1354
|
+
const filePath = join3(workspace, entry.target);
|
|
1386
1355
|
if (!force && existsSync4(filePath)) {
|
|
1387
1356
|
continue;
|
|
1388
1357
|
}
|
|
1389
|
-
const templatePath =
|
|
1358
|
+
const templatePath = join3(templateDir, entry.source);
|
|
1390
1359
|
if (!existsSync4(templatePath)) {
|
|
1391
1360
|
console.warn(`Warning: Template file missing: ${templatePath}`);
|
|
1392
1361
|
continue;
|
|
@@ -1397,15 +1366,15 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1397
1366
|
writeFileSync2(filePath, content);
|
|
1398
1367
|
created.push(entry.target);
|
|
1399
1368
|
}
|
|
1400
|
-
const memoryDir =
|
|
1369
|
+
const memoryDir = join3(workspace, "memory");
|
|
1401
1370
|
if (!existsSync4(memoryDir)) {
|
|
1402
1371
|
mkdirSync2(memoryDir, { recursive: true });
|
|
1403
|
-
created.push(
|
|
1372
|
+
created.push(join3("memory", ""));
|
|
1404
1373
|
}
|
|
1405
|
-
const skillsDir =
|
|
1374
|
+
const skillsDir = join3(workspace, "skills");
|
|
1406
1375
|
if (!existsSync4(skillsDir)) {
|
|
1407
1376
|
mkdirSync2(skillsDir, { recursive: true });
|
|
1408
|
-
created.push(
|
|
1377
|
+
created.push(join3("skills", ""));
|
|
1409
1378
|
}
|
|
1410
1379
|
const seeded = this.seedBuiltinSkills(skillsDir, { force });
|
|
1411
1380
|
if (seeded > 0) {
|
|
@@ -1428,11 +1397,11 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1428
1397
|
if (!entry.isDirectory()) {
|
|
1429
1398
|
continue;
|
|
1430
1399
|
}
|
|
1431
|
-
const src =
|
|
1432
|
-
if (!existsSync4(
|
|
1400
|
+
const src = join3(sourceDir, entry.name);
|
|
1401
|
+
if (!existsSync4(join3(src, "SKILL.md"))) {
|
|
1433
1402
|
continue;
|
|
1434
1403
|
}
|
|
1435
|
-
const dest =
|
|
1404
|
+
const dest = join3(targetDir, entry.name);
|
|
1436
1405
|
if (!force && existsSync4(dest)) {
|
|
1437
1406
|
continue;
|
|
1438
1407
|
}
|
|
@@ -1446,11 +1415,11 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1446
1415
|
const require2 = createRequire(import.meta.url);
|
|
1447
1416
|
const entry = require2.resolve("nextclaw-core");
|
|
1448
1417
|
const pkgRoot = resolve4(dirname(entry), "..");
|
|
1449
|
-
const distSkills =
|
|
1418
|
+
const distSkills = join3(pkgRoot, "dist", "skills");
|
|
1450
1419
|
if (existsSync4(distSkills)) {
|
|
1451
1420
|
return distSkills;
|
|
1452
1421
|
}
|
|
1453
|
-
const srcSkills =
|
|
1422
|
+
const srcSkills = join3(pkgRoot, "src", "agent", "skills");
|
|
1454
1423
|
if (existsSync4(srcSkills)) {
|
|
1455
1424
|
return srcSkills;
|
|
1456
1425
|
}
|
|
@@ -1464,9 +1433,9 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1464
1433
|
if (override) {
|
|
1465
1434
|
return override;
|
|
1466
1435
|
}
|
|
1467
|
-
const cliDir = resolve4(
|
|
1436
|
+
const cliDir = resolve4(fileURLToPath2(new URL(".", import.meta.url)));
|
|
1468
1437
|
const pkgRoot = resolve4(cliDir, "..", "..");
|
|
1469
|
-
const candidates = [
|
|
1438
|
+
const candidates = [join3(pkgRoot, "templates")];
|
|
1470
1439
|
for (const candidate of candidates) {
|
|
1471
1440
|
if (existsSync4(candidate)) {
|
|
1472
1441
|
return candidate;
|
|
@@ -1475,22 +1444,22 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1475
1444
|
return null;
|
|
1476
1445
|
}
|
|
1477
1446
|
getBridgeDir() {
|
|
1478
|
-
const userBridge =
|
|
1479
|
-
if (existsSync4(
|
|
1447
|
+
const userBridge = join3(getDataDir2(), "bridge");
|
|
1448
|
+
if (existsSync4(join3(userBridge, "dist", "index.js"))) {
|
|
1480
1449
|
return userBridge;
|
|
1481
1450
|
}
|
|
1482
1451
|
if (!which("npm")) {
|
|
1483
1452
|
console.error("npm not found. Please install Node.js >= 18.");
|
|
1484
1453
|
process.exit(1);
|
|
1485
1454
|
}
|
|
1486
|
-
const cliDir = resolve4(
|
|
1455
|
+
const cliDir = resolve4(fileURLToPath2(new URL(".", import.meta.url)));
|
|
1487
1456
|
const pkgRoot = resolve4(cliDir, "..", "..");
|
|
1488
|
-
const pkgBridge =
|
|
1489
|
-
const srcBridge =
|
|
1457
|
+
const pkgBridge = join3(pkgRoot, "bridge");
|
|
1458
|
+
const srcBridge = join3(pkgRoot, "..", "..", "bridge");
|
|
1490
1459
|
let source = null;
|
|
1491
|
-
if (existsSync4(
|
|
1460
|
+
if (existsSync4(join3(pkgBridge, "package.json"))) {
|
|
1492
1461
|
source = pkgBridge;
|
|
1493
|
-
} else if (existsSync4(
|
|
1462
|
+
} else if (existsSync4(join3(srcBridge, "package.json"))) {
|
|
1494
1463
|
source = srcBridge;
|
|
1495
1464
|
}
|
|
1496
1465
|
if (!source) {
|
|
@@ -1539,6 +1508,7 @@ program.command("start").description(`Start the ${APP_NAME2} gateway + UI in the
|
|
|
1539
1508
|
program.command("serve").description(`Run the ${APP_NAME2} gateway + UI in the foreground`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after start", false).action(async (opts) => runtime.serve(opts));
|
|
1540
1509
|
program.command("stop").description(`Stop the ${APP_NAME2} background service`).action(async () => runtime.stop());
|
|
1541
1510
|
program.command("agent").description("Interact with the agent directly").option("-m, --message <message>", "Message to send to the agent").option("-s, --session <session>", "Session ID", "cli:default").option("--no-markdown", "Disable Markdown rendering").action(async (opts) => runtime.agent(opts));
|
|
1511
|
+
program.command("update").description(`Update ${APP_NAME2}`).option("--timeout <ms>", "Update command timeout in milliseconds").action(async (opts) => runtime.update(opts));
|
|
1542
1512
|
var registerClawHubInstall = (cmd) => {
|
|
1543
1513
|
cmd.command("install <slug>").description("Install a skill from ClawHub").option("--version <version>", "Skill version (default: latest)").option("--registry <url>", "ClawHub registry base URL").option("--workdir <dir>", "Workspace directory to install into").option("--dir <dir>", "Skills directory name (default: skills)").option("-f, --force", "Overwrite existing skill files", false).action(async (slug, opts) => runtime.skillsInstall({ slug, ...opts }));
|
|
1544
1514
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nextclaw",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"chokidar": "^3.6.0",
|
|
40
40
|
"commander": "^12.1.0",
|
|
41
|
-
"nextclaw-core": "^0.4.
|
|
42
|
-
"nextclaw-server": "^0.3.
|
|
41
|
+
"nextclaw-core": "^0.4.5",
|
|
42
|
+
"nextclaw-server": "^0.3.3"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^20.17.6",
|
|
@@ -54,7 +54,8 @@
|
|
|
54
54
|
"vitest": "^2.1.2"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
|
-
"dev": "
|
|
57
|
+
"dev": "tsx watch --tsconfig tsconfig.json src/cli/index.ts",
|
|
58
|
+
"dev:build": "pnpm -C ../nextclaw-core build && pnpm -C ../nextclaw-server build && tsx src/cli/index.ts",
|
|
58
59
|
"build": "pnpm -C ../nextclaw-core build && pnpm -C ../nextclaw-server build && tsup src/index.ts src/cli/index.ts --format esm --dts --out-dir dist && node scripts/copy-ui-dist.mjs",
|
|
59
60
|
"start": "node dist/cli.js",
|
|
60
61
|
"lint": "eslint .",
|