@cli-remote/local 0.0.2 → 0.0.3
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.cjs +217 -44
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -9940,6 +9940,8 @@ var require_lib = __commonJS({
|
|
|
9940
9940
|
|
|
9941
9941
|
// src/index.ts
|
|
9942
9942
|
var import_node_fs2 = require("node:fs");
|
|
9943
|
+
var import_node_child_process2 = require("node:child_process");
|
|
9944
|
+
var import_node_os5 = require("node:os");
|
|
9943
9945
|
var import_node_path5 = require("node:path");
|
|
9944
9946
|
var import_node_url = require("node:url");
|
|
9945
9947
|
|
|
@@ -9978,6 +9980,7 @@ var ACCESS_TOKEN_TTL_MS = 60 * 6e4;
|
|
|
9978
9980
|
var REFRESH_TOKEN_TTL_MS = 30 * 24 * 60 * 6e4;
|
|
9979
9981
|
var REFRESH_MARGIN_MS = 5 * 6e4;
|
|
9980
9982
|
var OUTPUT_BUFFER_SIZE = 500;
|
|
9983
|
+
var RECONNECT_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
9981
9984
|
var DEFAULT_CONFIG_DIR = ".cli-remote";
|
|
9982
9985
|
var CREDENTIALS_FILE = "credentials.json";
|
|
9983
9986
|
var CONFIG_FILE = "config.json";
|
|
@@ -10211,6 +10214,10 @@ var SessionLogger = class {
|
|
|
10211
10214
|
if (this.closed) return;
|
|
10212
10215
|
this.write({ ts: Date.now(), event: "rejected", cmd, reason, dangerous });
|
|
10213
10216
|
}
|
|
10217
|
+
logForced(cmd) {
|
|
10218
|
+
if (this.closed) return;
|
|
10219
|
+
this.write({ ts: Date.now(), event: "forced", cmd });
|
|
10220
|
+
}
|
|
10214
10221
|
logExit(code) {
|
|
10215
10222
|
if (this.closed) return;
|
|
10216
10223
|
this.write({ ts: Date.now(), event: "exit", code });
|
|
@@ -10600,23 +10607,17 @@ async function startLocal(opts = {}) {
|
|
|
10600
10607
|
console.log(`[local] connecting to ${url}`);
|
|
10601
10608
|
console.log(`[local] deviceId=${credentials.deviceId}`);
|
|
10602
10609
|
console.log(`[local] whitelist: ${whitelist.size} commands`);
|
|
10603
|
-
|
|
10610
|
+
let ws = null;
|
|
10604
10611
|
let heartbeatTimer = null;
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
lineBuffers.clear();
|
|
10612
|
+
let reconnectTimer = null;
|
|
10613
|
+
let reconnectAttempts = 0;
|
|
10614
|
+
let userExitCode = null;
|
|
10615
|
+
function stopHeartbeat() {
|
|
10610
10616
|
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
|
10611
|
-
|
|
10612
|
-
ws.close();
|
|
10613
|
-
} catch {
|
|
10614
|
-
}
|
|
10615
|
-
process.exit(code);
|
|
10617
|
+
heartbeatTimer = null;
|
|
10616
10618
|
}
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
ws.send(
|
|
10619
|
+
function sendAuth() {
|
|
10620
|
+
ws?.send(
|
|
10620
10621
|
encodeFrame({
|
|
10621
10622
|
t: "auth",
|
|
10622
10623
|
role: "bridge",
|
|
@@ -10624,13 +10625,73 @@ async function startLocal(opts = {}) {
|
|
|
10624
10625
|
token: credentials.accessToken
|
|
10625
10626
|
})
|
|
10626
10627
|
);
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
|
|
10633
|
-
|
|
10628
|
+
}
|
|
10629
|
+
function connect() {
|
|
10630
|
+
if (userExitCode !== null) return;
|
|
10631
|
+
const sock = new wrapper_default(url);
|
|
10632
|
+
ws = sock;
|
|
10633
|
+
sock.on("open", () => {
|
|
10634
|
+
console.log("[local] connected");
|
|
10635
|
+
sendAuth();
|
|
10636
|
+
stopHeartbeat();
|
|
10637
|
+
heartbeatTimer = setInterval(() => {
|
|
10638
|
+
if (sock.readyState === wrapper_default.OPEN) {
|
|
10639
|
+
sock.send(encodeFrame({ t: "ping" }));
|
|
10640
|
+
}
|
|
10641
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
10642
|
+
});
|
|
10643
|
+
sock.on("message", (raw) => handleFrame(sock, raw));
|
|
10644
|
+
sock.on("close", () => {
|
|
10645
|
+
stopHeartbeat();
|
|
10646
|
+
if (ws === sock) ws = null;
|
|
10647
|
+
if (userExitCode !== null) {
|
|
10648
|
+
process.exit(userExitCode);
|
|
10649
|
+
}
|
|
10650
|
+
console.log("[local] disconnected; PTY sessions kept alive, reconnecting\u2026");
|
|
10651
|
+
scheduleReconnect();
|
|
10652
|
+
});
|
|
10653
|
+
sock.on("error", (err) => {
|
|
10654
|
+
console.error("[local] ws error:", err.message);
|
|
10655
|
+
});
|
|
10656
|
+
}
|
|
10657
|
+
async function scheduleReconnect() {
|
|
10658
|
+
if (reconnectTimer || userExitCode !== null) return;
|
|
10659
|
+
const idx = Math.min(reconnectAttempts, RECONNECT_DELAYS_MS.length - 1);
|
|
10660
|
+
const delay = RECONNECT_DELAYS_MS[idx];
|
|
10661
|
+
reconnectAttempts++;
|
|
10662
|
+
console.log(`[local] reconnecting in ${Math.round(delay / 1e3)}s (attempt ${reconnectAttempts})`);
|
|
10663
|
+
reconnectTimer = setTimeout(() => {
|
|
10664
|
+
reconnectTimer = null;
|
|
10665
|
+
ensureFreshAccessToken(baseUrl, credentials).then((creds) => {
|
|
10666
|
+
credentials = creds;
|
|
10667
|
+
connect();
|
|
10668
|
+
}).catch(async (e) => {
|
|
10669
|
+
await clearCredentials();
|
|
10670
|
+
console.error(`[local] ${e.message}`);
|
|
10671
|
+
console.error("[local] \u51ED\u8BC1\u5DF2\u5931\u6548\u5E76\u6E05\u9664\uFF1B\u8BF7\u91CD\u65B0\u8FD0\u884C cli-local \u5B8C\u6210\u6388\u6743");
|
|
10672
|
+
exitProcess(1);
|
|
10673
|
+
});
|
|
10674
|
+
}, delay);
|
|
10675
|
+
}
|
|
10676
|
+
function exitProcess(code) {
|
|
10677
|
+
userExitCode = code;
|
|
10678
|
+
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
10679
|
+
reconnectTimer = null;
|
|
10680
|
+
pty.killAll();
|
|
10681
|
+
for (const [, logger] of loggers) logger.logExit(-1);
|
|
10682
|
+
loggers.clear();
|
|
10683
|
+
lineBuffers.clear();
|
|
10684
|
+
stopHeartbeat();
|
|
10685
|
+
try {
|
|
10686
|
+
ws?.close();
|
|
10687
|
+
} catch {
|
|
10688
|
+
}
|
|
10689
|
+
process.exit(code);
|
|
10690
|
+
}
|
|
10691
|
+
function cleanup(code = 0) {
|
|
10692
|
+
exitProcess(code);
|
|
10693
|
+
}
|
|
10694
|
+
function handleFrame(sock, raw) {
|
|
10634
10695
|
let frame;
|
|
10635
10696
|
try {
|
|
10636
10697
|
frame = decodeFrame(toUint8(raw));
|
|
@@ -10639,6 +10700,10 @@ async function startLocal(opts = {}) {
|
|
|
10639
10700
|
}
|
|
10640
10701
|
switch (frame.t) {
|
|
10641
10702
|
case "auth-ok":
|
|
10703
|
+
if (reconnectAttempts > 0) {
|
|
10704
|
+
console.log(`[local] reconnected after ${reconnectAttempts} attempt(s); ${pty.list().length} PTY session(s) alive`);
|
|
10705
|
+
}
|
|
10706
|
+
reconnectAttempts = 0;
|
|
10642
10707
|
console.log(`[local] auth ok, deviceId=${frame.channelId}`);
|
|
10643
10708
|
break;
|
|
10644
10709
|
case "auth-err":
|
|
@@ -10664,20 +10729,13 @@ async function startLocal(opts = {}) {
|
|
|
10664
10729
|
default:
|
|
10665
10730
|
console.log("[local] unhandled frame:", frame.t);
|
|
10666
10731
|
}
|
|
10667
|
-
}
|
|
10732
|
+
}
|
|
10668
10733
|
async function handleAuthErr(reason) {
|
|
10669
10734
|
if (reason === "access token expired") {
|
|
10670
10735
|
try {
|
|
10671
10736
|
credentials = await ensureFreshAccessToken(baseUrl, credentials);
|
|
10672
10737
|
console.log("[local] token refreshed, retrying auth");
|
|
10673
|
-
|
|
10674
|
-
encodeFrame({
|
|
10675
|
-
t: "auth",
|
|
10676
|
-
role: "bridge",
|
|
10677
|
-
deviceId: credentials.deviceId,
|
|
10678
|
-
token: credentials.accessToken
|
|
10679
|
-
})
|
|
10680
|
-
);
|
|
10738
|
+
sendAuth();
|
|
10681
10739
|
return;
|
|
10682
10740
|
} catch (e) {
|
|
10683
10741
|
console.error(`[local] ${e.message}`);
|
|
@@ -10686,7 +10744,7 @@ async function startLocal(opts = {}) {
|
|
|
10686
10744
|
await clearCredentials();
|
|
10687
10745
|
console.error("[local] auth failed:", reason);
|
|
10688
10746
|
console.error("[local] \u51ED\u8BC1\u5DF2\u6E05\u9664\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C cli-local \u5B8C\u6210\u6388\u6743");
|
|
10689
|
-
|
|
10747
|
+
exitProcess(1);
|
|
10690
10748
|
}
|
|
10691
10749
|
function handleSpawn(frame) {
|
|
10692
10750
|
const sessionId = frame.sessionId;
|
|
@@ -10742,6 +10800,15 @@ async function startLocal(opts = {}) {
|
|
|
10742
10800
|
const logger = loggers.get(sessionId);
|
|
10743
10801
|
const session = pty.get(sessionId);
|
|
10744
10802
|
if (!session || !logger) return;
|
|
10803
|
+
if (frame.force) {
|
|
10804
|
+
const line = new TextDecoder().decode(frame.data);
|
|
10805
|
+
ptyWriteChar(sessionId, line + "\r");
|
|
10806
|
+
logger.logInput(new TextEncoder().encode(line + "\r"));
|
|
10807
|
+
logger.logForced(line);
|
|
10808
|
+
lineBuffers.set(sessionId, "");
|
|
10809
|
+
console.log(`[local] forced execution in ${sessionId}: ${line}`);
|
|
10810
|
+
return;
|
|
10811
|
+
}
|
|
10745
10812
|
if (session.cmd === "shell" && !session.inAltScreen) {
|
|
10746
10813
|
handleShellInput(sessionId, frame.data, logger);
|
|
10747
10814
|
} else {
|
|
@@ -10816,23 +10883,13 @@ async function startLocal(opts = {}) {
|
|
|
10816
10883
|
);
|
|
10817
10884
|
}
|
|
10818
10885
|
function safeSend(data) {
|
|
10819
|
-
if (ws.readyState === wrapper_default.OPEN) {
|
|
10886
|
+
if (ws && ws.readyState === wrapper_default.OPEN) {
|
|
10820
10887
|
ws.send(data);
|
|
10821
10888
|
}
|
|
10822
10889
|
}
|
|
10823
|
-
ws.on("close", () => {
|
|
10824
|
-
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
|
10825
|
-
pty.killAll();
|
|
10826
|
-
for (const [, logger] of loggers) logger.logExit(-1);
|
|
10827
|
-
loggers.clear();
|
|
10828
|
-
lineBuffers.clear();
|
|
10829
|
-
console.log("[local] disconnected");
|
|
10830
|
-
});
|
|
10831
|
-
ws.on("error", (err) => {
|
|
10832
|
-
console.error("[local] error:", err.message);
|
|
10833
|
-
});
|
|
10834
10890
|
process.on("SIGINT", () => cleanup(0));
|
|
10835
10891
|
process.on("SIGTERM", () => cleanup(0));
|
|
10892
|
+
connect();
|
|
10836
10893
|
}
|
|
10837
10894
|
function toUint8(raw) {
|
|
10838
10895
|
if (raw instanceof Buffer) return new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
@@ -10897,6 +10954,8 @@ if (argUrl && !argMatch && (argUrl === "-h" || argUrl === "--help" || argUrl ===
|
|
|
10897
10954
|
|
|
10898
10955
|
usage:
|
|
10899
10956
|
cli-local [HUB_URL]
|
|
10957
|
+
cli-local install [HUB_URL] \u5B89\u88C5 macOS launchd \u5E38\u9A7B\u670D\u52A1\uFF08\u5F00\u673A\u81EA\u542F + \u65AD\u7EBF\u81EA\u52A8\u91CD\u8FDE\uFF09
|
|
10958
|
+
cli-local uninstall \u5378\u8F7D launchd \u5E38\u9A7B\u670D\u52A1
|
|
10900
10959
|
|
|
10901
10960
|
\u9996\u6B21\u8FD0\u884C\uFF08\u65E0\u914D\u7F6E\uFF09\u4F1A\u8FDB\u5165\u5F15\u5BFC\uFF1A
|
|
10902
10961
|
1. \u63D0\u793A hub \u5730\u5740\uFF08\u56DE\u8F66\u7528\u9ED8\u8BA4\uFF09
|
|
@@ -10905,6 +10964,8 @@ usage:
|
|
|
10905
10964
|
4. \u968F\u540E\u8D70 OAuth Device Flow\uFF08RFC 8628\uFF09\uFF1A\u81EA\u52A8\u6253\u5F00\u6388\u6743\u9875 \u2192 \u6279\u51C6\u672C\u8BBE\u5907
|
|
10906
10965
|
5. \u51ED\u8BC1\u5B58\u5165 ~/.cli-remote/credentials.json\uFF080600\uFF09\uFF0C\u4E4B\u540E\u81EA\u52A8\u7EED\u671F
|
|
10907
10966
|
|
|
10967
|
+
\u65AD\u7EBF\u81EA\u52A8\u91CD\u8FDE\uFF1Ahub \u91CD\u542F/\u7F51\u7EDC\u95EA\u65AD\u540E\u8FDB\u7A0B\u4E0D\u9000\u51FA\uFF0CPTY \u4F1A\u8BDD\u4FDD\u6D3B\u5E76\u81EA\u52A8\u91CD\u8FDE\u3002
|
|
10968
|
+
|
|
10908
10969
|
environment:
|
|
10909
10970
|
RELAY_URL hub ws url (overrides argv and config)
|
|
10910
10971
|
REGISTRATION_KEY registration key (fallback of config.json)
|
|
@@ -10919,7 +10980,119 @@ config (~/.cli-remote/config.json):
|
|
|
10919
10980
|
}
|
|
10920
10981
|
|
|
10921
10982
|
example:
|
|
10922
|
-
cli-local wss://cli-remote.mkjs.net/ws
|
|
10983
|
+
cli-local wss://cli-remote.mkjs.net/ws
|
|
10984
|
+
cli-local install # \u914D\u7F6E\u5E76\u6388\u6743\u540E\uFF0C\u5B89\u88C5\u5E38\u9A7B\u670D\u52A1`);
|
|
10985
|
+
process.exit(0);
|
|
10986
|
+
}
|
|
10987
|
+
var LAUNCHD_LABEL = "net.cli-remote.local";
|
|
10988
|
+
function launchdPlistPath() {
|
|
10989
|
+
return (0, import_node_path5.join)((0, import_node_os5.homedir)(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
10990
|
+
}
|
|
10991
|
+
function entryScript() {
|
|
10992
|
+
const a1 = process.argv[1];
|
|
10993
|
+
if (!a1 || a1.endsWith(".ts")) return null;
|
|
10994
|
+
try {
|
|
10995
|
+
return (0, import_node_fs2.realpathSync)(a1);
|
|
10996
|
+
} catch {
|
|
10997
|
+
return a1;
|
|
10998
|
+
}
|
|
10999
|
+
}
|
|
11000
|
+
function run(cmd, args, okToFail = false) {
|
|
11001
|
+
try {
|
|
11002
|
+
return (0, import_node_child_process2.execFileSync)(cmd, args, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
11003
|
+
} catch (e) {
|
|
11004
|
+
if (okToFail) return null;
|
|
11005
|
+
throw e;
|
|
11006
|
+
}
|
|
11007
|
+
}
|
|
11008
|
+
function launchdInstall(urlArg) {
|
|
11009
|
+
if (process.platform !== "darwin") {
|
|
11010
|
+
console.error(`[local] launchd \u5E38\u9A7B\u4EC5\u652F\u6301 macOS\uFF08\u5F53\u524D ${process.platform}\uFF09\uFF1BLinux \u8BF7\u7528 systemd --user \u81EA\u884C\u6258\u7BA1`);
|
|
11011
|
+
process.exit(1);
|
|
11012
|
+
}
|
|
11013
|
+
const home = (0, import_node_os5.homedir)();
|
|
11014
|
+
const entry = entryScript();
|
|
11015
|
+
if (!entry) {
|
|
11016
|
+
console.error("[local] \u5F53\u524D\u4EE5\u6E90\u7801\uFF08tsx\uFF09\u6A21\u5F0F\u8FD0\u884C\uFF0C\u65E0\u6CD5\u5B89\u88C5\u5E38\u9A7B\u670D\u52A1\u3002");
|
|
11017
|
+
console.error("[local] \u8BF7\u5148\u901A\u8FC7 npm \u5B89\u88C5\uFF1Anpm i -g @cli-remote/local\uFF0C\u518D\u7528\u5B89\u88C5\u7248\u6267\u884C install\u3002");
|
|
11018
|
+
process.exit(1);
|
|
11019
|
+
}
|
|
11020
|
+
if (urlArg) {
|
|
11021
|
+
const cfgDir = (0, import_node_path5.join)(home, DEFAULT_CONFIG_DIR);
|
|
11022
|
+
(0, import_node_fs2.mkdirSync)(cfgDir, { recursive: true });
|
|
11023
|
+
const cfgPath = (0, import_node_path5.join)(cfgDir, "config.json");
|
|
11024
|
+
let cfg = {};
|
|
11025
|
+
try {
|
|
11026
|
+
cfg = JSON.parse((0, import_node_fs2.readFileSync)(cfgPath, "utf-8"));
|
|
11027
|
+
} catch {
|
|
11028
|
+
}
|
|
11029
|
+
cfg.relayUrl = urlArg;
|
|
11030
|
+
(0, import_node_fs2.writeFileSync)(cfgPath, JSON.stringify(cfg, null, 2) + "\n");
|
|
11031
|
+
console.log(`[local] relayUrl \u5DF2\u5199\u5165 ${cfgPath}`);
|
|
11032
|
+
}
|
|
11033
|
+
const credPath = (0, import_node_path5.join)(home, DEFAULT_CONFIG_DIR, CREDENTIALS_FILE);
|
|
11034
|
+
if (!(0, import_node_fs2.existsSync)(credPath)) {
|
|
11035
|
+
console.error("[local] \u5C1A\u672A\u6388\u6743\uFF08\u627E\u4E0D\u5230 credentials.json\uFF09\u3002");
|
|
11036
|
+
console.error("[local] \u8BF7\u5148\u4EA4\u4E92\u5F0F\u8FD0\u884C\u4E00\u6B21 cli-local \u5B8C\u6210\u914D\u7F6E\u4E0E\u6388\u6743\uFF0C\u518D\u5B89\u88C5\u5E38\u9A7B\u670D\u52A1\u3002");
|
|
11037
|
+
process.exit(1);
|
|
11038
|
+
}
|
|
11039
|
+
const plist = launchdPlistPath();
|
|
11040
|
+
const logDir = (0, import_node_path5.join)(home, DEFAULT_CONFIG_DIR, "logs");
|
|
11041
|
+
(0, import_node_fs2.mkdirSync)((0, import_node_path5.dirname)(plist), { recursive: true });
|
|
11042
|
+
(0, import_node_fs2.mkdirSync)(logDir, { recursive: true });
|
|
11043
|
+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
11044
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
11045
|
+
<plist version="1.0">
|
|
11046
|
+
<dict>
|
|
11047
|
+
<key>Label</key><string>${LAUNCHD_LABEL}</string>
|
|
11048
|
+
<key>ProgramArguments</key>
|
|
11049
|
+
<array>
|
|
11050
|
+
<string>${process.execPath}</string>
|
|
11051
|
+
<string>${entry}</string>
|
|
11052
|
+
</array>
|
|
11053
|
+
<key>RunAtLoad</key><true/>
|
|
11054
|
+
<key>KeepAlive</key><true/>
|
|
11055
|
+
<key>ThrottleInterval</key><integer>30</integer>
|
|
11056
|
+
<key>StandardOutPath</key><string>${(0, import_node_path5.join)(logDir, "daemon.out.log")}</string>
|
|
11057
|
+
<key>StandardErrorPath</key><string>${(0, import_node_path5.join)(logDir, "daemon.err.log")}</string>
|
|
11058
|
+
</dict>
|
|
11059
|
+
</plist>
|
|
11060
|
+
`;
|
|
11061
|
+
(0, import_node_fs2.writeFileSync)(plist, xml);
|
|
11062
|
+
const uid = process.getuid?.();
|
|
11063
|
+
if (uid === void 0) {
|
|
11064
|
+
console.error("[local] \u65E0\u6CD5\u786E\u5B9A uid\uFF0Claunchd \u5B89\u88C5\u5931\u8D25");
|
|
11065
|
+
process.exit(1);
|
|
11066
|
+
}
|
|
11067
|
+
const guiDomain = `gui/${uid}`;
|
|
11068
|
+
run("launchctl", ["bootout", guiDomain, plist], true);
|
|
11069
|
+
run("launchctl", ["unload", "-w", plist], true);
|
|
11070
|
+
run("launchctl", ["bootstrap", guiDomain, plist]);
|
|
11071
|
+
run("launchctl", ["enable", `${guiDomain}/${LAUNCHD_LABEL}`], true);
|
|
11072
|
+
console.log(`[local] launchd \u670D\u52A1\u5DF2\u5B89\u88C5\u5E76\u542F\u52A8\uFF1A${LAUNCHD_LABEL}`);
|
|
11073
|
+
console.log(`[local] plist: ${plist}`);
|
|
11074
|
+
console.log("[local] \u65E5\u5FD7: ~/.cli-remote/logs/daemon.out.log / daemon.err.log");
|
|
11075
|
+
console.log("[local] \u7BA1\u7406\u670D\u52A1: launchctl kickstart -k, bootout, \u6216 cli-local uninstall");
|
|
11076
|
+
}
|
|
11077
|
+
function launchdUninstall() {
|
|
11078
|
+
const plist = launchdPlistPath();
|
|
11079
|
+
if (!(0, import_node_fs2.existsSync)(plist)) {
|
|
11080
|
+
console.log("[local] \u672A\u627E\u5230\u5DF2\u5B89\u88C5\u7684\u5E38\u9A7B\u670D\u52A1\uFF08nothing to uninstall\uFF09");
|
|
11081
|
+
process.exit(0);
|
|
11082
|
+
}
|
|
11083
|
+
const uid = process.getuid?.();
|
|
11084
|
+
const guiDomain = `gui/${uid ?? 0}`;
|
|
11085
|
+
run("launchctl", ["bootout", guiDomain, plist], true);
|
|
11086
|
+
run("launchctl", ["unload", "-w", plist], true);
|
|
11087
|
+
(0, import_node_fs2.rmSync)(plist);
|
|
11088
|
+
console.log(`[local] launchd \u670D\u52A1\u5DF2\u505C\u6B62\u5E76\u5378\u8F7D\uFF1A${LAUNCHD_LABEL}`);
|
|
11089
|
+
}
|
|
11090
|
+
if (argUrl && !argMatch && argUrl === "install") {
|
|
11091
|
+
launchdInstall(process.argv[3]);
|
|
11092
|
+
process.exit(0);
|
|
11093
|
+
}
|
|
11094
|
+
if (argUrl && !argMatch && argUrl === "uninstall") {
|
|
11095
|
+
launchdUninstall();
|
|
10923
11096
|
process.exit(0);
|
|
10924
11097
|
}
|
|
10925
11098
|
startLocal(argMatch ? { url: argUrl } : {}).catch((err) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cli-remote/local",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Local PTY agent for cli-remote — exposes your local CLI tools (claude/codex/kimi-cli/shell) to the mobile web client via a self-hosted hub.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|