toyon 0.3.0 → 0.4.1

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 (44) hide show
  1. package/README.md +15 -15
  2. package/bin/toyon.js +57 -13
  3. package/dist/bridge.js +1 -1
  4. package/dist/cli.js +1676 -2
  5. package/dist/daemon.js +5759 -4845
  6. package/dist/shell/assets/{Editor-Lle8R8mY.js → Editor-BV5mlMUd.js} +189 -179
  7. package/dist/shell/assets/{XTerm-DcWpV1FL.js → XTerm-vYHVHYnx.js} +1 -1
  8. package/dist/shell/assets/cssMode-DmPPq0RM.js +1 -0
  9. package/dist/shell/assets/{freemarker2-B5OkSZOW.js → freemarker2-D0jw6qr7.js} +2 -2
  10. package/dist/shell/assets/grammar-SjzA6dB3.js +12 -0
  11. package/dist/shell/assets/handlebars-DP51I8rr.js +1 -0
  12. package/dist/shell/assets/html-lErft7TP.js +1 -0
  13. package/dist/shell/assets/htmlMode-B8WYzHvO.js +1 -0
  14. package/dist/shell/assets/index-2d0IGh4f.js +232 -0
  15. package/dist/shell/assets/index-DZ08PVmu.css +1 -0
  16. package/dist/shell/assets/javascript-2o8dwNxB.js +1 -0
  17. package/dist/shell/assets/{jsonMode-Cq43R9DW.js → jsonMode-BzyCh8f1.js} +1 -1
  18. package/dist/shell/assets/liquid-DwwOicEv.js +1 -0
  19. package/dist/shell/assets/{lspLanguageFeatures-BtjVqb14.js → lspLanguageFeatures-BSPiRlDO.js} +1 -1
  20. package/dist/shell/assets/mdx-Dx7gR42C.js +1 -0
  21. package/dist/shell/assets/python-B09pxq08.js +1 -0
  22. package/dist/shell/assets/razor-DO8UQZDP.js +1 -0
  23. package/dist/shell/assets/tsMode-1xhdljsc.js +1 -0
  24. package/dist/shell/assets/wasm-inlined-CG6Dc4jp.js +1 -0
  25. package/dist/shell/assets/xml-Be6HmYJA.js +1 -0
  26. package/dist/shell/assets/yaml-D4xpEWFo.js +1 -0
  27. package/dist/shell/index.html +35 -4
  28. package/package.json +1 -1
  29. package/dist/shell/assets/cssMode-Ck0mAapo.js +0 -1
  30. package/dist/shell/assets/handlebars-C6vrFwYj.js +0 -1
  31. package/dist/shell/assets/html-CE92cnIr.js +0 -1
  32. package/dist/shell/assets/htmlMode-CfM52A9Q.js +0 -1
  33. package/dist/shell/assets/index-DOf1M9v5.js +0 -233
  34. package/dist/shell/assets/index-b4LMTPcs.css +0 -1
  35. package/dist/shell/assets/javascript-C7Q1bCJn.js +0 -1
  36. package/dist/shell/assets/liquid-CnxQAGJm.js +0 -1
  37. package/dist/shell/assets/mdx-ycMLgnto.js +0 -1
  38. package/dist/shell/assets/python-se_0lOPN.js +0 -1
  39. package/dist/shell/assets/razor-DjByizBq.js +0 -1
  40. package/dist/shell/assets/tsMode-D1mOZbLC.js +0 -11
  41. package/dist/shell/assets/typescript-B-dZdvXG.js +0 -1
  42. package/dist/shell/assets/workers-DXwGNRtC.js +0 -1
  43. package/dist/shell/assets/xml-CoqNFco9.js +0 -1
  44. package/dist/shell/assets/yaml-D5Qru8sI.js +0 -1
package/README.md CHANGED
@@ -4,12 +4,10 @@ Toyon is where you ask for changes to your web app and try them as they happen.
4
4
 
5
5
  Each copy runs on your own machine, and the next one is pre-warmed. Works with Claude Code, Codex and OpenCode over the Agent Client Protocol (ACP).
6
6
 
7
- ![Toyon with three chats on a plant shop: the open one is adding a dark mode, and the shop beside it has already turned dark while the agent works](https://raw.githubusercontent.com/toyon-dev/toyon/main/docs/images/toyon.jpg)
8
-
9
- **Status: pre-alpha, built in the open.** Runs on macOS and Linux. Windows through WSL2 is next. Expect rough edges, and say so in an issue.
10
-
11
7
  [How it works](#how-it-works) · [Install](#install) · [Under the hood](#under-the-hood) · [Trust](#trust) · [Uninstall](#uninstall)
12
8
 
9
+ ![Toyon with four chats on a plant shop, each changing its own copy. The desk opens a code, a phone signs in with it and starts a copy of its own, both screens follow that chat, and both end on the last copy with its Wildflowers filter pressed, ready to land](https://raw.githubusercontent.com/toyon-dev/toyon/main/docs/images/toyon.gif)
10
+
13
11
  ## Why
14
12
 
15
13
  A diff says what changed, not whether the page still looks right. A preview link at the end of a run shows you the result after the agent has stopped, too late to steer it. And with more than one agent going it gets worse: terminal splits, copies of the repo made by hand, dev servers fighting over a port.
@@ -18,13 +16,11 @@ In Toyon you point at a button in the page and ask for it to be bigger, watch it
18
16
 
19
17
  ## How it works
20
18
 
21
- - Every idea gets its own copy of your project, with the app running.
19
+ - Every idea gets its own running copy of your project.
22
20
  - You judge the work by using the app first, then read the change.
23
- - When you're not sure, try more than one version.
24
- - Watch and steer while it works, or leave and come back to your app already running.
25
- - Fix the small thing yourself. A one-line change does not need another prompt.
26
- - Nothing is kept until you say so.
27
- - Your editor stays yours.
21
+ - Watch and steer while it works, or leave and come back to it later.
22
+ - Kick off more work or check in remotely from your phone.
23
+ - Nothing is kept until you press land.
28
24
 
29
25
  Each copy is a branch and a git worktree with your dependencies and `.env` files; one spare per project is kept warm.
30
26
 
@@ -56,6 +52,7 @@ toyon ~/projects/app
56
52
 
57
53
  You need:
58
54
 
55
+ - macOS or Linux. Windows through WSL2 is not supported yet.
59
56
  - git and Node 18 or newer. Bun comes with the package.
60
57
  - An account for the agent you pick: a Claude plan or an Anthropic API key for Claude Code, a ChatGPT plan or an OpenAI API key for Codex, or any provider OpenCode signs into.
61
58
  - On Linux, bubblewrap and socat for the agents' sandbox (`sudo apt install bubblewrap socat`). `toyon doctor` checks both and prints the AppArmor profile Ubuntu 24.04 and later ask for.
@@ -64,9 +61,12 @@ Each agent signs in from the chat. Claude Code and Codex install on first start;
64
61
 
65
62
  ## How is this different from what you use now?
66
63
 
67
- - **Claude Code or Codex in a terminal.** Toyon runs that same agent under your own login and config; for Claude Code that includes your permission rules, hooks, slash commands and MCP servers. What changes is around it: each chat gets its own copy of the project with the app running, and nothing lands until you press.
68
- - **Cursor, Zed or VS Code.** Toyon sits beside your editor, not in place of it. Their agent panels and worktrees live in the editor, with a browser you open when you want it; in Toyon the running app is the centre of every chat, wired to its source. Your checkout stays yours, and any file opens back in your editor from its menu.
69
- - **Conductor or Superset.** They are good tools for running many agents at once. Toyon is built around the app instead of the agents: every chat opens with your app running at the centre, connected to its code, so you see each change before you keep it. It is MIT licensed, needs no account, sends no telemetry, runs in your browser on macOS or Linux, and lands work as a pull request on GitHub or on your own machine without it.
64
+ | Coming from | What stays | What changes |
65
+ |---|---|---|
66
+ | Claude Code or Codex in a terminal | The same agent under your login, with your permission rules, hooks, slash commands and MCP servers | Each chat gets its own copy of the project with the app running, and nothing lands until you press |
67
+ | Cursor, Zed or VS Code | Your editor and your checkout; any file opens back in your editor | The running app is the centre of every chat, wired to its source |
68
+ | Lovable, v0 or Bolt | The loop: a chat and the page it changes | Your own project on your machine, with your database, Docker and private packages; each chat is a branch in your repository |
69
+ | Conductor or Superset | Many agents at once, each on its own copy | Built around the app instead of the agents; MIT, no account, no telemetry, lands on your machine without GitHub |
70
70
 
71
71
  ## Under the hood
72
72
 
@@ -78,7 +78,7 @@ A project with a page and an API behind it:
78
78
  {
79
79
  "setup": ["npm install"],
80
80
  "run": {
81
- "web": "vite --port $PORT",
81
+ "web": "vite --port $PORT --strictPort",
82
82
  "api": "node --watch server.js"
83
83
  },
84
84
  "check": "npm test",
@@ -102,7 +102,7 @@ Copies start when you open them, and stop their servers when nobody has looked a
102
102
 
103
103
  Toyon can also run on a box you open from your phone, or on your own Fly account with the laptop closed. This moves Toyon and its copies off your laptop; it does not publish your app. None of it passes through a Toyon server; there is none. `toyon remote` puts a box on your own domain behind Caddy or on your Tailscale tailnet, `toyon deploy fly up` builds a machine on your Fly account and prints the link, and the Dockerfile in the package runs on any host with a disk and a port range. A Fly machine measured about $4-6 a month in ordinary use, plus whatever your agents spend, and its first chat can sign in with your Claude plan. [toyon.cloud](https://toyon.cloud) keeps a list of your machines in your browser, and nothing else.
104
104
 
105
- These routes are new, and the shell has no phone layout yet. How to set each one up, and what it has been checked with, is in [docs/remote.md](https://github.com/toyon-dev/toyon/blob/main/docs/remote.md).
105
+ These routes are new. How to set each one up, and what it has been checked with, is in [docs/remote.md](https://github.com/toyon-dev/toyon/blob/main/docs/remote.md).
106
106
 
107
107
  ## Disk
108
108
 
package/bin/toyon.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  // The npm entry. Everything toyon does runs under bun; this finds one and hands over. The `bun`
3
- // package in our dependencies carries the platform binary, so `npx toyon` works on a machine
4
- // with only Node; a bun already on PATH is the fallback when that optional download failed.
3
+ // package in our dependencies carries the platform binary, so `npx toyon` works on a machine with
4
+ // only Node. Three places are tried in turn: where bun's postinstall puts the binary, where the
5
+ // platform package keeps it when that postinstall never ran, and finally a bun already on PATH.
5
6
 
6
7
  import { spawnSync } from "node:child_process";
7
- import { existsSync } from "node:fs";
8
8
  import { createRequire } from "node:module";
9
9
  import { dirname, join } from "node:path";
10
10
  import { fileURLToPath } from "node:url";
@@ -12,28 +12,72 @@ import { fileURLToPath } from "node:url";
12
12
  const here = dirname(fileURLToPath(import.meta.url));
13
13
  const require = createRequire(import.meta.url);
14
14
 
15
+ // The bun this package was built against: the daemon and bun-pty are tested on it, and an older one
16
+ // on PATH fails somewhere opaque rather than here.
17
+ const FLOOR = require("../package.json").dependencies.bun;
18
+
19
+ function parse(v) {
20
+ const bare = v.trim().replace(/^[\^~]/, "");
21
+ return bare.split(".").map(Number);
22
+ }
23
+ function atLeast(version, floor) {
24
+ const a = parse(version);
25
+ const b = parse(floor);
26
+ for (let i = 0; i < b.length; i++) {
27
+ if ((a[i] ?? 0) !== b[i]) return (a[i] ?? 0) > b[i];
28
+ }
29
+ return true;
30
+ }
31
+
32
+ // Whether a candidate is a bun we can use is asked of the candidate itself. When npm or pnpm skips
33
+ // bun's postinstall the package still leaves a bin/bun.exe behind: a shell script that prints an
34
+ // error and exits 1. And `npx` puts node_modules/.bin first on PATH, where that same stub sits
35
+ // under the name `bun`. Existence proves nothing and so does the file's shape (an asdf or mise
36
+ // shim is a script and a real bun); a run does, for the price of one spawn per candidate.
37
+ function usable(file) {
38
+ const r = spawnSync(file, ["--version"], { encoding: "utf8" });
39
+ return r.status === 0 && /^\d+\.\d+\.\d+/.test(r.stdout.trim()) && atLeast(r.stdout, FLOOR);
40
+ }
41
+
15
42
  function bundledBun() {
16
43
  try {
17
44
  // the package's postinstall leaves the real binary at bin/bun.exe on every platform
18
- const exe = join(dirname(require.resolve("bun/package.json")), "bin", "bun.exe");
19
- return existsSync(exe) ? exe : null;
45
+ return join(dirname(require.resolve("bun/package.json")), "bin", "bun.exe");
20
46
  } catch {
21
47
  return null;
22
48
  }
23
49
  }
24
50
 
25
- function pathBun() {
26
- const which = process.platform === "win32" ? "where" : "which";
27
- const r = spawnSync(which, ["bun"], { encoding: "utf8" });
28
- const found = r.status === 0 ? r.stdout.split("\n")[0].trim() : "";
29
- return found || null;
51
+ // Where the platform packages keep the binary before bun's postinstall moves it into place. A
52
+ // skipped postinstall is the only reason bundledBun misses, so the binary is still right here.
53
+ // On Alpine both the glibc and the musl package install; the probe tells them apart.
54
+ function platformBuns() {
55
+ const arch = process.arch === "arm64" ? "aarch64" : process.arch;
56
+ const names = [`@oven/bun-${process.platform}-${arch}`];
57
+ if (process.platform === "linux") names.push(`@oven/bun-linux-${arch}-musl`);
58
+ const out = [];
59
+ for (const name of names) {
60
+ try {
61
+ out.push(join(dirname(require.resolve(`${name}/package.json`)), "bin", "bun"));
62
+ } catch {
63
+ // not installed for this platform; try the next candidate
64
+ }
65
+ }
66
+ return out;
67
+ }
68
+
69
+ // every bun on PATH, not the first: under npx the first is the stub in node_modules/.bin
70
+ function pathBuns() {
71
+ const r = spawnSync("which", ["-a", "bun"], { encoding: "utf8" });
72
+ return r.status === 0 ? r.stdout.split("\n").filter((line) => line.trim()) : [];
30
73
  }
31
74
 
32
- const bun = bundledBun() ?? pathBun();
75
+ const bun = [bundledBun(), ...platformBuns(), ...pathBuns()].filter(Boolean).find(usable);
33
76
  if (!bun) {
34
77
  console.error(
35
- "toyon: bun is not installed and npm could not fetch it for this platform.\n" +
36
- "install it from https://bun.sh and run toyon again.",
78
+ `toyon: could not find a usable bun (${FLOOR} or newer).\n` +
79
+ "the bundled copy is missing or incomplete, and there is none on PATH.\n" +
80
+ "install bun from https://bun.sh, or reinstall toyon with install scripts enabled.",
37
81
  );
38
82
  process.exit(1);
39
83
  }
package/dist/bridge.js CHANGED
@@ -1 +1 @@
1
- var T=[{id:"quick-open",key:"p"},{id:"commands",key:"p",shift:!0,bareAlias:"F1"},{id:"search",key:"f",shift:!0},{id:"chats",key:"g"},{id:"changes",key:"b",ctrlAlias:{key:"g",shift:!0}},{id:"files",key:"e",shift:!0},{id:"composer",key:"l"},{id:"rail",key:"k",shift:!0},{id:"keys",key:","},{id:"terminal",key:"j",ctrlAlias:{key:"`"}},{id:"design",key:"d"},{id:"term-tab",key:"`",ctrl:!0,shift:!0},{id:"pick",key:"e"},{id:"inspect",key:"i"},{id:"zen",key:"."},{id:"new",key:"k",aliases:["n"]},{id:"worktree",key:"1-9"},{id:"wt-prev",key:"ArrowUp",alt:!0,ctrlAlias:{key:"Tab",shift:!0},cmdShiftAlias:["[","{"]},{id:"wt-next",key:"ArrowDown",alt:!0,ctrlAlias:{key:"Tab"},cmdShiftAlias:["]","}"]},{id:"wt-unseen-prev",key:"ArrowUp",alt:!0,shift:!0},{id:"wt-unseen-next",key:"ArrowDown",alt:!0,shift:!0},{id:"mark-unread",key:"u",shift:!0},{id:"project",key:"o",ctrlAlias:{key:"r",hostOnly:!0},cmdShiftAlias:["o"]},{id:"refs",key:"g",shift:!0},{id:"routes",key:"u"},{id:"reload",key:"r"}];function H(e,{guest:t=!1}={}){if(e.altKey){if(e.metaKey||e.ctrlKey)return null;let r=T.find((i)=>i.alt&&i.key===e.key&&!!i.shift===e.shiftKey);return r&&r.id!=="worktree"?{id:r.id}:null}if(!e.metaKey&&!e.ctrlKey){if(e.shiftKey||t)return null;let r=T.find((i)=>i.bareAlias===e.key);return r&&r.id!=="worktree"?{id:r.id}:null}if(!!e.ctrlKey===e.metaKey)return null;let n=e.key.length===1?e.key.toLowerCase():e.key;if(e.metaKey&&!e.shiftKey&&n>="1"&&n<="9")return{id:"worktree",digit:Number(n)};for(let r of T){if(r.id==="worktree")continue;let i=r.ctrlAlias;if(i&&e.ctrlKey&&i.key===n&&!!i.shift===e.shiftKey&&!(t&&i.hostOnly))return{id:r.id};if(e.metaKey&&e.shiftKey&&r.cmdShiftAlias?.includes(n))return{id:r.id};if(r.alt)continue;if(e.ctrlKey&&!r.ctrl||!!r.shift!==e.shiftKey)continue;if(r.key===n||r.aliases?.includes(n))return{id:r.id}}return null}var G=Symbol.for("react.forward_ref"),V=Symbol.for("react.memo");function R(e){if(e._debugSource?.fileName)return{file:e._debugSource.fileName,line:e._debugSource.lineNumber};let t=e._debugStack?.stack;if(t){let n=t.match(/https?:\/\/[^/]+(\/src\/[^)\s?]+)(?:\?[^:)\s]*)?:(\d+):\d+/);if(n?.[1])return{file:n[1],line:Number(n[2])||void 0}}return null}function _(e){for(let t=e;t;t=t.return){let n=R(t);if(n)return n}return null}function C(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===G)return t.displayName||C(t.render);if(t?.$$typeof===V)return t.displayName||C(t.type);return null}var J=(e)=>typeof e.type==="string"||e.tag===6,Q=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function Z(e){let t=null,n=(r)=>{for(let i=r.child??null;i;i=i.sibling??null)if(J(i)){if(t)return!1;t=i}else if(!n(i))return!1;return!0};return n(e)?t:null}function ee(e){for(let t=e;t;t=t.return){let n=R(t);if(n)return t._debugOwner===null?null:n}return null}function K(e){let t=_(e),n=null,r=null,i=!1;for(let o=e;o;o=o.return){let s=C(o.type);if(!s)continue;let l=!!e&&Q(Z(o),e),a=ee(o);if(n&&!(l&&a))break;if(n=s,r=a,i=l,!l)break}if(r&&t&&r.file===t.file&&r.line===t.line)r=null;return{src:t,comp:n,call:r,wraps:i}}function L({src:e,call:t,wraps:n},r){let i=n?t:e,o=n?e:t;return(r?o??i:i??o)??null}if(window.__toyonBridge)throw Error("Toyon bridge already installed");window.__toyonBridge=!0;var b=window.__toyonShellOrigins??[],O=null,c=(e)=>{try{let t=O?[O]:b.length?b:["*"];for(let n of t)window.parent.postMessage({__toyon:!0,...e},n)}catch{}};c({type:"loaded",url:location.href,title:document.title});var w="#ff4929",W="#1d2021";window.addEventListener("vite:afterUpdate",()=>c({type:"hmr"}));window.addEventListener("error",(e)=>{c({type:"page-error",message:String(e.message),source:e.filename,line:e.lineno})});window.addEventListener("unhandledrejection",(e)=>{c({type:"page-error",message:`unhandled rejection: ${String(e.reason)}`})});var S=()=>c({type:"navigated",url:location.href,title:document.title}),te=history.pushState.bind(history);history.pushState=(...e)=>{te(...e),S()};var ne=history.replaceState.bind(history);history.replaceState=(...e)=>{ne(...e),S()};window.addEventListener("popstate",S);window.addEventListener("hashchange",S);var F=document.title;if(document.head)new MutationObserver(()=>{if(document.title===F)return;F=document.title,c({type:"title",title:F})}).observe(document.head,{childList:!0,subtree:!0,characterData:!0});var j=!1;window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;let t=H(e,{guest:!0});if(j){if(t?.id!=="zen")return}else if(e.key==="Escape"){c({type:"key",key:"Escape",meta:!1});return}else if(!t)return;e.preventDefault(),e.stopPropagation(),c({type:"key",key:e.key,meta:e.metaKey,ctrl:e.ctrlKey,shift:e.shiftKey,alt:e.altKey})},!0);var q=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!q(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="none";c({type:"drag-files"})});window.addEventListener("drop",(e)=>{if(!q(e))return;e.preventDefault(),c({type:"drop-files"})});function P(e){for(let t of Object.keys(e))if(t.startsWith("__reactFiber$"))return e[t]??null;return null}var p=null;function re(){if(p?.isConnected)return p;return p=document.createElement("div"),p.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:2147483647;",document.documentElement.appendChild(p),p}function m(){if(p)p.innerHTML=""}var N=20;function E(e,t,n=!0){let r=document.createElement("div");if(r.style.cssText=`position:fixed;left:${e.left}px;top:${e.top}px;width:${e.width}px;height:${e.height}px;outline:2px solid ${w};outline-offset:-1px;${n?`background:${w}14;`:""}border-radius:2px;`,t){let i=e.top>=N,o=e.bottom+N<=window.innerHeight;if(t.style.top=i?`${-N}px`:o?`${e.height+4}px`:"2px",!i&&!o)t.style.left="2px";r.appendChild(t)}if(re().appendChild(r),t){let i=t.getBoundingClientRect(),o=i.right-(window.innerWidth-2);if(o>0){let s=Number.parseFloat(t.style.left||"0");t.style.left=`${s-Math.min(o,Math.max(0,i.left-2))}px`}}}function g(e,t){let n=document.createElement("div");if(n.textContent=e,n.style.cssText=`position:absolute;left:0;background:${w};color:${W};font:11px -apple-system,sans-serif;padding:1px 6px;border-radius:3px;white-space:nowrap;`,t){let r=document.createElement("span");r.textContent=` ${t}`,r.style.opacity="0.55",n.appendChild(r)}return n}var x=!1,d=null,h=!1,f=!1,y=!1,M=(e)=>`${U(e.file)}${e.line?`:${e.line}`:""}`;function A(e){d=e,m();let t=K(P(e)),{src:n,comp:r,call:i}=t,o=L(t,f),s=o===n?i:n,l=h!==y,a=(...k)=>k.filter(Boolean).join(" ")||void 0,u=l?o?g(`open ${M(o)}`,a(s&&`⇧ ${M(s)}`,y&&"⌥ chat")):g(`find ${I(e)}`,a(y&&"⌥ chat")):g(r?`<${r} />${o?` · ${M(o)}`:""}`:I(e),a(!y&&"⌥ code"));E(e.getBoundingClientRect(),u,l)}function I(e){let t=e.tagName.toLowerCase(),n=e.classList[0];return(e.id?`${t}#${e.id}`:n?`${t}.${n}`:t).slice(0,48)}var ie=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function oe(e){let t="";for(let r of Array.from(e.childNodes))if(r.nodeType===Node.TEXT_NODE)t+=r.textContent??"";let n=[];for(let r of Array.from(e.attributes)){if(n.length===12)break;if(r.value&&(ie.has(r.name)||r.name.startsWith("data-")))n.push([r.name.slice(0,40),r.value.slice(0,200)])}return{tag:e.tagName.toLowerCase().slice(0,40),id:e.id.slice(0,200),classes:Array.from(e.classList).slice(0,16).map((r)=>r.slice(0,120)),text:t.replace(/\s+/g," ").trim().slice(0,200),attrs:n}}function z(e){let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t!==d||e.altKey!==h||e.shiftKey!==f;if(h=e.altKey,f=e.shiftKey,n)A(t)}function X(e){e.preventDefault(),e.stopPropagation();let t=d??document.elementFromPoint(e.clientX,e.clientY),n=K(t?P(t):null),{src:r,comp:i,call:o}=n;f=e.shiftKey;let s=L(n,f),l=e.altKey!==y;if(D(),!t)return;c({type:"picked",verb:l?"code":"chat",site:s&&s===o?"call":"source",component:i,file:r?.file??null,line:r?.line??null,callFile:o?.file??null,callLine:o?.line??null,selector:se(t),tag:t.tagName.toLowerCase(),classes:t.className?.toString?.().slice(0,200)??"",text:t.textContent?.trim().slice(0,120)??"",html:t.outerHTML.slice(0,600),route:location.pathname+location.search,element:oe(t)})}function v(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),D(),c({type:"pick-cancel"});return}if((e.key==="Alt"||e.key==="Shift")&&(h!==e.altKey||f!==e.shiftKey)){if(h=e.altKey,f=e.shiftKey,d)A(d)}}function le(e){if(y=e,x){if(d)A(d);return}x=!0,d=null,h=!1,f=!1,document.addEventListener("mousemove",z,!0),document.addEventListener("click",X,!0),document.addEventListener("keydown",v,!0),document.addEventListener("keyup",v,!0),document.documentElement.style.cursor="crosshair"}function D(){x=!1,y=!1,d=null,h=!1,f=!1,m(),document.removeEventListener("mousemove",z,!0),document.removeEventListener("click",X,!0),document.removeEventListener("keydown",v,!0),document.removeEventListener("keyup",v,!0),document.documentElement.style.cursor=""}function se(e){let t=[],n=e;for(let r=0;n&&n!==document.documentElement&&r<6;r++){if(n.id){t.unshift(`#${CSS.escape(n.id)}`);break}let i=n.parentElement,o=i?Array.from(i.children).indexOf(n)+1:1;t.unshift(`${n.tagName.toLowerCase()}:nth-child(${o})`),n=i}return t.join(" > ")}function U(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function ae(e,t){return e.endsWith(t)||t.endsWith(U(e))}function ce(e,t){let n=[],r=0;for(let s of Array.from(document.querySelectorAll("*"))){let l=_(P(s));if(l)r++;if(!l||!ae(l.file,e))continue;n.push({el:s,line:l.line??-1})}if(!t||t.length===0)return{matched:n,fromFile:n,withSource:r};if(t.length===1&&t[0][0]===t[0][1]){let s=t[0][0],l=n.filter((u)=>u.line===s);if(l.length>0)return{matched:l,fromFile:n,withSource:r};let a=n.filter((u)=>u.line>0&&u.line<s);return a.sort((u,k)=>k.line-u.line),{matched:a.slice(0,1),fromFile:n,withSource:r}}return{matched:n.filter((s)=>t.some(([l,a])=>s.line>=l-8&&s.line<=a+1)),fromFile:n,withSource:r}}function ue(e,t){m();let{matched:n,fromFile:r,withSource:i}=ce(e,t),o=0;for(let{el:s}of n){if(o>=40)break;let l=s.getBoundingClientRect();if(l.width>0&&l.height>0)E(l),o++}if(o===0)c({type:"highlight-miss",path:e,fileMatched:r.length,withSource:i,ranges:t})}window.addEventListener("message",(e)=>{if(e.source!==window.parent)return;if(b.length&&!b.includes(e.origin))return;let t=e.data;if(!t?.__toyon)return;O=e.origin;let n=t;switch(n.type){case"reload":location.reload();break;case"navigate":if(/^[/?#]/.test(n.path))location.assign(n.path);break;case"back":history.back();break;case"forward":history.forward();break;case"links":{let r=new Set,i=[];for(let o of Array.from(document.querySelectorAll("a[href]"))){if(o.origin!==location.origin||o.target==="_blank"||o.hasAttribute("download"))continue;let s=o.pathname+(o.hash.startsWith("#/")?o.hash:"");if(s.startsWith("/__toyon")||r.has(s))continue;r.add(s);let l=(o.textContent||o.getAttribute("aria-label")||"").replace(/\s+/g," ").trim();if(i.push({path:s,text:l.slice(0,80)}),i.length>=200)break}c({type:"links",links:i});break}case"pick-start":le(n.verb==="code");break;case"pick-mods":if(x&&(h!==n.alt||f!==n.shift)){if(h=n.alt,f=n.shift,d)A(d)}break;case"pick-cancel":D();break;case"highlight-file":ue(n.path,n.ranges??null);break;case"highlight-computed":{m();let r=/^(color|font|line-height|letter-|text-|word-)/,i=(l)=>{if(/^(INPUT|TEXTAREA|SELECT)$/.test(l.tagName))return!0;for(let a=l.firstChild;a;a=a.nextSibling)if(a.nodeType===3&&a.textContent&&a.textContent.trim())return!0;return!1},o=document.querySelectorAll("*"),s=!0;for(let l=0;l<o.length;l++){let a=getComputedStyle(o[l]),u=([B,Y])=>a.getPropertyValue(B)===Y&&(!r.test(B)||i(o[l]));if(n.match==="any"?n.props.some(u):n.props.every(u))E(o[l].getBoundingClientRect(),s&&n.label?g(n.label):void 0),s=!1}break}case"highlight-selector":{m();try{let r=document.querySelectorAll(n.selector);for(let i=0;i<r.length;i++)E(r[i].getBoundingClientRect(),i===0&&n.label?g(n.label):void 0)}catch{}break}case"highlight-clear":m();break;case"zen":j=n.on;break;case"theme":if(/^#[0-9a-f]{3,8}$/i.test(n.accent))w=n.accent;if(/^#[0-9a-f]{3,8}$/i.test(n.accentFg))W=n.accentFg;break}});
1
+ var b=[{id:"quick-open",key:"p"},{id:"commands",key:"p",shift:!0,bareAlias:"F1"},{id:"search",key:"f",shift:!0},{id:"chats",key:"g"},{id:"changes",key:"b",ctrlAlias:{key:"g",shift:!0}},{id:"files",key:"e",shift:!0},{id:"panel-tab-prev",key:"ArrowLeft",alt:!0,textKeeps:!0},{id:"panel-tab-next",key:"ArrowRight",alt:!0,textKeeps:!0},{id:"composer",key:"l"},{id:"rail",key:"k",shift:!0},{id:"keys",key:","},{id:"terminal",key:"j",ctrlAlias:{key:"`"}},{id:"design",key:"d"},{id:"term-tab",key:"`",ctrl:!0,shift:!0},{id:"pick",key:"e"},{id:"inspect",key:"i"},{id:"zen",key:"."},{id:"new",key:"k",aliases:["n"]},{id:"worktree",key:"1-9"},{id:"wt-prev",key:"ArrowUp",alt:!0,ctrlAlias:{key:"Tab",shift:!0},cmdShiftAlias:["[","{"]},{id:"wt-next",key:"ArrowDown",alt:!0,ctrlAlias:{key:"Tab"},cmdShiftAlias:["]","}"]},{id:"wt-unseen-prev",key:"ArrowUp",alt:!0,shift:!0},{id:"wt-unseen-next",key:"ArrowDown",alt:!0,shift:!0},{id:"mark-unread",key:"u",shift:!0},{id:"project",key:"o",ctrlAlias:{key:"r",hostOnly:!0},cmdShiftAlias:["o"]},{id:"refs",key:"g",shift:!0},{id:"routes",key:"u"},{id:"reload",key:"r"}];function B(e,{guest:t=!1}={}){if(e.altKey){if(e.metaKey||e.ctrlKey)return null;let r=b.find((i)=>i.alt&&i.key===e.key&&!!i.shift===e.shiftKey);return r&&r.id!=="worktree"?{id:r.id}:null}if(!e.metaKey&&!e.ctrlKey){if(e.shiftKey||t)return null;let r=b.find((i)=>i.bareAlias===e.key);return r&&r.id!=="worktree"?{id:r.id}:null}if(!!e.ctrlKey===e.metaKey)return null;let n=e.key.length===1?e.key.toLowerCase():e.key;if(e.metaKey&&!e.shiftKey&&n>="1"&&n<="9")return{id:"worktree",digit:Number(n)};for(let r of b){if(r.id==="worktree")continue;let i=r.ctrlAlias;if(i&&e.ctrlKey&&i.key===n&&!!i.shift===e.shiftKey&&!(t&&i.hostOnly))return{id:r.id};if(e.metaKey&&e.shiftKey&&r.cmdShiftAlias?.includes(n))return{id:r.id};if(r.alt)continue;if(e.ctrlKey&&!r.ctrl||!!r.shift!==e.shiftKey)continue;if(r.key===n||r.aliases?.includes(n))return{id:r.id}}return null}function H(e){let t=b.find((n)=>n.id===e);if(!t)throw Error(`unknown chord ${e}`);return t}function I(e){let t=e;if(!t?.tagName)return!1;if(t.isContentEditable||t.tagName==="TEXTAREA")return!0;return t.tagName==="INPUT"&&!["button","checkbox","radio","range","submit","reset"].includes(t.type??"")}var J=Symbol.for("react.forward_ref"),Q=Symbol.for("react.memo");function W(e){if(e._debugSource?.fileName)return{file:e._debugSource.fileName,line:e._debugSource.lineNumber};let t=e._debugStack?.stack;if(t){let n=t.match(/https?:\/\/[^/]+(\/src\/[^)\s?]+)(?:\?[^:)\s]*)?:(\d+):\d+/);if(n?.[1])return{file:n[1],line:Number(n[2])||void 0}}return null}function K(e){for(let t=e;t;t=t.return){let n=W(t);if(n)return n}return null}function C(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===J)return t.displayName||C(t.render);if(t?.$$typeof===Q)return t.displayName||C(t.type);return null}var Z=(e)=>typeof e.type==="string"||e.tag===6,ee=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function te(e){let t=null,n=(r)=>{for(let i=r.child??null;i;i=i.sibling??null)if(Z(i)){if(t)return!1;t=i}else if(!n(i))return!1;return!0};return n(e)?t:null}function ne(e){for(let t=e;t;t=t.return){let n=W(t);if(n)return t._debugOwner===null?null:n}return null}function L(e){let t=K(e),n=null,r=null,i=!1;for(let o=e;o;o=o.return){let s=C(o.type);if(!s)continue;let l=!!e&&ee(te(o),e),a=ne(o);if(n&&!(l&&a))break;if(n=s,r=a,i=l,!l)break}if(r&&t&&r.file===t.file&&r.line===t.line)r=null;return{src:t,comp:n,call:r,wraps:i}}function _({src:e,call:t,wraps:n},r){let i=n?t:e,o=n?e:t;return(r?o??i:i??o)??null}if(window.__toyonBridge)throw Error("Toyon bridge already installed");window.__toyonBridge=!0;var w=window.__toyonShellOrigins??[],M=null,c=(e)=>{try{let t=M?[M]:w.length?w:["*"];for(let n of t)window.parent.postMessage({__toyon:!0,...e},n)}catch{}};c({type:"loaded",url:location.href,title:document.title});var x="#ff4929",X="#1d2021";window.addEventListener("vite:afterUpdate",()=>c({type:"hmr"}));window.addEventListener("error",(e)=>{c({type:"page-error",message:String(e.message),source:e.filename,line:e.lineno})});window.addEventListener("unhandledrejection",(e)=>{c({type:"page-error",message:`unhandled rejection: ${String(e.reason)}`})});var A=()=>c({type:"navigated",url:location.href,title:document.title}),re=history.pushState.bind(history);history.pushState=(...e)=>{re(...e),A()};var ie=history.replaceState.bind(history);history.replaceState=(...e)=>{ie(...e),A()};window.addEventListener("popstate",A);window.addEventListener("hashchange",A);var N=document.title;if(document.head)new MutationObserver(()=>{if(document.title===N)return;N=document.title,c({type:"title",title:N})}).observe(document.head,{childList:!0,subtree:!0,characterData:!0});var q=!1;window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;let t=B(e,{guest:!0});if(t&&H(t.id).textKeeps&&I(e.target))return;if(q){if(t?.id!=="zen")return}else if(e.key==="Escape"){c({type:"key",key:"Escape",meta:!1});return}else if(!t)return;e.preventDefault(),e.stopPropagation(),c({type:"key",key:e.key,meta:e.metaKey,ctrl:e.ctrlKey,shift:e.shiftKey,alt:e.altKey})},!0);var z=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!z(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="none";c({type:"drag-files"})});window.addEventListener("drop",(e)=>{if(!z(e))return;e.preventDefault(),c({type:"drop-files"})});function P(e){for(let t of Object.keys(e))if(t.startsWith("__reactFiber$"))return e[t]??null;return null}var p=null;function oe(){if(p?.isConnected)return p;return p=document.createElement("div"),p.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:2147483647;",document.documentElement.appendChild(p),p}function m(){if(p)p.innerHTML=""}var F=20;function E(e,t,n=!0){let r=document.createElement("div");if(r.style.cssText=`position:fixed;left:${e.left}px;top:${e.top}px;width:${e.width}px;height:${e.height}px;outline:2px solid ${x};outline-offset:-1px;${n?`background:${x}14;`:""}border-radius:2px;`,t){let i=e.top>=F,o=e.bottom+F<=window.innerHeight;if(t.style.top=i?`${-F}px`:o?`${e.height+4}px`:"2px",!i&&!o)t.style.left="2px";r.appendChild(t)}if(oe().appendChild(r),t){let i=t.getBoundingClientRect(),o=i.right-(window.innerWidth-2);if(o>0){let s=Number.parseFloat(t.style.left||"0");t.style.left=`${s-Math.min(o,Math.max(0,i.left-2))}px`}}}function g(e,t){let n=document.createElement("div");if(n.textContent=e,n.style.cssText=`position:absolute;left:0;background:${x};color:${X};font:11px -apple-system,sans-serif;padding:1px 6px;border-radius:3px;white-space:nowrap;`,t){let r=document.createElement("span");r.textContent=` ${t}`,r.style.opacity="0.55",n.appendChild(r)}return n}var v=!1,d=null,h=!1,f=!1,y=!1,O=(e)=>`${G(e.file)}${e.line?`:${e.line}`:""}`;function T(e){d=e,m();let t=L(P(e)),{src:n,comp:r,call:i}=t,o=_(t,f),s=o===n?i:n,l=h!==y,a=(...k)=>k.filter(Boolean).join(" ")||void 0,u=l?o?g(`open ${O(o)}`,a(s&&`⇧ ${O(s)}`,y&&"⌥ chat")):g(`find ${j(e)}`,a(y&&"⌥ chat")):g(r?`<${r} />${o?` · ${O(o)}`:""}`:j(e),a(!y&&"⌥ code"));E(e.getBoundingClientRect(),u,l)}function j(e){let t=e.tagName.toLowerCase(),n=e.classList[0];return(e.id?`${t}#${e.id}`:n?`${t}.${n}`:t).slice(0,48)}var le=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function se(e){let t="";for(let r of Array.from(e.childNodes))if(r.nodeType===Node.TEXT_NODE)t+=r.textContent??"";let n=[];for(let r of Array.from(e.attributes)){if(n.length===12)break;if(r.value&&(le.has(r.name)||r.name.startsWith("data-")))n.push([r.name.slice(0,40),r.value.slice(0,200)])}return{tag:e.tagName.toLowerCase().slice(0,40),id:e.id.slice(0,200),classes:Array.from(e.classList).slice(0,16).map((r)=>r.slice(0,120)),text:t.replace(/\s+/g," ").trim().slice(0,200),attrs:n}}function U(e){let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t!==d||e.altKey!==h||e.shiftKey!==f;if(h=e.altKey,f=e.shiftKey,n)T(t)}function Y(e){e.preventDefault(),e.stopPropagation();let t=d??document.elementFromPoint(e.clientX,e.clientY),n=L(t?P(t):null),{src:r,comp:i,call:o}=n;f=e.shiftKey;let s=_(n,f),l=e.altKey!==y;if(D(),!t)return;c({type:"picked",verb:l?"code":"chat",site:s&&s===o?"call":"source",component:i,file:r?.file??null,line:r?.line??null,callFile:o?.file??null,callLine:o?.line??null,selector:ce(t),tag:t.tagName.toLowerCase(),classes:t.className?.toString?.().slice(0,200)??"",text:t.textContent?.trim().slice(0,120)??"",html:t.outerHTML.slice(0,600),route:location.pathname+location.search,element:se(t)})}function S(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),D(),c({type:"pick-cancel"});return}if((e.key==="Alt"||e.key==="Shift")&&(h!==e.altKey||f!==e.shiftKey)){if(h=e.altKey,f=e.shiftKey,d)T(d)}}function ae(e){if(y=e,v){if(d)T(d);return}v=!0,d=null,h=!1,f=!1,document.addEventListener("mousemove",U,!0),document.addEventListener("click",Y,!0),document.addEventListener("keydown",S,!0),document.addEventListener("keyup",S,!0),document.documentElement.style.cursor="crosshair"}function D(){v=!1,y=!1,d=null,h=!1,f=!1,m(),document.removeEventListener("mousemove",U,!0),document.removeEventListener("click",Y,!0),document.removeEventListener("keydown",S,!0),document.removeEventListener("keyup",S,!0),document.documentElement.style.cursor=""}function ce(e){let t=[],n=e;for(let r=0;n&&n!==document.documentElement&&r<6;r++){if(n.id){t.unshift(`#${CSS.escape(n.id)}`);break}let i=n.parentElement,o=i?Array.from(i.children).indexOf(n)+1:1;t.unshift(`${n.tagName.toLowerCase()}:nth-child(${o})`),n=i}return t.join(" > ")}function G(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function ue(e,t){return e.endsWith(t)||t.endsWith(G(e))}function de(e,t){let n=[],r=0;for(let s of Array.from(document.querySelectorAll("*"))){let l=K(P(s));if(l)r++;if(!l||!ue(l.file,e))continue;n.push({el:s,line:l.line??-1})}if(!t||t.length===0)return{matched:n,fromFile:n,withSource:r};if(t.length===1&&t[0][0]===t[0][1]){let s=t[0][0],l=n.filter((u)=>u.line===s);if(l.length>0)return{matched:l,fromFile:n,withSource:r};let a=n.filter((u)=>u.line>0&&u.line<s);return a.sort((u,k)=>k.line-u.line),{matched:a.slice(0,1),fromFile:n,withSource:r}}return{matched:n.filter((s)=>t.some(([l,a])=>s.line>=l-8&&s.line<=a+1)),fromFile:n,withSource:r}}function fe(e,t){m();let{matched:n,fromFile:r,withSource:i}=de(e,t),o=0;for(let{el:s}of n){if(o>=40)break;let l=s.getBoundingClientRect();if(l.width>0&&l.height>0)E(l),o++}if(o===0)c({type:"highlight-miss",path:e,fileMatched:r.length,withSource:i,ranges:t})}window.addEventListener("message",(e)=>{if(e.source!==window.parent)return;if(w.length&&!w.includes(e.origin))return;let t=e.data;if(!t?.__toyon)return;M=e.origin;let n=t;switch(n.type){case"reload":location.reload();break;case"navigate":if(/^[/?#]/.test(n.path))location.assign(n.path);break;case"back":history.back();break;case"forward":history.forward();break;case"links":{let r=new Set,i=[];for(let o of Array.from(document.querySelectorAll("a[href]"))){if(o.origin!==location.origin||o.target==="_blank"||o.hasAttribute("download"))continue;let s=o.pathname+(o.hash.startsWith("#/")?o.hash:"");if(s.startsWith("/__toyon")||r.has(s))continue;r.add(s);let l=(o.textContent||o.getAttribute("aria-label")||"").replace(/\s+/g," ").trim();if(i.push({path:s,text:l.slice(0,80)}),i.length>=200)break}c({type:"links",links:i});break}case"pick-start":ae(n.verb==="code");break;case"pick-mods":if(v&&(h!==n.alt||f!==n.shift)){if(h=n.alt,f=n.shift,d)T(d)}break;case"pick-cancel":D();break;case"highlight-file":fe(n.path,n.ranges??null);break;case"highlight-computed":{m();let r=/^(color|font|line-height|letter-|text-|word-)/,i=(l)=>{if(/^(INPUT|TEXTAREA|SELECT)$/.test(l.tagName))return!0;for(let a=l.firstChild;a;a=a.nextSibling)if(a.nodeType===3&&a.textContent&&a.textContent.trim())return!0;return!1},o=document.querySelectorAll("*"),s=!0;for(let l=0;l<o.length;l++){let a=getComputedStyle(o[l]),u=([R,V])=>a.getPropertyValue(R)===V&&(!r.test(R)||i(o[l]));if(n.match==="any"?n.props.some(u):n.props.every(u))E(o[l].getBoundingClientRect(),s&&n.label?g(n.label):void 0),s=!1}break}case"highlight-selector":{m();try{let r=document.querySelectorAll(n.selector);for(let i=0;i<r.length;i++)E(r[i].getBoundingClientRect(),i===0&&n.label?g(n.label):void 0)}catch{}break}case"highlight-clear":m();break;case"zen":q=n.on;break;case"theme":if(/^#[0-9a-f]{3,8}$/i.test(n.accent))x=n.accent;if(/^#[0-9a-f]{3,8}$/i.test(n.accentFg))X=n.accentFg;break}});