@jian-ai/remote-control 0.8.3 → 0.8.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.
@@ -4,15 +4,26 @@ import { createHash } from 'node:crypto';
4
4
  import {
5
5
  existsSync,
6
6
  mkdtempSync,
7
+ readdirSync,
7
8
  readFileSync,
8
9
  realpathSync,
9
10
  rmSync,
10
11
  statSync,
11
12
  writeFileSync,
12
13
  } from 'node:fs';
13
- import { chmod, copyFile, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
14
+ import {
15
+ chmod,
16
+ copyFile,
17
+ mkdir,
18
+ readdir,
19
+ readFile,
20
+ rename,
21
+ rm,
22
+ unlink,
23
+ writeFile,
24
+ } from 'node:fs/promises';
14
25
  import { homedir, tmpdir } from 'node:os';
15
- import { dirname, join, resolve } from 'node:path';
26
+ import { basename, dirname, join, resolve } from 'node:path';
16
27
  import { fileURLToPath, pathToFileURL } from 'node:url';
17
28
 
18
29
  const configDir = join(homedir(), '.config', 'jian-remote');
@@ -53,7 +64,7 @@ export function parseCliInvocation(argv = args) {
53
64
  * Stamped to the release tag on npm publish and when the gateway serves this script.
54
65
  * Compatibility with the gateway requires the same major.minor (see versionsCompatible).
55
66
  */
56
- export const PACKAGE_VERSION = '0.8.3';
67
+ export const PACKAGE_VERSION = '0.8.4';
57
68
 
58
69
  /** Soft stdout/stderr caps while capturing a command (chars). Gateway schema matches these. */
59
70
  const STDOUT_CAP = 400_000;
@@ -142,12 +153,291 @@ export function macosAppBundlePaths(home = homedir()) {
142
153
  appRoot,
143
154
  contents: join(appRoot, 'Contents'),
144
155
  macosDir: join(appRoot, 'Contents', 'MacOS'),
156
+ /** Homebrew / official Node often load `@rpath/libnode.*.dylib` from here. */
157
+ libDir: join(appRoot, 'Contents', 'lib'),
145
158
  executable: join(appRoot, 'Contents', 'MacOS', MACOS_APP_NAME),
146
159
  infoPlist: join(appRoot, 'Contents', 'Info.plist'),
147
160
  bundleId: MACOS_BUNDLE_ID,
148
161
  };
149
162
  }
150
163
 
164
+ /** dyld system locations — leave these on the host; do not copy into the app. */
165
+ export function isMacSystemLibrary(depPath) {
166
+ if (typeof depPath !== 'string' || !depPath) return true;
167
+ if (depPath.startsWith('/usr/lib/')) return true;
168
+ if (depPath.startsWith('/System/')) return true;
169
+ if (depPath.startsWith('/Library/Apple/')) return true;
170
+ if (depPath.startsWith('/usr/local/lib/libSystem')) return true;
171
+ return false;
172
+ }
173
+
174
+ /**
175
+ * Parse `otool -L` lines into load-command paths (skips the header "path:" line).
176
+ * Example line: `\t@rpath/libnode.147.dylib (compatibility version 147.0.0, current version …)`
177
+ */
178
+ export function parseOtoolDependencies(stdout) {
179
+ const deps = [];
180
+ for (const line of String(stdout || '').split('\n')) {
181
+ const trimmed = line.trim();
182
+ if (!trimmed || trimmed.endsWith(':')) continue;
183
+ const match = /^(.+?)\s+\(compatibility version\b/.exec(trimmed);
184
+ if (!match) continue;
185
+ const dep = match[1].trim();
186
+ if (dep) deps.push(dep);
187
+ }
188
+ return deps;
189
+ }
190
+
191
+ /**
192
+ * Parse LC_RPATH entries from `otool -l` (or `otool -l -v`) output.
193
+ * Looks for: `cmd LC_RPATH` … `path <value> (offset …)`
194
+ */
195
+ export function parseOtoolRpaths(stdout) {
196
+ const rpaths = [];
197
+ const lines = String(stdout || '').split('\n');
198
+ for (let i = 0; i < lines.length; i += 1) {
199
+ if (!/\bLC_RPATH\b/.test(lines[i])) continue;
200
+ for (let j = i + 1; j < Math.min(i + 6, lines.length); j += 1) {
201
+ const match = /^\s*path\s+(.+?)(?:\s+\(offset\s+\d+\))?\s*$/.exec(lines[j]);
202
+ if (match) {
203
+ rpaths.push(match[1].trim());
204
+ break;
205
+ }
206
+ }
207
+ }
208
+ return rpaths;
209
+ }
210
+
211
+ /**
212
+ * Expand @executable_path / @loader_path / @rpath against the source Node layout.
213
+ * Absolute paths pass through. Unresolvable @rpath names return null.
214
+ */
215
+ export function resolveMachODependency(
216
+ dep,
217
+ { binaryPath, executablePath, rpaths = [], exists = existsSync } = {},
218
+ ) {
219
+ if (typeof dep !== 'string' || !dep) return null;
220
+ const loaderDir = dirname(binaryPath);
221
+ const execDir = dirname(executablePath || binaryPath);
222
+
223
+ const expandPrefix = (value) => {
224
+ if (value.startsWith('@loader_path')) {
225
+ return join(loaderDir, value.slice('@loader_path'.length).replace(/^\//, '') || '.');
226
+ }
227
+ if (value.startsWith('@executable_path')) {
228
+ return join(execDir, value.slice('@executable_path'.length).replace(/^\//, '') || '.');
229
+ }
230
+ return value;
231
+ };
232
+
233
+ if (dep.startsWith('@rpath/')) {
234
+ const rest = dep.slice('@rpath/'.length);
235
+ for (const rpath of rpaths) {
236
+ const base = expandPrefix(rpath);
237
+ const candidate = join(base, rest);
238
+ if (exists(candidate)) return candidate;
239
+ }
240
+ // Common Node layouts when LC_RPATH is missing from a stub parse: bin/ + ../lib/.
241
+ for (const candidate of [
242
+ join(loaderDir, rest),
243
+ join(loaderDir, '..', 'lib', rest),
244
+ join(execDir, rest),
245
+ join(execDir, '..', 'lib', rest),
246
+ ]) {
247
+ if (exists(candidate)) return candidate;
248
+ }
249
+ return null;
250
+ }
251
+
252
+ if (dep.startsWith('@loader_path') || dep.startsWith('@executable_path')) {
253
+ const candidate = expandPrefix(dep);
254
+ return exists(candidate) ? candidate : null;
255
+ }
256
+
257
+ if (dep.startsWith('/')) {
258
+ return exists(dep) ? dep : null;
259
+ }
260
+
261
+ return null;
262
+ }
263
+
264
+ const SIBLING_DYLIB_PREFIXES = [
265
+ 'libnode.',
266
+ 'libuv.',
267
+ 'libbrotli',
268
+ 'libcares.',
269
+ 'libnghttp',
270
+ 'libopenssl.',
271
+ 'libssl.',
272
+ 'libcrypto.',
273
+ 'libicu',
274
+ ];
275
+
276
+ /**
277
+ * Sibling search when otool is unavailable or incomplete — Homebrew Cellar and
278
+ * official tarballs keep libnode next to bin/ or under ../lib/.
279
+ */
280
+ export function discoverSiblingNodeLibraries(nodePath, { exists = existsSync, listDir } = {}) {
281
+ const dir = dirname(nodePath);
282
+ const searchDirs = [dir, join(dir, 'lib'), join(dir, '..', 'lib')];
283
+ const found = [];
284
+ const list =
285
+ listDir ||
286
+ ((path) => {
287
+ try {
288
+ return readdirSync(path);
289
+ } catch {
290
+ return [];
291
+ }
292
+ });
293
+ for (const searchDir of searchDirs) {
294
+ if (!exists(searchDir)) continue;
295
+ for (const name of list(searchDir)) {
296
+ if (!name.endsWith('.dylib')) continue;
297
+ if (!SIBLING_DYLIB_PREFIXES.some((prefix) => name.startsWith(prefix))) continue;
298
+ const full = join(searchDir, name);
299
+ if (exists(full)) found.push(full);
300
+ }
301
+ }
302
+ return found;
303
+ }
304
+
305
+ /**
306
+ * BFS: every non-system Mach-O dependency of `nodePath` that must live inside the .app.
307
+ * Returns absolute source paths (deduped, stable order).
308
+ */
309
+ export function collectNodeRuntimeLibraries(
310
+ nodePath,
311
+ {
312
+ exists = existsSync,
313
+ readDeps = defaultReadOtoolDeps,
314
+ readRpaths = defaultReadOtoolRpaths,
315
+ listDir,
316
+ } = {},
317
+ ) {
318
+ const realNode = (() => {
319
+ try {
320
+ return realpathSync(nodePath);
321
+ } catch {
322
+ return nodePath;
323
+ }
324
+ })();
325
+
326
+ const queue = [realNode];
327
+ const seenBinaries = new Set();
328
+ const libraries = [];
329
+ const seenLibs = new Set();
330
+
331
+ const enqueueLib = (source) => {
332
+ let real = source;
333
+ try {
334
+ real = realpathSync(source);
335
+ } catch {
336
+ // keep source
337
+ }
338
+ if (seenLibs.has(real)) return;
339
+ seenLibs.add(real);
340
+ libraries.push(real);
341
+ queue.push(real);
342
+ };
343
+
344
+ // Seed Cellar/tarball siblings first so a missing otool still walks transitive deps.
345
+ for (const sibling of discoverSiblingNodeLibraries(realNode, { exists, listDir })) {
346
+ enqueueLib(sibling);
347
+ }
348
+
349
+ while (queue.length > 0) {
350
+ const current = queue.shift();
351
+ if (!current || seenBinaries.has(current)) continue;
352
+ seenBinaries.add(current);
353
+
354
+ const rpaths = readRpaths(current);
355
+ const deps = readDeps(current);
356
+ for (const dep of deps) {
357
+ if (isMacSystemLibrary(dep)) continue;
358
+ // Self-id lines sometimes appear as the dylib's install name — skip when it resolves to self.
359
+ const resolved = resolveMachODependency(dep, {
360
+ binaryPath: current,
361
+ executablePath: realNode,
362
+ rpaths,
363
+ exists,
364
+ });
365
+ if (!resolved) continue;
366
+ let realResolved = resolved;
367
+ try {
368
+ realResolved = realpathSync(resolved);
369
+ } catch {
370
+ // keep
371
+ }
372
+ if (realResolved === realNode || realResolved === current) continue;
373
+ if (isMacSystemLibrary(realResolved)) continue;
374
+ enqueueLib(realResolved);
375
+ }
376
+ }
377
+
378
+ return libraries;
379
+ }
380
+
381
+ function defaultReadOtoolDeps(binaryPath) {
382
+ const result = spawnSync('otool', ['-L', binaryPath], { encoding: 'utf8' });
383
+ if (result.status !== 0) return [];
384
+ return parseOtoolDependencies(result.stdout || '');
385
+ }
386
+
387
+ function defaultReadOtoolRpaths(binaryPath) {
388
+ const result = spawnSync('otool', ['-l', binaryPath], { encoding: 'utf8' });
389
+ if (result.status !== 0) return [];
390
+ return parseOtoolRpaths(result.stdout || '');
391
+ }
392
+
393
+ /** Drop Gatekeeper quarantine on a path (best-effort; missing xattr is fine). */
394
+ export function clearMacQuarantine(targetPath) {
395
+ spawnSync('xattr', ['-dr', 'com.apple.quarantine', targetPath], { encoding: 'utf8' });
396
+ }
397
+
398
+ function runInstallNameTool(argv, run) {
399
+ // -add_rpath fails (status 1) when the rpath already exists — that is fine.
400
+ return run('install_name_tool', argv);
401
+ }
402
+
403
+ /**
404
+ * Rewrite load commands so bundled libs resolve via `@rpath/<basename>` inside Contents/lib.
405
+ * Best-effort: missing install_name_tool still leaves copies under Contents/lib for @rpath.
406
+ */
407
+ export function rewriteBundledMachOLinks({
408
+ executablePath,
409
+ libDir,
410
+ libraryBasenames,
411
+ readDeps = defaultReadOtoolDeps,
412
+ run = (cmd, argv) => spawnSync(cmd, argv, { encoding: 'utf8' }),
413
+ }) {
414
+ const names = new Set(libraryBasenames);
415
+
416
+ runInstallNameTool(['-add_rpath', '@executable_path/../lib', executablePath], run);
417
+ runInstallNameTool(['-add_rpath', '@executable_path', executablePath], run);
418
+
419
+ for (const name of names) {
420
+ runInstallNameTool(['-id', `@rpath/${name}`, join(libDir, name)], run);
421
+ }
422
+
423
+ const consumers = [executablePath, ...[...names].map((name) => join(libDir, name))];
424
+ for (const consumer of consumers) {
425
+ for (const dep of readDeps(consumer)) {
426
+ if (isMacSystemLibrary(dep)) continue;
427
+ const depBase = basename(
428
+ dep
429
+ .replace(/^@rpath\//, '')
430
+ .replace(/^@loader_path\//, '')
431
+ .replace(/^@executable_path\//, ''),
432
+ );
433
+ if (!names.has(depBase)) continue;
434
+ const desired = `@rpath/${depBase}`;
435
+ if (dep === desired) continue;
436
+ runInstallNameTool(['-change', dep, desired, consumer], run);
437
+ }
438
+ }
439
+ }
440
+
151
441
  export function buildMacosAppInfoPlist() {
152
442
  return `<?xml version="1.0" encoding="UTF-8"?>
153
443
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -214,26 +504,78 @@ export function buildLaunchAgentPlist({
214
504
  }
215
505
 
216
506
  /**
217
- * Copy the current Node binary into Jian Remote.app and ad-hoc sign so Login Items / TCC
218
- * attach to Jian, not the shared system node (unsigned / ad-hoc — not Developer ID).
507
+ * Copy the current Node binary *and* its @rpath shared libs (libnode, ICU, …) into
508
+ * Jian Remote.app, then ad-hoc sign so Login Items / TCC attach to Jian — not system node.
509
+ * Homebrew / nvm / fnm / official pkg layouts resolve via Contents/lib (@executable_path/../lib).
219
510
  */
220
- async function materializeMacosAppRuntime() {
221
- const paths = macosAppBundlePaths();
511
+ export async function materializeMacosAppRuntime({
512
+ sourceNode = process.execPath,
513
+ home = homedir(),
514
+ collectLibraries = collectNodeRuntimeLibraries,
515
+ } = {}) {
516
+ const paths = macosAppBundlePaths(home);
222
517
  await mkdir(paths.macosDir, { recursive: true, mode: 0o755 });
518
+ await mkdir(paths.libDir, { recursive: true, mode: 0o755 });
223
519
  await writeFile(paths.infoPlist, buildMacosAppInfoPlist(), { mode: 0o644 });
224
- const source = process.execPath;
520
+
521
+ let realSource = sourceNode;
522
+ try {
523
+ realSource = realpathSync(sourceNode);
524
+ } catch {
525
+ // keep sourceNode
526
+ }
527
+
225
528
  const temp = `${paths.executable}.${process.pid}.tmp`;
226
- await copyFile(source, temp);
529
+ await copyFile(realSource, temp);
227
530
  await chmod(temp, 0o755);
228
531
  await rename(temp, paths.executable);
229
- // Best-effort ad-hoc sign with our bundle id; ignore failures on locked-down hosts.
532
+
533
+ // Drop stale dylibs from a previous Node major so @rpath cannot pick an old libnode.
534
+ try {
535
+ for (const name of await readdir(paths.libDir)) {
536
+ if (!name.endsWith('.dylib')) continue;
537
+ await rm(join(paths.libDir, name), { force: true });
538
+ }
539
+ } catch {
540
+ // lib dir may be brand new
541
+ }
542
+
543
+ const librarySources = collectLibraries(realSource);
544
+ const libraryBasenames = [];
545
+ for (const libSource of librarySources) {
546
+ const name = basename(libSource);
547
+ if (!name.endsWith('.dylib')) continue;
548
+ const dest = join(paths.libDir, name);
549
+ await copyFile(libSource, dest);
550
+ await chmod(dest, 0o755);
551
+ libraryBasenames.push(name);
552
+ }
553
+
554
+ if (libraryBasenames.length > 0) {
555
+ rewriteBundledMachOLinks({
556
+ executablePath: paths.executable,
557
+ libDir: paths.libDir,
558
+ libraryBasenames,
559
+ });
560
+ }
561
+
562
+ clearMacQuarantine(paths.appRoot);
563
+
564
+ // Sign nested dylibs first, then the executable, then the bundle (ad-hoc / unsigned path).
565
+ for (const name of libraryBasenames) {
566
+ spawnSync(
567
+ 'codesign',
568
+ ['--force', '-s', '-', '--identifier', MACOS_BUNDLE_ID, join(paths.libDir, name)],
569
+ { stdio: 'ignore' },
570
+ );
571
+ }
230
572
  spawnSync('codesign', ['--force', '-s', '-', '--identifier', MACOS_BUNDLE_ID, paths.executable], {
231
573
  stdio: 'ignore',
232
574
  });
233
575
  spawnSync('codesign', ['--force', '-s', '-', '--identifier', MACOS_BUNDLE_ID, paths.appRoot], {
234
576
  stdio: 'ignore',
235
577
  });
236
- return paths;
578
+ return { ...paths, bundledLibraries: libraryBasenames };
237
579
  }
238
580
 
239
581
  export function parseRelease(version) {
Binary file
@@ -94,127 +94,201 @@ private let hotspot = CGPoint(x: 12, y: 12)
94
94
 
95
95
  /// Ship asset `macos/jian-pointer.png` (@3x master) as base64 — single-file helper stays
96
96
  /// reliable when only the binary is copied into Application Support (no sidecar PNG).
97
- private let jianPointerPngBase64 =
98
- "iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAaf0lEQVR4nO1dW6wkV3Vd+1T38EcQ"
99
- "Fi+bGc+MZ+w4g4AoJIoQkSIh8oNEflAUPhARQrZxHIcoxglfiD+IQTaDI5IoEZHgI5FCflBeH0mk"
100
- "RCbGCEuQsQdzPXc8Y5vwCijhJ3du19n5OK99TlXfe7v7VN+err3s7nr0o2qq1121zt7n7AMoFAqF"
101
- "QqFQKBQKhUKhUCgUCoVCoVAoFAqFQqFQKBQKhUKhUCgUCoVCoTh20HGfwHyQODfm4zsPxc2EYyQ0"
102
- "VTq2kl2RsCZC95B31SPPpbESfMxYA6EFmXuPRnM35oB7V3s2ldzjw4CELlS5y9tDjl2+fCA3ufOe"
103
- "7O1K7LFgIELPU+U+IpNcULG3A04rXRJnO5TcY8QAhO4jc0lkAigxueckDjqvDlPZPfURnPuJraTe"
104
- "VlQmNM3T2STDFNgtX6O+M+nZyfFJrqLLaZ5LbCX1VqMioXvJfACRKawWxD2kEemoW8ouC4KnHUrs"
105
- "0aESoQ8nc5fIgbgkxbrfX2eQqizJGYjJGbl7iK2k3mJM6n/lXDKT42sgvyB011NT8X0Ckb2UFJn9"
106
- "+8Sqf4UAcNpmt0VuiwK3iZTU24EKCi3VeR6ZpSqLdU9wimTPuEy9ycRcjd0Tc3xy+5j9WxhJoVWt"
107
- "R4A6Ct3hXYfMXoUDodOOqNpOsenOj/3wp+FbvvPJ170yHYDlsTjxjhlgJqfDgbhecYMgu/eSV29h"
108
- "sv0fEHM6hKr1zYwVFbpPnecocyKzYzZRRvI7P/aDn/YdYedTt77KfS6KqfDK0ic7YoulV225H/F9"
109
- "c9VaY9Y3NWoSOnjjaJZz9XVLgnHbhxB5HnYeOXkLgEBMwKk1g9mz2HaJHdaL/eg2GtWC3OSoROh5"
110
- "6izJbIIqE8gQiMydf/j9/13mqM9/5sxrI6EjkQNRreW0fhDZD/DWQc2Rbys2Hit46DJUB3S8MoQy"
111
- "JzIbENGyZAYAMpOGBaHJk9XtM0Rk3TbIghypyVkOL82e1MJbewcewiRui4Jah9apEnvTsYJCp2gc"
112
- "kIjsNNoAgAEZgMgkm2GMU2pjQGTOP/zyj1c5+SuP3XVbICdHNbaWnRJbp9CWmdM6/I6uNQF61Fot"
113
- "yE2GGoSOcWXKIxnk1JKMsxhOmYkaAzLm/MMvrUTmgN2LF05xICuz9es2EdtaWGbAitekorNFEm+1"
114
- "IDc5KhE6euegxADIkPfKgdBOmRs6//BLP6l0/gCA3cfffMYR1BHZq7FlG4md9ol1562TzxYNR09p"
115
- "ZsliVevNR8VMobfMyYL4DZ88caR2Sl0ZZx/41lUA2H38LWeTOreGYFtma4hbC6aWmYiYCEyWmQC2"
116
- "TL616FhqQ6aRiV2LoIhZc0o/Ahqz3jwsQa6gwkAQeOrkqlOgw9kMQwCZqNID4ewD39ylZjqFmU7J"
117
- "TCdophNqJg2ZSQMzmRA1DfzDrRsDagyRMd4auQecPUL4h6ZsPIk7Uroeio3BquSSzE6ZvxiLjiE6"
118
- "H7YbRqElztz/9A410wk10wkZ94CZTsg4YrtHY2Aak0jtrFC6i1D2iFYqkTeRWqb0FceOupbDL72j"
119
- "TmQIihcVcFic+fDXnwOAq5//xbvAxoJMCzbEZCzZ1lkP27ZsYIkJYAKzJTAsOQthmRmgaEFC2tx1"
120
- "itK0+caiErlILoV0CZWLUQ6zNiU78+GvP0cmqPVkQmYygVs2aRktiIGPwKBrQWiOBYFakM1CDUKn"
121
- "BItMrGRZwmg5DMzwCi1x+r6vXSZzYormxDSzIs5bT4gmDZmmgWkaIiMtiFELcvNhBXJ1MoVhW0hX"
122
- "SLYEhVvMQ1/++CuWPz2B0/d+9Zkz9z31bfKkRhO89aShZuKW1BiYiSHTGOexTWzEUqHSgdRRtPPI"
123
- "jqr1MWI1tSwyheG/dBuWqmaWinLUIjUAnL73yWc9qaNaIzUWJ06pJ30WxFsmtSCbjsoeOhkP8YNL"
124
- "H+1u4QuiKqnv8WrtQnvT4LHRJFJHC2KahowRvlotyKajrp+NiRXpnfMedstGOS5//BV1iX3f1y5T"
125
- "c2JCzYkpUniv8Q1HR2oXszaO4H0WxKgF2TCsSGgSi/jjdW65FNXM37pXQF0L8h/PevvhH5NIah+v"
126
- "dkkZaky/BSG1IBuGlRMrc7YzqwGYQrFXQ2ULcslZkBOTaEOaaRbWS8tgQRq1IBuKumE7v0KxsZga"
127
- "hxSiHagTtqtvQZ70FmQaiB0yjBMkpfYWxKgF2VBUjgnnCRb/HHxJahhWRH0LcmKKEK9uJhMy08al"
128
- "0Bu1IDcBKhA6KHG+wzcQw3r+qIy6FuSJSz5mPaHmxATJW6sFuQkwQNaOslXZ7S766AFQ3YLc++Tl"
129
- "GNaL1iMsJ2pBNhQVCU0kFMc/idtt+jEH/dEqW5BnnAXx3rpJ5A72Qy3IZqF2KTAqVsm7j8EVWiKQ"
130
- "+u5P7K38XafveeISALzwp7/8c6AZsW/fsiUitK3rfkfE3PrBA3CDB6xlAiyHgQMCYlAufO88AkgH"
131
- "5VbAMI1CKrY9qZP9WA+qp807FmSS+oRIC0JqQY4LQ/R88w3BuOmNiBDrNWJ4CzKZpERMGB1T24Io"
132
- "sY+KgaqPzldqrJvRWKcFIWdBLBGbxSwIqGf8IslBuURqQQ7HkH2T0+0zhaWl9Kwdm2xBetRaLcgS"
133
- "GJDQKdxx8L71YqMtSB6z9kcRFkRj1odiAMshIZMr2AQ+A9hgC6IlFFbGmoZDldG8zcCwFmQ6z4I0"
134
- "cyyIK8hzaAkFqAU5AGsc30dRozcJx2BBjLAgjbAgvr+4iNerBVkYA1uOEuuNQx8Vw1kQ6rMgRJZa"
135
- "b0GsK6FAWsWpEtY6AnvTMYgFkQVvfO+92NdaqzhVhxK6QHULIksohH4gzVGrOFHnoT33DsaaLcfN"
136
- "gcEtiCViBAtCfVWcAD/zka9njSNUcVILAlXoAzFICQVTWpBJgxSv7liQWMXpaIkYd7ARWxAl9CGo"
137
- "XULBR0FyCxKiIKmKkyFRlqxIxJRRkH5SR4yL1Go5joDBLAjKKAiCBQEb+CgIwBaAi4VYlkkYIFgQ"
138
- "ZmIXDwlFJElOUzce+6EKvQDqW5BOPZBJqrPn+oH4uiByFoR8mBd67Qcg+9K4lVEotRJ6QdQelHvm"
139
- "w19/jprp1A/GFX56YsgkP51XcCIqrUc/qUtPvf1QQi+B2uMX3aDciR9lHhqJvnKTSRnFVDA+xqqj"
140
- "Qh/aUAQwBpVWQq+AunVBnvo2ykZiHFneITX5GcaKcmtIpC5leiTWQwm9Iuoq9dcun7n/6Z1QkN1X"
141
- "QhU+OpZL8DMixJnGQtmIRN+s68xWcziDEroCqluQ+7+xE5Q5VkPt+GjfjzqyWSp19M55NnEEUEJX"
142
- "RF1SP71DSaVD1KMR8WlKE5qaLOKB6EOyDo7lOM+thBK6MmqT+uwD37qa+nu4KT3IhBAeBesh/bT7"
143
- "cNLmPOqx5aRWQg+A2hbk7O/85wtuygxP6uijTayFAGmkc7Uei9sAoIQeFFVJ/eClayT6d6RZebNE"
144
- "C7KeeOn5gNT4dkFT3wOjZtr87IPPXgeAK4+ev5XJMoGYXZiDmVMcml1HPM9gHkfO20MVek2oqdZ3"
145
- "/N7Od8/9/tXvd3rgSZWOXjqEp3NXHV/cMiih14iapAaAcw+98MNYVSyPcABxRIsc97b9jUMl9JpR"
146
- "u8F47qHrPxIKDUjPXCQMO8zdQlIroY8JNUl9/uGXfhzZm4IbiaS0hcydAyX0MaIWqXceOXVLsh0A"
147
- "ksXI+bvtbIYS+thRw4Kc/+j1/z7/8Ms/EYNk0ekXnfcl3drwnRJ6Q1BHrbeTpItACb1BWFmp/+C/"
148
- "/kdsFoo8DiihNwyrWxA6YHP7ea2ZwgVRI+M3LMaUF+xCFXoBbD6ZM7B4znZtM5TQiq2CEnrrwfFp"
149
- "DFBCbxG+88nXvdIVlGEWHC7IvN3cPgZCb/cFPWZw4Zk5e20EWDOhmTGSC7tu7Hzy9T/jLy+H/+OL"
150
- "gddiz7b+DGsitL/QYVVRFTufesOrOLcaoq7dfMneRgwch45EdnoxrvbJ4Nh55OSrwS2DOXsIcos7"
151
- "4jiu+4CE7mOvMroGnv/06dcwtxZsGeyeMgJLHRb3Re79OYBtEu6BCC2Imyvz1nq3oXHl0fO3Mrct"
152
- "rLXM1pPZsuOztVGd2RObpQXJPHXxG2wPmYFBCC1uc3nkKPi6tV/Ao2b4DutDcfnjr1gqW/i9r/z2"
153
- "e7nd2+d2f5/bG/vc3phxu78Puz/jdn/Gdtaync0Ql61l27bMsxbWWnDbMrfWrUcye2JnVgMZX3mO"
154
- "gmyhMgdUbhR2bnVIBOdCKIbH3Z/YW4iAR3nvUh2HbGth25btrIWdtbBtG7bZti3btvVk9tszT+a2"
155
- "ZW5bto7MzK11VqO1zOzJ7EjNsMlHI1dnPw8LMIff24TaUY4+ZUZgMstox4BYlMjlZ2vj9b/+J3/L"
156
- "bB0prQ3qa2HbFuzJzG0guoVfd6ocCNxGdRaWwwKCzNJLs2yvbDeJJSoSurx2SZkdk6W3Gw7r6EC0"
157
- "lEqzZXh1RSA3W8u2tcy2hW2jAnOwFs5uBM8syMyJzFKVmaXJ8Jd9nnfeTtRUaJ6nzEh85qEUehVV"
158
- "Xgdufe8X/4EjQkMuLFsWpHUkto74XTKnRqD/nrwR6MUjkXn7IxsSFQhd2ojcM6fXh1Po2kQezEuD"
159
- "GbAMWO/AJEETeTkncKHM3LUZmTJzce3dgXOB3k4yA8M2CoMyF4F/W+1ibroql3jj+/7mX8HhP5EA"
160
- "kZEKjkQNcWbOGoDI3iPJHBuC3EfmkaAGoYuGYNhI8hxVmq37cSpgaCIPp9KAvCzcR+zgjSN5rVf2"
161
- "XjJnNmMumUegzsAgUY4Q0QAn9xEi/uGWuxpuJlUucfL9X3kije3rOLWCqIVVm9sA7PXMoyMzsDKh"
162
- "WahzvHipEdj7oyxP6E20GMuo9Knf+qenitoZBeL1y3ZySVCOF/UIZB4HKkc5sh8hWg0ORGZrl7Uc"
163
- "x0HkQY+ZzWAFzCG3VGaU4hBuhEXiZA6Zt1+dgWqEliSGuB32NXjsQoTeRFUusYxK3/7Bf3k6q4Hb"
164
- "U0tRIrJU3g3dqlBmQeTMZoyDzEC1sF1YC1cyqIlv8yCLoR754g5B5B/840PvX+T961PpUPX2ABvi"
165
- "ltHLdVrifS5lZFiB0CwvYBKQtJ03YHwMlRdU6Jr43lfuf6+d7e19/+8/8r7a372USn/o376ZzQRL"
166
- "afLMo9eEKdTZrY9KlSVq9LZjwM2D4H4EZjATyEkGeQNNsMalc9u1E/q7X/7Au90EO36OEtM06z6H"
167
- "uaBUhT9MAMREAOczabplxxv3sHmcRA6o66FZ3BZjiMnHUJ06L+yhV8XLf/Ub7+TZ3h7P/u+Gne3d"
168
- "4HbvBs/2bizyHbW6n/bh9D1PXJKkzubsTlNJ9Ot1T1Bj7KjfOUkEnyWxWfbhXQNe/NJ73vHil97z"
169
- "DtsmEvvlvm339r/75Q+8e4jjLkNqIhKT0RvqeOswJb1/+3w7Mm51BpYidAqHAvB5XL8a8lQpqpR6"
170
- "g4l+C88/eu4NdU6/H9f/8td+yRN4n2eOxNze2PfLG/6xv8h3Dtk4PH3vk8+KqdmKGWHD5Gxid8D2"
171
- "115cGEsqdCB1bAIKaYgKjdQ48X0S4Elth1Ppa3/xq291hN3b55kjriBx2N7n9sb+y3/9m+8a4hyW"
172
- "SonHOQezWWEFwaX1SGERv13pzG9+VByC5TlMFNZTYgXMBMtgYoa1CzThj4wX/uztFzIfGarZE4k5"
173
- "sRsDtpZ44u8cm+M8z9z31Lev/vHPnwMMsfDRDL/q2tm+5d1z2gTfkBy37RggsRIag9J/2KDOvntk"
174
- "a5//9OnX1Dk2cPXzb7uTZ0l5ex6z4rHvxvLtzxY5ziK2YzmVDopc+migUGqoKvejZm87kcnyKylV"
175
- "KzukR1KveuDdx996dvfxt5x15Lyxnz08Ybndn7nBqX5Qqt8XBqi++KX3vGPV86iFM/c/vRMnoxeV"
176
- "9+NkQMW0KVTuUNRIrIieMrGJWHSDFA1DSeqdR07esuzRdy9eOMX2hiesJ3DxQCCuTQRGO5uxnaV9"
177
- "drZZKi0noCefPRQWmsJchH1cjpMGjRe1PLRLrqR0oZ9yGgC5FiPBsvv7sZYBQ4AFmHf+6I2vdkkP"
178
- "onMPXfvRvANceezO24ojyiyDCMSmmc2iFzXGMAzDiM49/r1ERC9+8d1vP/n+v/tqnUuxIrIJNP06"
179
- "IzE6XecDLfVYUYnQ/vo65sKx2KuI28cMMLFFIjUT2BgitgATM9HOIydvIRCd++j1SOznP3PmtZnq"
180
- "ZD8gJ1KHn1gQ2iubARsLMobADUcOSI9qBlO1ZWp5EIg42gpQh6+uAQjPZ3L/em0QAit7L+nt0vx3"
181
- "KQ8gwk4iUeCSCATAmJgZS0kEkTFLp1j22uEyPRZT7yK05b7KuDtAY0CmITNpYCYNmUlDzXQKM52Y"
182
- "5sT01Af/+RuL/MsXsROLEnr34oXbud3fZ7vfws5m7OtzpJIGceR3snUAOuHUEWKITGHoCoasYSgH"
183
- "eGZFUnwj0VpZhyIWY4Gdtb4uRRsfRcEW956ZhfW1LmIhF1eByFUimvnPz0RRl1kLdtWKrn/hXW+r"
184
- "dy1yLOqlzz74zLX5s7GN2iIfihUtB7tbXbzdR+/hXyQQOHVc4uRL3GvEIv1FADHH7xM2g/PIdSdV"
185
- "WQagKUi9u0swmIk5/vGyIRATwZqWyRAwc3HqBXD3J/aqztctsXvxwu0H+2I1zvNQoz+0CNdlRBNP"
186
- "PePkfGclzofri0IsbZvVqRCP2GvPVR6yKD8f6sH5SkWpwKG/XYfacUHpffWi61945y+sfj36sQj5"
187
- "zz74zDW3No+0SuZ5GKDguUh9+4R3TINn9iMUSAlVNCPBU0FC6y2IJ6V7BFviKw+xFWRPxPWVijhV"
188
- "LArkdvbFVzEKteQSwRfAsCNp8r4FMjyqmI9aUY7Cevh4nW+KMxPge/lK8yFSMeTb6t6OsLinytvr"
189
- "gT9mOB7YH5tcdJBY+BdmIrIEhm0BS0StddZjRrCL2Y5FsAT5g5Uqb3uKA1CzL8ccUntPzcRMHANO"
190
- "ediY2XdoR/oRQ7Ks50ec35L3n3PcZrLefxv4/iQW7EJixC2BybKlFmSIrCHQzFz781958+0f+vdv"
191
- "1boqS6t46GvCJakVB6FyfejDSQ0ATIK9IdgWgtgkvuuwn7F8vfvHEXI4Bm6kgSEm686RLHNriQ3B"
192
- "tpZhWsQ+yUdHX+NwVSty5bG7bktp2BAzSt4tb58oJAaIARVJkHyjzNPGJC51P7D0CYhIhw92GEOu"
193
- "w4+BaQz5YVhEjYtJN5OGzGRCZjpBM52QmU5O3/PEpRonswyuPHrnraHBGsOUoTELa2GZAR+LhghD"
194
- "axx6sAr+iEoNlGrt98Qkn/fN4T04tNcNx88VkH8u3rcjdPkjC4KxYOsP78OF3BIsESNYj7IX/Xpx"
195
- "5bN3n4xlv1LPRaSl2+g2K8ZLYokhJw3iSIxI43T1kXG2+C0EWRf6lTgchInJPTlSc/wbcBuWicky"
196
- "iIiJmC2RI3bLnWEha4YrxsPo1LBDMNTZJdmgLt0bgYHnKSxUg8sN4ROlRzzyg7n7+RgiRHjqvq8Y"
197
- "42hbl6m0rYWfFuLq599216CXZh5i2NJlVUUX3HhLE2/urIwdA89TCPSTeo4CdrvhzPnKOftJREjc"
198
- "cWPsMPkUy+6WQOyGhoVGYgswWuaQRTzaqdTElcfuui1UG+U4bM03Cv3foXsns3K4H2sgdB8kyWWK"
199
- "e9WvRYp0OA/P3kcnjhN8nxLrXT3BWQ+ALRGhdX56jdi9eOF2DnOqhPp/he1I3WNEC7D0GyNvEALH"
200
- "RmiJmj9A1hANwWif1+GYo2Hi0KOVmS0TyLIFyLTENqVydi++6XaYpjn7wDd3651jFzFzWU7bltRZ"
201
- "WCf0XDIV7IANIHRNiIZolOvCZ7oOUiHRwgBs7FkVOM8AWYAN8x0PXLo25Blf+ezPvjGl4+WIntA7"
202
- "0Xp/ESxHCErH9qGg8rjVGdjavoiyNlzqZ+2i0yZVJyJj0ohwQ2SMATVNKBlGxvWhvuMjz71U+wyv"
203
- "XLxwSvRvjrNgxXhzNr+KIzZEwROECq9ZAkoJvaWEBhKpxUABigMJ4kiVWLHIkdoQGQPTEJFp3H5P"
204
- "cNOYO3738ournNHu5958Jp+mLU3hJuYhlFMf2zgFhZ9fpYjeQAmdY7sJDSCROg6mkYNPZRaRIqE9"
205
- "wR2RfT2PWOzR/RGcffDZ60c9k93Pvem0S+iV0xpHAnP/umwYhqgHhDrHvh5QMjtsMaEBodL+qUNq"
206
- "EyyI2yfsh1DunOSyboaZq9pXLl44FX1vTJAUE2fKuQdhLdtgLcQ8hLG7bWodZuE7VecM209oABmp"
207
- "Y80L8rWYU1GXkqxSud3rYQyk+Ez2XbGTqkjhhTF/Yi5ulvMUynolro9GLP2Qz0VYWI3QUAz/ViU0"
208
- "sHVRjhI9UQ9m5lAcwMXzYvyWYYhgjSemG5kOQwRmMBl2I8SIYOOAX1cqQZA5D6yI2PFBxE4eOdoM"
209
- "mSVMmXvBYCVzH7ac0B4x4eLXGMxpwIEgoQWDbBgY4LMxxEwEMuzGR/p6H+zFmYmEUU+x7kg3EW6L"
210
- "EbcsUtElt4xixMhzDNNBrihybLnlCOgvtxArLkjLIKIgVGzn+0GxsRmOIa9mUNW44Q1DQeyk3N39"
211
- "6c4RLIxajcMwEkIDh5MaKfohQ34lsd1u0SMvkNt/BVIGxy8KIkbljS1GkSsRoTjP5j4yi69XQucY"
212
- "EaGBIuHinxIhuw28EA2RjUmkfdmXUX41O4SLigt4z5HHkXNVdu9UMi+K8REaQC+pg4noJW2RpBGv"
213
- "iabgPKTYWt6ok4rsXy1VGVAyL4aRERqYT2q/oELGY2dAaTf6PnsgpOntiSMn0oa4SN4AVDIfFSMk"
214
- "NHAwqf0qlaY7cxg9163cJxuFxT7OX+9XcBklyb5DyXwARkpoICPgwcQWb6biE0cxHNmK2OLOSv6p"
215
- "3t1K5kMwYkID/aSOG8W1Kcnd85a54Hytn8R+ByN/M6BEPjpGTmjgcH4e5JMXuXy9nOS+hXhZibwg"
216
- "lNAdFF64q9y9G4egT3YP2KVEXhZK6LnoafjVulr9Yq0krgAl9JFRu1aHElihUCgUCoVCoVAoFAqF"
217
- "QqFQKBQKhUKhUCgUCoVCoVAoFAqFQqFQKBQKhUKhUCgUa8X/A+26fqLnlvojAAAAAElFTkSuQmCC"
97
+ private let jianPointerPngBase64 = """
98
+ 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
291
+ """
218
292
 
219
293
  private let jianPointerImage: NSImage? = {
220
294
  guard let data = Data(base64Encoded: jianPointerPngBase64, options: .ignoreUnknownCharacters)
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jian-ai/remote-control",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Jian Remote Control worker — connect a computer to a Jian gateway over HTTPS",
5
5
  "type": "module",
6
6
  "bin": {