@lobehub/cli 0.0.60 → 0.0.62
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 +5585 -3413
- package/dist/maintenanceWorker.mjs +91 -0
- package/man/man1/lh.1 +1 -1
- package/package.json +28 -27
|
@@ -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.62" "User Commands"
|
|
4
4
|
.SH NAME
|
|
5
5
|
lh \- LobeHub CLI \- manage and connect to LobeHub services
|
|
6
6
|
.SH SYNOPSIS
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.62",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"lh": "dist/index.js",
|
|
@@ -16,10 +16,35 @@
|
|
|
16
16
|
"dist",
|
|
17
17
|
"man"
|
|
18
18
|
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "bun scripts/ensureWorkspaceLinks.ts && tsdown && tsdown src/daemon/maintenanceWorker.ts --no-config --no-clean --format esm --target node22",
|
|
21
|
+
"cli:link": "bun link",
|
|
22
|
+
"cli:unlink": "bun unlink",
|
|
23
|
+
"dev": "LOBEHUB_CLI_HOME=.lobehub-dev bun src/index.ts",
|
|
24
|
+
"man:generate": "bun src/man/generate.ts",
|
|
25
|
+
"prepublishOnly": "npm run build && npm run man:generate",
|
|
26
|
+
"test": "bunx vitest run --config vitest.config.mts --silent='passed-only'",
|
|
27
|
+
"test:coverage": "bunx vitest run --config vitest.config.mts --coverage",
|
|
28
|
+
"test:e2e": "bunx vitest run --config vitest.e2e.config.mts --silent='passed-only'",
|
|
29
|
+
"type-check": "tsc --noEmit"
|
|
30
|
+
},
|
|
19
31
|
"dependencies": {
|
|
20
32
|
"ws": "^8.21.0"
|
|
21
33
|
},
|
|
22
34
|
"devDependencies": {
|
|
35
|
+
"@lobechat/agent-gateway-client": "workspace:*",
|
|
36
|
+
"@lobechat/agent-tracing": "workspace:*",
|
|
37
|
+
"@lobechat/const": "workspace:*",
|
|
38
|
+
"@lobechat/device-control": "workspace:*",
|
|
39
|
+
"@lobechat/device-gateway-client": "workspace:*",
|
|
40
|
+
"@lobechat/device-identity": "workspace:*",
|
|
41
|
+
"@lobechat/eval-rubric": "workspace:*",
|
|
42
|
+
"@lobechat/heterogeneous-agents": "workspace:*",
|
|
43
|
+
"@lobechat/html-artifact": "workspace:*",
|
|
44
|
+
"@lobechat/local-file-shell": "workspace:*",
|
|
45
|
+
"@lobechat/tool-runtime": "workspace:*",
|
|
46
|
+
"@lobechat/types": "workspace:*",
|
|
47
|
+
"@lobechat/utils": "workspace:*",
|
|
23
48
|
"@trpc/client": "^11.18.0",
|
|
24
49
|
"@types/node": "^24.13.2",
|
|
25
50
|
"@types/semver": "^7.7.1",
|
|
@@ -38,20 +63,7 @@
|
|
|
38
63
|
"tsdown": "^0.21.10",
|
|
39
64
|
"typescript": "^6.0.3",
|
|
40
65
|
"url-join": "^5.0.0",
|
|
41
|
-
"vitest": "5.0.0"
|
|
42
|
-
"@lobechat/agent-gateway-client": "1.0.0",
|
|
43
|
-
"@lobechat/agent-tracing": "1.0.0",
|
|
44
|
-
"@lobechat/const": "1.0.0",
|
|
45
|
-
"@lobechat/device-control": "1.0.0",
|
|
46
|
-
"@lobechat/device-gateway-client": "1.0.0",
|
|
47
|
-
"@lobechat/device-identity": "1.0.0",
|
|
48
|
-
"@lobechat/eval-rubric": "1.0.0",
|
|
49
|
-
"@lobechat/html-artifact": "1.0.0",
|
|
50
|
-
"@lobechat/heterogeneous-agents": "1.0.0",
|
|
51
|
-
"@lobechat/local-file-shell": "1.0.0",
|
|
52
|
-
"@lobechat/tool-runtime": "1.0.0",
|
|
53
|
-
"@lobechat/types": "1.0.0",
|
|
54
|
-
"@lobechat/utils": "1.0.0"
|
|
66
|
+
"vitest": "5.0.0"
|
|
55
67
|
},
|
|
56
68
|
"engines": {
|
|
57
69
|
"node": ">=22.15"
|
|
@@ -59,16 +71,5 @@
|
|
|
59
71
|
"publishConfig": {
|
|
60
72
|
"access": "public",
|
|
61
73
|
"registry": "https://registry.npmjs.org"
|
|
62
|
-
},
|
|
63
|
-
"scripts": {
|
|
64
|
-
"build": "bun scripts/ensureWorkspaceLinks.ts && tsdown",
|
|
65
|
-
"cli:link": "bun link",
|
|
66
|
-
"cli:unlink": "bun unlink",
|
|
67
|
-
"dev": "LOBEHUB_CLI_HOME=.lobehub-dev bun src/index.ts",
|
|
68
|
-
"man:generate": "bun src/man/generate.ts",
|
|
69
|
-
"test": "bunx vitest run --config vitest.config.mts --silent='passed-only'",
|
|
70
|
-
"test:coverage": "bunx vitest run --config vitest.config.mts --coverage",
|
|
71
|
-
"test:e2e": "bunx vitest run --config vitest.e2e.config.mts --silent='passed-only'",
|
|
72
|
-
"type-check": "tsc --noEmit"
|
|
73
74
|
}
|
|
74
|
-
}
|
|
75
|
+
}
|