pinomad 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/chunk-0dh2k3er.js +43 -0
  2. package/dist/{chunk-47ff1d1t.js → chunk-1mjbt2z2.js} +191 -11
  3. package/dist/{chunk-7wj0jh3t.js → chunk-1rdbnvy6.js} +1 -1
  4. package/dist/{chunk-ksfxqd8s.js → chunk-35szq73k.js} +2682 -459
  5. package/dist/{chunk-mnmqyq7d.js → chunk-5j7ybhjj.js} +1984 -333
  6. package/dist/{chunk-agq4tn9r.js → chunk-5pv0g1nj.js} +12 -10
  7. package/dist/{chunk-7mn38n4f.js → chunk-63ymn5c9.js} +2 -2
  8. package/dist/{chunk-nppgxh6c.js → chunk-6j6hkfbj.js} +8 -4
  9. package/dist/{chunk-pqe7q1s7.js → chunk-6vbp1vva.js} +2 -1
  10. package/dist/{chunk-g3ahp7b9.js → chunk-9trbbz4r.js} +1 -1
  11. package/dist/{chunk-gg2dcqbg.js → chunk-b0nwq1dt.js} +29 -12
  12. package/dist/chunk-dsr19q5h.js +23 -0
  13. package/dist/{chunk-41q0saz0.js → chunk-e53c0s8z.js} +9 -7
  14. package/dist/{chunk-np4jd070.js → chunk-e59k3bmz.js} +307 -56
  15. package/dist/chunk-eerpgvy9.js +315 -0
  16. package/dist/chunk-eewxy4cp.js +240 -0
  17. package/dist/{chunk-vqkb70d7.js → chunk-evbv1fkn.js} +3 -3
  18. package/dist/{chunk-vx7dy07y.js → chunk-ex5yr09h.js} +11 -6
  19. package/dist/{chunk-t91zt5f0.js → chunk-hg9gs396.js} +1 -1
  20. package/dist/{chunk-aqj9wfmb.js → chunk-mtkvft88.js} +1 -1
  21. package/dist/{chunk-t5abqsva.js → chunk-mxwcnnkg.js} +15 -305
  22. package/dist/{chunk-5qf1grkk.js → chunk-w927q9m1.js} +52 -16
  23. package/dist/pinomad.js +12 -12
  24. package/package.json +16 -11
  25. package/web/assets/{core-DnpzcQzs.js → core-BWHGsFpV.js} +1 -1
  26. package/web/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  27. package/web/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  28. package/web/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  29. package/web/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  30. package/web/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  31. package/web/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  32. package/web/assets/{highlighted-diff-Dn5ifsvK.js → highlighted-diff-DJ7KZCpS.js} +2 -2
  33. package/web/assets/{highlights-DnHv6NBM.js → highlights-CyEmo6OI.js} +1 -1
  34. package/web/assets/{highlights-themes-CUdrlZk3.js → highlights-themes-CSNkBojy.js} +1 -1
  35. package/web/assets/index-C_qkbyL7.css +1 -0
  36. package/web/assets/index-DefQtCI2.js +396 -0
  37. package/web/assets/{shiki-BuPP5HCg.js → shiki-BzCmRG-v.js} +2 -2
  38. package/web/assets/{shiki-langs-FJk0v0Ga.js → shiki-langs-DOkjyV4d.js} +1 -1
  39. package/web/assets/{stream-tokenizer-Bl6bisIa.js → stream-tokenizer-CBPqFe4Z.js} +1 -1
  40. package/web/assets/{theming-themes-BL_CC-Mm.js → theming-themes-wKVca0aB.js} +1 -1
  41. package/web/assets/{xterm-view-ZsuzJb2C.js → xterm-view-CKa1-QCM.js} +12 -12
  42. package/web/index.html +3 -2
  43. package/web/theme-boot.js +11 -0
  44. package/dist/chunk-42nqtx5r.js +0 -22
  45. package/dist/chunk-jeqsdcj1.js +0 -96
  46. package/web/assets/index-BV0ecolo.css +0 -1
  47. package/web/assets/index-DNsTTgPE.js +0 -396
@@ -1,29 +1,7 @@
1
- import {
2
- ProtocolMismatchError,
3
- connectRemoteDurable
4
- } from "./chunk-np4jd070.js";
5
- import {
6
- isParseArgsError
7
- } from "./chunk-kzbzacz9.js";
8
- import {
9
- DEFAULT_DATA_DIR,
10
- hostAddress
11
- } from "./chunk-ngf1zatm.js";
12
- import {
13
- commandHint,
14
- hostEntry,
15
- packagedVersion
16
- } from "./chunk-7wj0jh3t.js";
17
-
18
- // apps/host/src/cli/service.ts
19
- import { execFile as execFile2 } from "node:child_process";
20
- import { homedir as homedir2 } from "node:os";
21
- import { resolve as resolve2 } from "node:path";
22
- import { fileURLToPath } from "node:url";
23
- import { parseArgs, promisify as promisify2 } from "node:util";
24
-
25
1
  // apps/host/src/service/definition.ts
26
2
  import { join, resolve } from "node:path";
3
+ var LAUNCHER_EXECUTABLE = "pinomad-host";
4
+ var isLauncher = (path) => path.endsWith(`.app/Contents/MacOS/${LAUNCHER_EXECUTABLE}`);
27
5
  function sanitizePath(path) {
28
6
  const seen = new Set;
29
7
  const kept = [];
@@ -149,11 +127,21 @@ function specFromLaunchdPlist(text) {
149
127
  const workdir = /<key>WorkingDirectory<\/key>\s*<string>([\s\S]*?)<\/string>/.exec(text)?.[1];
150
128
  if (workdir === undefined)
151
129
  throw new Error("plist has no WorkingDirectory");
152
- return specFromProgram(program, env, xmlUnescape(workdir));
130
+ if (program[0] === undefined || !isLauncher(program[0]))
131
+ return specFromProgram(program, env, xmlUnescape(workdir));
132
+ return { ...specFromProgram(program.slice(1), env, xmlUnescape(workdir)), launcher: program[0] };
153
133
  }
154
134
  var xmlEscape = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
155
135
  function launchdPlist(spec) {
156
- const program = [spec.nodePath, spec.mainPath, ...spec.entryArgs, "--data-dir", spec.dataDir, ...spec.hostArgs];
136
+ const program = [
137
+ ...spec.launcher === undefined ? [] : [spec.launcher],
138
+ spec.nodePath,
139
+ spec.mainPath,
140
+ ...spec.entryArgs,
141
+ "--data-dir",
142
+ spec.dataDir,
143
+ ...spec.hostArgs
144
+ ];
157
145
  const log = join(spec.dataDir, "logs", "host.log");
158
146
  const env = Object.entries(spec.env).map(([key, value]) => ` <key>${xmlEscape(key)}</key>
159
147
  <string>${xmlEscape(value)}</string>`);
@@ -207,37 +195,6 @@ WantedBy=default.target
207
195
  `;
208
196
  }
209
197
 
210
- // apps/host/src/service/idle.ts
211
- async function waitForIdle(remote, onBusy) {
212
- if (remote.view.current().tasks === undefined)
213
- await remote.controller.toggleTasks();
214
- let announced = false;
215
- await new Promise((resolve2) => {
216
- const check = () => {
217
- const view = remote.view.current();
218
- if (view.connection !== "connected") {
219
- unsubscribe();
220
- resolve2();
221
- return;
222
- }
223
- const tasks = view.tasks;
224
- if (tasks === undefined)
225
- return;
226
- if (Object.keys(tasks.tasks).length === 0) {
227
- unsubscribe();
228
- resolve2();
229
- return;
230
- }
231
- if (!announced) {
232
- announced = true;
233
- onBusy(tasks);
234
- }
235
- };
236
- const unsubscribe = remote.view.subscribe(check);
237
- check();
238
- });
239
- }
240
-
241
198
  // apps/host/src/service/manager.ts
242
199
  import { execFile, spawn } from "node:child_process";
243
200
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
@@ -416,251 +373,4 @@ function serviceManager(platform = process.platform) {
416
373
  throw new Error(`service commands support macOS and Linux, not ${platform}`);
417
374
  }
418
375
 
419
- // apps/host/src/cli/service.ts
420
- var run2 = promisify2(execFile2);
421
- var repoRoot = fileURLToPath(new URL("../../../../", import.meta.url));
422
- var message = (error) => error instanceof Error ? error.message : String(error);
423
- function connectToHost(url, token, timeoutMs = 3000) {
424
- const connecting = connectRemoteDurable({ url, token, reconnectDelayMs: { min: 200, max: 2000 } });
425
- const timedOut = Symbol("timedOut");
426
- return Promise.race([
427
- connecting,
428
- new Promise((resolve3) => {
429
- const timer = setTimeout(() => resolve3(timedOut), timeoutMs);
430
- timer.unref();
431
- })
432
- ]).then((winner) => {
433
- if (winner !== timedOut)
434
- return winner;
435
- connecting.then((remote) => remote.close(), () => {});
436
- throw new Error("connect timed out");
437
- });
438
- }
439
- async function install(argv) {
440
- const spec = installSpec(argv, {
441
- execPath: process.execPath,
442
- env: process.env,
443
- home: homedir2(),
444
- cwd: process.cwd(),
445
- mainPath: hostEntry.script,
446
- entryArgs: hostEntry.args
447
- });
448
- const path = await serviceManager().install(spec);
449
- console.log(`installed ${path}`);
450
- console.log(`data dir: ${spec.dataDir}`);
451
- console.log(`browser link: ${commandHint("link")} pairing QR: ${commandHint("pair")}`);
452
- }
453
- async function waitUntilIdle(address, connect, log) {
454
- try {
455
- const remote = await connect(address.url, address.token);
456
- await waitForIdle(remote, (tasks) => {
457
- log("waiting for running tasks to finish (Ctrl-C to cancel)");
458
- for (const task of Object.values(tasks.tasks)) {
459
- log(` ${task.kind} in conversation ${task.conversationId}`);
460
- }
461
- });
462
- remote.close();
463
- } catch {}
464
- }
465
- async function stopService({
466
- force,
467
- argv,
468
- manager = serviceManager(),
469
- connect = connectToHost,
470
- log = (line) => console.log(line),
471
- logError = (line) => console.error(line)
472
- }) {
473
- const state = await manager.state();
474
- if (!state.installed) {
475
- log(`service not installed (${commandHint("service")} install)`);
476
- return 1;
477
- }
478
- if (state.stopped) {
479
- log("already stopped");
480
- return 0;
481
- }
482
- if (!force) {
483
- const spec = argv.length === 0 ? await manager.read() : undefined;
484
- const port = spec === undefined ? undefined : argValue(spec.hostArgs, "--port");
485
- const flags = spec === undefined ? argv : ["--data-dir", spec.dataDir, ...port === undefined ? [] : ["--url", `ws://127.0.0.1:${port}`]];
486
- const address = await hostAddress(flags).catch((error) => {
487
- if (isParseArgsError(error))
488
- throw error;
489
- return;
490
- });
491
- if (address !== undefined)
492
- await waitUntilIdle(address, connect, log);
493
- }
494
- const holdInterrupt = () => {};
495
- process.on("SIGINT", holdInterrupt);
496
- try {
497
- await manager.stop();
498
- } finally {
499
- process.off("SIGINT", holdInterrupt);
500
- }
501
- const after = await manager.state();
502
- if (!after.stopped) {
503
- logError(`the host is still running (${after.detail}); run \`${commandHint("service")} stop\` again`);
504
- return 1;
505
- }
506
- log(`stopped; it stays off, also after a restart, until \`${commandHint("service")} start\``);
507
- return 0;
508
- }
509
- async function startService({
510
- manager = serviceManager(),
511
- log = (line) => console.log(line)
512
- } = {}) {
513
- if (!(await manager.state()).installed) {
514
- log(`service not installed (${commandHint("service")} install)`);
515
- return 1;
516
- }
517
- await manager.start();
518
- log("started");
519
- return 0;
520
- }
521
- async function versionLine() {
522
- if (packagedVersion !== undefined)
523
- return `version: ${packagedVersion}`;
524
- const head = await run2("git", ["rev-parse", "--short", "HEAD"], { cwd: repoRoot }).then(({ stdout }) => stdout.trim(), () => "unknown");
525
- return `checkout: ${head}`;
526
- }
527
- async function reachabilityLine(argv) {
528
- try {
529
- const { url, token } = await hostAddress(argv);
530
- const remote = await connectToHost(url, token);
531
- if (remote.view.current().tasks === undefined)
532
- await remote.controller.toggleTasks();
533
- const tasks = remote.view.current().tasks;
534
- const count = tasks === undefined ? 0 : Object.keys(tasks.tasks).length;
535
- remote.close();
536
- return `host: reachable at ${url}, ${count} live task${count === 1 ? "" : "s"}`;
537
- } catch (error) {
538
- if (isParseArgsError(error))
539
- throw error;
540
- return `host: unreachable (${message(error)})`;
541
- }
542
- }
543
- var serviceStatusJson = (state) => JSON.stringify({
544
- installed: state.installed,
545
- stopped: state.stopped,
546
- running: state.running,
547
- ...state.pid === undefined ? {} : { pid: state.pid },
548
- detail: state.detail
549
- });
550
- async function status(argv) {
551
- const state = await serviceManager().state();
552
- if (argv.includes("--json")) {
553
- console.log(serviceStatusJson(state));
554
- return;
555
- }
556
- console.log(`service: ${state.installed ? state.detail : "not installed"}`);
557
- console.log(await versionLine());
558
- console.log(await reachabilityLine(argv));
559
- }
560
- async function restartService({
561
- force,
562
- argv,
563
- manager = serviceManager(),
564
- restart,
565
- connect = connectToHost,
566
- pollTimeoutMs = 30000,
567
- pollDelayMs = 500
568
- }) {
569
- const state = await manager.state();
570
- if (!state.installed) {
571
- console.log(`service not installed (${commandHint("service")} install)`);
572
- return 1;
573
- }
574
- if (state.stopped && restart === undefined) {
575
- console.log(`service stopped (${commandHint("service")} start)`);
576
- return 1;
577
- }
578
- const address = await hostAddress(argv).catch((error) => {
579
- if (isParseArgsError(error))
580
- throw error;
581
- return;
582
- });
583
- if (!force && address !== undefined)
584
- await waitUntilIdle(address, connect, (line) => console.log(line));
585
- await (restart?.() ?? manager.restart());
586
- if (address === undefined) {
587
- console.log("restart requested (host address unknown; not polling)");
588
- return 0;
589
- }
590
- const deadline = Date.now() + pollTimeoutMs;
591
- for (;; ) {
592
- try {
593
- const remote = await connect(address.url, address.token, 2000);
594
- remote.close();
595
- console.log(`host restarted, reachable at ${address.url}`);
596
- return 0;
597
- } catch (error) {
598
- if (error instanceof ProtocolMismatchError && error.direction === "client-older") {
599
- const newer = error.hostVersion ?? `protocol major ${error.hostMajor}`;
600
- console.log(`host restarted (${newer}, newer than this upgrader), reachable at ${address.url}`);
601
- return 0;
602
- }
603
- if (Date.now() > deadline) {
604
- console.error(`host did not answer within ${pollTimeoutMs / 1000}s after restart: ${message(error)}`);
605
- return 1;
606
- }
607
- await new Promise((resolve3) => setTimeout(resolve3, pollDelayMs));
608
- }
609
- }
610
- }
611
- async function logs(argv) {
612
- const { values } = parseArgs({
613
- args: [...argv],
614
- options: {
615
- follow: { type: "boolean", default: false },
616
- lines: { type: "string", short: "n", default: "100" },
617
- "data-dir": { type: "string" }
618
- }
619
- });
620
- const dataDir = resolve2(values["data-dir"] ?? DEFAULT_DATA_DIR);
621
- await serviceManager().logs(dataDir, Number(values.lines), values.follow);
622
- }
623
- async function main(argv) {
624
- const [command, ...args] = argv;
625
- try {
626
- switch (command) {
627
- case "install":
628
- await install(args);
629
- break;
630
- case "uninstall":
631
- await serviceManager().uninstall();
632
- console.log("uninstalled");
633
- break;
634
- case "status":
635
- await status(args);
636
- break;
637
- case "restart": {
638
- const force = args.includes("--force");
639
- process.exitCode = await restartService({ force, argv: args.filter((arg) => arg !== "--force") });
640
- break;
641
- }
642
- case "stop": {
643
- const force = args.includes("--force");
644
- process.exitCode = await stopService({ force, argv: args.filter((arg) => arg !== "--force") });
645
- break;
646
- }
647
- case "start":
648
- process.exitCode = await startService();
649
- break;
650
- case "logs":
651
- await logs(args);
652
- break;
653
- default:
654
- console.error(`usage: ${commandHint("service")} install|uninstall|status|restart|stop|start|logs`);
655
- process.exitCode = 1;
656
- }
657
- } catch (error) {
658
- if (isParseArgsError(error))
659
- throw error;
660
- console.error(message(error));
661
- process.exitCode = 1;
662
- }
663
- }
664
- if (false) {}
665
-
666
- export { installSpec, argValue, withoutArg, withoutRelayArgs, serviceManager, stopService, startService, versionLine, reachabilityLine, serviceStatusJson, restartService, main };
376
+ export { LAUNCHER_EXECUTABLE, isLauncher, installSpec, argValue, withoutArg, withoutRelayArgs, serviceManager };
@@ -3,36 +3,40 @@ import {
3
3
  joinServer,
4
4
  openServiceSlot,
5
5
  writeService
6
- } from "./chunk-gg2dcqbg.js";
7
- import"./chunk-7mn38n4f.js";
8
- import"./chunk-nppgxh6c.js";
9
- import"./chunk-t91zt5f0.js";
6
+ } from "./chunk-b0nwq1dt.js";
7
+ import"./chunk-63ymn5c9.js";
8
+ import"./chunk-6j6hkfbj.js";
9
+ import"./chunk-hg9gs396.js";
10
10
  import {
11
11
  normalizeOrigin,
12
12
  readRemovalNotice,
13
13
  readServerConfig
14
14
  } from "./chunk-nq57fdnq.js";
15
- import"./chunk-g3ahp7b9.js";
15
+ import"./chunk-9trbbz4r.js";
16
+ import"./chunk-eerpgvy9.js";
17
+ import"./chunk-e59k3bmz.js";
18
+ import"./chunk-kzbzacz9.js";
16
19
  import {
20
+ LAUNCHER_EXECUTABLE,
17
21
  argValue,
22
+ isLauncher,
18
23
  serviceManager,
19
24
  withoutArg,
20
25
  withoutRelayArgs
21
- } from "./chunk-t5abqsva.js";
22
- import"./chunk-np4jd070.js";
23
- import"./chunk-kzbzacz9.js";
24
- import"./chunk-47ff1d1t.js";
25
- import"./chunk-pqe7q1s7.js";
26
+ } from "./chunk-mxwcnnkg.js";
27
+ import"./chunk-1mjbt2z2.js";
28
+ import"./chunk-6vbp1vva.js";
26
29
  import {
27
30
  DEFAULT_DATA_DIR
28
31
  } from "./chunk-ngf1zatm.js";
29
32
  import {
30
33
  commandHint
31
- } from "./chunk-7wj0jh3t.js";
34
+ } from "./chunk-1rdbnvy6.js";
32
35
  import"./chunk-df32avw6.js";
33
36
 
34
37
  // apps/host/src/cli/up.ts
35
- import { resolve } from "node:path";
38
+ import { existsSync } from "node:fs";
39
+ import { isAbsolute, resolve } from "node:path";
36
40
  import { createInterface } from "node:readline/promises";
37
41
  import { parseArgs } from "node:util";
38
42
  var OFFICIAL_SERVER_ORIGIN = "https://app.pinomad.si";
@@ -85,7 +89,14 @@ async function upHost(args, deps) {
85
89
  const lan = (hostArgs) => withLan(hostArgs, lanPort);
86
90
  const notes = [];
87
91
  if (reach.server && config === undefined) {
88
- const joined = await joinServer({ origin, dataDir, code: args.code, editHostArgs: lan }, { ...deps, manager });
92
+ const joined = await joinServer({
93
+ origin,
94
+ dataDir,
95
+ code: args.code,
96
+ ...args.token === undefined ? {} : { token: args.token },
97
+ ...args.launcher === undefined ? {} : { launcher: args.launcher },
98
+ editHostArgs: lan
99
+ }, { ...deps, manager });
89
100
  return {
90
101
  joined: { origin: joined.origin, username: joined.username, fresh: true },
91
102
  ...lanPort === undefined ? {} : { lanPort },
@@ -94,7 +105,7 @@ async function upHost(args, deps) {
94
105
  };
95
106
  }
96
107
  const edit = reach.server ? (hostArgs) => lan(withoutRelayArgs(hostArgs)) : lan;
97
- const service = await writeService(slot, edit, { changed: reach.server });
108
+ const service = await writeService(slot, edit, { changed: reach.server, launcher: args.launcher });
98
109
  if (!reach.server && config !== undefined) {
99
110
  notes.push(`still joined to ${config.origin} — run \`${commandHint("leave")}\` to leave it`);
100
111
  }
@@ -105,6 +116,12 @@ async function upHost(args, deps) {
105
116
  notes
106
117
  };
107
118
  }
119
+ async function readAllStdin() {
120
+ let text = "";
121
+ for await (const chunk of process.stdin)
122
+ text += String(chunk);
123
+ return text;
124
+ }
108
125
  async function askOnTerminal(question) {
109
126
  const terminal = createInterface({ input: process.stdin, output: process.stdout });
110
127
  try {
@@ -139,7 +156,8 @@ var FLAGS = `choose with flags:
139
156
  --server [--origin URL] through a PiNomad server (default ${OFFICIAL_SERVER_ORIGIN})
140
157
  --lan [--remote-port N] only on the local network and tailnet (default port ${DEFAULT_REMOTE_PORT})
141
158
  --server --lan both
142
- --yes keep what this host has, or the server on a new host`;
159
+ --yes keep what this host has, or the server on a new host
160
+ --token-stdin join with a one-time token read from stdin, without a code`;
143
161
  async function main(argv, deps) {
144
162
  const { values } = parseArgs({
145
163
  args: [...argv],
@@ -150,6 +168,8 @@ async function main(argv, deps) {
150
168
  yes: { type: "boolean", short: "y" },
151
169
  origin: { type: "string" },
152
170
  code: { type: "boolean" },
171
+ "token-stdin": { type: "boolean" },
172
+ launcher: { type: "string" },
153
173
  "remote-port": { type: "string" },
154
174
  "data-dir": { type: "string" }
155
175
  }
@@ -157,6 +177,20 @@ async function main(argv, deps) {
157
177
  const log = deps?.log ?? ((line) => console.log(line));
158
178
  try {
159
179
  const dataDir = resolve(values["data-dir"] ?? DEFAULT_DATA_DIR);
180
+ const launcher = values.launcher;
181
+ if (launcher !== undefined && process.platform !== "darwin")
182
+ throw new Error("--launcher is for the Mac App's service only");
183
+ if (launcher !== undefined && !(isAbsolute(launcher) && isLauncher(launcher))) {
184
+ throw new Error(`--launcher ${launcher}: not a path to the launcher inside an app (….app/Contents/MacOS/${LAUNCHER_EXECUTABLE})`);
185
+ }
186
+ if (launcher !== undefined && !existsSync(launcher))
187
+ throw new Error(`--launcher ${launcher}: no such file`);
188
+ let token;
189
+ if (values["token-stdin"] === true) {
190
+ token = (await (deps?.readStdin ?? readAllStdin)()).trim();
191
+ if (token === "")
192
+ throw new Error("--token-stdin: no join token on stdin");
193
+ }
160
194
  const origin = normalizeOrigin(values.origin ?? (await readServerConfig(dataDir))?.origin ?? await lastRemovedOrigin(dataDir) ?? OFFICIAL_SERVER_ORIGIN);
161
195
  const current = await currentReach(dataDir, deps);
162
196
  let reach = resolveReach({ server: values.server, lan: values.lan }, current);
@@ -182,7 +216,9 @@ async function main(argv, deps) {
182
216
  origin,
183
217
  reach,
184
218
  ...values["remote-port"] === undefined ? {} : { remotePort: values["remote-port"] },
185
- ...values.code === true ? { code: true } : {}
219
+ ...values.code === true ? { code: true } : {},
220
+ ...token === undefined ? {} : { token },
221
+ ...launcher === undefined ? {} : { launcher }
186
222
  }, deps);
187
223
  if (outcome.joined !== undefined) {
188
224
  const who = outcome.joined.username ?? "an account";
package/dist/pinomad.js CHANGED
@@ -5,24 +5,24 @@ import {
5
5
  } from "./chunk-kzbzacz9.js";
6
6
  import {
7
7
  packagedVersion
8
- } from "./chunk-7wj0jh3t.js";
8
+ } from "./chunk-1rdbnvy6.js";
9
9
  import {
10
10
  __require
11
11
  } from "./chunk-df32avw6.js";
12
12
 
13
13
  // apps/cli/src/pinomad.ts
14
14
  var COMMANDS = {
15
- up: () => import("./chunk-5qf1grkk.js"),
16
- status: () => import("./chunk-41q0saz0.js"),
17
- host: () => import("./chunk-ksfxqd8s.js"),
18
- server: () => import("./chunk-mnmqyq7d.js"),
19
- relay: () => import("./chunk-mnmqyq7d.js"),
20
- service: () => import("./chunk-vx7dy07y.js"),
21
- upgrade: () => import("./chunk-jeqsdcj1.js"),
22
- link: () => import("./chunk-aqj9wfmb.js"),
23
- pair: () => import("./chunk-vqkb70d7.js"),
24
- join: () => import("./chunk-42nqtx5r.js"),
25
- leave: () => import("./chunk-agq4tn9r.js")
15
+ up: () => import("./chunk-w927q9m1.js"),
16
+ status: () => import("./chunk-e53c0s8z.js"),
17
+ host: () => import("./chunk-35szq73k.js"),
18
+ server: () => import("./chunk-5j7ybhjj.js"),
19
+ relay: () => import("./chunk-5j7ybhjj.js"),
20
+ service: () => import("./chunk-ex5yr09h.js"),
21
+ upgrade: () => import("./chunk-eewxy4cp.js"),
22
+ link: () => import("./chunk-mtkvft88.js"),
23
+ pair: () => import("./chunk-evbv1fkn.js"),
24
+ join: () => import("./chunk-dsr19q5h.js"),
25
+ leave: () => import("./chunk-5pv0g1nj.js")
26
26
  };
27
27
  var USAGE = `pinomad — PiNomad host, server, and utilities
28
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinomad",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "description": "PiNomad — self-hosted coding agent: host, relay, and web client in one package",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -20,25 +20,30 @@
20
20
  },
21
21
  "homepage": "https://github.com/bubbleptr/pinomad",
22
22
  "dependencies": {
23
- "@earendil-works/chord": "1.4.0",
24
- "@earendil-works/pi-ai": "1.4.0",
25
- "@earendil-works/pi-codemode": "1.4.0",
26
- "@earendil-works/pi-coding-agent": "1.4.0",
27
- "@earendil-works/pi-durable": "1.4.0",
28
- "@earendil-works/pi-mcp": "1.4.0",
23
+ "@earendil-works/chord": "1.5.0",
24
+ "@earendil-works/pi-ai": "1.5.0",
25
+ "@earendil-works/pi-codemode": "1.5.0",
26
+ "@earendil-works/pi-coding-agent": "1.5.0",
27
+ "@earendil-works/pi-durable": "1.5.0",
28
+ "@earendil-works/pi-mcp": "1.5.0",
29
29
  "@lydell/node-pty": "1.2.0-beta.18",
30
30
  "@noble/curves": "2.4.0",
31
31
  "diff": "8.0.4",
32
32
  "node-datachannel": "0.33.4",
33
33
  "proper-lockfile": "4.1.2",
34
34
  "typebox": "1.3.27",
35
- "undici": "8.10.2",
35
+ "undici": "8.12.3",
36
36
  "uqr": "0.1.3",
37
37
  "ws": "8.22.0",
38
+ "nodemailer": "10.3.1",
38
39
  "@noble/ciphers": "2.4.0",
39
40
  "@noble/hashes": "2.4.0",
40
- "@earendil-works/pi-agent-core": "1.4.0",
41
- "@earendil-works/pi-telemetry": "1.4.0",
42
- "@earendil-works/pi-tui": "1.4.0"
41
+ "@earendil-works/pi-agent-core": "1.5.0",
42
+ "@earendil-works/pi-schema": "1.5.0",
43
+ "@earendil-works/pi-telemetry": "1.5.0",
44
+ "@earendil-works/pi-tui": "1.5.0"
45
+ },
46
+ "pinomad": {
47
+ "protocolMajor": 5
43
48
  }
44
49
  }