@earzbook/openclaw 0.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/README.md +46 -0
- package/dist/adapter.d.ts +29 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +368 -0
- package/dist/adapter.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +84 -0
- package/dist/config.js.map +1 -0
- package/dist/dispatch.d.ts +48 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/dispatch.js +261 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +571 -0
- package/dist/index.js.map +1 -0
- package/dist/lockfile.d.ts +20 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/lockfile.js +113 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/logging.d.ts +5 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +98 -0
- package/dist/logging.js.map +1 -0
- package/dist/platform/launchd.d.ts +12 -0
- package/dist/platform/launchd.d.ts.map +1 -0
- package/dist/platform/launchd.js +37 -0
- package/dist/platform/launchd.js.map +1 -0
- package/dist/platform/systemd.d.ts +10 -0
- package/dist/platform/systemd.d.ts.map +1 -0
- package/dist/platform/systemd.js +18 -0
- package/dist/platform/systemd.js.map +1 -0
- package/dist/self-update.d.ts +36 -0
- package/dist/self-update.d.ts.map +1 -0
- package/dist/self-update.js +151 -0
- package/dist/self-update.js.map +1 -0
- package/dist/types.d.ts +236 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
package/dist/lockfile.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Single-instance guard via advisory lockfile.
|
|
2
|
+
//
|
|
3
|
+
// On startup, we open ~/.earzbook/sidecar.lock with O_RDWR and try to
|
|
4
|
+
// `flock` it exclusively. If another sidecar process holds the lock the
|
|
5
|
+
// flock fails and we exit — this prevents launchd/systemd from running
|
|
6
|
+
// two copies simultaneously (which would each open a WS to the relay and
|
|
7
|
+
// thrash on plugin-role replacement).
|
|
8
|
+
//
|
|
9
|
+
// We deliberately use a file inside ~/.earzbook (not /var/run or /tmp) so
|
|
10
|
+
// the lock dies with the user's home filesystem; if you nuke ~/.earzbook
|
|
11
|
+
// you also reset the lock.
|
|
12
|
+
import { closeSync, mkdirSync, openSync, readFileSync, unlinkSync, writeSync, } from "node:fs";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
import { dirname, join } from "node:path";
|
|
15
|
+
import { warn } from "./logging.js";
|
|
16
|
+
const LOCK_PATH = join(homedir(), ".earzbook", "openclaw.lock");
|
|
17
|
+
export class LockHeldError extends Error {
|
|
18
|
+
constructor(path) {
|
|
19
|
+
super(`another sidecar instance holds ${path}`);
|
|
20
|
+
this.name = "LockHeldError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Acquire an exclusive lock on the sidecar lockfile. Throws LockHeldError
|
|
25
|
+
* if another process already holds it.
|
|
26
|
+
*
|
|
27
|
+
* We try to use proper-lockfile semantics via flock if available, but Node
|
|
28
|
+
* lacks a stable flock binding in the stdlib. The fallback is O_CREAT |
|
|
29
|
+
* O_EXCL: if the file exists, we treat that as held UNLESS the recorded
|
|
30
|
+
* pid is no longer running (stale lock → take it over).
|
|
31
|
+
*/
|
|
32
|
+
export function acquireLock() {
|
|
33
|
+
ensureParentDir();
|
|
34
|
+
// Try exclusive create first; this is the simple and most portable lock.
|
|
35
|
+
let fd;
|
|
36
|
+
try {
|
|
37
|
+
// 'wx+' = O_RDWR | O_CREAT | O_EXCL. Fails if file exists.
|
|
38
|
+
fd = openSync(LOCK_PATH, "wx+", 0o600);
|
|
39
|
+
}
|
|
40
|
+
catch (_e) {
|
|
41
|
+
// File exists → check if the holder is alive.
|
|
42
|
+
if (isStaleLock()) {
|
|
43
|
+
// Best-effort: remove the stale file and retry once.
|
|
44
|
+
try {
|
|
45
|
+
unlinkSync(LOCK_PATH);
|
|
46
|
+
fd = openSync(LOCK_PATH, "wx+", 0o600);
|
|
47
|
+
}
|
|
48
|
+
catch (_e2) {
|
|
49
|
+
throw new LockHeldError(LOCK_PATH);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
throw new LockHeldError(LOCK_PATH);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Write our pid into the lockfile so we can detect stale locks later.
|
|
57
|
+
writeSync(fd, `${process.pid}\n`);
|
|
58
|
+
return {
|
|
59
|
+
fd,
|
|
60
|
+
release() {
|
|
61
|
+
try {
|
|
62
|
+
closeSync(fd);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
/* ignore */
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
unlinkSync(LOCK_PATH);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
/* ignore */
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function ensureParentDir() {
|
|
77
|
+
const dir = dirname(LOCK_PATH);
|
|
78
|
+
try {
|
|
79
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
/* exists or perms error — open will surface a clear failure later */
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function isStaleLock() {
|
|
86
|
+
try {
|
|
87
|
+
const raw = readFileSync(LOCK_PATH, "utf8").trim();
|
|
88
|
+
const pid = parseInt(raw, 10);
|
|
89
|
+
if (!Number.isFinite(pid) || pid <= 0)
|
|
90
|
+
return true;
|
|
91
|
+
if (pid === process.pid)
|
|
92
|
+
return true; // shouldn't happen, but defensive
|
|
93
|
+
try {
|
|
94
|
+
// Signal 0 = existence check; throws ESRCH if no such process.
|
|
95
|
+
process.kill(pid, 0);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
const code = e.code;
|
|
100
|
+
// ESRCH = no such pid → stale. EPERM = pid exists but we can't signal
|
|
101
|
+
// it (different uid) → treat as alive to be safe.
|
|
102
|
+
if (code === "ESRCH")
|
|
103
|
+
return true;
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
warn("[lockfile]", "stale-check failed:", e);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export const LOCK_FILE_PATH = LOCK_PATH;
|
|
113
|
+
//# sourceMappingURL=lockfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function log(tag: string, ...parts: unknown[]): void;
|
|
2
|
+
export declare function warn(tag: string, ...parts: unknown[]): void;
|
|
3
|
+
export declare function errLog(tag: string, ...parts: unknown[]): void;
|
|
4
|
+
export declare const LOG_PATH: string;
|
|
5
|
+
//# sourceMappingURL=logging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAiGA,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAG1D;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAE3D;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAE7D;AAED,eAAO,MAAM,QAAQ,QAAW,CAAC"}
|
package/dist/logging.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Structured logging for the sidecar daemon.
|
|
2
|
+
//
|
|
3
|
+
// Writes to ~/.earzbook/sidecar.log (via launchd/systemd's stdout redirect)
|
|
4
|
+
// AND mirrors to the process's stdout/stderr so `tail -f` works directly on
|
|
5
|
+
// the log file. Size-based rotation keeps the log bounded at ROTATE_BYTES;
|
|
6
|
+
// when exceeded, we truncate-and-rewrite-tail in place (no rename/dup-fd
|
|
7
|
+
// dance — launchd/systemd's append-mode fds tolerate this since we only
|
|
8
|
+
// affect bytes before the current write position).
|
|
9
|
+
//
|
|
10
|
+
// Format: `<ISO-8601> [pid=<PID>] <TAG> <message>` — one line per log call.
|
|
11
|
+
// Trace gating: set EARZBOOK_SIDECAR_DEBUG=1 for verbose; otherwise INFO+
|
|
12
|
+
// only. Errors always print.
|
|
13
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
const LOG_DIR = join(homedir(), ".earzbook");
|
|
17
|
+
const LOG_FILE = join(LOG_DIR, "openclaw.log");
|
|
18
|
+
const ROTATE_BYTES = 10 * 1024 * 1024; // 10 MB
|
|
19
|
+
const KEEP_TAIL_BYTES = 1 * 1024 * 1024; // keep last 1 MB after rotation
|
|
20
|
+
const DEBUG = process.env.EARZBOOK_SIDECAR_DEBUG === "1";
|
|
21
|
+
function ensureLogDir() {
|
|
22
|
+
if (!existsSync(LOG_DIR)) {
|
|
23
|
+
mkdirSync(LOG_DIR, { recursive: true, mode: 0o700 });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function maybeRotate() {
|
|
27
|
+
try {
|
|
28
|
+
if (!existsSync(LOG_FILE))
|
|
29
|
+
return;
|
|
30
|
+
const st = statSync(LOG_FILE);
|
|
31
|
+
if (st.size < ROTATE_BYTES)
|
|
32
|
+
return;
|
|
33
|
+
// Read the tail and overwrite the file. This is intentional: we don't
|
|
34
|
+
// rename to .1 because that would break launchd/systemd's open fd —
|
|
35
|
+
// they'd keep appending to the renamed file and we'd see no log.
|
|
36
|
+
const fd = readFileSync(LOG_FILE);
|
|
37
|
+
const tail = fd.slice(fd.length - KEEP_TAIL_BYTES);
|
|
38
|
+
writeFileSync(LOG_FILE, tail);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Rotation is best-effort; never let it crash logging.
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function formatLine(level, tag, parts) {
|
|
45
|
+
const ts = new Date().toISOString();
|
|
46
|
+
const body = parts
|
|
47
|
+
.map(p => {
|
|
48
|
+
if (p instanceof Error)
|
|
49
|
+
return `${p.message}${p.stack ? `\n${p.stack}` : ""}`;
|
|
50
|
+
if (typeof p === "object") {
|
|
51
|
+
try {
|
|
52
|
+
return JSON.stringify(p);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return String(p);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return String(p);
|
|
59
|
+
})
|
|
60
|
+
.join(" ");
|
|
61
|
+
return `${ts} [pid=${process.pid}] [${level}] ${tag} ${body}\n`;
|
|
62
|
+
}
|
|
63
|
+
// Whether stdout is a real terminal (dev: `earzbook-openclaw ...` in a
|
|
64
|
+
// shell) or a redirected file (launchd/systemd point StandardOutPath at the
|
|
65
|
+
// same log file we'd write to directly). When NOT a TTY, writing both to
|
|
66
|
+
// stdout AND appendFileSync to the same file produces duplicate lines —
|
|
67
|
+
// so we let stdout do all the work and skip the explicit file write.
|
|
68
|
+
const STDOUT_IS_TTY = Boolean(process.stdout.isTTY);
|
|
69
|
+
function emit(level, tag, parts) {
|
|
70
|
+
const line = formatLine(level, tag, parts);
|
|
71
|
+
if (STDOUT_IS_TTY) {
|
|
72
|
+
// Dev mode: stdout goes to the terminal. Also append to the log file
|
|
73
|
+
// so a `tail -f ~/.earzbook/openclaw.log` works during dev.
|
|
74
|
+
try {
|
|
75
|
+
ensureLogDir();
|
|
76
|
+
maybeRotate();
|
|
77
|
+
appendFileSync(LOG_FILE, line, { mode: 0o600 });
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
/* file write failed — terminal still has the line */
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const stream = level === "info" ? process.stdout : process.stderr;
|
|
84
|
+
stream.write(line);
|
|
85
|
+
}
|
|
86
|
+
export function log(tag, ...parts) {
|
|
87
|
+
if (!DEBUG && parts.length === 0)
|
|
88
|
+
return;
|
|
89
|
+
emit("info", tag, parts);
|
|
90
|
+
}
|
|
91
|
+
export function warn(tag, ...parts) {
|
|
92
|
+
emit("warn", tag, parts);
|
|
93
|
+
}
|
|
94
|
+
export function errLog(tag, ...parts) {
|
|
95
|
+
emit("error", tag, parts);
|
|
96
|
+
}
|
|
97
|
+
export const LOG_PATH = LOG_FILE;
|
|
98
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface LaunchdPlistInput {
|
|
2
|
+
/** Reverse-DNS label. Use "app.earzbook.sidecar". */
|
|
3
|
+
label: string;
|
|
4
|
+
/** Absolute path to the earzbook-openclaw binary (from `command -v`). */
|
|
5
|
+
binaryPath: string;
|
|
6
|
+
/** Absolute path to the sidecar config JSON. */
|
|
7
|
+
configPath: string;
|
|
8
|
+
/** Absolute path to the unified log file. */
|
|
9
|
+
logPath: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function renderLaunchdPlist(input: LaunchdPlistInput): string;
|
|
12
|
+
//# sourceMappingURL=launchd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launchd.d.ts","sourceRoot":"","sources":["../../src/platform/launchd.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAuBnE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Generate the LaunchAgent plist that registers the sidecar with launchd.
|
|
2
|
+
//
|
|
3
|
+
// Kept in code (rather than only in the bash pair script) so that a future
|
|
4
|
+
// in-app "repair connection" path can re-emit the plist after install if
|
|
5
|
+
// the file gets nuked. The pair script remains the primary install path.
|
|
6
|
+
export function renderLaunchdPlist(input) {
|
|
7
|
+
// ThrottleInterval=10 keeps launchd from tight-looping if we crash on
|
|
8
|
+
// startup; KeepAlive (only on non-success exit) ensures auto-restart.
|
|
9
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
10
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
11
|
+
<plist version="1.0">
|
|
12
|
+
<dict>
|
|
13
|
+
<key>Label</key><string>${escapeXml(input.label)}</string>
|
|
14
|
+
<key>ProgramArguments</key>
|
|
15
|
+
<array>
|
|
16
|
+
<string>${escapeXml(input.binaryPath)}</string>
|
|
17
|
+
<string>--config</string>
|
|
18
|
+
<string>${escapeXml(input.configPath)}</string>
|
|
19
|
+
</array>
|
|
20
|
+
<key>RunAtLoad</key><true/>
|
|
21
|
+
<key>KeepAlive</key>
|
|
22
|
+
<dict><key>SuccessfulExit</key><false/></dict>
|
|
23
|
+
<key>ThrottleInterval</key><integer>10</integer>
|
|
24
|
+
<key>StandardOutPath</key><string>${escapeXml(input.logPath)}</string>
|
|
25
|
+
<key>StandardErrorPath</key><string>${escapeXml(input.logPath)}</string>
|
|
26
|
+
</dict>
|
|
27
|
+
</plist>
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
function escapeXml(s) {
|
|
31
|
+
return s
|
|
32
|
+
.replace(/&/g, "&")
|
|
33
|
+
.replace(/</g, "<")
|
|
34
|
+
.replace(/>/g, ">")
|
|
35
|
+
.replace(/"/g, """);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=launchd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launchd.js","sourceRoot":"","sources":["../../src/platform/launchd.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,yEAAyE;AAazE,MAAM,UAAU,kBAAkB,CAAC,KAAwB;IACzD,sEAAsE;IACtE,sEAAsE;IACtE,OAAO;;;;4BAImB,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC;;;cAGpC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC;;cAE3B,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC;;;;;;sCAMH,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;wCACtB,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;;;CAG/D,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SystemdUnitInput {
|
|
2
|
+
/** Absolute path to the earzbook-openclaw binary. */
|
|
3
|
+
binaryPath: string;
|
|
4
|
+
/** Absolute path to the sidecar config JSON. */
|
|
5
|
+
configPath: string;
|
|
6
|
+
/** Absolute path to the log file. */
|
|
7
|
+
logPath: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function renderSystemdUnit(input: SystemdUnitInput): string;
|
|
10
|
+
//# sourceMappingURL=systemd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd.d.ts","sourceRoot":"","sources":["../../src/platform/systemd.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAejE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Generate the systemd --user unit that registers the sidecar.
|
|
2
|
+
export function renderSystemdUnit(input) {
|
|
3
|
+
return `[Unit]
|
|
4
|
+
Description=Earzbook OpenClaw sidecar
|
|
5
|
+
After=network-online.target
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
ExecStart=${input.binaryPath} --config ${input.configPath}
|
|
9
|
+
Restart=on-failure
|
|
10
|
+
RestartSec=10
|
|
11
|
+
StandardOutput=append:${input.logPath}
|
|
12
|
+
StandardError=append:${input.logPath}
|
|
13
|
+
|
|
14
|
+
[Install]
|
|
15
|
+
WantedBy=default.target
|
|
16
|
+
`;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=systemd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd.js","sourceRoot":"","sources":["../../src/platform/systemd.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAW/D,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,OAAO;;;;;YAKG,KAAK,CAAC,UAAU,aAAa,KAAK,CAAC,UAAU;;;wBAGjC,KAAK,CAAC,OAAO;uBACd,KAAK,CAAC,OAAO;;;;CAInC,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export interface VersionResponse {
|
|
3
|
+
latestVersion: string;
|
|
4
|
+
minVersion: string;
|
|
5
|
+
releasedAt?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface SelfUpdateOptions {
|
|
8
|
+
versionEndpoint: string;
|
|
9
|
+
installedVersion: string;
|
|
10
|
+
/** Override fetch for tests. */
|
|
11
|
+
fetchFn?: typeof fetch;
|
|
12
|
+
/** Override spawn for tests. */
|
|
13
|
+
spawnFn?: typeof spawn;
|
|
14
|
+
/** Inject for testing — skips real timer. */
|
|
15
|
+
scheduleTimer?: (cb: () => void, ms: number) => NodeJS.Timeout;
|
|
16
|
+
}
|
|
17
|
+
export interface SelfUpdateRunner {
|
|
18
|
+
/** Run one immediate version check + update if needed. */
|
|
19
|
+
checkNow(): Promise<{
|
|
20
|
+
action: "none" | "soft-update" | "force-update";
|
|
21
|
+
targetVersion?: string;
|
|
22
|
+
detail?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/** Schedule the daily background check. Call once after a successful first checkNow(). */
|
|
25
|
+
startDailyTimer(): void;
|
|
26
|
+
stop(): void;
|
|
27
|
+
}
|
|
28
|
+
export declare function createSelfUpdateRunner(opts: SelfUpdateOptions): SelfUpdateRunner;
|
|
29
|
+
/**
|
|
30
|
+
* Simple semver-less-than: split on dots, compare numerically. Pre-release
|
|
31
|
+
* suffixes (e.g. "0.1.0-rc.1") are ignored for the comparison — the
|
|
32
|
+
* version endpoint should only ever publish stable versions. Defensive on
|
|
33
|
+
* malformed input: a parse failure returns false (treat as equal).
|
|
34
|
+
*/
|
|
35
|
+
export declare function lt(a: string, b: string): boolean;
|
|
36
|
+
//# sourceMappingURL=self-update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-update.d.ts","sourceRoot":"","sources":["../src/self-update.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAS3C,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,OAAO,CAAC;CAChE;AAED,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,QAAQ,IAAI,OAAO,CAAC;QAClB,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,CAAC;QAChD,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,0FAA0F;IAC1F,eAAe,IAAI,IAAI,CAAC;IACxB,IAAI,IAAI,IAAI,CAAC;CACd;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,iBAAiB,GACtB,gBAAgB,CAqHlB;AAED;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAShD"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// Self-update: check the version endpoint at startup and once per day.
|
|
2
|
+
// Force-update (mandatory) if our installed version < minVersion, soft
|
|
3
|
+
// update (nice-to-have) if installed < latestVersion.
|
|
4
|
+
//
|
|
5
|
+
// "Force" path: spawn `npm install -g @earzbook/openclaw@<minVersion>`,
|
|
6
|
+
// then process.exit(0). launchd (KeepAlive=true) or systemd (Restart=on-
|
|
7
|
+
// failure) brings us back up; on the next start we run the freshly-
|
|
8
|
+
// installed binary. We exit cleanly with code 0 because this is NOT a
|
|
9
|
+
// failure — we WANT the supervisor to restart us with the new code.
|
|
10
|
+
//
|
|
11
|
+
// "Soft" path: same install command but we don't exit; the new code only
|
|
12
|
+
// takes effect on the next natural restart (machine reboot, manual kill).
|
|
13
|
+
// Acceptable for non-critical updates.
|
|
14
|
+
//
|
|
15
|
+
// We compare versions with a simple semver split — full semver-range
|
|
16
|
+
// libraries are overkill here and would bloat the bundle.
|
|
17
|
+
import { spawn } from "node:child_process";
|
|
18
|
+
import { log, warn, errLog } from "./logging.js";
|
|
19
|
+
const TAG = "[earzbook-sidecar:self-update]";
|
|
20
|
+
const NPM_PACKAGE = "@earzbook/openclaw";
|
|
21
|
+
const DAILY_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
22
|
+
export function createSelfUpdateRunner(opts) {
|
|
23
|
+
const fetchFn = opts.fetchFn ?? fetch;
|
|
24
|
+
const spawnFn = opts.spawnFn ?? spawn;
|
|
25
|
+
const scheduleTimer = opts.scheduleTimer ?? setInterval;
|
|
26
|
+
let dailyTimer = null;
|
|
27
|
+
async function fetchVersionInfo() {
|
|
28
|
+
try {
|
|
29
|
+
const res = await fetchFn(opts.versionEndpoint, {
|
|
30
|
+
headers: { Accept: "application/json" },
|
|
31
|
+
});
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
warn(TAG, `version endpoint returned ${res.status}`);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const body = (await res.json());
|
|
37
|
+
if (typeof body.latestVersion !== "string" ||
|
|
38
|
+
typeof body.minVersion !== "string") {
|
|
39
|
+
warn(TAG, "version endpoint returned malformed body");
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return body;
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
46
|
+
warn(TAG, `version endpoint fetch failed: ${msg}`);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function runNpmInstall(targetVersion) {
|
|
51
|
+
return new Promise(resolve => {
|
|
52
|
+
log(TAG, `running: npm install -g ${NPM_PACKAGE}@${targetVersion}`);
|
|
53
|
+
const child = spawnFn("npm", ["install", "-g", `${NPM_PACKAGE}@${targetVersion}`], {
|
|
54
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
55
|
+
});
|
|
56
|
+
let stderr = "";
|
|
57
|
+
child.stderr?.on("data", c => {
|
|
58
|
+
stderr += c.toString();
|
|
59
|
+
});
|
|
60
|
+
child.on("error", (e) => {
|
|
61
|
+
errLog(TAG, `npm install errored: ${e.message}`);
|
|
62
|
+
resolve({ ok: false, detail: e.message });
|
|
63
|
+
});
|
|
64
|
+
child.on("close", code => {
|
|
65
|
+
if (code === 0) {
|
|
66
|
+
log(TAG, `npm install ok`);
|
|
67
|
+
resolve({ ok: true, detail: "" });
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const tail = stderr.slice(-300).trim();
|
|
71
|
+
warn(TAG, `npm install exit=${code} stderr-tail="${tail}"`);
|
|
72
|
+
resolve({ ok: false, detail: `exit=${code} ${tail}` });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async function checkNow() {
|
|
78
|
+
const info = await fetchVersionInfo();
|
|
79
|
+
if (!info)
|
|
80
|
+
return { action: "none", detail: "version-endpoint-unreachable" };
|
|
81
|
+
if (lt(opts.installedVersion, info.minVersion)) {
|
|
82
|
+
log(TAG, `installed=${opts.installedVersion} < minVersion=${info.minVersion} — forcing update`);
|
|
83
|
+
const result = await runNpmInstall(info.minVersion);
|
|
84
|
+
if (result.ok) {
|
|
85
|
+
// Tell the caller — they will exit(0) and let supervisor relaunch.
|
|
86
|
+
return { action: "force-update", targetVersion: info.minVersion };
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
action: "none",
|
|
90
|
+
detail: `force-update install failed: ${result.detail}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (lt(opts.installedVersion, info.latestVersion)) {
|
|
94
|
+
log(TAG, `installed=${opts.installedVersion} < latestVersion=${info.latestVersion} — soft updating`);
|
|
95
|
+
const result = await runNpmInstall(info.latestVersion);
|
|
96
|
+
if (result.ok) {
|
|
97
|
+
return { action: "soft-update", targetVersion: info.latestVersion };
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
action: "none",
|
|
101
|
+
detail: `soft-update install failed: ${result.detail}`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
log(TAG, `installed=${opts.installedVersion} is current (latest=${info.latestVersion})`);
|
|
105
|
+
return { action: "none" };
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
checkNow,
|
|
109
|
+
startDailyTimer() {
|
|
110
|
+
if (dailyTimer)
|
|
111
|
+
return;
|
|
112
|
+
dailyTimer = scheduleTimer(() => {
|
|
113
|
+
void checkNow();
|
|
114
|
+
}, DAILY_CHECK_INTERVAL_MS);
|
|
115
|
+
log(TAG, `daily update check scheduled (every ${DAILY_CHECK_INTERVAL_MS / 1000}s)`);
|
|
116
|
+
},
|
|
117
|
+
stop() {
|
|
118
|
+
if (dailyTimer) {
|
|
119
|
+
clearInterval(dailyTimer);
|
|
120
|
+
dailyTimer = null;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Simple semver-less-than: split on dots, compare numerically. Pre-release
|
|
127
|
+
* suffixes (e.g. "0.1.0-rc.1") are ignored for the comparison — the
|
|
128
|
+
* version endpoint should only ever publish stable versions. Defensive on
|
|
129
|
+
* malformed input: a parse failure returns false (treat as equal).
|
|
130
|
+
*/
|
|
131
|
+
export function lt(a, b) {
|
|
132
|
+
const pa = parseSemver(a);
|
|
133
|
+
const pb = parseSemver(b);
|
|
134
|
+
if (!pa || !pb)
|
|
135
|
+
return false;
|
|
136
|
+
for (let i = 0; i < 3; i++) {
|
|
137
|
+
if (pa[i] < pb[i])
|
|
138
|
+
return true;
|
|
139
|
+
if (pa[i] > pb[i])
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
function parseSemver(s) {
|
|
145
|
+
const cleaned = s.replace(/^v/, "").split("-")[0].split("+")[0];
|
|
146
|
+
const parts = cleaned.split(".").map(p => parseInt(p, 10));
|
|
147
|
+
if (parts.length !== 3 || parts.some(p => !Number.isFinite(p)))
|
|
148
|
+
return null;
|
|
149
|
+
return [parts[0], parts[1], parts[2]];
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=self-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-update.js","sourceRoot":"","sources":["../src/self-update.ts"],"names":[],"mappings":"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"}
|