@sma1lboy/rove 0.9.266 → 0.9.267
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/dist/cli/{chunk-e69s8s16.js → chunk-02htajas.js} +3 -3
- package/dist/cli/chunk-0bcs1v6n.js +2 -0
- package/dist/cli/{chunk-7wsxppwc.js → chunk-0fejmkz1.js} +1 -1
- package/dist/cli/{chunk-gskbzgc3.js → chunk-0g4wc808.js} +1 -1
- package/dist/cli/chunk-0t0ykzek.js +2 -0
- package/dist/cli/chunk-1b3pq6g6.js +2 -0
- package/dist/cli/{chunk-tz3eftty.js → chunk-1qvrn21x.js} +1 -1
- package/dist/cli/chunk-1z1tjqyy.js +3 -0
- package/dist/cli/{chunk-yk498qwr.js → chunk-1z2sze0v.js} +1 -1
- package/dist/cli/{chunk-3zsm2jbm.js → chunk-2a19815h.js} +2 -2
- package/dist/cli/chunk-2gc4kqrt.js +2 -0
- package/dist/cli/chunk-2geegpp7.js +2 -0
- package/dist/cli/chunk-2jzaabcy.js +11 -0
- package/dist/cli/{chunk-ag3txfg2.js → chunk-2r1fgng9.js} +1 -1
- package/dist/cli/{chunk-n3f5sdka.js → chunk-32j6y5d1.js} +1 -1
- package/dist/cli/{chunk-rbr6qapz.js → chunk-3gegmpff.js} +1 -1
- package/dist/cli/{chunk-8vkma6c4.js → chunk-3nf9zbm7.js} +1 -1
- package/dist/cli/{chunk-zprhxt1q.js → chunk-3qkhxem2.js} +1 -1
- package/dist/cli/chunk-3xrbb1yv.js +2 -0
- package/dist/cli/{chunk-31jxjkrq.js → chunk-48ynmrd8.js} +1 -1
- package/dist/cli/{chunk-b3pm5nvh.js → chunk-4bfwafzg.js} +1 -1
- package/dist/cli/{chunk-8saxdp88.js → chunk-4fa35dbn.js} +1 -1
- package/dist/cli/{chunk-ejd307we.js → chunk-4kdakncb.js} +1 -1
- package/dist/cli/{chunk-mr0z23fd.js → chunk-57qny54a.js} +1 -1
- package/dist/cli/chunk-5d3p4rqv.js +2 -0
- package/dist/cli/{chunk-hc6qpkpy.js → chunk-5m1ef9ez.js} +2 -2
- package/dist/cli/{chunk-wvaf3d9j.js → chunk-5r4d0h87.js} +1 -1
- package/dist/cli/chunk-5vetsh77.js +4 -0
- package/dist/cli/chunk-66zvkh5z.js +2 -0
- package/dist/cli/chunk-6xsc9crp.js +4 -0
- package/dist/cli/{chunk-7c4zdjr5.js → chunk-6z02cd58.js} +1 -1
- package/dist/cli/{chunk-ye4vt96f.js → chunk-7ag59vyh.js} +9 -7
- package/dist/cli/{chunk-hq3hd8qr.js → chunk-7maf6x1g.js} +1 -1
- package/dist/cli/{chunk-3342qzve.js → chunk-7mwvvj46.js} +1 -1
- package/dist/cli/{chunk-me656p3n.js → chunk-835qwnnq.js} +2 -2
- package/dist/cli/chunk-84m0d72d.js +2 -0
- package/dist/cli/chunk-85m74thf.js +31 -0
- package/dist/cli/{chunk-tdhk4dz8.js → chunk-8t7qbr1e.js} +1 -1
- package/dist/cli/{chunk-yztr951z.js → chunk-a0rz9g11.js} +1 -1
- package/dist/cli/{chunk-qpr14v8x.js → chunk-a4znycsh.js} +1 -1
- package/dist/cli/{chunk-kvwqh35r.js → chunk-a569ctz6.js} +1 -1
- package/dist/cli/{chunk-3x0ryj15.js → chunk-acqcph62.js} +1 -1
- package/dist/cli/chunk-ak0frbbw.js +3 -0
- package/dist/cli/chunk-ankt6yse.js +2 -0
- package/dist/cli/{chunk-80jqznbm.js → chunk-av482xxw.js} +1 -1
- package/dist/cli/chunk-awgsda64.js +2 -0
- package/dist/cli/chunk-axjcmamn.js +2 -0
- package/dist/cli/chunk-azpvsc5d.js +2 -0
- package/dist/cli/{chunk-zh0c8yzw.js → chunk-bejhca6z.js} +1 -1
- package/dist/cli/chunk-bm2baazf.js +2 -0
- package/dist/cli/{chunk-wqckm0k6.js → chunk-br8r72bf.js} +1 -1
- package/dist/cli/{chunk-sdya3r5j.js → chunk-bvsjep6w.js} +1 -1
- package/dist/cli/{chunk-1vtfzcca.js → chunk-c1dz3qg3.js} +1 -1
- package/dist/cli/{chunk-2gjrfqhs.js → chunk-c25vea1q.js} +1 -1
- package/dist/cli/{chunk-qwz9728j.js → chunk-cangy5wn.js} +1 -1
- package/dist/cli/chunk-dhcx1gna.js +3 -0
- package/dist/cli/chunk-e7h7w4n0.js +4 -0
- package/dist/cli/{chunk-sr4c9fve.js → chunk-eckrcmtz.js} +1 -1
- package/dist/cli/{chunk-7zyyvc3d.js → chunk-eqa843hf.js} +1 -1
- package/dist/cli/{chunk-n0rtj4z7.js → chunk-eqdbfgq5.js} +1 -1
- package/dist/cli/{chunk-cbc1h345.js → chunk-eyrt04mg.js} +1 -2
- package/dist/cli/{chunk-3126c9x9.js → chunk-f09ex46c.js} +1 -1
- package/dist/cli/{chunk-szjgjrar.js → chunk-f2bqrzsy.js} +1 -1
- package/dist/cli/chunk-f8gg8cqh.js +3 -0
- package/dist/cli/{chunk-wyn3zbh4.js → chunk-f8w52tsz.js} +2 -2
- package/dist/cli/{chunk-qs0526nj.js → chunk-fcnd49ce.js} +1 -1
- package/dist/cli/{chunk-ek6kywem.js → chunk-fcqtqpm1.js} +1 -1
- package/dist/cli/chunk-fjvefbnr.js +16 -0
- package/dist/cli/chunk-fvvb0072.js +3 -0
- package/dist/cli/{chunk-b4zqkdyq.js → chunk-ga412sby.js} +1 -1
- package/dist/cli/{chunk-5v02t4pz.js → chunk-gak4aag4.js} +25 -8
- package/dist/cli/{chunk-vxc90473.js → chunk-gg5f2ayw.js} +1 -1
- package/dist/cli/{chunk-30g1bgkg.js → chunk-ggnq2vvk.js} +1 -1
- package/dist/cli/{chunk-4018sjy3.js → chunk-ghkr7f4t.js} +1 -1
- package/dist/cli/{chunk-41x1hrqe.js → chunk-gq36nzg8.js} +1 -1
- package/dist/cli/{chunk-mh2s5ttr.js → chunk-gqh6atvp.js} +2 -2
- package/dist/cli/{chunk-y078swzq.js → chunk-gs6j7y6q.js} +1 -1
- package/dist/cli/chunk-gytx47yk.js +3 -0
- package/dist/cli/{chunk-1jz7ppsy.js → chunk-h6bbe9nd.js} +1 -1
- package/dist/cli/{chunk-9g2faw9a.js → chunk-h8t4xg1p.js} +1 -1
- package/dist/cli/{chunk-re15t5r1.js → chunk-heajz5tw.js} +1 -1
- package/dist/cli/{chunk-yadx0wc5.js → chunk-hf168gph.js} +1 -1
- package/dist/cli/{chunk-1ys1maw7.js → chunk-hsy5gebc.js} +1 -1
- package/dist/cli/{chunk-cajrtabt.js → chunk-hv79ys32.js} +1 -1
- package/dist/cli/{chunk-mb018hfg.js → chunk-hy0r635n.js} +3 -3
- package/dist/cli/{chunk-812et2xk.js → chunk-j1z9kgyd.js} +1 -1
- package/dist/cli/{chunk-w196jkg5.js → chunk-jj5f4n51.js} +1 -1
- package/dist/cli/{chunk-z80jjarw.js → chunk-jp8vfwqm.js} +1 -1
- package/dist/cli/chunk-kcd1w62f.js +2 -0
- package/dist/cli/{chunk-tshbjft4.js → chunk-ke19jzhg.js} +2 -2
- package/dist/cli/chunk-kq01awhv.js +3 -0
- package/dist/cli/{chunk-kmgheesn.js → chunk-krnacq08.js} +2 -2
- package/dist/cli/{chunk-t6hzyee7.js → chunk-kwyxwcr8.js} +1 -1
- package/dist/cli/chunk-kx7b5nht.js +11 -0
- package/dist/cli/{chunk-a42j8eek.js → chunk-mj7nfaaf.js} +1 -1
- package/dist/cli/{chunk-c47gag5r.js → chunk-mvnz68vh.js} +1 -1
- package/dist/cli/{chunk-j1fe3j54.js → chunk-mzk4p07t.js} +2 -2
- package/dist/cli/chunk-n1tfhd48.js +2 -0
- package/dist/cli/{chunk-rtkj4wdw.js → chunk-n1v59qgs.js} +2 -2
- package/dist/cli/{chunk-drt79f2t.js → chunk-n2j5sk0g.js} +1 -1
- package/dist/cli/chunk-npnbq79j.js +2 -0
- package/dist/cli/{chunk-5srsjs7r.js → chunk-nw4p86t1.js} +1 -1
- package/dist/cli/{chunk-dzmfexh8.js → chunk-p4fjynez.js} +1 -1
- package/dist/cli/{chunk-8sksdq95.js → chunk-p6jw0zcd.js} +1 -1
- package/dist/cli/{chunk-ve348rmz.js → chunk-p9t6ye6t.js} +2 -2
- package/dist/cli/{chunk-amc17enx.js → chunk-pv2334ak.js} +1 -1
- package/dist/cli/chunk-pxdnc5mz.js +91 -0
- package/dist/cli/{chunk-4rya4jmx.js → chunk-qeya7dv5.js} +2 -2
- package/dist/cli/{chunk-6a70wv2b.js → chunk-qgrg9a5n.js} +1 -1
- package/dist/cli/{chunk-4z01vg3t.js → chunk-qnpkhvrn.js} +1 -1
- package/dist/cli/{chunk-cgxgqc87.js → chunk-qykg15ks.js} +1 -1
- package/dist/cli/{chunk-625773dm.js → chunk-r0etc6vp.js} +1 -1
- package/dist/cli/chunk-r40aj7z6.js +2 -0
- package/dist/cli/{chunk-jrqtzp35.js → chunk-r67c54hn.js} +1 -1
- package/dist/cli/chunk-ra1m0gs4.js +3 -0
- package/dist/cli/{chunk-m6pp9gaf.js → chunk-rfp0ayra.js} +1 -1
- package/dist/cli/chunk-rn08whn3.js +20 -0
- package/dist/cli/chunk-s3cvbp3a.js +3 -0
- package/dist/cli/chunk-s4ghfrr9.js +2 -0
- package/dist/cli/chunk-s4nrmbqh.js +13 -0
- package/dist/cli/{chunk-p2vagan3.js → chunk-s7mzpdgb.js} +1 -1
- package/dist/cli/{chunk-tgfn5ykb.js → chunk-sfn4s219.js} +1 -1
- package/dist/cli/chunk-sq6zj3fb.js +5 -0
- package/dist/cli/{chunk-n9w0026r.js → chunk-tca0hx96.js} +1 -1
- package/dist/cli/{chunk-xh72jz7c.js → chunk-tst79jmx.js} +1 -1
- package/dist/cli/{chunk-mtw6nce9.js → chunk-twjt04z3.js} +1 -1
- package/dist/cli/{chunk-qga9xd2f.js → chunk-v8nvfyd4.js} +1 -1
- package/dist/cli/{chunk-m8shvh3j.js → chunk-v967kt9x.js} +1 -1
- package/dist/cli/{chunk-w78n33b8.js → chunk-vckr5yvb.js} +1 -1
- package/dist/cli/{chunk-67qa9eca.js → chunk-vd6z4v6p.js} +1 -1
- package/dist/cli/{chunk-gvmgabps.js → chunk-wa7jswp3.js} +1 -1
- package/dist/cli/{chunk-agt2sdaw.js → chunk-wd9n7cwz.js} +6 -6
- package/dist/cli/chunk-x4s60mnd.js +2 -0
- package/dist/cli/chunk-xex81qeb.js +2 -0
- package/dist/cli/{chunk-bwr6dygx.js → chunk-xfgqae9t.js} +1 -1
- package/dist/cli/chunk-xt543e2h.js +3 -0
- package/dist/cli/{chunk-z72f3d9m.js → chunk-xymn760d.js} +17 -17
- package/dist/cli/chunk-y1xnjx8x.js +4 -0
- package/dist/cli/chunk-y7a8h5xe.js +2 -0
- package/dist/cli/chunk-y8b2p44q.js +2 -0
- package/dist/cli/{chunk-yyjskza5.js → chunk-ycd28edp.js} +1 -1
- package/dist/cli/chunk-yfvt96ar.js +3 -0
- package/dist/cli/{chunk-rwmxpjrx.js → chunk-ykyertq9.js} +1 -1
- package/dist/cli/chunk-yssxs1fn.js +3 -0
- package/dist/cli/{chunk-z3zaa155.js → chunk-yzkhwn31.js} +1 -1
- package/dist/cli/{chunk-prqeddy7.js → chunk-z1nj22va.js} +1 -1
- package/dist/cli/chunk-z7d7gk7p.js +2 -0
- package/dist/cli/{chunk-0sm0wcx9.js → chunk-zg66t7k9.js} +1 -1
- package/dist/cli/chunk-zy2jdze4.js +3 -0
- package/dist/cli/index.js +8 -8
- package/dist/cli/pty-host-node.mjs +29 -7
- package/dist/cli/rove-run.js +1 -1
- package/dist/cli/rove.js +1 -1
- package/dist/completions/rove.bash +1 -1
- package/dist/completions/rove.fish +1 -1
- package/dist/completions/rove.zsh +1 -1
- package/dist/skills/rove/SKILL.md +25 -20
- package/dist/skills/rove/references/api-flags.md +3 -1
- package/dist/web/assets/index-BM0Pt6E-.js +111 -0
- package/dist/web/assets/index-DneB7YXQ.css +1 -0
- package/dist/web/index.html +2 -2
- package/dist/web-ui/assets/{harness-dYkQBfYz.js → harness-pEyVtWV4.js} +1 -1
- package/dist/web-ui/assets/index-Bsn8NuKa.css +1 -0
- package/dist/web-ui/assets/{index-ByMdqeTv.js → index-Dyg-qcgB.js} +2 -2
- package/dist/web-ui/index.html +2 -2
- package/package.json +3 -3
- package/dist/cli/chunk-09sfrqkr.js +0 -2
- package/dist/cli/chunk-1bmhygwd.js +0 -2
- package/dist/cli/chunk-1gawhhd0.js +0 -3
- package/dist/cli/chunk-1nrva2m2.js +0 -11
- package/dist/cli/chunk-1pg3247n.js +0 -16
- package/dist/cli/chunk-2gk96h3f.js +0 -2
- package/dist/cli/chunk-2vrx0pmv.js +0 -2
- package/dist/cli/chunk-4250pw6r.js +0 -3
- package/dist/cli/chunk-4b9f565d.js +0 -2
- package/dist/cli/chunk-4dsyczce.js +0 -2
- package/dist/cli/chunk-4gngf0mt.js +0 -70
- package/dist/cli/chunk-4sj2sqyt.js +0 -2
- package/dist/cli/chunk-56n0whme.js +0 -2
- package/dist/cli/chunk-696sqb6j.js +0 -2
- package/dist/cli/chunk-7nrzkqt5.js +0 -3
- package/dist/cli/chunk-aeswyjhk.js +0 -3
- package/dist/cli/chunk-b39sdtt0.js +0 -3
- package/dist/cli/chunk-b7xjhgts.js +0 -4
- package/dist/cli/chunk-bav3bh70.js +0 -4
- package/dist/cli/chunk-bc72rgkm.js +0 -2
- package/dist/cli/chunk-bnv1mm5h.js +0 -4
- package/dist/cli/chunk-chzn3px6.js +0 -31
- package/dist/cli/chunk-cqsc0wmp.js +0 -20
- package/dist/cli/chunk-g1px1rk6.js +0 -9
- package/dist/cli/chunk-kg8k1rar.js +0 -2
- package/dist/cli/chunk-m86qk3za.js +0 -2
- package/dist/cli/chunk-njvz867e.js +0 -2
- package/dist/cli/chunk-nyw4s1pv.js +0 -2
- package/dist/cli/chunk-pcqw7r50.js +0 -2
- package/dist/cli/chunk-qdvtz853.js +0 -3
- package/dist/cli/chunk-r4vfng2z.js +0 -2
- package/dist/cli/chunk-r6k3ve2g.js +0 -3
- package/dist/cli/chunk-s0gp5b9p.js +0 -10
- package/dist/cli/chunk-s27a0ckk.js +0 -3
- package/dist/cli/chunk-sgngkkp3.js +0 -2
- package/dist/cli/chunk-spee6wv8.js +0 -3
- package/dist/cli/chunk-swxq6yak.js +0 -2
- package/dist/cli/chunk-trhrdby1.js +0 -4
- package/dist/cli/chunk-tvbbnfp2.js +0 -2
- package/dist/cli/chunk-xgans9wf.js +0 -3
- package/dist/cli/chunk-xm7a6swz.js +0 -2
- package/dist/cli/chunk-y87f04kk.js +0 -2
- package/dist/cli/chunk-ywwm92e5.js +0 -2
- package/dist/cli/chunk-z5g3twhn.js +0 -2
- package/dist/cli/chunk-z99ynm4r.js +0 -3
- package/dist/web/assets/index-BsbDxm3K.js +0 -109
- package/dist/web/assets/index-DNv-oxrT.css +0 -1
- package/dist/web-ui/assets/index-nMJ42IGm.css +0 -1
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{RoveKeymap,armPrefixNow,bindingReachability,configurePrefix,currentPrefixConfiguration,dispatchKeyEvent,inputPassthroughReachable,insertRegistration,invokeArmedPrefixAction,isCtrlModifierKeyName,persistedSoundVolume,prefixHudHideDirect,prefixHudShowDirect,readKeybindingsFile,resetKeybindingsFileCache,resetPrefixConfiguration,resetPrefixState,resolveUserKeybindings}from"./chunk-rtkj4wdw.js";import{$Fragment,$jsx,$jsxs,createRoot,flushSync,useRenderer}from"./chunk-29kvfqeh.js";import{RemoteOrchestrator}from"./chunk-7nrzkqt5.js";import{require_react_production}from"./chunk-2wd4744g.js";import{updaterShell,updaterShellFailureHint}from"./chunk-qpr14v8x.js";import{BUNDLED_THEMES,DEFAULT_THEME,DEFAULT_THEME_MODE,TERMINAL_TABS_PREFIX,applyDisplayOverlay,readPersistedUiPrefs,resolveTheme,resolveThemeMode}from"./chunk-z80jjarw.js";import{loadUserThemes}from"./chunk-z3zaa155.js";import{connectIfRunning}from"./chunk-tgfn5ykb.js";import{tildify}from"./chunk-ag3txfg2.js";import{CURRENT_VERSION}from"./chunk-dzmfexh8.js";import{loadStateFile,patchStateFile,readStateFileStrict,replaceStateFile}from"./chunk-n3f5sdka.js";import{kvStatePath}from"./chunk-prqeddy7.js";import{localeState,setLocaleLang,t}from"./chunk-625773dm.js";import{isLocaleId}from"./chunk-xgans9wf.js";import{createStateCell,profileMark,profileTick,recentStateChangesForDiagnostics,renderProfileOn}from"./chunk-cmp64q4j.js";import{installClientCrashHandlers,logClient,logClientError,setClientLogContext}from"./chunk-gskbzgc3.js";import{__toESM}from"./chunk-91sykzqq.js";import{RGBA}from"@opentui/core";var import_react3=__toESM(require_react_production(),1);var import_react=__toESM(require_react_production(),1);function useAccessor(state){return import_react.useSyncExternalStore(state.subscribe,state.get,state.get)}var store=createStateCell({themes:{...BUNDLED_THEMES},active:DEFAULT_THEME,mode:DEFAULT_THEME_MODE,transparentBackground:!0,focusAccent:"primary"});function listThemes(){return Object.keys(store.get().themes)}function hasTheme(name){return Boolean(store.get().themes[name])}function addTheme(name,theme){if(!name)return!1;if(!theme||typeof theme!=="object"||!theme.theme)return!1;return store.update((s)=>({...s,themes:{...s.themes,[name]:theme}})),!0}function selectedTheme(){return store.get().active}function setTheme(name){if(!hasTheme(name))return!1;return store.update((s)=>({...s,active:name})),!0}function transparentBackground(){return store.get().transparentBackground}function setTransparentBackground(v){store.update((s)=>({...s,transparentBackground:v}))}function focusAccent(){return store.get().focusAccent}function setFocusAccent(v){store.update((s)=>({...s,focusAccent:v}))}function themeMode(){return store.get().mode}function setThemeMode(mode){store.update((s)=>({...s,mode}))}var ThemeContext=import_react3.createContext(null),HOST_PALETTE_QUERY_TIMEOUT_MS=2000;function resolveActive(state,mode){let active=state.themes[state.active];if(active)return resolveTheme(active,mode);let fallback=state.themes[DEFAULT_THEME]??Object.values(state.themes)[0];if(!fallback)return resolveTheme({theme:{background:"#000000",text:"#ffffff"}},mode);return resolveTheme(fallback,mode)}function useHostThemeMode(renderer){let[mode,setMode]=import_react3.useState(()=>renderer?.themeMode??null);return import_react3.useEffect(()=>{if(!renderer)return;let onChange=(next)=>setMode(next);return renderer.on("theme_mode",onChange),setMode(renderer.themeMode),()=>{renderer.off("theme_mode",onChange)}},[renderer]),mode}function ThemeProvider(props){import_react3.useMemo(()=>{store.update((s)=>({...s,mode:props.mode??s.mode,active:props.theme&&s.themes[props.theme]?props.theme:s.active}))},[]);let state=useAccessor(store),renderer=useRenderer(),hostMode=useHostThemeMode(renderer),mode=resolveThemeMode(state.mode,hostMode),[hostBackground,setHostBackground]=import_react3.useState(null);import_react3.useEffect(()=>{if(!state.transparentBackground)return;if(renderer?.screenMode==="split-footer")return;if(!renderer)return;let cancelled=!1;return renderer.getPalette({timeout:HOST_PALETTE_QUERY_TIMEOUT_MS}).then((colors)=>{if(cancelled||!colors.defaultBackground)return;setHostBackground(RGBA.fromHex(colors.defaultBackground))}).catch(()=>{}),()=>{cancelled=!0}},[renderer,state.transparentBackground]);let theme=import_react3.useMemo(()=>applyDisplayOverlay(resolveActive(state,mode),state.focusAccent,state.transparentBackground,hostBackground??void 0),[state,mode,hostBackground]);import_react3.useEffect(()=>{if(renderer?.screenMode==="split-footer")return;renderer?.setBackgroundColor(theme.background??RGBA.fromInts(0,0,0))},[renderer,theme]);let value=import_react3.useMemo(()=>({theme,selected:state.active,transparentBackground:state.transparentBackground,focusAccent:state.focusAccent,modePreference:state.mode,mode:()=>mode,set(name){if(!hasTheme(name))return!1;return store.update((s)=>({...s,active:name})),!0},setMode(next){store.update((s)=>({...s,mode:next}))},setTransparentBackground(v){store.update((s)=>({...s,transparentBackground:v}))},setFocusAccent(v){store.update((s)=>({...s,focusAccent:v}))},preview:(options)=>applyDisplayOverlay(resolveActive({...state,active:options.themeName},resolveThemeMode(options.themeMode,hostMode)),options.focusAccent,options.transparentBackground,hostBackground??void 0),all:listThemes,has:hasTheme}),[theme,state,mode,hostMode,hostBackground]);return $jsx(ThemeContext.Provider,{value,children:props.children})}function useTheme(){let value=import_react3.useContext(ThemeContext);if(!value)throw Error("Theme context must be used within a context provider");return value}var import_react4=__toESM(require_react_production(),1);function useLang(){return useAccessor(localeState())}function useT(){let lang=useLang();return import_react4.useCallback((key,params)=>t(key,params),[lang])}var import_react7=__toESM(require_react_production(),1);var CTRL_HOLD_THRESHOLD_MS=400;function createCtrlHoldDetector(callbacks){let state={kind:"idle"},held=new Set,reset=()=>{if(state.kind==="pending")clearTimeout(state.timer);if(state.kind==="visible")callbacks.onHide();state={kind:"idle"}},cancel=()=>{reset(),held.clear()};return{keypress:(event)=>{if(!isCtrlModifierKeyName(event.name)){cancel();return}if(event.eventType==="repeat"&&held.has(event.name))return;if(event.eventType!=="press")return;if(held.add(event.name),state.kind!=="idle")return;state={kind:"pending",timer:setTimeout(()=>{state={kind:"visible"},callbacks.onReveal()},CTRL_HOLD_THRESHOLD_MS)}},keyrelease:(event)=>{if(!isCtrlModifierKeyName(event.name)||event.eventType!=="release")return;if(held.delete(event.name),held.size===0)reset()},cancel}}function availableActions(stack){let seen=new Set,actions=[],passthrough=inputPassthroughReachable(stack);for(let registration of[...stack].reverse()){let config=registration.config();if(config.enabled===!1)continue;for(let binding of config.bindings){if(binding.prefix&¤tPrefixConfiguration().key===null)continue;if(binding.yieldToPassthrough&&passthrough)continue;let chord=`${binding.prefix===!0}:${binding.key}`;if(seen.has(chord))continue;if(seen.add(chord),binding.id&&binding.action)actions.push({owner:registration.id,binding})}if(config.modal)break}return actions}function capturePaletteActions(stack){let seen=new Set;return availableActions(stack).flatMap(({owner,binding})=>{let id=binding.id;if(!id||id==="palette.open"||seen.has(id))return[];return seen.add(id),[{id,key:binding.key,prefix:binding.prefix===!0,run:()=>{let live=availableActions(stack).find((entry)=>entry.owner===owner&&entry.binding.id===id&&entry.binding.key===binding.key&&entry.binding.prefix===binding.prefix);if(!live?.binding.action)return!1;return live.binding.action.run(),!0}}]})}function bindByIds(handlers){let out=[];for(let id in handlers){let handler=handlers[id];if(!handler)continue;let action=typeof handler==="function"?void 0:handler,cmd=typeof handler==="function"?handler:()=>handler.run(),binding=findBinding(id),chords=binding?.keys??[],prefixChords=binding?.prefixKeys??[];if(chords.length===0&&prefixChords.length===0){console.warn(`[rove/keybindings] bindByIds: id="${id}" has no chords (or doesn't exist in RoveKeymap)`);continue}chords.forEach((key,slot)=>out.push({key,cmd,action,slot,id,yieldToPassthrough:binding?.yieldToPassthrough})),prefixChords.forEach((key,slot)=>out.push({key,prefix:!0,cmd,action,slot,id}))}return out}var KEYMAP_DEFAULTS=new Map(RoveKeymap.map((b)=>[b.id,{keys:[...b.keys],prefixKeys:b.prefixKeys&&[...b.prefixKeys],hint:b.hint?{...b.hint}:void 0}]));function defaultChordsOf(id){return KEYMAP_DEFAULTS.get(id)?.keys??[]}function resetKeymapToDefaults(){for(let row of RoveKeymap){let def=KEYMAP_DEFAULTS.get(row.id);if(!def)continue;let mutable=row;mutable.keys=[...def.keys],mutable.prefixKeys=def.prefixKeys&&[...def.prefixKeys],mutable.hint=def.hint?{...def.hint}:void 0}}var keymapVersionValue=0,keymapVersionListeners=new Set;function keymapVersion(){return keymapVersionValue}function subscribeKeymapVersion(listener){return keymapVersionListeners.add(listener),()=>{keymapVersionListeners.delete(listener)}}function bumpKeymapVersion(){keymapVersionValue+=1;for(let listener of[...keymapVersionListeners])listener()}var KEYMAP_BY_ID=new Map(RoveKeymap.map((b)=>[b.id,b]));function findBinding(id){return KEYMAP_BY_ID.get(id)}var MODIFIER_GLYPH={ctrl:"\u2303",control:"\u2303",alt:"\u2325",opt:"\u2325",option:"\u2325",shift:"\u21E7",cmd:"\u2318",command:"\u2318",meta:"\u2318",super:"\u2318"},KEY_GLYPH={enter:"\u23CE",return:"\u23CE",esc:"\u238B",escape:"\u238B",space:"\u2423",up:"\u2191",down:"\u2193",left:"\u2190",right:"\u2192",backspace:"\u232B",delete:"\u2326",del:"\u2326",pgup:"\u21DE",pageup:"\u21DE",pgdn:"\u21DF",pagedown:"\u21DF",home:"\u2196",end:"\u2198"};function formatKey(k,upper){if(k.includes("/"))return k.split("/").map((part)=>formatKey(part,upper)).join("/");let low=k.toLowerCase();if(low==="tab")return"tab";let named=KEY_GLYPH[low];if(named)return named;if(/^f\d{1,2}$/.test(low))return low.toUpperCase();if(!upper)return k;if(/^[a-z]$/.test(low))return k.toUpperCase();return k.replace(/[a-z]+/gi,(run)=>run.toUpperCase())}function formatChord(chord,prefixGlyph="\u2303A"){let s=chord.trim();if(!s)return s;let pm=/^prefix\s+(.+)$/i.exec(s);if(pm){let suffix=pm[1]??"";return`${prefixGlyph} ${suffix.includes("+")?formatChord(suffix,prefixGlyph):formatKey(suffix,!0)}`}let parts=s.split("+");if(parts.length===1)return formatKey(parts[0]??"",!1);let key=parts[parts.length-1]??"";return`${parts.slice(0,-1).map((p)=>MODIFIER_GLYPH[p.toLowerCase().trim()]??p).join("")} ${formatKey(key,!0)}`}var DIRECT_GUIDE_PREFIX_ACTION_ID="prefix.moreCommands",CTRL_FOLLOW_UP_CHORD=/^ctrl\+[^+]+$/;function ctrlFollowUpKey(chord){return CTRL_FOLLOW_UP_CHORD.test(chord)?chord.slice(5):null}function shortcutCaption(input){let binding=findBinding(input.bindingId);if(!binding)return null;if(input.reachability.direct.has(input.bindingId)){let direct=binding.keys[0];if(direct)return formatChord(direct)}if(input.prefixKey&&input.reachability.prefix.has(input.bindingId)){let stroke=binding.prefixKeys?.[0];if(stroke)return`${formatChord(input.prefixKey)} ${formatChord(stroke)}`}return null}function directGuideOptions(reachability,prefixKey){let options=RoveKeymap.filter((binding)=>reachability.direct.has(binding.id)).flatMap((binding)=>{let strokes=binding.keys.flatMap((chord)=>ctrlFollowUpKey(chord)??[]);if(strokes.length>2)return[{stroke:`${strokes[0]}-${strokes.at(-1)}`,action:binding.id}];return strokes.map((stroke)=>({stroke,action:binding.id}))}),prefixStroke=prefixKey?ctrlFollowUpKey(prefixKey):null;if(prefixStroke&&reachability.prefix.size>0)options.push({stroke:prefixStroke,action:DIRECT_GUIDE_PREFIX_ACTION_ID});return options}var import_react5=__toESM(require_react_production(),1);function useLatest(value){let ref=import_react5.useRef(value);return ref.current=value,ref}var ModalScopeContext=import_react7.createContext(null),nextId=1,stack=[],installedRenderer=null,installed=null,listener=null,releaseListener=null,ctrlHoldDetector=null,supersededRenderers=new WeakSet;function ensureInstalled(renderer){if(!renderer)throw Error("useBindings: no renderer in scope; call inside a component rendered by @opentui/react.");if(installedRenderer===renderer)return;if(supersededRenderers.has(renderer))return;if(installed&&listener)installed.off("keypress",listener);if(installed&&releaseListener)installed.off("keyrelease",releaseListener);if(ctrlHoldDetector?.cancel(),installedRenderer)supersededRenderers.add(installedRenderer);stack.length=0,resetPrefixState(),installedRenderer=renderer,installed=renderer.keyInput,ctrlHoldDetector=createCtrlHoldDetector({onReveal:()=>{resetPrefixState();let options=directGuideOptions(bindingReachability(stack),currentPrefixConfiguration().key);if(options.length>0)prefixHudShowDirect(options)},onHide:prefixHudHideDirect}),listener=(evt)=>{profileTick("key"),ctrlHoldDetector?.keypress(evt),dispatchKeyEvent(stack,evt,Date.now(),{flushSync})},releaseListener=(evt)=>ctrlHoldDetector?.keyrelease(evt),installed.on("keypress",listener),installed.on("keyrelease",releaseListener)}function modalActive(){return stack.some((r)=>r.modalOwner!==void 0)}function currentBindingReachability(){return bindingReachability(stack)}function armPrefixFromCurrentStack(){return armPrefixNow(stack)}function invokeArmedPrefixActionFromCurrentStack(actionId,stroke){return invokeArmedPrefixAction(stack,actionId,stroke)}var stackVersion=0,stackListeners=new Set;function bumpStackVersion(){prefixHudHideDirect(),stackVersion++;for(let listener2 of stackListeners)listener2()}function bindingReachabilitySignature(config){let bindings=config.bindings.map((binding)=>[binding.id??"",binding.key,binding.prefix===!0?"p":"d",binding.passthrough===!0?"i":"u"].join(":")).join("|");return`${config.enabled===!1?"off":"on"};${config.modal===!0?"modal":"plain"};${bindings}`}function useBindingStackVersion(){return import_react7.useSyncExternalStore((onChange)=>{return stackListeners.add(onChange),()=>stackListeners.delete(onChange)},()=>stackVersion)}function useBindings(config,opts){let renderer=useRenderer();ensureInstalled(renderer);let configRef=useLatest(config),scope=import_react7.useContext(ModalScopeContext),reachabilitySignature=bindingReachabilitySignature(config()),previousReachabilitySignature=import_react7.useRef(reachabilitySignature);import_react7.useEffect(()=>{if(previousReachabilitySignature.current===reachabilitySignature)return;previousReachabilitySignature.current=reachabilitySignature,bumpStackVersion()},[reachabilitySignature]),import_react7.useEffect(()=>{if(supersededRenderers.has(renderer))return;if(opts?.modalOwner!==void 0)resetPrefixState();let reg={config:()=>configRef.current(),id:nextId++,modalOwner:opts?.modalOwner,modalMember:opts?.modalOwner===void 0?scope??void 0:void 0};return insertRegistration(stack,reg),bumpStackVersion(),()=>{let i=stack.findIndex((r)=>r.id===reg.id);if(i>=0)stack.splice(i,1);bumpStackVersion()}},[])}function pageCloseBindings(cmd){return[{key:"escape",cmd},{key:"q",cmd},{key:"ctrl+c",cmd}]}function currentPaletteActions(){return capturePaletteActions(stack)}import{createCliRenderer}from"@opentui/core";var import_react21=__toESM(require_react_production(),1);async function connectPaneOrchestrator(options={}){let tag=options.logTag??"orch-connect",connect=options.connect??connectIfRunning,remote=null;try{let client=await connect();if(!client)return logClient(tag,"no daemon running \u2014 caller degrades"),null;return remote=new RemoteOrchestrator(client,{...options.orchestratorOptions,channels:options.channels}),await remote.init(),remote}catch(err){return logClientError(tag,err),remote?.dispose(),null}}var cached=null;function applyUserKeybindings(){if(cached)return cached;let{report,prefix}=resolveUserKeybindings(readKeybindingsFile(),RoveKeymap,process.platform);if(report.exists)configurePrefix(prefix);for(let w of report.warnings)console.warn(`[rove/keybindings] ${w}`);return cached=report,cached}function pluginKeybindings(){return userKeybindingsReport().plugins}function userKeybindingsReport(){return cached??applyUserKeybindings()}function reloadUserKeybindings(){cached=null,resetKeybindingsFileCache(),resetKeymapToDefaults(),resetPrefixConfiguration();let report=applyUserKeybindings();return bumpKeymapVersion(),report}var UI_PREFS_FOCUS_ACCENT_SLOTS=["primary","success","info"];var UI_PREFS_THEME_MODES=["dark","light","auto"];function applyUiPrefs(target,prefs){if(typeof prefs.theme==="string"&&prefs.theme.length>0&&prefs.theme!==target.selectedTheme()){if(!target.hasTheme(prefs.theme))target.reloadUserThemes();if(target.hasTheme(prefs.theme))target.setTheme(prefs.theme)}if(prefs.themeMode===null||typeof prefs.themeMode==="string"){let mode=normalizeThemeMode(prefs.themeMode);if(mode&&mode!==target.themeMode())target.setThemeMode(mode)}if(typeof prefs.transparentBackground==="boolean"&&prefs.transparentBackground!==target.transparentBackground())target.setTransparentBackground(prefs.transparentBackground);if(prefs.focusAccent===null||typeof prefs.focusAccent==="string"){let slot=normalizeFocusAccent(prefs.focusAccent);if(slot&&slot!==target.focusAccent())target.setFocusAccent(slot)}}function normalizeFocusAccent(value){if(value===null)return"primary";return UI_PREFS_FOCUS_ACCENT_SLOTS.includes(value)?value:null}function normalizeThemeMode(value){if(value===null)return"dark";return UI_PREFS_THEME_MODES.includes(value)?value:null}var STALL_HEARTBEAT_MS=1000,STALL_THRESHOLD_MS=2000;function stallReport(gapMs,mem,heartbeatMs=STALL_HEARTBEAT_MS,thresholdMs=STALL_THRESHOLD_MS){let stallMs=gapMs-heartbeatMs;if(stallMs<thresholdMs)return null;let mb=(n)=>Math.round(n/1048576);return`event loop stalled ~${stallMs}ms \u2014 rss=${mb(mem.rss)}MB heapUsed=${mb(mem.heapUsed)}MB`}function installEventLoopStallTelemetry(){let last=Date.now(),timer=setInterval(()=>{let now=Date.now(),gap=now-last;last=now;let report=stallReport(gap,process.memoryUsage());if(report)logClient("stall",report)},STALL_HEARTBEAT_MS);return timer.unref?.(),()=>clearInterval(timer)}var KITTY_KEYBOARD={};function hostTargetFps(){return 60}function hostRenderOptions(onDestroy){let base={backgroundColor:"transparent",externalOutputMode:"passthrough",exitOnCtrlC:!1,screenMode:"alternate-screen",useKittyKeyboard:KITTY_KEYBOARD,targetFps:hostTargetFps()};return onDestroy?{...base,onDestroy}:base}function inlineRenderOptions(heightRows,onDestroy){let base={backgroundColor:"transparent",exitOnCtrlC:!1,screenMode:"split-footer",footerHeight:heightRows,useKittyKeyboard:KITTY_KEYBOARD};return onDestroy?{...base,onDestroy}:base}function installExitRestoreBackstop(renderer){process.on("exit",()=>renderer.destroy())}var BRACKETED_PASTE_ON="\x1B[?2004h",BRACKETED_PASTE_OFF="\x1B[?2004l";function installBracketedPasteMode(stdout=process.stdout){if(!stdout.isTTY)return()=>{};let write=(seq)=>{try{stdout.write(seq)}catch{}};write(BRACKETED_PASTE_ON);let restored=!1,restore=()=>{if(restored)return;restored=!0,write(BRACKETED_PASTE_OFF)};return process.on("exit",restore),restore}var exitCriticalWork=new Set;async function whenExitReady(){while(exitCriticalWork.size>0)await Promise.allSettled([...exitCriticalWork])}function installPaneExitBackstop(opts={}){let ceilingMs=opts.ceilingMs??5000,exit=opts.exit??((code)=>process.exit(code)),exitScheduled=!1,exited=!1,exitOnce=()=>{if(exited)return;exited=!0,exit(0)},scheduleExit=()=>{if(exitScheduled)return;exitScheduled=!0;let ceiling=setTimeout(()=>{console.error(`[rove] exit backstop: ${exitCriticalWork.size} task(s) still in flight after ${ceilingMs}ms \u2014 exiting anyway`),exitOnce()},ceilingMs);ceiling.unref?.(),whenExitReady().then(()=>{clearTimeout(ceiling),exitOnce()})};for(let signal of["SIGHUP","SIGTERM","SIGINT"])process.on(signal,scheduleExit)}function installOrphanExitWatchdog(intervalMs=5000){let timer=setInterval(()=>{if(process.ppid===1)process.exit(0)},intervalMs);return timer.unref?.(),()=>clearInterval(timer)}var SYNC_START=Buffer.from("\x1B[?2026h"),SYNC_END=Buffer.from("\x1B[?2026l");class ImeAnchorController{owner=null;anchor=null;claim(owner,anchor){this.owner=owner,this.anchor={x:Math.max(0,Math.trunc(anchor.x)),y:Math.max(0,Math.trunc(anchor.y))}}release(owner){if(this.owner!==owner)return!1;return this.owner=null,this.anchor=null,!0}current(){return this.anchor}}var imeAnchorController=new ImeAnchorController;class ImeAnchorFrameTransformer{controller;pending=Buffer.alloc(0);frame=Buffer.alloc(0);constructor(controller){this.controller=controller}push(chunk){let data=this.pending.length>0?Buffer.concat([this.pending,chunk]):chunk;this.pending=Buffer.alloc(0);let output=[],offset=0;while(offset<data.length){if(this.frame.length===0){let start=data.indexOf(SYNC_START,offset);if(start<0){let tail2=data.subarray(offset),pendingLength2=longestMarkerPrefixSuffix(tail2,[SYNC_START]),safeLength2=tail2.length-pendingLength2;if(safeLength2>0)output.push(tail2.subarray(0,safeLength2));if(pendingLength2>0)this.pending=Buffer.from(tail2.subarray(safeLength2));break}if(start>offset)output.push(data.subarray(offset,start));this.frame=Buffer.from(SYNC_START),offset=start+SYNC_START.length;continue}let end=data.indexOf(SYNC_END,offset),restart=data.indexOf(SYNC_START,offset);if(restart>=0&&(end<0||restart<end)){this.frame=Buffer.from(SYNC_START),offset=restart+SYNC_START.length;continue}if(end>=0){if(end>offset)this.frame=Buffer.concat([this.frame,data.subarray(offset,end)]);output.push(this.frame);let anchor=this.controller.current();if(anchor)output.push(Buffer.from(`\x1B[${anchor.y+1};${anchor.x+1}H\x1B[?25l`));output.push(SYNC_END),this.frame=Buffer.alloc(0),offset=end+SYNC_END.length;continue}let tail=data.subarray(offset),pendingLength=longestMarkerPrefixSuffix(tail,[SYNC_START,SYNC_END]),safeLength=tail.length-pendingLength;if(safeLength>0)this.frame=Buffer.concat([this.frame,tail.subarray(0,safeLength)]);if(pendingLength>0)this.pending=Buffer.from(tail.subarray(safeLength));break}return output.length>0?Buffer.concat(output):Buffer.alloc(0)}flush(){if(this.frame.length>0)return this.frame=Buffer.alloc(0),this.pending=Buffer.alloc(0),Buffer.alloc(0);let pending=this.pending;return this.pending=Buffer.alloc(0),pending}}function longestMarkerPrefixSuffix(bytes,markers){let max=Math.min(bytes.length,Math.max(...markers.map((marker)=>marker.length-1)));for(let length=max;length>0;length-=1){let suffix=bytes.subarray(bytes.length-length);if(markers.some((marker)=>length<marker.length&&suffix.equals(marker.subarray(0,length))))return length}return 0}function asBuffer(chunk,encodingOrCallback){if(typeof chunk!=="string")return Buffer.from(chunk);let encoding=typeof encodingOrCallback==="string"?encodingOrCallback:void 0;return Buffer.from(chunk,encoding)}function writeCallback(encodingOrCallback,maybeCallback){return typeof encodingOrCallback==="function"?encodingOrCallback:maybeCallback}function createImeAnchoredOutput(target,controller=imeAnchorController){let transformer=new ImeAnchorFrameTransformer(controller),exposedWrite=(chunk,encodingOrCallback,maybeCallback)=>{let transformed=transformer.push(asBuffer(chunk,encodingOrCallback)),callback=writeCallback(encodingOrCallback,maybeCallback);if(transformed.length===0){if(callback)queueMicrotask(()=>callback(null));return!0}return callback?target.write(transformed,callback):target.write(transformed)};return{stdout:new Proxy(target,{get(stream,property){if(property==="write")return exposedWrite;let value=Reflect.get(stream,property,stream);return typeof value==="function"?value.bind(stream):value},set(stream,property,value){if(property==="write")return exposedWrite=value,!0;return Reflect.set(stream,property,value,stream)}}),flush(){let pending=transformer.flush();if(pending.length>0)target.write(pending)}}}var IME_ANCHOR_PLATFORMS=new Set(["darwin","win32"]);function createHostImeOutput(opts){if(!IME_ANCHOR_PLATFORMS.has(opts.platform)||!opts.fullscreen)return{active:!1,rendererOptions:{},attach:()=>()=>{},flush:()=>{}};let output=createImeAnchoredOutput(opts.stdout,opts.controller);return{active:!0,rendererOptions:{stdout:output.stdout,remote:!1},attach:(renderer)=>installRendererResizeForwarder(renderer,opts.stdout),flush:()=>output.flush()}}function installRendererResizeForwarder(renderer,terminal,signals=process){let onResize=()=>{let{columns:width,rows:height}=terminal;if(!width||!height)return;renderer.resize(width,height)};return signals.on("SIGWINCH",onResize),()=>signals.removeListener("SIGWINCH",onResize)}function needsScreenSelfHeal(platform){return platform==="win32"}function requestFullRepaint(renderer){if(renderer.screenMode!=="alternate-screen")return!1;let internals=renderer;return internals.forceFullRepaintRequested=!0,renderer.requestRender(),!0}function writeThroughRenderer(renderer,chunk,fallback=process.stdout){let writeOut=renderer?.writeOut;try{if(typeof writeOut==="function")writeOut.call(renderer,chunk);else fallback.write(chunk)}catch{}}function redrawScreen(renderer){if(renderer.screenMode!=="alternate-screen")return!1;return writeThroughRenderer(renderer,"\x1B[H\x1B[2J"),requestFullRepaint(renderer)}function installScreenSelfHeal(opts){let platform=opts.platform??process.platform;if(!needsScreenSelfHeal(platform))return()=>{};let{renderer}=opts,repaint=()=>{requestFullRepaint(renderer)};return renderer.on("resize",repaint),renderer.on("focus",repaint),()=>{renderer.off("resize",repaint),renderer.off("focus",repaint)}}var import_react9=__toESM(require_react_production(),1);var PANE_ORDER=["sidebar","workspace","files","terminal"],FocusContext=import_react9.createContext(null);function FocusProvider(props){let[focused,setFocusedState]=import_react9.useState(props.initial??"sidebar"),renderer=useRenderer(),focusedRef=useLatest(focused),setFocused=import_react9.useCallback((pane)=>{if(focusedRef.current===pane)return;let current=renderer?.currentFocusedRenderable;if(current&&!current.isDestroyed)try{current.blur()}catch{}setFocusedState(pane)},[renderer]),cycle=import_react9.useCallback((delta)=>{let next=(PANE_ORDER.indexOf(focusedRef.current)+delta+PANE_ORDER.length)%PANE_ORDER.length;setFocused(PANE_ORDER[next])},[setFocused]),value=import_react9.useMemo(()=>({focused,is:(pane)=>focused===pane,setFocused,cycle}),[focused,setFocused,cycle]);return $jsx(FocusContext.Provider,{value,children:props.children})}function useFocus(){let ctx=import_react9.useContext(FocusContext);if(!ctx)throw Error("useFocus: must be called inside <FocusProvider>. See src/tui-react/context/focus.tsx.");return ctx}function useOptionalFocus(){return import_react9.useContext(FocusContext)}var import_react10=__toESM(require_react_production(),1);var WRITE_DEBOUNCE_MS=250;function createKvCore(){let store2=createStateCell(loadStateFile(),"kv.snapshot"),dirtyKeys=new Set,quiet=new Map,seeded=new Map,writeTimer=null,errorListeners=new Set,reportedKeys=new Set;function reportWriteError(err){let fresh=[...dirtyKeys].filter((key)=>!reportedKeys.has(key));if(fresh.length===0)return;for(let key of fresh)reportedKeys.add(key);let failure={keys:fresh,file:kvStatePath(),error:err};for(let listener2 of errorListeners)listener2(failure)}function writeNow(label){if(dirtyKeys.size===0)return!0;try{let patch={},snap=store2.get();for(let key of dirtyKeys)patch[key]=quiet.has(key)?quiet.get(key):snap[key];return patchStateFile(patch,"strict"),dirtyKeys.clear(),reportedKeys.clear(),!0}catch(err){return console.error(`[rove] kv ${label} failed:`,err),reportWriteError(err),!1}}function cancelTimer(){if(writeTimer)clearTimeout(writeTimer),writeTimer=null}function scheduleWrite(){cancelTimer(),writeTimer=setTimeout(()=>{writeTimer=null,writeNow("write")},WRITE_DEBOUNCE_MS)}return{snapshot:store2.get,subscribe:store2.subscribe,get(key,defaultValue){return(quiet.has(key)?quiet.get(key):store2.get()[key])??defaultValue},set(key,value){if(key.startsWith(TERMINAL_TABS_PREFIX)){logClientError("kv",Error(`refused a local write of ${key}: tabs go through the daemon`));return}quiet.delete(key),store2.update((s)=>{if(value!==void 0)return{...s,[key]:value};if(!(key in s))return s;let next={...s};return delete next[key],next}),dirtyKeys.add(key),scheduleWrite()},setQuiet(key,value){quiet.set(key,value),dirtyKeys.add(key),scheduleWrite()},seed(key,value){if(!seeded.has(key))seeded.set(key,value);if(quiet.has(key)||store2.get()[key]!==void 0)return;store2.update((s)=>({...s,[key]:value}))},flush(){return cancelTimer(),writeNow("flush")},clear(){try{replaceStateFile({})}catch(err){return console.error("[rove] kv clear write failed:",err),!1}return cancelTimer(),dirtyKeys.clear(),reportedKeys.clear(),quiet.clear(),store2.set({}),!0},reload(){try{readStateFileStrict(),cancelTimer(),writeNow("reload flush");let fresh=readStateFileStrict(),before=store2.get(),next={...fresh};for(let[key,value]of seeded)if(next[key]===void 0)next[key]=value;for(let key of dirtyKeys)if(before[key]===void 0)delete next[key];else next[key]=before[key];for(let key of[...quiet.keys()])if(!dirtyKeys.has(key))quiet.delete(key);if(dirtyKeys.size>0)scheduleWrite();let changed=0;for(let key of new Set([...Object.keys(before),...Object.keys(next)]))if(JSON.stringify(before[key])!==JSON.stringify(next[key]))changed++;if(changed>0)store2.set(next);return{ok:!0,changed}}catch(error){return{ok:!1,error}}},onWriteError(listener2){return errorListeners.add(listener2),()=>{errorListeners.delete(listener2)}}}}var Ctx=import_react10.createContext(null);function KVProvider(props){let[core]=import_react10.useState(createKvCore),snapshot=import_react10.useSyncExternalStore(core.subscribe,core.snapshot,core.snapshot);import_react10.useEffect(()=>{let flush=()=>{core.flush()};return process.on("exit",flush),()=>{process.off("exit",flush)}},[core]);let value=import_react10.useMemo(()=>({ready:!0,store:snapshot,signal(name,defaultValue){return core.seed(name,defaultValue),[()=>core.get(name)??defaultValue,(next)=>core.set(name,next)]},get:core.get,set:core.set,setQuiet:core.setQuiet,flush:core.flush,clear:core.clear,reload:core.reload,onWriteError:core.onWriteError}),[core,snapshot]);return $jsx(Ctx.Provider,{value,children:props.children})}function useKV(){let value=import_react10.useContext(Ctx);if(!value)throw Error("KV context must be used within a context provider");return value}function useOptionalKV(){return import_react10.useContext(Ctx)??null}var import_react13=__toESM(require_react_production(),1);var import_react12=__toESM(require_react_production(),1);var TOAST_DURATION_MS=4500;function unreadKey(taskId,tabId){return`${taskId}:${tabId}`}function addUnread(prev,input){let key=unreadKey(input.taskId,input.tabId),existing=prev.get(key);if(existing==="needs_input"||existing==="error")return prev;let next=new Map(prev);return next.set(key,input.kind),next}function removeUnread(prev,taskId,tabId){let key=unreadKey(taskId,tabId);if(!prev.has(key))return prev;let next=new Map(prev);return next.delete(key),next}function shouldShowToast(kind,toastEnabled){return kind==="error"||toastEnabled}function shouldPlaySound(input,soundEnabled){return soundEnabled&&input.silent!==!0}function attentionKindFor(state){if(state==="permission_needed")return"needs_input";if(state==="error"||state==="rate_limited"||state==="dead")return"error";if(state==="turn_complete")return"done";return null}function chipAttentionKind(turn){if(turn==="done")return"done";if(turn==="error"||turn==="rate_limited"||turn==="dead")return"error";if(turn==="needs_input")return"needs_input";return null}function attentionEdges(prev,next,skip,kindFor){if(prev===null)return[];let out=[];for(let[key,state]of next){if(key===skip)continue;if(prev.get(key)===state)continue;let kind=kindFor(state);if(kind)out.push({key,kind})}return out}function sanitizeOscBody(body){let out="",segmentStart=0;for(let i=0;i<body.length;i++){let code=body.charCodeAt(i);if(code>31&&(code<127||code>159))continue;out+=`${body.slice(segmentStart,i)} `,segmentStart=i+1}return segmentStart===0?body:out+body.slice(segmentStart)}function osc9(body){return`\x1B]9;${sanitizeOscBody(body)}\x07`}import{existsSync,mkdirSync}from"fs";import{tmpdir}from"os";import{basename,delimiter,extname,isAbsolute,join,resolve}from"path";var pulse_default="../pulse-ynhb2ave.wav";function scaleWavVolume(wav,volume){let gain=Math.min(1,Math.max(0,volume));if(wav.length<12)return null;if(wav.readUInt32BE(0)!==1380533830||wav.readUInt32BE(8)!==1463899717)return null;let bitsPerSample,format,data;for(let offset=12;offset+8<=wav.length;){let id=wav.readUInt32BE(offset),size=wav.readUInt32LE(offset+4),start=offset+8,end=start+size;if(size<0||end>wav.length)return null;if(id===1718449184){if(size<16)return null;format=wav.readUInt16LE(start),bitsPerSample=wav.readUInt16LE(start+14)}else if(id===1684108385)data={start,end};offset=end+size%2}if(format!==1||bitsPerSample!==16||!data)return null;if((data.end-data.start)%2!==0)return null;let out=Buffer.from(wav);if(gain===1)return out;for(let i=data.start;i<data.end;i+=2){let scaled=Math.round(out.readInt16LE(i)*gain);out.writeInt16LE(Math.min(32767,Math.max(-32768,scaled)),i)}return out}var pulseAsset=isAbsolute(pulse_default)?pulse_default:resolve(import.meta.dir,pulse_default),DIR=join(tmpdir(),"rove-sfx"),PLAYERS=["ffplay","mpv","mpg123","mpg321","mplayer","afplay","play","omxplayer","aplay","cmdmp3","cvlc","powershell.exe"];function args(player,file){if(player==="ffplay")return[player,"-autoexit","-nodisp",file];if(player==="mpv")return[player,"--no-video","--audio-display=no",file];if(player==="mplayer")return[player,"-vo","null",file];if(player==="cvlc")return[player,"--play-and-exit",file];if(player==="powershell.exe")return[player,"-c",`(New-Object Media.SoundPlayer '${file.replace(/'/g,"''")}').PlaySync()`];return[player,file]}var cachedPlayer,cachedPaths=new Map;function pathDirs(rawPath,delim=delimiter){return rawPath.split(delim).filter(Boolean)}function pickPlayer(){if(cachedPlayer!==void 0)return cachedPlayer;let segments=pathDirs(process.env.PATH??"");return cachedPlayer=PLAYERS.find((p)=>segments.some((dir)=>existsSync(join(dir,p))))??null,cachedPlayer}function assetNameFor(assetPath,volume){let name=basename(assetPath),ext=extname(name);return`${name.slice(0,name.length-ext.length)}@${Math.round(volume*100)}${ext}`}async function ensureAsset(volume){let cached2=cachedPaths.get(volume);if(cached2)return cached2;let pending=(async()=>{mkdirSync(DIR,{recursive:!0});let dest=join(DIR,assetNameFor(pulseAsset,volume)),out=Bun.file(dest);if(await out.exists())return dest;let source=Buffer.from(await Bun.file(pulseAsset).arrayBuffer());return await Bun.write(out,scaleWavVolume(source,volume)??source),dest})();return cachedPaths.set(volume,pending),pending}function pulse(volume=persistedSoundVolume()){if(!(volume>0))return;let player=pickPlayer();if(!player)return;ensureAsset(volume).then((path)=>{try{Bun.spawn(args(player,path),{stdin:"ignore",stdout:"ignore",stderr:"ignore"}).unref?.()}catch{}}).catch(()=>{return})}var ctx=import_react12.createContext(null);function NotificationsProvider(props){let[toasts,setToasts]=import_react12.useState([]),[unread,setUnread]=import_react12.useState(new Map),kv=useOptionalKV(),renderer=useRenderer(),snapshot=import_react12.useMemo(()=>loadStateFile(),[]),prefs=import_react12.useMemo(()=>({"notifications.sound.enabled":kv?.get("notifications.sound.enabled")??snapshot["notifications.sound.enabled"],"notifications.toast.enabled":kv?.get("notifications.toast.enabled")??snapshot["notifications.toast.enabled"]}),[kv,snapshot]),counter=import_react12.useRef(0),timers=import_react12.useRef(new Set);import_react12.useEffect(()=>()=>{for(let id of timers.current)clearTimeout(id);timers.current.clear()},[]);let dismiss=import_react12.useCallback((id)=>{setToasts((prev)=>prev.filter((t2)=>t2.id!==id))},[]),notify=import_react12.useCallback((input)=>{setUnread((prev)=>addUnread(prev,input));let soundEnabled=prefs["notifications.sound.enabled"]!==!1;if(shouldPlaySound(input,soundEnabled))writeThroughRenderer(renderer,`\x07${osc9(`Rove \u2014 ${input.title}`)}`),pulse();let toastEnabled=prefs["notifications.toast.enabled"]!==!1;if(shouldShowToast(input.kind,toastEnabled)){let id=++counter.current;setToasts((prev)=>[...prev,{id,...input}]);let timer=setTimeout(()=>{timers.current.delete(timer),dismiss(id)},TOAST_DURATION_MS);timers.current.add(timer)}},[prefs,dismiss,renderer]),markRead=import_react12.useCallback((taskId,tabId)=>{setUnread((prev)=>removeUnread(prev,taskId,tabId))},[]),value=import_react12.useMemo(()=>({toasts,unread,notify,dismiss,markRead}),[toasts,unread,notify,dismiss,markRead]);return $jsx(ctx.Provider,{value,children:props.children})}function useNotifications(){let value=import_react12.useContext(ctx);if(!value)throw Error("useNotifications must be used within a NotificationsProvider");return value}function useOptionalNotifications(){return import_react12.useContext(ctx)}function KvWriteErrorToasts(){let kv=useOptionalKV(),notifications=useOptionalNotifications();return import_react13.useEffect(()=>{if(!kv||!notifications)return;return kv.onWriteError((failure)=>{notifications.notify({taskId:"",tabId:"",kind:"error",title:t("settings.stateWrite.failedTitle"),body:t("settings.stateWrite.failedBody",{file:tildify(failure.file),keys:failure.keys.join(", ")})})})},[kv,notifications]),null}var import_react17=__toESM(require_react_production(),1);function isNarrowWidth(cols){return cols<70}function narrowSurface(args2){if(args2.focusedPane==="sidebar")return"sidebar";return args2.hasSelection||args2.hasOpenPage?"content":"sidebar"}var import_react15=__toESM(require_react_production(),1);var stores=new WeakMap;function terminalSizeStore(source){let existing=stores.get(source);if(existing)return existing;let listeners=new Set,size={width:source.width,height:source.height},notify=()=>{for(let listener2 of listeners)listener2()},store2={subscribe(listener2){if(listeners.add(listener2),listeners.size===1)source.on("resize",notify);return()=>{if(listeners.delete(listener2),listeners.size===0)source.off("resize",notify)}},snapshot(){if(size.width!==source.width||size.height!==source.height)size={width:source.width,height:source.height};return size}};return stores.set(source,store2),store2}function useTerminalSize(){let store2=terminalSizeStore(useRenderer());return import_react15.useSyncExternalStore(store2.subscribe,store2.snapshot)}function useDialogPaddingX(){let dims=useTerminalSize();return isNarrowWidth(dims.width)?1:2}var DIALOG_CONTENT_OPACITY=0.5,TRANSPARENT_DIALOG_CONTENT_OPACITY=0.75;function Dialog(props){let dimensions=useTerminalSize(),{theme}=useTheme(),renderer=useRenderer(),dismissRef=import_react17.useRef(!1),width=props.size==="xlarge"?140:props.size==="large"?110:props.size==="small"?50:80,VERTICAL_MARGIN=2,upperFifth=props.placement==="upper-fifth"&&!isNarrowWidth(dimensions.width),headerTop=Math.max(2,Math.floor(dimensions.height/5)),cardTop=upperFifth?Math.max(2,headerTop-1):0,maxCardHeight=Math.max(8,upperFifth?dimensions.height-cardTop-2:dimensions.height-4);return $jsx("box",{onMouseDown:()=>{dismissRef.current=!!renderer?.getSelection()},onMouseUp:()=>{if(dismissRef.current){dismissRef.current=!1;return}props.onClose?.()},width:dimensions.width,height:dimensions.height,alignItems:"center",justifyContent:upperFifth?"flex-start":"center",paddingTop:cardTop,position:"absolute",zIndex:3000,left:0,top:0,shouldFill:!1,children:$jsx("box",{onMouseUp:(e)=>{dismissRef.current=!1,e.stopPropagation()},width,maxWidth:dimensions.width-2,maxHeight:maxCardHeight,flexShrink:1,flexGrow:0,backgroundColor:theme.backgroundDialog,paddingTop:1,children:props.children})})}var entrySeq=0,ctx2=import_react17.createContext(null);function DialogProvider(props){let[stack2,setStack]=import_react17.useState([]),[size,setSize]=import_react17.useState("medium"),[placement,setPlacement]=import_react17.useState("center"),renderer=useRenderer(),{transparentBackground:transparentBackground2}=useTheme(),focusRef=import_react17.useRef(null),refocusTimer=import_react17.useRef(null);import_react17.useEffect(()=>()=>{if(refocusTimer.current)clearTimeout(refocusTimer.current)},[]);let refocus=import_react17.useCallback(()=>{if(refocusTimer.current)clearTimeout(refocusTimer.current);refocusTimer.current=setTimeout(()=>{let focus=focusRef.current;if(!focus||focus.isDestroyed)return;function find(item){for(let child of item.getChildren()){if(child===focus)return!0;if(find(child))return!0}return!1}let root=renderer?.root;if(!root)return;if(!find(root))return;focus.focus()},1)},[renderer]),stackRef=useLatest(stack2),captureFocusIfFirst=import_react17.useCallback(()=>{if(refocusTimer.current)clearTimeout(refocusTimer.current);if(stackRef.current.length===0)focusRef.current=renderer?.currentFocusedRenderable??null,focusRef.current?.blur()},[renderer]),dismissTop=import_react17.useCallback(()=>{let selection=renderer?.getSelection();if(selection){if(renderer?.clearSelection(),selection.getSelectedText())return}stackRef.current.at(-1)?.onClose?.(),setStack((s)=>s.slice(0,-1)),refocus()},[renderer,refocus]),value=import_react17.useMemo(()=>({clear(options){for(let item of stackRef.current)item.onClose?.();if(setSize("medium"),setPlacement("center"),setStack([]),options?.refocus===!1)focusRef.current=null;else refocus()},replace(thunk,onClose){captureFocusIfFirst();for(let item of stackRef.current)item.onClose?.();setSize("medium"),setPlacement("center"),setStack([{key:++entrySeq,element:thunk,onClose}])},push(thunk,onClose){captureFocusIfFirst(),setStack((s)=>[...s,{key:++entrySeq,element:thunk,onClose}])},pop(){if(stackRef.current.at(-1)?.onClose?.(),setStack((s)=>s.slice(0,-1)),stackRef.current.length<=1)refocus()},get stack(){return stackRef.current},get size(){return size},setSize,get placement(){return placement},setPlacement}),[stack2,size,placement,refocus,captureFocusIfFirst]),top=stack2.at(-1),contentOpacity=top?transparentBackground2?TRANSPARENT_DIALOG_CONTENT_OPACITY:DIALOG_CONTENT_OPACITY:1;return $jsxs(ctx2.Provider,{value,children:[$jsx("box",{flexGrow:1,backgroundColor:top&&!transparentBackground2?"black":"transparent",children:$jsx("box",{flexGrow:1,opacity:contentOpacity,children:props.children})}),$jsx("box",{position:"absolute",zIndex:3000,children:top?$jsxs(ModalScopeContext,{value:MODAL_SCOPE,children:[$jsx(ModalBarrier,{dismissTop}),$jsx(Dialog,{onClose:()=>value.clear(),size,placement,children:top.element()},top.key)]}):null})]})}var MODAL_SCOPE=Symbol("rove.dialog.modal");function ModalBarrier(props){return useBindings(()=>({modal:!0,bindings:[{key:"escape",cmd:props.dismissTop},{key:"ctrl+c",cmd:props.dismissTop}]}),{modalOwner:MODAL_SCOPE}),null}function useDialog(){let value=import_react17.useContext(ctx2);if(!value)throw Error("useDialog must be used within a DialogProvider");return value}function useOptionalDialog(){return import_react17.useContext(ctx2)}function showDialog(dialog,body,opts){return new Promise((resolve2)=>{if(dialog.replace(()=>body(resolve2),()=>resolve2(void 0)),opts?.size)dialog.setSize(opts.size)})}var import_react18=__toESM(require_react_production(),1);function PaneCrashFallback(props){let{theme}=useTheme(),t2=useT(),sizing=props.width===void 0?{flexGrow:1}:{width:props.width,flexShrink:0};return $jsxs("box",{...sizing,flexDirection:"column",backgroundColor:theme.background,paddingLeft:1,paddingTop:1,gap:1,children:[$jsx("text",{fg:theme.error,wrapMode:"word",children:props.region?t2("common.paneCrash.regionTitle",{region:t2(`common.paneCrash.region.${props.region}`)}):t2("common.paneCrash.title")}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t2(props.region?"common.paneCrash.regionHint":"common.paneCrash.hint")}),$jsx("text",{fg:theme.focusAccent,onMouseUp:props.onRetry,children:t2("common.paneCrash.retry")})]})}function formatPaneCrashDiagnostic(region,error,info){let base=error instanceof Error?error.stack??error.message:String(error),componentStack=info.componentStack?.trim()||"(unavailable)",stateChanges=recentStateChangesForDiagnostics();return`region: ${region??"root"}
|
|
3
|
-
${base}
|
|
4
|
-
React component stack:
|
|
5
|
-
${componentStack}
|
|
6
|
-
Recent state changes:
|
|
7
|
-
${stateChanges.length>0?stateChanges.join(`
|
|
8
|
-
`):"(none recorded)"}`}function sameKeys(a,b){if(a===b)return!0;if(!a||!b||a.length!==b.length)return!1;return a.every((value,i)=>Object.is(value,b[i]))}class PaneErrorBoundary extends import_react18.Component{state={error:null};static getDerivedStateFromError(error){return{error}}componentDidCatch(error,info){logClientError("pane-crash",formatPaneCrashDiagnostic(this.props.region,error,info))}componentDidUpdate(prev){if(this.state.error!==null&&!sameKeys(prev.resetKeys,this.props.resetKeys))this.setState({error:null})}retry=()=>this.setState({error:null});render(){if(this.state.error!==null)return $jsx(PaneCrashFallback,{region:this.props.region,width:this.props.width,onRetry:this.retry});return this.props.children}}var import_react19=__toESM(require_react_production(),1);function countCommit(id){profileTick(`commit.${id}`)}function RenderProfiler(props){if(!renderProfileOn)return props.children;return $jsx(import_react19.Profiler,{id:props.id,onRender:countCommit,children:props.children})}var FALLBACK_THEME=DEFAULT_THEME,themeTarget={selectedTheme,hasTheme,setTheme,reloadUserThemes:()=>{for(let{name,theme}of loadUserThemes())addTheme(name,theme)},themeMode,setThemeMode,transparentBackground,setTransparentBackground,focusAccent,setFocusAccent};function UiPrefsSync(){return import_react21.useEffect(()=>{let disposed=!1,orch=null,disposers=[];return(async()=>{let remote=await connectPaneOrchestrator({logTag:"ui-prefs",channels:["ui-prefs","keybindings"]});if(!remote)return;if(disposed){remote.dispose();return}orch=remote;let applyPrefs=(payload)=>{if(!payload)return;if(applyUiPrefs(themeTarget,payload),isLocaleId(payload.locale))setLocaleLang(payload.locale)},prefsStore=remote.uiPrefsStore();applyPrefs(prefsStore.get()),disposers.push(prefsStore.subscribe(()=>applyPrefs(prefsStore.get())));let revStore=remote.keybindingsRevStore(),lastKeybindingsRev=revStore.get();disposers.push(revStore.subscribe(()=>{let rev=revStore.get();if(rev==null||rev===lastKeybindingsRev)return;let isFirst=lastKeybindingsRev===null;if(lastKeybindingsRev=rev,!isFirst)reloadUserKeybindings()}))})(),()=>{disposed=!0;for(let dispose of disposers)dispose();orch?.dispose()}},[]),null}async function bootPaneHost(opts){if(opts.logContext)setClientLogContext(opts.logContext);installClientCrashHandlers(),applyUserKeybindings();for(let{name,theme}of loadUserThemes())addTheme(name,theme);let prefs=readPersistedUiPrefs(FALLBACK_THEME,hasTheme);applyUiPrefs(themeTarget,{theme:prefs.theme,themeMode:prefs.themeMode,transparentBackground:prefs.transparent,focusAccent:prefs.focusAccent}),setLocaleLang(prefs.locale);let kv=opts.providers?.kv??!1,focus=opts.providers?.focus??!0,notifications=opts.providers?.notifications??!1,screen=await opts.setup(prefs),imeOutput=createHostImeOutput({platform:process.platform,fullscreen:opts.inlineRows===void 0,stdout:process.stdout}),detachImeOutput=()=>{},onDestroy=()=>{detachImeOutput(),imeOutput.flush(),screen.onDestroy?.()},renderer=await createCliRenderer({...opts.inlineRows!==void 0?inlineRenderOptions(opts.inlineRows,onDestroy):hostRenderOptions(onDestroy),...imeOutput.rendererOptions});if(detachImeOutput=imeOutput.attach(renderer),installScreenSelfHeal({renderer}),renderProfileOn)renderer.setFrameCallback(async()=>{profileMark("firstFrame"),profileTick("frame")});let body=$jsxs($Fragment,{children:[$jsx(UiPrefsSync,{}),$jsx(KvWriteErrorToasts,{}),$jsx(PaneErrorBoundary,{children:$jsx(RenderProfiler,{id:"root",children:screen.root()})})]}),withDialog=$jsx(DialogProvider,{children:notifications?$jsx(NotificationsProvider,{children:body}):body}),withFocus=focus?$jsx(FocusProvider,{initial:"sidebar",children:withDialog}):withDialog,withKv=kv?$jsx(KVProvider,{children:withFocus}):withFocus;createRoot(renderer).render($jsx(ThemeProvider,{theme:prefs.theme,children:withKv})),installExitRestoreBackstop(renderer),installBracketedPasteMode(),installPaneExitBackstop(),installOrphanExitWatchdog(),installEventLoopStallTelemetry()}var import_react22=__toESM(require_react_production(),1);import{SyntaxStyle}from"@opentui/core";var INLINE_LINK=/\[([^\]]*)\]\([^)]*\)/g;function releaseNotesMarkdown(body){return body.replace(/\r\n/g,`
|
|
9
|
-
`).replace(INLINE_LINK,"$1").trim()}function buildReleaseNotesStyle(theme){let heading={fg:theme.accent,bold:!0},code={fg:theme.info};return SyntaxStyle.fromStyles({"markup.heading":heading,"markup.heading.1":heading,"markup.heading.2":heading,"markup.heading.3":heading,"markup.heading.4":heading,"markup.heading.5":heading,"markup.heading.6":heading,"markup.strong":{fg:theme.text,bold:!0},"markup.italic":{italic:!0},"markup.strikethrough":{fg:theme.textMuted,dim:!0},"markup.raw":code,"markup.raw.block":code,"markup.list":{fg:theme.textMuted},"markup.list.checked":{fg:theme.success},"markup.list.unchecked":{fg:theme.textMuted},"markup.quote":{fg:theme.textMuted,italic:!0},"markup.link":{fg:theme.info},"markup.link.label":{fg:theme.info},"markup.link.url":{fg:theme.textMuted,dim:!0}})}function ReleaseNotesBody(props){let content=import_react22.useMemo(()=>releaseNotesMarkdown(props.body),[props.body]);return $jsx(MarkdownText,{content})}function MarkdownText(props){let{theme}=useTheme(),syntaxStyle=import_react22.useMemo(()=>buildReleaseNotesStyle(theme),[theme]);return $jsx("markdown",{content:props.content,syntaxStyle,fg:theme.text})}import{spawnSync}from"child_process";function waitForKeypress(){if(!process.stdin.isTTY)return Promise.resolve();return new Promise((resolve2)=>{let stdin=process.stdin,done=()=>{stdin.off("data",done),stdin.setRawMode?.(!1),stdin.pause(),resolve2()};stdin.setRawMode?.(!0),stdin.resume(),stdin.once("data",done)})}async function runShellUpdater(opts){opts.renderer?.destroy(),process.stdout.write(`
|
|
10
|
-
rove ${CURRENT_VERSION} -> ${opts.targetLabel}
|
|
11
|
-
`),process.stdout.write(`running: ${opts.command}
|
|
12
|
-
|
|
13
|
-
`);let shell=updaterShell(),result=spawnSync(shell,["-c",opts.command],{stdio:"inherit"}),code=result.status??(result.error?1:0);if(result.error){process.stderr.write(`
|
|
14
|
-
rove update: failed to start updater (${shell}): ${result.error.message}
|
|
15
|
-
`);let hint=updaterShellFailureHint();if(hint)process.stderr.write(hint)}if(code===0)opts.onSuccess?.();process.stdout.write(code===0?`
|
|
16
|
-
${opts.t("update.updateComplete")}
|
|
17
|
-
`:`
|
|
18
|
-
${opts.t("update.updateFailed",{code:String(code)})}
|
|
19
|
-
`),process.stdout.write(opts.t("update.pressAnyKey")),await waitForKeypress(),process.exit(code)}
|
|
20
|
-
export{useAccessor,useTheme,useT,bindByIds,defaultChordsOf,keymapVersion,subscribeKeymapVersion,findBinding,pluginKeybindings,userKeybindingsReport,reloadUserKeybindings,hostTargetFps,imeAnchorController,redrawScreen,useLatest,useFocus,useOptionalFocus,useKV,useOptionalKV,attentionKindFor,chipAttentionKind,attentionEdges,useNotifications,useOptionalNotifications,formatChord,DIRECT_GUIDE_PREFIX_ACTION_ID,shortcutCaption,modalActive,currentBindingReachability,armPrefixFromCurrentStack,invokeArmedPrefixActionFromCurrentStack,useBindingStackVersion,useBindings,pageCloseBindings,currentPaletteActions,isNarrowWidth,narrowSurface,useTerminalSize,useDialogPaddingX,useDialog,useOptionalDialog,showDialog,PaneErrorBoundary,RenderProfiler,bootPaneHost,ReleaseNotesBody,MarkdownText,runShellUpdater};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{shQuote}from"./chunk-b7xjhgts.js";import{loadStateFile,updateStateFile}from"./chunk-n3f5sdka.js";import{homeDir}from"./chunk-prqeddy7.js";import{shortHomeTag}from"./chunk-n0rtj4z7.js";var LOCAL_MACHINE_ID="local",ALIAS_RE=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function isValidMachineAlias(alias){return alias!==LOCAL_MACHINE_ID&&alias.length<=64&&ALIAS_RE.test(alias)}function parseSshTarget(target){let trimmed=target.trim();if(!trimmed)return null;let at=trimmed.lastIndexOf("@"),user=at>=0?trimmed.slice(0,at):void 0,rest=at>=0?trimmed.slice(at+1):trimmed;if(at>=0&&!user)return null;let bracketed=/^\[([^\]]+)\](?::(\d{1,5}))?$/.exec(rest),portMatch=bracketed?null:/^([^:]*):(\d{1,5})$/.exec(rest),host=bracketed?bracketed[1]??"":portMatch?portMatch[1]??"":rest,rawPort=bracketed?bracketed[2]:portMatch?.[2],port=rawPort?Number(rawPort):void 0;if(!host||/\s/.test(host))return null;if(port!==void 0&&(port<1||port>65535))return null;return{host,...user?{user}:{},...port?{port}:{}}}function defaultMachineAlias(args){let source=!args.typedUser&&args.port===void 0&&!isIpLiteral(args.typedHost)?args.typedHost:args.remoteHostname||args.typedHost;return sanitizeAlias(source)}function isIpLiteral(host){return host.includes(":")||/^\d{1,3}(\.\d{1,3}){3}$/.test(host)}function sanitizeAlias(raw){return(raw.split(".")[0]??raw).replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64)}function sshTargetOf(config){return config.user?`${config.user}@${config.host}`:config.host}function readMachines(state){let raw=state.machines;if(!raw||typeof raw!=="object"||Array.isArray(raw))return{};return raw}function listMachines(){let machines=readMachines(loadStateFile());return Object.entries(machines).map(([alias,config])=>({alias,...config}))}function getMachine(alias){return readMachines(loadStateFile())[alias]??null}function addMachine(alias,config){let added=!1;return updateStateFile((state)=>{let machines={...readMachines(state)};added=machines[alias]===void 0,machines[alias]={...config,addedAt:config.addedAt??machines[alias]?.addedAt??new Date().toISOString()},state.machines=machines;return}),{added}}function updateMachine(alias,patch){updateStateFile((state)=>{let machines={...readMachines(state)},existing=machines[alias];if(!existing)return!1;machines[alias]={...existing,...patch},state.machines=machines;return})}function setMachineIdentity(alias,identity){updateMachine(alias,{identity})}function removeMachine(alias){let removed=!1;return updateStateFile((state)=>{let machines={...readMachines(state)};if(removed=machines[alias]!==void 0,!removed)return!1;delete machines[alias],state.machines=machines;return}),removed}function dedupeMachines(entries){let kept=[],seen=[];for(let entry of entries){let identity=entry.identity;if(identity){if(seen.some((other)=>sameMachine(other,identity)))continue;seen.push(identity)}kept.push(entry)}return kept}function sameMachine(a,b){return a.hostname===b.hostname&&a.homeDir===b.homeDir&&a.daemonPid===b.daemonPid}function duplicateAliasOf(machines,self,identity){for(let[alias,config]of Object.entries(machines)){if(alias===self)continue;let other=config.identity;if(!other)continue;if(other.hostname===identity.hostname&&other.homeDir===identity.homeDir&&other.daemonPid===identity.daemonPid)return alias}return null}import{tmpdir}from"os";import{join}from"path";var CONTROL_PERSIST_SECONDS=300;function machineSocketDir(alias,home=homeDir()){let natural=join(home,".rove","machines",alias);if(Buffer.byteLength(join(natural,"daemon.sock"),"utf8")<=SOCKET_PATH_LIMIT)return natural;return join(tmpdir(),`rove-m-${shortHomeTag(home)}-${shortHomeTag(alias)}`)}var SOCKET_PATH_LIMIT=100;function localDaemonSocketPath(alias,home=homeDir()){return join(machineSocketDir(alias,home),"daemon.sock")}function localPtySocketPath(alias,home=homeDir()){return join(machineSocketDir(alias,home),"pty.sock")}function controlPath(alias,home=homeDir()){return join(machineSocketDir(alias,home),"cm")}function machineSshArgs(alias,config,opts={}){let argv=["ssh"];if(opts.batch!==!1)argv.push("-o","BatchMode=yes");if(opts.mux!==!1&&process.platform!=="win32")argv.push("-o","ControlMaster=auto","-o",`ControlPath=${controlPath(alias,opts.home)}`,"-o",`ControlPersist=${CONTROL_PERSIST_SECONDS}`);if(argv.push("-o","StrictHostKeyChecking=accept-new"),config.port)argv.push("-p",String(config.port));if(config.auth.kind==="key"&&config.auth.keyPath)argv.push("-i",config.auth.keyPath);return argv.push(sshTargetOf(config)),argv}import{spawn}from"child_process";import{mkdirSync}from"fs";import{posix}from"path";var PATTERNS=[["host-key-changed",/REMOTE HOST IDENTIFICATION HAS CHANGED|Host key for .* has changed/i],["host-key-unverified",/Host key verification failed|No .*host key is known for/i],["auth-denied",/Permission denied \(|Too many authentication failures|no matching host key type/i],["unresolved",/Could not resolve hostname|Name or service not known|nodename nor servname/i],["refused",/Connection refused/i],["timeout",/timed out|Operation timed out|No route to host|Network is unreachable/i]];function classifySshFailure(stderr){for(let[kind,pattern]of PATTERNS)if(pattern.test(stderr))return kind;return"unknown"}function sshFailureRemedy(kind,target){switch(kind){case"unresolved":return`${target} does not resolve to an address. Check the name, or the Host block in ~/.ssh/config; on a tailnet, check \`tailscale status\`.`;case"refused":return`${target} refused the connection: nothing listens for ssh there. Enable Remote Login / start sshd on it, or pass the right --port.`;case"timeout":return`${target} did not answer. Is it awake and on this network (or VPN / tailnet)?`;case"host-key-changed":return`${target}'s host key CHANGED since you last connected. That is either a reinstall or someone in the middle. If you reinstalled it, remove the old key with \`ssh-keygen -R <host>\` and retry; otherwise stop here.`;case"host-key-unverified":return`${target}'s host key is not trusted yet. Run \`rove machine add\` in a terminal to confirm its fingerprint, or connect once with \`ssh ${target}\`.`;case"auth-denied":return`${target} rejected every key ssh offered. Load your key into ssh-agent, pass --identity <key>, or install a key there with \`ssh-copy-id ${target}\`.`;case"unknown":return`ssh to ${target} failed. Run \`ssh ${target} true\` to see why.`}}async function runOnMachine(alias,config,command,opts={}){try{mkdirSync(machineSocketDir(alias,opts.home),{recursive:!0,mode:448})}catch{}let argv=[...machineSshArgs(alias,config,{home:opts.home}),command];return await new Promise((resolve)=>{let stdout="",stderr="",settled=!1,done=(exitCode)=>{if(settled)return;settled=!0,clearTimeout(timer),resolve({stdout,stderr,exitCode})},child=spawn(argv[0]??"ssh",argv.slice(1),{stdio:["ignore","pipe","pipe"]}),timer=setTimeout(()=>{child.kill("SIGKILL"),stderr+=`
|
|
3
|
-
timed out`,done(-1)},opts.timeoutMs??30000);child.stdout?.on("data",(c)=>{stdout+=c.toString()}),child.stderr?.on("data",(c)=>{stderr+=c.toString()}),child.on("error",()=>done(-1)),child.on("close",(code)=>done(code??-1))})}async function discoverMachine(alias,config,opts={}){let found=await probe(alias,config,roveCommand(config.roveBin),opts);if(found.ok||found.code!=="NO_ROVE")return found;let located=parseLocatedRove((await runOnMachine(alias,config,LOCATE_ROVE_SCRIPT,opts)).stdout);if(!located||located===config.roveBin)return found;let retry=await probe(alias,config,roveCommand(located),opts);return retry.ok?{...retry,roveBin:located}:retry}function roveCommand(roveBin){if(!roveBin)return"rove";return`PATH=${shQuote(posix.dirname(roveBin))}:"$PATH" ${shQuote(roveBin)}`}var LOCATE_ROVE_SCRIPT=[`p=$("\${SHELL:-sh}" -lc 'command -v rove' 2>/dev/null)`,'if [ -n "$p" ] && [ -x "$p" ]; then echo "ROVE_BIN=$p"; exit 0; fi','for p in "$HOME/.bun/bin/rove" "$HOME/.npm-global/bin/rove" "$HOME/.local/bin/rove" /opt/homebrew/bin/rove /usr/local/bin/rove "$HOME"/.nvm/versions/node/*/bin/rove; do',' if [ -x "$p" ]; then echo "ROVE_BIN=$p"; exit 0; fi',"done","exit 1"].join(`
|
|
4
|
-
`);function parseLocatedRove(stdout){return/^ROVE_BIN=(\/\S.*)$/m.exec(stdout)?.[1]?.trim()??null}var ROVE_MISSING=/(?:^|\W)rove:? (?:command not found|not found)|command not found:? rove|\/rove:? No such file or directory|no such file or directory: \S*\/rove\b/i;async function probe(alias,config,rove,opts){let first=await runOnMachine(alias,config,`${rove} daemon status --json`,opts),parsed=parseStatusJson(first.stdout);if(parsed)return{ok:!0,status:parsed};let combined=`${first.stdout}
|
|
5
|
-
${first.stderr}`.trim();if(ROVE_MISSING.test(combined))return{ok:!1,code:"NO_ROVE",message:`Rove is not installed on ${alias}: not on its PATH, its login shell's PATH, or the usual bun/npm/nvm install dirs. Install it there with \`npm i -g @sma1lboy/rove\`, then re-run.`};if(first.exitCode===255||first.exitCode===-1){let ssh=classifySshFailure(first.stderr),remedy=sshFailureRemedy(ssh,sshTargetOf(config));return{ok:!1,code:"SSH_FAILED",ssh,message:ssh==="unknown"&&combined?`${remedy}
|
|
6
|
-
${combined}`:remedy}}let started=await runOnMachine(alias,config,`${rove} daemon restart`,{...opts,timeoutMs:60000}),second=await runOnMachine(alias,config,`${rove} daemon status --json`,opts),retry=parseStatusJson(second.stdout);if(retry)return{ok:!0,status:retry};if(looksLikeOldStatus(second.stdout))return{ok:!1,code:"BAD_STATUS",message:`${alias} runs a Rove too old for machines (its \`daemon status\` reports no pty socket). Upgrade it: \`ssh ${alias} npm i -g @sma1lboy/rove\`.`};return{ok:!1,code:started.exitCode===0?"BAD_STATUS":"NO_DAEMON",message:`could not read a daemon status from ${alias}: ${`${second.stdout}
|
|
7
|
-
${second.stderr}
|
|
8
|
-
${started.stderr}`.trim()||"no output"}`}}function firstJsonObject(text){let start=text.indexOf("{");if(start<0)return null;let depth=0,inString=!1,escaped=!1;for(let i=start;i<text.length;i++){let ch=text[i];if(inString){if(escaped)escaped=!1;else if(ch==="\\")escaped=!0;else if(ch==='"')inString=!1;continue}if(ch==='"')inString=!0;else if(ch==="{")depth++;else if(ch==="}"&&--depth===0)return text.slice(start,i+1)}return null}function looksLikeOldStatus(stdout){let json=firstJsonObject(stdout);if(json===null)return!1;try{let raw=JSON.parse(json);return typeof raw.socketPath==="string"&&typeof raw.ptySocketPath!=="string"}catch{return!1}}function parseStatusJson(stdout){let json=firstJsonObject(stdout);if(json===null)return null;let raw;try{raw=JSON.parse(json)}catch{return null}if(!raw||typeof raw!=="object")return null;let o=raw,socketPath=typeof o.socketPath==="string"?o.socketPath:"",ptySocketPath=typeof o.ptySocketPath==="string"?o.ptySocketPath:"";if(!socketPath||!ptySocketPath)return null;return{socketPath,ptySocketPath,homeDir:typeof o.homeDir==="string"?o.homeDir:"",hostname:typeof o.hostname==="string"?o.hostname:"",roveVersion:typeof o.roveVersion==="string"?o.roveVersion:"",daemonPid:typeof o.daemonPid==="number"?o.daemonPid:0}}
|
|
9
|
-
export{isValidMachineAlias,parseSshTarget,defaultMachineAlias,sanitizeAlias,sshTargetOf,readMachines,listMachines,getMachine,addMachine,updateMachine,setMachineIdentity,removeMachine,dedupeMachines,duplicateAliasOf,machineSocketDir,localDaemonSocketPath,localPtySocketPath,machineSshArgs,discoverMachine,roveCommand};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ensureForwards,startTunnel}from"./chunk-s27a0ckk.js";import"./chunk-g1px1rk6.js";import"./chunk-b7xjhgts.js";import"./chunk-7kysxgbq.js";import"./chunk-n3f5sdka.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-gskbzgc3.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{startTunnel,ensureForwards};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{TaskIndexStore}from"./chunk-1ys1maw7.js";import"./chunk-qkehg2c1.js";import"./chunk-r6k3ve2g.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-tdhk4dz8.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-gskbzgc3.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{TaskIndexStore};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{machineTasks}from"./chunk-qdvtz853.js";import"./chunk-s27a0ckk.js";import{dedupeMachines,listMachines}from"./chunk-g1px1rk6.js";import"./chunk-31jxjkrq.js";import"./chunk-b7xjhgts.js";import"./chunk-3126c9x9.js";import"./chunk-bwr6dygx.js";import"./chunk-812et2xk.js";import"./chunk-2brn8e1y.js";import"./chunk-7kysxgbq.js";import"./chunk-m6pp9gaf.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-n3f5sdka.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-kmgheesn.js";import"./chunk-szjgjrar.js";import"./chunk-gskbzgc3.js";import"./chunk-pn5ygqn6.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";async function mergeTaskList(local){let machines=dedupeMachines(listMachines());if(machines.length===0)return local;let tasks=(local.tasks??[]).map((task)=>({...task,origin:{machineId:"local",hostLabel:"local"}}));for(let entry of machines){let remote=await machineTasks(entry);if(!remote)continue;let hostLabel=entry.alias;for(let task of remote)tasks.push({...task,origin:{machineId:entry.alias,hostLabel}})}return{tasks}}export{mergeTaskList};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{Orchestrator}from"./chunk-bav3bh70.js";import"./chunk-zprhxt1q.js";import"./chunk-s0gp5b9p.js";import"./chunk-1vtfzcca.js";import{PLACEHOLDER_TASK_TITLE}from"./chunk-cbc1h345.js";import"./chunk-j1fe3j54.js";import"./chunk-41x1hrqe.js";import"./chunk-yk498qwr.js";import"./chunk-sak1tphp.js";import"./chunk-hpay0ax8.js";import"./chunk-catrr0z3.js";import"./chunk-2tfnscxk.js";import"./chunk-9g2faw9a.js";import"./chunk-t7j8g9f6.js";import"./chunk-dmzg9zdc.js";import"./chunk-6xppe9bj.js";import"./chunk-b7xjhgts.js";import"./chunk-2brn8e1y.js";import"./chunk-xy8be792.js";import"./chunk-7kysxgbq.js";import"./chunk-h2m7em1e.js";import"./chunk-m6pp9gaf.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-n3f5sdka.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-cmp64q4j.js";import"./chunk-pn5ygqn6.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{PLACEHOLDER_TASK_TITLE,Orchestrator};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ensureGlobalRoveHooks}from"./chunk-ek6kywem.js";import{publishRoveTerminalTitle}from"./chunk-3aqhytyy.js";import"./chunk-17e2tgyg.js";import"./chunk-2bgmby1d.js";import"./chunk-kvwqh35r.js";import"./chunk-rbr6qapz.js";import"./chunk-2tfnscxk.js";import"./chunk-8saxdp88.js";import"./chunk-w7zv47mp.js";import"./chunk-812et2xk.js";import"./chunk-zsfyj36g.js";import"./chunk-tgfn5ykb.js";import"./chunk-qga9xd2f.js";import"./chunk-5v02t4pz.js";import"./chunk-2brn8e1y.js";import"./chunk-xh72jz7c.js";import"./chunk-7zyyvc3d.js";import"./chunk-r6k3ve2g.js";import"./chunk-xy8be792.js";import"./chunk-7kysxgbq.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-tdhk4dz8.js";import{takeWelcome}from"./chunk-vxc90473.js";import{LAST_RUN_VERSION_KEY,enforceResetGate}from"./chunk-b3pm5nvh.js";import"./chunk-0rrmz6k6.js";import"./chunk-tjj9bt7n.js";import{CURRENT_VERSION,compareSemver}from"./chunk-dzmfexh8.js";import{maybeHintSkillInstall}from"./chunk-wyn3zbh4.js";import"./chunk-m6pp9gaf.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import{loadStateFile,patchStateFile}from"./chunk-n3f5sdka.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-625773dm.js";import"./chunk-xgans9wf.js";import"./chunk-cmp64q4j.js";import"./chunk-kmgheesn.js";import"./chunk-szjgjrar.js";import"./chunk-gskbzgc3.js";import"./chunk-pn5ygqn6.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-91sykzqq.js";var WHATS_NEW_SEEN_KEY="app.whatsNewSeenVersion";function whatsNewFromVersion(state,current=CURRENT_VERSION){let stamped=state[WHATS_NEW_SEEN_KEY]??state[LAST_RUN_VERSION_KEY];if(typeof stamped!=="string"||stamped.length===0)return null;return compareSemver(current,stamped)>0?stamped:null}function takeWhatsNew(){let from=whatsNewFromVersion(loadStateFile());try{patchStateFile({[WHATS_NEW_SEEN_KEY]:CURRENT_VERSION})}catch{}return from}async function startTui(){let whatsNewFrom=takeWhatsNew(),welcome=takeWelcome();enforceResetGate(),publishRoveTerminalTitle(),await maybeHintSkillInstall(),await ensureGlobalRoveHooks();let{loadPluginEngines}=await import("./chunk-ywwm92e5.js");loadPluginEngines();let{startWorkspaceHost}=await import("./chunk-z72f3d9m.js");await startWorkspaceHost({whatsNewFrom,welcome})}export{startTui};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ensureForwards}from"./chunk-s27a0ckk.js";import{dedupeMachines,discoverMachine,listMachines,localDaemonSocketPath,localPtySocketPath,updateMachine}from"./chunk-g1px1rk6.js";import{findCheckouts,isLocalCheckout,parseRepoRef,repoIdentity,unpushedCommits}from"./chunk-31jxjkrq.js";import{ApiError}from"./chunk-3126c9x9.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{getSavedRepos}from"./chunk-m6pp9gaf.js";import{RoveDaemonClient}from"./chunk-kmgheesn.js";import{ROVE_API_VERSION}from"./chunk-szjgjrar.js";import{hostname}from"os";var LOCAL_MACHINE="local";async function machineDaemonSocket(entry){let socketPath=localDaemonSocketPath(entry.alias);if(await answers(socketPath))return socketPath;if(!entry.sockets||!await forward(entry,entry.sockets))return null;if(await answers(socketPath))return socketPath;let found=await discoverMachine(entry.alias,entry);if(!found.ok)return null;let sockets={daemon:found.status.socketPath,pty:found.status.ptySocketPath};return updateMachine(entry.alias,{sockets,...found.roveBin?{roveBin:found.roveBin}:{}}),await forward(entry,sockets)&&await answers(socketPath)?socketPath:null}function forward(entry,sockets){return ensureForwards({alias:entry.alias,config:entry,remoteDaemonSocket:sockets.daemon,remotePtySocket:sockets.pty})}async function answers(socketPath){let client=new RoveDaemonClient(socketPath);try{return await client.request("hello",{}),!0}catch{return!1}finally{client.close()}}async function machineTasks(entry){let socketPath=await machineDaemonSocket(entry);if(!socketPath)return null;let client=new RoveDaemonClient(socketPath);try{return(await client.request("task.list")).tasks??[]}catch{return null}finally{client.close()}}function requireMachine(alias){let entry=listMachines().find((m)=>m.alias===alias);if(entry)return entry;throw new ApiError(`no machine named "${alias}"`,"UNKNOWN_MACHINE",{hint:"list the registered machines and retry with one of their aliases, or register it first",nextCommandArgs:["machine","list"]})}var AUTO_MACHINE="auto",busy=(tasks)=>tasks.filter((task)=>task.status==="in_progress").length;async function pickMachine(localTasks,readTasks=machineTasks,machines=dedupeMachines(listMachines()),hosts){let[local,...remote]=await Promise.all([localTasks().catch(()=>[]),...machines.map((entry)=>readTasks(entry))]),loads={[LOCAL_MACHINE]:busy(local)};machines.forEach((entry,i)=>{let tasks=remote[i];if(tasks)loads[entry.alias]=busy(tasks)});let pool=[null,...machines.filter((entry)=>loads[entry.alias]!==void 0)],skipped;if(hosts){let ok=await Promise.all(pool.map((entry)=>hosts(entry).catch(()=>!1)));if(ok.some(Boolean))skipped=pool.filter((_,i)=>!ok[i]).map((entry)=>entry?.alias??LOCAL_MACHINE),pool=pool.filter((_,i)=>ok[i])}let best=null,bestLoad=Number.POSITIVE_INFINITY;for(let entry of pool){let load=loads[entry?.alias??LOCAL_MACHINE]??0;if(load<bestLoad)best=entry,bestLoad=load}return{entry:best,loads,...skipped?{skipped}:{}}}function repoWanted(repo){if(typeof repo!=="string")return null;let ref=parseRepoRef(repo);if(ref.kind==="id")return{origin:ref.id};return isLocalCheckout(ref.path)?repoIdentity(ref.path):null}function repoHosts(params){if(flagOn(params.clone))return;let want=repoWanted(params.repo);if(!want||!want.origin&&!want.root)return;return async(entry)=>{if(entry===null){if(typeof params.repo==="string"&&parseRepoRef(params.repo).kind==="path")return!0;return getSavedRepos().some((path)=>findCheckouts(want,[{path,identity:repoIdentity(path)??{}}]).length)}let socket=await machineDaemonSocket(entry);if(!socket)return!1;let client=new RoveDaemonClient(socket);try{let res=await client.request("api.invoke",{verb:"repo-match",params:{...want.origin?{origin:want.origin}:{},...want.root?{root:want.root}:{}},forwarded:!0,from:hostname()});return res.ok&&Boolean(res.result.repo)}finally{client.close()}}}async function routeTarget(args){if(args.machine===AUTO_MACHINE){let hosts=args.params?repoHosts(args.params):void 0;return(await pickMachine(args.localTasks??(async()=>[]),machineTasks,void 0,hosts)).entry}if(args.machine!==void 0&&args.machine!==LOCAL_MACHINE)return requireMachine(args.machine);if(args.machine===LOCAL_MACHINE||!args.taskId)return null;let machines=dedupeMachines(listMachines());if(machines.length===0||await args.isLocalTask(args.taskId))return null;for(let entry of machines)if((await machineTasks(entry))?.some((task)=>task.id===args.taskId))return entry;return null}async function forwardVerb(entry,verb,params,socketPath){let target=socketPath??await machineDaemonSocket(entry);if(!target)return offline(entry.alias);let client=new RoveDaemonClient(target);try{let repo=await translateRepo(client,entry.alias,params);if(repo.failure)return repo.failure;if(verb==="land"&¶ms["dry-run"]===void 0){let published=await client.request("api.invoke",{verb:"publish",params:{"task-id":params["task-id"]},forwarded:!0,from:hostname()});if(published.ok||published.error.code!=="UNKNOWN_VERB")return published}return await client.request("api.invoke",{verb,params:repo.params,forwarded:!0,from:hostname()})}catch(err){let message=errorMessage(err);if(/unknown daemon request:/i.test(message))return tooOld(entry.alias);return failure("MACHINE_UNREACHABLE",`machine "${entry.alias}": ${message}`,{hint:"check the machine is up and reachable over ssh, then retry",nextCommandArgs:["machine","list"]})}finally{client.close()}}async function translateRepo(client,alias,params){let repo=params.repo;if(typeof repo!=="string")return{params};let ref=parseRepoRef(repo),local=ref.kind==="path"&&isLocalCheckout(ref.path);if(ref.kind==="path"&&!local)return{params};let identity=ref.kind==="id"?{origin:ref.id}:repoIdentity(repo);if(!identity?.origin&&!identity?.root)return{params};let allowFork=flagOn(params["allow-fork"]),ask=await client.request("api.invoke",{verb:"repo-match",params:{...identity.origin?{origin:identity.origin}:{},...identity.root?{root:identity.root}:{},...allowFork?{"allow-fork":!0}:{}},forwarded:!0,from:hostname()});if(!ask.ok)return ask.error.code==="UNKNOWN_VERB"?{params}:{failure:ask};let answer=ask.result,found=answer.repo;if(found){let base=params["base-branch"],unpushed=local&&typeof base==="string"?unpushedCommits(repo,base):null;if(typeof base==="string"&&unpushed)return{failure:failure("UNPUSHED_BASE",`${base} has ${unpushed} commit${unpushed===1?"":"s"} no remote has; ${alias} cannot base a task on it`,{hint:`push it first (\`git -C ${repo} push -u origin ${base}\`), then dispatch again`})};return{params:{...params,repo:found}}}if(answer.fork)return{failure:failure("FORK_MATCH",`machine "${alias}" only has ${answer.fork}, a fork of ${identity.origin??repo} (same history, other origin)`,{hint:"pass --allow-fork to use it, or --clone with the repo id to fetch the repo itself there"})};if(flagOn(params.clone)&&identity.origin)return{params:{...params,repo:ref.kind==="id"?repo:identity.origin}};return{failure:failure("NO_REMOTE_CHECKOUT",`machine "${alias}" has no checkout of ${identity.origin??repo}`,{hint:identity.origin?`pass --clone to clone it on ${alias}, or --repo with ${alias}'s own path`:`clone it on ${alias} (and open it there once so Rove knows it), or pass --repo with ${alias}'s own path`})}}var flagOn=(value)=>value===!0||value==="true";function offline(alias){return failure("MACHINE_UNREACHABLE",`machine "${alias}" did not answer`,{hint:`check \`ssh ${alias} true\` works without a prompt, then retry`,nextCommandArgs:["machine","list"]})}function tooOld(alias){return failure("MACHINE_VERSION_SKEW",`machine "${alias}" runs a Rove too old to accept forwarded verbs`,{hint:`upgrade Rove on ${alias} (\`rove update\` there), then retry`})}function failure(code,message,data){return{apiVersion:ROVE_API_VERSION,ok:!1,error:{message,code,...data}}}async function invokeRouted(args){if(args.forwarded)return args.runHere();let taskId=args.params["task-id"],target;try{target=await routeTarget({machine:args.machine,taskId:typeof taskId==="string"?taskId:void 0,isLocalTask:args.isLocalTask,...args.localTasks?{localTasks:args.localTasks}:{},params:args.params})}catch(err){if(!(err instanceof ApiError))throw err;return failure(err.code,err.message,err.data??{})}return target?forwardVerb(target,args.verb,args.params):args.runHere()}async function machinePtySocket(alias){let entry=requireMachine(alias);if(!await machineDaemonSocket(entry))throw new ApiError(`machine "${alias}" did not answer`,"MACHINE_UNREACHABLE");return localPtySocketPath(alias)}
|
|
3
|
-
export{LOCAL_MACHINE,machineDaemonSocket,machineTasks,requireMachine,AUTO_MACHINE,pickMachine,repoWanted,repoHosts,routeTarget,forwardVerb,invokeRouted,machinePtySocket};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{readLastActiveTaskId,writeLastActiveTaskId}from"./chunk-1vtfzcca.js";import"./chunk-n3f5sdka.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{writeLastActiveTaskId,readLastActiveTaskId};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{toTaskId}from"./chunk-xy8be792.js";import{coerceVendorId}from"./chunk-h2m7em1e.js";import{DAEMON_MIGRATION_MARKER}from"./chunk-tdhk4dz8.js";import{LockfileError,acquire}from"./chunk-zh0c8yzw.js";import{logClient}from"./chunk-gskbzgc3.js";import{defaultClientLogPath}from"./chunk-n0rtj4z7.js";import{existsSync}from"fs";import{copyFile,readFile}from"fs/promises";import{dirname,join}from"path";function coerceTask(value){if(!value||typeof value!=="object")return null;let v=value;if(typeof v.id!=="string"||typeof v.title!=="string"||typeof v.repo!=="string"||typeof v.branch!=="string"||typeof v.worktreePath!=="string"||typeof v.status!=="string"||typeof v.createdAt!=="string"||typeof v.updatedAt!=="string")return null;if(!isTaskStatus(v.status))return null;let kind=v.kind==="main"?"main":v.kind==="dir"?"dir":"task",scratch=kind==="dir"&&v.scratch===!0,healedStatus=kind==="main"&&(v.status==="in_progress"||v.status==="done")?"backlog":v.status,deletion=coerceDeletion(v.deletion),quotaResume=coerceQuotaResume(v.quotaResume),linkedWorkItem=coerceLinkedWorkItem(v.linkedWorkItem),dispatcher=coerceDispatcher(v.dispatcher),routine=coerceRoutine(v.routine),report=coerceWorkerReport(v.report);return{id:toTaskId(v.id),title:v.title,repo:v.repo,branch:v.branch,worktreePath:v.worktreePath,status:healedStatus,pinned:typeof v.pinned==="boolean"?v.pinned:!1,kind,...scratch?{scratch:!0}:{},...routine?{routine}:{},vendor:coerceVendorId(typeof v.vendor==="string"?v.vendor:void 0),...typeof v.command==="string"&&v.command.trim().length>0?{command:v.command}:{},prStatus:coercePRStatus(v.prStatus),...typeof v.modelEffort==="string"&&v.modelEffort.length>0?{modelEffort:v.modelEffort}:{},...typeof v.model==="string"&&v.model.length>0?{model:v.model}:{},...typeof v.tier==="string"&&v.tier.length>0?{tier:v.tier}:{},...typeof v.groupId==="string"&&v.groupId.length>0?{groupId:v.groupId}:{},...v.observedLanguage==="zh"||v.observedLanguage==="en"?{observedLanguage:v.observedLanguage}:{},...deletion?{deletion}:{},...quotaResume?{quotaResume}:{},...linkedWorkItem?{linkedWorkItem}:{},...dispatcher?{dispatcher}:{},...typeof v.prompt==="string"&&v.prompt.length>0?{prompt:v.prompt}:{},...typeof v.baseRef==="string"&&v.baseRef.trim().length>0?{baseRef:v.baseRef}:{},...typeof v.worktreeName==="string"&&v.worktreeName.trim().length>0?{worktreeName:v.worktreeName}:{},...report?{report}:{},...v.requireReport===!0?{requireReport:!0}:{},createdAt:v.createdAt,updatedAt:v.updatedAt}}function coerceWorkerReport(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.at!=="string"||v.at.length===0)return;return{at:v.at,...typeof v.branch==="string"&&v.branch.length>0?{branch:v.branch}:{},...typeof v.pr==="number"&&Number.isFinite(v.pr)?{pr:v.pr}:{},...typeof v.summary==="string"&&v.summary.length>0?{summary:v.summary}:{}}}function coerceDispatcher(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.taskId!=="string"||v.taskId.length===0)return;if(typeof v.tabId!=="string"||v.tabId.length===0)return;return{taskId:v.taskId,tabId:v.tabId}}function coerceRoutine(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.automationId!=="string"||v.automationId.length===0)return;return{automationId:v.automationId}}function coerceQuotaResume(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.resumeAt!=="string"||v.resumeAt.length===0)return;if(typeof v.requestedAt!=="string"||v.requestedAt.length===0)return;return{resumeAt:v.resumeAt,requestedAt:v.requestedAt}}function coerceLinkedWorkItem(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(v.provider!=="github")return;if(v.type!=="issue"&&v.type!=="pr")return;if(typeof v.number!=="number"||!Number.isFinite(v.number))return;if(typeof v.title!=="string"||typeof v.url!=="string"||v.url.length===0)return;return{provider:v.provider,type:v.type,number:v.number,title:v.title,url:v.url}}function coerceDeletion(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(v.phase!=="queued"&&v.phase!=="running"&&v.phase!=="error"||typeof v.force!=="boolean"||typeof v.requestedAt!=="string"||v.requestedAt.length===0||v.error!==void 0&&typeof v.error!=="string")return;return{phase:v.phase,force:v.force,...typeof v.deleteBranch==="boolean"?{deleteBranch:v.deleteBranch}:{},requestedAt:v.requestedAt,...typeof v.error==="string"?{error:v.error}:{}}}function coercePRStatus(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(!isPRProviderId(v.provider)||!isPRLifecycleState(v.lifecycle)||!isPRCheckState(v.checkState))return;return{provider:v.provider,lifecycle:v.lifecycle,checkState:v.checkState,...typeof v.number==="number"&&Number.isFinite(v.number)?{number:v.number}:{},...typeof v.url==="string"?{url:v.url}:{},...typeof v.title==="string"?{title:v.title}:{},...typeof v.baseRef==="string"?{baseRef:v.baseRef}:{},...typeof v.reviewDecision==="string"?{reviewDecision:v.reviewDecision}:{},...typeof v.mergeable==="string"?{mergeable:v.mergeable}:{},...typeof v.lastCheckedAt==="string"?{lastCheckedAt:v.lastCheckedAt}:{},...typeof v.lastError==="string"?{lastError:v.lastError}:{}}}function isPRProviderId(v){return v==="github"||v==="gitlab"||v==="bitbucket"||v==="unknown"}function isPRLifecycleState(v){return v==="creating"||v==="open"||v==="ready_to_merge"||v==="merged"||v==="closed"||v==="unknown"}function isPRCheckState(v){return v==="none"||v==="pending"||v==="passing"||v==="failing"||v==="unknown"}function isTaskStatus(s){return s==="backlog"||s==="in_progress"||s==="in_review"||s==="done"||s==="canceled"||s==="error"}var sleep=(ms)=>new Promise((resolve)=>setTimeout(resolve,ms)),LOCK_RETRY_DELAY_MS=25,LOCK_MAX_WAIT_MS=5000;async function acquireWithRetry(lockPath){let deadline=Date.now()+LOCK_MAX_WAIT_MS;for(;;)try{return await acquire(lockPath)}catch(err){if(!(err instanceof LockfileError)||Date.now()>=deadline)throw err;await sleep(LOCK_RETRY_DELAY_MS)}}var CURRENT_VERSION=3;async function backupCorruptManifest(path,now=()=>new Date){let backupPath=`${path}.corrupt-${now().toISOString().replaceAll(":","-")}`;try{return await copyFile(path,backupPath),backupPath}catch{return null}}var SUPPORTED_VERSIONS=new Set([1,2,3]);function warnManifestRecovery(message,manifestPath){console.warn(message),logClient("tasks-index",message,manifestPath?defaultClientLogPath(dirname(dirname(manifestPath))):void 0)}async function recoverUnsupportedVersion(parsed,sourcePath){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return!1;let version=parsed.version;if(version===void 0||SUPPORTED_VERSIONS.has(version))return!1;let backup=await backupCorruptManifest(sourcePath);return warnManifestRecovery(`[rove] tasks.json at ${sourcePath} has unsupported version=${String(version)}; recovering with empty index.${backup?` Original bytes backed up to ${backup}.`:" Backup copy failed; the stale file is left in place."}`,sourcePath),!0}function normalizeIndex(parsed,source){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return warnManifestRecovery(`[rove] tasks.json at ${source} is not an object; recovering with empty index.`,source),{version:CURRENT_VERSION,tasks:[]};let obj=parsed,version=obj.version;if(version!==void 0&&!SUPPORTED_VERSIONS.has(version))return warnManifestRecovery(`[rove] tasks.json at ${source} has unsupported version=${String(version)}; recovering with empty index.`,source),{version:CURRENT_VERSION,tasks:[]};let rawTasks=Array.isArray(obj.tasks)?obj.tasks:[],tasks=[];for(let entry of rawTasks){let task=coerceTask(entry);if(task)tasks.push(task);else console.warn(`[rove] dropping malformed task entry from ${source}: ${JSON.stringify(entry)}`)}return{version:CURRENT_VERSION,tasks}}var TOMBSTONE_TTL_MS=2592000000;function readableLegacyIndexPath(canonicalPath,legacyPath){return existsSync(join(dirname(canonicalPath),DAEMON_MIGRATION_MARKER))?void 0:legacyPath}async function readDiskIndex(path,legacyPath){let raw,sourcePath=path;try{raw=await readFile(sourcePath,"utf8")}catch(err){if(err.code!=="ENOENT")throw err;let legacy=readableLegacyIndexPath(path,legacyPath);if(!legacy)return{tasks:[],removed:[]};sourcePath=legacy;try{raw=await readFile(sourcePath,"utf8")}catch(legacyErr){if(legacyErr.code==="ENOENT")return{tasks:[],removed:[]};throw legacyErr}}let parsed;try{parsed=JSON.parse(raw)}catch{return await backupCorruptManifest(sourcePath),{tasks:[],removed:[]}}if(await recoverUnsupportedVersion(parsed,sourcePath))return{tasks:[],removed:[]};return{tasks:normalizeIndex(parsed,sourcePath).tasks,removed:coerceTombstones(parsed)}}function coerceTombstones(parsed){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return[];let raw=parsed.removed;if(!Array.isArray(raw))return[];let out=[];for(let entry of raw){if(!entry||typeof entry!=="object")continue;let v=entry;if(typeof v.id==="string"&&v.id.length>0&&typeof v.at==="string")out.push({id:v.id,at:v.at})}return out}function mergeTasksWithDisk(cacheTasks,diskTasks,dirty,removed,diskRemoved=[],now=Date.now()){let tombstones=new Map;for(let t of diskRemoved){let at=Date.parse(t.at);if(!Number.isFinite(at)||now-at>TOMBSTONE_TTL_MS)continue;tombstones.set(t.id,t.at)}for(let[id,at]of removed)tombstones.set(id,at);let diskById=new Map(diskTasks.map((t)=>[t.id,t])),result=[],included=new Set;for(let task of cacheTasks){if(tombstones.has(task.id))continue;if(dirty.has(task.id))result.push(task);else{let onDisk=diskById.get(task.id);if(onDisk===void 0)continue;result.push(onDisk)}included.add(task.id)}for(let task of diskTasks){if(included.has(task.id)||tombstones.has(task.id))continue;result.push(task),included.add(task.id)}return{tasks:result,removed:[...tombstones].map(([id,at])=>({id,at}))}}async function recoverIndexFromDisk(path,legacyPath){let raw,sourcePath=path;try{raw=await readFile(path,"utf8")}catch(err){if(err.code!=="ENOENT")throw err;let legacy=readableLegacyIndexPath(path,legacyPath),legacyRaw;if(legacy)try{legacyRaw=await readFile(legacy,"utf8"),sourcePath=legacy}catch(legacyErr){if(legacyErr.code!=="ENOENT")throw legacyErr}if(legacyRaw===void 0)return{version:CURRENT_VERSION,tasks:[]};raw=legacyRaw}let parsed;try{parsed=JSON.parse(raw)}catch(err){let backup=await backupCorruptManifest(sourcePath);return warnManifestRecovery(`[rove] tasks.json at ${sourcePath} is corrupted (${err.message}); recovering with empty index.${backup?` Original bytes backed up to ${backup}.`:" Backup copy failed; the stale file is left in place."}`,sourcePath),{version:CURRENT_VERSION,tasks:[]}}if(await recoverUnsupportedVersion(parsed,sourcePath))return{version:CURRENT_VERSION,tasks:[]};return normalizeIndex(parsed,sourcePath)}
|
|
3
|
-
export{acquireWithRetry,readableLegacyIndexPath,readDiskIndex,mergeTasksWithDisk,recoverIndexFromDisk};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{DIRTY_WORKTREE_CODE,canonicalize,describeDirtyWorktreeWork,isRoveManagedPath,isUnderManagedWorktreesRoot,managedWorktreeRootForPath,remoteManagedRootForPath,remoteWorktreePathFor,requireAbsolute,worktreePathFor}from"./chunk-j1fe3j54.js";import{execHostForRepo,execHostForWorktreePath}from"./chunk-yk498qwr.js";import{readFirstNonEmptyRepoFile}from"./chunk-catrr0z3.js";import{parsePorcelainRows}from"./chunk-dmzg9zdc.js";import{READ_ONLY_GIT_ENV}from"./chunk-6xppe9bj.js";import{getRemoteRepoConfig}from"./chunk-m6pp9gaf.js";import{loadStateFile}from"./chunk-n3f5sdka.js";import path5 from"path";function parseDirtyPaths(stdout){return parsePorcelainRows(stdout).filter((row)=>(row.x+row.y).trim().length>0).map((row)=>row.path).filter((p)=>p.length>0)}function isDirtyOutput(stdout){return parseDirtyPaths(stdout).length>0}import fs from"fs/promises";import path from"path";var WORKTREE_CLONE_IGNORED_KEY="worktree.cloneIgnored",DEFAULT_CLONE_DIRS=["node_modules",".venv","target",".build"];function isCloneIgnoredEnabled(){return loadStateFile()[WORKTREE_CLONE_IGNORED_KEY]!==!1}function parseCloneDirs(text){return text.split(/\r?\n/).map((line)=>line.replace(/#.*$/,"").trim()).filter((e)=>e.length>0&&e!=="."&&e!==".."&&!/[/\\]/.test(e)&&!e.startsWith("-"))}function resolveCloneDirs(worktreePath){let file=readFirstNonEmptyRepoFile(worktreePath,"clone-dirs");return file===void 0?DEFAULT_CLONE_DIRS:parseCloneDirs(file)}var CLONEFILEAT_PERL='my $r = syscall(462, -2, $ARGV[0], -2, $ARGV[1], 0); if ($r != 0) { print STDERR "clonefileat: $!\\n"; exit 1 }';function defaultCloneDeps(exec){return{platform:process.platform,statDev:async(p)=>(await fs.stat(p)).dev,isApfs:async(p)=>{let r=await exec.run(["/bin/df","-T","apfs",p]);return r.exitCode===0&&r.stdout.trim().split(`
|
|
3
|
-
`).length>1},clone:async(source,target)=>{let r=await exec.run(["/usr/bin/perl","-e",CLONEFILEAT_PERL,source,target]);if(r.exitCode!==0)throw Error(r.stderr.trim()||`perl exited ${r.exitCode}`)},log:(message)=>console.error(`[rove] ${message}`)}}async function discoverIgnoredDirs(exec,repo,names){let r=await exec.run(["git","ls-files","--others","--ignored","--exclude-standard","--directory","-z"],{cwd:repo,env:READ_ONLY_GIT_ENV});if(r.exitCode!==0)return[];return r.stdout.split("\x00").filter((entry)=>entry.endsWith("/")).map((entry)=>entry.slice(0,-1)).filter((rel)=>names.has(path.posix.basename(rel)))}async function isRealDirectory(p){try{return(await fs.lstat(p)).isDirectory()}catch{return!1}}async function exists(p){try{return await fs.lstat(p),!0}catch{return!1}}function cloneDirNames(exec,worktreePath,deps){if(exec.isRemote||deps.platform!=="darwin"||!isCloneIgnoredEnabled())return[];return resolveCloneDirs(worktreePath)}function regenerableDirNames(exec,worktreePath,deps){return cloneDirNames(exec,worktreePath,deps).filter((name)=>DEFAULT_CLONE_DIRS.includes(name))}async function cloneIgnoredDirs(exec,repo,worktreePath,deps=defaultCloneDeps(exec)){try{let names=new Set(cloneDirNames(exec,worktreePath,deps));if(names.size===0)return[];let apfsByDev=new Map,todo=[];for(let rel of await discoverIgnoredDirs(exec,repo,names)){let source=path.join(repo,rel),target=path.join(worktreePath,rel),targetParent=path.dirname(target);if(!await isRealDirectory(source)||await exists(target)||!await isRealDirectory(targetParent))continue;let dev=await deps.statDev(source);if(dev!==await deps.statDev(targetParent))continue;let apfs=apfsByDev.get(dev);if(apfs===void 0)apfs=await deps.isApfs(source),apfsByDev.set(dev,apfs);if(apfs)todo.push({rel,source,target})}return(await Promise.all(todo.map(async({rel,source,target})=>{try{return await deps.clone(source,target),rel}catch(err){return deps.log(`clone of ignored dir ${rel} into ${worktreePath} failed: ${err instanceof Error?err.message:err}`),null}}))).filter((rel)=>rel!==null)}catch(err){return deps.log(`cloning ignored dirs into ${worktreePath} failed: ${err instanceof Error?err.message:err}`),[]}}var defaultExecDeps={execForRepo:execHostForRepo,execForPath:execHostForWorktreePath,remoteBasePath(repoKey){return getRemoteRepoConfig(repoKey)?.basePath??null}};class GitCommandError extends Error{args;cwd;exitCode;stdout;stderr;constructor(args,cwd,result){super(`git ${args.join(" ")} (cwd=${cwd}) exited with code ${result.exitCode}: ${result.stderr.trim()||result.stdout.trim()}`);this.name="GitCommandError",this.args=args,this.cwd=cwd,this.exitCode=result.exitCode,this.stdout=result.stdout,this.stderr=result.stderr}}import path2 from"path";var MAX_IGNORED_ENTRY_KB=65536;function parseIgnoredPaths(stdoutZ){return stdoutZ.split("\x00").filter((entry)=>entry.startsWith("!! ")).map((entry)=>entry.slice(3)).filter((p)=>p.length>0)}var DU_ARGV_BUDGET_BYTES=98304;function parseDuKb(stdout){let sizes=new Map;for(let line of stdout.split(`
|
|
4
|
-
`)){let m=/^(\d+)\s+(.+)$/.exec(line.trim());if(m?.[1]&&m[2])sizes.set(m[2],Number.parseInt(m[1],10))}return sizes}async function duKb(exec,worktreePath,paths){let sizes=new Map,batch=[],bytes=0,flush=async()=>{if(batch.length===0)return;let du=await exec.run(["du","-sk","--",...batch],{cwd:worktreePath});for(let[p,kb]of parseDuKb(du.stdout))sizes.set(p,kb);batch.length=0,bytes=0};for(let p of paths){if(p.includes(`
|
|
5
|
-
`)){let one=await exec.run(["du","-sk","--",p],{cwd:worktreePath}),kb=/^\s*(\d+)/.exec(one.stdout)?.[1];if(one.exitCode===0&&kb)sizes.set(p,Number.parseInt(kb,10));continue}if(bytes+p.length+1>DU_ARGV_BUDGET_BYTES)await flush();batch.push(p),bytes+=p.length+1}return await flush(),sizes}async function smallIgnoredPaths(exec,worktreePath,regenerable=[]){try{let status=await exec.run(["git","status","--porcelain","-z","--ignored"],{cwd:worktreePath,env:READ_ONLY_GIT_ENV});if(status.exitCode!==0)return"unknown";let paths=parseIgnoredPaths(status.stdout).filter((p)=>!regenerable.includes(path2.posix.basename(p.replace(/\/$/,""))));if(paths.length===0)return[];let sizes=await duKb(exec,worktreePath,paths);return paths.filter((p)=>{let kb=sizes.get(p);return kb!==void 0&&kb<=MAX_IGNORED_ENTRY_KB})}catch{return"unknown"}}async function gitlinkPaths(git,tree){let out=await git(["ls-tree","-r",tree]);if(out.exitCode!==0)return[];return out.stdout.split(`
|
|
6
|
-
`).filter((line)=>line.startsWith("160000 ")).map((line)=>line.slice(line.indexOf("\t")+1)).filter((p)=>p.length>0)}function branchRefSlug(branch){return(branch??"").replace(/[\u0000-\u0020\u007f~^:?*[\\/]+/g,"-").replace(/@\{/g,"-").replace(/\.{2,}/g,"-").replace(/^[-.]+|[-.]+$/g,"")||"detached"}function salvageRef(branch,now){let stamp=now.toISOString().replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");return`refs/rove/salvage/${branchRefSlug(branch)}-${stamp}`}async function createSalvageRef(git,preferred,commit){for(let attempt=1;attempt<=50;attempt++){let ref=attempt===1?preferred:`${preferred}-${attempt}`;if((await git(["update-ref",ref,commit,""])).exitCode===0)return ref}return null}async function salvageWorktree(deps,exec,worktreePath,now=new Date){let git=(args)=>deps.runGit(exec,args,{cwd:worktreePath,allowFail:!0});try{let status=await git(["status","--porcelain"]);if(status.exitCode!==0)return null;let probe=await smallIgnoredPaths(exec,worktreePath),ignored=probe==="unknown"?[]:probe;if(status.stdout.trim().length===0&&ignored.length===0)return null;let indexPath=(await git(["rev-parse","--git-path","rove-salvage-index"])).stdout.trim();if(!indexPath)return null;let withIndex=(args)=>deps.runGit(exec,args,{cwd:worktreePath,allowFail:!0,env:{GIT_INDEX_FILE:indexPath}}),head=(await git(["rev-parse","HEAD"])).stdout.trim(),branch=(await git(["rev-parse","--abbrev-ref","HEAD"])).stdout.trim();try{if(head&&(await withIndex(["read-tree",head])).exitCode!==0)return null;if((await withIndex(["add","-A"])).exitCode!==0)return null;if(ignored.length>0)await withIndex(["add","-f","--",...ignored]);let tree=(await withIndex(["write-tree"])).stdout.trim();if(!tree)return null;let message=`rove salvage: force-removed worktree ${worktreePath}`,commit=(await withIndex(head?["commit-tree",tree,"-p",head,"-m",message]:["commit-tree",tree,"-m",message])).stdout.trim();if(!commit)return null;let ref=await createSalvageRef(git,salvageRef(branch&&branch!=="HEAD"?branch:null,now),commit);if(!ref)return null;return{ref,commit,uncaptured:await gitlinkPaths(git,tree)}}finally{await exec.run(["rm","-f",indexPath],{cwd:worktreePath}).catch(()=>{return})}}catch{return null}}async function anchorBranchTip(deps,exec,repo,branch,now=new Date){if(!branch||branch==="HEAD")return null;let git=(args)=>deps.runGit(exec,args,{cwd:repo,allowFail:!0});try{let tipOut=await git(["rev-parse","--verify",`refs/heads/${branch}`]),tip=tipOut.stdout.trim();if(tipOut.exitCode!==0||!tip)return null;let holders=await git(["for-each-ref","--contains",tip,"--format=%(refname)"]);if(holders.exitCode===0){if(holders.stdout.split(`
|
|
7
|
-
`).map((l)=>l.trim()).filter((l)=>l.length>0&&l!==`refs/heads/${branch}`).length>0)return null}let ref=salvageRef(branch,now);if((await git(["update-ref",ref,tip])).exitCode!==0)return null;return{ref,commit:tip,uncaptured:[]}}catch{return null}}async function branchExists(deps,ctx,branch){return(await deps.runGit(ctx.exec,["show-ref","--verify","--quiet",`refs/heads/${branch}`],{cwd:ctx.dir,allowFail:!0,readOnly:!0})).exitCode===0}async function deleteBranchIn(deps,exec,repo,branch,force){if(!branch||branch==="HEAD")return{deleted:!1,reason:"no branch to delete"};let out=await deps.runGit(exec,["branch",force?"-D":"-d",branch],{cwd:repo,allowFail:!0});if(out.exitCode===0)return{deleted:!0};if(!await branchExists(deps,{exec,dir:repo,remote:exec.isRemote},branch))return{deleted:!0};return{deleted:!1,reason:out.stderr.trim()||out.stdout.trim()||`git branch exited ${out.exitCode}`}}async function deleteBranchAnchored(deps,exec,repo,branch,opts){if(opts.force)opts.onAnchor?.(await anchorBranchTip(deps,exec,repo,branch));return await deleteBranchIn(deps,exec,repo,branch,opts.force)}async function branchHasUpstream(deps,worktreePath,branch){return(await deps.runGit(deps.execAt(worktreePath),["for-each-ref","--format=%(upstream)",`refs/heads/${branch}`],{cwd:worktreePath,readOnly:!0})).stdout.trim().length>0}async function hasLocalBranch(deps,worktreePath,branch){return(await deps.runGit(deps.execAt(worktreePath),["show-ref","--verify","--quiet",`refs/heads/${branch}`],{cwd:worktreePath,allowFail:!0,readOnly:!0})).exitCode===0}async function renameBranch(deps,worktreePath,from,to){let exec=deps.execAt(worktreePath);if(from===to)return;let repo=await deps.findRepoFor(exec,worktreePath);if(!repo)throw Error(`renameBranch(): ${worktreePath} is not a git worktree`);let out=await deps.runGit(exec,["branch","-m",from,to],{cwd:repo,allowFail:!0});if(out.exitCode===0)return;let ctx={exec,dir:repo,remote:exec.isRemote};if(!await branchExists(deps,ctx,from)&&await branchExists(deps,ctx,to))return;throw new GitCommandError(["branch","-m",from,to],repo,out)}import fs2 from"fs";import path3 from"path";async function mapWithLimit(items,limit,fn){let results=Array(items.length),next=0,worker=async()=>{for(;;){let i=next++;if(i>=items.length)return;results[i]=await fn(items[i])}},width=Math.max(1,Math.min(limit,items.length));return await Promise.all(Array.from({length:width},worker)),results}var PROBE_CONCURRENCY=6;function parseWorktreeListPorcelain(out){let records=[],current=null;for(let rawLine of out.split(`
|
|
8
|
-
`)){let line=rawLine.replace(/\r$/,"");if(line===""){if(current)records.push(current);current=null;continue}if(!current)current={};if(line.startsWith("worktree "))current.path=line.slice(9);else if(line.startsWith("HEAD "))current.head=line.slice(5);else if(line.startsWith("branch ")){let ref=line.slice(7);current.branch=ref.startsWith("refs/heads/")?ref.slice(11):ref}else if(line==="detached")current.detached=!0;else if(line==="bare")current.bare=!0}if(current)records.push(current);return records}async function lastActivityMs(deps,ctx,worktreePath){try{let stdout=await deps.runGitStdoutAt(ctx,worktreePath,["log","-1","--format=%ct"]),secs=Number.parseInt(stdout.trim(),10);if(Number.isFinite(secs)&&secs>0)return secs*1000}catch{}if(!ctx.exec.isRemote)try{return fs2.statSync(worktreePath).mtimeMs}catch{}return 0}async function listBranchNames(deps,repo){let ctx=deps.ctxFor(repo);requireAbsolute("repo",ctx.dir);let stdout;try{stdout=await deps.runGitStdout(ctx,["for-each-ref","--format=%(refname)","refs/heads","refs/remotes/origin"])}catch{return[]}let names=new Set;for(let line of stdout.split(`
|
|
9
|
-
`)){let name=line.trim().replace(/^refs\/(?:heads|remotes\/origin)\//,"");if(name&&name!=="HEAD")names.add(name)}return[...names]}async function listManaged(deps,repo){let ctx=deps.ctxFor(repo);requireAbsolute("repo",ctx.dir);let all=parseWorktreeListPorcelain(await deps.runGitStdout(ctx,["worktree","list","--porcelain"])),kept=[];for(let entry of all){if(!entry.path)continue;let callerRoot=ctx.remote?remoteManagedRootForPath(ctx.dir,entry.path):managedWorktreeRootForPath(repo,entry.path);if(!callerRoot)continue;if(!entry.branch||entry.detached)continue;let rel=path3.relative(canonicalize(callerRoot),canonicalize(entry.path));kept.push({callerPath:path3.join(callerRoot,rel),probePath:entry.path,branch:entry.branch,head:entry.head??""})}return mapWithLimit(kept,PROBE_CONCURRENCY,async(e)=>({path:e.callerPath,branch:e.branch,head:e.head,dirty:await deps.isDirty(e.probePath).catch(()=>null)}))}async function listAllAdoptable(deps,repo){let ctx=deps.ctxFor(repo),adoptable=await adoptablePaths(deps,ctx),infos=await mapWithLimit(adoptable,PROBE_CONCURRENCY,async(entry)=>{let[dirty,activityMs]=await Promise.all([deps.isDirty(entry.path).catch(()=>null),lastActivityMs(deps,ctx,entry.path)]);return{path:entry.path,branch:entry.branch,head:entry.head,dirty,roveManaged:ctx.remote?remoteManagedRootForPath(ctx.dir,entry.path)!==null:isRoveManagedPath(repo,entry.path),lastActivityMs:activityMs}});return infos.sort((a,b)=>b.lastActivityMs-a.lastActivityMs),infos}async function adoptablePaths(deps,ctx){requireAbsolute("repo",ctx.dir);let all=parseWorktreeListPorcelain(await deps.runGitStdout(ctx,["worktree","list","--porcelain"])),canon=(p)=>ctx.remote?p:canonicalize(p),canonRepo=canon(ctx.dir),canonMain=all.find((entry)=>entry.path)?.path,canonMainPath=canonMain?canon(canonMain):null,kept=[];for(let entry of all){if(!entry.path)continue;if(entry.bare)continue;if(!entry.branch||entry.detached)continue;let canonEntry=canon(entry.path);if(canonMainPath!==null&&canonEntry===canonMainPath)continue;if(canonEntry===canonRepo)continue;kept.push({path:entry.path,branch:entry.branch,head:entry.head??""})}return kept}async function unreadableWorktreeNames(deps,ctx){if(ctx.remote)return[];requireAbsolute("repo",ctx.dir);let adminRoot;try{let common=(await deps.runGitStdout(ctx,["rev-parse","--git-common-dir"])).trim();if(!common)return[];adminRoot=path3.join(path3.resolve(ctx.dir,common),"worktrees")}catch{return[]}let names;try{names=fs2.readdirSync(adminRoot,{withFileTypes:!0}).filter((entry)=>entry.isDirectory()).map((entry)=>entry.name)}catch{return[]}if(names.length===0)return[];let listed;try{listed=await deps.runGitStdout(ctx,["worktree","list","--porcelain"])}catch{return[]}let reported=new Set(parseWorktreeListPorcelain(listed).filter((entry)=>entry.path).map((entry)=>canonicalize(entry.path))),missing=[];for(let name of names){let gitdir;try{gitdir=fs2.readFileSync(path3.join(adminRoot,name,"gitdir"),"utf8").trim()}catch{missing.push(name);continue}if(gitdir&&!reported.has(canonicalize(path3.dirname(gitdir))))missing.push(name)}return missing}import path4 from"path";async function isRegisteredWorktree(deps,exec,repo,worktreePath){let out=await deps.runGit(exec,["worktree","list","--porcelain"],{cwd:repo,allowFail:!0,readOnly:!0});if(out.exitCode!==0)return!1;let same=(a,b)=>exec.isRemote?a===b:canonicalize(a)===canonicalize(b);return parseWorktreeListPorcelain(out.stdout).some((e)=>e.path!==void 0&&same(e.path,worktreePath))}async function deregisteredWorktreeResidue(exec,worktreePath){let pointer=(await exec.readFile(`${worktreePath}/.git`))?.trim().match(/^gitdir:\s*(.+)$/)?.[1]?.trim();if(!pointer)return!1;let marker="/worktrees/",at=pointer.lastIndexOf(marker);if(at<0)return!1;return await exec.exists(pointer.slice(0,at))}function dirtyRefusal(worktreePath,ignored,dirty=[]){return`${DIRTY_WORKTREE_CODE}: ${worktreePath} has ${describeDirtyWorktreeWork(ignored,dirty)} \u2014 forcing the removal salvages it to a ref first`}async function removeWorktree(deps,worktreePath,opts){requireAbsolute("path",worktreePath);let exec=deps.execForPath(worktreePath),force=opts?.force===!0;if(!await exec.exists(worktreePath)){let goneRepo=opts?.repo??await deps.findRepoFor(exec,path4.dirname(worktreePath));if(goneRepo){if(await deps.runGit(exec,["worktree","prune"],{cwd:goneRepo,allowFail:!0}),opts?.deleteBranch===!0&&opts.branch){let outcome=await deleteBranchAnchored(deps.branchDeps(),exec,goneRepo,opts.branch,{force});if(!outcome.deleted)opts.onBranchKept?.({branch:opts.branch,reason:outcome.reason})}}return}let repo=await deps.findRepoFor(exec,worktreePath);if(repo===null||!await isRegisteredWorktree(deps,exec,repo,worktreePath)){if(await deregisteredWorktreeResidue(exec,worktreePath)){opts?.onResidue?.({path:worktreePath,reason:"a previous removal deregistered the worktree"});return}if(repo){opts?.onResidue?.({path:worktreePath,reason:"a previous removal deregistered the worktree"});return}if(!force)throw Error(`remove(): ${worktreePath} is not a git worktree`);if(!isUnderManagedWorktreesRoot(worktreePath,opts?.repo))throw Error(`remove(): ${worktreePath} has no reachable git repo and is not under a Rove worktrees root; refusing to delete it`);if(opts?.onSalvage?.(null),await exec.run(["rm","-rf",worktreePath]),await exec.exists(worktreePath))opts?.onResidue?.({path:worktreePath,reason:"the directory could not be deleted"});return}let branch=opts?.deleteBranch?await deps.currentBranch(worktreePath).catch(()=>null)??opts.branch??null:null;if(force){let salvaged=await salvageWorktree({runGit:(e,a,o)=>deps.runGit(e,a,o)},exec,worktreePath);opts?.onSalvage?.(salvaged)}else{let dirty=await deps.dirtyPaths(worktreePath);if(dirty.length>0)throw Error(dirtyRefusal(worktreePath,[],dirty));let ignored=await deps.ignoredWork(worktreePath);if(ignored==="unknown"||ignored.length>0)throw Error(dirtyRefusal(worktreePath,ignored))}let args=force?["worktree","remove","--force",worktreePath]:["worktree","remove",worktreePath],result=await deps.runGit(exec,args,{cwd:repo,allowFail:!0});if(result.exitCode!==0){if(await isRegisteredWorktree(deps,exec,repo,worktreePath))throw new GitCommandError(args,repo,result);opts?.onResidue?.({path:worktreePath,reason:result.stderr.trim()||result.stdout.trim()||"unknown"})}if(await deps.runGit(exec,["worktree","prune"],{cwd:repo,allowFail:!0}),branch){let outcome=await deleteBranchAnchored(deps.branchDeps(),exec,repo,branch,{force});if(!outcome.deleted)opts?.onBranchKept?.({branch,reason:outcome.reason})}}class GitWorktreeManager{execDeps;cloneDeps;constructor(execDeps=defaultExecDeps,cloneDeps=defaultCloneDeps){this.execDeps=execDeps;this.cloneDeps=cloneDeps}ctxFor(repoKey){let basePath=this.execDeps.remoteBasePath(repoKey);return basePath?{exec:this.execDeps.execForRepo(repoKey),dir:basePath,remote:!0}:{exec:this.execDeps.execForRepo(repoKey),dir:repoKey,remote:!1}}async runGit(exec,args,opts){if(!opts.cwd)throw Error("runGit(): cwd is required; refusing to inherit from process.cwd()");let env=opts.readOnly?{...opts.env,...READ_ONLY_GIT_ENV}:opts.env,r=await exec.run(["git",...args],{cwd:opts.cwd,env}),result={stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode};if(result.exitCode!==0&&!opts.allowFail)throw new GitCommandError(args,opts.cwd,result);return result}async create(repo,branch,worktreePath,baseRef){let ctx=this.ctxFor(repo);if(requireAbsolute("repo",ctx.dir),requireAbsolute("path",worktreePath),!branch)throw Error("create(): branch must be a non-empty string");if(await ctx.exec.exists(worktreePath)){let existing=await this.tryDescribe(ctx,worktreePath);if(existing){if(existing.branch!==branch)throw Error(`worktree at ${worktreePath} is on branch '${existing.branch}', refusing to hijack to '${branch}'`);return existing}throw Error(`create(): ${worktreePath} exists but is not a registered git worktree`)}await ctx.exec.mkdirp(path5.dirname(worktreePath));let args=await branchExists(this.branchDeps(),ctx,branch)?["worktree","add",worktreePath,branch]:baseRef?["worktree","add","-b",branch,worktreePath,baseRef]:["worktree","add","-b",branch,worktreePath];await this.runGit(ctx.exec,args,{cwd:ctx.dir});let info=await this.tryDescribe(ctx,worktreePath);if(!info)throw Error(`create(): git reported success but ${worktreePath} is not a worktree`);if(info.branch!==branch)throw Error(`create(): post-condition failed \u2014 expected branch '${branch}' at ${worktreePath}, got '${info.branch}'`);return info}async createForTask(args){let basePath=this.execDeps.remoteBasePath(args.repo),target=basePath?remoteWorktreePathFor(basePath,args.slug):worktreePathFor(args.repo,args.slug),ctx=this.ctxFor(args.repo),skipClone=ctx.remote||await ctx.exec.exists(target),info=await this.create(args.repo,args.branch,target,args.baseRef);if(!skipClone)await cloneIgnoredDirs(ctx.exec,args.repo,info.path,this.cloneDeps(ctx.exec));return info}async remove(worktreePath,opts){await removeWorktree({runGit:(exec,args,runOpts)=>this.runGit(exec,args,runOpts),execForPath:(p)=>this.execDeps.execForPath(p),findRepoFor:(exec,p)=>this.findRepoFor(exec,p),currentBranch:(p)=>this.currentBranch(p),dirtyPaths:(p)=>this.dirtyPaths(p),ignoredWork:(p)=>this.ignoredWork(p),branchDeps:()=>this.branchDeps()},worktreePath,opts)}async deleteBranch(repo,branch,opts){let ctx=this.ctxFor(repo);return requireAbsolute("repo",ctx.dir),await deleteBranchAnchored(this.branchDeps(),ctx.exec,ctx.dir,branch,{force:opts?.force===!0,onAnchor:opts?.onAnchor})}execAt(worktreePath){return requireAbsolute("path",worktreePath),this.execDeps.execForPath(worktreePath)}branchDeps(){return{runGit:(exec,args,opts)=>this.runGit(exec,args,opts),execAt:(worktreePath)=>this.execAt(worktreePath),findRepoFor:(exec,worktreePath)=>this.findRepoFor(exec,worktreePath)}}listDeps(){return{ctxFor:(repoKey)=>this.ctxFor(repoKey),runGitStdout:async(ctx,args)=>(await this.runGit(ctx.exec,args,{cwd:ctx.dir,readOnly:!0})).stdout,runGitStdoutAt:async(ctx,cwd,args)=>(await this.runGit(ctx.exec,args,{cwd,readOnly:!0})).stdout,isDirty:(worktreePath)=>this.isDirty(worktreePath)}}list(repo){return listManaged(this.listDeps(),repo)}listAll(repo){return listAllAdoptable(this.listDeps(),repo)}listAdoptablePaths(repo){return adoptablePaths(this.listDeps(),this.ctxFor(repo))}listUnreadableWorktrees(repo){return unreadableWorktreeNames(this.listDeps(),this.ctxFor(repo))}listBranchNames(repo){return listBranchNames(this.listDeps(),repo)}async pathExists(worktreePath){return this.execAt(worktreePath).exists(worktreePath)}async pruneWorktrees(repo){let ctx=this.ctxFor(repo);requireAbsolute("repo",ctx.dir),await this.runGit(ctx.exec,["worktree","prune"],{cwd:ctx.dir,allowFail:!0})}async isDirty(worktreePath){return(await this.dirtyPaths(worktreePath)).length>0}async dirtyPaths(worktreePath){let out=await this.runGit(this.execAt(worktreePath),["status","--porcelain"],{cwd:worktreePath,readOnly:!0});return parseDirtyPaths(out.stdout)}async ignoredWork(worktreePath){let exec=this.execAt(worktreePath);return smallIgnoredPaths(exec,worktreePath,regenerableDirNames(exec,worktreePath,this.cloneDeps(exec)))}async currentBranch(worktreePath){let name=(await this.runGit(this.execAt(worktreePath),["rev-parse","--abbrev-ref","HEAD"],{cwd:worktreePath,readOnly:!0})).stdout.trim();if(!name||name==="HEAD")throw Error(`currentBranch(): ${worktreePath} is in detached-HEAD state`);return name}branchHasUpstream(worktreePath,branch){return branchHasUpstream(this.branchDeps(),worktreePath,branch)}hasLocalBranch(worktreePath,branch){return hasLocalBranch(this.branchDeps(),worktreePath,branch)}renameBranch(worktreePath,from,to){return renameBranch(this.branchDeps(),worktreePath,from,to)}async tryDescribe(ctx,worktreePath){let out=await this.runGit(ctx.exec,["worktree","list","--porcelain"],{cwd:ctx.dir,readOnly:!0}),entries=parseWorktreeListPorcelain(out.stdout),norm=(p)=>ctx.remote?p:canonicalize(p),target=norm(worktreePath),match=entries.find((e)=>e.path&&norm(e.path)===target);if(!match||!match.path||!match.branch||match.detached)return null;return{path:worktreePath,branch:match.branch,head:match.head??"",dirty:await this.isDirty(match.path)}}async findRepoFor(exec,worktreePath){try{let out=await this.runGit(exec,["rev-parse","--git-common-dir"],{cwd:worktreePath,allowFail:!0,readOnly:!0});if(out.exitCode!==0)return null;let gitDir=out.stdout.trim();if(!gitDir)return null;let absolute=path5.isAbsolute(gitDir)?gitDir:path5.resolve(worktreePath,gitDir);return path5.basename(absolute)===".git"?path5.dirname(absolute):absolute}catch(err){if(err instanceof GitCommandError)return null;throw err}}}
|
|
10
|
-
export{parseDirtyPaths,isDirtyOutput,defaultExecDeps,GitWorktreeManager};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{localDaemonSocketPath,localPtySocketPath,machineSocketDir,machineSshArgs,roveCommand}from"./chunk-g1px1rk6.js";import{homeDir}from"./chunk-prqeddy7.js";import{logClientError}from"./chunk-gskbzgc3.js";import{spawn as spawn2}from"child_process";import{mkdirSync as mkdirSync2,rmSync as rmSync2}from"fs";import{connect as netConnect}from"net";import{spawn}from"child_process";import{mkdirSync,rmSync}from"fs";import{createServer}from"net";function useStdioTransport(platform=process.platform){return platform==="win32"||process.env.ROVE_MACHINE_TRANSPORT==="stdio"}function relayCommand(roveBin,pty){return`${roveCommand(roveBin)} daemon relay${pty?" --pty":""}`}var servers=new Map;function serve(path,argv){if(servers.has(path))return Promise.resolve();let server=createServer((conn)=>{let[cmd,...args]=argv,child=spawn(cmd??"ssh",args,{stdio:["pipe","pipe","ignore"],windowsHide:!0});conn.pipe(child.stdin),child.stdout?.pipe(conn);let end=()=>{conn.destroy(),child.kill()};conn.on("close",()=>child.kill()),conn.on("error",end),child.on("exit",()=>conn.end()),child.on("error",(err)=>{logClientError("machines",err),end()})});return servers.set(path,server),new Promise((resolve,reject)=>{server.once("error",(err)=>{servers.delete(path),reject(err)}),rmSync(path,{force:!0}),server.listen(path,()=>resolve())})}async function ensureStdioForwards(args){mkdirSync(machineSocketDir(args.alias,args.home),{recursive:!0});let ssh=machineSshArgs(args.alias,args.config,{home:args.home});await serve(localDaemonSocketPath(args.alias,args.home),[...ssh,relayCommand(args.config.roveBin,!1)]),await serve(localPtySocketPath(args.alias,args.home),[...ssh,relayCommand(args.config.roveBin,!0)])}function stopStdioForwards(alias,home){for(let path of[localDaemonSocketPath(alias,home),localPtySocketPath(alias,home)])servers.get(path)?.close(),servers.delete(path)}var DIR_MODE=448,BACKOFF_START_MS=500,BACKOFF_MAX_MS=5000,HEALTH_INTERVAL_MS=1e4;function startTunnel(opts){let home=opts.home??homeDir(),daemonSocketPath=localDaemonSocketPath(opts.alias,home),ptySocketPath=localPtySocketPath(opts.alias,home),listeners=new Set,state="connecting",stopped=!1,backoff=BACKOFF_START_MS,setState=(next)=>{if(state===next)return;state=next;for(let listener of listeners)listener(next)},handle={alias:opts.alias,daemonSocketPath,ptySocketPath,state:()=>state,onState:(listener)=>{return listeners.add(listener),()=>listeners.delete(listener)},stop:()=>{if(stopped=!0,useStdioTransport())stopStdioForwards(opts.alias,home)}},schedule=opts.setTimeoutFn??((fn,ms)=>setTimeout(fn,ms)),stdio=()=>ensureStdioForwards({alias:opts.alias,config:opts.config,home}).then(()=>socketAnswers(daemonSocketPath)).catch(()=>!1),ensure=opts.ensureFn??(useStdioTransport()?stdio:()=>ensureForwards({alias:opts.alias,config:opts.config,remoteDaemonSocket:opts.remoteDaemonSocket,remotePtySocket:opts.remotePtySocket,home})),check=opts.checkFn??(()=>socketAnswers(daemonSocketPath)),attempt=async()=>{if(stopped)return;let up=await ensure();if(stopped)return;if(up){backoff=BACKOFF_START_MS,setState("online"),schedule(()=>void health(),HEALTH_INTERVAL_MS);return}setState("offline");let wait=backoff;backoff=Math.min(backoff*2,BACKOFF_MAX_MS),schedule(()=>void attempt(),wait)},health=async()=>{if(stopped)return;if(await check()){if(!stopped)schedule(()=>void health(),HEALTH_INTERVAL_MS);return}setState("offline"),attempt()};return attempt(),handle}async function ensureForwards(args){let home=args.home??homeDir();if(useStdioTransport())return ensureStdioForwards({alias:args.alias,config:args.config,home}).then(()=>socketAnswers(localDaemonSocketPath(args.alias,home))).catch(()=>!1);let daemonLocal=localDaemonSocketPath(args.alias,home),ptyLocal=localPtySocketPath(args.alias,home);try{mkdirSync2(machineSocketDir(args.alias,home),{recursive:!0,mode:DIR_MODE})}catch{}if(await socketAnswers(daemonLocal))return!0;for(let path of[daemonLocal,ptyLocal])try{rmSync2(path,{force:!0})}catch{}let base=machineSshArgs(args.alias,args.config,{home});if(await runSsh([...base,"true"])!==0)return!1;let target=base.at(-1)??args.alias,flags=base.slice(0,-1);return await runSsh([...flags,"-O","forward","-L",`${daemonLocal}:${args.remoteDaemonSocket}`,"-L",`${ptyLocal}:${args.remotePtySocket}`,target])===0&&await socketAnswers(daemonLocal)}function runSsh(argv){return new Promise((resolve)=>{let child=spawn2(argv[0]??"ssh",argv.slice(1),{stdio:"ignore"});child.on("error",()=>resolve(-1)),child.on("close",(code)=>resolve(code??-1))})}function socketAnswers(path){return new Promise((resolve)=>{let socket=netConnect(path),done=(answer)=>{socket.destroy(),resolve(answer)};socket.once("connect",()=>done(!0)),socket.once("error",()=>done(!1)),socket.setTimeout(1500,()=>done(!1))})}
|
|
3
|
-
export{startTunnel,ensureForwards};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{openDaemonSession,resolveActiveTaskId}from"./chunk-re15t5r1.js";import"./chunk-tgfn5ykb.js";import"./chunk-qga9xd2f.js";import"./chunk-5v02t4pz.js";import"./chunk-wqckm0k6.js";import"./chunk-yt15y085.js";import"./chunk-kmgheesn.js";import"./chunk-szjgjrar.js";import"./chunk-gskbzgc3.js";import"./chunk-pn5ygqn6.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{resolveActiveTaskId,openDaemonSession};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{DEFAULT_TERMINAL_COLORS}from"./chunk-4250pw6r.js";import{OWNER_ONLY_DIR_MODE,OWNER_ONLY_FILE_MODE,tightenDirPermissionsSync,tightenFilePermissionsSync}from"./chunk-yt15y085.js";import{defaultPtyFreezeDir}from"./chunk-n0rtj4z7.js";import{randomUUID}from"crypto";import{mkdirSync,readFileSync,readdirSync,renameSync,rmSync,statSync,writeFileSync}from"fs";import{join}from"path";import{StringDecoder}from"string_decoder";var DEFAULT_MODES={applicationCursorKeys:!1,applicationKeypad:!1,origin:!1,wraparound:!0,reverseWraparound:!1,cursorBlink:!1,cursorVisible:!0,insertMode:!1,sendFocus:!1,bracketedPaste:!1,synchronizedOutput:!1,altScreen:!1,mouseProtocol:"none",mouseEncoding:"default"},MOUSE_PROTOCOLS={9:"x10",1000:"vt200",1002:"drag",1003:"any"},MOUSE_ENCODINGS={1006:"sgr",1016:"sgr-pixels"};function freshModeTrack(modes={...DEFAULT_MODES}){return{modes,carry:""}}function normalizeTerminalModes(raw){let modes={...DEFAULT_MODES};if(typeof raw!=="object"||raw===null)return modes;let record=raw;for(let key of Object.keys(DEFAULT_MODES))if(typeof record[key]==="boolean"&&typeof modes[key]==="boolean")modes[key]=record[key];if(Object.values(MOUSE_PROTOCOLS).includes(record.mouseProtocol))modes.mouseProtocol=record.mouseProtocol;if(Object.values(MOUSE_ENCODINGS).includes(record.mouseEncoding))modes.mouseEncoding=record.mouseEncoding;return modes}function scanTerminalModes(track,chunk){let text=track.carry+chunk;track.carry="";let replies=[],i=text.indexOf("\x1B");while(i!==-1){if(i+1>=text.length){track.carry="\x1B";break}let next=text.charCodeAt(i+1);if(next===91){let end=csiEnd(text,i+2);if(end===-1){if(text.length-i<=64)track.carry=text.slice(i);break}if(end>=0)applyCsi(track.modes,text.slice(i+2,end),text[end],replies);i=text.indexOf("\x1B",end>=0?end+1:i+2);continue}if(next===61)track.modes.applicationKeypad=!0;else if(next===62)track.modes.applicationKeypad=!1;else if(next===99)track.modes={...DEFAULT_MODES};i=text.indexOf("\x1B",i+1)}return replies}function terminalModePreamble(modes){let set=[],reset=[];if(modes.applicationCursorKeys)set.push(1);if(modes.origin)set.push(6);if(!modes.wraparound)reset.push(7);if(modes.cursorBlink)set.push(12);if(!modes.cursorVisible)reset.push(25);if(modes.reverseWraparound)set.push(45);for(let[mode,protocol]of Object.entries(MOUSE_PROTOCOLS))if(modes.mouseProtocol===protocol)set.push(+mode);for(let[mode,encoding]of Object.entries(MOUSE_ENCODINGS))if(modes.mouseEncoding===encoding)set.push(+mode);if(modes.sendFocus)set.push(1004);if(modes.bracketedPaste)set.push(2004);let out=modes.altScreen?"\x1B[?1049h":"";if(set.length>0)out+=`\x1B[?${set.join(";")}h`;if(reset.length>0)out+=`\x1B[?${reset.join(";")}l`;if(modes.applicationKeypad)out+="\x1B=";if(modes.insertMode)out+="\x1B[4h";return out}function csiEnd(text,from){for(let j=from;j<text.length;j++){let c=text.charCodeAt(j);if(c>=64&&c<=126)return j;if(c<32||c>63)return-2}return-1}function applyCsi(modes,body,final,replies){let start=0,prefix="",first=body.charCodeAt(0);if(first>=60&&first<=63)prefix=body[0],start=1;let end=body.length;while(end>start&&body.charCodeAt(end-1)<=47)end--;let intermediates=body.slice(end),params=body.slice(start,end).split(";").map((param)=>Number.parseInt(param.split(":")[0]??"",10)||0);if(intermediates===""&&(final==="h"||final==="l")){let on=final==="h";if(prefix==="?")for(let mode of params)setPrivateMode(modes,mode,on);else if(prefix===""&¶ms.includes(4))modes.insertMode=on}else if(intermediates==="$"&&final==="p"&&(prefix==="?"||prefix==="")){let mode=params[0]??0,value=prefix==="?"?privateModeValue(modes,mode):ansiModeValue(modes,mode);replies.push(`\x1B[${prefix}${mode};${value}$y`)}else if(intermediates==="!"&&final==="p"&&prefix==="")softReset(modes);else if(intermediates===""&&final==="c"&&prefix===""&&(params[0]??0)===0)replies.push("\x1B[?1;2c")}function setPrivateMode(modes,mode,on){if(mode in MOUSE_PROTOCOLS){modes.mouseProtocol=on?MOUSE_PROTOCOLS[mode]:"none";return}if(mode in MOUSE_ENCODINGS){modes.mouseEncoding=on?MOUSE_ENCODINGS[mode]:"default";return}switch(mode){case 1:modes.applicationCursorKeys=on;break;case 6:modes.origin=on;break;case 7:modes.wraparound=on;break;case 12:modes.cursorBlink=on;break;case 25:modes.cursorVisible=on;break;case 45:modes.reverseWraparound=on;break;case 66:modes.applicationKeypad=on;break;case 1004:modes.sendFocus=on;break;case 47:case 1047:case 1049:modes.altScreen=on;break;case 2004:modes.bracketedPaste=on;break;case 2026:modes.synchronizedOutput=on;break}}function softReset(modes){Object.assign(modes,{applicationCursorKeys:!1,applicationKeypad:!1,origin:!1,wraparound:!0,reverseWraparound:!1,cursorVisible:!0,insertMode:!1,sendFocus:!1,bracketedPaste:!1,synchronizedOutput:!1})}var NOT_RECOGNIZED=0,SET=1,RESET=2,PERMANENTLY_SET=3,PERMANENTLY_RESET=4,flag=(on)=>on?SET:RESET;function privateModeValue(modes,mode){if(mode in MOUSE_PROTOCOLS)return flag(modes.mouseProtocol===MOUSE_PROTOCOLS[mode]);if(mode in MOUSE_ENCODINGS)return flag(modes.mouseEncoding===MOUSE_ENCODINGS[mode]);switch(mode){case 1:return flag(modes.applicationCursorKeys);case 6:return flag(modes.origin);case 7:return flag(modes.wraparound);case 8:return PERMANENTLY_SET;case 12:return flag(modes.cursorBlink);case 25:return flag(modes.cursorVisible);case 45:return flag(modes.reverseWraparound);case 66:return flag(modes.applicationKeypad);case 67:case 1005:case 1015:return PERMANENTLY_RESET;case 1004:return flag(modes.sendFocus);case 1048:return SET;case 47:case 1047:case 1049:return flag(modes.altScreen);case 2004:return flag(modes.bracketedPaste);case 2026:return flag(modes.synchronizedOutput);default:return NOT_RECOGNIZED}}function ansiModeValue(modes,mode){switch(mode){case 2:return PERMANENTLY_RESET;case 4:return flag(modes.insertMode);case 12:return PERMANENTLY_SET;case 20:return RESET;default:return NOT_RECOGNIZED}}var FREEZE_VERSION=1;function freezeSession(session,now=new Date){return{v:FREEZE_VERSION,key:session.key,cwd:session.cwd,command:[...session.command],cols:session.cols,rows:session.rows,title:session.title,totalBytes:session.totalBytes,exit:session.exit,ringB64:Buffer.concat(session.chunks).toString("base64"),...session.ringModes?{ringModes:session.ringModes.modes}:{},updatedAt:now.toISOString()}}function thawRing(record,cap){let ring;try{ring=Buffer.from(record.ringB64,"base64")}catch{return null}let cut=Math.max(0,ring.byteLength-cap),trimmed=ring.subarray(cut),ringModes=freshModeTrack(normalizeTerminalModes(record.ringModes));if(cut>0)scanTerminalModes(ringModes,ring.subarray(0,cut).toString("latin1"));return{chunks:trimmed.byteLength>0?[trimmed]:[],bytes:trimmed.byteLength,ringModes}}function thawSession(record,cap){let ring=thawRing(record,cap);if(!ring)return null;let modes=freshModeTrack({...ring.ringModes.modes});for(let chunk of ring.chunks)scanTerminalModes(modes,chunk.toString("latin1"));return{key:record.key,generation:randomUUID(),cwd:record.cwd,proc:null,alive:!1,chunks:[...ring.chunks],bytes:ring.bytes,totalBytes:Math.max(record.totalBytes,ring.bytes),cols:record.cols,rows:record.rows,command:record.command,title:record.title,titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:DEFAULT_TERMINAL_COLORS,modes,ringModes:ring.ringModes,sinks:new Map,emulatorSinks:new Set,parked:!1,parkedScreenBytes:0,exit:record.exit,restored:!0,lastFreezeAtMs:0}}function recordFile(dir,key){return join(dir,`${encodeURIComponent(key)}.json`)}function parseRecord(raw){try{let parsed=JSON.parse(raw);if(parsed?.v!==FREEZE_VERSION)return null;if(typeof parsed.key!=="string"||parsed.key.length===0)return null;if(parsed.key.startsWith("::"))return null;if(typeof parsed.cwd!=="string"||!Array.isArray(parsed.command))return null;if(typeof parsed.ringB64!=="string"||typeof parsed.totalBytes!=="number")return null;return parsed}catch{return null}}var FREEZE_TTL_MS=1209600000,FREEZE_RESTORE_MAX_BYTES=67108864;function updatedAtMs(record){let t=Date.parse(record.updatedAt);return Number.isFinite(t)?t:0}function loadFrozenSessions(dir=defaultPtyFreezeDir(),now=Date.now(),report){let names;try{names=readdirSync(dir)}catch{return[]}let entries=[];for(let name of names){if(!name.endsWith(".json"))continue;try{let st=statSync(join(dir,name));entries.push({name,size:st.size,mtimeMs:st.mtimeMs})}catch{}}entries.sort((a,b)=>b.mtimeMs-a.mtimeMs);let kept=[],stale=[],bytesRead=0,deferred=0,unreadable=0;for(let entry of entries){if(now-entry.mtimeMs>FREEZE_TTL_MS){stale.push(entry.name);continue}if(bytesRead+entry.size>FREEZE_RESTORE_MAX_BYTES&&kept.length>0){deferred++;continue}let record=null;try{record=parseRecord(readFileSync(join(dir,entry.name),"utf8"))}catch{}if(bytesRead+=entry.size,!record){unreadable++;continue}if(now-updatedAtMs(record)>FREEZE_TTL_MS)stale.push(entry.name);else kept.push(record)}for(let name of stale)try{rmSync(join(dir,name),{force:!0})}catch{}return kept.sort((a,b)=>updatedAtMs(b)-updatedAtMs(a)),report?.({restored:kept.length,bytesRead,deferred,expired:stale.length,unreadable}),kept}function tightenExistingPermissions(dir){tightenDirPermissionsSync(dir);let names;try{names=readdirSync(dir)}catch{return}for(let name of names)if(name.endsWith(".json"))tightenFilePermissionsSync(join(dir,name))}function fileFreezeSink(dir=defaultPtyFreezeDir()){return tightenExistingPermissions(dir),{save(record){try{mkdirSync(dir,{recursive:!0,mode:OWNER_ONLY_DIR_MODE});let target=recordFile(dir,record.key),staging=`${target}.${process.pid}.tmp`;writeFileSync(staging,JSON.stringify(record),{encoding:"utf8",mode:OWNER_ONLY_FILE_MODE}),renameSync(staging,target)}catch{}},drop(key){try{rmSync(recordFile(dir,key),{force:!0})}catch{}}}}function clearFrozenSessions(dir=defaultPtyFreezeDir()){try{rmSync(dir,{recursive:!0,force:!0})}catch{}}
|
|
3
|
-
export{freshModeTrack,scanTerminalModes,terminalModePreamble,freezeSession,thawSession,FREEZE_TTL_MS,FREEZE_RESTORE_MAX_BYTES,loadFrozenSessions,fileFreezeSink,clearFrozenSessions};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{PS_PROBE_TIMEOUT_MS,engineProcessIn,foregroundEngine,foregroundEngineIn,hasAncestor,parsePsSnapshot,psSnapshot,psSnapshotWith,vendorFromArgv}from"./chunk-b4zqkdyq.js";import"./chunk-rbr6qapz.js";import"./chunk-2tfnscxk.js";import"./chunk-8saxdp88.js";import"./chunk-w7zv47mp.js";import"./chunk-2brn8e1y.js";import"./chunk-xh72jz7c.js";import"./chunk-7zyyvc3d.js";import"./chunk-r6k3ve2g.js";import"./chunk-xy8be792.js";import"./chunk-7kysxgbq.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-tdhk4dz8.js";import"./chunk-m6pp9gaf.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-n3f5sdka.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-gskbzgc3.js";import"./chunk-pn5ygqn6.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{PsProbeUnavailableError}from"./chunk-pxk2c2vj.js";import"./chunk-91sykzqq.js";export{vendorFromArgv,psSnapshotWith,psSnapshot,parsePsSnapshot,hasAncestor,foregroundEngineIn,foregroundEngine,engineProcessIn,PsProbeUnavailableError,PS_PROBE_TIMEOUT_MS};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{embeddedTerminalEnv}from"./chunk-7bgbansg.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,clearFrozenSessions,fileFreezeSink,freezeSession,freshModeTrack,loadFrozenSessions,scanTerminalModes,terminalModePreamble,thawSession}from"./chunk-spee6wv8.js";import{ClientWriter,LineReceiver,clearTransientStatuses,createOscSignals,objectPayload,optionalBoolean,requireString,scanOscSignals}from"./chunk-k67vbszb.js";import{writeTextAtomic}from"./chunk-5mhvjytn.js";import{DEFAULT_TERMINAL_COLORS,foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors}from"./chunk-4250pw6r.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-rxqdw6s5.js";import{resolveLoginShell}from"./chunk-f5n0tgky.js";import{recordPtyExit}from"./chunk-sr4c9fve.js";import"./chunk-etfh8f4z.js";import{spawnDetachedDaemon,withoutPtyJob}from"./chunk-5v02t4pz.js";import{CURRENT_VERSION}from"./chunk-dzmfexh8.js";import{listenOnUnixSocket}from"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import{ensureOwnerOnlyStateDir}from"./chunk-yt15y085.js";import{DAEMON_PROTOCOL_VERSION,frameToLine}from"./chunk-kmgheesn.js";import"./chunk-szjgjrar.js";import{rotateLogIfNeeded}from"./chunk-gskbzgc3.js";import"./chunk-pn5ygqn6.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,endpointPathFor,isWindowsPipePath,resolveDaemonHomeDir}from"./chunk-n0rtj4z7.js";import{preRenameStateDir}from"./chunk-b39sdtt0.js";import{ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";function formatPtyHostLine(event,message,now=new Date){return`[${now.toISOString()}] pty-host [${event}]: ${message}`}import{readFileSync}from"fs";import{mkdir,unlink}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync}from"fs";import{homedir}from"os";import{join}from"path";var PTY_HOST_DATA_ENTRIES=["pty-exits.json","pty-sessions"];function lstatIfExists(path){try{return lstatSync(path)}catch{return}}function migrateLegacyPtyHostData(homeDir=readRoveHomeDirEnv()??homedir()){let canonicalDir=join(homeDir,ROVE_STATE_DIR_BASENAME),legacyDir=preRenameStateDir(homeDir);if(canonicalDir===legacyDir)return[];let moved=[];for(let name of PTY_HOST_DATA_ENTRIES){let canonical=join(canonicalDir,name),legacy=join(legacyDir,name);try{if(existsSync(canonical))continue;let stat=lstatIfExists(legacy);if(!stat||stat.isSymbolicLink())continue;mkdirSync(canonicalDir,{recursive:!0}),renameSync(legacy,canonical),moved.push(name)}catch{}}return moved}import{randomUUID as randomUUID2}from"crypto";var TERMINAL_NAME="xterm-256color";function bunTerminalDriver(spawn){let spawnTerminal=spawn??((argv,options)=>Bun.spawn(argv,options));return(request)=>{let proc=spawnTerminal([...request.argv],{cwd:request.cwd,env:request.env,terminal:{cols:request.cols,rows:request.rows,name:TERMINAL_NAME,data:(_terminal,data)=>request.onData(data)}});return{pid:proc.pid,exited:proc.exited.then(()=>({code:proc.exitCode??null,signal:proc.signalCode??null}),()=>({code:null,signal:null})),write:(data)=>proc.terminal?.write(data),resize:(cols,rows)=>proc.terminal?.resize(cols,rows),close:()=>proc.terminal?.close(),kill:(signal)=>proc.kill(signal)}}}import{randomUUID}from"crypto";import{StringDecoder}from"string_decoder";function freshSessionState(key,spec,argv){return{key,generation:randomUUID(),cwd:spec.cwd,proc:null,alive:!0,chunks:[],bytes:0,totalBytes:0,cols:spec.cols??80,rows:spec.rows??24,command:argv,title:"",titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:parseTerminalDefaultColors(spec.defaultColors)??DEFAULT_TERMINAL_COLORS,modes:freshModeTrack(),ringModes:freshModeTrack(),sinks:new Map,emulatorSinks:new Set,parked:!1,parkedScreenBytes:0,exit:null,restored:!1,lastFreezeAtMs:0,frozenTotalBytes:0}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,programStatusEvent:s.programStatusEvent,programStatus:s.oscSignals?.records.get(""),contexts:s.oscSignals?.contexts,totalBytes:s.totalBytes,parked:s.parked,parkedScreenBytes:s.parkedScreenBytes,exit:s.exit,restored:s.restored||void 0}}function describeExit(exit){if(exit?.signal)return` (signal ${exit.signal})`;if(exit&&exit.code!==null)return` (code ${exit.code})`;return" (cause unknown)"}function ringTail(chunks,bytes,maxBytes){let skip=Math.max(0,bytes-maxBytes),seen=0,parts=[];for(let chunk of chunks){if(seen+chunk.byteLength>skip)parts.push(seen>=skip?chunk:chunk.subarray(skip-seen));seen+=chunk.byteLength}return Buffer.concat(parts).toString("utf8")}function hostStats(sessions,perSessionCap,parkRestoreDeltas,parkRestoreFallbacks){let ringBytes=0,count=0,parkedSessions=0,parkedScreenBytes=0;for(let session of sessions)if(count++,ringBytes+=session.bytes,session.parked)parkedSessions++,parkedScreenBytes+=session.parkedScreenBytes;return{ringBytes,ringCapacityBytes:count*perSessionCap,parkedSessions,parkedScreenBytes,parkRestoreDeltas,parkRestoreFallbacks}}var OSC_TITLE_RE=/\x1b\][02];([^\x07\x1b]*)(?:\x07|\x1b\\)/g,TITLE_CARRY_CAP=1024;function titleCarryFrom(rest){let osc=rest.lastIndexOf("\x1B]");if(osc!==-1)return rest.slice(osc,osc+TITLE_CARRY_CAP);return rest.endsWith("\x1B")?"\x1B":""}function foldOscTitle(prevCarry,chunkText){let text=prevCarry+chunkText,title=null,end=0;OSC_TITLE_RE.lastIndex=0;for(let match=OSC_TITLE_RE.exec(text);match;match=OSC_TITLE_RE.exec(text))title=match[1]??"",end=match.index+match[0].length;return{title,carry:titleCarryFrom(text.slice(end))}}function scanOscTitle(session,buf){let{title,carry}=foldOscTitle(session.titleCarry,session.titleDecoder.write(buf));if(title!==null)session.title=title;session.titleCarry=carry}function peekRing(session,sinceOffset){if(!session)return{exists:!1,alive:!1,pid:null,offset:0,data:"",sinceValid:!1,exit:null};let windowStart=session.totalBytes-session.bytes,buf=Buffer.concat(session.chunks),sinceValid=!1;if(sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes)buf=buf.subarray(sinceOffset-windowStart),sinceValid=!0;return{exists:!0,alive:session.alive,pid:session.proc?.pid??null,offset:session.totalBytes,data:buf.toString("base64"),sinceValid,exit:session.exit??null}}async function settledWithin(exited,ms){let timer,settled=await Promise.race([exited.then(()=>!0,()=>!0),new Promise((resolve)=>{timer=setTimeout(()=>resolve(!1),ms)})]);if(timer)clearTimeout(timer);return settled}function signalProcessGroup(pid,signal,fallback,platform=process.platform,onSignal){if(platform!=="win32"&&pid>1)try{process.kill(-pid,signal),onSignal?.(`sent ${signal} to process group -${pid}`);return}catch{}try{fallback(),onSignal?.(`sent ${signal} to pid ${pid} (per-process fallback)`)}catch{}}var TERMINATION_GRACE_MS=500;async function terminatePtyChild(proc,onSettled,onSignal){if(proc.endTree){onSignal?.(await proc.endTree()),signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS),onSettled();return}if(signalProcessGroup(proc.pid,"SIGTERM",()=>proc.kill("SIGTERM"),process.platform,onSignal),!await settledWithin(proc.exited,TERMINATION_GRACE_MS))signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS);onSettled()}class PtyChildController{deps;constructor(deps){this.deps=deps}spawn(key,spec,spare=!1){let argv=spec.command&&spec.command.length>0?[...spec.command]:[spec.shell??resolveLoginShell()],session=freshSessionState(key,spec,argv);if(this.startChild(session),session.alive)this.deps.log?.("pty",`spawned ${argv[0]} for ${key} (pid ${session.proc?.pid})`),this.deps.onSessionStart?.(spare);return session}startChild(session){session.generation=randomUUID2(),session.oscSignals=void 0,session.programStatusEvent=void 0,this.reportStatus(session,null);try{session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...session.command],cwd:session.cwd,env:embeddedTerminalEnv(process.env,{TERM:"xterm-256color",COLUMNS:String(session.cols),LINES:String(session.rows),BASH_SILENCE_DEPRECATION_WARNING:"1",ROVE_TERMINAL_PTY:"1"}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0,session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session))}catch(err){session.alive=!1,this.deps.log?.("pty",`spawn failed for ${session.key}: ${err instanceof Error?err.message:String(err)}`)}}async endChild(session){if(!session.alive)return;let proc=session.proc;if(!proc){this.markExited(session);return}await terminatePtyChild(proc,()=>this.markExited(session),(line)=>this.deps.log?.("pty-signal",`${session.key}: ${line}`))}markExited(session,exit){if(!session.alive)return;if(session.alive=!1,session.oscSignals){let before=session.oscSignals.records.get("");if(clearTransientStatuses(session.oscSignals),before!==session.oscSignals.records.get(""))this.reportStatus(session,null)}let sessionExit={code:exit?.code??null,signal:exit?.signal??null,at:new Date().toISOString()};session.exit=sessionExit;try{session.proc?.close()}catch{}this.deps.onExit?.(session,sessionExit)}reportStatus(session,status){let event={key:session.key,generation:session.generation,revision:(session.programStatusEvent?.revision??0)+1,at:Date.now(),status};session.programStatusEvent=event,this.deps.onProgramStatus?.(event)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),text=buf.toString("latin1");session.oscSignals??=createOscSignals();let queries=scanOscSignals(session.oscSignals,buf,Date.now(),(status)=>this.reportStatus(session,status)),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,text);session.colorQueryCarry=colorQueries.carry;let replies=colorQueries.slots.map((slot)=>formatDefaultColorReply(slot,session.defaultColors));for(let i=0;i<Math.min(queries,16);i++)replies.push("\x1B]7501;?\x1B\\");let modeReplies=scanTerminalModes(session.modes,text);if(session.emulatorSinks.size===0)replies.push(...modeReplies);if(replies.length>0)try{session.proc?.write(replies.join(""))}catch{}scanOscTitle(session,buf),session.chunks.push(buf),session.bytes+=buf.byteLength,session.totalBytes+=buf.byteLength;while(session.bytes>this.deps.scrollbackCap&&session.chunks.length>1){let dropped=session.chunks.shift();if(!dropped)break;session.bytes-=dropped.byteLength,scanTerminalModes(session.ringModes,dropped.toString("latin1"))}this.deps.onOutput?.(session,buf)}}function shouldFreeze(session,now){let appended=session.totalBytes-(session.frozenTotalBytes??0);if(appended<=0)return!1;let since=now-session.lastFreezeAtMs;if(since<5000)return!1;return appended>=65536||since>=60000}class WarmSpare{deps;spare=null;constructor(deps){this.deps=deps}warm(cwd,shell,cols=80,rows=24){let argv0=shell??resolveLoginShell();if(this.spare?.alive&&this.spare.cwd===cwd&&this.spare.command[0]===argv0)return;let old=this.spare;if(this.spare=null,old)this.deps.endChild(old);let session=this.deps.spawn("::spare",{cwd,command:[argv0],cols,rows},!0);this.spare=session.alive?session:null}adopt(key,spec){let spare=this.spare;if(!spare?.alive||spare.cwd!==spec.cwd)return null;let want=spec.command&&spec.command.length>0?spec.command:[spec.shell??resolveLoginShell()];if(want.length!==1||want[0]!==spare.command[0])return null;this.spare=null,spare.key=key,spare.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??spare.defaultColors;let cols=spec.cols??spare.cols,rows=spec.rows??spare.rows;if(spare.cols!==cols||spare.rows!==rows){spare.cols=cols,spare.rows=rows;try{spare.proc?.resize(cols,rows)}catch{return this.deps.markExited(spare),null}}return this.deps.log?.("pty",`adopted warm shell for ${key} (pid ${spare.proc?.pid})`),this.deps.onSessionStart?.(),this.warm(spec.cwd,spare.command[0],cols,rows),spare}async end(){let spare=this.spare;if(this.spare=null,spare)await this.deps.endChild(spare)}}var LOGGED_WRITE_BYTES=1024,DEFAULT_SCROLLBACK_CAP=524288,EXIT_TAIL_BYTES=16384;class PtyHost{sessions=new Map;opts;scrollbackCap;parkRestoreDeltas=0;parkRestoreFallbacks=0;childController;warmSpare;constructor(opts={}){this.opts=opts,this.scrollbackCap=opts.scrollbackCap??DEFAULT_SCROLLBACK_CAP,this.childController=new PtyChildController({driver:opts.driver,onProgramStatus:(event)=>this.opts.onProgramStatus?.(event),scrollbackCap:this.scrollbackCap,onSessionStart:(spare)=>{if(!spare)this.opts.onSessionStart?.()},onOutput:(session,data)=>{if(session.sinks.size===0){this.maybeFreeze(session);return}let frame={type:"event",name:"pty.data",payload:{key:session.key,data:data.toString("base64")}};for(let sink of session.sinks.values())sink(frame);this.maybeFreeze(session)},onExit:(session,exit)=>{let frame={type:"event",name:"pty.exit",payload:{key:session.key,pid:session.proc?.pid??null,...exit}};for(let sink of session.sinks.values())sink(frame);if(this.opts.log?.("pty",`session ${session.key} exited${describeExit(exit)}`),this.maybeFreeze(session,!0),!session.closedByRequest)try{this.opts.onSessionExit?.({key:session.key,pid:session.proc?.pid??null,exit,tail:ringTail(session.chunks,session.bytes,EXIT_TAIL_BYTES)})}catch{}this.opts.onSessionEnd?.()},log:(event,message)=>this.opts.log?.(event,message)}),this.warmSpare=new WarmSpare({spawn:(key,spec,spare)=>this.childController.spawn(key,spec,spare),endChild:(session)=>this.childController.endChild(session),markExited:(session)=>this.childController.markExited(session),log:(event,message)=>this.opts.log?.(event,message),onSessionStart:()=>this.opts.onSessionStart?.()})}open(key,spec,token,sink,sinceOffset,sincePid,answersQueries=!1){let session=this.sessions.get(key),created=!1,respawned=!1;if(!session)created=!0,session=this.warmSpare.adopt(key,spec)??this.childController.spawn(key,spec),this.sessions.set(key,session);else if(!session.alive&&session.restored)this.respawn(session,spec),respawned=session.alive;else if(session.alive&&spec.cols!==void 0&&spec.rows!==void 0&&(session.cols!==spec.cols||session.rows!==spec.rows))this.resize(key,spec.cols,spec.rows);let defaultColors=parseTerminalDefaultColors(spec.defaultColors);if(defaultColors)session.defaultColors=defaultColors;if(session.sinks.set(token,sink),answersQueries)session.emulatorSinks.add(token);else session.emulatorSinks.delete(token);session.parked=!1,session.parkedScreenBytes=0;let windowStart=session.totalBytes-session.bytes,replay=Buffer.concat(session.chunks),sinceValid=!1;if(!created&&sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes&&sincePid!==void 0&&sincePid===session.proc?.pid)replay=replay.subarray(sinceOffset-windowStart),sinceValid=!0;if(sinceOffset!==void 0&&sincePid!==void 0)if(sinceValid)this.parkRestoreDeltas++;else this.parkRestoreFallbacks++;if(!sinceValid)replay=Buffer.concat([Buffer.from(terminalModePreamble(session.ringModes.modes),"latin1"),replay]);return{replay:replay.toString("base64"),alive:session.alive,pid:session.proc?.pid??null,created,respawned,offset:session.totalBytes,sinceValid}}warm(cwd,shell,cols=80,rows=24){this.warmSpare.warm(cwd,shell,cols,rows)}write(key,data){let session=this.sessions.get(key);if(!session?.alive||data.length===0)return;if(data.length>=LOGGED_WRITE_BYTES)this.opts.log?.("pty",`wrote ${data.length} bytes to ${key}`);try{session.proc?.write(data)}catch(error){this.opts.log?.("pty",`write failed on ${key} (${data.length} bytes): ${String(error)}`)}}resize(key,cols,rows){let session=this.sessions.get(key);if(!session?.alive)return;session.cols=cols,session.rows=rows;try{session.proc?.resize(cols,rows)}catch{}}killIfGeneration(key,expectedGeneration){let session=this.sessions.get(key);if(!session)return{accepted:!1,reason:"missing-session"};if(session.generation!==expectedGeneration)return{accepted:!1,reason:"generation-mismatch"};return this.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}kill(key){let session=this.sessions.get(key);if(!session)return Promise.resolve();return this.sessions.delete(key),session.closedByRequest=!0,this.opts.freeze?.drop(key),this.childController.endChild(session)}rename(from,to){let session=this.sessions.get(from);if(!session||from===to||this.sessions.has(to))return!1;if(this.sessions.delete(from),session.key=to,session.programStatusEvent){let previous=session.programStatusEvent;this.opts.onProgramStatus?.({...previous,revision:previous.revision+1,at:Date.now(),status:null}),session.programStatusEvent={...previous,key:to,revision:previous.revision+1,at:Date.now()},this.opts.onProgramStatus?.(session.programStatusEvent)}return this.sessions.set(to,session),this.opts.freeze?.drop(from),this.maybeFreeze(session,!0),this.opts.log?.("pty",`renamed session ${from} \u2192 ${to}`),!0}detach(key,token,parked=!1,parkedScreenBytes=0){let session=this.sessions.get(key);if(!session)return;session.sinks.delete(token),session.emulatorSinks.delete(token),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(session.emulatorSinks.delete(token),!session.sinks.delete(token))continue;this.applyParkedOnDetach(session)}}applyParkedOnDetach(session,parked=!1,parkedScreenBytes=0){if(session.sinks.size!==0)return;session.parked=parked,session.parkedScreenBytes=parked?Math.max(0,parkedScreenBytes):0}list(){return Array.from(this.sessions.values(),(s)=>sessionInfo(s))}peek(key,sinceOffset){return peekRing(this.sessions.get(key),sinceOffset)}stats(){return hostStats(this.sessions.values(),this.scrollbackCap,this.parkRestoreDeltas,this.parkRestoreFallbacks)}async killAll(){let sessions=Array.from(this.sessions.keys(),(key)=>this.kill(key));sessions.push(this.warmSpare.end()),await Promise.all(sessions)}async shutdown(){this.flushFrozen();let endings=Array.from(this.sessions.values(),(session)=>this.childController.endChild(session));endings.push(this.warmSpare.end()),await Promise.all(endings)}flushFrozen(){for(let session of this.sessions.values())this.maybeFreeze(session,!0)}restoreFrozen(records){let restoredCount=0;for(let record of records){if(this.sessions.has(record.key))continue;let session=thawSession(record,this.scrollbackCap);if(!session)continue;this.sessions.set(record.key,session),restoredCount++}if(restoredCount>0)this.opts.log?.("pty",`restored ${restoredCount} frozen session(s) from disk`);return restoredCount}respawn(session,spec){if(session.restored=!1,session.exit=null,spec.command&&spec.command.length>0)session.command=[...spec.command];if(session.cols=spec.cols??session.cols,session.rows=spec.rows??session.rows,session.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??session.defaultColors,this.childController.startChild(session),!session.alive)return;this.opts.log?.("pty",`respawned restored session ${session.key} (pid ${session.proc?.pid})`),this.opts.onSessionStart?.()}maybeFreeze(session,force=!1){let freeze=this.opts.freeze;if(!freeze||session.key.startsWith("::"))return;if(session.closedByRequest)return;let now=Date.now();if(!force&&!shouldFreeze(session,now))return;session.lastFreezeAtMs=now,session.frozenTotalBytes=session.totalBytes,freeze.save(freezeSession(session))}liveCount(){let n=0;for(let session of this.sessions.values())if(session.alive)n++;return n}}function dispatchPtyRequest(req,client,deps){let{ptys}=deps;switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.openChecked":case"pty.open":{let payload=objectPayload(req.payload);if(req.name==="pty.openChecked"&&requireString(payload,"admissionToken")!==admissionToken(ptys))return{kind:"changed"};let open=ptys.open(requireString(payload,"key"),{cwd:requireString(payload,"cwd"),command:Array.isArray(payload.command)?payload.command.filter((c)=>typeof c==="string"):void 0,shell:typeof payload.shell==="string"?payload.shell:void 0,cols:typeof payload.cols==="number"?payload.cols:void 0,rows:typeof payload.rows==="number"?payload.rows:void 0,defaultColors:parseTerminalDefaultColors(payload.defaultColors)??void 0},client,(frame)=>deps.writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0,payload.answersQueries===!0);return req.name==="pty.openChecked"?{kind:"opened",open}:open}case"pty.write":{let payload=objectPayload(req.payload);return ptys.write(requireString(payload,"key"),typeof payload.data==="string"?payload.data:""),{}}case"pty.resize":{let payload=objectPayload(req.payload);return ptys.resize(requireString(payload,"key"),typeof payload.cols==="number"?payload.cols:80,typeof payload.rows==="number"?payload.rows:24),{}}case"pty.kill":{let payload=objectPayload(req.payload),key=requireString(payload,"key");if("expectedGeneration"in payload)return ptys.killIfGeneration(key,requireString(payload,"expectedGeneration"));if(optionalBoolean(payload,"wait")===!0)return ptys.kill(key).then(()=>({accepted:!0,ended:!0}),(err)=>{return logDaemonError("pty-kill",err),{accepted:!0,ended:!1}});return ptys.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}case"pty.rename":{let payload=objectPayload(req.payload);return{renamed:ptys.rename(requireString(payload,"from"),requireString(payload,"to"))}}case"pty.detach":{let payload=objectPayload(req.payload);ptys.detach(requireString(payload,"key"),client,payload.parked===!0,typeof payload.parkedScreenBytes==="number"?payload.parkedScreenBytes:0)}return{};case"pty.watchStatus":client.watchProgramStatus=!0;for(let session of ptys.list())if(session.programStatusEvent)deps.writeFrame(client,{type:"event",name:"pty.programStatus",payload:session.programStatusEvent});return{supported:!0};case"pty.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),admissionToken:admissionToken(ptys),stats:ptys.stats(),...deps.version?{version:deps.version}:{}};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0)}case"pty.warm":{let payload=objectPayload(req.payload);return ptys.warm(requireString(payload,"cwd"),typeof payload.shell==="string"?payload.shell:void 0,typeof payload.cols==="number"?payload.cols:void 0,typeof payload.rows==="number"?payload.rows:void 0),{}}case"spawn.detached":{if(process.platform!=="win32")throw Error("spawn.detached is Windows-only");let payload=objectPayload(req.payload),env=objectPayload(payload.env);return spawnDetachedDaemon(requireString(payload,"command"),Array.isArray(payload.args)?payload.args.filter((a)=>typeof a==="string"):[],withoutPtyJob(Object.fromEntries(Object.entries(env).filter((e)=>typeof e[1]==="string"))),requireString(payload,"logPath")),{}}case"daemon.stop":return deps.requestStop(),{};default:throw Error(`unknown pty-host request: ${req.name}`)}}function admissionToken(ptys){return JSON.stringify(ptys.list().map((s)=>[s.key,s.generation,s.pid,s.alive]))}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.ROVE_PTY_MAX_LIFETIME_MS;if(raw===void 0)return null;let n=Number(raw);return Number.isFinite(n)&&n>0?n:null}function resolveIdleExitMs(){let raw=process.env.ROVE_PTY_IDLE_EXIT_MS;if(raw===void 0)return DEFAULT_IDLE_EXIT_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_IDLE_EXIT_MS}async function startPtyHostServer(options={}){migrateLegacyPtyHostData();let socketPath=options.socketPath??defaultPtyHostSocketPath(),pidPath=options.pidPath??defaultPtyHostPidPath(),freezeDir=options.freezeDir??defaultPtyFreezeDir(),idleExitMs=options.idleExitMs||resolveIdleExitMs(),orphanCheckMs=options.orphanCheckMs||DEFAULT_ORPHAN_CHECK_MS,maxLifetimeMs=options.maxLifetimeMs??resolveMaxLifetimeMs(),bootedAtMs=Date.now(),log=options.log??(()=>{}),clients=new Set,stopping=!1,wipeFreezeOnStop=!1,idleTimer=null,cancelIdle=()=>{if(idleTimer)clearTimeout(idleTimer);idleTimer=null},armIdle=()=>{if(stopping)return;cancelIdle(),idleTimer=setTimeout(()=>{if(stopping||ptys.liveCount()>0)return;log("idle",`no live sessions for ${idleExitMs}ms \u2014 exiting`),stop()},idleExitMs)},orphaned=()=>{if(maxLifetimeMs!==null&&Date.now()-bootedAtMs>=maxLifetimeMs)return`exceeded its ${maxLifetimeMs}ms lifetime ceiling`;let owner;try{owner=readFileSync(pidPath,"utf8").trim()}catch{return`pidfile ${pidPath} is gone`}let pid=Number.parseInt(owner,10);if(pid===process.pid)return null;return Number.isInteger(pid)?`pidfile ${pidPath} now names pid ${pid}`:`pidfile ${pidPath} is unreadable`},orphanTimer=setInterval(()=>{if(stopping)return;let reason=orphaned();if(!reason)return;log("orphan",`${reason} \u2014 exiting rather than outliving my owner`),stop()},orphanCheckMs);orphanTimer.unref?.();let ptys=new PtyHost({onProgramStatus:(event)=>{for(let client of clients)if(client.watchProgramStatus)writeFrame(client,{type:"event",name:"pty.programStatus",payload:event})},onSessionStart:cancelIdle,onSessionEnd:()=>{if(ptys.liveCount()===0)armIdle()},onSessionExit:(info)=>{try{recordPtyExit(info)}catch(err){log("pty",`exit record write failed for ${info.key}: ${err instanceof Error?err.message:String(err)}`)}},freeze:fileFreezeSink(freezeDir),driver:options.driver,log});ptys.restoreFrozen(loadFrozenSessions(freezeDir,Date.now(),(s)=>{let mib=(bytes)=>`${Math.round(bytes/1048576)}MB`,notes=[`restored ${s.restored} (${mib(s.bytesRead)})`];if(s.deferred>0)notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);if(s.expired>0)notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS/86400000}-day TTL`);if(s.unreadable>0)notes.push(`${s.unreadable} unreadable`);log("freeze",notes.join(", "))}));let pipeSocket=isWindowsPipePath(socketPath);if(await ensureOwnerOnlyStateDir(resolveDaemonHomeDir()),!pipeSocket)await mkdir(dirname(socketPath),{recursive:!0});await mkdir(dirname(pidPath),{recursive:!0});let server=createServer((socket)=>{let client={socket,writer:new ClientWriter(socket,{onOverflow:()=>{log("backpressure","disconnecting PTY client whose critical queue exceeded 8MiB"),socket.destroy()}})};clients.add(client);let receiver=new LineReceiver;socket.on("data",(chunk)=>{if(!receiver.push(chunk,(line)=>handleLine(client,line)))log("framing","disconnecting PTY client whose request exceeded 8MiB"),socket.destroy()}),socket.on("error",()=>{}),socket.on("close",()=>{clients.delete(client),ptys.detachClient(client)})}),api={socketPath,pidPath,async close(){if(stopping)return;if(stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown(),wipeFreezeOnStop)clearFrozenSessions(freezeDir);for(let client of Array.from(clients))client.socket.destroy();if(await new Promise((resolve)=>server.close(()=>resolve())),!pipeSocket)await unlink(socketPath).catch(()=>{});await unlink(pidPath).catch(()=>{})}};async function stop(){await api.close().catch((err)=>logDaemonError("pty-host-shutdown",err)),options.onStop?.()}let verbDeps={ptys,writeFrame,requestStop:()=>{wipeFreezeOnStop=!0,setTimeout(()=>void stop(),0).unref()},...options.version?{version:options.version}:{}};function handleLine(client,line){if(line.trim().length>0){let frame=null;try{frame=JSON.parse(line)}catch{writeFrame(client,{type:"response",id:"parse-error",error:{message:"malformed frame"}})}if(frame)if(frame.type!=="request")writeFrame(client,{type:"response",id:"parse-error",error:{message:"requests only"}});else{let req=frame,reply=(payload)=>writeFrame(client,{type:"response",id:req.id,name:req.name,payload}),fail=(err)=>writeFrame(client,{type:"response",id:req.id,name:req.name,error:{message:err instanceof Error?err.message:String(err)}});try{let payload=dispatchPtyRequest(req,client,verbDeps);if(payload instanceof Promise)payload.then(reply,fail);else reply(payload)}catch(err){fail(err)}}}}if(await listenOnUnixSocket(server,socketPath),await writeTextAtomic(pidPath,`${process.pid}
|
|
3
|
-
`),!pipeSocket)await writeTextAtomic(endpointPathFor(pidPath),`${socketPath}
|
|
4
|
-
`);return armIdle(),log("boot",`pty host listening on ${socketPath}`),api}function writeFrame(client,frame){client.writer.write(frameToLine(frame))}async function runPtyHostSubcommand(_argv){rotateLogIfNeeded(defaultPtyHostLogPath()),installDaemonCrashHandlers();let server=await startPtyHostServer({log:(event,message)=>console.log(formatPtyHostLine(event,message)),version:CURRENT_VERSION,onStop:()=>process.exit(0)});console.log(formatPtyHostLine("listen",`v${CURRENT_VERSION} listening on ${server.socketPath}`));let shutdown=async(signal)=>{console.log(formatPtyHostLine("signal",`${signal} received \u2014 closing host, frozen sessions kept`)),await server.close(),process.exit(0)};process.once("SIGINT",()=>void shutdown("SIGINT")),process.once("SIGTERM",()=>void shutdown("SIGTERM"))}export{runPtyHostSubcommand};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ENGINE_NOT_OBSERVED_REASON,ENGINE_START_POLL_MS,ENGINE_START_PROBE_MS,deliverHostedPrompt,deliverToKey,ensurePtyHost,findEngineKey,isTaskKey,killTaskSessions,listSessions,listSessionsOrNull,openPtyHost,outcomeFields,taskKeys}from"./chunk-4rya4jmx.js";import"./chunk-1gawhhd0.js";import"./chunk-ve348rmz.js";import"./chunk-yk498qwr.js";import"./chunk-sak1tphp.js";import"./chunk-a42j8eek.js";import"./chunk-4250pw6r.js";import"./chunk-bnv1mm5h.js";import"./chunk-rxqdw6s5.js";import"./chunk-z80jjarw.js";import"./chunk-f5n0tgky.js";import"./chunk-z3zaa155.js";import"./chunk-30g1bgkg.js";import"./chunk-hpay0ax8.js";import"./chunk-catrr0z3.js";import"./chunk-b4zqkdyq.js";import"./chunk-rbr6qapz.js";import"./chunk-2tfnscxk.js";import"./chunk-8saxdp88.js";import"./chunk-w7zv47mp.js";import"./chunk-etfh8f4z.js";import"./chunk-b7xjhgts.js";import"./chunk-3126c9x9.js";import"./chunk-bwr6dygx.js";import"./chunk-812et2xk.js";import"./chunk-zsfyj36g.js";import"./chunk-tgfn5ykb.js";import"./chunk-qga9xd2f.js";import"./chunk-5v02t4pz.js";import"./chunk-ag3txfg2.js";import"./chunk-2brn8e1y.js";import"./chunk-xh72jz7c.js";import"./chunk-7zyyvc3d.js";import"./chunk-r6k3ve2g.js";import"./chunk-xy8be792.js";import"./chunk-7kysxgbq.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-tdhk4dz8.js";import"./chunk-m6pp9gaf.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-n3f5sdka.js";import"./chunk-zh0c8yzw.js";import"./chunk-wqckm0k6.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-625773dm.js";import"./chunk-xgans9wf.js";import"./chunk-cmp64q4j.js";import"./chunk-kmgheesn.js";import"./chunk-szjgjrar.js";import"./chunk-gskbzgc3.js";import"./chunk-pn5ygqn6.js";import"./chunk-n0rtj4z7.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import"./chunk-91sykzqq.js";export{taskKeys,outcomeFields,openPtyHost,listSessionsOrNull,listSessions,killTaskSessions,isTaskKey,findEngineKey,ensurePtyHost,deliverToKey,deliverHostedPrompt,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON};
|