toyon 0.15.0 → 0.17.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 +1 -1
- package/dist/CHANGELOG.md +62 -0
- package/dist/bridge.js +1 -1
- package/dist/cli.js +114 -47
- package/dist/daemon.js +1849 -1115
- package/dist/shell/assets/{Editor-jjf6IGvI.js → Editor-BMBnZV2V.js} +175 -175
- package/dist/shell/assets/{XTerm-ClBPMY5e.js → XTerm-xxm4nCyN.js} +1 -1
- package/dist/shell/assets/{cssMode-CgTk4Slg.js → cssMode-DRRmIKjD.js} +1 -1
- package/dist/shell/assets/{freemarker2-B4Eirl4Y.js → freemarker2-BWXbPnFF.js} +1 -1
- package/dist/shell/assets/{grammar-E8nWrhy3.js → grammar-BlgE3B1J.js} +1 -1
- package/dist/shell/assets/{handlebars-C6uEGz8T.js → handlebars-swdzvdWB.js} +1 -1
- package/dist/shell/assets/{html-tDAdsEYh.js → html-GPVhANjL.js} +1 -1
- package/dist/shell/assets/{htmlMode-DXGTr81h.js → htmlMode-BTtuR8kD.js} +1 -1
- package/dist/shell/assets/index-9aG0ri4Y.css +1 -0
- package/dist/shell/assets/index-miqqiN7Z.js +269 -0
- package/dist/shell/assets/{javascript-BeM3ebwd.js → javascript-CFXn2iKE.js} +1 -1
- package/dist/shell/assets/{jsonMode-CXStIFU4.js → jsonMode-wmrRCrSu.js} +1 -1
- package/dist/shell/assets/{liquid-2UNKoWGQ.js → liquid-Bz7Svg4V.js} +1 -1
- package/dist/shell/assets/{lspLanguageFeatures-G4xsCwWV.js → lspLanguageFeatures-BDP4BowE.js} +1 -1
- package/dist/shell/assets/{mdx-CoF6St9y.js → mdx-CzERTPdi.js} +1 -1
- package/dist/shell/assets/{python-rULGuAEe.js → python-3OsSAVmo.js} +1 -1
- package/dist/shell/assets/{razor-0I41g6kD.js → razor-BKY4SJuy.js} +1 -1
- package/dist/shell/assets/{tsMode-CyMsmAXC.js → tsMode-BESW693Z.js} +1 -1
- package/dist/shell/assets/{xml-BNhTd1tm.js → xml-SaTEQQ9V.js} +1 -1
- package/dist/shell/assets/{yaml-Cp69rkq5.js → yaml-gHi84-nk.js} +1 -1
- package/dist/shell/index.html +2 -2
- package/package.json +1 -1
- package/dist/shell/assets/index-1FLxRByi.js +0 -267
- package/dist/shell/assets/index-D-4W2x1P.css +0 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ Point at anything on the page to talk about it or open the line that draws it, a
|
|
|
28
28
|
|
|
29
29
|
One Toyon holds every project you open, and the list of chats shows which one needs you.
|
|
30
30
|
|
|
31
|
-
When your check passes, land merges into main on your machine by default, or pushes, or
|
|
31
|
+
When your check passes, land merges into main on your machine by default, or pushes, or creates a pull request.
|
|
32
32
|
|
|
33
33
|
Built for web apps. A project without a page still works; the chat takes the middle instead of the preview.
|
|
34
34
|
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
What changed in each release of Toyon, newest first.
|
|
4
4
|
|
|
5
|
+
## 0.17.0 (2026-10-21)
|
|
6
|
+
|
|
7
|
+
The composer's @ menu reaches the other worktrees of the project, the editor pane can wrap long lines, and a git command that hangs no longer holds up every later landing.
|
|
8
|
+
|
|
9
|
+
### New
|
|
10
|
+
- The composer's @ menu lists the project's other worktrees. A bare @ offers the three you sent to most recently, each with its status dot, title and the time since the last send, and typing part of a title searches them all. The pick puts the worktree's name in the message so the agent can read that chat.
|
|
11
|
+
- The editor pane has a wrap button that folds long lines at the pane's edge or goes back to sideways scrolling. The choice holds for the window and applies to the diff view too.
|
|
12
|
+
- Up and down walk the archived and discovered rows of the rail as they already walked your own. Stepping onto an archived row opens its page and keeps the focus on the row.
|
|
13
|
+
- `toyon <file>` with a window already open shows the file there and brings the window forward instead of opening a second one, and the project picker takes a file as well as a folder.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- On the PR route the button reads create PR until a pull request exists, since open read as opening its page.
|
|
17
|
+
- The plan row in the transcript shows the plan's first heading, as the row above the composer does, and keeps the path in its tooltip and menu.
|
|
18
|
+
- The chats palette leads each group with the chat's name and the age of its newest hit, and shows the chat's ask beneath it on up to two lines.
|
|
19
|
+
- Project search stops at a page of results so a lockfile cannot fill it, and a new query or a closed palette cancels the running one. The footer says when not every match is shown. The symbol lookup on cmd+I stops reading once it has enough rows, so a common name no longer drains the whole project.
|
|
20
|
+
- A plain git command inside a landing or sync has a ten-minute ceiling. Before, one hung process could hold the project's lock and silently queue every later land or sync; now it is killed and the row says so.
|
|
21
|
+
- The daemon's log rotates at 10 MB, is readable only by you, opens each run with a line naming the version, and no longer prints the signed-in link with its token. Refusals, git failures and closed connections take one line each instead of a stack trace.
|
|
22
|
+
- Agent settings, hooks and plugin code are denied to the agent file by file instead of by folder, so its skills, commands and prompts are ordinary edits again. The refusal row names what it guards.
|
|
23
|
+
- Archiving the row you are on moves you to the nearest row above it that is waiting, done, unseen, working or has its app up, and only looks below when none qualifies, so old worktrees parked at the bottom of the rail are not pulled into view.
|
|
24
|
+
- While a commit or land runs, the commit box shows the step's line where the message was and keeps its height, so the foot does not jump. The typed message is held and clears only once the tree is clean, so a refused hook gives the words back to edit.
|
|
25
|
+
- Waiting lines in the files tree, history, design pane, terminal, boot and import views and the pickers show as live text instead of a spinner beside the words.
|
|
26
|
+
- The archived row's menu item reads delete instead of delete for good; the confirm dialog still spells out what goes with it.
|
|
27
|
+
- When a sync finds that the changes carried on the row no longer fit over main, it asks the agent to fix them and names the clashing files, instead of leaving a bare line on the row.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- A reply containing a raw HTML tag such as `<title>` or `<script>` drew nothing after the tag; the tags now show as text.
|
|
31
|
+
- A table wider than the chat column scrolls inside itself, with a fade at the edge that has more behind it, instead of pushing the whole transcript sideways.
|
|
32
|
+
- Switching worktrees quickly could paint the previous chat's text in the new one for a moment.
|
|
33
|
+
- The caret in an empty composer was drawn behind the ghost text; it shows over it now.
|
|
34
|
+
- Sideways scrolling in the editor that ran off a line's end no longer triggers the browser's back or forward swipe.
|
|
35
|
+
- Clicking a tool row left a lone accent line across the top of the transcript on the next keypress; the focus ring now draws whole inside the row.
|
|
36
|
+
- The time tip on a daemon row followed the pointer across the next message; it sits above the word it belongs to.
|
|
37
|
+
- The Dock helper wrote the signed-in link, token included, to its launcher log. The link is printed only to a terminal now; a file gets the bare address and the token file's path.
|
|
38
|
+
- A landing mark could stay on a row after its record had moved on, and a failed Tailscale status check raised an unhandled error instead of reading as not running.
|
|
39
|
+
|
|
40
|
+
## 0.16.0 (2026-10-18)
|
|
41
|
+
|
|
42
|
+
Streamed replies are written to the transcript a few characters at a time instead of a line at a time, the plan card follows the file Claude Code keeps itself, and the checks and preview in the PR line are links.
|
|
43
|
+
|
|
44
|
+
### New
|
|
45
|
+
- In the composer's PR line, "checks running", "checks failed" and "preview up" are links: checks open the pull request's checks tab and the preview opens the branch on its host. A right-click offers to open or copy the link. Under automerge the line says "when checks pass" while checks run and carries no link.
|
|
46
|
+
- A sent attachment's menu can reveal the copy Toyon kept in Finder, or copy its path, in archived chats too.
|
|
47
|
+
- The editor header has a copy button beside reveal that puts the file's full path on the clipboard. It is hidden for a loose file dropped in from outside the worktree.
|
|
48
|
+
- In the full view of an attachment, the left and right arrow keys step to the previous or next attachment of the same message, with a position count beside the close button. Closing returns focus to the chip you ended on.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
- Text streamed by the agent is written to the transcript a few characters a frame instead of a line at a time, so a pinned transcript scrolls smoothly rather than jumping a line per repaint. A reply the agent hands over whole, as after a tool call, still shows at once.
|
|
52
|
+
- The plan card reads the plan file Claude Code keeps itself, in a folder in the worktree that git ignores, so a plan rejected and revised no longer shows a stale copy. An agent that keeps no file still gets Toyon's numbered copy. The plan row in the composer is named by the plan's first heading and follows rewrites; the file name stays in its tooltip and menu.
|
|
53
|
+
- An agent that looked unavailable is checked again whenever the composer or its settings page shows it, or when the window regains focus, so signing in or finishing an install clears the warning without a restart. Before, it was checked once at boot.
|
|
54
|
+
- Once a landing has merged a pull request, the row drops the PR as soon as new work starts over it; undoing that work brings it back with its link.
|
|
55
|
+
- The preview threw row and its fix press are gone. What the page threw still rides behind your next message, so the agent sees it there.
|
|
56
|
+
- The release notes open in the same document view as the editor's markdown preview, with the same type, a jump list of headings, find and select-all.
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
- In the installed app, a press on the top bar's blank strip closes an open address list or menu, instead of only dragging the window.
|
|
60
|
+
- A preview that reopened after its worktree slept, or after the proxy restarted, came back at the root. It now returns to the page it was on, with its query and hash.
|
|
61
|
+
- The element picker's outline draws above the page's own popovers and menus, which could hide it.
|
|
62
|
+
- In the address field above the preview, enter on a cleared field goes to the root instead of reloading the page, and the key hint says so while the field is empty.
|
|
63
|
+
- The typed row in the address list no longer repeats its path as a guessed name, and a path ending in a query no longer gets a garbled page name.
|
|
64
|
+
- A second message sent while a landing's commit was still running took the sending slot from the first, so the two drew out of order. The placeholder now holds its place behind queued messages.
|
|
65
|
+
- Text in the composer, the question card and the commit box sits exactly in line with the transcript, so an answer no longer jumps sideways by a couple of pixels as it goes through.
|
|
66
|
+
|
|
5
67
|
## 0.15.0 (2026-10-15)
|
|
6
68
|
|
|
7
69
|
A row from another project that is waiting on you now shows on the rail in front of you, files dropped on the rail land in a worktree's composer, and a tool row that touched a file grows an eye that opens it.
|
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:"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:"ArrowLeft",textKeeps:!0},{id:"forward",key:"ArrowRight",textKeeps:!0},{id:"close",key:"w"}],G=new Set(["zen","close","back","forward"]);function X(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 U(e){if(e.altKey||e.key.toLowerCase()!=="s")return!1;return!!e.ctrlKey!==e.metaKey}function q(e){let t=b.find((n)=>n.id===e);if(!t)throw Error(`unknown chord ${e}`);return t}function z(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 re=Symbol.for("react.forward_ref"),ie=Symbol.for("react.memo");function Y(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 L(e){for(let t=e;t;t=t.return){let n=Y(t);if(n)return n}return null}function C(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===re)return t.displayName||C(t.render);if(t?.$$typeof===ie)return t.displayName||C(t.type);return null}var oe=(e)=>typeof e.type==="string"||e.tag===6,le=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function se(e){let t=null,n=(r)=>{for(let i=r.child??null;i;i=i.sibling??null)if(oe(i)){if(t)return!1;t=i}else if(!n(i))return!1;return!0};return n(e)?t:null}function ae(e){for(let t=e;t;t=t.return){let n=Y(t);if(n)return t._debugOwner===null?null:n}return null}function N(e){let t=L(e),n=null,r=null,i=!1;for(let o=e;o;o=o.return){let s=C(o.type);if(!s)continue;let l=!!e&&le(se(o),e),a=ae(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 v=window.__toyonShellOrigins??[],P=null,c=(e)=>{try{let t=P?[P]:v.length?v:["*"];for(let n of t)window.parent.postMessage({__toyon:!0,...e},n)}catch{}};c({type:"loaded",url:location.href,title:document.title});var E="#fa891e",V="#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 K=()=>c({type:"navigated",url:location.href,title:document.title}),ce=history.pushState.bind(history);history.pushState=(...e)=>{ce(...e),B(),K()};var ue=history.replaceState.bind(history);history.replaceState=(...e)=>{ue(...e),K()};window.addEventListener("popstate",K);window.addEventListener("hashchange",K);var de=window.navigation,g=null;function B(){g=de?.currentEntry?.index??null}B();window.addEventListener("popstate",()=>{let e=g;B();let t=e===null||g===null||e===g?void 0:g<e?"back":"forward";c({type:"traversed",...t?{dir:t}:{}})});var fe=performance.getEntriesByType("navigation")[0];if(fe?.type==="back_forward")c({type:"traversed"});window.addEventListener("pageshow",(e)=>{if(e.persisted)c({type:"traversed"})});var F=document.title;if(document.head)new MutationObserver(()=>{if(document.title===F)return;F=document.title,c({type:"title",title:F})}).observe(document.head,{childList:!0,subtree:!0,characterData:!0});var J=!1,R=null;window.addEventListener("keyup",(e)=>{if(window.__toyonShell||e.key!==R)return;R=null,c({type:"key",key:e.key,meta:!1,up:!0})},!0);window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;if(U(e))e.preventDefault();let t=X(e,{guest:!0});if(t&&q(t.id).textKeeps&&z(e.target))return;if(J){if(!t||!G.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}),R=e.altKey?"Alt":e.ctrlKey?"Control":e.metaKey?"Meta":null},!0);var D=()=>c({type:"focus",gesture:navigator.userActivation?.isActive??!0});window.addEventListener("focusin",D,!0);window.addEventListener("focus",D);if(document.hasFocus()&&document.activeElement&&document.activeElement!==document.body)D();var H=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!H(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="copy";c({type:"drag-files",over:!0})});window.addEventListener("dragleave",(e)=>{if(H(e))c({type:"drag-files",over:!1})});window.addEventListener("drop",(e)=>{if(!H(e))return;e.preventDefault(),c({type:"drop-files",files:Array.from(e.dataTransfer?.files??[])})});function I(e){for(let t of Object.keys(e))if(t.startsWith("__reactFiber$"))return e[t]??null;return null}var y=null;function pe(){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 O=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>=O,o=e.bottom+O<=window.innerHeight;if(t.style.top=i?`${-O}px`:o?`${e.height+4}px`:"2px",!i&&!o)t.style.left="2px";r.appendChild(t)}if(pe().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 k(e,t){let n=document.createElement("div");if(n.textContent=e,n.style.cssText=`position:absolute;left:0;background:${E};color:${V};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 S=!1,d=null,p=!1,f=!1,h=!1,M=(e)=>`${te(e.file)}${e.line?`:${e.line}`:""}`;function T(e){d=e,m();let t=N(I(e)),{src:n,comp:r,call:i}=t,o=_(t,f),s=o===n?i:n,l=p!==h,a=(...w)=>w.filter(Boolean).join(" ")||void 0,u=l?o?k(`open ${M(o)}`,a(s&&`⇧ ${M(s)}`,h&&"⌥ chat")):k(`find ${Z(e)}`,a(h&&"⌥ chat")):k(r?`<${r} />${o?` · ${M(o)}`:""}`:Z(e),a(!h&&"⌥ 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 ye=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function he(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&&(ye.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 Q(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)T(t)}function ee(e){e.preventDefault(),e.stopPropagation();let t=d??document.elementFromPoint(e.clientX,e.clientY),n=N(t?I(t):null),{src:r,comp:i,call:o}=n;f=e.shiftKey;let s=_(n,f),l=e.altKey!==h;if(W(),!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:ge(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:he(t)})}function A(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),W(),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)T(d)}}function me(e){if(h=e,S){if(d)T(d);return}S=!0,d=null,p=!1,f=!1,document.addEventListener("mousemove",Q,!0),document.addEventListener("click",ee,!0),document.addEventListener("keydown",A,!0),document.addEventListener("keyup",A,!0),document.documentElement.style.cursor="crosshair"}function W(){S=!1,h=!1,d=null,p=!1,f=!1,m(),document.removeEventListener("mousemove",Q,!0),document.removeEventListener("click",ee,!0),document.removeEventListener("keydown",A,!0),document.removeEventListener("keyup",A,!0),document.documentElement.style.cursor=""}function ge(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 te(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function ke(e,t){return e.endsWith(t)||t.endsWith(te(e))}function we(e,t){let n=[],r=0;for(let s of Array.from(document.querySelectorAll("*"))){let l=L(I(s));if(l)r++;if(!l||!ke(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,w)=>w.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 be(e,t){m();let{matched:n,fromFile:r,withSource:i}=we(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(v.length&&!v.includes(e.origin))return;let t=e.data;if(!t?.__toyon)return;P=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":me(n.verb==="code");break;case"pick-mods":if(S&&(p!==n.alt||f!==n.shift)){if(p=n.alt,f=n.shift,d)T(d)}break;case"pick-cancel":W();break;case"highlight-file":be(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=([j,ne])=>a.getPropertyValue(j)===ne&&(!r.test(j)||i(o[l]));if(n.match==="any"?n.props.some(u):n.props.every(u))x(o[l].getBoundingClientRect(),s&&n.label?k(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?k(n.label):void 0)}catch{}break}case"highlight-clear":m();break;case"zen":J=n.on;break;case"theme":if(/^#[0-9a-f]{3,8}$/i.test(n.accent))E=n.accent;if(/^#[0-9a-f]{3,8}$/i.test(n.accentFg))V=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,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:"ArrowLeft",textKeeps:!0},{id:"forward",key:"ArrowRight",textKeeps:!0},{id:"close",key:"w"}],X=new Set(["zen","close","back","forward"]);function U(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 q(e){if(e.altKey||e.key.toLowerCase()!=="s")return!1;return!!e.ctrlKey!==e.metaKey}function z(e){let t=b.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 ie=Symbol.for("react.forward_ref"),oe=Symbol.for("react.memo");function Y(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 L(e){for(let t=e;t;t=t.return){let n=Y(t);if(n)return n}return null}function C(e){if(typeof e==="function")return e.displayName||e.name||null;let t=e;if(t?.$$typeof===ie)return t.displayName||C(t.render);if(t?.$$typeof===oe)return t.displayName||C(t.type);return null}var le=(e)=>typeof e.type==="string"||e.tag===6,se=(e,t)=>!!e&&(e===t||!!e.stateNode&&e.stateNode===t.stateNode);function ae(e){let t=null,n=(r)=>{for(let i=r.child??null;i;i=i.sibling??null)if(le(i)){if(t)return!1;t=i}else if(!n(i))return!1;return!0};return n(e)?t:null}function ce(e){for(let t=e;t;t=t.return){let n=Y(t);if(n)return t._debugOwner===null?null:n}return null}function N(e){let t=L(e),n=null,r=null,i=!1;for(let o=e;o;o=o.return){let s=C(o.type);if(!s)continue;let l=!!e&&se(ae(o),e),a=ce(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 v=window.__toyonShellOrigins??[],P=null,c=(e)=>{try{let t=P?[P]:v.length?v:["*"];for(let n of t)window.parent.postMessage({__toyon:!0,...e},n)}catch{}};c({type:"loaded",url:location.href,title:document.title});var E="#fa891e",J="#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 K=()=>c({type:"navigated",url:location.href,title:document.title}),ue=history.pushState.bind(history);history.pushState=(...e)=>{ue(...e),D(),K()};var de=history.replaceState.bind(history);history.replaceState=(...e)=>{de(...e),K()};window.addEventListener("popstate",K);window.addEventListener("hashchange",K);var fe=window.navigation,g=null;function D(){g=fe?.currentEntry?.index??null}D();window.addEventListener("popstate",()=>{let e=g;D();let t=e===null||g===null||e===g?void 0:g<e?"back":"forward";c({type:"traversed",...t?{dir:t}:{}})});var pe=performance.getEntriesByType("navigation")[0];if(pe?.type==="back_forward")c({type:"traversed"});window.addEventListener("pageshow",(e)=>{if(e.persisted)c({type:"traversed"})});var F=document.title;if(document.head)new MutationObserver(()=>{if(document.title===F)return;F=document.title,c({type:"title",title:F})}).observe(document.head,{childList:!0,subtree:!0,characterData:!0});var Q=!1,R=null;window.addEventListener("keyup",(e)=>{if(window.__toyonShell||e.key!==R)return;R=null,c({type:"key",key:e.key,meta:!1,up:!0})},!0);window.addEventListener("keydown",(e)=>{if(window.__toyonShell)return;if(q(e))e.preventDefault();let t=U(e,{guest:!0});if(t&&z(t.id).textKeeps&&V(e.target))return;if(Q){if(!t||!X.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}),R=e.altKey?"Alt":e.ctrlKey?"Control":e.metaKey?"Meta":null},!0);var H=()=>c({type:"focus",gesture:navigator.userActivation?.isActive??!0});window.addEventListener("focusin",H,!0);window.addEventListener("focus",H);if(document.hasFocus()&&document.activeElement&&document.activeElement!==document.body)H();var I=(e)=>!e.defaultPrevented&&!!e.dataTransfer?.types.includes("Files");window.addEventListener("dragover",(e)=>{if(!I(e))return;if(e.preventDefault(),e.dataTransfer)e.dataTransfer.dropEffect="copy";c({type:"drag-files",over:!0})});window.addEventListener("dragleave",(e)=>{if(I(e))c({type:"drag-files",over:!1})});window.addEventListener("drop",(e)=>{if(!I(e))return;e.preventDefault(),c({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,B=typeof HTMLElement<"u"&&"showPopover"in HTMLElement.prototype;function ye(){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;",B)u.popover="manual";document.documentElement.appendChild(u)}if(B&&!u.matches(":popover-open"))u.showPopover();return u}function m(){if(!u)return;if(u.innerHTML="",B&&u.matches(":popover-open"))u.hidePopover()}var O=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>=O,o=e.bottom+O<=window.innerHeight;if(t.style.top=i?`${-O}px`:o?`${e.height+4}px`:"2px",!i&&!o)t.style.left="2px";r.appendChild(t)}if(ye().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 k(e,t){let n=document.createElement("div");if(n.textContent=e,n.style.cssText=`position:absolute;left:0;background:${E};color:${J};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 S=!1,f=null,y=!1,p=!1,h=!1,M=(e)=>`${ne(e.file)}${e.line?`:${e.line}`:""}`;function T(e){f=e,m();let t=N(W(e)),{src:n,comp:r,call:i}=t,o=_(t,p),s=o===n?i:n,l=y!==h,a=(...w)=>w.filter(Boolean).join(" ")||void 0,d=l?o?k(`open ${M(o)}`,a(s&&`⇧ ${M(s)}`,h&&"⌥ chat")):k(`find ${Z(e)}`,a(h&&"⌥ chat")):k(r?`<${r} />${o?` · ${M(o)}`:""}`:Z(e),a(!h&&"⌥ code"));x(e.getBoundingClientRect(),d,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 he=new Set(["name","placeholder","aria-label","title","alt","for","href","type","role","src"]);function me(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&&(he.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 ee(e){let t=document.elementFromPoint(e.clientX,e.clientY);if(!t)return;let n=t!==f||e.altKey!==y||e.shiftKey!==p;if(y=e.altKey,p=e.shiftKey,n)T(t)}function te(e){e.preventDefault(),e.stopPropagation();let t=f??document.elementFromPoint(e.clientX,e.clientY),n=N(t?W(t):null),{src:r,comp:i,call:o}=n;p=e.shiftKey;let s=_(n,p),l=e.altKey!==h;if(j(),!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:ke(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:me(t)})}function A(e){if(e.key==="Escape"&&e.type==="keydown"){e.preventDefault(),e.stopPropagation(),j(),c({type:"pick-cancel"});return}if((e.key==="Alt"||e.key==="Shift")&&(y!==e.altKey||p!==e.shiftKey)){if(y=e.altKey,p=e.shiftKey,f)T(f)}}function ge(e){if(h=e,S){if(f)T(f);return}S=!0,f=null,y=!1,p=!1,document.addEventListener("mousemove",ee,!0),document.addEventListener("click",te,!0),document.addEventListener("keydown",A,!0),document.addEventListener("keyup",A,!0),document.documentElement.style.cursor="crosshair"}function j(){S=!1,h=!1,f=null,y=!1,p=!1,m(),document.removeEventListener("mousemove",ee,!0),document.removeEventListener("click",te,!0),document.removeEventListener("keydown",A,!0),document.removeEventListener("keyup",A,!0),document.documentElement.style.cursor=""}function ke(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 ne(e){let t=e.lastIndexOf("/src/");return t>=0?e.slice(t+1):e.split("/").slice(-2).join("/")}function we(e,t){return e.endsWith(t)||t.endsWith(ne(e))}function be(e,t){let n=[],r=0;for(let s of Array.from(document.querySelectorAll("*"))){let l=L(W(s));if(l)r++;if(!l||!we(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((d)=>d.line===s);if(l.length>0)return{matched:l,fromFile:n,withSource:r};let a=n.filter((d)=>d.line>0&&d.line<s);return a.sort((d,w)=>w.line-d.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 ve(e,t){m();let{matched:n,fromFile:r,withSource:i}=be(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(v.length&&!v.includes(e.origin))return;let t=e.data;if(!t?.__toyon)return;P=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":ge(n.verb==="code");break;case"pick-mods":if(S&&(y!==n.alt||p!==n.shift)){if(y=n.alt,p=n.shift,f)T(f)}break;case"pick-cancel":j();break;case"highlight-file":ve(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]),d=([G,re])=>a.getPropertyValue(G)===re&&(!r.test(G)||i(o[l]));if(n.match==="any"?n.props.some(d):n.props.every(d))x(o[l].getBoundingClientRect(),s&&n.label?k(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?k(n.label):void 0)}catch{}break}case"highlight-clear":m();break;case"zen":Q=n.on;break;case"theme":if(/^#[0-9a-f]{3,8}$/i.test(n.accent))E=n.accent;if(/^#[0-9a-f]{3,8}$/i.test(n.accentFg))J=n.accentFg;break}});
|
package/dist/cli.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
|
-
import { existsSync as
|
|
5
|
+
import { existsSync as existsSync12, statSync as statSync5 } from "fs";
|
|
6
6
|
import { join as join7, resolve } from "path";
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "toyon",
|
|
10
|
-
version: "0.
|
|
10
|
+
version: "0.17.0",
|
|
11
11
|
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.",
|
|
12
12
|
license: "MIT",
|
|
13
13
|
type: "module",
|
|
@@ -57,13 +57,13 @@ var package_default = {
|
|
|
57
57
|
|
|
58
58
|
// src/app.ts
|
|
59
59
|
import { spawn as spawn3, spawnSync } from "child_process";
|
|
60
|
-
import { existsSync as
|
|
60
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
61
61
|
import { homedir as homedir2 } from "os";
|
|
62
62
|
import { join as join3 } from "path";
|
|
63
63
|
|
|
64
64
|
// src/daemon.ts
|
|
65
65
|
import { spawn } from "child_process";
|
|
66
|
-
import { existsSync as
|
|
66
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync } from "fs";
|
|
67
67
|
import { homedir } from "os";
|
|
68
68
|
import { join as join2 } from "path";
|
|
69
69
|
|
|
@@ -76,6 +76,8 @@ var isTailnetName = (host) => host.endsWith(".ts.net");
|
|
|
76
76
|
var APP_SCHEME = "toyon";
|
|
77
77
|
var START_LINK = `${APP_SCHEME}://start`;
|
|
78
78
|
var LSREGISTER = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";
|
|
79
|
+
var FD_LIMIT_LOW = 4096;
|
|
80
|
+
var fdLimitLine = (n) => `open-file limit is ${n}; raise it with ulimit -n 8192 before toyon starts`;
|
|
79
81
|
var DAEMON_FILES = {
|
|
80
82
|
token: "token",
|
|
81
83
|
helper: "Toyon.app",
|
|
@@ -5249,19 +5251,31 @@ function parseVersion(v) {
|
|
|
5249
5251
|
return { nums: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] ?? null };
|
|
5250
5252
|
}
|
|
5251
5253
|
|
|
5254
|
+
// ../shared/src/logfile.ts
|
|
5255
|
+
import { chmodSync, existsSync, openSync, renameSync, statSync } from "fs";
|
|
5256
|
+
var LOG_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
5257
|
+
var previousLog = (path) => `${path}.1`;
|
|
5258
|
+
function openLog(path, maxBytes = LOG_ROTATE_BYTES) {
|
|
5259
|
+
if (existsSync(path) && statSync(path).size > maxBytes)
|
|
5260
|
+
renameSync(path, previousLog(path));
|
|
5261
|
+
const fd = openSync(path, "a", 384);
|
|
5262
|
+
chmodSync(path, 384);
|
|
5263
|
+
return fd;
|
|
5264
|
+
}
|
|
5265
|
+
|
|
5252
5266
|
// src/layout.ts
|
|
5253
|
-
import { existsSync, realpathSync } from "fs";
|
|
5267
|
+
import { existsSync as existsSync2, realpathSync } from "fs";
|
|
5254
5268
|
import { delimiter, dirname, join } from "path";
|
|
5255
5269
|
import { fileURLToPath } from "url";
|
|
5256
5270
|
var here = dirname(fileURLToPath(import.meta.url));
|
|
5257
|
-
var packaged =
|
|
5271
|
+
var packaged = existsSync2(join(here, "daemon.js"));
|
|
5258
5272
|
var method = installMethod(packaged ? join(here, "..", "package.json") : null);
|
|
5259
5273
|
function installOnPath() {
|
|
5260
5274
|
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
5261
5275
|
if (dir === "" || dir.includes("/_npx/"))
|
|
5262
5276
|
continue;
|
|
5263
5277
|
const bin = join(dir, "toyon");
|
|
5264
|
-
if (!
|
|
5278
|
+
if (!existsSync2(bin))
|
|
5265
5279
|
continue;
|
|
5266
5280
|
try {
|
|
5267
5281
|
return installMethod(realpathSync(bin));
|
|
@@ -5308,13 +5322,13 @@ async function daemonFetch(path, init = {}) {
|
|
|
5308
5322
|
}
|
|
5309
5323
|
}
|
|
5310
5324
|
function readToken() {
|
|
5311
|
-
if (!
|
|
5325
|
+
if (!existsSync3(tokenFile))
|
|
5312
5326
|
return null;
|
|
5313
5327
|
const t = readFileSync(tokenFile, "utf8").trim();
|
|
5314
5328
|
return t === "" ? null : t;
|
|
5315
5329
|
}
|
|
5316
5330
|
function readPid() {
|
|
5317
|
-
if (!
|
|
5331
|
+
if (!existsSync3(pidFile))
|
|
5318
5332
|
return null;
|
|
5319
5333
|
const n = Number(readFileSync(pidFile, "utf8").trim());
|
|
5320
5334
|
return Number.isInteger(n) && n > 0 ? n : null;
|
|
@@ -5329,7 +5343,7 @@ function alive(pid) {
|
|
|
5329
5343
|
}
|
|
5330
5344
|
async function startDaemon() {
|
|
5331
5345
|
mkdirSync(home, { recursive: true });
|
|
5332
|
-
const logFd =
|
|
5346
|
+
const logFd = openLog(logFile);
|
|
5333
5347
|
const child = spawn(process.execPath, ["run", daemonEntry], {
|
|
5334
5348
|
detached: true,
|
|
5335
5349
|
stdio: ["ignore", logFd, logFd],
|
|
@@ -5377,6 +5391,9 @@ var shellOrigins = ["http://toyon.localhost", `http://toyon.localhost:${port}`];
|
|
|
5377
5391
|
function shellUrl(token, branded) {
|
|
5378
5392
|
return `${branded ? shellOrigins[0] : shellOrigins[1]}/#token=${token}`;
|
|
5379
5393
|
}
|
|
5394
|
+
function shellLine(url, tty = process.stdout.isTTY === true) {
|
|
5395
|
+
return tty ? `toyon: ${url}` : `toyon: ${url.replace(/#token=.*$/, "")}; token read from ${tokenFile}`;
|
|
5396
|
+
}
|
|
5380
5397
|
|
|
5381
5398
|
// src/openUrl.ts
|
|
5382
5399
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -5397,16 +5414,16 @@ var CHROMIUMS = [
|
|
|
5397
5414
|
var pwaCacheDir = join3(home, "pwa");
|
|
5398
5415
|
function profilesOf(browser) {
|
|
5399
5416
|
const root = join3(homedir2(), "Library", "Application Support", browser.dataDir);
|
|
5400
|
-
if (!
|
|
5417
|
+
if (!existsSync4(root))
|
|
5401
5418
|
return [];
|
|
5402
5419
|
return readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => join3(root, d.name));
|
|
5403
5420
|
}
|
|
5404
5421
|
function pwaStillInstalled(browser, id) {
|
|
5405
|
-
return profilesOf(browser).some((p) =>
|
|
5422
|
+
return profilesOf(browser).some((p) => existsSync4(join3(p, "Web Applications", "Manifest Resources", id)));
|
|
5406
5423
|
}
|
|
5407
5424
|
function findPwaId(browser) {
|
|
5408
5425
|
const cache = join3(pwaCacheDir, `${browser.name.replace(/\W+/g, "-")}.id`);
|
|
5409
|
-
if (
|
|
5426
|
+
if (existsSync4(cache)) {
|
|
5410
5427
|
const id = readFileSync2(cache, "utf8").trim();
|
|
5411
5428
|
if (/^[a-p]{32}$/.test(id) && pwaStillInstalled(browser, id))
|
|
5412
5429
|
return id;
|
|
@@ -5415,7 +5432,7 @@ function findPwaId(browser) {
|
|
|
5415
5432
|
const re = new RegExp(`web_apps-dt-([a-p]{32})[\\s\\S]{0,16}?(?:${ids})`);
|
|
5416
5433
|
for (const p of profilesOf(browser)) {
|
|
5417
5434
|
const dir = join3(p, "Sync Data", "LevelDB");
|
|
5418
|
-
if (!
|
|
5435
|
+
if (!existsSync4(dir))
|
|
5419
5436
|
continue;
|
|
5420
5437
|
for (const f of readdirSync(dir)) {
|
|
5421
5438
|
if (!/\.(log|ldb)$/.test(f))
|
|
@@ -5431,7 +5448,7 @@ function findPwaId(browser) {
|
|
|
5431
5448
|
return null;
|
|
5432
5449
|
}
|
|
5433
5450
|
function openShell(daemon) {
|
|
5434
|
-
console.log(
|
|
5451
|
+
console.log(shellLine(daemon.url));
|
|
5435
5452
|
const found = process.platform === "darwin" ? launchInstalledApp() : { kind: "none" };
|
|
5436
5453
|
if (found.kind === "launched")
|
|
5437
5454
|
return;
|
|
@@ -5441,6 +5458,41 @@ function openShell(daemon) {
|
|
|
5441
5458
|
const where = defaultBrowserInstalls(readLinkHandlers()) ? "" : `open it in ${found.browser} to `;
|
|
5442
5459
|
console.log(`tip: ${where}install Toyon as an app from the top bar; toyon then opens in its own window`);
|
|
5443
5460
|
}
|
|
5461
|
+
function focusShell() {
|
|
5462
|
+
if (process.platform !== "darwin")
|
|
5463
|
+
return;
|
|
5464
|
+
const bundle = installedAppBundle();
|
|
5465
|
+
if (!bundle)
|
|
5466
|
+
return;
|
|
5467
|
+
const child = spawn3("open", [bundle], { stdio: "ignore" });
|
|
5468
|
+
child.on("error", () => {});
|
|
5469
|
+
child.unref();
|
|
5470
|
+
}
|
|
5471
|
+
function installedAppBundle() {
|
|
5472
|
+
const apps = join3(homedir2(), "Applications");
|
|
5473
|
+
const shelves = existsSync4(apps) ? readdirSync(apps, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith(".localized")).map((d) => join3(apps, d.name)) : [];
|
|
5474
|
+
for (const app of CHROMIUMS) {
|
|
5475
|
+
const id = findPwaId(app);
|
|
5476
|
+
if (!id)
|
|
5477
|
+
continue;
|
|
5478
|
+
const kept = profilesOf(app).map((p) => join3(p, "Web Applications", `_crx_${id}`));
|
|
5479
|
+
const hit = [...shelves, ...kept].flatMap(bundlesIn).find((b) => {
|
|
5480
|
+
try {
|
|
5481
|
+
return readFileSync2(join3(b, "Contents", "Info.plist"), "latin1").includes(id);
|
|
5482
|
+
} catch {
|
|
5483
|
+
return false;
|
|
5484
|
+
}
|
|
5485
|
+
});
|
|
5486
|
+
if (hit)
|
|
5487
|
+
return hit;
|
|
5488
|
+
}
|
|
5489
|
+
return null;
|
|
5490
|
+
}
|
|
5491
|
+
function bundlesIn(dir) {
|
|
5492
|
+
if (!existsSync4(dir))
|
|
5493
|
+
return [];
|
|
5494
|
+
return readdirSync(dir).filter((n) => n.endsWith(".app")).map((n) => join3(dir, n));
|
|
5495
|
+
}
|
|
5444
5496
|
function launchInstalledApp() {
|
|
5445
5497
|
let seen = null;
|
|
5446
5498
|
for (const app of CHROMIUMS) {
|
|
@@ -5671,12 +5723,12 @@ policy
|
|
|
5671
5723
|
// src/deploy/fly.ts
|
|
5672
5724
|
import { randomBytes } from "crypto";
|
|
5673
5725
|
import { Resolver } from "dns/promises";
|
|
5674
|
-
import { existsSync as
|
|
5726
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4, mkdtempSync, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
5675
5727
|
import { tmpdir } from "os";
|
|
5676
5728
|
import { join as join5 } from "path";
|
|
5677
5729
|
|
|
5678
5730
|
// ../shared/src/managed-load.ts
|
|
5679
|
-
import { readFileSync as readFileSync3, statSync } from "fs";
|
|
5731
|
+
import { readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
5680
5732
|
import { userInfo } from "os";
|
|
5681
5733
|
async function plutilJson(path) {
|
|
5682
5734
|
const p = Bun.spawn(["plutil", "-convert", "json", "-o", "-", path], { stdout: "pipe", stderr: "pipe" });
|
|
@@ -5698,7 +5750,7 @@ async function loadManaged(opts = {}) {
|
|
|
5698
5750
|
for (const s of sources) {
|
|
5699
5751
|
let st;
|
|
5700
5752
|
try {
|
|
5701
|
-
st =
|
|
5753
|
+
st = statSync2(s.path);
|
|
5702
5754
|
} catch {
|
|
5703
5755
|
reads.push(s);
|
|
5704
5756
|
continue;
|
|
@@ -5731,12 +5783,12 @@ function refusedByPolicy(verb, m) {
|
|
|
5731
5783
|
}
|
|
5732
5784
|
|
|
5733
5785
|
// src/deploy/context.ts
|
|
5734
|
-
import { cpSync, existsSync as
|
|
5786
|
+
import { cpSync, existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
5735
5787
|
import { join as join4 } from "path";
|
|
5736
5788
|
var bunVersion = package_default.dependencies.bun;
|
|
5737
5789
|
function machineSources() {
|
|
5738
5790
|
const dist = packaged ? here : join4(here, "..", "dist");
|
|
5739
|
-
return
|
|
5791
|
+
return existsSync5(join4(dist, "daemon.js")) ? { dist, cloud: join4(dist, "..", "cloud") } : null;
|
|
5740
5792
|
}
|
|
5741
5793
|
function machinePackageJson() {
|
|
5742
5794
|
const manifest = {
|
|
@@ -5841,7 +5893,7 @@ function secret(env, file) {
|
|
|
5841
5893
|
if (fromEnv)
|
|
5842
5894
|
return fromEnv;
|
|
5843
5895
|
const path = join5(cloudDir, file);
|
|
5844
|
-
return
|
|
5896
|
+
return existsSync6(path) ? readFileSync4(path, "utf8").trim() || null : null;
|
|
5845
5897
|
}
|
|
5846
5898
|
async function capture(bin, args, input) {
|
|
5847
5899
|
const p = Bun.spawn([bin, ...args], {
|
|
@@ -5906,7 +5958,7 @@ async function up(cmd, bin) {
|
|
|
5906
5958
|
throw new DeployError("could not tell which Fly region is closest; pass --region (`fly platform regions` lists them)");
|
|
5907
5959
|
console.log(cmd.region ? `region ${region}` : `region ${region}, the closest to you; --region picks another`);
|
|
5908
5960
|
mkdirSync4(cloudDir, { recursive: true, mode: 448 });
|
|
5909
|
-
if (!
|
|
5961
|
+
if (!existsSync6(tokenFile2(cmd.name)))
|
|
5910
5962
|
writeFileSync3(tokenFile2(cmd.name), randomBytes(32).toString("hex"), { mode: 384 });
|
|
5911
5963
|
const token = readFileSync4(tokenFile2(cmd.name), "utf8").trim();
|
|
5912
5964
|
const app = ["-a", cmd.name];
|
|
@@ -6014,7 +6066,7 @@ async function deploy(cmd) {
|
|
|
6014
6066
|
await up(cmd, bin);
|
|
6015
6067
|
else if (cmd.action === "destroy")
|
|
6016
6068
|
return await destroy(cmd, bin);
|
|
6017
|
-
else if (
|
|
6069
|
+
else if (existsSync6(tokenFile2(cmd.name))) {
|
|
6018
6070
|
await printLinks(cmd.name, readFileSync4(tokenFile2(cmd.name), "utf8").trim());
|
|
6019
6071
|
} else {
|
|
6020
6072
|
throw new DeployError(`${cmd.name} was not deployed from this machine; its token is not in ${cloudDir}`);
|
|
@@ -6029,7 +6081,7 @@ async function deploy(cmd) {
|
|
|
6029
6081
|
}
|
|
6030
6082
|
|
|
6031
6083
|
// src/doctor.ts
|
|
6032
|
-
import { existsSync as
|
|
6084
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
6033
6085
|
|
|
6034
6086
|
// src/sandboxDeps.ts
|
|
6035
6087
|
import { readFileSync as readFileSync5 } from "fs";
|
|
@@ -6147,6 +6199,8 @@ async function doctor() {
|
|
|
6147
6199
|
} else {
|
|
6148
6200
|
const version = h.version ?? "?";
|
|
6149
6201
|
lines.push(line(true, "daemon", `${version} at ${base}, pid ${h.pid ?? "?"}${h.branded ? ", also http://toyon.localhost" : ""}` + (h.lag ? `, event loop worst ${h.lag.max}ms${h.lag.maxCause ? ` (${h.lag.maxCause})` : ""}` : "")));
|
|
6202
|
+
if (h.fdLimit !== undefined && h.fdLimit < FD_LIMIT_LOW)
|
|
6203
|
+
lines.push(line(false, "limits", fdLimitLine(h.fdLimit)));
|
|
6150
6204
|
if (h.remote) {
|
|
6151
6205
|
lines.push(line(true, "remote", `https://${h.remote.host}/ through a TLS front on 127.0.0.1:${port}, previews at ${h.remote.previews}`));
|
|
6152
6206
|
}
|
|
@@ -6189,9 +6243,11 @@ async function doctor() {
|
|
|
6189
6243
|
lines.push(line(false, "shell", `could not fetch: ${e.message}`));
|
|
6190
6244
|
}
|
|
6191
6245
|
}
|
|
6192
|
-
if (
|
|
6193
|
-
const kb = Math.round(
|
|
6194
|
-
|
|
6246
|
+
if (existsSync7(logFile)) {
|
|
6247
|
+
const kb = (p) => Math.round(statSync3(p).size / 1024);
|
|
6248
|
+
const before = previousLog(logFile);
|
|
6249
|
+
const kept = existsSync7(before) ? `, and ${kb(before)} KB kept from before` : "";
|
|
6250
|
+
lines.push(line(true, "log", `${logFile} (${kb(logFile)} KB${kept})`));
|
|
6195
6251
|
}
|
|
6196
6252
|
const width = Math.max(...lines.map((l) => l.label.length));
|
|
6197
6253
|
for (const l of lines) {
|
|
@@ -6226,19 +6282,25 @@ async function helper(args) {
|
|
|
6226
6282
|
return 1;
|
|
6227
6283
|
if (plan.kind === "start")
|
|
6228
6284
|
return 0;
|
|
6285
|
+
let shown = true;
|
|
6229
6286
|
for (const path of plan.paths) {
|
|
6230
6287
|
const res = await post("/open", daemon.token, { path });
|
|
6231
6288
|
if (!res.ok)
|
|
6232
6289
|
console.error(`could not open ${path}: ${await res.text()}`);
|
|
6290
|
+
else if (!(await res.json()).delivered)
|
|
6291
|
+
shown = false;
|
|
6233
6292
|
}
|
|
6234
|
-
|
|
6293
|
+
if (shown)
|
|
6294
|
+
focusShell();
|
|
6295
|
+
else
|
|
6296
|
+
openShell(daemon);
|
|
6235
6297
|
return 0;
|
|
6236
6298
|
}
|
|
6237
6299
|
|
|
6238
6300
|
// src/logs.ts
|
|
6239
|
-
import { existsSync as
|
|
6301
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
|
|
6240
6302
|
async function logs(opts) {
|
|
6241
|
-
if (!
|
|
6303
|
+
if (!existsSync8(logFile)) {
|
|
6242
6304
|
console.log(`no log yet at ${logFile}; it appears once \`toyon\` has started the daemon`);
|
|
6243
6305
|
return opts.follow ? 0 : 1;
|
|
6244
6306
|
}
|
|
@@ -6254,12 +6316,12 @@ async function logs(opts) {
|
|
|
6254
6316
|
`);
|
|
6255
6317
|
if (!opts.follow)
|
|
6256
6318
|
return 0;
|
|
6257
|
-
let offset =
|
|
6319
|
+
let offset = statSync4(logFile).size;
|
|
6258
6320
|
for (;; ) {
|
|
6259
6321
|
await Bun.sleep(300);
|
|
6260
|
-
if (!
|
|
6322
|
+
if (!existsSync8(logFile))
|
|
6261
6323
|
continue;
|
|
6262
|
-
const size =
|
|
6324
|
+
const size = statSync4(logFile).size;
|
|
6263
6325
|
if (size < offset)
|
|
6264
6326
|
offset = 0;
|
|
6265
6327
|
if (size === offset)
|
|
@@ -6280,17 +6342,17 @@ function confirm(question) {
|
|
|
6280
6342
|
}
|
|
6281
6343
|
|
|
6282
6344
|
// src/remote.ts
|
|
6283
|
-
import { existsSync as
|
|
6345
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
6284
6346
|
|
|
6285
6347
|
// ../shared/src/tailscale.ts
|
|
6286
|
-
import { existsSync as
|
|
6348
|
+
import { existsSync as existsSync9, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
6287
6349
|
var dnsName = (raw) => (raw ?? "").replace(/\.$/, "").toLowerCase();
|
|
6288
6350
|
|
|
6289
6351
|
class TailscaleError extends Error {
|
|
6290
6352
|
}
|
|
6291
6353
|
var MAC_APP_CLI = "/Applications/Tailscale.app/Contents/MacOS/Tailscale";
|
|
6292
6354
|
function findTailscale() {
|
|
6293
|
-
return Bun.which("tailscale") ?? (
|
|
6355
|
+
return Bun.which("tailscale") ?? (existsSync9(MAC_APP_CLI) ? MAC_APP_CLI : null);
|
|
6294
6356
|
}
|
|
6295
6357
|
var NOT_INSTALLED = "Tailscale is not installed here (no tailscale on PATH); https://tailscale.com/download";
|
|
6296
6358
|
function tailscaleCli(bin = findTailscale()) {
|
|
@@ -6456,7 +6518,7 @@ async function turnRemoteOff(ts, daemonPort, file, was) {
|
|
|
6456
6518
|
|
|
6457
6519
|
// src/remote.ts
|
|
6458
6520
|
function saved() {
|
|
6459
|
-
if (!
|
|
6521
|
+
if (!existsSync10(remoteFile))
|
|
6460
6522
|
return null;
|
|
6461
6523
|
return parseRemote(readFileSync7(remoteFile, "utf8"));
|
|
6462
6524
|
}
|
|
@@ -6685,11 +6747,11 @@ async function restart() {
|
|
|
6685
6747
|
}
|
|
6686
6748
|
|
|
6687
6749
|
// src/uninstall.ts
|
|
6688
|
-
import { existsSync as
|
|
6750
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8, rmSync as rmSync4 } from "fs";
|
|
6689
6751
|
import { join as join6 } from "path";
|
|
6690
6752
|
function readState() {
|
|
6691
6753
|
const file = join6(home, DAEMON_FILES.state);
|
|
6692
|
-
if (!
|
|
6754
|
+
if (!existsSync11(file))
|
|
6693
6755
|
return {};
|
|
6694
6756
|
try {
|
|
6695
6757
|
return JSON.parse(readFileSync8(file, "utf8"));
|
|
@@ -6718,7 +6780,7 @@ async function uninstall(opts) {
|
|
|
6718
6780
|
const repo = repos.find((r) => r.id === w.repoId);
|
|
6719
6781
|
console.log(` ${w.path} (worktree of ${repo?.path ?? "?"})`);
|
|
6720
6782
|
}
|
|
6721
|
-
if (
|
|
6783
|
+
if (existsSync11(helper))
|
|
6722
6784
|
console.log(` ${helper} (the hidden helper that starts Toyon from the Dock app)`);
|
|
6723
6785
|
console.log("and stops the daemon if it is running.");
|
|
6724
6786
|
console.log("it keeps: your repos, every branch Toyon made" + (branches.length ? ` (${branches.length} under toyon/)` : "") + ", and Toyon's settings in each repo (.toyon/ or toyon.json).");
|
|
@@ -6730,16 +6792,16 @@ async function uninstall(opts) {
|
|
|
6730
6792
|
await stop();
|
|
6731
6793
|
for (const w of worktrees) {
|
|
6732
6794
|
const repo = repos.find((r) => r.id === w.repoId);
|
|
6733
|
-
if (repo &&
|
|
6795
|
+
if (repo && existsSync11(repo.path)) {
|
|
6734
6796
|
const ok = await git(repo.path, "worktree", "remove", "--force", w.path);
|
|
6735
|
-
if (!ok &&
|
|
6797
|
+
if (!ok && existsSync11(w.path))
|
|
6736
6798
|
rmSync4(w.path, { recursive: true, force: true });
|
|
6737
6799
|
await git(repo.path, "worktree", "prune");
|
|
6738
|
-
} else if (
|
|
6800
|
+
} else if (existsSync11(w.path)) {
|
|
6739
6801
|
rmSync4(w.path, { recursive: true, force: true });
|
|
6740
6802
|
}
|
|
6741
6803
|
}
|
|
6742
|
-
if (
|
|
6804
|
+
if (existsSync11(helper)) {
|
|
6743
6805
|
try {
|
|
6744
6806
|
await Bun.spawn([LSREGISTER, "-u", helper], { stdout: "ignore", stderr: "ignore" }).exited;
|
|
6745
6807
|
} catch {}
|
|
@@ -6837,7 +6899,7 @@ async function restartOnto(version) {
|
|
|
6837
6899
|
async function open2(cmd) {
|
|
6838
6900
|
const explicit = cmd.path !== null;
|
|
6839
6901
|
const target = resolve(cmd.path ?? process.cwd());
|
|
6840
|
-
const register = explicit ||
|
|
6902
|
+
const register = explicit || existsSync12(join7(target, ".git"));
|
|
6841
6903
|
if (process.platform === "linux") {
|
|
6842
6904
|
const missing = missingSandboxTools();
|
|
6843
6905
|
const blocked = missing.length === 0 ? bwrapStartError() : null;
|
|
@@ -6849,7 +6911,7 @@ async function open2(cmd) {
|
|
|
6849
6911
|
const daemon = await ensureDaemon();
|
|
6850
6912
|
if (!daemon)
|
|
6851
6913
|
return 1;
|
|
6852
|
-
const file = explicit &&
|
|
6914
|
+
const file = explicit && existsSync12(target) && statSync5(target).isFile();
|
|
6853
6915
|
if (file) {
|
|
6854
6916
|
const res = await post("/open", daemon.token, { path: target });
|
|
6855
6917
|
if (!res.ok) {
|
|
@@ -6857,6 +6919,11 @@ async function open2(cmd) {
|
|
|
6857
6919
|
return 1;
|
|
6858
6920
|
}
|
|
6859
6921
|
const opened = await res.json();
|
|
6922
|
+
if (opened.delivered) {
|
|
6923
|
+
console.log(`toyon: ${target} is open in Toyon`);
|
|
6924
|
+
focusShell();
|
|
6925
|
+
return 0;
|
|
6926
|
+
}
|
|
6860
6927
|
console.log(opened.kind === "file" ? `toyon: opening ${target} in its project` : `toyon: opening ${target}`);
|
|
6861
6928
|
} else if (register) {
|
|
6862
6929
|
const res = await post("/register", daemon.token, { path: target });
|
|
@@ -6872,7 +6939,7 @@ async function start() {
|
|
|
6872
6939
|
const daemon = await ensureDaemon();
|
|
6873
6940
|
if (!daemon)
|
|
6874
6941
|
return 1;
|
|
6875
|
-
console.log(
|
|
6942
|
+
console.log(shellLine(daemon.url));
|
|
6876
6943
|
return 0;
|
|
6877
6944
|
}
|
|
6878
6945
|
async function run(cmd) {
|