frely-cli 0.6.2 → 0.6.8
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 +117 -50
- package/dist/agent-help.d.ts +47 -58
- package/dist/agent-help.js +24 -10
- package/dist/agent-help.js.map +1 -1
- package/dist/cloud.d.ts +7 -0
- package/dist/cloud.js +263 -0
- package/dist/cloud.js.map +1 -0
- package/dist/device/connection-status.d.ts +45 -0
- package/dist/device/connection-status.js +132 -0
- package/dist/device/connection-status.js.map +1 -0
- package/dist/device/control.d.ts +2 -3
- package/dist/device/control.js +50 -5
- package/dist/device/control.js.map +1 -1
- package/dist/device/relay-client.d.ts +6 -1
- package/dist/device/relay-client.js +148 -44
- package/dist/device/relay-client.js.map +1 -1
- package/dist/device/transport.d.ts +10 -0
- package/dist/device/transport.js +24 -0
- package/dist/device/transport.js.map +1 -0
- package/dist/diagnostics.d.ts +66 -4
- package/dist/diagnostics.js +133 -25
- package/dist/diagnostics.js.map +1 -1
- package/dist/index.js +35 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp-authorization.js +3 -3
- package/dist/mcp-authorization.js.map +1 -1
- package/dist/mcp-command.d.ts +9 -0
- package/dist/mcp-command.js +68 -0
- package/dist/mcp-command.js.map +1 -0
- package/dist/runtime/mcp.d.ts +2 -0
- package/dist/runtime/mcp.js +35 -3
- package/dist/runtime/mcp.js.map +1 -1
- package/dist/runtime/process-tree.js +33 -2
- package/dist/runtime/process-tree.js.map +1 -1
- package/dist/service.d.ts +4 -0
- package/dist/service.js +28 -4
- package/dist/service.js.map +1 -1
- package/dist/upgrade/installation.d.ts +24 -0
- package/dist/upgrade/installation.js +137 -0
- package/dist/upgrade/installation.js.map +1 -0
- package/dist/upgrade/maintenance.d.ts +15 -0
- package/dist/upgrade/maintenance.js +133 -0
- package/dist/upgrade/maintenance.js.map +1 -0
- package/dist/upgrade/release.d.ts +9 -0
- package/dist/upgrade/release.js +45 -0
- package/dist/upgrade/release.js.map +1 -0
- package/dist/upgrade/service-refresh.d.ts +38 -0
- package/dist/upgrade/service-refresh.js +138 -0
- package/dist/upgrade/service-refresh.js.map +1 -0
- package/dist/upgrade/update.d.ts +49 -0
- package/dist/upgrade/update.js +228 -0
- package/dist/upgrade/update.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createConnection, createServer } from "node:net";
|
|
2
|
+
import { chmod, lstat, mkdir, rm } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
/** An existing relay owns this gate; no updater daemon or remote upgrade jobs. */
|
|
6
|
+
export class MaintenanceGate {
|
|
7
|
+
paused = false;
|
|
8
|
+
requests = 0;
|
|
9
|
+
processes = new Set();
|
|
10
|
+
enter() {
|
|
11
|
+
if (this.paused)
|
|
12
|
+
throw new Error("Frely is preparing an upgrade. Retry after it completes.");
|
|
13
|
+
return this.track();
|
|
14
|
+
}
|
|
15
|
+
track() {
|
|
16
|
+
this.requests++;
|
|
17
|
+
let done = false;
|
|
18
|
+
return () => { if (!done) {
|
|
19
|
+
done = true;
|
|
20
|
+
this.requests--;
|
|
21
|
+
} };
|
|
22
|
+
}
|
|
23
|
+
registerProcesses(count) {
|
|
24
|
+
this.processes.add(count);
|
|
25
|
+
return () => this.processes.delete(count);
|
|
26
|
+
}
|
|
27
|
+
pause() {
|
|
28
|
+
if (this.paused)
|
|
29
|
+
throw new Error("Another upgrade holds this service.");
|
|
30
|
+
this.paused = true;
|
|
31
|
+
}
|
|
32
|
+
resume() { this.paused = false; }
|
|
33
|
+
get idle() { return this.requests === 0 && [...this.processes].every((count) => count() === 0); }
|
|
34
|
+
}
|
|
35
|
+
export function maintenancePath(pid) {
|
|
36
|
+
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "frely", `upgrade-${pid}.sock`);
|
|
37
|
+
}
|
|
38
|
+
export async function serveMaintenance(gate, path = maintenancePath(process.pid)) {
|
|
39
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
40
|
+
const directory = await lstat(dirname(path));
|
|
41
|
+
if (directory.isSymbolicLink() || !directory.isDirectory() || directory.uid !== process.getuid?.())
|
|
42
|
+
throw new Error("Unsafe maintenance directory.");
|
|
43
|
+
await chmod(dirname(path), 0o700);
|
|
44
|
+
let owner;
|
|
45
|
+
const sockets = new Set();
|
|
46
|
+
const server = createServer((socket) => {
|
|
47
|
+
sockets.add(socket);
|
|
48
|
+
socket.on("error", () => socket.destroy());
|
|
49
|
+
socket.on("close", () => { sockets.delete(socket); if (owner === socket) {
|
|
50
|
+
owner = undefined;
|
|
51
|
+
gate.resume();
|
|
52
|
+
} });
|
|
53
|
+
socket.setTimeout(2000, () => socket.destroy());
|
|
54
|
+
let input = "";
|
|
55
|
+
socket.on("data", (data) => {
|
|
56
|
+
input += data.toString("utf8");
|
|
57
|
+
if (input.length > 32 || owner === socket) {
|
|
58
|
+
socket.destroy();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (!input.includes("\n"))
|
|
62
|
+
return;
|
|
63
|
+
if (input !== "drain\n" || owner) {
|
|
64
|
+
socket.end("busy\n");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// The runtime may own maintenance for an external installation refresh.
|
|
68
|
+
try {
|
|
69
|
+
gate.pause();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
socket.end("busy\n");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
owner = socket;
|
|
76
|
+
socket.setTimeout(0);
|
|
77
|
+
const deadline = Date.now() + 3000;
|
|
78
|
+
const interval = setInterval(() => {
|
|
79
|
+
if (gate.idle) {
|
|
80
|
+
clearInterval(interval);
|
|
81
|
+
socket.write("ready\n");
|
|
82
|
+
}
|
|
83
|
+
else if (Date.now() >= deadline) {
|
|
84
|
+
clearInterval(interval);
|
|
85
|
+
socket.end("busy\n");
|
|
86
|
+
}
|
|
87
|
+
}, 50);
|
|
88
|
+
socket.once("close", () => clearInterval(interval));
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
server.maxConnections = 4;
|
|
92
|
+
// Refuse an existing socket instead of unlinking another runtime's endpoint.
|
|
93
|
+
await new Promise((resolve, reject) => {
|
|
94
|
+
server.once("error", reject);
|
|
95
|
+
server.listen(path, () => { server.off("error", reject); resolve(); });
|
|
96
|
+
});
|
|
97
|
+
await chmod(path, 0o600);
|
|
98
|
+
return async () => {
|
|
99
|
+
for (const socket of sockets)
|
|
100
|
+
socket.destroy();
|
|
101
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
102
|
+
await rm(path, { force: true });
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export async function acquireMaintenance(pid, path = maintenancePath(pid)) {
|
|
106
|
+
const info = await lstat(path).catch(() => null);
|
|
107
|
+
if (!info?.isSocket() || info.uid !== process.getuid?.() || (info.mode & 0o077) !== 0) {
|
|
108
|
+
throw new Error("The running service has no private upgrade endpoint. Finish its tasks and restart it from a local terminal before upgrading.");
|
|
109
|
+
}
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
const socket = createConnection(path);
|
|
112
|
+
const fail = () => { socket.destroy(); reject(new Error("The service is busy or cannot enter maintenance. Finish its tasks, then run frely upgrade in a local terminal.")); };
|
|
113
|
+
socket.setTimeout(5000, fail);
|
|
114
|
+
socket.once("error", fail);
|
|
115
|
+
socket.once("connect", () => socket.write("drain\n"));
|
|
116
|
+
let text = "", ready = false;
|
|
117
|
+
socket.on("data", (data) => {
|
|
118
|
+
text += data.toString("utf8");
|
|
119
|
+
if (text.length > 32 || (text.includes("\n") && text !== "ready\n")) {
|
|
120
|
+
fail();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (text === "ready\n") {
|
|
124
|
+
ready = true;
|
|
125
|
+
socket.setTimeout(0);
|
|
126
|
+
resolve(() => socket.destroy());
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
socket.once("close", () => { if (!ready)
|
|
130
|
+
fail(); });
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=maintenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/upgrade/maintenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Installation } from "./installation.js";
|
|
2
|
+
export interface Release {
|
|
3
|
+
version: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function stableVersion(value: unknown): string;
|
|
7
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
8
|
+
export declare function latestRelease(installation: Installation, request?: typeof fetch): Promise<Release>;
|
|
9
|
+
export declare function standaloneAsset(platform?: NodeJS.Platform, arch?: NodeJS.Architecture, target?: string | undefined): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export function stableVersion(value) {
|
|
2
|
+
if (typeof value !== "string" || !/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u.test(value))
|
|
3
|
+
throw new Error("Release source did not return a stable version.");
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
export function compareVersions(a, b) {
|
|
7
|
+
const parse = (v) => {
|
|
8
|
+
const core = v.split("-")[0].split("+")[0];
|
|
9
|
+
return stableVersion(core).split(".").map(BigInt);
|
|
10
|
+
};
|
|
11
|
+
const aa = parse(a), bb = parse(b);
|
|
12
|
+
for (let i = 0; i < 3; i++)
|
|
13
|
+
if (aa[i] !== bb[i])
|
|
14
|
+
return aa[i] > bb[i] ? 1 : -1;
|
|
15
|
+
return a.includes("-") === b.includes("-") ? 0 : a.includes("-") ? -1 : 1;
|
|
16
|
+
}
|
|
17
|
+
export async function latestRelease(installation, request = fetch) {
|
|
18
|
+
const standalone = installation.method === "standalone";
|
|
19
|
+
const response = await request(standalone
|
|
20
|
+
? "https://api.github.com/repos/FrelyHQ/frely-cli/releases/latest"
|
|
21
|
+
: "https://registry.npmjs.org/frely-cli/latest", {
|
|
22
|
+
headers: { accept: "application/json", "user-agent": "frely-cli" },
|
|
23
|
+
signal: AbortSignal.timeout(4000), redirect: "error",
|
|
24
|
+
});
|
|
25
|
+
if (!response.ok)
|
|
26
|
+
throw new Error(`Release lookup failed (HTTP ${response.status}).`);
|
|
27
|
+
const text = await response.text();
|
|
28
|
+
if (text.length > 1024 * 1024)
|
|
29
|
+
throw new Error("Release metadata is too large.");
|
|
30
|
+
const data = JSON.parse(text);
|
|
31
|
+
if (standalone && (data.draft !== false || data.prerelease !== false))
|
|
32
|
+
throw new Error("GitHub release is not a stable published release.");
|
|
33
|
+
const version = stableVersion(standalone ? String(data.tag_name).replace(/^v/u, "") : data.version);
|
|
34
|
+
if (!standalone && data.name !== "frely-cli")
|
|
35
|
+
throw new Error("Release package name does not match frely-cli.");
|
|
36
|
+
return { version, ...(standalone ? { baseUrl: `https://github.com/FrelyHQ/frely-cli/releases/download/v${version}` } : {}) };
|
|
37
|
+
}
|
|
38
|
+
export function standaloneAsset(platform = process.platform, arch = process.arch, target = typeof FRELY_BUILD_TARGET === "string" ? FRELY_BUILD_TARGET : undefined) {
|
|
39
|
+
// Compiled target includes libc, so an Alpine executable never changes distribution during an upgrade.
|
|
40
|
+
const value = target ?? `${platform === "win32" ? "windows" : platform}-${arch}`;
|
|
41
|
+
if (!/^(?:darwin-(?:arm64|x64)|linux-(?:arm64|x64)(?:-musl)?|windows-(?:arm64|x64))$/u.test(value))
|
|
42
|
+
throw new Error("This platform has no standalone release.");
|
|
43
|
+
return `frely-${value}${value.startsWith("windows") ? ".exe" : ""}`;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=release.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release.js","sourceRoot":"","sources":["../../src/upgrade/release.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type DiagnosticLog } from "../runtime/diagnostics.js";
|
|
2
|
+
import { type Installation } from "./installation.js";
|
|
3
|
+
import type { MaintenanceGate } from "./maintenance.js";
|
|
4
|
+
export interface InstalledCandidate {
|
|
5
|
+
fingerprint: string;
|
|
6
|
+
version: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RefreshProbe {
|
|
9
|
+
read(): Promise<InstalledCandidate>;
|
|
10
|
+
verify(candidate: InstalledCandidate): Promise<boolean>;
|
|
11
|
+
}
|
|
12
|
+
/** Inspect only the installation this process already runs; never follow PATH or download code. */
|
|
13
|
+
export declare function installationProbe(installation: Installation): RefreshProbe;
|
|
14
|
+
/** One tick at a time. Busy work keeps its connection and admission; only idle runtimes drain. */
|
|
15
|
+
export declare class ServiceRefresh {
|
|
16
|
+
private readonly options;
|
|
17
|
+
private candidate;
|
|
18
|
+
private checking;
|
|
19
|
+
private restarting;
|
|
20
|
+
private deferredFingerprint;
|
|
21
|
+
constructor(options: {
|
|
22
|
+
probe: RefreshProbe;
|
|
23
|
+
gate: MaintenanceGate;
|
|
24
|
+
signal: AbortSignal;
|
|
25
|
+
restart: () => void;
|
|
26
|
+
log?: DiagnosticLog;
|
|
27
|
+
currentVersion?: string;
|
|
28
|
+
});
|
|
29
|
+
check(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
/** Only an already-running managed POSIX service watches its supported installation. */
|
|
32
|
+
export declare function watchServiceInstallation(options: {
|
|
33
|
+
gate: MaintenanceGate;
|
|
34
|
+
signal: AbortSignal;
|
|
35
|
+
restart: () => void;
|
|
36
|
+
log?: DiagnosticLog;
|
|
37
|
+
onEnabled?: () => void;
|
|
38
|
+
}): Promise<() => void>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { execFile as execFileCallback } from "node:child_process";
|
|
2
|
+
import { readFile, stat } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { VERSION } from "../version.js";
|
|
7
|
+
import { diagnostic } from "../runtime/diagnostics.js";
|
|
8
|
+
import { inspectInstallation } from "./installation.js";
|
|
9
|
+
const execFile = promisify(execFileCallback);
|
|
10
|
+
/** Inspect only the installation this process already runs; never follow PATH or download code. */
|
|
11
|
+
export function installationProbe(installation) {
|
|
12
|
+
let standaloneCache;
|
|
13
|
+
const version = async () => {
|
|
14
|
+
const standalone = installation.method === "standalone";
|
|
15
|
+
const result = await execFile(standalone ? installation.entry : process.execPath, standalone ? ["--version"] : [installation.entry, "--version"], { cwd: homedir(), timeout: 10000, maxBuffer: 65536 });
|
|
16
|
+
const value = result.stdout.trim();
|
|
17
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u.test(value))
|
|
18
|
+
throw new Error("Invalid installed CLI version.");
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
21
|
+
const fingerprint = async () => {
|
|
22
|
+
const files = installation.method === "standalone" ? [installation.entry]
|
|
23
|
+
: [installation.entry, join(dirname(dirname(installation.entry)), "package.json")];
|
|
24
|
+
return (await Promise.all(files.map(async (path) => {
|
|
25
|
+
const info = await stat(path, { bigint: true });
|
|
26
|
+
if (!info.isFile())
|
|
27
|
+
throw new Error("Installed CLI file is unavailable.");
|
|
28
|
+
return [info.dev, info.ino, info.size, info.mtimeNs, info.ctimeNs].join(":");
|
|
29
|
+
}))).join("|");
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
async read() {
|
|
33
|
+
const before = await fingerprint();
|
|
34
|
+
let installed;
|
|
35
|
+
if (installation.method === "standalone") {
|
|
36
|
+
if (standaloneCache?.fingerprint === before)
|
|
37
|
+
return standaloneCache;
|
|
38
|
+
installed = await version();
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const metadata = JSON.parse(await readFile(join(dirname(dirname(installation.entry)), "package.json"), "utf8"));
|
|
42
|
+
if (metadata.name !== "frely-cli" || typeof metadata.version !== "string")
|
|
43
|
+
throw new Error("Installed package is unavailable.");
|
|
44
|
+
installed = metadata.version;
|
|
45
|
+
}
|
|
46
|
+
if (before !== await fingerprint())
|
|
47
|
+
throw new Error("Installation is changing.");
|
|
48
|
+
const candidate = { fingerprint: before, version: installed };
|
|
49
|
+
if (installation.method === "standalone")
|
|
50
|
+
standaloneCache = candidate;
|
|
51
|
+
return candidate;
|
|
52
|
+
},
|
|
53
|
+
async verify(candidate) {
|
|
54
|
+
return await fingerprint() === candidate.fingerprint && await version() === candidate.version
|
|
55
|
+
&& await fingerprint() === candidate.fingerprint;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** One tick at a time. Busy work keeps its connection and admission; only idle runtimes drain. */
|
|
60
|
+
export class ServiceRefresh {
|
|
61
|
+
options;
|
|
62
|
+
candidate;
|
|
63
|
+
checking = false;
|
|
64
|
+
restarting = false;
|
|
65
|
+
deferredFingerprint;
|
|
66
|
+
constructor(options) {
|
|
67
|
+
this.options = options;
|
|
68
|
+
}
|
|
69
|
+
async check() {
|
|
70
|
+
if (this.checking || this.restarting || this.options.signal.aborted)
|
|
71
|
+
return;
|
|
72
|
+
this.checking = true;
|
|
73
|
+
let paused = false;
|
|
74
|
+
const { probe, gate, signal, restart, log } = this.options;
|
|
75
|
+
try {
|
|
76
|
+
const candidate = await probe.read();
|
|
77
|
+
if (candidate.version === (this.options.currentVersion ?? VERSION)) {
|
|
78
|
+
this.candidate = undefined;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Two observations, separated by the polling interval, avoid switching during package extraction.
|
|
82
|
+
if (this.candidate?.fingerprint !== candidate.fingerprint || this.candidate.version !== candidate.version) {
|
|
83
|
+
this.candidate = candidate;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (signal.aborted)
|
|
87
|
+
return;
|
|
88
|
+
if (!gate.idle) {
|
|
89
|
+
if (this.deferredFingerprint !== candidate.fingerprint) {
|
|
90
|
+
diagnostic(log, "relay.upgrade_deferred");
|
|
91
|
+
this.deferredFingerprint = candidate.fingerprint;
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// An explicit frely upgrade may already own maintenance. Never resume another owner's gate.
|
|
96
|
+
try {
|
|
97
|
+
gate.pause();
|
|
98
|
+
paused = true;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!await probe.verify(candidate) || signal.aborted || !gate.idle)
|
|
104
|
+
return;
|
|
105
|
+
diagnostic(log, "relay.upgrade_restart");
|
|
106
|
+
restart();
|
|
107
|
+
this.restarting = true;
|
|
108
|
+
// Keep admission closed while the relay flushes and exits. Its existing supervisor restarts it.
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Missing files and unsuccessful startup are expected during external installation.
|
|
112
|
+
// Keep the loaded runtime alive and require two fresh observations before retrying.
|
|
113
|
+
this.candidate = undefined;
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
if (paused && !this.restarting)
|
|
117
|
+
gate.resume();
|
|
118
|
+
this.checking = false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Only an already-running managed POSIX service watches its supported installation. */
|
|
123
|
+
export async function watchServiceInstallation(options) {
|
|
124
|
+
if (options.signal.aborted || !["darwin", "linux"].includes(process.platform))
|
|
125
|
+
return () => { };
|
|
126
|
+
const installation = await inspectInstallation();
|
|
127
|
+
if (options.signal.aborted || !["standalone", "npm", "bun"].includes(installation.method))
|
|
128
|
+
return () => { };
|
|
129
|
+
options.onEnabled?.();
|
|
130
|
+
const refresh = new ServiceRefresh({ ...options, probe: installationProbe(installation) });
|
|
131
|
+
const timer = setInterval(() => { void refresh.check(); }, 5000);
|
|
132
|
+
timer.unref();
|
|
133
|
+
const close = () => { clearInterval(timer); options.signal.removeEventListener("abort", close); };
|
|
134
|
+
options.signal.addEventListener("abort", close, { once: true });
|
|
135
|
+
void refresh.check();
|
|
136
|
+
return close;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=service-refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-refresh.js","sourceRoot":"","sources":["../../src/upgrade/service-refresh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { readDeviceBinding } from "../device/state.js";
|
|
2
|
+
import { readConnectionStatus } from "../device/connection-status.js";
|
|
3
|
+
import { serviceCommand, serviceStatus, startMcpService, stopMcpService } from "../service.js";
|
|
4
|
+
import { inspectInstallation, type Installation } from "./installation.js";
|
|
5
|
+
import { latestRelease, type Release } from "./release.js";
|
|
6
|
+
import { acquireMaintenance } from "./maintenance.js";
|
|
7
|
+
export interface UpgradeResult {
|
|
8
|
+
state: "current" | "manual" | "upgraded";
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
export interface UpgradeInspection {
|
|
12
|
+
currentVersion: string;
|
|
13
|
+
latestVersion?: string;
|
|
14
|
+
installation: Installation;
|
|
15
|
+
state: "unsupported" | "available" | "current" | "unavailable";
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function inspectUpgrade(): Promise<UpgradeInspection>;
|
|
19
|
+
export declare function installedVersion(installation: Installation): Promise<string>;
|
|
20
|
+
declare function download(url: string, destination: string, maxBytes: number): Promise<void>;
|
|
21
|
+
export declare function validateStandalone(path: string, checksum: string, version: string, execute?: typeof installedVersion): Promise<void>;
|
|
22
|
+
export interface PreparedUpdate {
|
|
23
|
+
apply(): Promise<void>;
|
|
24
|
+
restore(): Promise<void>;
|
|
25
|
+
cleanup(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare function prepareStandalone(installation: Installation, release: Release, fetchFile?: typeof download, execute?: typeof installedVersion): Promise<PreparedUpdate>;
|
|
28
|
+
declare function installPackage(installation: Installation, version: string): Promise<void>;
|
|
29
|
+
declare function lockInstallation(installation: Installation): Promise<() => Promise<void>>;
|
|
30
|
+
declare const defaults: {
|
|
31
|
+
inspectInstallation: typeof inspectInstallation;
|
|
32
|
+
latestRelease: typeof latestRelease;
|
|
33
|
+
installedVersion: typeof installedVersion;
|
|
34
|
+
serviceStatus: typeof serviceStatus;
|
|
35
|
+
serviceCommand: typeof serviceCommand;
|
|
36
|
+
stopMcpService: typeof stopMcpService;
|
|
37
|
+
startMcpService: typeof startMcpService;
|
|
38
|
+
readDeviceBinding: typeof readDeviceBinding;
|
|
39
|
+
readConnectionStatus: typeof readConnectionStatus;
|
|
40
|
+
acquireMaintenance: typeof acquireMaintenance;
|
|
41
|
+
prepareStandalone: typeof prepareStandalone;
|
|
42
|
+
installPackage: typeof installPackage;
|
|
43
|
+
lockInstallation: typeof lockInstallation;
|
|
44
|
+
pause: (ms: number) => Promise<unknown>;
|
|
45
|
+
};
|
|
46
|
+
export type UpgradeDependencies = typeof defaults;
|
|
47
|
+
/** Upgrade in the calling terminal. Busy MCP callers fail before any service stop or package write. */
|
|
48
|
+
export declare function upgrade(write: (message: string) => void, dependencies?: UpgradeDependencies): Promise<UpgradeResult>;
|
|
49
|
+
export {};
|