toyon 0.6.0 → 0.7.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.
- package/README.md +5 -5
- package/dist/bridge.js +1 -1
- package/dist/cli.js +104 -21
- package/dist/daemon.js +3280 -999
- package/dist/shell/assets/{Editor-D5UJRxLO.js → Editor-Duhn2F88.js} +189 -189
- package/dist/shell/assets/{XTerm-l6IDHxt8.js → XTerm-CF8bkkwi.js} +12 -12
- package/dist/shell/assets/{cssMode-DIt1Onbo.js → cssMode-CaBWxaDj.js} +1 -1
- package/dist/shell/assets/{freemarker2-BlnMjxhl.js → freemarker2-Qj5oMLk2.js} +1 -1
- package/dist/shell/assets/{grammar-xCgG7hS1.js → grammar-YjPoOd1d.js} +1 -1
- package/dist/shell/assets/{handlebars-CgcpCzmy.js → handlebars-N_jFNLBH.js} +1 -1
- package/dist/shell/assets/{html-yqzA9zjA.js → html-CuTufuXa.js} +1 -1
- package/dist/shell/assets/{htmlMode-AyUHvgCk.js → htmlMode-DzHlP1s-.js} +1 -1
- package/dist/shell/assets/index-BWSk_4yc.js +250 -0
- package/dist/shell/assets/index-C01XmhdL.css +1 -0
- package/dist/shell/assets/{javascript-CYZ-NuGG.js → javascript-DBXFKiXL.js} +1 -1
- package/dist/shell/assets/{jsonMode-BpybSxrR.js → jsonMode-DVynVZZ-.js} +1 -1
- package/dist/shell/assets/{liquid-BHHjN7T9.js → liquid-CPflmua8.js} +1 -1
- package/dist/shell/assets/{lspLanguageFeatures-CHyCsA1P.js → lspLanguageFeatures-Bw23HdhQ.js} +1 -1
- package/dist/shell/assets/{mdx-CCgYQauJ.js → mdx-BIo7iUIS.js} +1 -1
- package/dist/shell/assets/{python-C1JulLv8.js → python-w7xWVunv.js} +1 -1
- package/dist/shell/assets/{razor-Dj4sWgNm.js → razor-C_h6ql0l.js} +1 -1
- package/dist/shell/assets/{tsMode-D1gKgsY6.js → tsMode-BD-oIhVs.js} +1 -1
- package/dist/shell/assets/{xml-BHUNgL0o.js → xml-BDJjSxEs.js} +1 -1
- package/dist/shell/assets/{yaml-CetvwW8L.js → yaml-BXfVW0R6.js} +1 -1
- package/dist/shell/index.html +2 -2
- package/package.json +1 -1
- package/dist/shell/assets/index-BGLn9_S8.js +0 -241
- package/dist/shell/assets/index-Cm07OHxH.css +0 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ In Toyon you point at a button in the page and ask for it to be bigger, watch it
|
|
|
24
24
|
|
|
25
25
|
Each copy is a branch and a git worktree with your dependencies and `.env` files; one spare per project is kept warm.
|
|
26
26
|
|
|
27
|
-
Point at anything on the page to talk about it or open the line that draws it, and the design pane maps it to your tokens and components.
|
|
27
|
+
Point at anything on the page to talk about it or open the line that draws it, and the design pane maps it to your tokens and components. What the agent is told about the page, and the keys, are in [docs/preview.md](https://github.com/toyon-dev/toyon/blob/main/docs/preview.md).
|
|
28
28
|
|
|
29
29
|
One Toyon holds every project you open, and the list of chats shows which one needs you.
|
|
30
30
|
|
|
@@ -65,7 +65,7 @@ Each agent signs in from the chat. Claude Code and Codex install on first start;
|
|
|
65
65
|
|---|---|---|
|
|
66
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
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 |
|
|
68
|
+
| Lovable, v0 or Bolt | The loop: a chat and the page it changes, and pointing at an element to talk about it | Your own project on your machine, with your database, Docker and private packages; each chat is a branch in your repository |
|
|
69
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
|
|
@@ -79,16 +79,16 @@ A project with a page and an API behind it:
|
|
|
79
79
|
"setup": ["npm install"],
|
|
80
80
|
"run": {
|
|
81
81
|
"web": "vite --port $PORT --strictPort",
|
|
82
|
-
"api": "node --watch server.js"
|
|
82
|
+
"api": { "cmd": "node --watch server.js", "from": "trunk" }
|
|
83
83
|
},
|
|
84
84
|
"check": "npm test",
|
|
85
85
|
"land": { "route": "pr" }
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
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`.
|
|
89
|
+
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.
|
|
90
90
|
|
|
91
|
-
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. `toyon stop` stops
|
|
91
|
+
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).
|
|
92
92
|
|
|
93
93
|
## What it does not do
|
|
94
94
|
|
package/dist/bridge.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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"},{id:"back",key:"ArrowLeft",textKeeps:!0},{id:"forward",key:"ArrowRight",textKeeps:!0},{id:"close",key:"w"}],I=new Set(["zen","close","back","forward"]);function W(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 j(e){let t=b.find((n)=>n.id===e);if(!t)throw Error(`unknown chord ${e}`);return t}function X(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 ee=Symbol.for("react.forward_ref"),te=Symbol.for("react.memo");function q(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=q(t);if(n)return n}return null}function T(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===ee)return t.displayName||T(t.render);if(t?.$$typeof===te)return t.displayName||T(t.type);return null}var ne=(e)=>typeof e.type==="string"||e.tag===6,re=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function ie(e){let t=null,n=(r)=>{for(let i=r.child??null;i;i=i.sibling??null)if(ne(i)){if(t)return!1;t=i}else if(!n(i))return!1;return!0};return n(e)?t:null}function oe(e){for(let t=e;t;t=t.return){let n=q(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=T(o.type);if(!s)continue;let l=!!e&&re(ie(o),e),a=oe(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 E="#ff4929",G="#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}),le=history.pushState.bind(history);history.pushState=(...e)=>{le(...e),A()};var se=history.replaceState.bind(history);history.replaceState=(...e)=>{se(...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 U=!1,P=null;window.addEventListener("keyup",(e)=>{if(window.__toyonShell||e.key!==P)return;P=null,c({type:"key",key:e.key,meta:!1,up:!0})},!0);window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;let t=W(e,{guest:!0});if(t&&j(t.id).textKeeps&&X(e.target))return;if(U){if(!t||!I.has(t.id))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}),P=e.altKey?"Alt":e.ctrlKey?"Control":e.metaKey?"Meta":null},!0);var R=()=>c({type:"focus",gesture:navigator.userActivation?.isActive??!0});window.addEventListener("focusin",R,!0);window.addEventListener("focus",R);if(document.hasFocus()&&document.activeElement&&document.activeElement!==document.body)R();var Y=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!Y(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="none";c({type:"drag-files"})});window.addEventListener("drop",(e)=>{if(!Y(e))return;e.preventDefault(),c({type:"drop-files"})});function D(e){for(let t of Object.keys(e))if(t.startsWith("__reactFiber$"))return e[t]??null;return null}var p=null;function ae(){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 x(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 ${E};outline-offset:-1px;${n?`background:${E}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(ae().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:${E};color:${G};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)=>`${J(e.file)}${e.line?`:${e.line}`:""}`;function C(e){d=e,m();let t=L(D(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 ${z(e)}`,a(y&&"⌥ chat")):g(r?`<${r} />${o?` · ${O(o)}`:""}`:z(e),a(!y&&"⌥ code"));x(e.getBoundingClientRect(),u,l)}function z(e){let t=e.tagName.toLowerCase(),n=e.classList[0];return(e.id?`${t}#${e.id}`:n?`${t}.${n}`:t).slice(0,48)}var ce=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function ue(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&&(ce.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)C(t)}function V(e){e.preventDefault(),e.stopPropagation();let t=d??document.elementFromPoint(e.clientX,e.clientY),n=L(t?D(t):null),{src:r,comp:i,call:o}=n;f=e.shiftKey;let s=_(n,f),l=e.altKey!==y;if(B(),!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:fe(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:ue(t)})}function S(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),B(),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)C(d)}}function de(e){if(y=e,v){if(d)C(d);return}v=!0,d=null,h=!1,f=!1,document.addEventListener("mousemove",Z,!0),document.addEventListener("click",V,!0),document.addEventListener("keydown",S,!0),document.addEventListener("keyup",S,!0),document.documentElement.style.cursor="crosshair"}function B(){v=!1,y=!1,d=null,h=!1,f=!1,m(),document.removeEventListener("mousemove",Z,!0),document.removeEventListener("click",V,!0),document.removeEventListener("keydown",S,!0),document.removeEventListener("keyup",S,!0),document.documentElement.style.cursor=""}function fe(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 J(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function he(e,t){return e.endsWith(t)||t.endsWith(J(e))}function pe(e,t){let n=[],r=0;for(let s of Array.from(document.querySelectorAll("*"))){let l=K(D(s));if(l)r++;if(!l||!he(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 ye(e,t){m();let{matched:n,fromFile:r,withSource:i}=pe(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)x(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":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"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":de(n.verb==="code");break;case"pick-mods":if(v&&(h!==n.alt||f!==n.shift)){if(h=n.alt,f=n.shift,d)C(d)}break;case"pick-cancel":B();break;case"highlight-file":ye(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=([H,Q])=>a.getPropertyValue(H)===Q&&(!r.test(H)||i(o[l]));if(n.match==="any"?n.props.some(u):n.props.every(u))x(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++)x(r[i].getBoundingClientRect(),i===0&&n.label?g(n.label):void 0)}catch{}break}case"highlight-clear":m();break;case"zen":U=n.on;break;case"theme":if(/^#[0-9a-f]{3,8}$/i.test(n.accent))E=n.accent;if(/^#[0-9a-f]{3,8}$/i.test(n.accentFg))G=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:"wt-archive",key:"Backspace",alt:!0,textKeeps:!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:"ArrowLeft",textKeeps:!0},{id:"forward",key:"ArrowRight",textKeeps:!0},{id:"close",key:"w"}],I=new Set(["zen","close","back","forward"]);function W(e,{guest:t=!1}={}){if(e.altKey){if(e.metaKey||e.ctrlKey)return null;let r=b.find((i)=>i.alt&&!!i.shift===e.shiftKey&&(i.key===e.key||i.key.length===1&&e.code===`Key${i.key.toUpperCase()}`));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 j(e){let t=b.find((n)=>n.id===e);if(!t)throw Error(`unknown chord ${e}`);return t}function X(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 ee=Symbol.for("react.forward_ref"),te=Symbol.for("react.memo");function q(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 T(e){for(let t=e;t;t=t.return){let n=q(t);if(n)return n}return null}function K(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===ee)return t.displayName||K(t.render);if(t?.$$typeof===te)return t.displayName||K(t.type);return null}var ne=(e)=>typeof e.type==="string"||e.tag===6,re=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function ie(e){let t=null,n=(r)=>{for(let i=r.child??null;i;i=i.sibling??null)if(ne(i)){if(t)return!1;t=i}else if(!n(i))return!1;return!0};return n(e)?t:null}function oe(e){for(let t=e;t;t=t.return){let n=q(t);if(n)return t._debugOwner===null?null:n}return null}function L(e){let t=T(e),n=null,r=null,i=!1;for(let o=e;o;o=o.return){let s=K(o.type);if(!s)continue;let l=!!e&&re(ie(o),e),a=oe(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="#fa891e",U="#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}),le=history.pushState.bind(history);history.pushState=(...e)=>{le(...e),A()};var se=history.replaceState.bind(history);history.replaceState=(...e)=>{se(...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 G=!1,P=null;window.addEventListener("keyup",(e)=>{if(window.__toyonShell||e.key!==P)return;P=null,c({type:"key",key:e.key,meta:!1,up:!0})},!0);window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;let t=W(e,{guest:!0});if(t&&j(t.id).textKeeps&&X(e.target))return;if(G){if(!t||!I.has(t.id))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,code:e.code,meta:e.metaKey,ctrl:e.ctrlKey,shift:e.shiftKey,alt:e.altKey}),P=e.altKey?"Alt":e.ctrlKey?"Control":e.metaKey?"Meta":null},!0);var R=()=>c({type:"focus",gesture:navigator.userActivation?.isActive??!0});window.addEventListener("focusin",R,!0);window.addEventListener("focus",R);if(document.hasFocus()&&document.activeElement&&document.activeElement!==document.body)R();var Y=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!Y(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="copy";c({type:"drag-files"})});window.addEventListener("drop",(e)=>{if(!Y(e))return;e.preventDefault(),c({type:"drop-files",files:Array.from(e.dataTransfer?.files??[])})});function D(e){for(let t of Object.keys(e))if(t.startsWith("__reactFiber$"))return e[t]??null;return null}var y=null;function ae(){if(y?.isConnected)return y;return y=document.createElement("div"),y.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:2147483647;",document.documentElement.appendChild(y),y}function m(){if(y)y.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(ae().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:${U};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,p=!1,f=!1,h=!1,O=(e)=>`${J(e.file)}${e.line?`:${e.line}`:""}`;function C(e){d=e,m();let t=L(D(e)),{src:n,comp:r,call:i}=t,o=_(t,f),s=o===n?i:n,l=p!==h,a=(...k)=>k.filter(Boolean).join(" ")||void 0,u=l?o?g(`open ${O(o)}`,a(s&&`⇧ ${O(s)}`,h&&"⌥ chat")):g(`find ${z(e)}`,a(h&&"⌥ chat")):g(r?`<${r} />${o?` · ${O(o)}`:""}`:z(e),a(!h&&"⌥ code"));E(e.getBoundingClientRect(),u,l)}function z(e){let t=e.tagName.toLowerCase(),n=e.classList[0];return(e.id?`${t}#${e.id}`:n?`${t}.${n}`:t).slice(0,48)}var ce=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function ue(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&&(ce.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!==p||e.shiftKey!==f;if(p=e.altKey,f=e.shiftKey,n)C(t)}function V(e){e.preventDefault(),e.stopPropagation();let t=d??document.elementFromPoint(e.clientX,e.clientY),n=L(t?D(t):null),{src:r,comp:i,call:o}=n;f=e.shiftKey;let s=_(n,f),l=e.altKey!==h;if(B(),!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:fe(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:ue(t)})}function S(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),B(),c({type:"pick-cancel"});return}if((e.key==="Alt"||e.key==="Shift")&&(p!==e.altKey||f!==e.shiftKey)){if(p=e.altKey,f=e.shiftKey,d)C(d)}}function de(e){if(h=e,v){if(d)C(d);return}v=!0,d=null,p=!1,f=!1,document.addEventListener("mousemove",Z,!0),document.addEventListener("click",V,!0),document.addEventListener("keydown",S,!0),document.addEventListener("keyup",S,!0),document.documentElement.style.cursor="crosshair"}function B(){v=!1,h=!1,d=null,p=!1,f=!1,m(),document.removeEventListener("mousemove",Z,!0),document.removeEventListener("click",V,!0),document.removeEventListener("keydown",S,!0),document.removeEventListener("keyup",S,!0),document.documentElement.style.cursor=""}function fe(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 J(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function pe(e,t){return e.endsWith(t)||t.endsWith(J(e))}function ye(e,t){let n=[],r=0;for(let s of Array.from(document.querySelectorAll("*"))){let l=T(D(s));if(l)r++;if(!l||!pe(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 he(e,t){m();let{matched:n,fromFile:r,withSource:i}=ye(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":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"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":de(n.verb==="code");break;case"pick-mods":if(v&&(p!==n.alt||f!==n.shift)){if(p=n.alt,f=n.shift,d)C(d)}break;case"pick-cancel":B();break;case"highlight-file":he(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=([H,Q])=>a.getPropertyValue(H)===Q&&(!r.test(H)||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":G=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))U=n.accentFg;break}});
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
|
-
import { existsSync as existsSync10 } from "fs";
|
|
5
|
+
import { existsSync as existsSync10, statSync as statSync4 } from "fs";
|
|
6
6
|
import { join as join8, resolve } from "path";
|
|
7
7
|
|
|
8
8
|
// ../shared/src/daemon.ts
|
|
@@ -5158,7 +5158,7 @@ function parseVersion(v) {
|
|
|
5158
5158
|
// package.json
|
|
5159
5159
|
var package_default = {
|
|
5160
5160
|
name: "toyon",
|
|
5161
|
-
version: "0.
|
|
5161
|
+
version: "0.7.0",
|
|
5162
5162
|
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
5163
|
license: "MIT",
|
|
5164
5164
|
type: "module",
|
|
@@ -5286,6 +5286,60 @@ function shellUrl(token, branded) {
|
|
|
5286
5286
|
return branded ? `http://toyon.localhost/#token=${token}` : `http://toyon.localhost:${port}/#token=${token}`;
|
|
5287
5287
|
}
|
|
5288
5288
|
|
|
5289
|
+
// src/launcher.m
|
|
5290
|
+
var launcher_default = `// The Toyon.app bundle's executable. A plain C stub that execs the launch script never hears
|
|
5291
|
+
// about a file dropped on the Dock icon: that arrives as an Apple Event, which only an
|
|
5292
|
+
// NSApplication receives. So this is the smallest Cocoa app there is: it collects the paths the
|
|
5293
|
+
// event names, answers the event (Finder waits on the answer, and an exec before it would leave
|
|
5294
|
+
// Finder hanging), and once launched execs the script with those paths. The open-files call comes
|
|
5295
|
+
// before the finish-launching one, which is why the paths are collected first and the exec waits
|
|
5296
|
+
// for the second. With nothing dropped the script runs with no arguments.
|
|
5297
|
+
//
|
|
5298
|
+
// Read into the CLI as text (app.ts) and compiled at \`toyon --install-app\` on the machine itself.
|
|
5299
|
+
#import <Cocoa/Cocoa.h>
|
|
5300
|
+
#include <libgen.h>
|
|
5301
|
+
#include <mach-o/dyld.h>
|
|
5302
|
+
#include <stdlib.h>
|
|
5303
|
+
#include <unistd.h>
|
|
5304
|
+
|
|
5305
|
+
@interface Launcher : NSObject <NSApplicationDelegate>
|
|
5306
|
+
@property(strong) NSMutableArray<NSString *> *paths;
|
|
5307
|
+
@end
|
|
5308
|
+
|
|
5309
|
+
@implementation Launcher
|
|
5310
|
+
- (void)application:(NSApplication *)app openFiles:(NSArray<NSString *> *)files {
|
|
5311
|
+
[self.paths addObjectsFromArray:files];
|
|
5312
|
+
[app replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
|
|
5313
|
+
}
|
|
5314
|
+
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
|
|
5315
|
+
return YES;
|
|
5316
|
+
}
|
|
5317
|
+
- (void)applicationDidFinishLaunching:(NSNotification *)note {
|
|
5318
|
+
char self_[4096];
|
|
5319
|
+
uint32_t n = sizeof(self_);
|
|
5320
|
+
if (_NSGetExecutablePath(self_, &n) != 0) exit(1);
|
|
5321
|
+
NSString *script = [NSString stringWithFormat:@"%s/../Resources/launch.sh", dirname(self_)];
|
|
5322
|
+
NSMutableArray<NSString *> *argv = [NSMutableArray arrayWithObjects:@"bash", script, nil];
|
|
5323
|
+
[argv addObjectsFromArray:self.paths];
|
|
5324
|
+
const char **cargv = calloc(argv.count + 1, sizeof(char *));
|
|
5325
|
+
for (NSUInteger i = 0; i < argv.count; i++) cargv[i] = [argv[i] fileSystemRepresentation];
|
|
5326
|
+
execv("/bin/bash", (char *const *)cargv);
|
|
5327
|
+
exit(1);
|
|
5328
|
+
}
|
|
5329
|
+
@end
|
|
5330
|
+
|
|
5331
|
+
int main(void) {
|
|
5332
|
+
@autoreleasepool {
|
|
5333
|
+
NSApplication *app = [NSApplication sharedApplication];
|
|
5334
|
+
Launcher *launcher = [Launcher new];
|
|
5335
|
+
launcher.paths = [NSMutableArray new];
|
|
5336
|
+
app.delegate = launcher;
|
|
5337
|
+
[app run];
|
|
5338
|
+
}
|
|
5339
|
+
return 0;
|
|
5340
|
+
}
|
|
5341
|
+
`;
|
|
5342
|
+
|
|
5289
5343
|
// src/app.ts
|
|
5290
5344
|
var CHROMIUMS = ["Google Chrome", "Arc", "Brave Browser", "Microsoft Edge", "Chromium"];
|
|
5291
5345
|
var DATA_DIRS = {
|
|
@@ -5364,6 +5418,20 @@ function installApp(appUrl) {
|
|
|
5364
5418
|
<key>CFBundlePackageType</key><string>APPL</string>
|
|
5365
5419
|
<key>CFBundleExecutable</key><string>Toyon</string>
|
|
5366
5420
|
<key>CFBundleIconFile</key><string>AppIcon</string>
|
|
5421
|
+
<!-- takes any file or folder dropped on it, without becoming the default opener for anything -->
|
|
5422
|
+
<key>CFBundleDocumentTypes</key>
|
|
5423
|
+
<array>
|
|
5424
|
+
<dict>
|
|
5425
|
+
<key>CFBundleTypeName</key><string>Anything</string>
|
|
5426
|
+
<key>CFBundleTypeRole</key><string>Editor</string>
|
|
5427
|
+
<key>LSHandlerRank</key><string>Alternate</string>
|
|
5428
|
+
<key>LSItemContentTypes</key>
|
|
5429
|
+
<array>
|
|
5430
|
+
<string>public.item</string>
|
|
5431
|
+
<string>public.folder</string>
|
|
5432
|
+
</array>
|
|
5433
|
+
</dict>
|
|
5434
|
+
</array>
|
|
5367
5435
|
</dict></plist>
|
|
5368
5436
|
`);
|
|
5369
5437
|
const launcher = join3(resources, "launch.sh");
|
|
@@ -5386,6 +5454,22 @@ if ! curl -s --max-time 1 http://127.0.0.1:${port}/health >/dev/null 2>&1; then
|
|
|
5386
5454
|
fi
|
|
5387
5455
|
|
|
5388
5456
|
TOKEN=$(cat "$HOME/.toyon/token" 2>/dev/null)
|
|
5457
|
+
|
|
5458
|
+
# what was dropped on the icon, or opened with it: each path goes to the daemon, which opens a
|
|
5459
|
+
# project, a file in one, or a file on its own, and holds it for the window opened below. A
|
|
5460
|
+
# refusal is logged in the daemon's words, since nothing here has a screen (the daemon says it in
|
|
5461
|
+
# the shell too); a success is logged as its status alone, since the reply carries the file's text.
|
|
5462
|
+
for P in "$@"; do
|
|
5463
|
+
BODY=$("$BUN" -e 'console.log(JSON.stringify({ path: process.argv[1] }))' "$P" 2>/dev/null) || continue
|
|
5464
|
+
REPLY=$(curl -s -o /dev/null -w '%{http_code}' -X POST -H "Authorization: Bearer $TOKEN" \\
|
|
5465
|
+
-H "content-type: application/json" --data "$BODY" http://127.0.0.1:${port}/open 2>/dev/null)
|
|
5466
|
+
if [ "$REPLY" != "200" ]; then
|
|
5467
|
+
REPLY="$REPLY $(curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \\
|
|
5468
|
+
--data "$BODY" http://127.0.0.1:${port}/open 2>&1 | head -c 300)"
|
|
5469
|
+
fi
|
|
5470
|
+
echo "$(date '+%Y-%m-%d %H:%M:%S') open $P: $REPLY" >> "$HOME/.toyon/launcher.log"
|
|
5471
|
+
done
|
|
5472
|
+
|
|
5389
5473
|
URL="http://toyon.localhost:${port}/#token=$TOKEN"
|
|
5390
5474
|
MANIFEST_ID="${manifestId}"
|
|
5391
5475
|
CACHE_DIR="$HOME/.toyon/pwa"
|
|
@@ -5420,24 +5504,9 @@ exec open "$URL"
|
|
|
5420
5504
|
`);
|
|
5421
5505
|
chmodSync(launcher, 493);
|
|
5422
5506
|
const stub = join3(macos, "Toyon");
|
|
5423
|
-
const
|
|
5424
|
-
writeFileSync(
|
|
5425
|
-
|
|
5426
|
-
#include <stdint.h>
|
|
5427
|
-
#include <stdlib.h>
|
|
5428
|
-
#include <string.h>
|
|
5429
|
-
#include <unistd.h>
|
|
5430
|
-
#include <libgen.h>
|
|
5431
|
-
int main(int argc, char **argv) {
|
|
5432
|
-
char self[4096]; uint32_t n = sizeof(self);
|
|
5433
|
-
if (_NSGetExecutablePath(self, &n) != 0) return 1;
|
|
5434
|
-
char script[4600];
|
|
5435
|
-
snprintf(script, sizeof(script), "%s/../Resources/launch.sh", dirname(self));
|
|
5436
|
-
execl("/bin/bash", "bash", script, (char *)0);
|
|
5437
|
-
return 1;
|
|
5438
|
-
}
|
|
5439
|
-
`);
|
|
5440
|
-
const cc = spawnSync("clang", ["-O2", "-o", stub, cSrc], { stdio: "ignore" });
|
|
5507
|
+
const src = join3(home, "launcher.m");
|
|
5508
|
+
writeFileSync(src, launcher_default);
|
|
5509
|
+
const cc = spawnSync("clang", ["-O2", "-fobjc-arc", "-framework", "Cocoa", "-o", stub, src], { stdio: "ignore" });
|
|
5441
5510
|
if (cc.status !== 0) {
|
|
5442
5511
|
writeFileSync(stub, `#!/bin/bash
|
|
5443
5512
|
exec /bin/bash "$(dirname "$0")/../Resources/launch.sh"
|
|
@@ -5621,6 +5690,7 @@ var HELP = `toyon: one chat per git worktree, every worktree running live
|
|
|
5621
5690
|
|
|
5622
5691
|
usage
|
|
5623
5692
|
toyon [path] start the daemon if it is not running, register the repo at path
|
|
5693
|
+
(or open the file at path: in its project, or on its own)
|
|
5624
5694
|
(default: the current directory) and open the shell
|
|
5625
5695
|
toyon stop stop the daemon and every dev server and agent it runs
|
|
5626
5696
|
toyon restart stop the daemon and start it again from what is installed now; every
|
|
@@ -8334,7 +8404,20 @@ async function open2(cmd) {
|
|
|
8334
8404
|
console.error("daemon token missing; `toyon doctor` says where it looked");
|
|
8335
8405
|
return 1;
|
|
8336
8406
|
}
|
|
8337
|
-
|
|
8407
|
+
const file = explicit && existsSync10(target) && statSync4(target).isFile();
|
|
8408
|
+
if (file) {
|
|
8409
|
+
const res = await fetch(`${base}/open`, {
|
|
8410
|
+
method: "POST",
|
|
8411
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
8412
|
+
body: JSON.stringify({ path: target })
|
|
8413
|
+
});
|
|
8414
|
+
if (!res.ok) {
|
|
8415
|
+
console.error(`could not open ${target}: ${await res.text()}`);
|
|
8416
|
+
return 1;
|
|
8417
|
+
}
|
|
8418
|
+
const opened = await res.json();
|
|
8419
|
+
console.log(opened.kind === "file" ? `toyon: opening ${target} in its project` : `toyon: opening ${target}`);
|
|
8420
|
+
} else if (register) {
|
|
8338
8421
|
const res = await fetch(`${base}/register`, {
|
|
8339
8422
|
method: "POST",
|
|
8340
8423
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|