@sma1lboy/rove 0.9.238 → 0.9.240
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli/chunk-0mj358p5.js +3 -0
- package/dist/cli/{chunk-nntg9d85.js → chunk-0y4qgnby.js} +1 -1
- package/dist/cli/chunk-1brfxbvg.js +4 -0
- package/dist/cli/chunk-21fm5tks.js +2 -0
- package/dist/cli/{chunk-bkbmqec2.js → chunk-28zg6p31.js} +1 -1
- package/dist/cli/chunk-2andp9gs.js +2 -0
- package/dist/cli/{chunk-r2pztgm6.js → chunk-2bgmby1d.js} +1 -1
- package/dist/cli/chunk-2vgc5cyj.js +2 -0
- package/dist/cli/chunk-2x9yc5nx.js +2 -0
- package/dist/cli/chunk-30kjq5m7.js +2 -0
- package/dist/cli/{chunk-b503z32q.js → chunk-31y92jm8.js} +3 -3
- package/dist/cli/{chunk-mkksdcsw.js → chunk-3342qzve.js} +1 -1
- package/dist/cli/{chunk-0wgheepg.js → chunk-34261s0m.js} +3 -3
- package/dist/cli/chunk-3aqhytyy.js +3 -0
- package/dist/cli/chunk-3c58659p.js +2 -0
- package/dist/cli/chunk-3d1hjrq0.js +2 -0
- package/dist/cli/{chunk-pzbrj3gd.js → chunk-3vyk7bzb.js} +1 -1
- package/dist/cli/chunk-41x1hrqe.js +3 -0
- package/dist/cli/chunk-4dv0mgan.js +2 -0
- package/dist/cli/{chunk-mhg40es1.js → chunk-4hestsjp.js} +1 -1
- package/dist/cli/{chunk-77w83wgh.js → chunk-4tx2kayk.js} +1 -1
- package/dist/cli/{chunk-aj7fkrha.js → chunk-4xj52nx1.js} +1 -1
- package/dist/cli/{chunk-s1p650mm.js → chunk-53cyns0f.js} +1 -1
- package/dist/cli/chunk-576r5nht.js +5 -0
- package/dist/cli/{chunk-1bm6sryf.js → chunk-5nsvp4h7.js} +1 -1
- package/dist/cli/{chunk-zyd6k6ak.js → chunk-7q43tysm.js} +1 -1
- package/dist/cli/chunk-801h8bze.js +4 -0
- package/dist/cli/chunk-80ydqr3s.js +3 -0
- package/dist/cli/{chunk-cv1kaq8a.js → chunk-85zr7kph.js} +5 -5
- package/dist/cli/{chunk-zwgns5ce.js → chunk-8tadwbx9.js} +1 -1
- package/dist/cli/chunk-96cjpssp.js +3 -0
- package/dist/cli/{chunk-bs7v83x0.js → chunk-9aydqazr.js} +1 -1
- package/dist/cli/{chunk-7txq91d9.js → chunk-9jsm6h5y.js} +1 -1
- package/dist/cli/{chunk-pz907kve.js → chunk-9w5g7frx.js} +1 -1
- package/dist/cli/chunk-a0ave3g6.js +3 -0
- package/dist/cli/{chunk-vnpqemb0.js → chunk-a7kq09ke.js} +1 -1
- package/dist/cli/chunk-abyk3w2j.js +2 -0
- package/dist/cli/chunk-adkva3ep.js +6 -0
- package/dist/cli/{chunk-nvqdmx7q.js → chunk-ag3txfg2.js} +1 -1
- package/dist/cli/{chunk-2rg6aw59.js → chunk-atmaakwp.js} +1 -1
- package/dist/cli/chunk-axsm0gn5.js +3 -0
- package/dist/cli/chunk-b0ssvpht.js +3 -0
- package/dist/cli/chunk-b39sdtt0.js +3 -0
- package/dist/cli/{chunk-grt1e2s8.js → chunk-bb5zqmea.js} +2 -2
- package/dist/cli/{chunk-g56km26e.js → chunk-bn73kd6z.js} +1 -1
- package/dist/cli/chunk-c2m55b72.js +4 -0
- package/dist/cli/{chunk-ch0ehc06.js → chunk-cbc1h345.js} +1 -1
- package/dist/cli/{chunk-dnbh8hsm.js → chunk-cbjh43yc.js} +1 -1
- package/dist/cli/chunk-cst86kt3.js +2 -0
- package/dist/cli/chunk-des00203.js +2 -0
- package/dist/cli/chunk-dgs0m8r4.js +3 -0
- package/dist/cli/chunk-dkgxz9hf.js +5 -0
- package/dist/cli/{chunk-mb1e73jm.js → chunk-ekd274v3.js} +2 -2
- package/dist/cli/{chunk-gqphk56d.js → chunk-ekg3h5z3.js} +7 -7
- package/dist/cli/chunk-f1nf99hj.js +2 -0
- package/dist/cli/chunk-fert44x2.js +2 -0
- package/dist/cli/chunk-ff1h2qxd.js +2 -0
- package/dist/cli/{chunk-cv6r89jp.js → chunk-ffs26p85.js} +1 -1
- package/dist/cli/{chunk-hp32tbes.js → chunk-fg62y5fm.js} +1 -1
- package/dist/cli/{chunk-s9a974w9.js → chunk-fvmee0tr.js} +1 -1
- package/dist/cli/{chunk-8h0khkap.js → chunk-fwqd5ta2.js} +2 -2
- package/dist/cli/{chunk-acw32w13.js → chunk-g0eygcnq.js} +6 -5
- package/dist/cli/chunk-g4c4ffqp.js +20 -0
- package/dist/cli/{chunk-k7g060qr.js → chunk-g4j41mky.js} +2 -2
- package/dist/cli/{chunk-j6kataan.js → chunk-g5c5jytr.js} +1 -1
- package/dist/cli/{chunk-dqndd97s.js → chunk-gkdfct7t.js} +2 -2
- package/dist/cli/chunk-gvrtrvnz.js +96 -0
- package/dist/cli/chunk-h2m7em1e.js +3 -0
- package/dist/cli/chunk-h33m6cc6.js +8 -0
- package/dist/cli/{chunk-ynbfqbn9.js → chunk-h3fckxn3.js} +1 -1
- package/dist/cli/chunk-h7y9v8k1.js +4 -0
- package/dist/cli/{chunk-32mv1yy6.js → chunk-h9cg0j3a.js} +1 -1
- package/dist/cli/{chunk-h4qv19v8.js → chunk-hbn1t161.js} +1 -1
- package/dist/cli/{chunk-3es6spp4.js → chunk-hq9tbzqa.js} +2 -2
- package/dist/cli/{chunk-snjte1rd.js → chunk-hr2xky15.js} +1 -1
- package/dist/cli/chunk-jxqs4y9j.js +10 -0
- package/dist/cli/{chunk-s0snbj93.js → chunk-kb6xw0fw.js} +1 -1
- package/dist/cli/{chunk-vyb5a2rh.js → chunk-kg9kmwt9.js} +1 -1
- package/dist/cli/chunk-ktzbg4jg.js +2 -0
- package/dist/cli/chunk-kz4txj2e.js +8 -0
- package/dist/cli/{chunk-bhqracn8.js → chunk-m19q29wk.js} +1 -1
- package/dist/cli/chunk-m1ekbqyz.js +2 -0
- package/dist/cli/chunk-m4f5h05c.js +10 -0
- package/dist/cli/chunk-m5gx53yr.js +3 -0
- package/dist/cli/chunk-m6q44xc0.js +2 -0
- package/dist/cli/{chunk-hq2n27y1.js → chunk-mw0ysrpd.js} +1 -1
- package/dist/cli/{chunk-2cwb64fj.js → chunk-n5dea05t.js} +1 -1
- package/dist/cli/chunk-nc46gddg.js +3 -0
- package/dist/cli/{chunk-jhbc9nx2.js → chunk-nckmga7j.js} +1 -1
- package/dist/cli/chunk-nem2x959.js +2 -0
- package/dist/cli/chunk-ng12dprz.js +2 -0
- package/dist/cli/chunk-npwzmmv9.js +3 -0
- package/dist/cli/chunk-nzh30nty.js +4 -0
- package/dist/cli/{chunk-gqrh2gp1.js → chunk-p024scd4.js} +1 -1
- package/dist/cli/chunk-p18ehv9y.js +7 -0
- package/dist/cli/{chunk-3sg5v7cg.js → chunk-p83wf4zw.js} +2 -2
- package/dist/cli/{chunk-s278gjet.js → chunk-pdvyfz3n.js} +1 -1
- package/dist/cli/chunk-pe6wnsww.js +2 -0
- package/dist/cli/chunk-prqeddy7.js +3 -0
- package/dist/cli/chunk-pvm3fc44.js +2 -0
- package/dist/cli/{chunk-2yd128k1.js → chunk-q5eee34y.js} +6 -6
- package/dist/cli/{chunk-z5fnv7nk.js → chunk-q7zzycy7.js} +25 -23
- package/dist/cli/chunk-qvfdqrbf.js +3 -0
- package/dist/cli/{chunk-2xsem13q.js → chunk-qzsahxd9.js} +1 -1
- package/dist/cli/chunk-rqyaf0dw.js +4 -0
- package/dist/cli/chunk-s57vy3k3.js +2 -0
- package/dist/cli/{chunk-g2advs8t.js → chunk-sak1tphp.js} +1 -1
- package/dist/cli/{chunk-vdcn6h48.js → chunk-snhcvjdb.js} +1 -1
- package/dist/cli/{chunk-bav389wj.js → chunk-svm809bx.js} +1 -1
- package/dist/cli/chunk-szrfp0jq.js +2 -0
- package/dist/cli/chunk-t8v9rpdx.js +2 -0
- package/dist/cli/{chunk-j4xfsn9g.js → chunk-tbrkck2f.js} +1 -1
- package/dist/cli/chunk-tdhk4dz8.js +4 -0
- package/dist/cli/chunk-thsmzarw.js +3 -0
- package/dist/cli/{chunk-t3wwsz29.js → chunk-tvk46rfs.js} +1 -1
- package/dist/cli/{chunk-4d54zgc7.js → chunk-twyda1p8.js} +2 -2
- package/dist/cli/{chunk-s1e0e9hc.js → chunk-vej49hnt.js} +2 -2
- package/dist/cli/chunk-w2sp489k.js +3 -0
- package/dist/cli/{chunk-0wh2ff77.js → chunk-whbm14qr.js} +2 -2
- package/dist/cli/chunk-wp9bygh4.js +2 -0
- package/dist/cli/{chunk-ww4fbx8h.js → chunk-wtb8cycx.js} +2 -2
- package/dist/cli/chunk-x9s14ppv.js +4 -0
- package/dist/cli/{chunk-hk8mc43r.js → chunk-xckpezd9.js} +5 -5
- package/dist/cli/{chunk-dq2mh3b3.js → chunk-xv8fhxxm.js} +1 -1
- package/dist/cli/{chunk-85pk7c74.js → chunk-xx166cdv.js} +1 -1
- package/dist/cli/{chunk-ssfj9td0.js → chunk-y8tysjc2.js} +15 -13
- package/dist/cli/{chunk-y3k1accw.js → chunk-yexx8nec.js} +1 -1
- package/dist/cli/{chunk-9prawccj.js → chunk-yt15y085.js} +1 -1
- package/dist/cli/{chunk-n0mg67wn.js → chunk-ytxk6zqc.js} +1 -1
- package/dist/cli/chunk-yvjgwnb9.js +2 -0
- package/dist/cli/{chunk-n24dmy2r.js → chunk-yxt1y0n3.js} +9 -9
- package/dist/cli/chunk-ze0htjr5.js +2 -0
- package/dist/cli/chunk-zeb0sttx.js +2 -0
- package/dist/cli/chunk-znjcesdr.js +5 -0
- package/dist/cli/chunk-zsfyj36g.js +3 -0
- package/dist/cli/chunk-zt49bbg9.js +3 -0
- package/dist/cli/chunk-zt7wfnva.js +3 -0
- package/dist/cli/{chunk-6rvzzrd7.js → chunk-zx2n95qe.js} +1 -1
- package/dist/cli/index.js +12 -10
- package/dist/cli/pty-host-node.mjs +880 -169
- package/dist/cli/rove-run.js +1 -1
- package/dist/cli/rove.js +6 -6
- package/dist/skills/rove/SKILL.md +1 -1
- package/dist/skills/rove/references/api-flags.md +5 -5
- package/dist/web-ui/assets/{harness-CQ-1WI4q.js → harness-BHiciz5A.js} +2 -2
- package/dist/web-ui/assets/{index-_ttAn6pY.js → index-BkxJISAI.js} +2 -2
- package/dist/web-ui/assets/{index-C4dLQEqf.css → index-nMJ42IGm.css} +1 -1
- package/dist/web-ui/index.html +2 -2
- package/dist/web-ui/origin-policy.mjs +1 -1
- package/dist/web-ui/pty-server.mjs +24 -10
- package/dist/web-ui/pty-session-lifecycle.mjs +9 -13
- package/package.json +6 -8
- package/dist/cli/chunk-05jej26n.js +0 -3
- package/dist/cli/chunk-079cyb2e.js +0 -4
- package/dist/cli/chunk-1265fmzk.js +0 -3
- package/dist/cli/chunk-1da3bqjc.js +0 -4
- package/dist/cli/chunk-1tx1s5v6.js +0 -2
- package/dist/cli/chunk-507zn8rs.js +0 -3
- package/dist/cli/chunk-53afdybj.js +0 -3
- package/dist/cli/chunk-544bwsss.js +0 -4
- package/dist/cli/chunk-67ev8k22.js +0 -2
- package/dist/cli/chunk-6s5mev2n.js +0 -4
- package/dist/cli/chunk-6x5vzzpx.js +0 -3
- package/dist/cli/chunk-7s1kx9ez.js +0 -2
- package/dist/cli/chunk-85mk6j0s.js +0 -3
- package/dist/cli/chunk-8hbtca1g.js +0 -3
- package/dist/cli/chunk-8pa1ph1s.js +0 -7
- package/dist/cli/chunk-9ek7xm94.js +0 -8
- package/dist/cli/chunk-9k47xr7m.js +0 -2
- package/dist/cli/chunk-9mtxxsb3.js +0 -2
- package/dist/cli/chunk-a1k2z44b.js +0 -2
- package/dist/cli/chunk-a3yyrabb.js +0 -2
- package/dist/cli/chunk-ahnk6zx3.js +0 -2
- package/dist/cli/chunk-bc18gat5.js +0 -4
- package/dist/cli/chunk-be757xzj.js +0 -3
- package/dist/cli/chunk-bw73t1zw.js +0 -5
- package/dist/cli/chunk-c2tevj9f.js +0 -2
- package/dist/cli/chunk-d1agt94n.js +0 -8
- package/dist/cli/chunk-dc31fzrm.js +0 -2
- package/dist/cli/chunk-dw853n4w.js +0 -3
- package/dist/cli/chunk-eawt4n4g.js +0 -2
- package/dist/cli/chunk-egx76ah2.js +0 -5
- package/dist/cli/chunk-ex1a2djb.js +0 -2
- package/dist/cli/chunk-f5e3dcxe.js +0 -2
- package/dist/cli/chunk-fwb72vzc.js +0 -2
- package/dist/cli/chunk-fxs82dsx.js +0 -4
- package/dist/cli/chunk-g3r1dwy9.js +0 -3
- package/dist/cli/chunk-ge30p4s5.js +0 -3
- package/dist/cli/chunk-gmgsxdrf.js +0 -10
- package/dist/cli/chunk-he76emdm.js +0 -2
- package/dist/cli/chunk-hgx20x94.js +0 -2
- package/dist/cli/chunk-hnfp317x.js +0 -2
- package/dist/cli/chunk-hq4b3fca.js +0 -3
- package/dist/cli/chunk-janvvpv5.js +0 -8
- package/dist/cli/chunk-jvxh93nz.js +0 -3
- package/dist/cli/chunk-k6nxyxyh.js +0 -3
- package/dist/cli/chunk-k8tspshr.js +0 -2
- package/dist/cli/chunk-md8k7c5w.js +0 -2
- package/dist/cli/chunk-mppda1wq.js +0 -3
- package/dist/cli/chunk-ppwpjm39.js +0 -3
- package/dist/cli/chunk-pvw2y93q.js +0 -25
- package/dist/cli/chunk-pw6yfj10.js +0 -3
- package/dist/cli/chunk-q4nehkj9.js +0 -2
- package/dist/cli/chunk-qagek3wg.js +0 -5
- package/dist/cli/chunk-r8xqvg26.js +0 -2
- package/dist/cli/chunk-rz8zs7j8.js +0 -3
- package/dist/cli/chunk-sb0ns0c7.js +0 -3
- package/dist/cli/chunk-tcj36cqg.js +0 -2
- package/dist/cli/chunk-vejgnmcp.js +0 -2
- package/dist/cli/chunk-vzqrj32e.js +0 -2
- package/dist/cli/chunk-wpsbyq4s.js +0 -2
- package/dist/cli/chunk-wtqxv2rv.js +0 -39
- package/dist/cli/chunk-y05d79az.js +0 -2
- package/dist/cli/chunk-y4048296.js +0 -4
- package/dist/cli/chunk-y8fqdnh3.js +0 -3
- package/dist/cli/chunk-ygd572ee.js +0 -4
- package/dist/cli/chunk-yj5pjxx2.js +0 -2
- package/dist/cli/chunk-zja9chrd.js +0 -4
- package/dist/cli/chunk-zwej00t0.js +0 -5
- package/dist/cli/kobe-run.js +0 -3
- package/dist/cli/kobe.js +0 -7
- package/dist/completions/kobe.bash +0 -25
- package/dist/completions/kobe.fish +0 -27
- package/dist/completions/kobe.zsh +0 -35
- /package/dist/cli/{chunk-hqbmzz4t.js → chunk-0422g8ac.js} +0 -0
- /package/dist/cli/{chunk-khj0apc7.js → chunk-2tfnscxk.js} +0 -0
- /package/dist/cli/{chunk-7q67dz4c.js → chunk-4250pw6r.js} +0 -0
- /package/dist/cli/{chunk-xsrcwcjc.js → chunk-5mhvjytn.js} +0 -0
- /package/dist/cli/{chunk-ef39ym8f.js → chunk-7bgbansg.js} +0 -0
- /package/dist/cli/{chunk-nh4wvyz3.js → chunk-atn06ncf.js} +0 -0
- /package/dist/cli/{chunk-h4n8ffqy.js → chunk-dmzg9zdc.js} +0 -0
- /package/dist/cli/{chunk-w25b7xxz.js → chunk-etfh8f4z.js} +0 -0
- /package/dist/cli/{chunk-hape5vwj.js → chunk-hpay0ax8.js} +0 -0
- /package/dist/cli/{chunk-f10n6063.js → chunk-pn5ygqn6.js} +0 -0
- /package/dist/cli/{chunk-rcyasw34.js → chunk-rxqdw6s5.js} +0 -0
- /package/dist/cli/{chunk-exfyqsdd.js → chunk-vjvkkrzc.js} +0 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{errorMessage}from"./chunk-2brn8e1y.js";import{JsonHookAdapter,bobAuthSecretsPath,claudeGlobalConfigPath,codexAuthPath,copilotConfigPath,editJsonSettings,hookCommandQuoting,isObject,isRoveHook,kimiCredentialsPath,readTextFileSyncBounded,roveHookArgs,roveHookInvocation}from"./chunk-znjcesdr.js";import{quoteShellArgv}from"./chunk-7kysxgbq.js";import{getCustomEngineIds,getDisabledEngineIds}from"./chunk-h9cg0j3a.js";import{__require}from"./chunk-wqfp8d9w.js";import{existsSync}from"fs";import{homedir}from"os";import{dirname,join}from"path";function parseFlatHooks(raw){if(raw===void 0)return{ok:!0,doc:{}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{ok:!1,reason:`not valid JSON (${err instanceof Error?err.message:String(err)})`}}if(!isObject(parsed))return{ok:!1,reason:"top level is not a JSON object"};if(parsed.hooks===void 0)return{ok:!0,doc:parsed};if(!isObject(parsed.hooks))return{ok:!1,reason:'"hooks" is not an object'};for(let[event,entries]of Object.entries(parsed.hooks))if(!Array.isArray(entries))return{ok:!1,reason:`"hooks.${event}" is not an array`};return{ok:!0,doc:parsed}}function mergeFlatHooks(format,current,install,inv=roveHookInvocation()){let verbs=format.eventMap.map((spec)=>spec.verb),{hooks:rawHooks,...rest}=current,hooks=isObject(rawHooks)?{...rawHooks}:{},quoting=hookCommandQuoting();for(let{event,verb}of format.eventMap){let kept=(Array.isArray(hooks[event])?hooks[event]:[]).filter((entry)=>!isRoveHook(entry,verbs));if(install){let command=quoteShellArgv([...inv,"hook",verb,...roveHookArgs(format.vendor)],quoting);kept.push(format.withType?{type:"command",command}:{command})}if(kept.length>0)hooks[event]=kept;else delete hooks[event]}return{version:1,...rest,hooks}}var CURSOR_HOOK_EVENT_MAP=[{event:"sessionStart",verb:"session-start"}],CURSOR_FORMAT={vendor:"cursor",eventMap:CURSOR_HOOK_EVENT_MAP};function cursorHooksPath(home=homedir()){let override=process.env.CURSOR_CONFIG_DIR?.trim();return join(override||join(home,".cursor"),"hooks.json")}function parseCursorHooks(raw){return parseFlatHooks(raw)}function mergeCursorHooks(current,install,inv=roveHookInvocation()){return mergeFlatHooks(CURSOR_FORMAT,current,install,inv)}class CursorHookAdapter{vendor="cursor";supportsHooks(){return!0}globalSettingsPath(){return cursorHooksPath()}activityDetailFromPayload(){return}cwdFromPayload(payload){let roots=payload.workspace_roots;return Array.isArray(roots)?firstString(...roots):void 0}sessionFromPayload(payload){let sessionId=firstString(payload.session_id,payload.conversation_id);if(!sessionId)return;let transcriptPath=firstString(payload.transcript_path);return{sessionId,...transcriptPath?{transcriptPath}:{}}}async installActivityHooks(settingsFilePath,opts={}){if(!existsSync(dirname(settingsFilePath)))return{ok:!0};let outcome=await editJsonSettings(settingsFilePath,(cur)=>mergeCursorHooks(cur,!0),parseCursorHooks);if(!outcome.ok&&!opts.quiet)process.stderr.write(`[rove hooks] cursor: skipped ${outcome.file}: ${outcome.reason}
|
|
3
|
+
`);return outcome}async removeActivityHooks(settingsFilePath){if(!existsSync(settingsFilePath))return;await editJsonSettings(settingsFilePath,(cur)=>mergeCursorHooks(cur,!1),parseCursorHooks)}hookConfigRefusal(raw){let parsed=parseCursorHooks(raw);return parsed.ok?void 0:parsed.reason}supportsWorktreeSync(){return!1}async removeWorktreeSyncHook(){}async removeWorktreeWatchHook(){}}function firstString(...values){for(let value of values)if(typeof value==="string"&&value)return value;return}import{homedir as homedir2}from"os";import{join as join2}from"path";import{existsSync as existsSync2}from"fs";import{dirname as dirname2}from"path";function sessionStartOnly(matcher){return[{event:"SessionStart",verb:"session-start",...matcher?{matcher}:{}}]}class SessionStartHookAdapter extends JsonHookAdapter{async installActivityHooks(settingsFilePath,opts={}){if(!existsSync2(dirname2(settingsFilePath)))return{ok:!0};return super.installActivityHooks(settingsFilePath,opts)}async removeActivityHooks(settingsFilePath){if(!existsSync2(settingsFilePath))return;await super.removeActivityHooks(settingsFilePath)}sessionFromPayload(payload){if(typeof payload.session_id!=="string"||!payload.session_id)return;return{sessionId:payload.session_id,...typeof payload.transcript_path==="string"&&payload.transcript_path?{transcriptPath:payload.transcript_path}:{}}}}var DEVIN_HOOK_EVENT_MAP=sessionStartOnly();function devinSettingsPath(home=homedir2()){let xdg=process.env.XDG_CONFIG_HOME?.trim();return join2(xdg||join2(home,".config"),"devin","config.json")}class DevinHookAdapter extends SessionStartHookAdapter{vendor="devin";eventMap=DEVIN_HOOK_EVENT_MAP;globalSettingsPath(){return devinSettingsPath()}}import{homedir as homedir3}from"os";import{join as join3}from"path";var DROID_HOOK_EVENT_MAP=sessionStartOnly();function droidSettingsPath(home=homedir3()){return join3(home,".factory","settings.json")}class DroidHookAdapter extends SessionStartHookAdapter{vendor="droid";eventMap=DROID_HOOK_EVENT_MAP;globalSettingsPath(){return droidSettingsPath()}}import{homedir as homedir4}from"os";import{join as join4}from"path";var QODERCLI_HOOK_EVENT_MAP=sessionStartOnly("*");function qodercliSettingsPath(home=homedir4()){let override=process.env.QODERCLI_CONFIG_DIR?.trim();return join4(override||join4(home,".qoder"),"settings.json")}class QodercliHookAdapter extends SessionStartHookAdapter{vendor="qodercli";eventMap=QODERCLI_HOOK_EVENT_MAP;globalSettingsPath(){return qodercliSettingsPath()}}var pluginEngines=new Map;function registerPluginEngine(id,spec){if(Object.hasOwn(CONTRIB_ENGINES,id))return!1;return pluginEngines.set(id,spec),!0}function clearPluginEngines(){pluginEngines.clear()}function pluginEngineIds(){return[...pluginEngines.keys()]}var GEMINI={rules:[{state:"blocked",any:["\u2502 apply this change","\u2502 allow execution","waiting for user confirmation"]},{state:"blocked",all:["do you want to proceed"],any:["yes"]},{state:"working",any:["esc to cancel"]}]},OPENCODE={rules:[{state:"blocked",any:["\u25B3 permission required"]},{state:"blocked",all:["esc dismiss"],any:["enter confirm","enter submit","enter toggle"]},{state:"working",any:["esc interrupt","esc to interrupt","ctrl+c to interrupt","esc again to interrupt"]},{state:"idle",any:["enter send"]}]},CURSOR={rules:[{state:"blocked",any:["press any key to log in"]},{state:"blocked",all:["proceed (y)"]},{state:"blocked",any:["run this command?","waiting for approval","skip (esc or n)","(y) (enter)"]},{state:"working",any:["esc to cancel","ctrl+c to stop"]}]},GROK={rules:[{state:"blocked",any:["\u26A0 action required","ctrl+o:yolo"]},{state:"blocked",all:["\u2503"],lineRegex:["^\\s*\u2503\\s+\\S+\\s+\\(\u25CB\\)"]},{state:"working",any:["[stop]"],lineRegex:["^\\s*[\\u2800-\\u28FF]"]}]},DROID={rules:[{state:"blocked",all:["enter to select","esc to cancel"],any:["> yes, allow","> no, cancel"]},{state:"blocked",all:["enter select","esc cancel"]},{state:"working",any:["esc to stop"]}]},AMP={rules:[{state:"blocked",any:["waiting for approval","run this command?","allow editing file:","allow creating file:","confirm tool call"]},{state:"working",lineRegex:["^\\s*\u2570\\s+\\S+\\s+(thinking|streaming|running tools|waiting)\\s+\u2500"]}]},CLINE={rules:[{state:"blocked",any:["let cline use this tool"]},{state:"blocked",all:["execute command?","yes"],any:["[act mode]","[plan mode]"]},{state:"blocked",all:["use this tool?","yes"],any:["[act mode]","[plan mode]"]}]},KIRO={rules:[{state:"blocked",all:["requires approval"],any:["yes, single permission","trust, always allow","no (tab to edit)","esc to close"]},{state:"blocked",all:["pending from subagents","tool approval"],any:["approve all pending","configure individually","exit (cancel subagents)"]},{state:"working",any:["kiro is working"]},{state:"working",all:["esc to cancel"],lineRegex:["^\\s*[\u25D4\u25D1\u25D5\u25CF]\\s+[A-Za-z]"]}]},MAKI={rules:[{state:"blocked",all:["permission required","y allow","n deny"]},{state:"blocked",all:["permission required"],any:["confirm allow","confirm deny"]},{state:"blocked",all:["permission required","enter deny","esc cancel"]},{state:"blocked",all:["plan complete","enter confirm"],any:["space toggle parallel","edit plan"]},{state:"working",bottomLines:1,lineRegex:["^( [\\u2800-\\u28FF]){1,2} \\[(BUILD|PLAN|BASH)\\]"]},{state:"idle",bottomLines:1,lineRegex:["^ \\[(BUILD|PLAN|BASH)\\]"]}]},ANTIGRAVITY={rules:[{state:"blocked",all:["requesting permission for:","do you want to proceed?"]},{state:"blocked",all:["requesting permission for:","tab amend","edit command"]},{state:"working",lineRegex:["^\\s*[\\u2800-\\u28FF]+\\s+[A-Za-z]+\\w*ing\\b"]},{state:"working",bottomLines:5,lineRegex:["\xB7\\s*[1-9][0-9]*\\s+task"]}]},DEVIN={rules:[{state:"blocked",bottomLines:8,all:["do you trust the authors of this directory?","yes, trust "]},{state:"blocked",bottomLines:8,all:["approve once","select","confirm","esc cancel"]},{state:"working",bottomLines:8,all:["running tools","esc to interrupt"]},{state:"working",bottomLines:6,all:["guide devin while it works"]},{state:"working",bottomLines:8,all:["reading shell ","timeout:"]},{state:"idle",bottomLines:8,all:["ask devin to build","features, fix bugs","your code"],lineRegex:["^\\s*\u276D Ask Devin to build"]},{state:"idle",bottomLines:6,all:["context:"],lineRegex:["^\\s*\u276D"]}]},QODERCLI={rules:[{state:"blocked",all:["waiting for user confirmation"],any:["yes","no","allow","reject"]},{state:"blocked",all:["awaiting approval"],any:["allow","reject"]},{state:"blocked",any:["permission required","allow once or always?","asking user","enter your response","review your answers:","shell awaiting input"]},{state:"working",any:["(esc to cancel,"]},{state:"working",lineRegex:["^\\s*[\\u2800-\\u28FF]\\s+.*[A-Za-z]"]}]},CONTRIB_ENGINES={gemini:{displayName:"Gemini CLI",defaultCommand:["gemini"],screenManifest:GEMINI},opencode:{displayName:"OpenCode",defaultCommand:["opencode"],screenManifest:OPENCODE,firstMessageDelivery:"paste"},cursor:{displayName:"Cursor Agent",defaultCommand:["cursor-agent"],screenManifest:CURSOR,createHookAdapter:()=>new CursorHookAdapter},grok:{displayName:"Grok CLI",defaultCommand:["grok"],screenManifest:GROK},droid:{displayName:"Droid",defaultCommand:["droid"],screenManifest:DROID,createHookAdapter:()=>new DroidHookAdapter},amp:{displayName:"Amp",defaultCommand:["amp"],screenManifest:AMP},devin:{displayName:"Devin",defaultCommand:["devin"],processNames:["devin-cli"],screenManifest:DEVIN,createHookAdapter:()=>new DevinHookAdapter},qodercli:{displayName:"Qoder CLI",defaultCommand:["qodercli"],processNames:["qoder","qoderclicn","qodercn"],screenManifest:QODERCLI,createHookAdapter:()=>new QodercliHookAdapter},cline:{displayName:"Cline",defaultCommand:["cline"],screenManifest:CLINE},kiro:{displayName:"Kiro CLI",defaultCommand:["kiro-cli"],processNames:["kiro"],screenManifest:KIRO},maki:{displayName:"Maki",defaultCommand:["maki"],screenManifest:MAKI},antigravity:{displayName:"Antigravity",defaultCommand:["agy"],processNames:["antigravity","antigravity-cli"],screenManifest:ANTIGRAVITY}};function isContribEngine(id){return Object.hasOwn(CONTRIB_ENGINES,id)||pluginEngines.has(id)}var CONTRIB_ENGINE_IDS=Object.keys(CONTRIB_ENGINES);function contribEngineEntry(id,base){let spec=CONTRIB_ENGINES[id]??pluginEngines.get(id);if(!spec)return base;return{...base,displayName:spec.displayName,defaultCommand:spec.defaultCommand,...spec.processNames?{processNames:spec.processNames}:{},screenManifest:spec.screenManifest,...spec.identity?{identity:spec.identity}:{},...spec.firstMessageDelivery?{firstMessageDelivery:spec.firstMessageDelivery}:{},...spec.createHookAdapter?{createHookAdapter:spec.createHookAdapter}:{}}}import{homedir as homedir6}from"os";import{spawnSync}from"child_process";import{existsSync as existsSync3,statSync}from"fs";import{homedir as homedir5}from"os";import path from"path";var defaultBinaryDeps={fileExists(p){try{return statSync(p).isFile()}catch{return!1}},env(name){return process.env[name]},home(){return homedir5()},which(name){let cmd=process.platform==="win32"?"where":"which",out=spawnSync(cmd,[name],{encoding:"utf8"});if(out.status!==0)return;let first=out.stdout.split(`
|
|
4
|
+
`).map((l)=>l.trim()).filter(Boolean)[0];if(!first)return;if(first.startsWith(`${name}:`)&&first.includes("aliased to")){let aliasTarget=first.split("aliased to")[1]?.trim();return aliasTarget&&existsSync3(aliasTarget)?aliasTarget:void 0}return first},readdir(p){try{return __require("fs").readdirSync(p)}catch{return[]}}};class BinaryNotFoundError extends Error{checkedPaths;constructor(label,hint,checkedPaths){super(`${label} not found. Checked: ${checkedPaths.join(", ")}. ${hint}`);this.name="BinaryNotFoundError",this.checkedPaths=checkedPaths}}function npmStyleDirs({deps,home},locations=["system","nvm","windowsNpm","npmGlobal","local","bun","bin"]){return locations.flatMap((location)=>{switch(location){case"system":return["/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"];case"homebrew":return["/opt/homebrew/bin","/usr/local/bin"];case"nvm":{let bin=deps.env("NVM_BIN");return bin?[bin]:[]}case"windowsNpm":{if((deps.platform?.()??process.platform)!=="win32")return[];let appData=deps.env("APPDATA"),localAppData=deps.env("LOCALAPPDATA");return[...localAppData?[path.join(localAppData,"npm")]:[],...appData?[path.join(appData,"npm")]:[],path.join(home,"AppData/Roaming/npm")]}case"npmGlobal":return[path.join(home,".npm-global/bin")];case"local":return[path.join(home,".local/bin")];case"yarn":return[path.join(home,".yarn/bin")];case"bun":return[path.join(home,".bun/bin")];case"bin":return[path.join(home,"bin")]}})}function createBinaryFinder(spec){return async function(deps=defaultBinaryDeps){let checked=[],whichResult=deps.which(spec.name);if(whichResult){if(checked.push(`which:${whichResult}`),deps.fileExists(whichResult))return whichResult}for(let candidate of spec.candidates({deps,home:deps.home()}))if(checked.push(candidate),deps.fileExists(candidate))return candidate;throw spec.notFound(checked)}}import path2 from"path";class BobBinaryNotFoundError extends BinaryNotFoundError{constructor(checkedPaths){super("IBM Bob Shell binary","Ensure 'bob' is on PATH (for example `curl -fsSL https://bob.ibm.com/download/bobshell.sh | bash`).",checkedPaths);this.name="BobBinaryNotFoundError"}}var findBobBinary=createBinaryFinder({name:"bob",candidates({deps,home}){let names=(deps.platform?.()??process.platform)==="win32"?["bob.exe","bob.cmd","bob"]:["bob"];return npmStyleDirs({deps,home}).flatMap((dir)=>names.map((name)=>path2.join(dir,name)))},notFound:(checked)=>new BobBinaryNotFoundError(checked)});import path3 from"path";class ClaudeBinaryNotFoundError extends BinaryNotFoundError{constructor(checkedPaths){super("Claude Code binary","Ensure 'claude' is on PATH, or install at ~/.claude/local/claude.",checkedPaths);this.name="ClaudeBinaryNotFoundError"}}var findClaudeBinary=createBinaryFinder({name:"claude",candidates({deps,home}){let out=[path3.join(home,".claude","local","claude")];out.push(...npmStyleDirs({deps,home},["nvm"]).map((dir)=>path3.join(dir,"claude")));let nvmRoot=path3.join(home,".nvm","versions","node"),versions=(deps.readdir?.(nvmRoot)??[]).sort((a,b)=>b.localeCompare(a,void 0,{numeric:!0}));for(let v of versions)out.push(path3.join(nvmRoot,v,"bin","claude"));return out.push(...npmStyleDirs({deps,home},["system","local","npmGlobal","yarn","bun","bin"]).map((dir)=>path3.join(dir,"claude"))),out},notFound:(checked)=>new ClaudeBinaryNotFoundError(checked)});import path4 from"path";class CodexBinaryNotFoundError extends BinaryNotFoundError{constructor(checkedPaths){super("Codex CLI binary","Ensure 'codex' is on PATH (e.g. `brew install codex` or the official installer).",checkedPaths);this.name="CodexBinaryNotFoundError"}}var findCodexBinary=createBinaryFinder({name:"codex",candidates({deps,home}){return npmStyleDirs({deps,home},["system","nvm","local","bun","bin"]).map((dir)=>path4.join(dir,"codex"))},notFound:(checked)=>new CodexBinaryNotFoundError(checked)});import path5 from"path";class CopilotBinaryNotFoundError extends BinaryNotFoundError{constructor(checkedPaths){super("GitHub Copilot CLI binary","Ensure 'copilot' is on PATH (for example `npm install -g @github/copilot` or `brew install copilot-cli`).",checkedPaths);this.name="CopilotBinaryNotFoundError"}}var findCopilotBinary=createBinaryFinder({name:"copilot",candidates({deps,home}){let names=(deps.platform?.()??process.platform)==="win32"?["copilot.exe","copilot.cmd","copilot"]:["copilot"];return npmStyleDirs({deps,home}).flatMap((dir)=>names.map((name)=>path5.join(dir,name)))},notFound:(checked)=>new CopilotBinaryNotFoundError(checked)});import path6 from"path";class KimiBinaryNotFoundError extends BinaryNotFoundError{constructor(checkedPaths){super("Kimi Code CLI binary","Ensure 'kimi' is on PATH or installed at ~/.kimi-code/bin/kimi.",checkedPaths);this.name="KimiBinaryNotFoundError"}}var findKimiBinary=createBinaryFinder({name:"kimi",candidates:(ctx)=>[path6.join(ctx.home,".kimi-code/bin"),...npmStyleDirs(ctx,["local","bin","homebrew"])].map((dir)=>path6.join(dir,"kimi")),notFound:(checked)=>new KimiBinaryNotFoundError(checked)});import path7 from"path";class PiFamilyBinaryNotFoundError extends BinaryNotFoundError{constructor(name,checkedPaths){super(`${name} CLI binary`,`Ensure '${name}' is on PATH (e.g. \`brew install ${name}\`, or \`npm i -g ${name==="omp"?"@oh-my-pi/pi-coding-agent":"@earendil-works/pi-coding-agent"}\`).`,checkedPaths);this.name="PiFamilyBinaryNotFoundError"}}function candidatesFor(name,ctx){let{home}=ctx,out=npmStyleDirs(ctx,["system","local","bun","bin"]).map((dir)=>path7.join(dir,name)),packageName=name==="omp"?"@oh-my-pi/pi-coding-agent":"@earendil-works/pi-coding-agent";for(let prefix of[path7.join(home,".npm-global"),"/usr/local","/opt/homebrew"])out.push(path7.join(prefix,"bin",name)),out.push(path7.join(prefix,"lib/node_modules",packageName,"dist","cli.js"));return out}var findPiBinary=createBinaryFinder({name:"pi",candidates:(ctx)=>candidatesFor("pi",ctx),notFound:(checked)=>new PiFamilyBinaryNotFoundError("pi",checked)}),findOmpBinary=createBinaryFinder({name:"omp",candidates:(ctx)=>candidatesFor("omp",ctx),notFound:(checked)=>new PiFamilyBinaryNotFoundError("omp",checked)});var defaultDeps={readFile(p){return readTextFileSyncBounded(p)},env(name){return process.env[name]},home(){return homedir6()},findClaudeBinary(){return findClaudeBinary()},findCodexBinary(){return findCodexBinary()},findBobBinary(){return findBobBinary()},findCopilotBinary(){return findCopilotBinary()},findKimiBinary(){return findKimiBinary()},findPiBinary(){return findPiBinary()},findOmpBinary(){return findOmpBinary()}};function decodeJwtPayload(jwt){let parts=jwt.split(".");if(parts.length!==3)return null;let payload=parts[1];if(!payload)return null;let b64=payload.replace(/-/g,"+").replace(/_/g,"/"),padded=b64+"=".repeat((4-b64.length%4)%4);try{let json=Buffer.from(padded,"base64").toString("utf8"),obj=JSON.parse(json);return typeof obj==="object"&&obj!==null?obj:null}catch{return null}}async function probeBinary(probe){try{return{found:!0,path:await probe()}}catch(err){if(err instanceof BinaryNotFoundError)return{found:!1,error:"not found on PATH"};return{found:!1,error:errorMessage(err)}}}var cachedDefaultVendors=null;async function probeAvailableVendors(deps){return(await Promise.all([["claude",()=>deps.findClaudeBinary()],["codex",()=>deps.findCodexBinary()],["copilot",()=>deps.findCopilotBinary()],["kimi",()=>deps.findKimiBinary()],["pi",()=>deps.findPiBinary()],["omp",()=>deps.findOmpBinary()]].map(async([vendor,probe])=>(await probeBinary(probe)).found?vendor:null))).filter((v)=>v!==null)}function detectAvailableVendors(deps=defaultDeps){if(deps!==defaultDeps)return probeAvailableVendors(deps);if(cachedDefaultVendors)return cachedDefaultVendors;let pending=probeAvailableVendors(deps).catch((err)=>{throw cachedDefaultVendors=null,err});return cachedDefaultVendors=pending,pending}function resetAvailableVendorsCache(){cachedDefaultVendors=null,cachedContribEngines=null}async function installedEngineIds(deps=defaultDeps){let builtins=await detectAvailableVendors(deps),contrib=await detectContribEngines();return[...new Set([...builtins,...getCustomEngineIds(),...contrib])]}async function availableEngineIds(deps=defaultDeps){let disabled=new Set(getDisabledEngineIds());return(await installedEngineIds(deps)).filter((id)=>!disabled.has(id))}var cachedContribEngines=null;function detectContribEngines(){if(cachedContribEngines)return cachedContribEngines;let which=globalThis.Bun?.which;return cachedContribEngines=Promise.resolve([...which?CONTRIB_ENGINE_IDS.filter((id)=>{let bin=CONTRIB_ENGINES[id]?.defaultCommand[0];return bin?which(bin)!==null:!1}):[],...pluginEngineIds()]),cachedContribEngines}async function detectClaudeAccount(deps=defaultDeps){let binary=await probeBinary(()=>deps.findClaudeBinary()),configPath=claudeGlobalConfigPath(deps.env,deps.home()),raw;try{raw=deps.readFile(configPath)}catch(err){return{binary,account:{kind:"none"},accountError:`read ${configPath}: ${errorMessage(err)}`}}if(raw===null)return{binary,account:{kind:"none"}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{binary,account:{kind:"none"},accountError:`parse ${configPath}: ${errorMessage(err)}`}}let oauth=parsed?.oauthAccount;if(!oauth||typeof oauth!=="object")return{binary,account:{kind:"none"}};let o=oauth,email=typeof o.emailAddress==="string"?o.emailAddress:void 0;if(!email)return{binary,account:{kind:"none"}};return{binary,account:{kind:"oauth",email,organization:typeof o.organizationName==="string"?o.organizationName:void 0,displayName:typeof o.displayName==="string"?o.displayName:void 0,billingType:typeof o.billingType==="string"?o.billingType:void 0}}}async function detectCodexAccount(deps=defaultDeps){let binary=await probeBinary(()=>deps.findCodexBinary()),authPath=codexAuthPath(deps.env,deps.home()),raw;try{raw=deps.readFile(authPath)}catch(err){return{binary,account:{kind:"none"},accountError:`read ${authPath}: ${errorMessage(err)}`}}if(raw===null)return{binary,account:{kind:"none"}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{binary,account:{kind:"none"},accountError:`parse ${authPath}: ${errorMessage(err)}`}}let obj=parsed??{},tokens=obj.tokens,idToken=typeof tokens?.id_token==="string"?tokens.id_token:void 0;if(idToken){let payload=decodeJwtPayload(idToken);if(!payload)return{binary,account:{kind:"none"},accountError:"codex id_token: malformed JWT"};let email=typeof payload.email==="string"?payload.email:void 0,authClaimRaw=payload["https://api.openai.com/auth"],authClaim=typeof authClaimRaw==="object"&&authClaimRaw!==null&&!Array.isArray(authClaimRaw)?authClaimRaw:void 0,plan=typeof authClaim?.chatgpt_plan_type==="string"?authClaim.chatgpt_plan_type:void 0;if(email)return{binary,account:{kind:"chatgpt",email,plan}};return{binary,account:{kind:"none"},accountError:"codex id_token: no email claim"}}let apiKey=obj.OPENAI_API_KEY;if(typeof apiKey==="string"&&apiKey.length>0)return{binary,account:{kind:"apikey"}};return{binary,account:{kind:"none"}}}async function detectCopilotAccount(deps=defaultDeps){let binary=await probeBinary(()=>deps.findCopilotBinary());for(let source of["COPILOT_GITHUB_TOKEN","GH_TOKEN","GITHUB_TOKEN"])if(deps.env(source)?.trim())return{binary,account:{kind:"token",source}};let configPath=copilotConfigPath(deps.env,deps.home()),raw;try{raw=deps.readFile(configPath)}catch(err){return{binary,account:{kind:"none"},accountError:`read ${configPath}: ${errorMessage(err)}`}}if(raw===null)return{binary,account:{kind:"none"}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{binary,account:{kind:"none"},accountError:`parse ${configPath}: ${errorMessage(err)}`}}if(!isRecord(parsed))return{binary,account:{kind:"none"}};if(hasStringDeep(parsed,["github_token","oauth_token","access_token","token","selectedUser","currentUser","user"]))return{binary,account:{kind:"oauth"}};return{binary,account:{kind:"none"}}}async function detectBobAccount(deps=defaultDeps){let binary=await probeBinary(()=>deps.findBobBinary()),secretsPath=bobAuthSecretsPath(deps.home()),raw;try{raw=deps.readFile(secretsPath)}catch(err){return{binary,account:{kind:"none"},accountError:`read ${secretsPath}: ${errorMessage(err)}`}}if(raw===null)return{binary,account:{kind:"none"}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{binary,account:{kind:"none"},accountError:`parse ${secretsPath}: ${errorMessage(err)}`}}if(!isRecord(parsed))return{binary,account:{kind:"none"}};let signedIn=Object.entries(parsed).some(([key,value])=>key.startsWith("bob.auth.tokens-")&&typeof value==="string"&&value.length>0);return{binary,account:signedIn?{kind:"oauth"}:{kind:"none"}}}async function detectKimiAccount(deps=defaultDeps){let binary=await probeBinary(()=>deps.findKimiBinary()),credPath=kimiCredentialsPath(deps.env,deps.home()),raw;try{raw=deps.readFile(credPath)}catch(err){return{binary,account:{kind:"none"},accountError:`read ${credPath}: ${errorMessage(err)}`}}if(raw===null)return{binary,account:{kind:"none"}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{binary,account:{kind:"none"},accountError:`parse ${credPath}: ${errorMessage(err)}`}}if(!isRecord(parsed))return{binary,account:{kind:"none"}};let token=parsed.access_token;if(typeof token==="string"&&token.length>0)return{binary,account:{kind:"oauth"}};return{binary,account:{kind:"none"}}}function isRecord(v){return typeof v==="object"&&v!==null&&!Array.isArray(v)}function hasStringDeep(value,interestingKeys,depth=0){if(depth>4||!isRecord(value))return!1;for(let[key,entry]of Object.entries(value)){if(interestingKeys.includes(key)&&typeof entry==="string"&&entry.length>0)return!0;if(isRecord(entry)&&hasStringDeep(entry,interestingKeys,depth+1))return!0}return!1}
|
|
5
|
+
export{parseFlatHooks,mergeFlatHooks,registerPluginEngine,clearPluginEngines,pluginEngineIds,isContribEngine,CONTRIB_ENGINE_IDS,contribEngineEntry,resetAvailableVendorsCache,installedEngineIds,availableEngineIds,detectClaudeAccount,detectCodexAccount,detectCopilotAccount,detectBobAccount,detectKimiAccount};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{$jsx,$jsxs,ReleaseNotesBody,bootPaneHost,pageCloseBindings,runShellUpdater,useBindings,useRenderer,useT,useTheme}from"./chunk-
|
|
2
|
+
import{$jsx,$jsxs,ReleaseNotesBody,bootPaneHost,pageCloseBindings,runShellUpdater,useBindings,useRenderer,useT,useTheme}from"./chunk-g0eygcnq.js";import"./chunk-80ydqr3s.js";import{require_react_production}from"./chunk-a82ec09z.js";import"./chunk-764bsyb0.js";import"./chunk-4xj52nx1.js";import"./chunk-atn06ncf.js";import"./chunk-nckmga7j.js";import"./chunk-vjvkkrzc.js";import"./chunk-pdvyfz3n.js";import"./chunk-dgs0m8r4.js";import"./chunk-dmzg9zdc.js";import"./chunk-6xppe9bj.js";import"./chunk-96cjpssp.js";import"./chunk-9w5g7frx.js";import"./chunk-gvrtrvnz.js";import"./chunk-ag3txfg2.js";import"./chunk-2brn8e1y.js";import"./chunk-xy8be792.js";import{BREAKING_VERSIONS,CURRENT_VERSION,UPDATE_COMMAND,breakingVersionsCrossed,fetchReleaseNotes,fetchReleaseSummaries}from"./chunk-a0ave3g6.js";import"./chunk-40dgv828.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-snhcvjdb.js";import"./chunk-zt49bbg9.js";import"./chunk-nhakrm1f.js";import"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{__toESM}from"./chunk-wqfp8d9w.js";import{TextAttributes}from"@opentui/core";var import_react2=__toESM(require_react_production(),1);var RELEASE_LIMIT=20;function VersionsPage(props){let{theme}=useTheme(),t=useT(),renderer=useRenderer(),[releases,setReleases]=import_react2.useState(null),[cursor,setCursor]=import_react2.useState(0),[notes,setNotes]=import_react2.useState({}),[status,setStatus]=import_react2.useState(null),selected=releases?.[cursor],crossings=selected?breakingVersionsCrossed(CURRENT_VERSION,selected.version):[],loadSummaries=props.fetchSummaries??fetchReleaseSummaries,loadNotes=props.fetchNotes??fetchReleaseNotes;import_react2.useEffect(()=>{loadSummaries(RELEASE_LIMIT).then((fetched)=>setReleases(fetched))},[loadSummaries]);let selectedVersion=selected?.version;import_react2.useEffect(()=>{if(selectedVersion===void 0||notes[selectedVersion]!==void 0)return;setNotes((cache)=>({...cache,[selectedVersion]:"loading"})),loadNotes(selectedVersion).then((fetched)=>{setNotes((cache)=>({...cache,[selectedVersion]:fetched??"missing"}))})},[selectedVersion,notes,loadNotes]);function move(delta){let count=releases?.length??0;if(count===0)return;setCursor((index)=>(index+delta+count)%count)}async function installSelected(){if(!selected)return;setStatus(t("update.statusRunningUpdater")),await new Promise((resolve)=>setTimeout(resolve,30)),await runShellUpdater({renderer,t,targetLabel:selected.version,command:`${UPDATE_COMMAND} -s -- ${selected.version}`})}useBindings(()=>({bindings:[{key:"up",cmd:()=>move(-1)},{key:"down",cmd:()=>move(1)},{key:"k",cmd:()=>move(-1)},{key:"j",cmd:()=>move(1)},{key:"return",cmd:()=>void installSelected()},{key:"u",cmd:()=>void installSelected()},...pageCloseBindings(props.onClose)]}));let selectedNotes=selectedVersion===void 0?void 0:notes[selectedVersion];return $jsxs("box",{flexDirection:"column",flexGrow:1,paddingTop:1,paddingLeft:2,paddingRight:2,children:[$jsxs("box",{flexDirection:"row",justifyContent:"space-between",flexShrink:0,children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"none",children:t("update.versions.pageTitle")}),$jsx("text",{fg:theme.textMuted,wrapMode:"none",onMouseUp:props.onClose,children:t("update.versions.closeHint")})]}),$jsxs("box",{flexDirection:"row",flexGrow:1,paddingTop:1,gap:2,children:[$jsxs("box",{flexDirection:"column",width:26,flexShrink:0,children:[releases===null?$jsx("text",{fg:theme.textMuted,children:t("update.versions.loading")}):null,releases!==null&&releases.length===0?$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("update.versions.unavailable")}):null,(releases??[]).map((release,index)=>{let active=index===cursor,tags=[release.version===CURRENT_VERSION?t("update.versions.tagCurrent"):"",index===0?t("update.versions.tagLatest"):"",BREAKING_VERSIONS.includes(release.version)?t("update.versions.tagBreaking"):""].filter(Boolean).join(" ");return $jsxs("box",{flexDirection:"row",gap:1,paddingLeft:1,backgroundColor:active?theme.primary:void 0,onMouseUp:()=>setCursor(index),children:[$jsxs("text",{fg:active?theme.selectedListItemText:theme.text,attributes:release.version===CURRENT_VERSION?TextAttributes.BOLD:void 0,wrapMode:"none",children:["v",release.version]}),tags?$jsx("text",{fg:active?theme.selectedListItemText:theme.textMuted,wrapMode:"none",children:tags}):null]},release.version)})]}),$jsxs("box",{flexDirection:"column",flexGrow:1,flexShrink:1,children:[$jsx("scrollbox",{flexGrow:1,flexShrink:1,stickyScroll:!1,verticalScrollbarOptions:{trackOptions:{foregroundColor:"transparent"}},children:$jsxs("box",{flexDirection:"column",paddingRight:1,paddingBottom:1,gap:0,children:[selectedNotes==="loading"?$jsx("text",{fg:theme.textMuted,children:t("update.loadingNotes")}):null,selectedNotes==="missing"?$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("update.notesUnavailable")}):null,selectedNotes!==void 0&&selectedNotes!=="loading"&&selectedNotes!=="missing"?$jsx(ReleaseNotesBody,{body:selectedNotes.body}):null]})}),crossings.length>0?$jsx("text",{fg:theme.warning,wrapMode:"word",children:t("update.versions.breakingWarning",{versions:crossings.join(", ")})}):null]})]}),status?$jsx("text",{fg:theme.info,wrapMode:"word",children:status}):null,$jsx("box",{flexShrink:0,paddingTop:1,children:$jsx("text",{fg:theme.textMuted,attributes:TextAttributes.DIM,wrapMode:"none",children:t("update.versions.footerHint")})})]})}var INLINE_ROWS=24;async function startVersionsHost(){await bootPaneHost({inlineRows:INLINE_ROWS,setup:()=>({root:()=>$jsx(VersionsPage,{onClose:()=>process.exit(0)})})})}export{startVersionsHost,VersionsPage};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{acquireSync,releaseSync}from"./chunk-mw0ysrpd.js";import{kvStatePath}from"./chunk-prqeddy7.js";import{mkdirSync,readFileSync,renameSync,writeFileSync}from"fs";import{dirname}from"path";var corruptWarned=!1;function readSavedRepos(state){let raw=state.savedRepos;if(!Array.isArray(raw))return[];return raw.filter((entry)=>typeof entry==="string")}function loadStateFile(){return readStateFile(!1)}function readStateFile(ownsLock){let path=kvStatePath(),text;try{text=readFileSync(path,"utf8")}catch{return{}}try{let parsed=JSON.parse(text);if(parsed&&typeof parsed==="object"&&!Array.isArray(parsed))return parsed}catch{}if(!ownsLock){let lockPath=`${path}.lock`,token;try{token=acquireSync(lockPath,0)}catch{return{}}try{return readStateFile(!0)}finally{releaseSync(lockPath,token)}}try{if(renameSync(path,`${path}.corrupt-${Date.now()}`),!corruptWarned)corruptWarned=!0,console.error(`[rove] ${path} is corrupted; backed up and starting fresh.`)}catch{}return{}}function writeStateFile(state){let path=kvStatePath();mkdirSync(dirname(path),{recursive:!0});let nonce=Math.random().toString(36).slice(2),tmp=`${path}.${process.pid}.${nonce}.tmp`;writeFileSync(tmp,JSON.stringify(state),{encoding:"utf8",mode:384}),renameSync(tmp,path)}function updateStateFile(mutate){let lockPath=`${kvStatePath()}.lock`,token=acquireSync(lockPath);try{let state=readStateFile(!0);if(mutate(state)!==!1)writeStateFile(state);return state}finally{releaseSync(lockPath,token)}}function patchStateFile(patch){return updateStateFile((state)=>{for(let[key,value]of Object.entries(patch))if(value===void 0)delete state[key];else state[key]=value;return})}function getPersistedBool(key,defaultValue){let value=loadStateFile()[key];return typeof value==="boolean"?value:defaultValue}function replaceStateFile(snapshot){updateStateFile((state)=>{for(let key of Object.keys(state))delete state[key];Object.assign(state,snapshot);return})}
|
|
3
3
|
export{readSavedRepos,loadStateFile,updateStateFile,patchStateFile,getPersistedBool,replaceStateFile};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{BREAKING_VERSIONS,CURRENT_VERSION,compareSemver}from"./chunk-a0ave3g6.js";import{loadStateFile,patchStateFile}from"./chunk-7q43tysm.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";var LAST_RUN_VERSION_KEY="app.lastRunVersion";function resetGateBlockers(lastRun,current=CURRENT_VERSION,breaking=BREAKING_VERSIONS){if(typeof lastRun!=="string"||lastRun.length===0)return[];let[lo,hi]=compareSemver(lastRun,current)<=0?[lastRun,current]:[current,lastRun];return breaking.filter((b)=>compareSemver(b,lo)>0&&compareSemver(b,hi)<=0)}function enforceResetGate(){let cliName=ROVE_PRODUCT_NAME,lastRun=loadStateFile()[LAST_RUN_VERSION_KEY],blockers=resetGateBlockers(lastRun);if(blockers.length>0){let from=typeof lastRun==="string"?lastRun:"unknown";console.error([`${cliName} ${CURRENT_VERSION}: cannot start \u2014 version ${blockers.join(", ")} introduced breaking changes`,`(last run: ${from}). Your daemon/session state may be incompatible.`,"","Run:",` ${cliName} reset # stop daemon + PTY host + sessions (tasks kept)`,` ${cliName} reset --hard # additionally wipe the task index + UI state`,"","Then relaunch Rove. Worktrees are never touched."].join(`
|
|
3
|
+
`)),process.exit(1)}if(lastRun!==CURRENT_VERSION)stampResetGate()}function stampResetGate(){try{patchStateFile({[LAST_RUN_VERSION_KEY]:CURRENT_VERSION})}catch{}}
|
|
4
|
+
export{LAST_RUN_VERSION_KEY,enforceResetGate,stampResetGate};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{isRowTokenTone}from"./chunk-atn06ncf.js";import{sameWorktreeChanges}from"./chunk-dgs0m8r4.js";import{ensureDaemonReachable,isStaleInstallError}from"./chunk-96cjpssp.js";import{toTaskId}from"./chunk-xy8be792.js";import{CURRENT_VERSION}from"./chunk-a0ave3g6.js";import{homeDir}from"./chunk-prqeddy7.js";import{createStateCell,mapReadableState}from"./chunk-nhakrm1f.js";import{DAEMON_PROTOCOL_VERSION,MIN_COMPATIBLE_PROTOCOL_VERSION,isAttentionInboxState,isDaemonVersionStale,isForeignDaemonHome,isProtocolCompatible,isRoutineInboxState,parseDaemonStopReason}from"./chunk-adkva3ep.js";import{logClient,logClientError}from"./chunk-hq9tbzqa.js";function parseWorktreeChangesPayload(payload){let changes=payload?.changes;if(!changes||typeof changes!=="object"||Array.isArray(changes))return null;let map=new Map;for(let[path,value]of Object.entries(changes)){let counts=value;if(typeof counts?.added!=="number"||typeof counts.deleted!=="number")return null;map.set(path,{added:counts.added,deleted:counts.deleted,...typeof counts.behind==="number"?{behind:counts.behind}:{},...typeof counts.ahead==="number"?{ahead:counts.ahead}:{}})}let unreadable=payload?.unreadable;if(Array.isArray(unreadable)){for(let path of unreadable)if(typeof path==="string"&&path.length>0)map.set(path,null)}return map}function sameWorktreeChangesMap(a,b){if(a.size!==b.size)return!1;for(let[path,counts]of a){if(!b.has(path))return!1;if(!sameWorktreeChanges(counts,b.get(path)??null))return!1}return!0}function parseToken(raw){if(!raw||typeof raw!=="object")return null;let t=raw;if(typeof t.source!=="string"||typeof t.key!=="string")return null;if(typeof t.text!=="string"||t.text.length===0)return null;if(typeof t.expiresAt!=="number"||!Number.isFinite(t.expiresAt))return null;return{source:t.source,key:t.key,text:t.text,...isRowTokenTone(t.tone)?{tone:t.tone}:{},expiresAt:t.expiresAt}}function parseRowTokensPayload(payload){let tokens=payload?.tokens;if(!tokens||typeof tokens!=="object"||Array.isArray(tokens))return null;let out=new Map;for(let[taskId,list]of Object.entries(tokens)){if(!Array.isArray(list))continue;let parsed=list.map(parseToken).filter((token)=>token!==null);if(parsed.length>0)out.set(taskId,parsed)}return out}function sameRowTokenMap(a,b){if(a.size!==b.size)return!1;for(let[taskId,left]of a){let right=b.get(taskId);if(!right||right.length!==left.length)return!1;for(let[i,token]of left.entries()){let other=right[i];if(!other||other.source!==token.source||other.key!==token.key||other.text!==token.text||other.tone!==token.tone||other.expiresAt!==token.expiresAt)return!1}}return!0}function liveRowTokens(map,taskId,now){let tokens=map?.get(taskId);if(!tokens||tokens.length===0)return[];return tokens.filter((token)=>token.expiresAt>now)}function shouldLogReconnectAttempt(attempt){if(attempt>100)return!1;return attempt===1||attempt%10===0}function describePayload(value){if(value===void 0)return"undefined";if(value===null)return"null";let type=Array.isArray(value)?"array":typeof value,text;try{text=typeof value==="string"?value:JSON.stringify(value)}catch{text=String(value)}if(text.length>120)text=`${text.slice(0,120)}\u2026`;return`${type}:${text}`}function decodeUiPrefsPayload(payload){let p=payload;if(!p||typeof p!=="object"||!("theme"in p))return null;if(p.theme!==null&&typeof p.theme!=="string")return null;return{theme:typeof p.theme==="string"&&p.theme.length>0?p.theme:null,..."themeMode"in p?{themeMode:typeof p.themeMode==="string"?p.themeMode:null}:{},transparentBackground:p.transparentBackground!==!1,focusAccent:typeof p.focusAccent==="string"?p.focusAccent:null,locale:typeof p.locale==="string"?p.locale:"",sortMode:p.sortMode==="recent"||p.sortMode==="attention"||p.sortMode==="name"?p.sortMode:"default",keysCollapsed:p.keysCollapsed===!0,projectFilter:typeof p.projectFilter==="string"&&p.projectFilter.length>0?p.projectFilter:null}}var TOKEN_TOTAL_FIELDS=["inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens"];function parseContextUsagePayload(payload){let context=payload?.context;if(!context||typeof context!=="object"||Array.isArray(context))return null;let map=new Map;for(let[key,value]of Object.entries(context)){let v=value;if(typeof v?.contextTokens!=="number")return null;if(v.contextWindowTokens!==void 0&&typeof v.contextWindowTokens!=="number")return null;let totals={};for(let field of TOKEN_TOTAL_FIELDS){let raw=v[field];if(raw===void 0)continue;if(typeof raw!=="number")return null;totals[field]=raw}map.set(key,{contextTokens:v.contextTokens,...typeof v.contextWindowTokens==="number"?{contextWindowTokens:v.contextWindowTokens}:{},...v.approximate===!0?{approximate:!0}:{},...totals})}return map}function sameContextUsageMap(a,b){if(a.size!==b.size)return!1;for(let[key,value]of a){let other=b.get(key);if(!other||other.contextTokens!==value.contextTokens||other.contextWindowTokens!==value.contextWindowTokens||other.approximate!==value.approximate||TOKEN_TOTAL_FIELDS.some((field)=>other[field]!==value[field]))return!1}return!0}function parseUsageSnapshotPayload(payload){let usage=payload?.usage;if(!usage||typeof usage!=="object"||Array.isArray(usage))return null;let map=new Map;for(let[vendor,value]of Object.entries(usage)){let snapshot=value;if(typeof snapshot?.capturedAt!=="number"||!Array.isArray(snapshot.windows))return null;let windows=[];for(let raw of snapshot.windows){let w=raw;if(typeof w?.kind!=="string"||typeof w.label!=="string"||typeof w.percent!=="number")return null;if(w.resetsAt!==null&&typeof w.resetsAt!=="number")return null;windows.push({kind:w.kind,label:w.label,percent:w.percent,resetsAt:w.resetsAt})}map.set(vendor,{windows,capturedAt:snapshot.capturedAt})}return map}function sameUsageSnapshotMap(a,b){if(a.size!==b.size)return!1;for(let[vendor,usage]of a){let other=b.get(vendor);if(!other||other.capturedAt!==usage.capturedAt||other.windows.length!==usage.windows.length)return!1;for(let i=0;i<usage.windows.length;i++){let x=usage.windows[i],y=other.windows[i];if(!x||!y||x.kind!==y.kind||x.label!==y.label||x.percent!==y.percent||x.resetsAt!==y.resetsAt)return!1}}return!0}function parseTranscriptActivityPayload(payload){let activity=payload?.activity;if(!activity||typeof activity!=="object"||Array.isArray(activity))return null;let map=new Map;for(let[path,value]of Object.entries(activity)){let v=value;if(typeof v?.mtimeMs!=="number"||typeof v.completionAt!=="number")return null;if(v.completionId!==null&&typeof v.completionId!=="string")return null;map.set(path,{mtimeMs:v.mtimeMs,completionId:v.completionId,completionAt:v.completionAt})}return map}function sameTranscriptActivityMap(a,b){if(a.size!==b.size)return!1;for(let[path,v]of a){let other=b.get(path);if(!other||other.mtimeMs!==v.mtimeMs||other.completionId!==v.completionId||other.completionAt!==v.completionAt)return!1}return!0}function deserializeTask(s){return{id:toTaskId(s.id),title:s.title,repo:s.repo,branch:s.branch,worktreePath:s.worktreePath,kind:s.kind,...s.scratch?{scratch:!0}:{},...s.routine?{routine:s.routine}:{},status:s.status,pinned:s.pinned,vendor:s.vendor,command:s.command,prStatus:s.prStatus,modelEffort:s.modelEffort,model:s.model,tier:s.tier,groupId:s.groupId,observedLanguage:s.observedLanguage,deletion:s.deletion,quotaResume:s.quotaResume,linkedWorkItem:s.linkedWorkItem,dispatcher:s.dispatcher,prompt:s.prompt,baseRef:s.baseRef,worktreeName:s.worktreeName,report:s.report,createdAt:s.createdAt,updatedAt:s.updatedAt}}async function runReconnectLoop(deps){let delayMs=deps.spawnDaemon?Math.floor(Math.random()*400):500,attempt=0;while(!deps.isDisposed()){if(delayMs>0)await new Promise((r)=>setTimeout(r,delayMs));if(deps.isDisposed())break;attempt++;try{if(deps.spawnDaemon)await deps.ensureReachable();await deps.init(),logClient("orch",`reconnected and re-subscribed after ${attempt} attempt(s) \u2014 task list re-synced`);return}catch(err){if(isStaleInstallError(err)){logClientError("orch-reconnect-fatal",err),deps.onFatal?.(err);return}if(deps.shouldLogAttempt(attempt))logClientError("orch-reconnect",err);delayMs=delayMs===0?500:Math.min(delayMs*2,3000)}}}async function performInit(client,opts,signals){let hello=await client.request("hello",{protocolVersion:DAEMON_PROTOCOL_VERSION,minProtocolVersion:MIN_COMPATIBLE_PROTOCOL_VERSION}),daemonVersion=typeof hello.protocolVersion==="number"?hello.protocolVersion:DAEMON_PROTOCOL_VERSION,daemonMin=typeof hello.minProtocolVersion==="number"?hello.minProtocolVersion:daemonVersion;if(!isProtocolCompatible({localVersion:DAEMON_PROTOCOL_VERSION,localMin:MIN_COMPATIBLE_PROTOCOL_VERSION,remoteVersion:daemonVersion,remoteMin:daemonMin}))throw Error(`Rove daemon is protocol v${daemonVersion} (min v${daemonMin}); this client is v${DAEMON_PROTOCOL_VERSION} (min v${MIN_COMPATIBLE_PROTOCOL_VERSION}). Restart the daemon (\`rove daemon restart\`) or upgrade Rove.`);let clientHome=homeDir();if(!opts.expectForeignHome&&isForeignDaemonHome(hello.homeDir,clientHome))throw Error(`Rove daemon on this socket serves ${hello.homeDir}, but this client uses ${clientHome}. A sandbox or dev daemon has taken the production socket \u2014 stop it (\`rove daemon stop\`), or unset ROVE_DAEMON_SOCKET_PATH / ROVE_DAEMON_SOCKET_PATH before starting it.`);if(signals.setDaemonVersionSig(typeof hello.roveVersion==="string"?hello.roveVersion:null),opts.onPeerIdentity?.({hostname:typeof hello.hostname==="string"?hello.hostname:"",homeDir:typeof hello.homeDir==="string"?hello.homeDir:"",daemonPid:typeof hello.daemonPid==="number"?hello.daemonPid:0,roveVersion:typeof hello.roveVersion==="string"?hello.roveVersion:""}),signals.setDaemonRestartingSig(!1),hello.tasks&&opts.subscribesTasks)signals.setTasks(hello.tasks.map(deserializeTask));if(await client.subscribe({role:opts.role,channels:opts.channels,cellPixelSize:opts.cellPixelSize}),hello.capabilities?.includes("worktree.changes")){if(signals.worktreeChangesAcc()===null)signals.setWorktreeChangesSig(new Map)}else signals.setWorktreeChangesSig(null);if(hello.capabilities?.includes("transcript.activity")){if(signals.transcriptActivityAcc()===null)signals.setTranscriptActivitySig(new Map)}else signals.setTranscriptActivitySig(null);signals.setConnectionState("online"),logClient("orch",`subscribed as ${opts.role} (${signals.tasksAcc().length} tasks)`)}var MAP_CHANNELS={"usage.snapshot":{what:"usage payload",parse:parseUsageSnapshotPayload,same:sameUsageSnapshotMap,read:(signals)=>signals.usageSnapshotAcc(),write:(signals,next)=>signals.setUsageSnapshotSig(next)},"usage.context":{what:"context payload",parse:parseContextUsagePayload,same:sameContextUsageMap,read:(signals)=>signals.contextUsageAcc(),write:(signals,next)=>signals.setContextUsageSig(next)},"worktree.changes":{what:"changes payload",parse:parseWorktreeChangesPayload,same:sameWorktreeChangesMap,read:(signals)=>signals.worktreeChangesAcc(),write:(signals,next)=>signals.setWorktreeChangesSig(next)},"transcript.activity":{what:"activity payload",parse:parseTranscriptActivityPayload,same:sameTranscriptActivityMap,read:(signals)=>signals.transcriptActivityAcc(),write:(signals,next)=>signals.setTranscriptActivitySig(next)},"task.tokens":{what:"token map",parse:parseRowTokensPayload,same:sameRowTokenMap,read:(signals)=>signals.rowTokensAcc(),write:(signals,next)=>signals.setRowTokensSig(next)}};function handleMapChannel(name,payload,signals){let channel=MAP_CHANNELS[name];if(!channel)return!1;let next=channel.parse(payload);if(!next)return logClientError("orch",`dropped ${name} event: malformed ${channel.what} (${describePayload(payload)})`),!0;let current=channel.read(signals);if(current&&channel.same(current,next))return!0;return channel.write(signals,next),!0}function writeGraphicsToStdout(data){if(!process.stdout.isTTY)return;process.stdout.write(data)}function pruneEngineState(tasks,signals){let live=new Set(tasks.map((t)=>t.id)),current=signals.engineStateAcc();if(current.size>0){let next=null;for(let key of current.keys()){if(live.has(key))continue;if(!next)next=new Map(current);next.delete(key)}if(next)signals.setEngineStateSig(next)}let tabs=signals.engineTabStateAcc();if(tabs.size>0){let nextTabs=null;for(let key of tabs.keys()){if(live.has(key))continue;if(!nextTabs)nextTabs=new Map(tabs);nextTabs.delete(key)}if(nextTabs)signals.setEngineTabStateSig(nextTabs)}let lifecycle=signals.engineLifecycleAcc();if(lifecycle.size>0){let nextLifecycle=null;for(let key of lifecycle.keys()){if(live.has(key))continue;if(!nextLifecycle)nextLifecycle=new Map(lifecycle);nextLifecycle.delete(key)}if(nextLifecycle)signals.setEngineLifecycleSig(nextLifecycle)}}function pruneTaskJobs(tasks,signals){let current=signals.taskJobsAcc();if(current.size===0)return;let live=new Set(tasks.map((t)=>t.id)),next=null;for(let key of current.keys()){if(live.has(key))continue;if(!next)next=new Map(current);next.delete(key)}if(next)signals.setTaskJobsSig(next)}function handleOrchestratorEvent(name,payload,signals){if(name==="task.snapshot"){let value=payload?.tasks;if(Array.isArray(value))signals.setTasks(value.map(deserializeTask)),pruneEngineState(value,signals),pruneTaskJobs(value,signals);else logClientError("orch",`dropped task.snapshot event: tasks is not an array (got ${describePayload(value)})`);return}if(name==="daemon.stopping"){let p=payload;if(typeof p?.roveVersion==="string")signals.setDaemonVersionSig(p.roveVersion);if(parseDaemonStopReason(p?.reason)==="restart")signals.setDaemonRestartingSig(!0);return}if(name==="active-task"){let id=payload?.taskId;signals.setActiveTaskSig(typeof id==="string"?id:null);return}if(name==="update"){let info=payload?.info;signals.setUpdateSig(info??null);return}if(name==="engine-state"){let p=payload;if(typeof p?.taskId!=="string"||typeof p.state!=="string"){logClientError("orch",`dropped engine-state event: taskId/state must be strings (taskId=${describePayload(p?.taskId)}, state=${describePayload(p?.state)})`);return}let tabId=typeof p.tabId==="string"&&p.tabId?p.tabId:void 0,entry={state:p.state,detail:p.detail,...typeof p.sessionId==="string"&&p.sessionId?{sessionId:p.sessionId}:{},...typeof p.transcriptPath==="string"&&p.transcriptPath?{transcriptPath:p.transcriptPath}:{},...tabId?{tabId}:{},at:typeof p.at==="number"?p.at:0},prevTaskState=signals.engineStateAcc().get(p.taskId)?.state;if(!tabId){let next=new Map(signals.engineStateAcc());if(p.state==="idle")next.delete(p.taskId);else next.set(p.taskId,entry);signals.setEngineStateSig(next)}if((p.state==="idle"||p.state==="turn_complete"||p.state==="error"||p.state==="running"&&prevTaskState!=="running")&&signals.engineLifecycleAcc().has(p.taskId)){let lifecycle=new Map(signals.engineLifecycleAcc());lifecycle.delete(p.taskId),signals.setEngineLifecycleSig(lifecycle)}if(tabId){let nextTabs=new Map(signals.engineTabStateAcc()),tabs=new Map(nextTabs.get(p.taskId)??[]);tabs.set(tabId,entry),nextTabs.set(p.taskId,tabs),signals.setEngineTabStateSig(nextTabs)}return}if(name==="attention.inbox"){let items=payload?.items;if(!Array.isArray(items)){logClientError("orch",`dropped attention.inbox event: items is not an array (${describePayload(items)})`);return}let kept=items.filter((item)=>{if(!item||typeof item!=="object"||Array.isArray(item))return!1;let p=item;return(typeof p.taskId==="string"||p.taskId===null&&isRoutineInboxState(p.state))&&(p.tabId===null||typeof p.tabId==="string")&&isAttentionInboxState(p.state)&&(p.unread===void 0||typeof p.unread==="boolean")&&typeof p.at==="number"});if(kept.length!==items.length)logClientError("orch",`dropped ${items.length-kept.length} malformed attention.inbox item(s) of ${items.length} (${describePayload(items)})`);if(kept.length===0&&items.length>0)return;signals.setAttentionInboxSig(kept.map((item)=>({...item,unread:item.unread!==!1})));return}if(name==="task.jobs"){let p=payload;if(typeof p?.taskId!=="string"||p.kind!=="ensureWorktree"){logClientError("orch",`dropped task.jobs event: expected string taskId + kind "ensureWorktree" (taskId=${describePayload(p?.taskId)}, kind=${describePayload(p?.kind)})`);return}let current=signals.taskJobsAcc();if(p.phase==="running"){let next=new Map(current);next.set(p.taskId,{kind:p.kind}),signals.setTaskJobsSig(next);return}if((p.phase==="done"||p.phase==="error")&¤t.has(p.taskId)){let next=new Map(current);next.delete(p.taskId),signals.setTaskJobsSig(next)}return}if(handleMapChannel(name,payload,signals))return;if(name==="tab.open"){let p=payload;if(typeof p?.taskId!=="string"||typeof p.at!=="number"||typeof p.title!=="string"||!Array.isArray(p.argv)){logClientError("orch",`dropped tab.open event: malformed payload (${describePayload(payload)})`);return}signals.setTabOpenSig(p);return}if(name==="tab.close"){let p=payload;if(!(p&&"kind"in p&&p.kind==="terminal-tab"?typeof p.taskId==="string"&&typeof p.tabId==="string"&&typeof p.requestId==="string"&&typeof p.at==="number":typeof p?.taskId==="string"&&typeof p.at==="number"&&("title"in p)&&typeof p.title==="string")){logClientError("orch",`dropped tab.close event: malformed payload (${describePayload(payload)})`);return}signals.setTabCloseSig(p);return}if(name==="tab.rename"){let p=payload;if(typeof p?.taskId!=="string"||typeof p.tabId!=="string"||typeof p.title!=="string"||typeof p.at!=="number"){logClientError("orch",`dropped tab.rename event: malformed payload (${describePayload(payload)})`);return}signals.setTabRenameSig(p);return}if(name==="ui.prompt"){let p=payload;if(typeof p?.promptId!=="string"||typeof p.title!=="string"||typeof p.at!=="number"){logClientError("orch",`dropped ui.prompt event: malformed payload (${describePayload(payload)})`);return}signals.setUiPromptSig(p);return}if(name==="engine.lifecycle"){let p=payload;if(typeof p?.taskId!=="string"||typeof p.kind!=="string"){logClientError("orch",`dropped engine.lifecycle event: malformed payload (${describePayload(payload)})`);return}let prev=signals.engineLifecycleAcc(),cur=prev.get(p.taskId)??{subagents:0},entry=p.kind==="subagent-start"?{subagents:cur.subagents+1}:p.kind==="subagent-stop"?{subagents:Math.max(0,cur.subagents-1)}:cur;if(entry===cur&&!prev.has(p.taskId))return;let map=new Map(prev);if(entry.subagents===0)map.delete(p.taskId);else map.set(p.taskId,entry);signals.setEngineLifecycleSig(map);return}if(name==="graphics.write"){let p=payload;if(typeof p?.data!=="string"||typeof p.imageId!=="number"||typeof p.at!=="number"){logClientError("orch",`dropped graphics.write event: malformed payload (${describePayload(payload)})`);return}signals.writeGraphics(Buffer.from(p.data,"base64"));return}if(name==="notice.event"){let p=payload;if(typeof p?.title!=="string"||typeof p.at!=="number"||typeof p.kind!=="string"){logClientError("orch",`dropped notice.event: malformed payload (${describePayload(payload)})`);return}signals.setNoticeSig(p);return}if(name==="ui-prefs"){let decoded=decodeUiPrefsPayload(payload);if(!decoded){let theme=payload?.theme;logClientError("orch",`dropped ui-prefs event: theme must be a string (got ${describePayload(theme)})`);return}signals.setUiPrefsSig(decoded);return}if(name==="keybindings"){let p=payload;if(typeof p?.rev!=="number"){logClientError("orch",`dropped keybindings event: rev must be a number (got ${describePayload(p?.rev)})`);return}signals.setKeybindingsRevSig(p.rev)}}function subscribeTasksOp(tasks,listener){try{listener(tasks())}catch(err){console.error("[rove RemoteOrchestrator] task listener threw on subscribe:",err)}return tasks.subscribe(()=>{try{listener(tasks.get())}catch(err){console.error("[rove RemoteOrchestrator] task listener threw:",err)}})}async function createTaskOp(client,input){let{modelEffort,...rest}=input,res=await client.request("task.create",{...rest,effort:modelEffort});return deserializeTask(res.task)}async function ensureMainTaskOp(client,repo){let res=await client.request("task.ensureMain",{repo});return deserializeTask(res.task)}async function openDirectoryTaskOp(client,input){let res=await client.request("task.openDir",input);return deserializeTask(res.task)}async function adoptScratchRepoOp(client,id,repo){await client.request("task.adoptScratchRepo",{taskId:String(id),repo})}async function ensureWorktreeOp(client,id){return(await client.request("task.ensureWorktree",{taskId:String(id)})).worktreePath}async function forgetProjectOp(client,repo){await client.request("project.forget",{repo})}function reportEngineInterruptOp(client,taskId,tabId){client.request("engine.reportEvent",{kind:"turn-interrupted",taskId,tabId}).catch(()=>{})}async function setTitleOp(client,id,title){await client.request("task.rename",{taskId:String(id),title})}async function setBranchOp(client,id,branch){await client.request("task.setBranch",{taskId:String(id),branch})}async function setVendorOp(client,id,vendor,effort,model){await client.request("task.setVendor",{taskId:String(id),vendor,...effort!==void 0?{effort}:{},...model!==void 0?{model}:{}})}async function setCommandOp(client,id,command,vendor){await client.request("task.setCommand",{taskId:String(id),command,...vendor?{vendor}:{}})}async function setPinnedOp(client,id,pinned){await client.request("task.pin",{taskId:String(id),pinned})}async function moveTaskOp(client,id,delta){await client.request("task.move",{taskId:String(id),direction:delta<0?"up":"down"})}async function moveTaskToTopOp(client,id){await client.request("task.move",{taskId:String(id),direction:"top"})}async function setPromptOp(client,id,prompt){await client.request("task.setPrompt",{taskId:String(id),prompt})}async function setStatusOp(client,id,status){await client.request("task.status",{taskId:String(id),status})}async function deleteTaskOp(client,id,opts){await client.request("task.delete",{taskId:String(id),force:opts?.force,deleteBranch:opts?.deleteBranch})}async function dismissAttentionOp(client,taskId,tabId,at){return(await client.request("attention.dismiss",{taskId:String(taskId),...tabId!==null?{tabId}:{},at})).deleted}async function dismissRoutineAttentionOp(client,automationId){return(await client.request("attention.dismissRoutine",{automationId})).deleted}async function markAttentionReadOp(client,taskId,tabId,at){return(await client.request("attention.read",{taskId:String(taskId),...tabId!==null?{tabId}:{},at})).updated}async function landPreflightOp(client,id){return(await client.request("task.landPreflight",{taskId:String(id)})).result}async function landTaskOp(client,id,opts){return(await client.request("task.land",{taskId:String(id),strategy:opts?.strategy,deleteBranch:opts?.deleteBranch,removeWorktree:opts?.removeWorktree,callerCwd:opts?.callerCwd})).result}async function discoverAdoptableWorktreesOp(client,repo){return(await client.request("worktree.discoverAdoptable",{repo})).worktrees}async function adoptWorktreeOp(client,input){let res=await client.request("worktree.adopt",input);return deserializeTask(res.task)}async function listWorktreesOp(client,opts){return(await client.request("worktree.list",{network:opts?.network!==!1})).projects}async function removeWorktreeOp(client,path,force){return(await client.request("worktree.remove",{path,force})).residue??null}async function syncBaseOp(client,taskId){return(await client.request("task.syncBase",{taskId})).result}async function failingChecksOp(client,taskId){let res=await client.request("pr.failingChecks",{taskId});return{checks:res.checks??[],totalFailing:res.totalFailing??0,...res.unavailable?{unavailable:res.unavailable}:{}}}async function listIssuesOp(client,repoRoot){return client.request("issue.list",{repoRoot})}async function listIssueReposOp(client){return(await client.request("issue.repos",{})).repos??[]}async function listFieldNotesOp(client,repo){return(await client.request("note.list",{repo})).notes??[]}async function deleteFieldNoteOp(client,repo,id){return(await client.request("note.delete",{repo,id})).deleted===!0}async function mutateIssueOp(client,repoRoot,op){return client.request("issue.mutate",{repoRoot,op})}async function listAutomationsOp(client){return client.request("automation.list",{})}async function createAutomationOp(client,input){return client.request("automation.create",input)}async function automationRunsOp(client,id){return client.request("automation.runs",{id})}async function setAutomationEnabledOp(client,id,enabled){return client.request("automation.update",{id,enabled})}async function runAutomationNowOp(client,id){return client.request("automation.runNow",{id})}async function deleteAutomationOp(client,id){return client.request("automation.delete",{id})}async function listWorkItemsOp(client,args){return client.request("workitem.list",args)}async function startWorkItemOp(client,args){return client.request("workitem.start",args)}async function setActiveTaskOp(client,id){await client.request("task.setActive",{taskId:id===null?null:String(id)})}function replyTabCloseOp(client,requestId,closed){client.request("terminalTab.closeReply",{requestId,closed}).catch(()=>{})}function replyPromptOp(client,promptId,value){client.request("ui.promptReply",{promptId,...value!==void 0?{value}:{}}).catch(()=>{})}function reportUiEventOp(client,kind,taskId,detail){client.request("ui.reportEvent",{kind,...taskId?{taskId}:{},...detail?{detail}:{}}).catch(()=>{})}function recentTaskEventsOp(client,id){return client.request("task.recentEvents",{taskId:String(id)})}class RemoteOrchestrator{client;tasksAcc=createStateCell([],"orchestrator.tasks");activeTaskAcc=createStateCell(null,"orchestrator.active-task");updateAcc=createStateCell(null);daemonVersionAcc=createStateCell(null);daemonRestartingAcc=createStateCell(!1);daemonStaleAcc=mapReadableState(this.daemonVersionAcc,(version)=>isDaemonVersionStale(version??void 0,CURRENT_VERSION));engineStateAcc=createStateCell(new Map);engineTabStateAcc=createStateCell(new Map);attentionInboxAcc=createStateCell([]);taskJobsAcc=createStateCell(new Map);rowTokensAcc=createStateCell(new Map);worktreeChangesAcc=createStateCell(null);usageSnapshotAcc=createStateCell(null);contextUsageAcc=createStateCell(null);transcriptActivityAcc=createStateCell(null);noticeAcc=createStateCell(null);tabOpenAcc=createStateCell(null);tabCloseAcc=createStateCell(null);tabRenameAcc=createStateCell(null);uiPromptAcc=createStateCell(null);engineLifecycleAcc=createStateCell(new Map);uiPrefsAcc=createStateCell(null);keybindingsRevAcc=createStateCell(null);connectionStateAcc=createStateCell("online","orchestrator.connection");staleInstallAcc=createStateCell(null);ensureReachable;role;cellPixelSize;channels;subscribesTasks;expectForeignHome;onPeerIdentity;reconnectTask=null;signals;constructor(client,options={}){this.client=client;this.ensureReachable=options.ensureReachable??ensureDaemonReachable,this.role=options.role??"pane",this.cellPixelSize=options.cellPixelSize??null,this.channels=options.channels,this.subscribesTasks=!options.channels||options.channels.includes("task.snapshot"),this.expectForeignHome=options.expectForeignHome===!0,this.onPeerIdentity=options.onPeerIdentity,this.signals={writeGraphics:options.graphicsOut??(this.role==="gui"?writeGraphicsToStdout:()=>{}),tasksAcc:this.tasksAcc,setTasks:this.tasksAcc.set,setActiveTaskSig:this.activeTaskAcc.set,setUpdateSig:this.updateAcc.set,setDaemonVersionSig:this.daemonVersionAcc.set,setDaemonRestartingSig:this.daemonRestartingAcc.set,engineStateAcc:this.engineStateAcc,setEngineStateSig:this.engineStateAcc.set,engineTabStateAcc:this.engineTabStateAcc,setEngineTabStateSig:this.engineTabStateAcc.set,setAttentionInboxSig:this.attentionInboxAcc.set,taskJobsAcc:this.taskJobsAcc,setTaskJobsSig:this.taskJobsAcc.set,rowTokensAcc:this.rowTokensAcc,setRowTokensSig:this.rowTokensAcc.set,worktreeChangesAcc:this.worktreeChangesAcc,setWorktreeChangesSig:this.worktreeChangesAcc.set,usageSnapshotAcc:this.usageSnapshotAcc,setUsageSnapshotSig:this.usageSnapshotAcc.set,contextUsageAcc:this.contextUsageAcc,setContextUsageSig:this.contextUsageAcc.set,transcriptActivityAcc:this.transcriptActivityAcc,setTranscriptActivitySig:this.transcriptActivityAcc.set,setNoticeSig:this.noticeAcc.set,setTabOpenSig:this.tabOpenAcc.set,setTabCloseSig:this.tabCloseAcc.set,setTabRenameSig:this.tabRenameAcc.set,setUiPromptSig:this.uiPromptAcc.set,engineLifecycleAcc:this.engineLifecycleAcc,setEngineLifecycleSig:this.engineLifecycleAcc.set,setUiPrefsSig:this.uiPrefsAcc.set,setKeybindingsRevSig:this.keybindingsRevAcc.set,setConnectionState:this.connectionStateAcc.set},this.client.on("*",(frame)=>handleOrchestratorEvent(frame.name,frame.payload,this.signals)),this.client.onLifecycle("close",()=>{this.connectionStateAcc.set("disconnected");let spawnDaemon=this.role==="gui";logClient("orch",spawnDaemon?"daemon socket closed \u2014 starting silent spawning reconnect loop":"daemon socket closed \u2014 starting non-spawning reconnect loop"),this.reconnectLoop(spawnDaemon)})}reconnectLoop(spawnDaemon){if(this.reconnectTask)return this.reconnectTask;let task=runReconnectLoop({isDisposed:()=>this.client.isDisposed,spawnDaemon,ensureReachable:this.ensureReachable,init:()=>this.init(),shouldLogAttempt:shouldLogReconnectAttempt,onFatal:(err)=>this.staleInstallAcc.set(err instanceof Error?err.message:String(err))});this.reconnectTask=task;let clear=()=>{if(this.reconnectTask===task)this.reconnectTask=null};return task.then(clear,clear),task}writeGraphics(data){this.signals.writeGraphics(data)}async init(){await performInit(this.client,{role:this.role,cellPixelSize:this.cellPixelSize,channels:this.channels,subscribesTasks:this.subscribesTasks,expectForeignHome:this.expectForeignHome,onPeerIdentity:this.onPeerIdentity},this.signals)}connectionStateSignal(){return this.connectionStateAcc}staleInstallSignal(){return this.staleInstallAcc}async manualReconnect(){this.client.forceDisconnect(),await this.reconnectLoop(!0)}dispose(){this.client.close()}tasksSignal=()=>this.tasksAcc;activeTaskSignal=()=>this.activeTaskAcc;updateSignal=()=>this.updateAcc;daemonVersionSignal=()=>this.daemonVersionAcc;daemonStaleSignal=()=>this.daemonStaleAcc;daemonRestartingSignal=()=>this.daemonRestartingAcc;async restartDaemon(){await this.client.request("daemon.stop",{reason:"restart"}).catch(()=>{})}engineStateSignal=()=>this.engineStateAcc;engineTabStatesSignal=()=>this.engineTabStateAcc;attentionInboxSignal=()=>this.attentionInboxAcc;taskJobsSignal=()=>this.taskJobsAcc;rowTokensSignal=()=>this.rowTokensAcc;worktreeChangesSignal=()=>this.worktreeChangesAcc;usageSnapshotSignal=()=>this.usageSnapshotAcc;contextUsageSignal=()=>this.contextUsageAcc;transcriptActivitySignal=()=>this.transcriptActivityAcc;transcriptActivityStore=()=>this.transcriptActivityAcc;noticeStore=()=>this.noticeAcc;tabOpenStore=()=>this.tabOpenAcc;tabCloseStore=()=>this.tabCloseAcc;tabRenameStore=()=>this.tabRenameAcc;rpc={request:(name,payload)=>this.client.request(name,payload)};replyTerminalTabClose=(requestId,closed)=>replyTabCloseOp(this.client,requestId,closed);uiPromptStore=()=>this.uiPromptAcc;replyPrompt=(promptId,value)=>replyPromptOp(this.client,promptId,value);engineLifecycleSignal=()=>this.engineLifecycleAcc;recentTaskEvents(id){return recentTaskEventsOp(this.client,id)}reportUiEvent=(kind,taskId,detail)=>reportUiEventOp(this.client,kind,taskId,detail);reportScreenInput=async(taskId,tabId,blocked)=>{await this.client.request("engine.reportEvent",{source:"screen",taskId,tabId,blocked})};reportEngineInterrupt=(taskId,tabId)=>reportEngineInterruptOp(this.client,String(taskId),tabId);uiPrefsSignal=()=>this.uiPrefsAcc;uiPrefsStore=()=>this.uiPrefsAcc;keybindingsRevSignal=()=>this.keybindingsRevAcc;keybindingsRevStore=()=>this.keybindingsRevAcc;listTasks=()=>this.tasksAcc();getTask=(id)=>this.tasksAcc().find((task)=>task.id===id);subscribeTasks(listener){return subscribeTasksOp(this.tasksAcc,listener)}createTask=(input)=>createTaskOp(this.client,input);ensureMainTask=(repo)=>ensureMainTaskOp(this.client,repo);openDirectoryTask=(input)=>openDirectoryTaskOp(this.client,input);adoptScratchRepo=(id,repo)=>adoptScratchRepoOp(this.client,id,repo);ensureWorktree=(id)=>ensureWorktreeOp(this.client,id);forgetProject=(repo)=>forgetProjectOp(this.client,repo);setTitle=(id,title)=>setTitleOp(this.client,id,title);setBranch=(id,branch)=>setBranchOp(this.client,id,branch);setVendor=(id,vendor,effort,model)=>setVendorOp(this.client,id,vendor,effort,model);setCommand=(id,command,vendor)=>setCommandOp(this.client,id,command,vendor);setPinned=(id,pinned)=>setPinnedOp(this.client,id,pinned);moveTask=(id,delta)=>moveTaskOp(this.client,id,delta);moveTaskToTop=(id)=>moveTaskToTopOp(this.client,id);setStatus=(id,status)=>setStatusOp(this.client,id,status);setPrompt=(id,prompt)=>setPromptOp(this.client,id,prompt);deleteTask=(id,opts)=>deleteTaskOp(this.client,id,opts);dismissAttention=(taskId,tabId,at)=>dismissAttentionOp(this.client,taskId,tabId,at);dismissRoutineAttention=(automationId)=>dismissRoutineAttentionOp(this.client,automationId);markAttentionRead=(taskId,tabId,at)=>markAttentionReadOp(this.client,taskId,tabId,at);landPreflight(id){return landPreflightOp(this.client,id)}landTask(id,opts){return landTaskOp(this.client,id,opts)}discoverAdoptableWorktrees(repo){return discoverAdoptableWorktreesOp(this.client,repo)}adoptWorktree(input){return adoptWorktreeOp(this.client,input)}listWorktrees(opts){return listWorktreesOp(this.client,opts)}listIssues(repoRoot){return listIssuesOp(this.client,repoRoot)}listIssueRepos(){return listIssueReposOp(this.client)}mutateIssue(repoRoot,op){return mutateIssueOp(this.client,repoRoot,op)}listAutomations=()=>listAutomationsOp(this.client);createAutomation=(i)=>createAutomationOp(this.client,i);automationRuns=(id)=>automationRunsOp(this.client,id);setAutomationEnabled=(id,on)=>setAutomationEnabledOp(this.client,id,on);runAutomationNow=(id)=>runAutomationNowOp(this.client,id);deleteAutomation=(id)=>deleteAutomationOp(this.client,id);listWorkItems=(a)=>listWorkItemsOp(this.client,a);listFieldNotes=(repo)=>listFieldNotesOp(this.client,repo);deleteFieldNote=(repo,id)=>deleteFieldNoteOp(this.client,repo,id);failingChecks=(taskId)=>failingChecksOp(this.client,taskId);syncBase=(taskId)=>syncBaseOp(this.client,taskId);startWorkItem=(a)=>startWorkItemOp(this.client,a);removeWorktree(path,force){return removeWorktreeOp(this.client,path,force)}setActiveTask(id){return setActiveTaskOp(this.client,id)}}
|
|
3
|
+
export{liveRowTokens,RemoteOrchestrator};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import{NPX_MISSING_EXIT,bundledSkillDir,installedSkillDiffersFromBundled,
|
|
2
|
+
import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import{NPX_MISSING_EXIT,bundledSkillDir,installedSkillDiffersFromBundled,npxSkillsCommand,roveSkillPaths,roveSkillState,runNpxSkillsInstall}from"./chunk-g4c4ffqp.js";import"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-wqfp8d9w.js";import{existsSync,readFileSync}from"fs";import{join}from"path";var CLI_NAME=ROVE_PRODUCT_NAME,SKILL_VERBS=SUBCOMMAND_VERBS.skill;function skillUsage(){return[`usage: ${CLI_NAME} skill <verb>`,"","verbs:"," install [--global|-g | --project|-p] [--agent NAME]\u2026 Install the Rove agent skill (wraps `npx skills add`)"," status Show whether the skill is installed"," command [--global|-g | --project|-p] [--agent NAME]\u2026 Print the underlying npx command without running it",` print Print the bundled SKILL.md (also: \`${CLI_NAME} --skill\`)`,"",`The skill teaches a coding agent how to drive \`${CLI_NAME} api\`. Installs are`,"global (user-level) by default; --global/-g says so explicitly, --project/-p","installs into the current project instead. With no --agent, the agent-skills","CLI detects your installed agents and asks; repeat --agent to name them","(e.g. --agent claude-code --agent codex)."].join(`
|
|
3
3
|
`)}function parseInstallFlags(rest){let global=!0,agents=[];for(let i=0;i<rest.length;i++){let arg=rest[i];if(arg==="--project"||arg==="-p")global=!1;else if(arg==="--global"||arg==="-g")global=!0;else if(arg==="--agent"){let v=rest[i+1];if(!v||v.startsWith("--"))process.stderr.write(`${CLI_NAME} skill: --agent requires a value
|
|
4
4
|
`),process.exit(2);agents.push(v),i++}else if(arg.startsWith("--agent="))agents.push(arg.slice(8));else process.stderr.write(`${CLI_NAME} skill: unknown flag "${arg}"
|
|
5
5
|
|
|
@@ -10,10 +10,10 @@ ${skillUsage()}
|
|
|
10
10
|
`),!verb)process.exitCode=2;return}if(!SKILL_VERBS.includes(verb))process.stderr.write(`${CLI_NAME} skill: unknown verb "${verb}"
|
|
11
11
|
|
|
12
12
|
${skillUsage()}
|
|
13
|
-
`),process.exit(2);if(verb==="print"){let bundled2=bundledSkillDir(),path=bundled2?join(bundled2,"SKILL.md"):
|
|
14
|
-
`),process.exit(1);process.stdout.write(readFileSync(path,"utf8"));return}if(verb==="status"){let{isRovePluginEnabled}=await import("./chunk-
|
|
13
|
+
`),process.exit(2);if(verb==="print"){let bundled2=bundledSkillDir(),path=bundled2?join(bundled2,"SKILL.md"):roveSkillPaths().find((p)=>existsSync(p));if(!path)process.stderr.write(`${CLI_NAME} skill: no SKILL.md found (not bundled, not installed) \u2014 run \`${CLI_NAME} skill install\`
|
|
14
|
+
`),process.exit(1);process.stdout.write(readFileSync(path,"utf8"));return}if(verb==="status"){let{isRovePluginEnabled}=await import("./chunk-c2m55b72.js"),state=roveSkillState(),paths=roveSkillPaths(),pluginNote=isRovePluginEnabled()?` note: the Rove Claude Code plugin is enabled \u2014 for Claude Code the skill ships
|
|
15
15
|
inside the plugin and versions with it (staleness prompts are suppressed).
|
|
16
|
-
`:"",head=!state.installed?"\u2717 not installed":state.stale?`\u26A0 out of date (installed ${state.installedVersion===null?"unstamped":`v${state.installedVersion}`}, this Rove wants v${state.currentVersion})`:`\u2713 installed (v${state.installedVersion})`,contentDrift=state.installed&&!state.stale&&!!state.path&&installedSkillDiffersFromBundled(state.path);process.stdout.write([`${CLI_NAME} skill: ${head}`,...contentDrift?[" \u26A0 content differs from the copy bundled with this Rove at the same version \u2014",` run \`${CLI_NAME} --skill > ${state.path}\` to refresh it`]:[]
|
|
16
|
+
`:"",head=!state.installed?"\u2717 not installed":state.stale?`\u26A0 out of date (installed ${state.installedVersion===null?"unstamped":`v${state.installedVersion}`}, this Rove wants v${state.currentVersion})`:`\u2713 installed (v${state.installedVersion})`,contentDrift=state.installed&&!state.stale&&!!state.path&&installedSkillDiffersFromBundled(state.path);process.stdout.write([`${CLI_NAME} skill: ${head}`,...contentDrift?[" \u26A0 content differs from the copy bundled with this Rove at the same version \u2014",` run \`${CLI_NAME} --skill > ${state.path}\` to refresh it`]:[],` looked in: ${paths.join(`
|
|
17
17
|
`)}`,state.installed&&!state.stale?"":` \u2192 run \`${CLI_NAME} skill install\` to install / refresh`,""].join(`
|
|
18
18
|
`)+pluginNote);return}if(verb==="command"){let flags=parseInstallFlags(rest);process.stdout.write(`${npxSkillsCommand({agent:flags.agents,global:flags.global})}
|
|
19
19
|
`);return}let{agents,global}=parseInstallFlags(rest),bundled=bundledSkillDir();process.stdout.write(`${CLI_NAME} skill: running \`${npxSkillsCommand({agent:agents,global})}\`
|
|
@@ -21,5 +21,5 @@ ${bundled?"":`${CLI_NAME} skill: no bundled skill found \u2014 falling back to a
|
|
|
21
21
|
`}`);let code=await runNpxSkillsInstall(agents,global);if(code!==0){if(code!==NPX_MISSING_EXIT)process.stderr.write(`
|
|
22
22
|
${CLI_NAME} skill install failed (npx exited ${code}).
|
|
23
23
|
You can run it yourself: ${npxSkillsCommand({agent:agents,global})}
|
|
24
|
-
`);process.exit(code||1)}process.stdout.write(`${CLI_NAME} skill: installed.
|
|
24
|
+
`);process.exit(code||1)}if(global){let{settleWelcomeInstall}=await import("./chunk-f1nf99hj.js");settleWelcomeInstall("skill")}process.stdout.write(`${CLI_NAME} skill: installed.
|
|
25
25
|
`)}export{runSkillSubcommand};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{submitFeedback}from"./chunk-
|
|
2
|
+
import{submitFeedback}from"./chunk-4tx2kayk.js";import"./chunk-a0ave3g6.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";import{readFileSync}from"fs";var CLI_NAME=ROVE_PRODUCT_NAME,FEEDBACK_USAGE=[`Usage: ${CLI_NAME} feedback --title <text> (--body <text> | --body-file <path>) [--category <slug>]`,"","Create a GitHub Discussion in the Rove repository using the GitHub CLI.","","Requires:"," gh auth login","","Options:"," --title <text> Discussion title"," --body <text> Discussion body"," --body-file <path> Read the Discussion body from a file; use - for stdin"," --category <slug> Discussion category slug (default: feedback)"," -h, --help Print this help",""].join(`
|
|
3
3
|
`);function usageError(message){process.stderr.write(`${CLI_NAME} feedback: ${message}
|
|
4
4
|
|
|
5
5
|
${FEEDBACK_USAGE}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{stopDaemonProcess}from"./chunk-9w5g7frx.js";import{spawnDetachedDaemon}from"./chunk-gvrtrvnz.js";import{isProcessAlive,readPidFile}from"./chunk-a7kq09ke.js";import{DAEMON_PROTOCOL_VERSION,RoveDaemonClient}from"./chunk-adkva3ep.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath}from"./chunk-npwzmmv9.js";import{ROVE_PRODUCT_NAME}from"./chunk-nc46gddg.js";import{closeSync,existsSync,mkdirSync,openSync,statSync,unlinkSync}from"fs";import{dirname,resolve}from"path";import{fileURLToPath}from"url";var DAEMON_START_ARGS=["daemon","start"],DAEMON_HELLO_TIMEOUT_MS=3000,BUSY_DAEMON_GRACE_MS=15000;function insideEngineSession(env=process.env){return typeof env.ROVE_TASK_ID==="string"&&env.ROVE_TASK_ID!==""}function autospawnDaemonEnv(env=process.env,reason="autospawn"){let{ROVE_TASK_ID:_task,ROVE_TAB_ID:_tab,ROVE_TUI:_tui,ROVE_TERMINAL_PTY:_pty,ROVE_TASK_ID:_roveTask,ROVE_TAB_ID:_roveTab,ROVE_TUI:_roveTui,ROVE_TERMINAL_PTY:_rovePty,...rest}=env;return{...rest,ROVE_DAEMON_AUTOSPAWNED:"1",ROVE_DAEMON_SPAWN_REASON:reason}}function daemonSpawnReason(env=process.env){let raw=env.ROVE_DAEMON_SPAWN_REASON;if(raw==="explicit-restart"||raw==="autospawn")return raw;return env.ROVE_DAEMON_AUTOSPAWNED==="1"?"autospawn":"manual"}var SPAWN_LOCK_STALE_MS=40000,SPAWN_LOCK_WAIT_MS=30000;function tryAcquireSpawnLock(lockPath,staleMs=SPAWN_LOCK_STALE_MS){let create=()=>{return mkdirSync(dirname(lockPath),{recursive:!0}),closeSync(openSync(lockPath,"wx")),!0};try{return create()}catch{try{if(Date.now()-statSync(lockPath).mtimeMs<=staleMs)return!1;return unlinkSync(lockPath),create()}catch{return!1}}}async function ensureDaemonReachable(resolveSpawn=resolveRoveSpawn,spawnReason="autospawn"){let socketPath=defaultDaemonSocketPath(),state=await probeDaemonSocket(socketPath);if(state==="alive")return socketPath;if(state==="wedged"&&insideEngineSession())throw Error(`rove: daemon at ${socketPath} is not answering hello (busy or wedged); not restarting it from inside an engine session \u2014 retry, or run \`rove daemon restart\` from a regular shell`);let lockPath=`${defaultDaemonPidPath()}.spawn-lock`;if(!tryAcquireSpawnLock(lockPath)){let deadline=Date.now()+SPAWN_LOCK_WAIT_MS;while(Date.now()<deadline){if(await testDaemonResponds(socketPath))return socketPath;await new Promise((resolveTimer)=>setTimeout(resolveTimer,150))}throw Error(`rove: another process is starting the daemon but it never became reachable at ${socketPath}; check ${defaultDaemonLogPath()} or run \`rove doctor\``)}try{if(await probeDaemonSocket(socketPath)==="alive")return socketPath;let livePid=await readPidFile(defaultDaemonPidPath());if(livePid!==null&&livePid!==process.pid&&isProcessAlive(livePid)){let deadline2=Date.now()+BUSY_DAEMON_GRACE_MS;while(Date.now()<deadline2){if(await new Promise((resolveTimer)=>setTimeout(resolveTimer,250)),await testDaemonResponds(socketPath))return socketPath;if(!isProcessAlive(livePid))break}}let[command,...args]=resolveSpawn(DAEMON_START_ARGS);await stopDaemonProcess(socketPath,defaultDaemonPidPath()).catch(()=>{}),spawnDetachedDaemon(command,args,autospawnDaemonEnv(process.env,spawnReason),defaultDaemonLogPath());let deadline=Date.now()+5000;while(Date.now()<deadline){if(await testDaemonResponds(socketPath))return socketPath;await new Promise((resolveTimer)=>setTimeout(resolveTimer,100))}throw Error(`rove: daemon did not start (or stayed wedged) at ${socketPath}; check ${defaultDaemonLogPath()} or run \`rove doctor\``)}finally{try{unlinkSync(lockPath)}catch{}}}async function connectOrStartDaemon(spawnReason="autospawn"){let socketPath=await ensureDaemonReachable(resolveRoveSpawn,spawnReason),client=new RoveDaemonClient(socketPath);return await client.connect(),client}async function connectIfRunning(){let socketPath=defaultDaemonSocketPath();if(!await testDaemonResponds(socketPath))return null;let client=new RoveDaemonClient(socketPath);return await client.connect(),client}async function probeDaemonSocket(socketPath,timeoutMs=DAEMON_HELLO_TIMEOUT_MS){let probe=new RoveDaemonClient(socketPath);try{await probe.connect()}catch{return probe.close(),"absent"}let droppedByPeer=!1,offClose=probe.onLifecycle("close",()=>{droppedByPeer=!0}),replied=probe.request("hello",{protocolVersion:DAEMON_PROTOCOL_VERSION}).then(()=>!0).catch(()=>!0),timer,timedOut=new Promise((resolve2)=>{timer=setTimeout(()=>resolve2(!1),timeoutMs)}),settled=await Promise.race([replied,timedOut]);if(timer)clearTimeout(timer);if(offClose(),probe.close(),droppedByPeer)return"absent";return settled?"alive":"wedged"}async function testDaemonResponds(socketPath,timeoutMs=DAEMON_HELLO_TIMEOUT_MS){return await probeDaemonSocket(socketPath,timeoutMs)==="alive"}class StaleInstallError extends Error{candidates;constructor(cliName,dir,candidates){super(`${cliName}: this process is running from an install that no longer exists on disk \u2014 no ${cliName} entry near ${dir} (checked ${candidates.join(", ")}). Reinstall (\`npm install -g @sma1lboy/rove\`) and relaunch Rove.`);this.name="StaleInstallError",this.candidates=candidates}}function isStaleInstallError(err){return err instanceof Error&&err.name==="StaleInstallError"}function resolveRoveSpawn(subcommand,env=process.env,moduleFile=fileURLToPath(import.meta.url)){let here=moduleFile;if(here.startsWith("/$bunfs")||here.startsWith("B:\\~BUN"))return[process.execPath,...subcommand];let dir=dirname(here),cliName=ROVE_PRODUCT_NAME,candidates=[resolve(dir,`../cli/${cliName}.ts`),resolve(dir,`../../../rove/src/cli/${cliName}.ts`),resolve(dir,`../cli/${cliName}.js`),resolve(dir,"../cli/index.ts"),resolve(dir,"../../../rove/src/cli/index.ts"),resolve(dir,"../cli/index.js")],entry=candidates.find((candidate)=>existsSync(candidate));if(entry)return[process.execPath,entry,...subcommand];throw new StaleInstallError(cliName,dir,candidates)}
|
|
3
|
+
export{autospawnDaemonEnv,daemonSpawnReason,tryAcquireSpawnLock,ensureDaemonReachable,connectOrStartDaemon,connectIfRunning,probeDaemonSocket,testDaemonResponds,StaleInstallError,isStaleInstallError,resolveRoveSpawn};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{loadStateFile,updateStateFile}from"./chunk-
|
|
2
|
+
import{loadStateFile,updateStateFile}from"./chunk-7q43tysm.js";import{homeDir}from"./chunk-prqeddy7.js";import{shortHomeTag}from"./chunk-npwzmmv9.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(argv.push("-o","ControlMaster=auto","-o",`ControlPath=${controlPath(alias,opts.home)}`,"-o",`ControlPersist=${CONTROL_PERSIST_SECONDS}`,"-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}
|
|
3
3
|
export{isValidMachineAlias,parseSshTarget,defaultMachineAlias,sanitizeAlias,sshTargetOf,readMachines,listMachines,getMachine,addMachine,updateMachine,setMachineIdentity,removeMachine,dedupeMachines,duplicateAliasOf,machineSocketDir,localDaemonSocketPath,localPtySocketPath,machineSshArgs};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{localDaemonSocketPath,localPtySocketPath,machineSocketDir,machineSshArgs}from"./chunk-
|
|
2
|
+
import{localDaemonSocketPath,localPtySocketPath,machineSocketDir,machineSshArgs}from"./chunk-9aydqazr.js";import{homeDir}from"./chunk-prqeddy7.js";import{spawn}from"child_process";import{mkdirSync,rmSync}from"fs";import{connect as netConnect}from"net";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:()=>{stopped=!0}};if(process.platform==="win32")return setState("unsupported"),handle;let schedule=opts.setTimeoutFn??((fn,ms)=>setTimeout(fn,ms)),ensure=opts.ensureFn??(()=>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){if(process.platform==="win32")return!1;let home=args.home??homeDir(),daemonLocal=localDaemonSocketPath(args.alias,home),ptyLocal=localPtySocketPath(args.alias,home);try{mkdirSync(machineSocketDir(args.alias,home),{recursive:!0,mode:DIR_MODE})}catch{}if(await socketAnswers(daemonLocal))return!0;for(let path of[daemonLocal,ptyLocal])try{rmSync(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=spawn(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
3
|
export{startTunnel,ensureForwards};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{isProcessAlive,readPidFile}from"./chunk-
|
|
2
|
+
import{isProcessAlive,readPidFile}from"./chunk-a7kq09ke.js";import{RoveDaemonClient}from"./chunk-adkva3ep.js";import{unlink}from"fs/promises";async function stopDaemonProcess(socketPath,pidPath,opts={}){let oldPid=await readPidFile(pidPath),targetPid=oldPid!==null&&oldPid!==process.pid?oldPid:null,wasAlive=targetPid!==null&&isProcessAlive(targetPid),method=wasAlive?"graceful":"absent",client=new RoveDaemonClient(socketPath),stopRequest=client.request("daemon.stop",{reason:opts.reason??"stop"}).catch(()=>{return}),stopTimeout=new Promise((resolve)=>setTimeout(resolve,2000));if(await Promise.race([stopRequest,stopTimeout]),client.close(),wasAlive&&targetPid!==null){let deadline=Date.now()+5000,escalated=!1;while(Date.now()<deadline){try{process.kill(targetPid,0)}catch{break}if(!escalated&&Date.now()-(deadline-5000)>2000){try{process.kill(targetPid,"SIGTERM")}catch{}method="sigterm",escalated=!0}await new Promise((resolve)=>setTimeout(resolve,50))}try{process.kill(targetPid,0),process.kill(targetPid,"SIGKILL"),method="sigkill",await new Promise((resolve)=>setTimeout(resolve,100))}catch{}}let survivor=await readPidFile(pidPath);if(survivor!==null&&survivor!==process.pid&&isProcessAlive(survivor))return{pid:oldPid,method};return await unlink(socketPath).catch(()=>{}),await unlink(pidPath).catch(()=>{}),{pid:oldPid,method}}
|
|
3
3
|
export{stopDaemonProcess};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{isDev}from"./chunk-prqeddy7.js";import{fileURLToPath}from"url";var package_default={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.240",description:"Rove \u2014 the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:mock":"ROVE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:rubric":"bun run scripts/build-tier-rubric.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"ROVE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"ROVE_INCLUDE_SOCKET=1 ROVE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"ROVE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun scripts/render-track.mjs",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.21.3"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/rove-daemon":"0.7.20","@tsconfig/bun":"1.0.11","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var CURRENT_VERSION=package_default.version,PACKAGE_NAME=package_default.name;function repoSlug(){let url=package_default.repository?.url;if(!url)return null;let m=url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);if(!m||!m[1]||!m[2])return null;return`${m[1]}/${m[2]}`}var UPDATE_SCRIPT_URL="https://raw.githubusercontent.com/Sma1lboy/rove/main/scripts/update.sh",UPDATE_COMMAND=`curl -fsSL ${UPDATE_SCRIPT_URL} | sh`;function owningNpmPrefix(modulePath=fileURLToPath(import.meta.url)){let at=modulePath.indexOf("/lib/node_modules/");if(at<=0)return null;return modulePath.slice(0,at)}function recommendedGlobalInstallCommand(prefix=owningNpmPrefix()){let target=`${PACKAGE_NAME}@latest`;return prefix===null?`npm install -g ${target}`:`npm install -g --prefix ${prefix} ${target}`}var BREAKING_VERSIONS=[];function breakingVersionsCrossed(from,to,breaking=BREAKING_VERSIONS){let[lo,hi]=compareSemver(from,to)<=0?[from,to]:[to,from];return breaking.filter((b)=>compareSemver(b,lo)>0&&compareSemver(b,hi)<=0)}var FETCH_TIMEOUT_MS=3000,RELEASE_CHANNELS=["latest","nightly"],DEFAULT_RELEASE_CHANNEL="latest";function channelOf(version=CURRENT_VERSION){return prereleaseOf(version)?.split(".")[0]==="nightly"?"nightly":DEFAULT_RELEASE_CHANNEL}async function fetchLatestFromRegistry(packageName,channel){let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let encoded=packageName.replace("/","%2F"),res=await fetch(`https://registry.npmjs.org/${encoded}/${channel}`,{signal:ctrl.signal,headers:{accept:"application/json"}});if(!res.ok)return null;let body=await res.json();if(typeof body.version!=="string")return null;return body.version}catch{return null}finally{clearTimeout(timer)}}function isNewerSemver(latest,current){let core=compareSemver(latest,current);if(core!==0)return core>0;return comparePrerelease(prereleaseOf(latest),prereleaseOf(current))>0}function prereleaseOf(version){let dash=version.indexOf("-");return dash===-1?void 0:version.slice(dash+1)||void 0}function comparePrerelease(a,b){if(a===b)return 0;if(a===void 0)return 1;if(b===void 0)return-1;let aParts=a.split("."),bParts=b.split(".");for(let i=0;i<Math.max(aParts.length,bParts.length);i++){let av=aParts[i],bv=bParts[i];if(av===void 0)return-1;if(bv===void 0)return 1;if(av===bv)continue;let an=/^\d+$/.test(av)?Number.parseInt(av,10):null,bn=/^\d+$/.test(bv)?Number.parseInt(bv,10):null;if(an!==null&&bn!==null)return an>bn?1:-1;if(an!==null)return-1;if(bn!==null)return 1;return av>bv?1:-1}return 0}function compareSemver(aVersion,bVersion){let norm=(v)=>v.split("-")[0]??v,a=norm(aVersion).split(".").map((s)=>Number.parseInt(s,10)),b=norm(bVersion).split(".").map((s)=>Number.parseInt(s,10));for(let i=0;i<3;i++){let av=a[i]??0,bv=b[i]??0;if(Number.isNaN(av)||Number.isNaN(bv))return 0;if(av>bv)return 1;if(av<bv)return-1}return 0}async function checkLatestVersion(opts={}){let channel=opts.channel??channelOf(),fake=process.env.ROVE_FAKE_UPDATE;if(fake)return{current:CURRENT_VERSION,latest:fake,hasUpdate:isNewerSemver(fake,CURRENT_VERSION),channel};if(isDev()&&!opts.force)return null;let latest=await fetchLatestFromRegistry(PACKAGE_NAME,channel);if(!latest)return null;return{current:CURRENT_VERSION,latest,hasUpdate:isNewerSemver(latest,CURRENT_VERSION),channel}}function versionFromTagName(tagName){if(typeof tagName!=="string")return null;return tagName.match(/^v(\d+\.\d+\.\d+)$/)?.[1]??null}async function fetchReleaseNotes(version){let slug=repoSlug();if(!slug)return null;let tag=`v${version}`,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases/tags/${tag}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return null;let body=await res.json();if(typeof body.body!=="string"||typeof body.html_url!=="string")return null;return{body:body.body,url:body.html_url,version}}catch{return null}finally{clearTimeout(timer)}}async function fetchReleaseNotesRange(args){let slug=repoSlug();if(!slug)return[];let limit=args.limit??100,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string"||typeof release.body!=="string")return null;if(compareSemver(version,args.current)<=0)return null;if(compareSemver(version,args.latest)>0)return null;return{version,url:release.html_url,body:release.body}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}async function fetchReleaseSummaries(limit=12){let slug=repoSlug();if(!slug)return[];let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string")return null;return{version,url:release.html_url}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}function releasePageUrl(version){let slug=repoSlug();if(!slug)return null;return`https://github.com/${slug}/releases/tag/v${version}`}
|
|
3
|
+
export{package_default,CURRENT_VERSION,PACKAGE_NAME,repoSlug,UPDATE_SCRIPT_URL,UPDATE_COMMAND,owningNpmPrefix,recommendedGlobalInstallCommand,BREAKING_VERSIONS,breakingVersionsCrossed,RELEASE_CHANNELS,DEFAULT_RELEASE_CHANNEL,channelOf,isNewerSemver,compareSemver,checkLatestVersion,fetchReleaseNotes,fetchReleaseNotesRange,fetchReleaseSummaries,releasePageUrl};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{tightenFilePermissions}from"./chunk-
|
|
2
|
+
import{tightenFilePermissions}from"./chunk-yt15y085.js";import{isWindowsPipePath}from"./chunk-npwzmmv9.js";import{readFile,stat,unlink}from"fs/promises";var DEFAULT_SOCKET_WATCH_MS=5000;async function listenOnUnixSocket(server,socketPath){if(await new Promise((resolve,reject)=>{let evented=server;evented.once("error",reject),server.listen(socketPath,()=>{evented.removeListener("error",reject),resolve()})}),!isWindowsPipePath(socketPath))await tightenFilePermissions(socketPath)}function isProcessAlive(pid){if(!Number.isInteger(pid)||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(err){return err.code!=="ESRCH"}}async function readPidFile(pidPath){try{let raw=await readFile(pidPath,"utf8"),pid=Number(raw.trim());return Number.isInteger(pid)&&pid>1?pid:null}catch{return null}}function createSocketOwnershipGuard(options){let watchMs=options.watchMs??DEFAULT_SOCKET_WATCH_MS,stamp=null,lost=!1,timer=null,currentStamp=async()=>{try{let s=await stat(options.socketPath);return{dev:s.dev,ino:s.ino}}catch(err){return err.code==="ENOENT"?null:"error"}},stopTimer=()=>{if(timer)clearInterval(timer);timer=null},verify=async()=>{if(stamp===null||lost)return;let now=await currentStamp();if(now==="error")return;if(now===null||now.dev!==stamp.dev||now.ino!==stamp.ino)lost=!0},check=async()=>{if(stamp===null||lost)return;if(await verify(),!lost)return;stopTimer(),options.onLost()};return{async arm(){let now=await currentStamp();if(now===null||now==="error")return;if(stamp=now,watchMs>0)timer=setInterval(()=>void check(),watchMs),timer.unref?.()},async release(server){if(stopTimer(),await verify(),stamp===null||lost){server.unref();return}await new Promise((resolve)=>server.close(()=>resolve())),await unlink(options.socketPath).catch(()=>{}),await unlink(options.pidPath).catch(()=>{})}}}
|
|
3
3
|
export{listenOnUnixSocket,isProcessAlive,readPidFile,createSocketOwnershipGuard};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{API_VERBS,VERBS,VERB_ALIASES,VERB_GROUPS,findVerb,unknownVerbError}from"./chunk-xckpezd9.js";import"./chunk-svm809bx.js";import"./chunk-h3fckxn3.js";import"./chunk-p024scd4.js";import"./chunk-hr2xky15.js";import"./chunk-4tx2kayk.js";import"./chunk-17e2tgyg.js";import"./chunk-cbc1h345.js";import"./chunk-qvfdqrbf.js";import"./chunk-4hestsjp.js";import"./chunk-2bgmby1d.js";import"./chunk-rqyaf0dw.js";import"./chunk-41x1hrqe.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import"./chunk-qkehg2c1.js";import"./chunk-zx2n95qe.js";import"./chunk-bn73kd6z.js";import"./chunk-yxt1y0n3.js";import"./chunk-cbjh43yc.js";import"./chunk-2apszxn2.js";import"./chunk-sak1tphp.js";import"./chunk-x9s14ppv.js";import"./chunk-rxqdw6s5.js";import"./chunk-4250pw6r.js";import"./chunk-nckmga7j.js";import"./chunk-vjvkkrzc.js";import"./chunk-pdvyfz3n.js";import"./chunk-dkgxz9hf.js";import"./chunk-hpay0ax8.js";import"./chunk-g5c5jytr.js";import"./chunk-y8tysjc2.js";import"./chunk-576r5nht.js";import"./chunk-w7zv47mp.js";import"./chunk-2tfnscxk.js";import"./chunk-etfh8f4z.js";import"./chunk-6xppe9bj.js";import"./chunk-f7zjggfv.js";import"./chunk-zsfyj36g.js";import"./chunk-96cjpssp.js";import"./chunk-9w5g7frx.js";import"./chunk-gvrtrvnz.js";import"./chunk-ag3txfg2.js";import"./chunk-2brn8e1y.js";import"./chunk-yexx8nec.js";import"./chunk-znjcesdr.js";import"./chunk-7kysxgbq.js";import"./chunk-qzsahxd9.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-tdhk4dz8.js";import"./chunk-a0ave3g6.js";import"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-snhcvjdb.js";import"./chunk-zt49bbg9.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.js";import"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{unknownVerbError,findVerb,VERB_GROUPS,VERB_ALIASES,VERBS,API_VERBS};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{DAEMON_CHANNELS}from"./chunk-0422g8ac.js";import{logClientError}from"./chunk-hq9tbzqa.js";import{samePath}from"./chunk-pn5ygqn6.js";import{preRenameRuntimePaths}from"./chunk-b39sdtt0.js";import{readRoveEnv}from"./chunk-nc46gddg.js";import{connect}from"net";import{StringDecoder}from"string_decoder";function automationRunNeedsAttention(status){return status==="dispatch_failed"||status==="skipped_unavailable"}var ROUTINE_RESPONSE_MAX_CHARS=32000,ROUTINE_RESPONSE_WINDOW_MS=7200000;function routineRunResponseState(run,nowMs){if(run.response)return"responded";if(run.status!=="dispatched"&&run.status!=="revived")return null;return nowMs-Date.parse(run.at)>ROUTINE_RESPONSE_WINDOW_MS?"missing":"awaiting"}var ATTENTION_INBOX_STATES=["turn_complete","permission_needed","error","rate_limited","dead","routine_failed","routine_responded"];function isRoutineInboxState(state){return state==="routine_failed"||state==="routine_responded"}function isAttentionInboxState(value){return typeof value==="string"&&ATTENTION_INBOX_STATES.includes(value)}function attentionInboxItemKey(item){if(isRoutineInboxState(item.state)&&item.detail?.routine)return`\x00${item.state}\x00${item.detail.routine.automationId}`;return`${item.taskId}\x00${item.tabId??""}`}var CHANNEL_NAMES=DAEMON_CHANNELS;var CHANNEL_NAME_SET=new Set(CHANNEL_NAMES);function isChannelName(value){return typeof value==="string"&&CHANNEL_NAME_SET.has(value)}function normalizeChannelFilter(value){if(!Array.isArray(value))return null;let set=new Set;for(let name of value)if(isChannelName(name))set.add(name);return set.size>0?set:null}var DAEMON_PROTOCOL_VERSION=5,MIN_COMPATIBLE_PROTOCOL_VERSION=2;function isProtocolCompatible(args){return args.remoteVersion>=args.localMin&&args.localVersion>=args.remoteMin}function isDaemonVersionStale(daemonVersion,clientVersion){if(!daemonVersion)return!1;return daemonVersion!==clientVersion}function isForeignDaemonHome(daemonHome,clientHome){if(!daemonHome)return!1;return!samePath(daemonHome,clientHome)}var BLOCKING_RPCS=new Set(["ui.prompt","task.land","workitem.start","automation.runNow","task.ensureWorktree","task.ensureMain","worktree.discoverAdoptable","worktree.adopt","worktree.list","worktree.remove"]);function parseDaemonStopReason(value){return value==="restart"||value==="stop"||value==="idle"||value==="socket-lost"?value:void 0}function displayTaskTitle(task){return task.title||task.branch||task.worktreePath||task.repo||"scratch"}function serializeTask(task){return{id:task.id,title:displayTaskTitle(task),repo:task.repo,branch:task.branch,worktreePath:task.worktreePath,kind:task.kind??"task",...task.scratch?{scratch:!0}:{},...task.routine?{routine:task.routine}:{},status:task.status,pinned:task.pinned??!1,vendor:task.vendor,command:task.command,prStatus:task.prStatus,modelEffort:task.modelEffort,model:task.model,tier:task.tier,groupId:task.groupId,observedLanguage:task.observedLanguage,deletion:task.deletion,quotaResume:task.quotaResume,linkedWorkItem:task.linkedWorkItem,dispatcher:task.dispatcher,prompt:task.prompt,baseRef:task.baseRef,worktreeName:task.worktreeName,report:task.report,createdAt:task.createdAt,updatedAt:task.updatedAt}}function frameToLine(frame){return`${JSON.stringify(frame)}
|
|
3
|
+
`}class RpcTimeoutError extends Error{constructor(name,timeoutMs){super(`daemon rpc "${name}" timed out after ${timeoutMs}ms (daemon wedged?)`);this.name="RpcTimeoutError"}}function rpcTimeoutMs(){let raw=readRoveEnv("RPC_TIMEOUT_MS")?.trim();if(raw){let parsed=Number.parseInt(raw,10);if(Number.isFinite(parsed))return parsed}return 20000}class ConnectTimeoutError extends Error{constructor(socketPath,timeoutMs){super(`connecting to ${socketPath} timed out after ${timeoutMs}ms \u2014 nothing accepted the connection (daemon or PTY host not listening at that address)`);this.name="ConnectTimeoutError"}}function connectTimeoutMs(){let raw=readRoveEnv("CONNECT_TIMEOUT_MS")?.trim();if(raw){let parsed=Number.parseInt(raw,10);if(Number.isFinite(parsed))return parsed}return 5000}class RoveDaemonClient{socketPath;socket=null;buffer="";nextId=1;pending=new Map;handlers=new Map;lifecycleHandlers=new Map;connecting=null;disposed=!1;constructor(socketPath){this.socketPath=socketPath}connect(){if(this.socket)return Promise.resolve();if(this.disposed)return Promise.reject(Error("daemon client disposed"));if(this.connecting)return this.connecting;let p=this.openSocketWithFallback();this.connecting=p;let cleanup=()=>{if(this.connecting===p)this.connecting=null};return p.then(cleanup,cleanup),p}get isDisposed(){return this.disposed}close(){this.disposed=!0,this.socket?.end(),this.socket=null,this.failPending()}forceDisconnect(){let socket=this.socket;if(!socket)return;this.socket=null,socket.destroy(),this.failPending()}failPending(){if(this.pending.size===0)return;let err=Error("daemon connection closed");for(let pending of this.pending.values()){if(pending.timer)clearTimeout(pending.timer);pending.reject(err)}this.pending.clear()}on(name,handler){let set=this.handlers.get(name);if(!set)set=new Set,this.handlers.set(name,set);return set.add(handler),()=>{if(set?.delete(handler),set?.size===0)this.handlers.delete(name)}}onChannel(channel,handler){return this.on(channel,(frame)=>handler(frame.payload))}subscribe(opts={}){let payload={};if(opts.channels)payload.channels=opts.channels;if(opts.role)payload.role=opts.role;if(opts.cellPixelSize)payload.cellPixelWidth=opts.cellPixelSize.width,payload.cellPixelHeight=opts.cellPixelSize.height;return this.request("subscribe",payload)}onLifecycle(name,handler){let set=this.lifecycleHandlers.get(name);if(!set)set=new Set,this.lifecycleHandlers.set(name,set);return set.add(handler),()=>{if(set?.delete(handler),set?.size===0)this.lifecycleHandlers.delete(name)}}async request(name,payload){await this.connect();let socket=this.socket;if(!socket)throw Error("daemon connection is not open");let id=String(this.nextId++),promise=new Promise((resolve,reject)=>{let entry={resolve:(value)=>resolve(value),reject},timeoutMs=rpcTimeoutMs();if(timeoutMs>0&&!BLOCKING_RPCS.has(name))entry.timer=setTimeout(()=>this.onRequestTimeout(id,name,timeoutMs),timeoutMs);this.pending.set(id,entry)});return socket.write(frameToLine({type:"request",id,name,payload})),promise}onRequestTimeout(id,name,timeoutMs){let pending=this.pending.get(id);if(!pending)return;this.pending.delete(id),pending.reject(new RpcTimeoutError(name,timeoutMs)),this.forceDisconnect(),this.emitLifecycle("close")}async openSocketWithFallback(){try{await this.openSocket(this.socketPath);return}catch(err){if(!(err instanceof Error)||!("code"in err)||!["ENOENT","ECONNREFUSED"].includes(String(err.code)))throw err;for(let path of preRenameRuntimePaths(this.socketPath)){if(this.disposed)throw err;try{await this.openSocket(path);return}catch{}}throw err}}openSocket(path){return new Promise((resolve,reject)=>{let socket=connect(path);this.socket=socket;let timeoutMs=connectTimeoutMs(),timer;if(timeoutMs>0)timer=setTimeout(()=>{if(socket.off("connect",onConnect),socket.off("error",onError),socket.destroy(),this.socket===socket)this.socket=null;reject(new ConnectTimeoutError(this.socketPath,timeoutMs))},timeoutMs);let onConnect=()=>{if(timer)clearTimeout(timer);socket.off("error",onError),socket.on("error",()=>socket.destroy()),resolve()},onError=(err)=>{if(timer)clearTimeout(timer);if(socket.off("connect",onConnect),this.socket===socket)this.socket=null;reject(err)};socket.once("connect",onConnect),socket.once("error",onError);let decoder=new StringDecoder("utf8");this.buffer="",socket.on("data",(chunk)=>this.onData(decoder.write(chunk))),socket.on("close",()=>this.onSocketClose(socket))})}onSocketClose(which){if(this.socket!==which)return;this.socket=null,this.failPending(),this.emitLifecycle("close")}emitLifecycle(name){for(let handler of this.lifecycleHandlers.get(name)??[])try{handler()}catch(err){console.error(`[rove] lifecycle handler for "${name}" threw:`,err)}}onData(chunk){this.buffer+=chunk;let nl=this.buffer.indexOf(`
|
|
4
|
+
`);while(nl!==-1){let line=this.buffer.slice(0,nl);if(this.buffer=this.buffer.slice(nl+1),line.trim().length>0)this.onLine(line);nl=this.buffer.indexOf(`
|
|
5
|
+
`)}}onLine(line){let frame;try{frame=JSON.parse(line)}catch(err){logClientError("client-frame",err);return}if(frame.type==="event"){this.emit(frame);return}if(frame.type!=="response")return;let pending=this.pending.get(frame.id);if(!pending)return;if(this.pending.delete(frame.id),pending.timer)clearTimeout(pending.timer);if(frame.error){let err=Error(frame.error.message);if(frame.error.name)err.name=frame.error.name;pending.reject(err)}else pending.resolve(frame.payload)}emit(frame){for(let handler of this.handlers.get(frame.name)??[])try{handler(frame)}catch(err){logClientError("client-event",err)}for(let handler of this.handlers.get("*")??[])try{handler(frame)}catch(err){logClientError("client-event",err)}}}
|
|
6
|
+
export{automationRunNeedsAttention,ROUTINE_RESPONSE_MAX_CHARS,routineRunResponseState,isRoutineInboxState,isAttentionInboxState,attentionInboxItemKey,CHANNEL_NAMES,normalizeChannelFilter,DAEMON_PROTOCOL_VERSION,MIN_COMPATIBLE_PROTOCOL_VERSION,isProtocolCompatible,isDaemonVersionStale,isForeignDaemonHome,parseDaemonStopReason,displayTaskTitle,serializeTask,frameToLine,RpcTimeoutError,ConnectTimeoutError,RoveDaemonClient};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{homeDir}from"./chunk-
|
|
2
|
+
import{homeDir}from"./chunk-prqeddy7.js";import{pathWithin}from"./chunk-pn5ygqn6.js";import{homedir as osHomedir}from"os";import{join}from"path";function tildify(path,home=osHomedir()){let suffix=pathWithin(home,path);return suffix===null?path:suffix?`~/${suffix}`:"~"}function expandTilde(path){if(path==="~")return homeDir();if(path.startsWith("~/")||process.platform==="win32"&&path.startsWith("~\\"))return join(homeDir(),path.slice(2));return path}
|
|
3
3
|
export{tildify,expandTilde};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{pluginsOutdatedCachePath}from"./chunk-
|
|
2
|
+
import{pluginsOutdatedCachePath}from"./chunk-rqyaf0dw.js";import{readFileSync,writeFileSync}from"fs";var OUTDATED_CACHE_TTL_MS=86400000;function writeOutdatedCache(outdatedIds,homeDir){let cache={checkedAt:Date.now(),outdated:outdatedIds};try{writeFileSync(pluginsOutdatedCachePath(homeDir),`${JSON.stringify(cache,null,2)}
|
|
3
3
|
`)}catch{}}function readOutdatedCache(homeDir){try{let cache=JSON.parse(readFileSync(pluginsOutdatedCachePath(homeDir),"utf8"));if(typeof cache.checkedAt!=="number"||!Array.isArray(cache.outdated))return[];if(Date.now()-cache.checkedAt>OUTDATED_CACHE_TTL_MS)return[];return cache.outdated.filter((id)=>typeof id==="string")}catch{return[]}}
|
|
4
4
|
export{writeOutdatedCache,readOutdatedCache};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{pluginConfigDir,pluginStateDir}from"./chunk-rqyaf0dw.js";function buildPluginEnv(opts){let configDir=pluginConfigDir(opts.pluginId,opts.homeDir),stateDir=pluginStateDir(opts.pluginId,opts.homeDir),extra=withPluginEnvAliases(opts.extra??{});return{...process.env,...opts.homeDir?{ROVE_HOME_DIR:opts.homeDir}:{},ROVE_SOCKET_PATH:opts.socketPath,ROVE_BIN_PATH:opts.binPath,ROVE_PLUGIN_ID:opts.pluginId,ROVE_PLUGIN_ROOT:opts.pluginRoot,ROVE_PLUGIN_CONFIG_DIR:configDir,ROVE_PLUGIN_STATE_DIR:stateDir,...extra}}function withPluginEnvAliases(values){let aliases={};for(let[key,value]of Object.entries(values))if(key.startsWith("ROVE_"))aliases[`ROVE_${key.slice(5)}`]=value;else if(key.startsWith("ROVE_"))aliases[`ROVE_${key.slice(5)}`]=value;return{...aliases,...values}}
|
|
3
|
+
export{buildPluginEnv};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import{constants,accessSync,statSync}from"fs";import{isAbsolute}from"path";function isRunnableFile(path){try{if(!statSync(path).isFile())return!1;return accessSync(path,constants.X_OK),!0}catch{return!1}}function resolvePluginBinPath(argv=process.argv,moduleUrl=import.meta.url){if(moduleUrl.includes("/$bunfs/")||moduleUrl.includes("B:\\~BUN"))return process.execPath;let entry=argv[1];if(entry&&isAbsolute(entry)&&isRunnableFile(entry))return entry;return ROVE_PRODUCT_NAME}
|
|
3
|
+
export{resolvePluginBinPath};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{basename,dirname,join}from"path";var LEGACY_PRE_RENAME_RUNTIME_NAME="kobe";function preRenameStateDir(home){return join(home,`.${LEGACY_PRE_RENAME_RUNTIME_NAME}`)}function preRenameConfigDir(home){return join(home,".config",LEGACY_PRE_RENAME_RUNTIME_NAME)}function preRenameRuntimePaths(canonical){let name=basename(canonical);if(canonical.startsWith("\\\\.\\pipe\\rove-")&&canonical.endsWith("-pty"))return[canonical.replace("\\pipe\\rove-",`\\pipe\\${LEGACY_PRE_RENAME_RUNTIME_NAME}-`)];if(/^rove(?:-[a-f0-9]{8})?-(?:pty|daemon)(?:-\d+)?\.sock$/.test(name)||name==="rove.sock")return[join(dirname(canonical),name.replace(/^rove/,LEGACY_PRE_RENAME_RUNTIME_NAME))];if(["pty.sock","pty.pid","daemon.sock","daemon.pid"].includes(name)&&basename(dirname(canonical))===".rove")return[join(preRenameStateDir(dirname(dirname(canonical))),name)];return[]}
|
|
3
|
+
export{preRenameStateDir,preRenameConfigDir,preRenameRuntimePaths};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{stopLegacyTmux}from"./chunk-
|
|
2
|
+
import{stopLegacyTmux}from"./chunk-gkdfct7t.js";import{clearFrozenSessions}from"./chunk-0y4qgnby.js";import"./chunk-4250pw6r.js";import{stopDaemonProcess}from"./chunk-9w5g7frx.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{stampResetGate}from"./chunk-801h8bze.js";import"./chunk-a0ave3g6.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import{kvStatePath,legacyRoveKvStatePath,legacyRoveStateDir,roveStateDir}from"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import{defaultDaemonPidPath,defaultDaemonSocketPath,defaultPtyFreezeDir,defaultPtyHostPidPath,defaultPtyHostSocketPath}from"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";import{readFileSync}from"fs";import{unlink}from"fs/promises";import{join}from"path";import{createInterface}from"readline";var CLI_NAME=ROVE_PRODUCT_NAME;function printUsage(out){out.write([`Usage: ${CLI_NAME} reset [--hard] [--yes]`,"","Recover a wedged install: stop the daemon, Hosted PTY host, and any pre-v0.8 tmux sessions.","This ends background terminal and engine sessions; the next launch starts fresh.","Never touches your git worktrees.","","Options:"," --hard Also DELETE the task index and the whole settings file"," (saved projects, custom engines, theme, language, onboarding)"," -y, --yes Skip the interactive confirmation. REQUIRED without a terminal;"," a non-interactive run without it exits 2 and changes nothing."," -h, --help Print this help",""].join(`
|
|
3
3
|
`))}function taskCount(path){try{let parsed=JSON.parse(readFileSync(path,"utf8"));return Array.isArray(parsed.tasks)?parsed.tasks.length:null}catch{return null}}function stateSummary(path){let parsed;try{parsed=JSON.parse(readFileSync(path,"utf8"))}catch{return[]}let count=(key)=>Array.isArray(parsed[key])?parsed[key].length:0,lines=[` saved projects: ${count("savedRepos")}`,` custom engines: ${count("customEngineIds")} (their launch commands live here and nowhere else)`],present=[["activeTheme","theme"],["defaultVendor","default engine"],["locale","language"],["onboarded","onboarding (the wizard runs again)"]].filter(([key])=>parsed[key]!==void 0).map(([,label])=>label);if(present.length>0)lines.push(` also set: ${present.join(", ")}`);return lines.push(` ${Object.keys(parsed).length} setting(s) in total`),lines}async function confirmTty(prompt){let readline=createInterface({input:process.stdin,output:process.stdout});try{let answer=await new Promise((resolve)=>readline.question(prompt,resolve));return/^y(es)?$/i.test(answer.trim())}finally{readline.close()}}async function removeStateFile(path,label){try{await unlink(path),console.log(` removed ${label} (${path})`)}catch(err){if(err.code==="ENOENT")console.log(` ${label}: already absent`);else throw Error(`failed to remove ${label} (${path}): ${errorMessage(err)}`)}}async function runResetSubcommand(argv){if(argv.some((arg)=>arg==="--help"||arg==="-h"||arg==="help")){printUsage(process.stdout);return}let known=new Set(["--hard","--yes","-y"]),unknown=argv.find((arg)=>!known.has(arg));if(unknown!==void 0)process.stderr.write(`${CLI_NAME} reset: unknown argument "${unknown}"
|
|
4
4
|
|
|
5
|
-
`),printUsage(process.stderr),process.exit(2);let hard=argv.includes("--hard"),yes=argv.includes("--yes")||argv.includes("-y"),daemonSocket=defaultDaemonSocketPath(),tasksPath=join(roveStateDir(),"tasks.json"),legacyTasksPath=join(
|
|
5
|
+
`),printUsage(process.stderr),process.exit(2);let hard=argv.includes("--hard"),yes=argv.includes("--yes")||argv.includes("-y"),daemonSocket=defaultDaemonSocketPath(),tasksPath=join(roveStateDir(),"tasks.json"),legacyTasksPath=join(legacyRoveStateDir(),"tasks.json"),statePath=kvStatePath(),legacyStatePath=legacyRoveKvStatePath();if(console.log(`${CLI_NAME} reset will:`),console.log(" \u2022 stop the Rove daemon (graceful \u2192 SIGTERM \u2192 SIGKILL)"),console.log(` \u2022 remove its socket + pidfile (${daemonSocket})`),console.log(" \u2022 stop the standalone Hosted PTY host and all background terminal/engine sessions"),console.log(" \u2022 stop any pre-v0.8 tmux sessions after SIGTERM-ing their pane process groups"),hard){let count=taskCount(tasksPath)??taskCount(legacyTasksPath);console.log(` \u2022 DELETE the task index${count===null?"":` (${count} task(s))`} \u2014 ${tasksPath}`),console.log(` \u2022 DELETE the whole settings file \u2014 ${statePath}`);for(let line of stateSummary(statePath))console.log(line);console.log(" \u2022 DELETE the pre-Rove task/UI indexes too, so migration cannot restore reset state")}if(console.log(" \u2022 NOT touch your git worktrees under ~/.rove/worktrees/ or existing repo-local roots"),!hard)console.log(" (your task list, settings & worktrees are kept \u2014 add --hard to also delete the task index and settings file)");if(!yes){if(!process.stdin.isTTY){console.log(`
|
|
6
6
|
re-run with --yes to proceed (no interactive terminal for a y/N prompt) \u2014 nothing was changed`),process.exitCode=2;return}if(!await confirmTty(hard?`
|
|
7
7
|
Stop runtimes and DELETE the task index + settings file? [y/N] `:`
|
|
8
8
|
Stop runtimes? [y/N] `)){console.log("aborted \u2014 nothing changed");return}}console.log("");let daemon=await stopDaemonProcess(daemonSocket,defaultDaemonPidPath());console.log(daemon.method==="absent"?" daemon: was not running (cleared any stale socket/pidfile)":` daemon: stopped via ${daemon.method}${daemon.pid?` (pid ${daemon.pid})`:""}`);let ptyHost=await stopDaemonProcess(defaultPtyHostSocketPath(),defaultPtyHostPidPath());if(console.log(ptyHost.method==="absent"?" pty host: was not running (cleared any stale socket/pidfile)":` pty host: stopped via ${ptyHost.method}${ptyHost.pid?` (pid ${ptyHost.pid})`:""}`),ptyHost.method!=="graceful")clearFrozenSessions(defaultPtyFreezeDir()),console.log(` frozen sessions: cleared (${ptyHost.method} stop skips the host's own wipe)`);let legacyTmux=await stopLegacyTmux();if(legacyTmux.status==="failed"){console.error(` legacy tmux: cleanup failed \u2014 ${legacyTmux.error??"unknown error"}`),process.exitCode=1;return}if(console.log(legacyTmux.status==="absent"?" legacy tmux: no pre-v0.8 sessions found":` legacy tmux: stopped ${legacyTmux.sessions} session(s) after signalling ${legacyTmux.signalledGroups} pane group(s)`),hard)await removeStateFile(tasksPath,"task index"),await removeStateFile(legacyTasksPath,"legacy task index"),await removeStateFile(statePath,"UI state"),await removeStateFile(legacyStatePath,"legacy UI state");else stampResetGate();console.log(`
|