@cli-remote/local 0.0.3 → 0.0.4

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.
Files changed (2) hide show
  1. package/dist/index.cjs +263 -63
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3214,7 +3214,7 @@ var require_stream = __commonJS({
3214
3214
  };
3215
3215
  duplex._final = function(callback) {
3216
3216
  if (ws.readyState === ws.CONNECTING) {
3217
- ws.once("open", function open() {
3217
+ ws.once("open", function open2() {
3218
3218
  duplex._final(callback);
3219
3219
  });
3220
3220
  return;
@@ -3235,7 +3235,7 @@ var require_stream = __commonJS({
3235
3235
  };
3236
3236
  duplex._write = function(chunk, encoding, callback) {
3237
3237
  if (ws.readyState === ws.CONNECTING) {
3238
- ws.once("open", function open() {
3238
+ ws.once("open", function open2() {
3239
3239
  duplex._write(chunk, encoding, callback);
3240
3240
  });
3241
3241
  return;
@@ -6683,11 +6683,11 @@ var require_dijkstra = __commonJS({
6683
6683
  var predecessors = {};
6684
6684
  var costs = {};
6685
6685
  costs[s] = 0;
6686
- var open = dijkstra.PriorityQueue.make();
6687
- open.push(s, 0);
6686
+ var open2 = dijkstra.PriorityQueue.make();
6687
+ open2.push(s, 0);
6688
6688
  var closest, u, v, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit;
6689
- while (!open.empty()) {
6690
- closest = open.pop();
6689
+ while (!open2.empty()) {
6690
+ closest = open2.pop();
6691
6691
  u = closest.value;
6692
6692
  cost_of_s_to_u = closest.cost;
6693
6693
  adjacent_nodes = graph[u] || {};
@@ -6699,7 +6699,7 @@ var require_dijkstra = __commonJS({
6699
6699
  first_visit = typeof costs[v] === "undefined";
6700
6700
  if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
6701
6701
  costs[v] = cost_of_s_to_u_plus_cost_of_e;
6702
- open.push(v, cost_of_s_to_u_plus_cost_of_e);
6702
+ open2.push(v, cost_of_s_to_u_plus_cost_of_e);
6703
6703
  predecessors[v] = u;
6704
6704
  }
6705
6705
  }
@@ -9786,10 +9786,10 @@ var require_browser = __commonJS({
9786
9786
  text = canvas;
9787
9787
  canvas = void 0;
9788
9788
  }
9789
- return new Promise(function(resolve, reject) {
9789
+ return new Promise(function(resolve2, reject) {
9790
9790
  try {
9791
9791
  const data = QRCode2.create(text, opts);
9792
- resolve(renderFunc(data, canvas, opts));
9792
+ resolve2(renderFunc(data, canvas, opts));
9793
9793
  } catch (e) {
9794
9794
  reject(e);
9795
9795
  }
@@ -9870,11 +9870,11 @@ var require_server = __commonJS({
9870
9870
  }
9871
9871
  function render(renderFunc, text, params) {
9872
9872
  if (!params.cb) {
9873
- return new Promise(function(resolve, reject) {
9873
+ return new Promise(function(resolve2, reject) {
9874
9874
  try {
9875
9875
  const data = QRCode2.create(text, params.opts);
9876
9876
  return renderFunc(data, params.opts, function(err, data2) {
9877
- return err ? reject(err) : resolve(data2);
9877
+ return err ? reject(err) : resolve2(data2);
9878
9878
  });
9879
9879
  } catch (e) {
9880
9880
  reject(e);
@@ -9939,10 +9939,10 @@ var require_lib = __commonJS({
9939
9939
  });
9940
9940
 
9941
9941
  // src/index.ts
9942
- var import_node_fs2 = require("node:fs");
9942
+ var import_node_fs3 = require("node:fs");
9943
9943
  var import_node_child_process2 = require("node:child_process");
9944
- var import_node_os5 = require("node:os");
9945
- var import_node_path5 = require("node:path");
9944
+ var import_node_os6 = require("node:os");
9945
+ var import_node_path6 = require("node:path");
9946
9946
  var import_node_url = require("node:url");
9947
9947
 
9948
9948
  // ../../node_modules/.pnpm/ws@8.21.3/node_modules/ws/wrapper.mjs
@@ -9958,9 +9958,9 @@ var wrapper_default = import_websocket.default;
9958
9958
 
9959
9959
  // src/client.ts
9960
9960
  var import_node_readline = require("node:readline");
9961
- var import_promises2 = require("node:fs/promises");
9962
- var import_node_os4 = require("node:os");
9963
- var import_node_path4 = require("node:path");
9961
+ var import_promises3 = require("node:fs/promises");
9962
+ var import_node_os5 = require("node:os");
9963
+ var import_node_path5 = require("node:path");
9964
9964
 
9965
9965
  // ../shared/src/codec.ts
9966
9966
  var import_msgpack = __toESM(require_dist(), 1);
@@ -9980,6 +9980,9 @@ var ACCESS_TOKEN_TTL_MS = 60 * 6e4;
9980
9980
  var REFRESH_TOKEN_TTL_MS = 30 * 24 * 60 * 6e4;
9981
9981
  var REFRESH_MARGIN_MS = 5 * 6e4;
9982
9982
  var OUTPUT_BUFFER_SIZE = 500;
9983
+ var FILE_CHUNK_SIZE = 64 * 1024;
9984
+ var MAX_TRANSFER_BYTES = 500 * 1024 * 1024;
9985
+ var UPLOAD_DIR = "uploads";
9983
9986
  var RECONNECT_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
9984
9987
  var DEFAULT_CONFIG_DIR = ".cli-remote";
9985
9988
  var CREDENTIALS_FILE = "credentials.json";
@@ -10327,19 +10330,196 @@ function checkCommand(line, whitelist, dangerousPatterns = DANGEROUS_PATTERNS) {
10327
10330
  return { allowed: true };
10328
10331
  }
10329
10332
 
10330
- // src/auth.ts
10331
- var import_node_child_process = require("node:child_process");
10332
- var import_node_crypto = require("node:crypto");
10333
+ // src/file-transfer.ts
10334
+ var import_node_fs2 = require("node:fs");
10333
10335
  var import_promises = require("node:fs/promises");
10334
10336
  var import_node_os3 = require("node:os");
10335
10337
  var import_node_path3 = require("node:path");
10338
+ var FileTransferManager = class _FileTransferManager {
10339
+ constructor(send, log) {
10340
+ this.send = send;
10341
+ this.log = log;
10342
+ }
10343
+ uploads = /* @__PURE__ */ new Map();
10344
+ uploadDir() {
10345
+ return (0, import_node_path3.join)((0, import_node_os3.homedir)(), DEFAULT_CONFIG_DIR, UPLOAD_DIR);
10346
+ }
10347
+ expandPath(p) {
10348
+ const home = process.env.PTY_HOME ?? (0, import_node_os3.homedir)();
10349
+ if (p === "~") return home;
10350
+ if (p.startsWith("~/")) return (0, import_node_path3.join)(home, p.slice(2));
10351
+ return (0, import_node_path3.resolve)(p);
10352
+ }
10353
+ /** Strip any directory components and control chars from a client filename. */
10354
+ static sanitizeFilename(name) {
10355
+ const base = (0, import_node_path3.basename)(name).replace(/[\u0000-\u001f\u007f]/g, "");
10356
+ return base && base !== "." && base !== ".." ? base : "upload.bin";
10357
+ }
10358
+ async handleUploadStart(frame) {
10359
+ const { sessionId, uploadId, filename, size } = frame;
10360
+ if (this.uploads.has(uploadId)) return;
10361
+ if (size > MAX_TRANSFER_BYTES) {
10362
+ this.emit({
10363
+ t: "upload-err",
10364
+ sessionId,
10365
+ uploadId,
10366
+ reason: `\u6587\u4EF6\u8FC7\u5927\uFF08>${Math.floor(MAX_TRANSFER_BYTES / 1024 / 1024)}MB\uFF09`
10367
+ });
10368
+ return;
10369
+ }
10370
+ try {
10371
+ const dir = this.uploadDir();
10372
+ await (0, import_promises.mkdir)(dir, { recursive: true });
10373
+ const target = await this.uniqPath(dir, _FileTransferManager.sanitizeFilename(filename));
10374
+ const stream = (0, import_node_fs2.createWriteStream)(target, { mode: 384 });
10375
+ this.uploads.set(uploadId, {
10376
+ uploadId,
10377
+ sessionId,
10378
+ path: target,
10379
+ size,
10380
+ received: 0,
10381
+ lastSeq: 0,
10382
+ stream
10383
+ });
10384
+ this.emit({ t: "upload-ok", sessionId, uploadId, path: target });
10385
+ this.log(`upload start ${uploadId} \u2192 ${target} (${size}B)`);
10386
+ } catch (e) {
10387
+ this.emit({ t: "upload-err", sessionId, uploadId, reason: e.message });
10388
+ }
10389
+ }
10390
+ async uniqPath(dir, name) {
10391
+ let candidate = (0, import_node_path3.join)(dir, name);
10392
+ let i = 1;
10393
+ while (await exists(candidate)) {
10394
+ const dot = name.lastIndexOf(".");
10395
+ const stem = dot > 0 ? name.slice(0, dot) : name;
10396
+ const ext = dot > 0 ? name.slice(dot) : "";
10397
+ candidate = (0, import_node_path3.join)(dir, `${stem} (${i++})${ext}`);
10398
+ }
10399
+ return candidate;
10400
+ }
10401
+ handleUploadChunk(frame) {
10402
+ const up = this.uploads.get(frame.uploadId);
10403
+ if (!up) return;
10404
+ if (frame.seq <= up.lastSeq) return;
10405
+ up.lastSeq = frame.seq;
10406
+ up.received += frame.data.byteLength;
10407
+ up.stream.write(Buffer.from(frame.data.buffer, frame.data.byteOffset, frame.data.byteLength));
10408
+ }
10409
+ async handleUploadEnd(frame) {
10410
+ const up = this.uploads.get(frame.uploadId);
10411
+ if (!up) return;
10412
+ this.uploads.delete(frame.uploadId);
10413
+ await new Promise((res) => up.stream.end(res));
10414
+ const sizeOk = up.received === up.size;
10415
+ this.log(`upload done ${frame.uploadId}: ${up.received}B \u2192 ${up.path}`);
10416
+ if (!sizeOk) {
10417
+ this.emit({
10418
+ t: "upload-err",
10419
+ sessionId: up.sessionId,
10420
+ uploadId: frame.uploadId,
10421
+ reason: `\u5927\u5C0F\u4E0D\u5339\u914D\uFF08\u58F0\u660E ${up.size}B\uFF0C\u5B9E\u6536 ${up.received}B\uFF09`
10422
+ });
10423
+ }
10424
+ }
10425
+ abortUpload(uploadId) {
10426
+ const up = this.uploads.get(uploadId);
10427
+ if (!up) return;
10428
+ this.uploads.delete(uploadId);
10429
+ up.stream.destroy();
10430
+ this.log(`upload aborted ${uploadId}`);
10431
+ }
10432
+ /** Stream a file back to the web client with mild backpressure via `send`. */
10433
+ async handleDownloadReq(frame, isBusy) {
10434
+ const sessionId = frame.sessionId;
10435
+ const downloadId = "dl_" + Math.random().toString(36).slice(2, 10);
10436
+ let abs;
10437
+ try {
10438
+ abs = this.expandPath(frame.path);
10439
+ const st = await (0, import_promises.stat)(abs);
10440
+ if (!st.isFile()) throw new Error("\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
10441
+ if (st.size > MAX_TRANSFER_BYTES) {
10442
+ throw new Error(`\u6587\u4EF6\u8FC7\u5927\uFF08>${Math.floor(MAX_TRANSFER_BYTES / 1024 / 1024)}MB\uFF09`);
10443
+ }
10444
+ this.emit({
10445
+ t: "download-start",
10446
+ sessionId,
10447
+ downloadId,
10448
+ filename: (0, import_node_path3.basename)(abs),
10449
+ size: st.size
10450
+ });
10451
+ this.log(`download start ${downloadId} \u2190 ${abs} (${st.size}B)`);
10452
+ await this.streamFile(sessionId, downloadId, abs, isBusy);
10453
+ this.emit({ t: "download-end", sessionId, downloadId });
10454
+ this.log(`download done ${downloadId}: ${abs}`);
10455
+ } catch (e) {
10456
+ this.emit({
10457
+ t: "download-err",
10458
+ sessionId,
10459
+ downloadId,
10460
+ reason: e.message
10461
+ });
10462
+ }
10463
+ }
10464
+ async streamFile(sessionId, downloadId, abs, isBusy) {
10465
+ const handle = await (0, import_promises.open)(abs, "r");
10466
+ try {
10467
+ let seq = 0;
10468
+ let pos = 0;
10469
+ for (; ; ) {
10470
+ const buf = Buffer.alloc(FILE_CHUNK_SIZE);
10471
+ const { bytesRead } = await handle.read(buf, 0, FILE_CHUNK_SIZE, pos);
10472
+ if (bytesRead === 0) break;
10473
+ pos += bytesRead;
10474
+ seq++;
10475
+ this.emit({
10476
+ t: "download-chunk",
10477
+ sessionId,
10478
+ downloadId,
10479
+ data: new Uint8Array(buf.buffer, buf.byteOffset, bytesRead),
10480
+ seq
10481
+ });
10482
+ if (isBusy()) {
10483
+ await new Promise((res) => setImmediate(res));
10484
+ let spins = 0;
10485
+ while (isBusy() && spins++ < 2e3) {
10486
+ await new Promise((res) => setTimeout(res, 20));
10487
+ }
10488
+ }
10489
+ }
10490
+ } finally {
10491
+ await handle.close();
10492
+ }
10493
+ }
10494
+ abortAll() {
10495
+ for (const id of [...this.uploads.keys()]) this.abortUpload(id);
10496
+ }
10497
+ emit(frame) {
10498
+ this.send(encodeFrame(frame));
10499
+ }
10500
+ };
10501
+ async function exists(p) {
10502
+ try {
10503
+ await (0, import_promises.stat)(p);
10504
+ return true;
10505
+ } catch {
10506
+ return false;
10507
+ }
10508
+ }
10509
+
10510
+ // src/auth.ts
10511
+ var import_node_child_process = require("node:child_process");
10512
+ var import_node_crypto = require("node:crypto");
10513
+ var import_promises2 = require("node:fs/promises");
10514
+ var import_node_os4 = require("node:os");
10515
+ var import_node_path4 = require("node:path");
10336
10516
  var import_qrcode = __toESM(require_lib(), 1);
10337
10517
  function credentialsPath() {
10338
- return (0, import_node_path3.join)((0, import_node_os3.homedir)(), DEFAULT_CONFIG_DIR, CREDENTIALS_FILE);
10518
+ return (0, import_node_path4.join)((0, import_node_os4.homedir)(), DEFAULT_CONFIG_DIR, CREDENTIALS_FILE);
10339
10519
  }
10340
10520
  async function loadCredentials() {
10341
10521
  try {
10342
- const raw = JSON.parse(await (0, import_promises.readFile)(credentialsPath(), "utf-8"));
10522
+ const raw = JSON.parse(await (0, import_promises2.readFile)(credentialsPath(), "utf-8"));
10343
10523
  if (!raw.deviceId || !raw.accessToken || !raw.refreshToken) return null;
10344
10524
  return raw;
10345
10525
  } catch {
@@ -10348,16 +10528,16 @@ async function loadCredentials() {
10348
10528
  }
10349
10529
  async function saveCredentials(creds) {
10350
10530
  const path = credentialsPath();
10351
- await (0, import_promises.mkdir)((0, import_node_path3.join)(path, ".."), { recursive: true });
10352
- await (0, import_promises.writeFile)(path, JSON.stringify(creds, null, 2) + "\n", { mode: 384 });
10531
+ await (0, import_promises2.mkdir)((0, import_node_path4.join)(path, ".."), { recursive: true });
10532
+ await (0, import_promises2.writeFile)(path, JSON.stringify(creds, null, 2) + "\n", { mode: 384 });
10353
10533
  try {
10354
- await (0, import_promises.chmod)(path, 384);
10534
+ await (0, import_promises2.chmod)(path, 384);
10355
10535
  } catch {
10356
10536
  }
10357
10537
  }
10358
10538
  async function clearCredentials() {
10359
10539
  try {
10360
- await (0, import_promises.writeFile)(credentialsPath(), "");
10540
+ await (0, import_promises2.writeFile)(credentialsPath(), "");
10361
10541
  } catch {
10362
10542
  }
10363
10543
  }
@@ -10389,17 +10569,17 @@ function openBrowser(url) {
10389
10569
  }
10390
10570
  }
10391
10571
  async function mergeLocalConfig(patch) {
10392
- const dir = (0, import_node_path3.join)((0, import_node_os3.homedir)(), DEFAULT_CONFIG_DIR);
10393
- const path = (0, import_node_path3.join)(dir, CONFIG_FILE);
10572
+ const dir = (0, import_node_path4.join)((0, import_node_os4.homedir)(), DEFAULT_CONFIG_DIR);
10573
+ const path = (0, import_node_path4.join)(dir, CONFIG_FILE);
10394
10574
  let existing = {};
10395
10575
  try {
10396
- existing = JSON.parse(await (0, import_promises.readFile)(path, "utf-8"));
10576
+ existing = JSON.parse(await (0, import_promises2.readFile)(path, "utf-8"));
10397
10577
  } catch {
10398
10578
  }
10399
- await (0, import_promises.mkdir)(dir, { recursive: true });
10400
- await (0, import_promises.writeFile)(path, JSON.stringify({ ...existing, ...patch }, null, 2) + "\n");
10579
+ await (0, import_promises2.mkdir)(dir, { recursive: true });
10580
+ await (0, import_promises2.writeFile)(path, JSON.stringify({ ...existing, ...patch }, null, 2) + "\n");
10401
10581
  }
10402
- var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
10582
+ var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
10403
10583
  var AuthError = class extends Error {
10404
10584
  };
10405
10585
  async function deviceFlowAuthorize(baseUrl, registrationKey, deviceId) {
@@ -10411,7 +10591,7 @@ async function deviceFlowAuthorize(baseUrl, registrationKey, deviceId) {
10411
10591
  const res = await postJson(`${baseUrl}/oauth/device_authorization`, {
10412
10592
  registrationKey,
10413
10593
  device_id: deviceId,
10414
- device_name: (0, import_node_os3.hostname)(),
10594
+ device_name: (0, import_node_os4.hostname)(),
10415
10595
  platform: process.platform
10416
10596
  });
10417
10597
  if (res.status !== 200) {
@@ -10514,9 +10694,9 @@ async function ensureCredentials(baseUrl, registrationKey) {
10514
10694
 
10515
10695
  // src/client.ts
10516
10696
  async function loadConfig() {
10517
- const path = (0, import_node_path4.join)((0, import_node_os4.homedir)(), DEFAULT_CONFIG_DIR, CONFIG_FILE);
10697
+ const path = (0, import_node_path5.join)((0, import_node_os5.homedir)(), DEFAULT_CONFIG_DIR, CONFIG_FILE);
10518
10698
  try {
10519
- return JSON.parse(await (0, import_promises2.readFile)(path, "utf-8"));
10699
+ return JSON.parse(await (0, import_promises3.readFile)(path, "utf-8"));
10520
10700
  } catch {
10521
10701
  return {};
10522
10702
  }
@@ -10533,7 +10713,7 @@ function isTTY() {
10533
10713
  async function readInput(prompt) {
10534
10714
  const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stdout });
10535
10715
  try {
10536
- return await new Promise((resolve) => rl.question(prompt, (answer) => resolve(answer)));
10716
+ return await new Promise((resolve2) => rl.question(prompt, (answer) => resolve2(answer)));
10537
10717
  } finally {
10538
10718
  rl.close();
10539
10719
  }
@@ -10603,6 +10783,10 @@ async function startLocal(opts = {}) {
10603
10783
  const pty = new PtyManager();
10604
10784
  const loggers = /* @__PURE__ */ new Map();
10605
10785
  const lineBuffers = /* @__PURE__ */ new Map();
10786
+ const transfers = new FileTransferManager(
10787
+ (data) => safeSend(data),
10788
+ (msg) => console.log(`[local] ${msg}`)
10789
+ );
10606
10790
  let credentials = await ensureCredentials(baseUrl, registrationKey);
10607
10791
  console.log(`[local] connecting to ${url}`);
10608
10792
  console.log(`[local] deviceId=${credentials.deviceId}`);
@@ -10677,6 +10861,7 @@ async function startLocal(opts = {}) {
10677
10861
  userExitCode = code;
10678
10862
  if (reconnectTimer) clearTimeout(reconnectTimer);
10679
10863
  reconnectTimer = null;
10864
+ transfers.abortAll();
10680
10865
  pty.killAll();
10681
10866
  for (const [, logger] of loggers) logger.logExit(-1);
10682
10867
  loggers.clear();
@@ -10726,6 +10911,21 @@ async function startLocal(opts = {}) {
10726
10911
  case "replay-req":
10727
10912
  handleReplay(frame);
10728
10913
  break;
10914
+ case "upload-start":
10915
+ void transfers.handleUploadStart(frame);
10916
+ break;
10917
+ case "upload-chunk":
10918
+ transfers.handleUploadChunk(frame);
10919
+ break;
10920
+ case "upload-end":
10921
+ void transfers.handleUploadEnd(frame);
10922
+ break;
10923
+ case "download-req":
10924
+ void transfers.handleDownloadReq(
10925
+ frame,
10926
+ () => ws ? ws.bufferedAmount > 4 * 1024 * 1024 : false
10927
+ );
10928
+ break;
10729
10929
  default:
10730
10930
  console.log("[local] unhandled frame:", frame.t);
10731
10931
  }
@@ -10917,15 +11117,15 @@ function resolveHere() {
10917
11117
  if (DEBUG) console.error("[debug] cannot resolve script path");
10918
11118
  return;
10919
11119
  }
10920
- const hereDir = (0, import_node_path5.dirname)(here);
11120
+ const hereDir = (0, import_node_path6.dirname)(here);
10921
11121
  const candidates = [
10922
- (0, import_node_path5.join)(hereDir, "..", "node_modules", "node-pty", "prebuilds"),
10923
- (0, import_node_path5.join)(hereDir, "..", "..", "node-pty", "prebuilds"),
10924
- (0, import_node_path5.join)(hereDir, "..", "..", "..", "node_modules", "node-pty", "prebuilds")
11122
+ (0, import_node_path6.join)(hereDir, "..", "node_modules", "node-pty", "prebuilds"),
11123
+ (0, import_node_path6.join)(hereDir, "..", "..", "node-pty", "prebuilds"),
11124
+ (0, import_node_path6.join)(hereDir, "..", "..", "..", "node_modules", "node-pty", "prebuilds")
10925
11125
  ];
10926
11126
  let prebuildsDir = null;
10927
11127
  for (const c of candidates) {
10928
- if ((0, import_node_fs2.existsSync)(c)) {
11128
+ if ((0, import_node_fs3.existsSync)(c)) {
10929
11129
  prebuildsDir = c;
10930
11130
  break;
10931
11131
  }
@@ -10935,11 +11135,11 @@ function resolveHere() {
10935
11135
  return;
10936
11136
  }
10937
11137
  let n = 0;
10938
- for (const sub of (0, import_node_fs2.readdirSync)(prebuildsDir)) {
10939
- const helper = (0, import_node_path5.join)(prebuildsDir, sub, "spawn-helper");
10940
- if ((0, import_node_fs2.existsSync)(helper)) {
11138
+ for (const sub of (0, import_node_fs3.readdirSync)(prebuildsDir)) {
11139
+ const helper = (0, import_node_path6.join)(prebuildsDir, sub, "spawn-helper");
11140
+ if ((0, import_node_fs3.existsSync)(helper)) {
10941
11141
  try {
10942
- (0, import_node_fs2.chmodSync)(helper, 493);
11142
+ (0, import_node_fs3.chmodSync)(helper, 493);
10943
11143
  n++;
10944
11144
  } catch {
10945
11145
  }
@@ -10986,13 +11186,13 @@ example:
10986
11186
  }
10987
11187
  var LAUNCHD_LABEL = "net.cli-remote.local";
10988
11188
  function launchdPlistPath() {
10989
- return (0, import_node_path5.join)((0, import_node_os5.homedir)(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
11189
+ return (0, import_node_path6.join)((0, import_node_os6.homedir)(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
10990
11190
  }
10991
11191
  function entryScript() {
10992
11192
  const a1 = process.argv[1];
10993
11193
  if (!a1 || a1.endsWith(".ts")) return null;
10994
11194
  try {
10995
- return (0, import_node_fs2.realpathSync)(a1);
11195
+ return (0, import_node_fs3.realpathSync)(a1);
10996
11196
  } catch {
10997
11197
  return a1;
10998
11198
  }
@@ -11010,7 +11210,7 @@ function launchdInstall(urlArg) {
11010
11210
  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
11211
  process.exit(1);
11012
11212
  }
11013
- const home = (0, import_node_os5.homedir)();
11213
+ const home = (0, import_node_os6.homedir)();
11014
11214
  const entry = entryScript();
11015
11215
  if (!entry) {
11016
11216
  console.error("[local] \u5F53\u524D\u4EE5\u6E90\u7801\uFF08tsx\uFF09\u6A21\u5F0F\u8FD0\u884C\uFF0C\u65E0\u6CD5\u5B89\u88C5\u5E38\u9A7B\u670D\u52A1\u3002");
@@ -11018,28 +11218,28 @@ function launchdInstall(urlArg) {
11018
11218
  process.exit(1);
11019
11219
  }
11020
11220
  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");
11221
+ const cfgDir = (0, import_node_path6.join)(home, DEFAULT_CONFIG_DIR);
11222
+ (0, import_node_fs3.mkdirSync)(cfgDir, { recursive: true });
11223
+ const cfgPath = (0, import_node_path6.join)(cfgDir, "config.json");
11024
11224
  let cfg = {};
11025
11225
  try {
11026
- cfg = JSON.parse((0, import_node_fs2.readFileSync)(cfgPath, "utf-8"));
11226
+ cfg = JSON.parse((0, import_node_fs3.readFileSync)(cfgPath, "utf-8"));
11027
11227
  } catch {
11028
11228
  }
11029
11229
  cfg.relayUrl = urlArg;
11030
- (0, import_node_fs2.writeFileSync)(cfgPath, JSON.stringify(cfg, null, 2) + "\n");
11230
+ (0, import_node_fs3.writeFileSync)(cfgPath, JSON.stringify(cfg, null, 2) + "\n");
11031
11231
  console.log(`[local] relayUrl \u5DF2\u5199\u5165 ${cfgPath}`);
11032
11232
  }
11033
- const credPath = (0, import_node_path5.join)(home, DEFAULT_CONFIG_DIR, CREDENTIALS_FILE);
11034
- if (!(0, import_node_fs2.existsSync)(credPath)) {
11233
+ const credPath = (0, import_node_path6.join)(home, DEFAULT_CONFIG_DIR, CREDENTIALS_FILE);
11234
+ if (!(0, import_node_fs3.existsSync)(credPath)) {
11035
11235
  console.error("[local] \u5C1A\u672A\u6388\u6743\uFF08\u627E\u4E0D\u5230 credentials.json\uFF09\u3002");
11036
11236
  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
11237
  process.exit(1);
11038
11238
  }
11039
11239
  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 });
11240
+ const logDir = (0, import_node_path6.join)(home, DEFAULT_CONFIG_DIR, "logs");
11241
+ (0, import_node_fs3.mkdirSync)((0, import_node_path6.dirname)(plist), { recursive: true });
11242
+ (0, import_node_fs3.mkdirSync)(logDir, { recursive: true });
11043
11243
  const xml = `<?xml version="1.0" encoding="UTF-8"?>
11044
11244
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
11045
11245
  <plist version="1.0">
@@ -11053,12 +11253,12 @@ function launchdInstall(urlArg) {
11053
11253
  <key>RunAtLoad</key><true/>
11054
11254
  <key>KeepAlive</key><true/>
11055
11255
  <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>
11256
+ <key>StandardOutPath</key><string>${(0, import_node_path6.join)(logDir, "daemon.out.log")}</string>
11257
+ <key>StandardErrorPath</key><string>${(0, import_node_path6.join)(logDir, "daemon.err.log")}</string>
11058
11258
  </dict>
11059
11259
  </plist>
11060
11260
  `;
11061
- (0, import_node_fs2.writeFileSync)(plist, xml);
11261
+ (0, import_node_fs3.writeFileSync)(plist, xml);
11062
11262
  const uid = process.getuid?.();
11063
11263
  if (uid === void 0) {
11064
11264
  console.error("[local] \u65E0\u6CD5\u786E\u5B9A uid\uFF0Claunchd \u5B89\u88C5\u5931\u8D25");
@@ -11076,7 +11276,7 @@ function launchdInstall(urlArg) {
11076
11276
  }
11077
11277
  function launchdUninstall() {
11078
11278
  const plist = launchdPlistPath();
11079
- if (!(0, import_node_fs2.existsSync)(plist)) {
11279
+ if (!(0, import_node_fs3.existsSync)(plist)) {
11080
11280
  console.log("[local] \u672A\u627E\u5230\u5DF2\u5B89\u88C5\u7684\u5E38\u9A7B\u670D\u52A1\uFF08nothing to uninstall\uFF09");
11081
11281
  process.exit(0);
11082
11282
  }
@@ -11084,7 +11284,7 @@ function launchdUninstall() {
11084
11284
  const guiDomain = `gui/${uid ?? 0}`;
11085
11285
  run("launchctl", ["bootout", guiDomain, plist], true);
11086
11286
  run("launchctl", ["unload", "-w", plist], true);
11087
- (0, import_node_fs2.rmSync)(plist);
11287
+ (0, import_node_fs3.rmSync)(plist);
11088
11288
  console.log(`[local] launchd \u670D\u52A1\u5DF2\u505C\u6B62\u5E76\u5378\u8F7D\uFF1A${LAUNCHD_LABEL}`);
11089
11289
  }
11090
11290
  if (argUrl && !argMatch && argUrl === "install") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cli-remote/local",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
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": {