toyon 0.22.0 → 0.23.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 (108) hide show
  1. package/README.md +3 -3
  2. package/dist/CHANGELOG.md +28 -0
  3. package/dist/bridge.js +1 -1
  4. package/dist/cli.js +92 -3
  5. package/dist/daemon.js +9913 -9002
  6. package/dist/shell/assets/{Editor-1fCgxkUp.js → Editor-C2e_GpDQ.js} +165 -165
  7. package/dist/shell/assets/Editor-C2e_GpDQ.js.br +0 -0
  8. package/dist/shell/assets/Editor-C2e_GpDQ.js.gz +0 -0
  9. package/dist/shell/assets/XTerm-B84G0H5I.js +58 -0
  10. package/dist/shell/assets/XTerm-B84G0H5I.js.br +0 -0
  11. package/dist/shell/assets/XTerm-B84G0H5I.js.gz +0 -0
  12. package/dist/shell/assets/{cssMode-1LqDnQzX.js → cssMode-DhDLwjyN.js} +1 -1
  13. package/dist/shell/assets/cssMode-DhDLwjyN.js.br +0 -0
  14. package/dist/shell/assets/cssMode-DhDLwjyN.js.gz +0 -0
  15. package/dist/shell/assets/{freemarker2-BJFDEJKJ.js → freemarker2-rc8sP22g.js} +1 -1
  16. package/dist/shell/assets/freemarker2-rc8sP22g.js.br +0 -0
  17. package/dist/shell/assets/freemarker2-rc8sP22g.js.gz +0 -0
  18. package/dist/shell/assets/{grammar-DVeERVO3.js → grammar-Cty-NAQC.js} +1 -1
  19. package/dist/shell/assets/grammar-Cty-NAQC.js.br +0 -0
  20. package/dist/shell/assets/grammar-Cty-NAQC.js.gz +0 -0
  21. package/dist/shell/assets/{handlebars-BGFLy2DH.js → handlebars-BOQxV3p5.js} +1 -1
  22. package/dist/shell/assets/handlebars-BOQxV3p5.js.br +0 -0
  23. package/dist/shell/assets/handlebars-BOQxV3p5.js.gz +0 -0
  24. package/dist/shell/assets/{html-CPJflvc5.js → html-CxndUpse.js} +1 -1
  25. package/dist/shell/assets/html-CxndUpse.js.br +0 -0
  26. package/dist/shell/assets/html-CxndUpse.js.gz +0 -0
  27. package/dist/shell/assets/{htmlMode-CjqzceBV.js → htmlMode-CG7eVDLo.js} +1 -1
  28. package/dist/shell/assets/htmlMode-CG7eVDLo.js.br +0 -0
  29. package/dist/shell/assets/htmlMode-CG7eVDLo.js.gz +0 -0
  30. package/dist/shell/assets/index-DpSfPmkM.css +1 -0
  31. package/dist/shell/assets/index-DpSfPmkM.css.br +0 -0
  32. package/dist/shell/assets/index-DpSfPmkM.css.gz +0 -0
  33. package/dist/shell/assets/index-DzfHDra7.js +294 -0
  34. package/dist/shell/assets/index-DzfHDra7.js.br +0 -0
  35. package/dist/shell/assets/index-DzfHDra7.js.gz +0 -0
  36. package/dist/shell/assets/{javascript-B4CelO-C.js → javascript-CafoevnZ.js} +1 -1
  37. package/dist/shell/assets/{jsonMode-C2JxYuT6.js → jsonMode-Cg_4sMB_.js} +1 -1
  38. package/dist/shell/assets/jsonMode-Cg_4sMB_.js.br +0 -0
  39. package/dist/shell/assets/jsonMode-Cg_4sMB_.js.gz +0 -0
  40. package/dist/shell/assets/{liquid-BfXRgBm_.js → liquid-DxW_HNid.js} +1 -1
  41. package/dist/shell/assets/liquid-DxW_HNid.js.br +0 -0
  42. package/dist/shell/assets/liquid-DxW_HNid.js.gz +0 -0
  43. package/dist/shell/assets/{lspLanguageFeatures-CAi6hRgs.js → lspLanguageFeatures-Dhat9l4L.js} +1 -1
  44. package/dist/shell/assets/lspLanguageFeatures-Dhat9l4L.js.br +0 -0
  45. package/dist/shell/assets/lspLanguageFeatures-Dhat9l4L.js.gz +0 -0
  46. package/dist/shell/assets/{mdx-DeBYGdge.js → mdx-ZdMhgPNL.js} +1 -1
  47. package/dist/shell/assets/mdx-ZdMhgPNL.js.br +0 -0
  48. package/dist/shell/assets/mdx-ZdMhgPNL.js.gz +0 -0
  49. package/dist/shell/assets/{python-CFhHKm43.js → python-Bae_7wMM.js} +1 -1
  50. package/dist/shell/assets/python-Bae_7wMM.js.br +0 -0
  51. package/dist/shell/assets/python-Bae_7wMM.js.gz +0 -0
  52. package/dist/shell/assets/{razor-C-gkU4Y9.js → razor-CtwiCIJH.js} +1 -1
  53. package/dist/shell/assets/razor-CtwiCIJH.js.br +0 -0
  54. package/dist/shell/assets/razor-CtwiCIJH.js.gz +0 -0
  55. package/dist/shell/assets/toyon-mono-bold-9c1iJO0D.woff2 +0 -0
  56. package/dist/shell/assets/toyon-mono-regular-BXyxgSUK.woff2 +0 -0
  57. package/dist/shell/assets/{tsMode-8E7grKbo.js → tsMode-DH9rMbRS.js} +1 -1
  58. package/dist/shell/assets/tsMode-DH9rMbRS.js.br +0 -0
  59. package/dist/shell/assets/tsMode-DH9rMbRS.js.gz +0 -0
  60. package/dist/shell/assets/{xml-CBoTF2r1.js → xml-rA-vNTCn.js} +1 -1
  61. package/dist/shell/assets/xml-rA-vNTCn.js.br +0 -0
  62. package/dist/shell/assets/xml-rA-vNTCn.js.gz +0 -0
  63. package/dist/shell/assets/{yaml-CyKxhzxl.js → yaml-pOtRRozm.js} +1 -1
  64. package/dist/shell/assets/yaml-pOtRRozm.js.br +0 -0
  65. package/dist/shell/assets/yaml-pOtRRozm.js.gz +0 -0
  66. package/dist/shell/index.html +2 -2
  67. package/package.json +1 -1
  68. package/dist/shell/assets/Editor-1fCgxkUp.js.br +0 -0
  69. package/dist/shell/assets/Editor-1fCgxkUp.js.gz +0 -0
  70. package/dist/shell/assets/XTerm-B_hkTWne.js +0 -58
  71. package/dist/shell/assets/XTerm-B_hkTWne.js.br +0 -0
  72. package/dist/shell/assets/XTerm-B_hkTWne.js.gz +0 -0
  73. package/dist/shell/assets/cssMode-1LqDnQzX.js.br +0 -0
  74. package/dist/shell/assets/cssMode-1LqDnQzX.js.gz +0 -0
  75. package/dist/shell/assets/freemarker2-BJFDEJKJ.js.br +0 -0
  76. package/dist/shell/assets/freemarker2-BJFDEJKJ.js.gz +0 -0
  77. package/dist/shell/assets/grammar-DVeERVO3.js.br +0 -0
  78. package/dist/shell/assets/grammar-DVeERVO3.js.gz +0 -0
  79. package/dist/shell/assets/handlebars-BGFLy2DH.js.br +0 -0
  80. package/dist/shell/assets/handlebars-BGFLy2DH.js.gz +0 -0
  81. package/dist/shell/assets/html-CPJflvc5.js.br +0 -0
  82. package/dist/shell/assets/html-CPJflvc5.js.gz +0 -0
  83. package/dist/shell/assets/htmlMode-CjqzceBV.js.br +0 -0
  84. package/dist/shell/assets/htmlMode-CjqzceBV.js.gz +0 -0
  85. package/dist/shell/assets/index-DdrVWdNt.js +0 -292
  86. package/dist/shell/assets/index-DdrVWdNt.js.br +0 -0
  87. package/dist/shell/assets/index-DdrVWdNt.js.gz +0 -0
  88. package/dist/shell/assets/index-Dx-i3szQ.css +0 -1
  89. package/dist/shell/assets/index-Dx-i3szQ.css.br +0 -0
  90. package/dist/shell/assets/index-Dx-i3szQ.css.gz +0 -0
  91. package/dist/shell/assets/jsonMode-C2JxYuT6.js.br +0 -0
  92. package/dist/shell/assets/jsonMode-C2JxYuT6.js.gz +0 -0
  93. package/dist/shell/assets/liquid-BfXRgBm_.js.br +0 -0
  94. package/dist/shell/assets/liquid-BfXRgBm_.js.gz +0 -0
  95. package/dist/shell/assets/lspLanguageFeatures-CAi6hRgs.js.br +0 -0
  96. package/dist/shell/assets/lspLanguageFeatures-CAi6hRgs.js.gz +0 -0
  97. package/dist/shell/assets/mdx-DeBYGdge.js.br +0 -0
  98. package/dist/shell/assets/mdx-DeBYGdge.js.gz +0 -0
  99. package/dist/shell/assets/python-CFhHKm43.js.br +0 -0
  100. package/dist/shell/assets/python-CFhHKm43.js.gz +0 -0
  101. package/dist/shell/assets/razor-C-gkU4Y9.js.br +0 -0
  102. package/dist/shell/assets/razor-C-gkU4Y9.js.gz +0 -0
  103. package/dist/shell/assets/tsMode-8E7grKbo.js.br +0 -0
  104. package/dist/shell/assets/tsMode-8E7grKbo.js.gz +0 -0
  105. package/dist/shell/assets/xml-CBoTF2r1.js.br +0 -0
  106. package/dist/shell/assets/xml-CBoTF2r1.js.gz +0 -0
  107. package/dist/shell/assets/yaml-CyKxhzxl.js.br +0 -0
  108. package/dist/shell/assets/yaml-CyKxhzxl.js.gz +0 -0
package/README.md CHANGED
@@ -50,7 +50,7 @@ npm i -g toyon
50
50
  toyon ~/projects/app
51
51
  ```
52
52
 
53
- `toyon .` opens the folder you are in and `toyon --help` lists the rest. The install button in the top bar makes Toyon an app of its own in Chrome, Arc, Brave or Edge, with a Dock icon and no browser bar; from then on `toyon .` opens that. A global install keeps itself updated; `TOYON_UPDATES=off` stops it. Started with npx, Toyon offers the global install above the chat box once it has answered you. Run outside a project, Toyon opens with none: describe a new one in a sentence, or give the project picker a git URL to clone. `toyon https://github.com/you/app` opens it with that repository ready to clone into the folder you are in; a link to a branch, a file or a pull request on GitHub, GitLab or Codeberg is read back to its repository.
53
+ `toyon .` opens the folder you are in and `toyon --help` lists the rest. The install button in the top bar makes Toyon an app of its own in Chrome, Arc, Brave or Edge, with a Dock icon and no browser bar; from then on `toyon .` opens that. A global install keeps itself updated; `TOYON_UPDATES=off` stops it. Started with npx, Toyon offers the global install above the chat box once it has answered you. Run outside a project, Toyon opens with none: describe a new one in a sentence, or give the project picker a git URL to clone. `toyon https://github.com/you/app` opens it with that repository ready to clone into the folder you are in; a link to a branch, a file or a pull request on GitHub, GitLab or Codeberg is read back to its repository. `toyon send "fix the flaky test"` from a terminal inside a project sends that message into Toyon the way the chat box would: a new worktree from the main checkout, a take-over of a worktree Toyon does not run, or the chat of one it does; an agent running in that terminal can run it too, and `--carry` moves main's uncommitted changes along.
54
54
 
55
55
  You need:
56
56
 
@@ -81,14 +81,14 @@ A project with a page and an API behind it:
81
81
  "setup": ["npm install"],
82
82
  "run": {
83
83
  "web": "vite --port $PORT --strictPort",
84
- "api": { "cmd": "node --watch server.js", "from": "trunk" }
84
+ "api": "node --watch server/index.js"
85
85
  },
86
86
  "check": "npm test",
87
87
  "land": { "route": "pr" }
88
88
  }
89
89
  ```
90
90
 
91
- Each command gets its own `$PORT`, and the addresses of the others as `<NAME>_URL` (`API_URL` here), so the page can proxy to its API. The preview shows `web`. A command marked `from: "trunk"` runs once, in the main checkout, and every copy's page reaches that one until the copy's own changes touch it; then the copy starts its own. A copy that only changes the page costs one Vite.
91
+ Each command gets its own `$PORT`, and the addresses of the others as `<NAME>_URL` (`API_URL` here), so the page can proxy to its API. The preview shows `web`. A command that names a folder of the tree, `server/` here, runs once, in the main checkout, and every copy's page reaches that one until the copy's own changes touch that folder; then the copy starts its own. A copy that only changes the page costs one Vite.
92
92
 
93
93
  Copies start when you open them, and stop their servers when nobody has looked at them for a while; the chat and the agent keep going. Close the window and the daemon stops itself once nothing has needed it for half an hour; `toyon stop` stops it now, and everything it runs. `toyon doctor` says what is running and why a page cannot connect. Every setting, the port rules and the sleep delay are in [docs/settings.md](https://github.com/toyon-dev/toyon/blob/main/docs/settings.md).
94
94
 
package/dist/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  What changed in each release of Toyon, newest first.
4
4
 
5
+ ## 0.23.0 (2026-11-10)
6
+
7
+ The shell reads in Toyon Mono, a face of its own, and a worktree reaches main's servers by default instead of starting every command again.
8
+
9
+ ### New
10
+ - Code, the terminal, the editor and every other mono line read in Toyon Mono, a monospaced face drawn for Toyon and shipped with the shell, so the same letters show on every machine. The face is new and still being tuned; a letter that reads wrong is worth an issue.
11
+ - Main runs each command once, on its own working tree, and every worktree's page reaches it at its usual address. A worktree whose changes touch a command's files starts its own and the address quietly points there; one that only changes the page never pays for a server of its own. The page itself is never shared.
12
+ - When a command flips to a worktree, a card in the chat names the command and the file that caused it and offers the other places it could run: main's, or a remote named in settings. The chip under the composer follows the choice. A command moved back to main's by hand stays there until a further file under it changes, and it shows as preparing while its setup runs.
13
+ - `toyon send "fix the flaky test"` from a terminal inside a project sends that message into Toyon the way the chat box would: a new worktree from main, a take-over of a worktree Toyon does not run, or the chat of one it does. `--carry` brings main's uncommitted changes along, and an agent running in that terminal can run it too.
14
+ - A handoff row opens the plan page it came from: the eye control and the row menu offer open preview, open file, reveal and copy path.
15
+ - On a touch screen, a long press on plain transcript text selects it as the browser would. The message menu still opens on a link or a code block.
16
+
17
+ ### Changed
18
+ - `"paths": []` in settings is refused; write `"from": "trunk"` alone, which means the same thing: main runs the command and no file change flips it.
19
+ - The handoff going row lists each worktree by name as it is made, with its live dot once it exists, as the done row does. Handoff and worktrees tool rows read as a sentence, the piece titles or "the open ones and the newest archived", instead of a bare tool name.
20
+ - Asking the agent to split off, spin off or break out part of the work, or to put it in its own worktree, starts a handoff.
21
+ - Chat search ranks a hit that starts a word above one inside a longer word, so "rips" no longer sits level with "trips" and "strips", and the highlighted mark lands on the standalone word.
22
+ - opt+left and opt+right step the panel tabs when the focused field is empty, as cmd+left and cmd+right do. A field with text keeps the word jump.
23
+ - Under a picked option in your answer bubble, the option's description reads a step below the label and sits before the note you typed.
24
+ - Skill rows have a slash icon of their own, and a web search row wears the globe from the start instead of swapping to it once the call arrives.
25
+
26
+ ### Fixed
27
+ - The PR button offered create pr on a worktree whose branch already had a pull request. Toyon now finds the PR on GitHub when a turn settles and when the window returns; a merged one is taken only when its commits are in the worktree's own history, so a reused branch name cannot pull in a stranger's.
28
+ - A landed worktree with a merged PR and uncommitted changes still said land in the composer, the rail menu and the changes tab.
29
+ - The shine on a long running command's line was sized to the whole hidden command and flashed the entire visible line. It is now one glint of one width travelling at one speed.
30
+ - Restoring an old worktree whose settings differed from main's crashed. Each worktree now reads its own settings file, and a config reload restarts only the rows whose command changed.
31
+ - A row held open for a background command or a booked wakeup now keeps the machine awake and the worktree out of sleep, as a running turn does.
32
+
5
33
  ## 0.22.0 (2026-11-03)
6
34
 
7
35
  Your own messages and the agent's replies read the same way, with code, links and line breaks drawn as written, and the editor gains a split diff and an SVG preview.
package/dist/bridge.js CHANGED
@@ -1 +1 @@
1
- var v=[{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:"wt-back",key:"ArrowLeft",textKeeps:!0,emptyGives:!0},{id:"wt-forward",key:"ArrowRight",textKeeps:!0,emptyGives:!0},{id:"wt-archive",key:"Backspace",alt:!0,textKeeps:!0,emptyGives:!0},{id:"mark-unread",key:"u",alt:!0,textKeeps:!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"},{id:"back",key:"["},{id:"forward",key:"]"},{id:"close",key:"w"}],U=new Set(["zen","close","back","forward","wt-back","wt-forward"]);function q(e,{guest:t=!1}={}){if(e.altKey){if(e.metaKey||e.ctrlKey)return null;let r=v.find((o)=>o.alt&&!!o.shift===e.shiftKey&&(o.key===e.key||o.key.length===1&&e.code===`Key${o.key.toUpperCase()}`));return r&&r.id!=="worktree"?{id:r.id}:null}if(!e.metaKey&&!e.ctrlKey){if(e.shiftKey||t)return null;let r=v.find((o)=>o.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 v){if(r.id==="worktree")continue;let o=r.ctrlAlias;if(o&&e.ctrlKey&&o.key===n&&!!o.shift===e.shiftKey&&!(t&&o.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 Y(e){if(e.altKey||e.key.toLowerCase()!=="s")return!1;return!!e.ctrlKey!==e.metaKey}function Z(e){let t=v.find((n)=>n.id===e);if(!t)throw Error(`unknown chord ${e}`);return t}function V(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 se=Symbol.for("react.forward_ref"),ce=Symbol.for("react.memo");function J(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=J(t);if(n)return n}return null}function L(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===se)return t.displayName||L(t.render);if(t?.$$typeof===ce)return t.displayName||L(t.type);return null}var ue=(e)=>typeof e.type==="string"||e.tag===6,de=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function fe(e){let t=null,n=(r)=>{for(let o=r.child??null;o;o=o.sibling??null)if(ue(o)){if(t)return!1;t=o}else if(!n(o))return!1;return!0};return n(e)?t:null}function pe(e){for(let t=e;t;t=t.return){let n=J(t);if(n)return t._debugOwner===null?null:n}return null}function N(e){let t=_(e),n=null,r=null,o=!1;for(let i=e;i;i=i.return){let a=L(i.type);if(!a)continue;let l=!!e&&de(fe(i),e),c=pe(i);if(n&&!(l&&c))break;if(n=a,r=c,o=l,!l)break}if(r&&t&&r.file===t.file&&r.line===t.line)r=null;return{src:t,comp:n,call:r,wraps:o}}function F({src:e,call:t,wraps:n},r){let o=n?t:e,i=n?e:t;return(r?i??o:o??i)??null}if(window.__toyonBridge)throw Error("Toyon bridge already installed");window.__toyonBridge=!0;var E=window.__toyonShellOrigins??[],R=null,s=(e)=>{try{let t=R?[R]:E.length?E:["*"];for(let n of t)window.parent.postMessage({__toyon:!0,...e},n)}catch{}};s({type:"loaded",url:location.href,title:document.title});var x="#fa891e",ee="#1d2021";window.addEventListener("vite:afterUpdate",()=>s({type:"hmr"}));window.addEventListener("error",(e)=>{s({type:"page-error",message:String(e.message),source:e.filename,line:e.lineno})});window.addEventListener("unhandledrejection",(e)=>{s({type:"page-error",message:`unhandled rejection: ${String(e.reason)}`})});var C=()=>s({type:"navigated",url:location.href,title:document.title}),he=history.pushState.bind(history);history.pushState=(...e)=>{he(...e),H(),C()};var ye=history.replaceState.bind(history);history.replaceState=(...e)=>{ye(...e),C()};window.addEventListener("popstate",C);window.addEventListener("hashchange",C);var me=window.navigation,g=null;function H(){g=me?.currentEntry?.index??null}H();window.addEventListener("popstate",()=>{let e=g;H();let t=e===null||g===null||e===g?void 0:g<e?"back":"forward";s({type:"traversed",...t?{dir:t}:{}})});var ge=performance.getEntriesByType("navigation")[0];if(ge?.type==="back_forward")s({type:"traversed"});window.addEventListener("pageshow",(e)=>{if(e.persisted)s({type:"traversed"})});var M=document.title;if(document.head)new MutationObserver(()=>{if(document.title===M)return;M=document.title,s({type:"title",title:M})}).observe(document.head,{childList:!0,subtree:!0,characterData:!0});var te=!1,B=null;window.addEventListener("keyup",(e)=>{if(window.__toyonShell||e.key!==B)return;B=null,s({type:"key",key:e.key,meta:!1,up:!0})},!0);window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;if(Y(e))e.preventDefault();let t=q(e,{guest:!0});if(t&&Z(t.id).textKeeps&&V(e.target))return;if(te){if(!t||!U.has(t.id))return}else if(e.key==="Escape"){s({type:"key",key:"Escape",meta:!1});return}else if(!t)return;e.preventDefault(),e.stopPropagation(),s({type:"key",key:e.key,code:e.code,meta:e.metaKey,ctrl:e.ctrlKey,shift:e.shiftKey,alt:e.altKey}),B=e.altKey?"Alt":e.ctrlKey?"Control":e.metaKey?"Meta":null},!0);var I=()=>s({type:"focus",gesture:navigator.userActivation?.isActive??!0});window.addEventListener("focusin",I,!0);window.addEventListener("focus",I);if(document.hasFocus()&&document.activeElement&&document.activeElement!==document.body)I();var W=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!W(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="copy";s({type:"drag-files",over:!0})});window.addEventListener("dragleave",(e)=>{if(W(e))s({type:"drag-files",over:!1})});window.addEventListener("drop",(e)=>{if(!W(e))return;e.preventDefault(),s({type:"drop-files",files:Array.from(e.dataTransfer?.files??[])})});function G(e){for(let t of Object.keys(e))if(t.startsWith("__reactFiber$"))return e[t]??null;return null}var u=null,D=typeof HTMLElement<"u"&&"showPopover"in HTMLElement.prototype;function ke(){if(!u?.isConnected){if(u=document.createElement("div"),u.style.cssText="position:fixed;inset:0;width:auto;height:auto;max-width:none;max-height:none;margin:0;padding:0;border:0;background:transparent;overflow:visible;pointer-events:none;z-index:2147483647;",D)u.popover="manual";document.documentElement.appendChild(u)}if(D&&!u.matches(":popover-open"))u.showPopover();return u}function m(){if(!u)return;if(u.innerHTML="",D&&u.matches(":popover-open"))u.hidePopover()}var O=20;function S(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 o=e.top>=O,i=e.bottom+O<=window.innerHeight;if(t.style.top=o?`${-O}px`:i?`${e.height+4}px`:"2px",!o&&!i)t.style.left="2px";r.appendChild(t)}if(ke().appendChild(r),t){let o=t.getBoundingClientRect(),i=o.right-(window.innerWidth-2);if(i>0){let a=Number.parseFloat(t.style.left||"0");t.style.left=`${a-Math.min(i,Math.max(0,o.left-2))}px`}}}function k(e,t){let n=document.createElement("div");if(n.textContent=e,n.style.cssText=`position:absolute;left:0;background:${x};color:${ee};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 A=!1,f=null,h=!1,p=!1,y=!1,P=(e)=>`${oe(e.file)}${e.line?`:${e.line}`:""}`;function K(e){f=e,m();let t=N(G(e)),{src:n,comp:r,call:o}=t,i=F(t,p),a=i===n?o:n,l=h!==y,c=(...b)=>b.filter(Boolean).join(" ")||void 0,d=l?i?k(`open ${P(i)}`,c(a&&`⇧ ${P(a)}`,y&&"⌥ chat")):k(`find ${Q(e)}`,c(y&&"⌥ chat")):k(r?`<${r} />${i?` · ${P(i)}`:""}`:Q(e),c(!y&&"⌥ code"));S(e.getBoundingClientRect(),d,l)}function Q(e){let t=e.tagName.toLowerCase(),n=e.classList[0];return(e.id?`${t}#${e.id}`:n?`${t}.${n}`:t).slice(0,48)}var we=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function be(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&&(we.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 ne(e){let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t!==f||e.altKey!==h||e.shiftKey!==p;if(h=e.altKey,p=e.shiftKey,n)K(t)}function re(e){e.preventDefault(),e.stopPropagation();let t=f??document.elementFromPoint(e.clientX,e.clientY),n=N(t?G(t):null),{src:r,comp:o,call:i}=n;p=e.shiftKey;let a=F(n,p),l=e.altKey!==y;if(X(),!t)return;s({type:"picked",verb:l?"code":"chat",site:a&&a===i?"call":"source",component:o,file:r?.file??null,line:r?.line??null,callFile:i?.file??null,callLine:i?.line??null,selector:Ee(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:be(t)})}function T(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),X(),s({type:"pick-cancel"});return}if((e.key==="Alt"||e.key==="Shift")&&(h!==e.altKey||p!==e.shiftKey)){if(h=e.altKey,p=e.shiftKey,f)K(f)}}function ve(e){if(y=e,A){if(f)K(f);return}A=!0,f=null,h=!1,p=!1,document.addEventListener("mousemove",ne,!0),document.addEventListener("click",re,!0),document.addEventListener("keydown",T,!0),document.addEventListener("keyup",T,!0),document.documentElement.style.cursor="crosshair"}function X(){A=!1,y=!1,f=null,h=!1,p=!1,m(),document.removeEventListener("mousemove",ne,!0),document.removeEventListener("click",re,!0),document.removeEventListener("keydown",T,!0),document.removeEventListener("keyup",T,!0),document.documentElement.style.cursor=""}function Ee(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 o=n.parentElement,i=o?Array.from(o.children).indexOf(n)+1:1;t.unshift(`${n.tagName.toLowerCase()}:nth-child(${i})`),n=o}return t.join(" > ")}function oe(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function xe(e,t){return e.endsWith(t)||t.endsWith(oe(e))}function Se(e,t){let n=[],r=0;for(let a of Array.from(document.querySelectorAll("*"))){let l=_(G(a));if(l)r++;if(!l||!xe(l.file,e))continue;n.push({el:a,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 a=t[0][0],l=n.filter((d)=>d.line===a);if(l.length>0)return{matched:l,fromFile:n,withSource:r};let c=n.filter((d)=>d.line>0&&d.line<a);return c.sort((d,b)=>b.line-d.line),{matched:c.slice(0,1),fromFile:n,withSource:r}}return{matched:n.filter((a)=>t.some(([l,c])=>a.line>=l-8&&a.line<=c+1)),fromFile:n,withSource:r}}function Ae(e,t){m();let{matched:n,fromFile:r,withSource:o}=Se(e,t),i=0;for(let{el:a}of n){if(i>=40)break;let l=a.getBoundingClientRect();if(l.width>0&&l.height>0)S(l),i++}if(i===0)s({type:"highlight-miss",path:e,fileMatched:r.length,withSource:o,ranges:t})}var ie=!1,w=!1,Te=(e)=>{for(let t=e;t&&t!==document.documentElement;t=t.parentElement){let n=getComputedStyle(t),r=n.overflowX;if((r==="auto"||r==="scroll")&&t.scrollWidth>t.clientWidth+1)return!0;if(window.__toyonShell)continue;let o=n.touchAction;if(o!=="auto"&&o!=="manipulation"&&!o.includes("pan-x"))return!0}return!1},le=(e,t)=>{let n=e.touches[0]??e.changedTouches[0];if(n)s({type:"touch",phase:t,x:n.clientX,y:n.clientY})};window.addEventListener("touchstart",(e)=>{if(w=!1,!ie||e.touches.length!==1)return;let t=e.target instanceof Element?e.target:null;if(t?.closest("input, textarea, [contenteditable]")||Te(t))return;w=!0,le(e,"start")},{capture:!0,passive:!0});var j=(e,t)=>{if(!w)return;setTimeout(()=>{if(!w)return;let n=t==="move"&&(e.defaultPrevented||e.touches.length!==1);if(t!=="move"||n)w=!1;le(e,n?"cancel":t)},0)};window.addEventListener("touchmove",(e)=>j(e,"move"),{passive:!0});window.addEventListener("touchend",(e)=>j(e,"end"),!0);window.addEventListener("touchcancel",(e)=>j(e,"cancel"),!0);window.addEventListener("message",(e)=>{if(e.source!==window.parent)return;if(E.length&&!E.includes(e.origin))return;let t=e.data;if(!t?.__toyon)return;R=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":case"forward":{let r=window.navigation;if((n.type==="back"?r?.canGoBack:r?.canGoForward)===!1)break;if(n.type==="back")history.back();else history.forward();break}case"touches":ie=n.on;break;case"links":{let r=new Set,o=[];for(let i of Array.from(document.querySelectorAll("a[href]"))){if(i.origin!==location.origin||i.target==="_blank"||i.hasAttribute("download"))continue;let a=i.pathname+(i.hash.startsWith("#/")?i.hash:"");if(a.startsWith("/__toyon")||r.has(a))continue;r.add(a);let l=(i.textContent||i.getAttribute("aria-label")||"").replace(/\s+/g," ").trim();if(o.push({path:a,text:l.slice(0,80)}),o.length>=200)break}s({type:"links",links:o});break}case"pick-start":ve(n.verb==="code");break;case"pick-mods":if(A&&(h!==n.alt||p!==n.shift)){if(h=n.alt,p=n.shift,f)K(f)}break;case"pick-cancel":X();break;case"highlight-file":Ae(n.path,n.ranges??null);break;case"highlight-computed":{m();let r=/^(color|font|line-height|letter-|text-|word-)/,o=(l)=>{if(/^(INPUT|TEXTAREA|SELECT)$/.test(l.tagName))return!0;for(let c=l.firstChild;c;c=c.nextSibling)if(c.nodeType===3&&c.textContent&&c.textContent.trim())return!0;return!1},i=document.querySelectorAll("*"),a=!0;for(let l=0;l<i.length;l++){let c=getComputedStyle(i[l]),d=([z,ae])=>c.getPropertyValue(z)===ae&&(!r.test(z)||o(i[l]));if(n.match==="any"?n.props.some(d):n.props.every(d))S(i[l].getBoundingClientRect(),a&&n.label?k(n.label):void 0),a=!1}break}case"highlight-selector":{m();try{let r=document.querySelectorAll(n.selector);for(let o=0;o<r.length;o++)S(r[o].getBoundingClientRect(),o===0&&n.label?k(n.label):void 0)}catch{}break}case"highlight-clear":m();break;case"zen":te=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))ee=n.accentFg;break}});
1
+ var v=[{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,emptyGives:!0},{id:"panel-tab-next",key:"ArrowRight",alt:!0,textKeeps:!0,emptyGives:!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:"wt-back",key:"ArrowLeft",textKeeps:!0,emptyGives:!0},{id:"wt-forward",key:"ArrowRight",textKeeps:!0,emptyGives:!0},{id:"wt-archive",key:"Backspace",alt:!0,textKeeps:!0,emptyGives:!0},{id:"mark-unread",key:"u",alt:!0,textKeeps:!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"},{id:"back",key:"["},{id:"forward",key:"]"},{id:"close",key:"w"}],U=new Set(["zen","close","back","forward","wt-back","wt-forward"]);function q(e,{guest:t=!1}={}){if(e.altKey){if(e.metaKey||e.ctrlKey)return null;let r=v.find((o)=>o.alt&&!!o.shift===e.shiftKey&&(o.key===e.key||o.key.length===1&&e.code===`Key${o.key.toUpperCase()}`));return r&&r.id!=="worktree"?{id:r.id}:null}if(!e.metaKey&&!e.ctrlKey){if(e.shiftKey||t)return null;let r=v.find((o)=>o.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 v){if(r.id==="worktree")continue;let o=r.ctrlAlias;if(o&&e.ctrlKey&&o.key===n&&!!o.shift===e.shiftKey&&!(t&&o.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 Y(e){if(e.altKey||e.key.toLowerCase()!=="s")return!1;return!!e.ctrlKey!==e.metaKey}function Z(e){let t=v.find((n)=>n.id===e);if(!t)throw Error(`unknown chord ${e}`);return t}function V(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 se=Symbol.for("react.forward_ref"),ce=Symbol.for("react.memo");function J(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=J(t);if(n)return n}return null}function L(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===se)return t.displayName||L(t.render);if(t?.$$typeof===ce)return t.displayName||L(t.type);return null}var ue=(e)=>typeof e.type==="string"||e.tag===6,de=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function fe(e){let t=null,n=(r)=>{for(let o=r.child??null;o;o=o.sibling??null)if(ue(o)){if(t)return!1;t=o}else if(!n(o))return!1;return!0};return n(e)?t:null}function pe(e){for(let t=e;t;t=t.return){let n=J(t);if(n)return t._debugOwner===null?null:n}return null}function N(e){let t=_(e),n=null,r=null,o=!1;for(let i=e;i;i=i.return){let a=L(i.type);if(!a)continue;let l=!!e&&de(fe(i),e),c=pe(i);if(n&&!(l&&c))break;if(n=a,r=c,o=l,!l)break}if(r&&t&&r.file===t.file&&r.line===t.line)r=null;return{src:t,comp:n,call:r,wraps:o}}function F({src:e,call:t,wraps:n},r){let o=n?t:e,i=n?e:t;return(r?i??o:o??i)??null}if(window.__toyonBridge)throw Error("Toyon bridge already installed");window.__toyonBridge=!0;var E=window.__toyonShellOrigins??[],R=null,s=(e)=>{try{let t=R?[R]:E.length?E:["*"];for(let n of t)window.parent.postMessage({__toyon:!0,...e},n)}catch{}};s({type:"loaded",url:location.href,title:document.title});var x="#fa891e",ee="#1d2021";window.addEventListener("vite:afterUpdate",()=>s({type:"hmr"}));window.addEventListener("error",(e)=>{s({type:"page-error",message:String(e.message),source:e.filename,line:e.lineno})});window.addEventListener("unhandledrejection",(e)=>{s({type:"page-error",message:`unhandled rejection: ${String(e.reason)}`})});var C=()=>s({type:"navigated",url:location.href,title:document.title}),he=history.pushState.bind(history);history.pushState=(...e)=>{he(...e),H(),C()};var ye=history.replaceState.bind(history);history.replaceState=(...e)=>{ye(...e),C()};window.addEventListener("popstate",C);window.addEventListener("hashchange",C);var me=window.navigation,g=null;function H(){g=me?.currentEntry?.index??null}H();window.addEventListener("popstate",()=>{let e=g;H();let t=e===null||g===null||e===g?void 0:g<e?"back":"forward";s({type:"traversed",...t?{dir:t}:{}})});var ge=performance.getEntriesByType("navigation")[0];if(ge?.type==="back_forward")s({type:"traversed"});window.addEventListener("pageshow",(e)=>{if(e.persisted)s({type:"traversed"})});var M=document.title;if(document.head)new MutationObserver(()=>{if(document.title===M)return;M=document.title,s({type:"title",title:M})}).observe(document.head,{childList:!0,subtree:!0,characterData:!0});var te=!1,B=null;window.addEventListener("keyup",(e)=>{if(window.__toyonShell||e.key!==B)return;B=null,s({type:"key",key:e.key,meta:!1,up:!0})},!0);window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;if(Y(e))e.preventDefault();let t=q(e,{guest:!0});if(t&&Z(t.id).textKeeps&&V(e.target))return;if(te){if(!t||!U.has(t.id))return}else if(e.key==="Escape"){s({type:"key",key:"Escape",meta:!1});return}else if(!t)return;e.preventDefault(),e.stopPropagation(),s({type:"key",key:e.key,code:e.code,meta:e.metaKey,ctrl:e.ctrlKey,shift:e.shiftKey,alt:e.altKey}),B=e.altKey?"Alt":e.ctrlKey?"Control":e.metaKey?"Meta":null},!0);var I=()=>s({type:"focus",gesture:navigator.userActivation?.isActive??!0});window.addEventListener("focusin",I,!0);window.addEventListener("focus",I);if(document.hasFocus()&&document.activeElement&&document.activeElement!==document.body)I();var G=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!G(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="copy";s({type:"drag-files",over:!0})});window.addEventListener("dragleave",(e)=>{if(G(e))s({type:"drag-files",over:!1})});window.addEventListener("drop",(e)=>{if(!G(e))return;e.preventDefault(),s({type:"drop-files",files:Array.from(e.dataTransfer?.files??[])})});function W(e){for(let t of Object.keys(e))if(t.startsWith("__reactFiber$"))return e[t]??null;return null}var u=null,D=typeof HTMLElement<"u"&&"showPopover"in HTMLElement.prototype;function ke(){if(!u?.isConnected){if(u=document.createElement("div"),u.style.cssText="position:fixed;inset:0;width:auto;height:auto;max-width:none;max-height:none;margin:0;padding:0;border:0;background:transparent;overflow:visible;pointer-events:none;z-index:2147483647;",D)u.popover="manual";document.documentElement.appendChild(u)}if(D&&!u.matches(":popover-open"))u.showPopover();return u}function m(){if(!u)return;if(u.innerHTML="",D&&u.matches(":popover-open"))u.hidePopover()}var O=20;function S(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 o=e.top>=O,i=e.bottom+O<=window.innerHeight;if(t.style.top=o?`${-O}px`:i?`${e.height+4}px`:"2px",!o&&!i)t.style.left="2px";r.appendChild(t)}if(ke().appendChild(r),t){let o=t.getBoundingClientRect(),i=o.right-(window.innerWidth-2);if(i>0){let a=Number.parseFloat(t.style.left||"0");t.style.left=`${a-Math.min(i,Math.max(0,o.left-2))}px`}}}function k(e,t){let n=document.createElement("div");if(n.textContent=e,n.style.cssText=`position:absolute;left:0;background:${x};color:${ee};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 A=!1,f=null,h=!1,p=!1,y=!1,P=(e)=>`${oe(e.file)}${e.line?`:${e.line}`:""}`;function K(e){f=e,m();let t=N(W(e)),{src:n,comp:r,call:o}=t,i=F(t,p),a=i===n?o:n,l=h!==y,c=(...b)=>b.filter(Boolean).join(" ")||void 0,d=l?i?k(`open ${P(i)}`,c(a&&`⇧ ${P(a)}`,y&&"⌥ chat")):k(`find ${Q(e)}`,c(y&&"⌥ chat")):k(r?`<${r} />${i?` · ${P(i)}`:""}`:Q(e),c(!y&&"⌥ code"));S(e.getBoundingClientRect(),d,l)}function Q(e){let t=e.tagName.toLowerCase(),n=e.classList[0];return(e.id?`${t}#${e.id}`:n?`${t}.${n}`:t).slice(0,48)}var we=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function be(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&&(we.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 ne(e){let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t!==f||e.altKey!==h||e.shiftKey!==p;if(h=e.altKey,p=e.shiftKey,n)K(t)}function re(e){e.preventDefault(),e.stopPropagation();let t=f??document.elementFromPoint(e.clientX,e.clientY),n=N(t?W(t):null),{src:r,comp:o,call:i}=n;p=e.shiftKey;let a=F(n,p),l=e.altKey!==y;if(X(),!t)return;s({type:"picked",verb:l?"code":"chat",site:a&&a===i?"call":"source",component:o,file:r?.file??null,line:r?.line??null,callFile:i?.file??null,callLine:i?.line??null,selector:Ee(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:be(t)})}function T(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),X(),s({type:"pick-cancel"});return}if((e.key==="Alt"||e.key==="Shift")&&(h!==e.altKey||p!==e.shiftKey)){if(h=e.altKey,p=e.shiftKey,f)K(f)}}function ve(e){if(y=e,A){if(f)K(f);return}A=!0,f=null,h=!1,p=!1,document.addEventListener("mousemove",ne,!0),document.addEventListener("click",re,!0),document.addEventListener("keydown",T,!0),document.addEventListener("keyup",T,!0),document.documentElement.style.cursor="crosshair"}function X(){A=!1,y=!1,f=null,h=!1,p=!1,m(),document.removeEventListener("mousemove",ne,!0),document.removeEventListener("click",re,!0),document.removeEventListener("keydown",T,!0),document.removeEventListener("keyup",T,!0),document.documentElement.style.cursor=""}function Ee(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 o=n.parentElement,i=o?Array.from(o.children).indexOf(n)+1:1;t.unshift(`${n.tagName.toLowerCase()}:nth-child(${i})`),n=o}return t.join(" > ")}function oe(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function xe(e,t){return e.endsWith(t)||t.endsWith(oe(e))}function Se(e,t){let n=[],r=0;for(let a of Array.from(document.querySelectorAll("*"))){let l=_(W(a));if(l)r++;if(!l||!xe(l.file,e))continue;n.push({el:a,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 a=t[0][0],l=n.filter((d)=>d.line===a);if(l.length>0)return{matched:l,fromFile:n,withSource:r};let c=n.filter((d)=>d.line>0&&d.line<a);return c.sort((d,b)=>b.line-d.line),{matched:c.slice(0,1),fromFile:n,withSource:r}}return{matched:n.filter((a)=>t.some(([l,c])=>a.line>=l-8&&a.line<=c+1)),fromFile:n,withSource:r}}function Ae(e,t){m();let{matched:n,fromFile:r,withSource:o}=Se(e,t),i=0;for(let{el:a}of n){if(i>=40)break;let l=a.getBoundingClientRect();if(l.width>0&&l.height>0)S(l),i++}if(i===0)s({type:"highlight-miss",path:e,fileMatched:r.length,withSource:o,ranges:t})}var ie=!1,w=!1,Te=(e)=>{for(let t=e;t&&t!==document.documentElement;t=t.parentElement){let n=getComputedStyle(t),r=n.overflowX;if((r==="auto"||r==="scroll")&&t.scrollWidth>t.clientWidth+1)return!0;if(window.__toyonShell)continue;let o=n.touchAction;if(o!=="auto"&&o!=="manipulation"&&!o.includes("pan-x"))return!0}return!1},le=(e,t)=>{let n=e.touches[0]??e.changedTouches[0];if(n)s({type:"touch",phase:t,x:n.clientX,y:n.clientY})};window.addEventListener("touchstart",(e)=>{if(w=!1,!ie||e.touches.length!==1)return;let t=e.target instanceof Element?e.target:null;if(t?.closest("input, textarea, [contenteditable]")||Te(t))return;w=!0,le(e,"start")},{capture:!0,passive:!0});var j=(e,t)=>{if(!w)return;setTimeout(()=>{if(!w)return;let n=t==="move"&&(e.defaultPrevented||e.touches.length!==1);if(t!=="move"||n)w=!1;le(e,n?"cancel":t)},0)};window.addEventListener("touchmove",(e)=>j(e,"move"),{passive:!0});window.addEventListener("touchend",(e)=>j(e,"end"),!0);window.addEventListener("touchcancel",(e)=>j(e,"cancel"),!0);window.addEventListener("message",(e)=>{if(e.source!==window.parent)return;if(E.length&&!E.includes(e.origin))return;let t=e.data;if(!t?.__toyon)return;R=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":case"forward":{let r=window.navigation;if((n.type==="back"?r?.canGoBack:r?.canGoForward)===!1)break;if(n.type==="back")history.back();else history.forward();break}case"touches":ie=n.on;break;case"links":{let r=new Set,o=[];for(let i of Array.from(document.querySelectorAll("a[href]"))){if(i.origin!==location.origin||i.target==="_blank"||i.hasAttribute("download"))continue;let a=i.pathname+(i.hash.startsWith("#/")?i.hash:"");if(a.startsWith("/__toyon")||r.has(a))continue;r.add(a);let l=(i.textContent||i.getAttribute("aria-label")||"").replace(/\s+/g," ").trim();if(o.push({path:a,text:l.slice(0,80)}),o.length>=200)break}s({type:"links",links:o});break}case"pick-start":ve(n.verb==="code");break;case"pick-mods":if(A&&(h!==n.alt||p!==n.shift)){if(h=n.alt,p=n.shift,f)K(f)}break;case"pick-cancel":X();break;case"highlight-file":Ae(n.path,n.ranges??null);break;case"highlight-computed":{m();let r=/^(color|font|line-height|letter-|text-|word-)/,o=(l)=>{if(/^(INPUT|TEXTAREA|SELECT)$/.test(l.tagName))return!0;for(let c=l.firstChild;c;c=c.nextSibling)if(c.nodeType===3&&c.textContent&&c.textContent.trim())return!0;return!1},i=document.querySelectorAll("*"),a=!0;for(let l=0;l<i.length;l++){let c=getComputedStyle(i[l]),d=([z,ae])=>c.getPropertyValue(z)===ae&&(!r.test(z)||o(i[l]));if(n.match==="any"?n.props.some(d):n.props.every(d))S(i[l].getBoundingClientRect(),a&&n.label?k(n.label):void 0),a=!1}break}case"highlight-selector":{m();try{let r=document.querySelectorAll(n.selector);for(let o=0;o<r.length;o++)S(r[o].getBoundingClientRect(),o===0&&n.label?k(n.label):void 0)}catch{}break}case"highlight-clear":m();break;case"zen":te=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))ee=n.accentFg;break}});
package/dist/cli.js CHANGED
@@ -5290,7 +5290,7 @@ function parseVersion(v) {
5290
5290
  // package.json
5291
5291
  var package_default = {
5292
5292
  name: "toyon",
5293
- version: "0.22.0",
5293
+ version: "0.23.0",
5294
5294
  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.",
5295
5295
  license: "MIT",
5296
5296
  type: "module",
@@ -5644,6 +5644,7 @@ var VERBS = new Set([
5644
5644
  "uninstall",
5645
5645
  "remote",
5646
5646
  "pair",
5647
+ "send",
5647
5648
  "deploy",
5648
5649
  "help"
5649
5650
  ]);
@@ -5704,6 +5705,8 @@ function parseArgs(argv) {
5704
5705
  }
5705
5706
  return { kind: "remote", to, ports, tailscale };
5706
5707
  }
5708
+ case "send":
5709
+ return parseSend(rest);
5707
5710
  case "deploy":
5708
5711
  return parseDeploy(rest);
5709
5712
  }
@@ -5735,6 +5738,30 @@ function parseLogs(rest) {
5735
5738
  }
5736
5739
  return { kind: "logs", follow, lines };
5737
5740
  }
5741
+ function parseSend(rest) {
5742
+ let text = null;
5743
+ let file = null;
5744
+ let carry = false;
5745
+ for (let i = 0;i < rest.length; i++) {
5746
+ const a = rest[i];
5747
+ if (a === "--file" || a === "-f") {
5748
+ const value = rest[++i];
5749
+ if (!value)
5750
+ return { kind: "error", message: `${a} needs a path` };
5751
+ file = value;
5752
+ } else if (a === "--carry")
5753
+ carry = true;
5754
+ else if (a.startsWith("-"))
5755
+ return { kind: "error", message: `unknown option ${a}` };
5756
+ else if (text !== null)
5757
+ return { kind: "error", message: "toyon send takes one message; quote it" };
5758
+ else
5759
+ text = a;
5760
+ }
5761
+ if (text !== null && file !== null)
5762
+ return { kind: "error", message: "toyon send takes the message as text or from --file, not both" };
5763
+ return { kind: "send", text, file, carry };
5764
+ }
5738
5765
  var FLY_APP = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;
5739
5766
  function parseDeploy(rest) {
5740
5767
  const error = (message) => ({ kind: "error", message });
@@ -5787,6 +5814,10 @@ usage
5787
5814
  toyon <git url> open the shell with that repository ready to clone into the current
5788
5815
  directory; a page on GitHub, GitLab or Codeberg is read back to its
5789
5816
  repository, and to its branch
5817
+ toyon send [text] send a message to Toyon about the current directory: a new worktree
5818
+ of its project, a take-over of a worktree Toyon does not run, or the
5819
+ chat of one it does; the text, --file <path>, or stdin
5820
+ --carry move main's uncommitted changes into the worktree started for it
5790
5821
  toyon start start the daemon if it is not running, and open nothing
5791
5822
  toyon stop stop the daemon and every dev server and agent it runs
5792
5823
  toyon restart stop the daemon and start it again from what is installed now; every
@@ -6887,15 +6918,71 @@ async function restart() {
6887
6918
  return 0;
6888
6919
  }
6889
6920
 
6921
+ // src/send.ts
6922
+ import { readFileSync as readFileSync8 } from "fs";
6923
+ function sentBy(env = process.env) {
6924
+ return env.CLAUDECODE || env.CLAUDE_CODE_ENTRYPOINT ? "Claude Code" : undefined;
6925
+ }
6926
+ async function messageOf(cmd) {
6927
+ if (cmd.text !== null)
6928
+ return cmd.text;
6929
+ if (cmd.file !== null)
6930
+ return readFileSync8(cmd.file, "utf8");
6931
+ if (process.stdin.isTTY)
6932
+ return null;
6933
+ return await Bun.stdin.text();
6934
+ }
6935
+ async function send(cmd) {
6936
+ let text;
6937
+ try {
6938
+ text = await messageOf(cmd);
6939
+ } catch (e) {
6940
+ console.error(`toyon: could not read ${cmd.file}: ${e.message}`);
6941
+ return 1;
6942
+ }
6943
+ if (!text?.trim()) {
6944
+ console.error("toyon: give the message as text, with --file, or on stdin");
6945
+ return 2;
6946
+ }
6947
+ const daemon = await ensureDaemon();
6948
+ if (!daemon)
6949
+ return 1;
6950
+ const by = sentBy();
6951
+ const res = await post("/send", daemon.token, {
6952
+ path: process.cwd(),
6953
+ text,
6954
+ ...by ? { by } : {},
6955
+ ...cmd.carry ? { carry: true } : {}
6956
+ });
6957
+ if (!res.ok) {
6958
+ console.error(`could not send: ${await res.text()}`);
6959
+ return 1;
6960
+ }
6961
+ const reply = await res.json();
6962
+ console.log(sentLine(reply));
6963
+ if (reply.delivered)
6964
+ focusShell();
6965
+ else
6966
+ openShell(daemon);
6967
+ return 0;
6968
+ }
6969
+ function sentLine(reply) {
6970
+ if (reply.kind === "sent")
6971
+ return `toyon: sent to ${reply.title} in Toyon`;
6972
+ const stayed = reply.stayed && reply.stayed > 0 ? `; ${reply.stayed} uncommitted ${reply.stayed === 1 ? "file" : "files"} stayed on main, --carry moves them` : "";
6973
+ const notice = reply.notice ? `; ${reply.notice}` : "";
6974
+ return `toyon: ${reply.title} is open in Toyon${stayed}${notice}`;
6975
+ }
6976
+
6890
6977
  // src/uninstall.ts
6891
- import { existsSync as existsSync12, readFileSync as readFileSync8, rmSync as rmSync4 } from "fs";
6978
+ import { existsSync as existsSync12, readFileSync as readFileSync9, rmSync as rmSync4 } from "fs";
6892
6979
  import { join as join7 } from "path";
6893
6980
  function readState() {
6894
6981
  const file = join7(home, DAEMON_FILES.state);
6895
6982
  if (!existsSync12(file))
6896
6983
  return {};
6897
6984
  try {
6898
- return JSON.parse(readFileSync8(file, "utf8"));
6985
+ return JSON.parse(readFileSync9(file, "utf8"));
6899
6986
  } catch {
6900
6987
  return {};
6901
6988
  }
@@ -7137,6 +7224,8 @@ async function run(cmd) {
7137
7224
  return remote(cmd);
7138
7225
  case "pair":
7139
7226
  return pair();
7227
+ case "send":
7228
+ return send(cmd);
7140
7229
  case "deploy":
7141
7230
  return deploy(cmd);
7142
7231
  case "open":