toyon 0.9.0 → 0.10.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 (26) hide show
  1. package/dist/cli.js +64 -14
  2. package/dist/daemon.js +781 -190
  3. package/dist/shell/assets/{Editor-DAJni9OF.js → Editor-DL0q1Bu5.js} +161 -161
  4. package/dist/shell/assets/{XTerm-dug6M6yd.js → XTerm-C9YH4Lh2.js} +1 -1
  5. package/dist/shell/assets/{cssMode-B5iiwdXn.js → cssMode-Et22hXpa.js} +1 -1
  6. package/dist/shell/assets/{freemarker2-CdVcBNE9.js → freemarker2-Clz20PcM.js} +1 -1
  7. package/dist/shell/assets/{grammar-Cfxx1yRn.js → grammar-CPvdB3az.js} +1 -1
  8. package/dist/shell/assets/{handlebars-CW5EFZC2.js → handlebars-B4nvXAx8.js} +1 -1
  9. package/dist/shell/assets/{html-B8gP1xu-.js → html-DPIGgBLK.js} +1 -1
  10. package/dist/shell/assets/{htmlMode-C6I99y8u.js → htmlMode-C2LaVuEX.js} +1 -1
  11. package/dist/shell/assets/index-2QusTgw-.js +262 -0
  12. package/dist/shell/assets/index-TaJLoLSd.css +1 -0
  13. package/dist/shell/assets/{javascript-C_3_LFln.js → javascript-CnwJfTbN.js} +1 -1
  14. package/dist/shell/assets/{jsonMode-CD5xJEUk.js → jsonMode-8znCTiqR.js} +1 -1
  15. package/dist/shell/assets/{liquid-CJw93Zxn.js → liquid-Bdm-1CUh.js} +1 -1
  16. package/dist/shell/assets/{lspLanguageFeatures-wMR368iN.js → lspLanguageFeatures-B1DMU7yH.js} +1 -1
  17. package/dist/shell/assets/{mdx-BJ6yMgc3.js → mdx-Ktcqo9Jf.js} +1 -1
  18. package/dist/shell/assets/{python-BWGkxFUr.js → python-QX--d8LR.js} +1 -1
  19. package/dist/shell/assets/{razor-BV9pdU1A.js → razor-C0LrXteG.js} +1 -1
  20. package/dist/shell/assets/{tsMode-CN8OfYAX.js → tsMode-BtYCp6db.js} +1 -1
  21. package/dist/shell/assets/{xml-DBGLqvw7.js → xml-BXbaQ9MG.js} +1 -1
  22. package/dist/shell/assets/{yaml-dH0C6Dth.js → yaml-C6FhaU_C.js} +1 -1
  23. package/dist/shell/index.html +7 -2
  24. package/package.json +1 -1
  25. package/dist/shell/assets/index-BRSL9cyD.css +0 -1
  26. package/dist/shell/assets/index-D_PsyNmp.js +0 -266
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  // src/cli.ts
5
5
  import { existsSync as existsSync10, statSync as statSync4 } from "fs";
6
- import { join as join8, resolve } from "path";
6
+ import { join as join7, resolve } from "path";
7
7
 
8
8
  // ../shared/src/daemon.ts
9
9
  var DAEMON_FILES = {
@@ -5083,6 +5083,28 @@ function describeManaged(p) {
5083
5083
  return out;
5084
5084
  }
5085
5085
 
5086
+ // ../shared/src/pair.ts
5087
+ var isTailnetName = (host) => host.endsWith(".ts.net");
5088
+ var listed = (names) => names.length < 2 ? names[0] ?? "" : `${names.slice(0, -1).join(", ")} and ${names.at(-1)}`;
5089
+ function tailnetLine(phones) {
5090
+ if (phones === null)
5091
+ return { ok: true, text: "Your phone needs Tailscale on, signed in to the same tailnet." };
5092
+ if (phones.length === 0) {
5093
+ return {
5094
+ ok: false,
5095
+ text: "No phone has joined your tailnet. Install Tailscale on it and sign in to the same account first."
5096
+ };
5097
+ }
5098
+ const on = phones.filter((p) => p.online).map((p) => p.name);
5099
+ if (on.length > 0)
5100
+ return { ok: true, text: `${listed(on)} ${on.length > 1 ? "are" : "is"} on your tailnet.` };
5101
+ const off = phones.map((p) => p.name);
5102
+ return {
5103
+ ok: false,
5104
+ text: `${listed(off)} ${off.length > 1 ? "are" : "is"} not answering on your tailnet. Check Tailscale is on there.`
5105
+ };
5106
+ }
5107
+
5086
5108
  // ../shared/src/ports.ts
5087
5109
  var DAEMON_DEFAULT_PORT = 4141;
5088
5110
 
@@ -5130,6 +5152,16 @@ function installCommand(method, version) {
5130
5152
  return ["bun", "add", "-g", `toyon@${version}`];
5131
5153
  return null;
5132
5154
  }
5155
+ function restartCommand(method, version, onPath = "none", registry = null) {
5156
+ if (method !== "npx")
5157
+ return "toyon restart";
5158
+ const install = installCommand(onPath, version);
5159
+ if (!install)
5160
+ return `npx toyon@${version} restart`;
5161
+ if (registry)
5162
+ install.push(`--registry=${registry}`);
5163
+ return `${install.join(" ")} && toyon restart`;
5164
+ }
5133
5165
  function newer(a, b) {
5134
5166
  const pa = parseVersion(a);
5135
5167
  const pb = parseVersion(b);
@@ -5158,7 +5190,7 @@ function parseVersion(v) {
5158
5190
  // package.json
5159
5191
  var package_default = {
5160
5192
  name: "toyon",
5161
- version: "0.9.0",
5193
+ version: "0.10.0",
5162
5194
  description: "Toyon is where coding agents work on your web app while you check each change by using it. Every chat gets its own running copy with a live preview.",
5163
5195
  license: "MIT",
5164
5196
  type: "module",
@@ -5219,11 +5251,26 @@ import { homedir } from "os";
5219
5251
  import { join as join2 } from "path";
5220
5252
 
5221
5253
  // src/layout.ts
5222
- import { existsSync } from "fs";
5223
- import { dirname, join } from "path";
5254
+ import { existsSync, realpathSync } from "fs";
5255
+ import { delimiter, dirname, join } from "path";
5224
5256
  import { fileURLToPath } from "url";
5225
5257
  var here = dirname(fileURLToPath(import.meta.url));
5226
5258
  var packaged = existsSync(join(here, "daemon.js"));
5259
+ var method = installMethod(packaged ? join(here, "..", "package.json") : null);
5260
+ function installOnPath() {
5261
+ for (const dir of (process.env.PATH ?? "").split(delimiter)) {
5262
+ if (dir === "" || dir.includes("/_npx/"))
5263
+ continue;
5264
+ const bin = join(dir, "toyon");
5265
+ if (!existsSync(bin))
5266
+ continue;
5267
+ try {
5268
+ return installMethod(realpathSync(bin));
5269
+ } catch {}
5270
+ }
5271
+ return "none";
5272
+ }
5273
+ var restartCmd = restartCommand(method, package_default.version, method === "npx" ? installOnPath() : "none", process.env.npm_config_registry ?? null);
5227
5274
  var daemonEntry = packaged ? join(here, "daemon.js") : join(here, "../../daemon/src/index.ts");
5228
5275
  var iconSvg = packaged ? join(here, "shell", "icon.svg") : join(here, "../../shell/public/icon.svg");
5229
5276
 
@@ -6177,7 +6224,7 @@ function policyLines(m, daemon) {
6177
6224
  else
6178
6225
  lines.push(line(true, "policy", `${m.source}: ${describeManaged(m.policy).join(", ") || "nothing turned off"}`));
6179
6226
  if (daemon && (daemon.source !== m.source || daemon.hash !== m.hash)) {
6180
- lines.push(line(false, "daemon", "read an older policy; `toyon restart` applies this one"));
6227
+ lines.push(line(false, "daemon", `read an older policy; \`${restartCmd}\` applies this one`));
6181
6228
  }
6182
6229
  return lines;
6183
6230
  }
@@ -6191,7 +6238,7 @@ function agentLines(agents) {
6191
6238
  continue;
6192
6239
  const state = a.installed === null ? `${a.id} ${a.pinned} is not installed` : `${a.id} runs ${a.installed}, not the pinned ${a.pinned}`;
6193
6240
  if (a.error)
6194
- lines.push(line(false, "agents", `${state}: ${a.error}. \`toyon restart\` tries again`));
6241
+ lines.push(line(false, "agents", `${state}: ${a.error}. \`${restartCmd}\` tries again`));
6195
6242
  else
6196
6243
  lines.push(line(true, "agents", `${state}; it may still be installing`));
6197
6244
  }
@@ -6228,7 +6275,7 @@ async function doctor() {
6228
6275
  if (h.agents)
6229
6276
  lines.push(...agentLines(h.agents));
6230
6277
  if (version !== package_default.version) {
6231
- lines.push(line(false, "version", `cli is ${package_default.version} and the daemon is ${version}; \`toyon restart\` brings them level`));
6278
+ lines.push(line(false, "version", `cli is ${package_default.version} and the daemon is ${version}; \`${restartCmd}\` brings them level`));
6232
6279
  }
6233
6280
  if (h.updates?.managedBy === "policy") {
6234
6281
  lines.push(line(true, "updates", "off by your organization's policy"));
@@ -7951,6 +7998,11 @@ ${qrText(qrModules(mint.url))}
7951
7998
  `);
7952
7999
  console.log("Scan with your phone's camera. The code works once and lasts 2 minutes.");
7953
8000
  console.log(mint.url);
8001
+ if (isTailnetName(new URL(mint.url).hostname)) {
8002
+ const r = await fetch(`${base}/pair/phones`, { headers: { authorization: `Bearer ${token}` } }).catch(() => null);
8003
+ const phones = r?.ok ? await r.json() : null;
8004
+ console.log(tailnetLine(phones).text);
8005
+ }
7954
8006
  return null;
7955
8007
  }
7956
8008
  async function pair() {
@@ -8149,7 +8201,7 @@ async function remote(cmd) {
8149
8201
  } catch (e) {
8150
8202
  if (!(e instanceof TailscaleError))
8151
8203
  throw e;
8152
- if (was?.host.endsWith(".ts.net"))
8204
+ if (was && isTailnetName(was.host))
8153
8205
  console.error(`toyon: could not remove tailscale serve entries: ${e.message}`);
8154
8206
  }
8155
8207
  } else if (cmd.to !== null) {
@@ -8310,7 +8362,6 @@ async function uninstall(opts) {
8310
8362
 
8311
8363
  // src/update.ts
8312
8364
  import { spawnSync as spawnSync2 } from "child_process";
8313
- import { join as join7 } from "path";
8314
8365
  var WAIT_MS2 = 15000;
8315
8366
  async function update() {
8316
8367
  const managed = await loadManaged();
@@ -8320,7 +8371,6 @@ async function update() {
8320
8371
  console.error("updates are turned off for this machine (TOYON_UPDATES=off)");
8321
8372
  return 1;
8322
8373
  }
8323
- const method = installMethod(packaged ? join7(here, "..", "package.json") : null);
8324
8374
  if (method === "none") {
8325
8375
  console.error("toyon update works on a global npm or bun install, and this Toyon is not one; update it the way it was installed");
8326
8376
  return 1;
@@ -8374,7 +8424,7 @@ async function restartOnto(version) {
8374
8424
  }
8375
8425
  const token = readToken();
8376
8426
  if (!token) {
8377
- console.error("the daemon token is missing, so the daemon cannot be asked to restart; `toyon restart` does it by hand");
8427
+ console.error(`the daemon token is missing, so the daemon cannot be asked to restart; \`${restartCmd}\` does it by hand`);
8378
8428
  return 1;
8379
8429
  }
8380
8430
  const res = await fetch(`${base}/restart?token=${token}`, { method: "POST" }).catch(() => null);
@@ -8401,7 +8451,7 @@ function behind(daemonVersion) {
8401
8451
  async function open2(cmd) {
8402
8452
  const explicit = cmd.path !== null;
8403
8453
  const target = resolve(cmd.path ?? process.cwd());
8404
- const register = explicit || existsSync10(join8(target, ".git"));
8454
+ const register = explicit || existsSync10(join7(target, ".git"));
8405
8455
  if (process.platform === "linux") {
8406
8456
  const missing = missingSandboxTools();
8407
8457
  const blocked = missing.length === 0 ? bwrapStartError() : null;
@@ -8418,7 +8468,7 @@ async function open2(cmd) {
8418
8468
  return 1;
8419
8469
  }
8420
8470
  } else if (behind(running.version)) {
8421
- console.log(`toyon: the running daemon is ${running.version ?? "older"}; \`toyon restart\` starts ${package_default.version}`);
8471
+ console.log(`toyon: the running daemon is ${running.version ?? "older"}; \`${restartCmd}\` starts ${package_default.version}`);
8422
8472
  }
8423
8473
  const token = readToken();
8424
8474
  if (!token) {
@@ -8487,7 +8537,7 @@ async function run(cmd) {
8487
8537
  else if (!behind(h.version))
8488
8538
  console.log(`toyon ${package_default.version} (daemon ${h.version} running)`);
8489
8539
  else
8490
- console.log(`toyon ${package_default.version} (daemon ${h.version ?? "?"} running; \`toyon restart\` to update)`);
8540
+ console.log(`toyon ${package_default.version} (daemon ${h.version ?? "?"} running; \`${restartCmd}\` to update)`);
8491
8541
  return 0;
8492
8542
  }
8493
8543
  case "stop":