@lobehub/cli 0.0.61 → 0.0.63
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 +5114 -2534
- package/dist/maintenanceWorker.mjs +91 -0
- package/man/man1/lh.1 +8 -2
- package/package.json +8 -7
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
//#region src/daemon/maintenanceWorker.ts
|
|
6
|
+
/** Atomic replacement lets the connected daemon read progress during installation. */
|
|
7
|
+
async function writeMaintenanceState(file, operation) {
|
|
8
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
9
|
+
await writeFile(temporary, JSON.stringify(operation), { mode: 384 });
|
|
10
|
+
await rename(temporary, file);
|
|
11
|
+
}
|
|
12
|
+
async function run(command, args, timeout) {
|
|
13
|
+
await new Promise((resolve, reject) => {
|
|
14
|
+
const child = spawn(command, args, {
|
|
15
|
+
stdio: "inherit",
|
|
16
|
+
timeout
|
|
17
|
+
});
|
|
18
|
+
child.once("error", reject);
|
|
19
|
+
child.once("close", (code, signal) => {
|
|
20
|
+
if (code === 0) resolve();
|
|
21
|
+
else reject(/* @__PURE__ */ new Error(`CLI maintenance command failed (${signal ?? code}). See lh connect logs.`));
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/** Runs from a private copy outside the package being replaced. No runtime package imports. */
|
|
26
|
+
async function runMaintenanceWorker(config, ready) {
|
|
27
|
+
const { entry, executable, operation, statePath } = config;
|
|
28
|
+
const persist = async () => {
|
|
29
|
+
await writeMaintenanceState(config.receiptPath, operation);
|
|
30
|
+
await writeMaintenanceState(statePath, operation);
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
if (config.install) await run(config.install.command, config.install.args, 18e4);
|
|
34
|
+
const { stdout } = await promisify(execFile)(executable, [entry, "--version"], { timeout: 3e4 });
|
|
35
|
+
if (stdout.trim() !== operation.targetVersion) throw new Error("Installed CLI version did not match the requested version. The existing connection was kept.");
|
|
36
|
+
operation.stage = "restarting";
|
|
37
|
+
await persist();
|
|
38
|
+
ready();
|
|
39
|
+
const deadline = Date.now() + 3e4;
|
|
40
|
+
while (true) {
|
|
41
|
+
try {
|
|
42
|
+
process.kill(config.parentPid, 0);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error.code === "ESRCH") break;
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
if (Date.now() >= deadline) throw new Error("The previous CLI did not stop. No second daemon was started.");
|
|
48
|
+
await setTimeout$1(100);
|
|
49
|
+
}
|
|
50
|
+
await run(executable, [
|
|
51
|
+
entry,
|
|
52
|
+
...config.restartArgs,
|
|
53
|
+
"--daemon"
|
|
54
|
+
], 45e3);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
operation.stage = "failed";
|
|
57
|
+
operation.error = error instanceof Error ? error.message : String(error);
|
|
58
|
+
await persist();
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (process.argv[2] === "--maintenance-config") {
|
|
63
|
+
const configPath = process.argv[3];
|
|
64
|
+
const config = JSON.parse(await readFile(configPath, "utf8"));
|
|
65
|
+
await rm(configPath);
|
|
66
|
+
let started = false;
|
|
67
|
+
const timeout = setTimeout(() => process.disconnect?.(), 15e3);
|
|
68
|
+
process.once("message", () => {
|
|
69
|
+
started = true;
|
|
70
|
+
clearTimeout(timeout);
|
|
71
|
+
runMaintenanceWorker(config, () => {
|
|
72
|
+
if (!process.connected) throw new Error("The original daemon stopped during installation. Start the connection manually.");
|
|
73
|
+
process.send?.({ type: "ready-to-restart" });
|
|
74
|
+
}).catch((error) => {
|
|
75
|
+
console.error(error);
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
}).finally(async () => {
|
|
78
|
+
if (process.connected) process.disconnect();
|
|
79
|
+
await rm(process.argv[1], { force: true });
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
process.once("disconnect", () => {
|
|
83
|
+
clearTimeout(timeout);
|
|
84
|
+
if (!started) {
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
rm(process.argv[1], { force: true }).catch(console.error);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { runMaintenanceWorker, writeMaintenanceState };
|
package/man/man1/lh.1
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
.\" Code generated by `npm run man:generate`; DO NOT EDIT.
|
|
2
2
|
.\" Manual command details come from the Commander command tree.
|
|
3
|
-
.TH LH 1 "" "@lobehub/cli 0.0.
|
|
3
|
+
.TH LH 1 "" "@lobehub/cli 0.0.63" "User Commands"
|
|
4
4
|
.SH NAME
|
|
5
5
|
lh \- LobeHub CLI \- manage and connect to LobeHub services
|
|
6
6
|
.SH SYNOPSIS
|
|
@@ -93,7 +93,7 @@ Manage files
|
|
|
93
93
|
Publish local pages as artifacts
|
|
94
94
|
.TP
|
|
95
95
|
.B hetero
|
|
96
|
-
Run heterogeneous agent CLIs (Amp / Claude Code / CodeBuddy / Codex / Cursor / Factory Droid / Devin / Grok Build / Kimi Code / OpenCode / Pi / Qoder / TRAE CLI) and stream their output
|
|
96
|
+
Run heterogeneous agent CLIs (Amp / Claude Code / CodeBuddy / Codex / Cursor / Factory Droid / Devin / Grok Build / Kimi Code / OpenCode / Pi / Qoder / TRAE CLI / DeepSeek Harness) and stream their output
|
|
97
97
|
.TP
|
|
98
98
|
.B skill
|
|
99
99
|
Manage agent skills
|
|
@@ -128,6 +128,12 @@ Manage AI providers
|
|
|
128
128
|
.B project
|
|
129
129
|
Manage goal\-oriented projects
|
|
130
130
|
.TP
|
|
131
|
+
.B dashboard
|
|
132
|
+
Manage dashboards (boards of monitoring widgets)
|
|
133
|
+
.TP
|
|
134
|
+
.B widget
|
|
135
|
+
Build monitoring widgets: sandboxed scripts rendered as dashboard cards
|
|
136
|
+
.TP
|
|
131
137
|
.B plugin
|
|
132
138
|
Manage plugins
|
|
133
139
|
.TP
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.63",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"lh": "dist/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"man"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"@lydell/node-pty": "1.2.0-beta.15",
|
|
20
21
|
"ws": "^8.21.0"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
@@ -39,18 +40,18 @@
|
|
|
39
40
|
"typescript": "^6.0.3",
|
|
40
41
|
"url-join": "^5.0.0",
|
|
41
42
|
"vitest": "5.0.0",
|
|
42
|
-
"@lobechat/agent-gateway-client": "1.0.0",
|
|
43
43
|
"@lobechat/const": "1.0.0",
|
|
44
44
|
"@lobechat/device-control": "1.0.0",
|
|
45
|
+
"@lobechat/agent-gateway-client": "1.0.0",
|
|
45
46
|
"@lobechat/agent-tracing": "1.0.0",
|
|
46
|
-
"@lobechat/device-identity": "1.0.0",
|
|
47
|
-
"@lobechat/device-gateway-client": "1.0.0",
|
|
48
47
|
"@lobechat/eval-rubric": "1.0.0",
|
|
49
|
-
"@lobechat/
|
|
48
|
+
"@lobechat/device-gateway-client": "1.0.0",
|
|
49
|
+
"@lobechat/device-identity": "1.0.0",
|
|
50
50
|
"@lobechat/html-artifact": "1.0.0",
|
|
51
51
|
"@lobechat/local-file-shell": "1.0.0",
|
|
52
|
-
"@lobechat/
|
|
52
|
+
"@lobechat/heterogeneous-agents": "1.0.0",
|
|
53
53
|
"@lobechat/tool-runtime": "1.0.0",
|
|
54
|
+
"@lobechat/types": "1.0.0",
|
|
54
55
|
"@lobechat/utils": "1.0.0"
|
|
55
56
|
},
|
|
56
57
|
"engines": {
|
|
@@ -61,7 +62,7 @@
|
|
|
61
62
|
"registry": "https://registry.npmjs.org"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
|
-
"build": "bun scripts/ensureWorkspaceLinks.ts && tsdown",
|
|
65
|
+
"build": "bun scripts/ensureWorkspaceLinks.ts && tsdown && tsdown src/daemon/maintenanceWorker.ts --no-config --no-clean --format esm --target node22",
|
|
65
66
|
"cli:link": "bun link",
|
|
66
67
|
"cli:unlink": "bun unlink",
|
|
67
68
|
"dev": "LOBEHUB_CLI_HOME=.lobehub-dev bun src/index.ts",
|