pinomad 0.10.0 → 0.11.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.
@@ -3,7 +3,7 @@ import {
3
3
  generateKeyPair,
4
4
  keyPairFromPrivate,
5
5
  toBase64Url
6
- } from "./chunk-sygeb9qb.js";
6
+ } from "./chunk-pqe7q1s7.js";
7
7
 
8
8
  // apps/host/src/devices.ts
9
9
  import { link, readFile, unlink, writeFile } from "node:fs/promises";
@@ -140,53 +140,4 @@ function pairingOffers(ttlMs = 5 * 60 * 1000) {
140
140
  };
141
141
  }
142
142
 
143
- // apps/host/src/server-config.ts
144
- import { randomBytes as randomBytes2 } from "node:crypto";
145
- import { readFile as readFile2, rename, rm, writeFile as writeFile2 } from "node:fs/promises";
146
- import { join as join2 } from "node:path";
147
- var SERVER_CONFIG_FILE = "server.json";
148
- var normalizeOrigin = (origin) => origin.replace(/\/+$/, "");
149
- async function readServerConfig(dataDir) {
150
- let text;
151
- try {
152
- text = await readFile2(join2(dataDir, SERVER_CONFIG_FILE), "utf8");
153
- } catch (error) {
154
- if (error.code === "ENOENT")
155
- return;
156
- throw error;
157
- }
158
- let value;
159
- try {
160
- value = JSON.parse(text);
161
- } catch {
162
- throw new Error(`${join2(dataDir, SERVER_CONFIG_FILE)} is not valid JSON — delete it or run \`pinomad leave\``);
163
- }
164
- const origin = value?.origin;
165
- if (typeof origin !== "string" || origin.trim() === "") {
166
- throw new Error(`${join2(dataDir, SERVER_CONFIG_FILE)} is missing a string "origin"`);
167
- }
168
- const binding = value.binding;
169
- return {
170
- origin,
171
- ...typeof binding === "string" && binding !== "" ? { binding } : {}
172
- };
173
- }
174
- async function writeServerConfig(dataDir, config) {
175
- const path = join2(dataDir, SERVER_CONFIG_FILE);
176
- const tmp = `${path}.tmp-${process.pid}`;
177
- await writeFile2(tmp, `${JSON.stringify({ origin: normalizeOrigin(config.origin), binding: randomBytes2(16).toString("base64url") })}
178
- `, { mode: 384 });
179
- await rename(tmp, path);
180
- }
181
- var removeServerConfig = (dataDir) => rm(join2(dataDir, SERVER_CONFIG_FILE), { force: true });
182
- async function readServerBinding(dataDir) {
183
- return (await readServerConfig(dataDir))?.binding;
184
- }
185
- function resolveRelayOrigin(flag, config) {
186
- if (flag !== undefined && config !== undefined && normalizeOrigin(flag) !== normalizeOrigin(config.origin)) {
187
- throw new Error(`--relay ${flag} disagrees with ${SERVER_CONFIG_FILE} (${config.origin}) — remove one`);
188
- }
189
- return flag ?? config?.origin;
190
- }
191
-
192
- export { DevicesDoc, ensureDevices, RevocationsDoc, admitDevice, loadHostKey, loadRelayKey, pairingOffers, normalizeOrigin, readServerConfig, writeServerConfig, removeServerConfig, readServerBinding, resolveRelayOrigin };
143
+ export { DevicesDoc, ensureDevices, RevocationsDoc, admitDevice, loadHostKey, loadRelayKey, pairingOffers };
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  connectRemoteDurable
3
- } from "./chunk-4sepcfpy.js";
4
- import"./chunk-jgd38rna.js";
3
+ } from "./chunk-jt34g8st.js";
4
+ import"./chunk-xqycs43g.js";
5
5
  import {
6
6
  isLoopbackUrl
7
- } from "./chunk-sygeb9qb.js";
7
+ } from "./chunk-pqe7q1s7.js";
8
8
  import {
9
9
  hostAddress
10
10
  } from "./chunk-ngf1zatm.js";
@@ -1,19 +1,19 @@
1
- import {
2
- isParseArgsError
3
- } from "./chunk-kzbzacz9.js";
4
- import {
5
- commandHint,
6
- hostEntry,
7
- packagedVersion
8
- } from "./chunk-zehwx009.js";
9
1
  import {
10
2
  ProtocolMismatchError,
11
3
  connectRemoteDurable
12
- } from "./chunk-4sepcfpy.js";
4
+ } from "./chunk-jt34g8st.js";
5
+ import {
6
+ isParseArgsError
7
+ } from "./chunk-kzbzacz9.js";
13
8
  import {
14
9
  DEFAULT_DATA_DIR,
15
10
  hostAddress
16
11
  } from "./chunk-ngf1zatm.js";
12
+ import {
13
+ commandHint,
14
+ hostEntry,
15
+ packagedVersion
16
+ } from "./chunk-sd5fkxjj.js";
17
17
 
18
18
  // apps/host/src/cli/service.ts
19
19
  import { execFile as execFile2 } from "node:child_process";
@@ -81,20 +81,21 @@ function argValue(args, flag) {
81
81
  }
82
82
  return value;
83
83
  }
84
- function withoutRelayArgs(args) {
84
+ function withoutArg(args, flag) {
85
85
  const out = [];
86
86
  for (let i = 0;i < args.length; i += 1) {
87
87
  const arg = args[i];
88
- if (arg === "--relay") {
88
+ if (arg === flag) {
89
89
  i += 1;
90
90
  continue;
91
91
  }
92
- if (arg.startsWith("--relay="))
92
+ if (arg.startsWith(`${flag}=`))
93
93
  continue;
94
94
  out.push(arg);
95
95
  }
96
96
  return out;
97
97
  }
98
+ var withoutRelayArgs = (args) => withoutArg(args, "--relay");
98
99
  var unescapeExec = (value) => value.replace(/\\(.)/g, "$1");
99
100
  var unspecify = (value) => value.replace(/%%/g, "%").replace(/\$\$/g, "$");
100
101
  var xmlUnescape = (value) => value.replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
@@ -409,15 +410,13 @@ async function install(argv) {
409
410
  console.log(`data dir: ${spec.dataDir}`);
410
411
  console.log(`browser link: ${commandHint("link")} pairing QR: ${commandHint("pair")}`);
411
412
  }
412
- async function status(argv) {
413
- const state = await serviceManager().state();
414
- console.log(`service: ${state.installed ? state.detail : "not installed"}`);
415
- if (packagedVersion === undefined) {
416
- const head = await run2("git", ["rev-parse", "--short", "HEAD"], { cwd: repoRoot }).then(({ stdout }) => stdout.trim(), () => "unknown");
417
- console.log(`checkout: ${head}`);
418
- } else {
419
- console.log(`version: ${packagedVersion}`);
420
- }
413
+ async function versionLine() {
414
+ if (packagedVersion !== undefined)
415
+ return `version: ${packagedVersion}`;
416
+ const head = await run2("git", ["rev-parse", "--short", "HEAD"], { cwd: repoRoot }).then(({ stdout }) => stdout.trim(), () => "unknown");
417
+ return `checkout: ${head}`;
418
+ }
419
+ async function reachabilityLine(argv) {
421
420
  try {
422
421
  const { url, token } = await hostAddress(argv);
423
422
  const remote = await connectToHost(url, token);
@@ -425,14 +424,20 @@ async function status(argv) {
425
424
  await remote.controller.toggleTasks();
426
425
  const tasks = remote.view.current().tasks;
427
426
  const count = tasks === undefined ? 0 : Object.keys(tasks.tasks).length;
428
- console.log(`host: reachable at ${url}, ${count} live task${count === 1 ? "" : "s"}`);
429
427
  remote.close();
428
+ return `host: reachable at ${url}, ${count} live task${count === 1 ? "" : "s"}`;
430
429
  } catch (error) {
431
430
  if (isParseArgsError(error))
432
431
  throw error;
433
- console.log(`host: unreachable (${message(error)})`);
432
+ return `host: unreachable (${message(error)})`;
434
433
  }
435
434
  }
435
+ async function status(argv) {
436
+ const state = await serviceManager().state();
437
+ console.log(`service: ${state.installed ? state.detail : "not installed"}`);
438
+ console.log(await versionLine());
439
+ console.log(await reachabilityLine(argv));
440
+ }
436
441
  async function restartService({
437
442
  force,
438
443
  argv,
@@ -536,4 +541,4 @@ async function main(argv) {
536
541
  }
537
542
  if (false) {}
538
543
 
539
- export { installSpec, argValue, withoutRelayArgs, serviceManager, restartService, main };
544
+ export { installSpec, argValue, withoutArg, withoutRelayArgs, serviceManager, versionLine, reachabilityLine, restartService, main };
@@ -2,7 +2,176 @@ import {
2
2
  HOST_SETTING_KEYS,
3
3
  isQueueMode,
4
4
  isThinkingLevel
5
- } from "./chunk-sygeb9qb.js";
5
+ } from "./chunk-pqe7q1s7.js";
6
+
7
+ // packages/protocol/src/rtc.ts
8
+ function rtcAddressScope(address) {
9
+ const ip = parseRtcAddress(address);
10
+ if (ip === undefined)
11
+ return "unknown";
12
+ if (ip.family === 4)
13
+ return ipv4Scope(ip.octets);
14
+ const octets = mappedIpv4(ip.segments);
15
+ return octets === undefined ? ipv6Scope(ip.segments) : ipv4Scope(octets);
16
+ }
17
+ function rtcCandidateEnd(info) {
18
+ return {
19
+ ...info.type === undefined ? {} : { type: info.type },
20
+ ...info.address === undefined ? {} : { address: info.address },
21
+ scope: rtcAddressScope(info.address)
22
+ };
23
+ }
24
+ function rtcSelectedPair(local, remote) {
25
+ return { local: rtcCandidateEnd(local), remote: rtcCandidateEnd(remote) };
26
+ }
27
+ function parseRtcAddress(address) {
28
+ if (address === undefined)
29
+ return;
30
+ const text = address.trim();
31
+ if (text === "")
32
+ return;
33
+ let host = text;
34
+ if (text.startsWith("[")) {
35
+ const close = text.indexOf("]");
36
+ if (close === -1)
37
+ return;
38
+ const tail = text.slice(close + 1);
39
+ if (tail !== "" && !/^:\d+$/.test(tail))
40
+ return;
41
+ host = text.slice(1, close);
42
+ } else if (text.split(":").length === 2) {
43
+ const [candidate, port] = text.split(":");
44
+ if (/^\d+$/.test(port))
45
+ host = candidate;
46
+ }
47
+ const zone = host.indexOf("%");
48
+ if (zone !== -1)
49
+ host = host.slice(0, zone);
50
+ const ipv4 = parseIpv4(host);
51
+ if (ipv4 !== undefined)
52
+ return { family: 4, octets: ipv4 };
53
+ const ipv6 = parseIpv6(host);
54
+ return ipv6 === undefined ? undefined : { family: 6, segments: ipv6 };
55
+ }
56
+ function parseIpv4(text) {
57
+ const parts = text.split(".");
58
+ if (parts.length !== 4)
59
+ return;
60
+ const octets = [];
61
+ for (const part of parts) {
62
+ if (!/^(?:0|[1-9]\d{0,2})$/.test(part))
63
+ return;
64
+ const value = Number(part);
65
+ if (value > 255)
66
+ return;
67
+ octets.push(value);
68
+ }
69
+ return octets;
70
+ }
71
+ function parseIpv6(text) {
72
+ const halves = text.split("::");
73
+ if (halves.length > 2)
74
+ return;
75
+ const parsePart = (part, allowIpv4) => {
76
+ if (part === "")
77
+ return [];
78
+ const tokens = part.split(":");
79
+ const groups = [];
80
+ for (let index = 0;index < tokens.length; index++) {
81
+ const token = tokens[index];
82
+ if (allowIpv4 && index === tokens.length - 1 && token.includes(".")) {
83
+ const v4 = parseIpv4(token);
84
+ if (v4 === undefined)
85
+ return;
86
+ groups.push(v4[0] << 8 | v4[1], v4[2] << 8 | v4[3]);
87
+ continue;
88
+ }
89
+ if (!/^[0-9a-fA-F]{1,4}$/.test(token))
90
+ return;
91
+ groups.push(Number.parseInt(token, 16));
92
+ }
93
+ return groups;
94
+ };
95
+ if (halves.length === 1) {
96
+ const groups = parsePart(text, true);
97
+ return groups?.length === 8 ? groups : undefined;
98
+ }
99
+ const left = parsePart(halves[0], false);
100
+ const right = parsePart(halves[1], true);
101
+ if (left === undefined || right === undefined)
102
+ return;
103
+ const zeros = 8 - left.length - right.length;
104
+ if (zeros < 1)
105
+ return;
106
+ return [...left, ...new Array(zeros).fill(0), ...right];
107
+ }
108
+ function mappedIpv4(segments) {
109
+ if (!segments.slice(0, 5).every((group) => group === 0) || segments[5] !== 65535)
110
+ return;
111
+ return [segments[6] >> 8, segments[6] & 255, segments[7] >> 8, segments[7] & 255];
112
+ }
113
+ function ipv4Scope(octets) {
114
+ const [a, b] = octets;
115
+ if (a === 127)
116
+ return "loopback";
117
+ if (a === 100 && b >= 64 && b <= 127)
118
+ return "tailnet";
119
+ if (a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 169 && b === 254) {
120
+ return "lan";
121
+ }
122
+ return "public";
123
+ }
124
+ function ipv6Scope(segments) {
125
+ if (segments[0] === 64890 && segments[1] === 4444 && segments[2] === 41440)
126
+ return "tailnet";
127
+ if ((segments[0] & 65024) === 64512 || (segments[0] & 65472) === 65152)
128
+ return "lan";
129
+ if (segments.slice(0, 7).every((group) => group === 0) && segments[7] === 1)
130
+ return "loopback";
131
+ return "public";
132
+ }
133
+ var RTC_DEFAULT_STUN = ["stun:stun.cloudflare.com:3478"];
134
+ var RTC_DATA_CHANNEL_LABEL = "pinomad";
135
+ var RTC_MAX_RECORD_BYTES = 65535;
136
+ var RTC_DEFAULT_MAX_MESSAGE_SIZE = 65536;
137
+ var RTC_MIN_MAX_MESSAGE_SIZE = RTC_MAX_RECORD_BYTES;
138
+ function isRtcHello(value) {
139
+ if (typeof value !== "object" || value === null || Array.isArray(value))
140
+ return false;
141
+ const hello = value;
142
+ return Array.isArray(hello.stun) && hello.stun.every((server) => typeof server === "string" && server.length > 0) && hello.signalOnly === true;
143
+ }
144
+ function rtcCandidateType(candidate) {
145
+ const parts = candidate.trim().split(/\s+/);
146
+ const at = parts.indexOf("typ");
147
+ return at === -1 ? undefined : parts[at + 1];
148
+ }
149
+ function sdpCandidates(sdp) {
150
+ return sdp.split(/\r?\n/).filter((line) => line.startsWith("a=candidate:")).map((line) => line.slice("a=".length));
151
+ }
152
+ function withRtcCandidates(sdp, candidates) {
153
+ const lines = sdp.split(/\r?\n/).filter((line) => line !== "" && !line.startsWith("a=candidate:") && line !== "a=end-of-candidates");
154
+ const unique = [...new Set(candidates.map((candidate) => candidate.replace(/^a=/, "")))];
155
+ return [...lines, ...unique.map((candidate) => `a=${candidate}`), "a=end-of-candidates", ""].join(`\r
156
+ `);
157
+ }
158
+ function parseRtcMaxMessageSize(sdp) {
159
+ const line = sdp.split(/\r?\n/).find((entry) => entry.startsWith("a=max-message-size:"));
160
+ if (line === undefined)
161
+ return { kind: "bounded", bytes: RTC_DEFAULT_MAX_MESSAGE_SIZE };
162
+ const raw = line.slice("a=max-message-size:".length).trim();
163
+ if (!/^\d+$/.test(raw))
164
+ return { kind: "invalid", reason: `malformed a=max-message-size: ${raw}` };
165
+ const bytes = Number(raw);
166
+ if (!Number.isSafeInteger(bytes))
167
+ return { kind: "invalid", reason: `a=max-message-size is not a safe integer: ${raw}` };
168
+ if (bytes === 0)
169
+ return { kind: "unlimited" };
170
+ if (bytes < RTC_MIN_MAX_MESSAGE_SIZE) {
171
+ return { kind: "invalid", reason: `a=max-message-size ${bytes} cannot carry a ${RTC_MIN_MAX_MESSAGE_SIZE}-byte record` };
172
+ }
173
+ return { kind: "bounded", bytes };
174
+ }
6
175
 
7
176
  // packages/protocol/src/auth.ts
8
177
  var CUSTOM_PROVIDER_APIS = ["openai-completions", "openai-responses", "anthropic-messages", "google-generative-ai"];
@@ -218,175 +387,6 @@ function nonempty(value) {
218
387
  return typeof value === "string" && value.length > 0;
219
388
  }
220
389
 
221
- // packages/protocol/src/rtc.ts
222
- function rtcAddressScope(address) {
223
- const ip = parseRtcAddress(address);
224
- if (ip === undefined)
225
- return "unknown";
226
- if (ip.family === 4)
227
- return ipv4Scope(ip.octets);
228
- const octets = mappedIpv4(ip.segments);
229
- return octets === undefined ? ipv6Scope(ip.segments) : ipv4Scope(octets);
230
- }
231
- function rtcCandidateEnd(info) {
232
- return {
233
- ...info.type === undefined ? {} : { type: info.type },
234
- ...info.address === undefined ? {} : { address: info.address },
235
- scope: rtcAddressScope(info.address)
236
- };
237
- }
238
- function rtcSelectedPair(local, remote) {
239
- return { local: rtcCandidateEnd(local), remote: rtcCandidateEnd(remote) };
240
- }
241
- function parseRtcAddress(address) {
242
- if (address === undefined)
243
- return;
244
- const text = address.trim();
245
- if (text === "")
246
- return;
247
- let host = text;
248
- if (text.startsWith("[")) {
249
- const close = text.indexOf("]");
250
- if (close === -1)
251
- return;
252
- const tail = text.slice(close + 1);
253
- if (tail !== "" && !/^:\d+$/.test(tail))
254
- return;
255
- host = text.slice(1, close);
256
- } else if (text.split(":").length === 2) {
257
- const [candidate, port] = text.split(":");
258
- if (/^\d+$/.test(port))
259
- host = candidate;
260
- }
261
- const zone = host.indexOf("%");
262
- if (zone !== -1)
263
- host = host.slice(0, zone);
264
- const ipv4 = parseIpv4(host);
265
- if (ipv4 !== undefined)
266
- return { family: 4, octets: ipv4 };
267
- const ipv6 = parseIpv6(host);
268
- return ipv6 === undefined ? undefined : { family: 6, segments: ipv6 };
269
- }
270
- function parseIpv4(text) {
271
- const parts = text.split(".");
272
- if (parts.length !== 4)
273
- return;
274
- const octets = [];
275
- for (const part of parts) {
276
- if (!/^(?:0|[1-9]\d{0,2})$/.test(part))
277
- return;
278
- const value = Number(part);
279
- if (value > 255)
280
- return;
281
- octets.push(value);
282
- }
283
- return octets;
284
- }
285
- function parseIpv6(text) {
286
- const halves = text.split("::");
287
- if (halves.length > 2)
288
- return;
289
- const parsePart = (part, allowIpv4) => {
290
- if (part === "")
291
- return [];
292
- const tokens = part.split(":");
293
- const groups = [];
294
- for (let index = 0;index < tokens.length; index++) {
295
- const token = tokens[index];
296
- if (allowIpv4 && index === tokens.length - 1 && token.includes(".")) {
297
- const v4 = parseIpv4(token);
298
- if (v4 === undefined)
299
- return;
300
- groups.push(v4[0] << 8 | v4[1], v4[2] << 8 | v4[3]);
301
- continue;
302
- }
303
- if (!/^[0-9a-fA-F]{1,4}$/.test(token))
304
- return;
305
- groups.push(Number.parseInt(token, 16));
306
- }
307
- return groups;
308
- };
309
- if (halves.length === 1) {
310
- const groups = parsePart(text, true);
311
- return groups?.length === 8 ? groups : undefined;
312
- }
313
- const left = parsePart(halves[0], false);
314
- const right = parsePart(halves[1], true);
315
- if (left === undefined || right === undefined)
316
- return;
317
- const zeros = 8 - left.length - right.length;
318
- if (zeros < 1)
319
- return;
320
- return [...left, ...new Array(zeros).fill(0), ...right];
321
- }
322
- function mappedIpv4(segments) {
323
- if (!segments.slice(0, 5).every((group) => group === 0) || segments[5] !== 65535)
324
- return;
325
- return [segments[6] >> 8, segments[6] & 255, segments[7] >> 8, segments[7] & 255];
326
- }
327
- function ipv4Scope(octets) {
328
- const [a, b] = octets;
329
- if (a === 127)
330
- return "loopback";
331
- if (a === 100 && b >= 64 && b <= 127)
332
- return "tailnet";
333
- if (a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 169 && b === 254) {
334
- return "lan";
335
- }
336
- return "public";
337
- }
338
- function ipv6Scope(segments) {
339
- if (segments[0] === 64890 && segments[1] === 4444 && segments[2] === 41440)
340
- return "tailnet";
341
- if ((segments[0] & 65024) === 64512 || (segments[0] & 65472) === 65152)
342
- return "lan";
343
- if (segments.slice(0, 7).every((group) => group === 0) && segments[7] === 1)
344
- return "loopback";
345
- return "public";
346
- }
347
- var RTC_DEFAULT_STUN = ["stun:stun.cloudflare.com:3478"];
348
- var RTC_DATA_CHANNEL_LABEL = "pinomad";
349
- var RTC_MAX_RECORD_BYTES = 65535;
350
- var RTC_DEFAULT_MAX_MESSAGE_SIZE = 65536;
351
- var RTC_MIN_MAX_MESSAGE_SIZE = RTC_MAX_RECORD_BYTES;
352
- function isRtcHello(value) {
353
- if (typeof value !== "object" || value === null || Array.isArray(value))
354
- return false;
355
- const hello = value;
356
- return Array.isArray(hello.stun) && hello.stun.every((server) => typeof server === "string" && server.length > 0) && hello.signalOnly === true;
357
- }
358
- function rtcCandidateType(candidate) {
359
- const parts = candidate.trim().split(/\s+/);
360
- const at = parts.indexOf("typ");
361
- return at === -1 ? undefined : parts[at + 1];
362
- }
363
- function sdpCandidates(sdp) {
364
- return sdp.split(/\r?\n/).filter((line) => line.startsWith("a=candidate:")).map((line) => line.slice("a=".length));
365
- }
366
- function withRtcCandidates(sdp, candidates) {
367
- const lines = sdp.split(/\r?\n/).filter((line) => line !== "" && !line.startsWith("a=candidate:") && line !== "a=end-of-candidates");
368
- const unique = [...new Set(candidates.map((candidate) => candidate.replace(/^a=/, "")))];
369
- return [...lines, ...unique.map((candidate) => `a=${candidate}`), "a=end-of-candidates", ""].join(`\r
370
- `);
371
- }
372
- function parseRtcMaxMessageSize(sdp) {
373
- const line = sdp.split(/\r?\n/).find((entry) => entry.startsWith("a=max-message-size:"));
374
- if (line === undefined)
375
- return { kind: "bounded", bytes: RTC_DEFAULT_MAX_MESSAGE_SIZE };
376
- const raw = line.slice("a=max-message-size:".length).trim();
377
- if (!/^\d+$/.test(raw))
378
- return { kind: "invalid", reason: `malformed a=max-message-size: ${raw}` };
379
- const bytes = Number(raw);
380
- if (!Number.isSafeInteger(bytes))
381
- return { kind: "invalid", reason: `a=max-message-size is not a safe integer: ${raw}` };
382
- if (bytes === 0)
383
- return { kind: "unlimited" };
384
- if (bytes < RTC_MIN_MAX_MESSAGE_SIZE) {
385
- return { kind: "invalid", reason: `a=max-message-size ${bytes} cannot carry a ${RTC_MIN_MAX_MESSAGE_SIZE}-byte record` };
386
- }
387
- return { kind: "bounded", bytes };
388
- }
389
-
390
390
  // packages/protocol/src/attachments.ts
391
391
  var MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;
392
392
  var MAX_ATTACHMENTS_PER_MESSAGE = 10;
@@ -619,4 +619,4 @@ function homeOf(index, summaries, id) {
619
619
  return;
620
620
  }
621
621
 
622
- export { isCustomProviderApi, HOST_STREAM_NAMES, hostStreams, conversationStream, docStream, UNAUTHORIZED_CLOSE_CODE, INVALID_FRAME_CLOSE_CODE, PROTOCOL, hostSupportsCall, hostSupportsFeature, parseClientFrame, rtcSelectedPair, RTC_DEFAULT_STUN, RTC_DATA_CHANNEL_LABEL, RTC_MAX_RECORD_BYTES, isRtcHello, rtcCandidateType, sdpCandidates, withRtcCandidates, parseRtcMaxMessageSize, MAX_ATTACHMENTS_PER_MESSAGE, MAX_PENDING_ATTACHMENTS, MAX_PENDING_ATTACHMENT_BYTES, ATTACHMENT_TTL_MS, MAX_ATTACHMENT_NAME_LENGTH, isAttachmentId, base64DecodedLength, attachmentBeginProblem, attachmentChunkProblem, attachmentBlock, parseAttachmentBlock, organize, checkoutOf, homeOf };
622
+ export { rtcSelectedPair, RTC_DEFAULT_STUN, RTC_DATA_CHANNEL_LABEL, RTC_MAX_RECORD_BYTES, isRtcHello, rtcCandidateType, sdpCandidates, withRtcCandidates, parseRtcMaxMessageSize, isCustomProviderApi, HOST_STREAM_NAMES, hostStreams, conversationStream, docStream, UNAUTHORIZED_CLOSE_CODE, INVALID_FRAME_CLOSE_CODE, PROTOCOL, hostSupportsCall, hostSupportsFeature, parseClientFrame, MAX_ATTACHMENTS_PER_MESSAGE, MAX_PENDING_ATTACHMENTS, MAX_PENDING_ATTACHMENT_BYTES, ATTACHMENT_TTL_MS, MAX_ATTACHMENT_NAME_LENGTH, isAttachmentId, base64DecodedLength, attachmentBeginProblem, attachmentChunkProblem, attachmentBlock, parseAttachmentBlock, organize, checkoutOf, homeOf };
@@ -3,7 +3,7 @@ import {
3
3
  fromBase64Url,
4
4
  parseEndpointSet,
5
5
  toBase64Url
6
- } from "./chunk-sygeb9qb.js";
6
+ } from "./chunk-pqe7q1s7.js";
7
7
 
8
8
  // packages/protocol/src/relay.ts
9
9
  import { ed25519 } from "@noble/curves/ed25519.js";
package/dist/pinomad.js CHANGED
@@ -5,27 +5,33 @@ import {
5
5
  } from "./chunk-kzbzacz9.js";
6
6
  import {
7
7
  packagedVersion
8
- } from "./chunk-zehwx009.js";
8
+ } from "./chunk-sd5fkxjj.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
- host: () => import("./chunk-czj9nfrz.js"),
16
- server: () => import("./chunk-p978qj9m.js"),
17
- relay: () => import("./chunk-p978qj9m.js"),
18
- service: () => import("./chunk-bhtx2c8a.js"),
19
- upgrade: () => import("./chunk-73efzaf1.js"),
20
- link: () => import("./chunk-c5p9xkd8.js"),
21
- pair: () => import("./chunk-vax4zspw.js"),
22
- join: () => import("./chunk-c05g401k.js"),
23
- leave: () => import("./chunk-5791mb0b.js")
15
+ up: () => import("./chunk-n1m1tjrk.js"),
16
+ status: () => import("./chunk-b457q0tm.js"),
17
+ host: () => import("./chunk-67gq282t.js"),
18
+ server: () => import("./chunk-9h5vawnm.js"),
19
+ relay: () => import("./chunk-9h5vawnm.js"),
20
+ service: () => import("./chunk-h5q2y57m.js"),
21
+ upgrade: () => import("./chunk-6d16c2fv.js"),
22
+ link: () => import("./chunk-as6pyf00.js"),
23
+ pair: () => import("./chunk-tj57aqav.js"),
24
+ join: () => import("./chunk-greb3dp6.js"),
25
+ leave: () => import("./chunk-4dcs8sbj.js")
24
26
  };
25
27
  var USAGE = `pinomad — PiNomad host, server, and utilities
26
28
 
27
29
  usage: pinomad <command> [args…]
28
30
 
31
+ up [--server] [--lan] [--yes] set this host up: account, LAN, service
32
+ up --origin URL --remote-port N server to join (app.pinomad.si), LAN port (7422)
33
+ up --no-server|--no-lan [--data-dir D] turn a path off; with no flags, up asks
34
+ status [--data-dir D] joined server and account, LAN, service, host
29
35
  host [--data-dir DIR] [--port 7420] [--project DIR]… run the host in the foreground
30
36
  host --remote-port PORT [--public-url URL] remote access, LAN (ADR-0008)
31
37
  host --relay URL remote access via relay (ADR-0015)
@@ -37,7 +43,7 @@ usage: pinomad <command> [args…]
37
43
  upgrade [--force] [address flags] upgrade the package and restart the service
38
44
  link [--data-dir D|--url U …] print the browser link
39
45
  pair [--data-dir D|--url U …] print a pairing QR
40
- join <origin> <token> [--data-dir D] join this host to a server account
46
+ join <origin> [token] [--data-dir D] join this host to a server account
41
47
  leave [--data-dir D] leave the server account
42
48
  --version, -v print the version
43
49
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinomad",
3
- "version": "0.10.0",
3
+ "version": "0.11.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",