@sma1lboy/rove 0.9.238 → 0.9.239
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-77w83wgh.js → chunk-0k91029d.js} +1 -1
- package/dist/cli/chunk-0mj358p5.js +3 -0
- package/dist/cli/chunk-0n7w8t48.js +2 -0
- package/dist/cli/{chunk-grt1e2s8.js → chunk-0wrh5s5y.js} +2 -2
- package/dist/cli/{chunk-nntg9d85.js → chunk-0y4qgnby.js} +1 -1
- package/dist/cli/chunk-1brfxbvg.js +4 -0
- package/dist/cli/{chunk-bhqracn8.js → chunk-20qm75rb.js} +1 -1
- 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-hk8mc43r.js → chunk-2s2xy444.js} +5 -5
- 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-mkksdcsw.js → chunk-3342qzve.js} +1 -1
- 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-41x1hrqe.js +3 -0
- package/dist/cli/{chunk-mhg40es1.js → chunk-4hestsjp.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-acw32w13.js → chunk-5akk3wap.js} +6 -5
- package/dist/cli/chunk-7cce0st1.js +3 -0
- package/dist/cli/{chunk-zyd6k6ak.js → chunk-7q43tysm.js} +1 -1
- package/dist/cli/chunk-8bn6eg67.js +8 -0
- package/dist/cli/chunk-8rf7nzan.js +4 -0
- 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-vnpqemb0.js → chunk-a7kq09ke.js} +1 -1
- package/dist/cli/chunk-acxznk3y.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-2yd128k1.js → chunk-b9q8c2qg.js} +6 -6
- package/dist/cli/{chunk-g56km26e.js → chunk-bn73kd6z.js} +1 -1
- package/dist/cli/chunk-c2m55b72.js +4 -0
- package/dist/cli/{chunk-b503z32q.js → chunk-c60qsnfw.js} +3 -3
- 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-pzbrj3gd.js → chunk-cmcn8e8x.js} +1 -1
- package/dist/cli/{chunk-cv1kaq8a.js → chunk-cp89n425.js} +5 -5
- 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-gqphk56d.js → chunk-ekg3h5z3.js} +7 -7
- 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-fft50thp.js +3 -0
- 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-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-1bm6sryf.js → chunk-ga1pb0mr.js} +1 -1
- package/dist/cli/{chunk-dqndd97s.js → chunk-gkdfct7t.js} +2 -2
- package/dist/cli/chunk-gqydm0q8.js +2 -0
- 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-mb1e73jm.js → chunk-hen7jj2h.js} +2 -2
- 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-s0snbj93.js → chunk-kb6xw0fw.js} +1 -1
- package/dist/cli/{chunk-8h0khkap.js → chunk-ker4971f.js} +2 -2
- package/dist/cli/{chunk-vyb5a2rh.js → chunk-kg9kmwt9.js} +1 -1
- package/dist/cli/chunk-ktzbg4jg.js +2 -0
- package/dist/cli/chunk-m4f5h05c.js +10 -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-p6qr8sen.js +2 -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-z5fnv7nk.js → chunk-pqzbk1cz.js} +25 -23
- package/dist/cli/chunk-prqeddy7.js +3 -0
- package/dist/cli/chunk-pvm3fc44.js +2 -0
- package/dist/cli/chunk-qd5zgq91.js +10 -0
- package/dist/cli/chunk-qvfdqrbf.js +3 -0
- package/dist/cli/{chunk-2xsem13q.js → chunk-qzsahxd9.js} +1 -1
- package/dist/cli/{chunk-0wgheepg.js → chunk-rahv4nrm.js} +3 -3
- 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-ss8c3b25.js +3 -0
- package/dist/cli/{chunk-bav389wj.js → chunk-svm809bx.js} +1 -1
- 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-try1f2h3.js +3 -0
- package/dist/cli/{chunk-aj7fkrha.js → chunk-tsj1054w.js} +1 -1
- 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-wfhnbnbw.js +2 -0
- package/dist/cli/{chunk-0wh2ff77.js → chunk-whbm14qr.js} +2 -2
- package/dist/cli/{chunk-ww4fbx8h.js → chunk-wtb8cycx.js} +2 -2
- package/dist/cli/chunk-wvmjdnhk.js +2 -0
- package/dist/cli/chunk-x9s14ppv.js +4 -0
- 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/{chunk-zwgns5ce.js → chunk-zxsbz3kk.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,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{ROVE_STATE_DIR_BASENAME as ROVE_STATE_DIR_BASENAME2}from"./chunk-zt7wfnva.js";import{preRenameConfigDir,preRenameStateDir}from"./chunk-b39sdtt0.js";import{ROVE_CONFIG_DIR_BASENAME,ROVE_STATE_DIR_BASENAME,readRoveEnv,readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import{createHash}from"crypto";import{join as join2}from"path";import{homedir}from"os";import{join}from"path";function resolveProductHomeDir(){return readRoveHomeDirEnv()??homedir()}function defaultUiPrefsStatePath(homeDir=resolveProductHomeDir()){return join(homeDir,".config",ROVE_CONFIG_DIR_BASENAME,"state.json")}function defaultKeybindingsPath(homeDir=resolveProductHomeDir()){return join(homeDir,ROVE_STATE_DIR_BASENAME,"settings","keybindings.yaml")}function isDev(){return readRoveEnv("DEV")==="1"}function homeDir(){return resolveProductHomeDir()}function roveStateDir(){return join2(homeDir(),ROVE_STATE_DIR_BASENAME2)}function legacyRoveStateDir(){return preRenameStateDir(homeDir())}function kvStatePath(){return defaultUiPrefsStatePath(homeDir())}function legacyRoveKvStatePath(){return join2(preRenameConfigDir(homeDir()),"state.json")}function secretsPath(){return join2(roveStateDir(),"secrets.json")}function keybindingsConfigPath(){return defaultKeybindingsPath(homeDir())}function promptAttachmentsDir(){return join2(roveStateDir(),"attachments")}function remoteControlSocketPath(host,user,port){let hash=createHash("sha1").update(`${user}@${host}:${port??22}`).digest("hex").slice(0,16);return join2(roveStateDir(),"ssh",`${hash}.sock`)}function worktreeInitMarkerPath(worktreePath){let hash=createHash("sha1").update(worktreePath).digest("hex").slice(0,16);return join2(roveStateDir(),"worktree-init",hash)}
|
|
3
|
+
export{resolveProductHomeDir,defaultUiPrefsStatePath,defaultKeybindingsPath,isDev,homeDir,roveStateDir,legacyRoveStateDir,kvStatePath,legacyRoveKvStatePath,secretsPath,keybindingsConfigPath,promptAttachmentsDir,remoteControlSocketPath,worktreeInitMarkerPath};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{defaultClientLogPath,defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath,defaultDeliveryLockDir,defaultPtyExitsPath,defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,defaultWebTokenPath,fitSocketPath,isWindowsPipePath,resolveDaemonHomeDir,shortHomeTag,windowsPipePath}from"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{windowsPipePath,shortHomeTag,resolveDaemonHomeDir,isWindowsPipePath,fitSocketPath,defaultWebTokenPath,defaultPtyHostSocketPath,defaultPtyHostPidPath,defaultPtyHostLogPath,defaultPtyFreezeDir,defaultPtyExitsPath,defaultDeliveryLockDir,defaultDaemonSocketPath,defaultDaemonPidPath,defaultDaemonLogPath,defaultClientLogPath};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{LAST_RUN_VERSION_KEY}from"./chunk-8rf7nzan.js";import{isShellKind,shippedCompletionsPath}from"./chunk-yybpg7fh.js";import{isNpxMissing,markSkillHintSeen,npxSkillsArgv,npxSkillsCommand}from"./chunk-g4c4ffqp.js";import{loadStateFile,patchStateFile}from"./chunk-7q43tysm.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import{t}from"./chunk-snhcvjdb.js";import{spawnSync}from"child_process";import{appendFileSync,existsSync,mkdirSync,readFileSync,writeFileSync}from"fs";import{homedir}from"os";import{basename,join}from"path";var WELCOMED_KEY="welcomed",PENDING_SKILL_KEY="welcomePendingSkillInstall";function shouldWelcome(state){if(state[WELCOMED_KEY]===!0)return!1;return typeof state[LAST_RUN_VERSION_KEY]!=="string"}function takeWelcome(){if(!shouldWelcome(loadStateFile()))return null;try{patchStateFile({[WELCOMED_KEY]:!0})}catch{}return{shell:detectShell()}}var PENDING_COMPLETIONS_KEY="welcomePendingCompletions";function detectShell(env=process.env){let shell=basename(env.SHELL??"");return shell==="zsh"||shell==="bash"||shell==="fish"?shell:null}function completionHook(shell,cli,shipped){if(shipped===null)return legacyCompletionHook(shell,cli);return shell==="fish"?`test -f "${shipped}"; and source "${shipped}"`:`[ -f "${shipped}" ] && source "${shipped}"`}function legacyCompletionHook(shell,cli){return shell==="fish"?`${cli} completions fish | source`:`command -v ${cli} >/dev/null && source <(${cli} completions ${shell})`}function shippedScriptFor(shell,cli){let path=shippedCompletionsPath(shell,cli);return existsSync(path)?path:null}function installCompletions(shell,home=homedir(),cli=ROVE_PRODUCT_NAME,shipped=shippedScriptFor(shell,cli)){let hook=completionHook(shell,cli,shipped);if(shell==="fish"){let dir=join(home,".config","fish","completions"),path=join(dir,`${cli}.fish`);return mkdirSync(dir,{recursive:!0}),writeFileSync(path,`${hook}
|
|
3
|
+
`),{path,installed:!0}}let rc=join(home,shell==="zsh"?".zshrc":".bashrc"),existing=existsSync(rc)?readFileSync(rc,"utf8"):"";if(existing.includes(hook))return{path:rc,installed:!1};let legacy=legacyCompletionHook(shell,cli);if(existing.includes(legacy))return writeFileSync(rc,existing.replace(legacy,hook)),{path:rc,installed:!0};if(existing.includes(`${cli} completions`))return{path:rc,installed:!1};return appendFileSync(rc,`
|
|
4
|
+
# ${cli} completions
|
|
5
|
+
${hook}
|
|
6
|
+
`),{path:rc,installed:!0}}function recordWelcomeChoices(choices,shell){if(!choices.skill)markSkillHintSeen();try{patchStateFile({[PENDING_COMPLETIONS_KEY]:choices.completions&&shell!==null?shell:void 0,[PENDING_SKILL_KEY]:choices.skill?!0:void 0,"welcomeInstall.completions":choices.completions?{status:"queued"}:void 0,"welcomeInstall.skill":choices.skill?{status:"queued"}:void 0})}catch{}}function runPendingWelcomeInstalls(){let state=loadStateFile(),shell=state[PENDING_COMPLETIONS_KEY],wantsSkill=state[PENDING_SKILL_KEY]===!0,pendingShell=typeof shell==="string"&&isShellKind(shell)?shell:null;if(shell!==void 0&&pendingShell===null){process.stdout.write(`! Ignoring invalid pending completion shell; run rove completions --help to choose a supported shell.
|
|
7
|
+
`);try{patchStateFile({[PENDING_COMPLETIONS_KEY]:void 0,"welcomeInstall.completions":{status:"failed",reason:"Unsupported shell"}})}catch{}}if(pendingShell===null&&!wantsSkill)return;let cli=ROVE_PRODUCT_NAME,out=(line)=>process.stdout.write(`${line}
|
|
8
|
+
`),save=(patch)=>{try{patchStateFile(patch)}catch{out("! Could not save setup results; check permissions before retrying.")}},failed=(item,reason,command)=>{save({[`welcomeInstall.${item}`]:{status:"failed",reason}}),out(t("onboarding.installFailed",{item,reason,command}))};if(pendingShell!==null)try{let completion=installCompletions(pendingShell);save({[PENDING_COMPLETIONS_KEY]:void 0,"welcomeInstall.completions":{status:"succeeded"}}),out(t(completion.installed?"onboarding.appliedCompletions":"onboarding.keptCompletions",{path:completion.path}))}catch(error){failed("completions",error instanceof Error?error.message:String(error),`${cli} completions ${pendingShell} --install`)}if(wantsSkill){let command=`${cli} skill install`;if(isNpxMissing())failed("skill","npx is missing (install Node.js from https://nodejs.org)",command);else{out(t("onboarding.installingSkill",{command:npxSkillsCommand()}));try{let result=spawnSync("npx",npxSkillsArgv(),{stdio:"inherit"});if(result.status!==0)failed("skill",result.error?.message??(result.signal?`signal ${result.signal}`:`exit ${result.status}`),command);else save({[PENDING_SKILL_KEY]:void 0,"welcomeInstall.skill":{status:"succeeded"}}),out(t("onboarding.skillSucceeded"))}catch(error){failed("skill",error instanceof Error?error.message:String(error),command)}}}}function settleWelcomeInstall(item,shell){let state=loadStateFile(),key=item==="skill"?PENDING_SKILL_KEY:PENDING_COMPLETIONS_KEY;if(item==="skill"?state[key]!==!0:state[key]!==shell)return;try{patchStateFile({[key]:void 0,[`welcomeInstall.${item}`]:{status:"succeeded"}})}catch{process.stderr.write(`! Setup succeeded, but its queued state could not be saved. Check settings permissions.
|
|
9
|
+
`)}}
|
|
10
|
+
export{takeWelcome,detectShell,installCompletions,recordWelcomeChoices,runPendingWelcomeInstalls,settleWelcomeInstall};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{PROJECT_DIR_TOKEN,WORKTREE_BASE_KEY,defaultLocalWorktreesRoot,legacyLocalWorktreesRoot,managedWorktreeRootsFor,normalizeWorktreeBase,worktreeRootFor}from"./chunk-41x1hrqe.js";import{execHostForRepo}from"./chunk-cbjh43yc.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{getRemoteRepoConfig,isRemoteRepoKey}from"./chunk-h9cg0j3a.js";import{loadStateFile}from"./chunk-7q43tysm.js";import{pathWithin}from"./chunk-pn5ygqn6.js";class IllegalTransitionError extends Error{from;to;taskId;constructor(from,to,taskId){super(`illegal transition for task ${taskId}: ${from} -> ${to}`);this.from=from;this.to=to;this.taskId=taskId;this.name="IllegalTransitionError"}}class TaskNotFoundError extends Error{constructor(taskId){super(`task not found: ${taskId}`);this.name="TaskNotFoundError"}}class CannotDeleteMainTaskError extends Error{constructor(){super("cannot delete a main task; remove the repo from saved repos instead");this.name="CannotDeleteMainTaskError"}}var DIRTY_WORKTREE_CODE="DIRTY_WORKTREE";function describeDirtyWorktreeWork(ignored,dirty=[]){if(dirty.length>0)return`uncommitted or untracked changes: ${namePaths(dirty)}`;return ignored==="unknown"?"gitignored work this check could not read (git status --ignored failed) \u2014 nothing here can confirm it is empty":ignored.length>0?`gitignored work git status cannot see: ${ignored.join(", ")}`:"uncommitted or untracked changes"}var DIRTY_PATHS_SHOWN=10;function namePaths(paths){let shown=paths.slice(0,DIRTY_PATHS_SHOWN).join(", "),more=paths.length-DIRTY_PATHS_SHOWN;return more>0?`${shown} (+${more} more)`:shown}function dirtyRefusalReason(err){let message=errorMessage(err),at=message.indexOf(DIRTY_WORKTREE_CODE);if(at<0)return null;return message.slice(at+DIRTY_WORKTREE_CODE.length).replace(/^:\s*/,"")}class DirtyWorktreeError extends Error{taskId;ignored;dirty;constructor(taskId,ignored=[],dirty=[]){super(`${DIRTY_WORKTREE_CODE}: task ${taskId} worktree has ${describeDirtyWorktreeWork(ignored,dirty)}`);this.taskId=taskId;this.ignored=ignored;this.dirty=dirty;this.name="DirtyWorktreeError"}}class WorktreeRemoveFailedError extends Error{taskId;cause;constructor(taskId,cause){super(`failed to remove worktree for task ${taskId}: ${errorMessage(cause)}`);this.taskId=taskId;this.cause=cause;this.name="WorktreeRemoveFailedError"}}var TASK_DELETING_CODE="TASK_DELETING";class TaskDeletingError extends Error{taskId;constructor(taskId){super(`${TASK_DELETING_CODE}: task ${taskId} is being deleted`);this.taskId=taskId;this.name="TaskDeletingError"}}var MAIN_CHECKOUT_DIRTY_CODE="MAIN_CHECKOUT_DIRTY";class MainCheckoutDirtyError extends Error{repo;dir;constructor(repo,dir){super(`${MAIN_CHECKOUT_DIRTY_CODE}: base checkout at ${dir} has uncommitted changes; commit them before landing (never git stash \u2014 the stash stack is shared by every worktree of this repo)`);this.repo=repo;this.dir=dir;this.name="MainCheckoutDirtyError"}}var EMPTY_BRANCH_CODE="EMPTY_BRANCH";class EmptyBranchError extends Error{branch;landedOn;constructor(branch,landedOn){super(`${EMPTY_BRANCH_CODE}: '${branch}' has no commits ahead of '${landedOn}' \u2014 landing it would be a no-op (the worker may not have delivered anything)`);this.branch=branch;this.landedOn=landedOn;this.name="EmptyBranchError"}}var EMPTY_BRANCH_DIRTY_WORKTREE_CODE="EMPTY_BRANCH_DIRTY_WORKTREE";class EmptyBranchDirtyWorktreeError extends Error{branch;landedOn;worktreePath;files;constructor(branch,landedOn,worktreePath,files){let list=files.length>0?files.join(", "):"(none reported)";super(`${EMPTY_BRANCH_DIRTY_WORKTREE_CODE}: '${branch}' has no commits ahead of '${landedOn}' but its worktree ${worktreePath} has uncommitted changes (${list}) \u2014 commit them in the worktree first, then land again`);this.branch=branch;this.landedOn=landedOn;this.worktreePath=worktreePath;this.files=files;this.name="EmptyBranchDirtyWorktreeError"}}var MISSING_REF_CODE="MISSING_REF";class MissingRefError extends Error{branch;landedOn;dir;constructor(branch,landedOn,dir){super(`${MISSING_REF_CODE}: '${branch}' does not resolve in the base repo at ${dir} (comparing against '${landedOn}') \u2014 the branch was renamed or deleted outside Rove; re-point the task with \`rove api set-branch\` or recreate the branch`);this.branch=branch;this.landedOn=landedOn;this.dir=dir;this.name="MissingRefError"}}var LAND_CONFLICT_CODE="LAND_CONFLICT";class LandConflictError extends Error{taskId;branch;files;constructor(taskId,branch,files){let list=files.length>0?files.join(", "):"(none reported)";super(`${LAND_CONFLICT_CODE}: merging '${branch}' hit conflicts, merge aborted \u2014 conflicted files: ${list}`);this.taskId=taskId;this.branch=branch;this.files=files;this.name="LandConflictError"}}var GIT_COMMAND_FAILED_CODE="GIT_COMMAND_FAILED";class GitCommandFailedError extends Error{command;stderr;constructor(command,stderr,hint){let detail=stderr.trim()||"(git printed nothing on stderr)";super(`${GIT_COMMAND_FAILED_CODE}: \`git ${command}\` failed \u2014 ${detail}${hint?`; ${hint}`:""}`);this.command=command;this.stderr=stderr;this.name="GitCommandFailedError"}}var WORKTREE_NAME_TAKEN_CODE="WORKTREE_NAME_TAKEN";class WorktreeNameTakenError extends Error{worktreeName;constructor(worktreeName){super(`${WORKTREE_NAME_TAKEN_CODE}: worktree name '${worktreeName}' is already in use in this repo \u2014 pick another, or omit --worktree-name for a generated one`);this.worktreeName=worktreeName;this.name="WorktreeNameTakenError"}}var INVALID_WORKTREE_NAME_CODE="INVALID_WORKTREE_NAME";class InvalidWorktreeNameError extends Error{worktreeName;constructor(worktreeName){super(`${INVALID_WORKTREE_NAME_CODE}: worktree name '${worktreeName}' must be a single path segment of letters, digits, '.', '_' or '-' (no '/', no '..', not starting with '.')`);this.worktreeName=worktreeName;this.name="InvalidWorktreeNameError"}}import fs from"fs";import path from"path";var WORKTREE_BASE_CUSTOM_KEY="worktree.basePath.custom",PROJECT_SIBLING_BASE=`${PROJECT_DIR_TOKEN}/..`;function worktreeBaseKindOf(raw){let trimmed=raw.trim();if(!trimmed)return"default";if(trimmed.replace(/\/+$/,"")===PROJECT_SIBLING_BASE)return"nextToProject";return"custom"}function getWorktreeBaseOverride(projectDir){let value=loadStateFile()[WORKTREE_BASE_KEY];return normalizeWorktreeBase(typeof value==="string"?value:null,projectDir)}function worktreeRootFor2(repo){return worktreeRootFor(repo,getWorktreeBaseOverride(repo))}function managedWorktreeRootsFor2(repo){return managedWorktreeRootsFor(repo,getWorktreeBaseOverride(repo))}function worktreePathFor(repo,slug){if(!slug||/[/\\\0]/.test(slug))throw Error(`worktreePathFor: invalid slug: ${JSON.stringify(slug)}`);return path.join(worktreeRootFor2(repo),slug)}async function listWorktreeDirNames(repo){if(isRemoteRepoKey(repo)){let basePath=getRemoteRepoConfig(repo)?.basePath;if(!basePath)return[];let names2=new Set,host=execHostForRepo(repo),entries=await Promise.all(remoteManagedWorktreeRootsFor(basePath).map((root)=>host.readdir(root)));for(let list of entries)for(let name of list)names2.add(name);return[...names2]}let names=new Set;for(let root of managedWorktreeRootsFor2(repo))try{for(let e of fs.readdirSync(root,{withFileTypes:!0}))if(e.isDirectory())names.add(e.name)}catch{}return[...names]}function managedWorktreeRootForPath(repo,candidate){if(!path.isAbsolute(repo)||!path.isAbsolute(candidate))return null;let target=canonicalize(candidate);for(let rootPath of managedWorktreeRootsFor2(repo)){let root=canonicalize(rootPath),rel=pathWithin(root,target);if(rel!==null&&rel!=="")return rootPath}return null}function isRoveManagedPath(repo,candidate){return managedWorktreeRootForPath(repo,candidate)!==null}function isUnderManagedWorktreesRoot(candidate,projectDir){if(!path.isAbsolute(candidate))return!1;let target=canonicalize(candidate),roots=[getWorktreeBaseOverride(projectDir)??"",defaultLocalWorktreesRoot(),legacyLocalWorktreesRoot()];for(let rootPath of roots){if(!rootPath)continue;let root=canonicalize(rootPath),rel=pathWithin(root,target);if(rel===null)continue;if(rel.split("/").filter(Boolean).length===2)return!0}return!1}function remoteWorktreeRootFor(basePath){return`${stripTrailingSlash(basePath)}/.rove/worktrees`}function remoteManagedWorktreeRootsFor(basePath){let base=stripTrailingSlash(basePath);return[`${base}/.rove/worktrees`,`${base}/.rove/worktrees`]}function remoteWorktreePathFor(basePath,slug){if(!slug||/[/\\\0]/.test(slug))throw Error(`remoteWorktreePathFor: invalid slug: ${JSON.stringify(slug)}`);return`${remoteWorktreeRootFor(basePath)}/${slug}`}function remoteManagedRootForPath(basePath,candidate){for(let root of remoteManagedWorktreeRootsFor(basePath))if(candidate===root||candidate.startsWith(`${root}/`))return root;return null}function stripTrailingSlash(p){return p.length>1&&p.endsWith("/")?p.replace(/\/+$/,""):p}function requireAbsolute(name,value){if(!value||!path.isAbsolute(value))throw Error(`${name} must be an absolute path, got: ${JSON.stringify(value)}`)}function canonicalize(p){try{return fs.realpathSync(p)}catch{return path.resolve(p)}}
|
|
3
|
+
export{IllegalTransitionError,TaskNotFoundError,CannotDeleteMainTaskError,DIRTY_WORKTREE_CODE,describeDirtyWorktreeWork,dirtyRefusalReason,DirtyWorktreeError,WorktreeRemoveFailedError,TASK_DELETING_CODE,TaskDeletingError,MainCheckoutDirtyError,EmptyBranchError,EMPTY_BRANCH_DIRTY_WORKTREE_CODE,EmptyBranchDirtyWorktreeError,MissingRefError,LandConflictError,GitCommandFailedError,WorktreeNameTakenError,InvalidWorktreeNameError,WORKTREE_BASE_CUSTOM_KEY,PROJECT_SIBLING_BASE,worktreeBaseKindOf,worktreePathFor,listWorktreeDirNames,managedWorktreeRootForPath,isRoveManagedPath,isUnderManagedWorktreesRoot,remoteWorktreePathFor,remoteManagedRootForPath,requireAbsolute,canonicalize};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{toTaskId}from"./chunk-xy8be792.js";import{coerceVendorId}from"./chunk-05jej26n.js";import{DAEMON_MIGRATION_MARKER}from"./chunk-fxs82dsx.js";import{LockfileError,acquire}from"./chunk-hq2n27y1.js";import{logClient}from"./chunk-3es6spp4.js";import{defaultClientLogPath}from"./chunk-y8fqdnh3.js";import{existsSync}from"fs";import{copyFile,readFile}from"fs/promises";import{dirname,join}from"path";function coerceTask(value){if(!value||typeof value!=="object")return null;let v=value;if(typeof v.id!=="string"||typeof v.title!=="string"||typeof v.repo!=="string"||typeof v.branch!=="string"||typeof v.worktreePath!=="string"||typeof v.status!=="string"||typeof v.createdAt!=="string"||typeof v.updatedAt!=="string")return null;if(!isTaskStatus(v.status))return null;let kind=v.kind==="main"?"main":v.kind==="dir"?"dir":"task",scratch=kind==="dir"&&v.scratch===!0,healedStatus=kind==="main"&&(v.status==="in_progress"||v.status==="done")?"backlog":v.status,deletion=coerceDeletion(v.deletion),quotaResume=coerceQuotaResume(v.quotaResume),linkedWorkItem=coerceLinkedWorkItem(v.linkedWorkItem),dispatcher=coerceDispatcher(v.dispatcher),routine=coerceRoutine(v.routine),report=coerceWorkerReport(v.report);return{id:toTaskId(v.id),title:v.title,repo:v.repo,branch:v.branch,worktreePath:v.worktreePath,status:healedStatus,pinned:typeof v.pinned==="boolean"?v.pinned:!1,kind,...scratch?{scratch:!0}:{},...routine?{routine}:{},vendor:coerceVendorId(typeof v.vendor==="string"?v.vendor:void 0),...typeof v.command==="string"&&v.command.trim().length>0?{command:v.command}:{},prStatus:coercePRStatus(v.prStatus),...typeof v.modelEffort==="string"&&v.modelEffort.length>0?{modelEffort:v.modelEffort}:{},...typeof v.model==="string"&&v.model.length>0?{model:v.model}:{},...typeof v.tier==="string"&&v.tier.length>0?{tier:v.tier}:{},...typeof v.groupId==="string"&&v.groupId.length>0?{groupId:v.groupId}:{},...v.observedLanguage==="zh"||v.observedLanguage==="en"?{observedLanguage:v.observedLanguage}:{},...deletion?{deletion}:{},...quotaResume?{quotaResume}:{},...linkedWorkItem?{linkedWorkItem}:{},...dispatcher?{dispatcher}:{},...typeof v.prompt==="string"&&v.prompt.length>0?{prompt:v.prompt}:{},...typeof v.baseRef==="string"&&v.baseRef.trim().length>0?{baseRef:v.baseRef}:{},...typeof v.worktreeName==="string"&&v.worktreeName.trim().length>0?{worktreeName:v.worktreeName}:{},...report?{report}:{},createdAt:v.createdAt,updatedAt:v.updatedAt}}function coerceWorkerReport(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.at!=="string"||v.at.length===0)return;return{at:v.at,...typeof v.branch==="string"&&v.branch.length>0?{branch:v.branch}:{},...typeof v.pr==="number"&&Number.isFinite(v.pr)?{pr:v.pr}:{},...typeof v.summary==="string"&&v.summary.length>0?{summary:v.summary}:{}}}function coerceDispatcher(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.taskId!=="string"||v.taskId.length===0)return;if(typeof v.tabId!=="string"||v.tabId.length===0)return;return{taskId:v.taskId,tabId:v.tabId}}function coerceRoutine(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.automationId!=="string"||v.automationId.length===0)return;return{automationId:v.automationId}}function coerceQuotaResume(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.resumeAt!=="string"||v.resumeAt.length===0)return;if(typeof v.requestedAt!=="string"||v.requestedAt.length===0)return;return{resumeAt:v.resumeAt,requestedAt:v.requestedAt}}function coerceLinkedWorkItem(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(v.provider!=="github")return;if(v.type!=="issue"&&v.type!=="pr")return;if(typeof v.number!=="number"||!Number.isFinite(v.number))return;if(typeof v.title!=="string"||typeof v.url!=="string"||v.url.length===0)return;return{provider:v.provider,type:v.type,number:v.number,title:v.title,url:v.url}}function coerceDeletion(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(v.phase!=="queued"&&v.phase!=="running"&&v.phase!=="error"||typeof v.force!=="boolean"||typeof v.requestedAt!=="string"||v.requestedAt.length===0||v.error!==void 0&&typeof v.error!=="string")return;return{phase:v.phase,force:v.force,...typeof v.deleteBranch==="boolean"?{deleteBranch:v.deleteBranch}:{},requestedAt:v.requestedAt,...typeof v.error==="string"?{error:v.error}:{}}}function coercePRStatus(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(!isPRProviderId(v.provider)||!isPRLifecycleState(v.lifecycle)||!isPRCheckState(v.checkState))return;return{provider:v.provider,lifecycle:v.lifecycle,checkState:v.checkState,...typeof v.number==="number"&&Number.isFinite(v.number)?{number:v.number}:{},...typeof v.url==="string"?{url:v.url}:{},...typeof v.title==="string"?{title:v.title}:{},...typeof v.baseRef==="string"?{baseRef:v.baseRef}:{},...typeof v.reviewDecision==="string"?{reviewDecision:v.reviewDecision}:{},...typeof v.mergeable==="string"?{mergeable:v.mergeable}:{},...typeof v.lastCheckedAt==="string"?{lastCheckedAt:v.lastCheckedAt}:{},...typeof v.lastError==="string"?{lastError:v.lastError}:{}}}function isPRProviderId(v){return v==="github"||v==="gitlab"||v==="bitbucket"||v==="unknown"}function isPRLifecycleState(v){return v==="creating"||v==="open"||v==="ready_to_merge"||v==="merged"||v==="closed"||v==="unknown"}function isPRCheckState(v){return v==="none"||v==="pending"||v==="passing"||v==="failing"||v==="unknown"}function isTaskStatus(s){return s==="backlog"||s==="in_progress"||s==="in_review"||s==="done"||s==="canceled"||s==="error"}var sleep=(ms)=>new Promise((resolve)=>setTimeout(resolve,ms)),LOCK_RETRY_DELAY_MS=25,LOCK_MAX_WAIT_MS=5000;async function acquireWithRetry(lockPath){let deadline=Date.now()+LOCK_MAX_WAIT_MS;for(;;)try{return await acquire(lockPath)}catch(err){if(!(err instanceof LockfileError)||Date.now()>=deadline)throw err;await sleep(LOCK_RETRY_DELAY_MS)}}var CURRENT_VERSION=3;async function backupCorruptManifest(path,now=()=>new Date){let backupPath=`${path}.corrupt-${now().toISOString().replaceAll(":","-")}`;try{return await copyFile(path,backupPath),backupPath}catch{return null}}var SUPPORTED_VERSIONS=new Set([1,2,3]);function warnManifestRecovery(message,manifestPath){console.warn(message),logClient("tasks-index",message,manifestPath?defaultClientLogPath(dirname(dirname(manifestPath))):void 0)}async function recoverUnsupportedVersion(parsed,sourcePath){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return!1;let version=parsed.version;if(version===void 0||SUPPORTED_VERSIONS.has(version))return!1;let backup=await backupCorruptManifest(sourcePath);return warnManifestRecovery(`[rove] tasks.json at ${sourcePath} has unsupported version=${String(version)}; recovering with empty index.${backup?` Original bytes backed up to ${backup}.`:" Backup copy failed; the stale file is left in place."}`,sourcePath),!0}function normalizeIndex(parsed,source){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return warnManifestRecovery(`[rove] tasks.json at ${source} is not an object; recovering with empty index.`,source),{version:CURRENT_VERSION,tasks:[]};let obj=parsed,version=obj.version;if(version!==void 0&&!SUPPORTED_VERSIONS.has(version))return warnManifestRecovery(`[rove] tasks.json at ${source} has unsupported version=${String(version)}; recovering with empty index.`,source),{version:CURRENT_VERSION,tasks:[]};let rawTasks=Array.isArray(obj.tasks)?obj.tasks:[],tasks=[];for(let entry of rawTasks){let task=coerceTask(entry);if(task)tasks.push(task);else console.warn(`[rove] dropping malformed task entry from ${source}: ${JSON.stringify(entry)}`)}return{version:CURRENT_VERSION,tasks}}var TOMBSTONE_TTL_MS=2592000000;function readableLegacyIndexPath(canonicalPath,legacyPath){return existsSync(join(dirname(canonicalPath),DAEMON_MIGRATION_MARKER))?void 0:legacyPath}async function readDiskIndex(path,legacyPath){let raw,sourcePath=path;try{raw=await readFile(sourcePath,"utf8")}catch(err){if(err.code!=="ENOENT")throw err;let legacy=readableLegacyIndexPath(path,legacyPath);if(!legacy)return{tasks:[],removed:[]};sourcePath=legacy;try{raw=await readFile(sourcePath,"utf8")}catch(legacyErr){if(legacyErr.code==="ENOENT")return{tasks:[],removed:[]};throw legacyErr}}let parsed;try{parsed=JSON.parse(raw)}catch{return await backupCorruptManifest(sourcePath),{tasks:[],removed:[]}}if(await recoverUnsupportedVersion(parsed,sourcePath))return{tasks:[],removed:[]};return{tasks:normalizeIndex(parsed,sourcePath).tasks,removed:coerceTombstones(parsed)}}function coerceTombstones(parsed){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return[];let raw=parsed.removed;if(!Array.isArray(raw))return[];let out=[];for(let entry of raw){if(!entry||typeof entry!=="object")continue;let v=entry;if(typeof v.id==="string"&&v.id.length>0&&typeof v.at==="string")out.push({id:v.id,at:v.at})}return out}function mergeTasksWithDisk(cacheTasks,diskTasks,dirty,removed,diskRemoved=[],now=Date.now()){let tombstones=new Map;for(let t of diskRemoved){let at=Date.parse(t.at);if(!Number.isFinite(at)||now-at>TOMBSTONE_TTL_MS)continue;tombstones.set(t.id,t.at)}for(let[id,at]of removed)tombstones.set(id,at);let diskById=new Map(diskTasks.map((t)=>[t.id,t])),result=[],included=new Set;for(let task of cacheTasks){if(tombstones.has(task.id))continue;if(dirty.has(task.id))result.push(task);else{let onDisk=diskById.get(task.id);if(onDisk===void 0)continue;result.push(onDisk)}included.add(task.id)}for(let task of diskTasks){if(included.has(task.id)||tombstones.has(task.id))continue;result.push(task),included.add(task.id)}return{tasks:result,removed:[...tombstones].map(([id,at])=>({id,at}))}}async function recoverIndexFromDisk(path,legacyPath){let raw,sourcePath=path;try{raw=await readFile(path,"utf8")}catch(err){if(err.code!=="ENOENT")throw err;let legacy=readableLegacyIndexPath(path,legacyPath),legacyRaw;if(legacy)try{legacyRaw=await readFile(legacy,"utf8"),sourcePath=legacy}catch(legacyErr){if(legacyErr.code!=="ENOENT")throw legacyErr}if(legacyRaw===void 0)return{version:CURRENT_VERSION,tasks:[]};raw=legacyRaw}let parsed;try{parsed=JSON.parse(raw)}catch(err){let backup=await backupCorruptManifest(sourcePath);return warnManifestRecovery(`[rove] tasks.json at ${sourcePath} is corrupted (${err.message}); recovering with empty index.${backup?` Original bytes backed up to ${backup}.`:" Backup copy failed; the stale file is left in place."}`,sourcePath),{version:CURRENT_VERSION,tasks:[]}}if(await recoverUnsupportedVersion(parsed,sourcePath))return{version:CURRENT_VERSION,tasks:[]};return normalizeIndex(parsed,sourcePath)}
|
|
2
|
+
import{toTaskId}from"./chunk-xy8be792.js";import{coerceVendorId}from"./chunk-h2m7em1e.js";import{DAEMON_MIGRATION_MARKER}from"./chunk-tdhk4dz8.js";import{LockfileError,acquire}from"./chunk-mw0ysrpd.js";import{logClient}from"./chunk-hq9tbzqa.js";import{defaultClientLogPath}from"./chunk-npwzmmv9.js";import{existsSync}from"fs";import{copyFile,readFile}from"fs/promises";import{dirname,join}from"path";function coerceTask(value){if(!value||typeof value!=="object")return null;let v=value;if(typeof v.id!=="string"||typeof v.title!=="string"||typeof v.repo!=="string"||typeof v.branch!=="string"||typeof v.worktreePath!=="string"||typeof v.status!=="string"||typeof v.createdAt!=="string"||typeof v.updatedAt!=="string")return null;if(!isTaskStatus(v.status))return null;let kind=v.kind==="main"?"main":v.kind==="dir"?"dir":"task",scratch=kind==="dir"&&v.scratch===!0,healedStatus=kind==="main"&&(v.status==="in_progress"||v.status==="done")?"backlog":v.status,deletion=coerceDeletion(v.deletion),quotaResume=coerceQuotaResume(v.quotaResume),linkedWorkItem=coerceLinkedWorkItem(v.linkedWorkItem),dispatcher=coerceDispatcher(v.dispatcher),routine=coerceRoutine(v.routine),report=coerceWorkerReport(v.report);return{id:toTaskId(v.id),title:v.title,repo:v.repo,branch:v.branch,worktreePath:v.worktreePath,status:healedStatus,pinned:typeof v.pinned==="boolean"?v.pinned:!1,kind,...scratch?{scratch:!0}:{},...routine?{routine}:{},vendor:coerceVendorId(typeof v.vendor==="string"?v.vendor:void 0),...typeof v.command==="string"&&v.command.trim().length>0?{command:v.command}:{},prStatus:coercePRStatus(v.prStatus),...typeof v.modelEffort==="string"&&v.modelEffort.length>0?{modelEffort:v.modelEffort}:{},...typeof v.model==="string"&&v.model.length>0?{model:v.model}:{},...typeof v.tier==="string"&&v.tier.length>0?{tier:v.tier}:{},...typeof v.groupId==="string"&&v.groupId.length>0?{groupId:v.groupId}:{},...v.observedLanguage==="zh"||v.observedLanguage==="en"?{observedLanguage:v.observedLanguage}:{},...deletion?{deletion}:{},...quotaResume?{quotaResume}:{},...linkedWorkItem?{linkedWorkItem}:{},...dispatcher?{dispatcher}:{},...typeof v.prompt==="string"&&v.prompt.length>0?{prompt:v.prompt}:{},...typeof v.baseRef==="string"&&v.baseRef.trim().length>0?{baseRef:v.baseRef}:{},...typeof v.worktreeName==="string"&&v.worktreeName.trim().length>0?{worktreeName:v.worktreeName}:{},...report?{report}:{},createdAt:v.createdAt,updatedAt:v.updatedAt}}function coerceWorkerReport(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.at!=="string"||v.at.length===0)return;return{at:v.at,...typeof v.branch==="string"&&v.branch.length>0?{branch:v.branch}:{},...typeof v.pr==="number"&&Number.isFinite(v.pr)?{pr:v.pr}:{},...typeof v.summary==="string"&&v.summary.length>0?{summary:v.summary}:{}}}function coerceDispatcher(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.taskId!=="string"||v.taskId.length===0)return;if(typeof v.tabId!=="string"||v.tabId.length===0)return;return{taskId:v.taskId,tabId:v.tabId}}function coerceRoutine(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.automationId!=="string"||v.automationId.length===0)return;return{automationId:v.automationId}}function coerceQuotaResume(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(typeof v.resumeAt!=="string"||v.resumeAt.length===0)return;if(typeof v.requestedAt!=="string"||v.requestedAt.length===0)return;return{resumeAt:v.resumeAt,requestedAt:v.requestedAt}}function coerceLinkedWorkItem(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(v.provider!=="github")return;if(v.type!=="issue"&&v.type!=="pr")return;if(typeof v.number!=="number"||!Number.isFinite(v.number))return;if(typeof v.title!=="string"||typeof v.url!=="string"||v.url.length===0)return;return{provider:v.provider,type:v.type,number:v.number,title:v.title,url:v.url}}function coerceDeletion(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(v.phase!=="queued"&&v.phase!=="running"&&v.phase!=="error"||typeof v.force!=="boolean"||typeof v.requestedAt!=="string"||v.requestedAt.length===0||v.error!==void 0&&typeof v.error!=="string")return;return{phase:v.phase,force:v.force,...typeof v.deleteBranch==="boolean"?{deleteBranch:v.deleteBranch}:{},requestedAt:v.requestedAt,...typeof v.error==="string"?{error:v.error}:{}}}function coercePRStatus(value){if(!value||typeof value!=="object"||Array.isArray(value))return;let v=value;if(!isPRProviderId(v.provider)||!isPRLifecycleState(v.lifecycle)||!isPRCheckState(v.checkState))return;return{provider:v.provider,lifecycle:v.lifecycle,checkState:v.checkState,...typeof v.number==="number"&&Number.isFinite(v.number)?{number:v.number}:{},...typeof v.url==="string"?{url:v.url}:{},...typeof v.title==="string"?{title:v.title}:{},...typeof v.baseRef==="string"?{baseRef:v.baseRef}:{},...typeof v.reviewDecision==="string"?{reviewDecision:v.reviewDecision}:{},...typeof v.mergeable==="string"?{mergeable:v.mergeable}:{},...typeof v.lastCheckedAt==="string"?{lastCheckedAt:v.lastCheckedAt}:{},...typeof v.lastError==="string"?{lastError:v.lastError}:{}}}function isPRProviderId(v){return v==="github"||v==="gitlab"||v==="bitbucket"||v==="unknown"}function isPRLifecycleState(v){return v==="creating"||v==="open"||v==="ready_to_merge"||v==="merged"||v==="closed"||v==="unknown"}function isPRCheckState(v){return v==="none"||v==="pending"||v==="passing"||v==="failing"||v==="unknown"}function isTaskStatus(s){return s==="backlog"||s==="in_progress"||s==="in_review"||s==="done"||s==="canceled"||s==="error"}var sleep=(ms)=>new Promise((resolve)=>setTimeout(resolve,ms)),LOCK_RETRY_DELAY_MS=25,LOCK_MAX_WAIT_MS=5000;async function acquireWithRetry(lockPath){let deadline=Date.now()+LOCK_MAX_WAIT_MS;for(;;)try{return await acquire(lockPath)}catch(err){if(!(err instanceof LockfileError)||Date.now()>=deadline)throw err;await sleep(LOCK_RETRY_DELAY_MS)}}var CURRENT_VERSION=3;async function backupCorruptManifest(path,now=()=>new Date){let backupPath=`${path}.corrupt-${now().toISOString().replaceAll(":","-")}`;try{return await copyFile(path,backupPath),backupPath}catch{return null}}var SUPPORTED_VERSIONS=new Set([1,2,3]);function warnManifestRecovery(message,manifestPath){console.warn(message),logClient("tasks-index",message,manifestPath?defaultClientLogPath(dirname(dirname(manifestPath))):void 0)}async function recoverUnsupportedVersion(parsed,sourcePath){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return!1;let version=parsed.version;if(version===void 0||SUPPORTED_VERSIONS.has(version))return!1;let backup=await backupCorruptManifest(sourcePath);return warnManifestRecovery(`[rove] tasks.json at ${sourcePath} has unsupported version=${String(version)}; recovering with empty index.${backup?` Original bytes backed up to ${backup}.`:" Backup copy failed; the stale file is left in place."}`,sourcePath),!0}function normalizeIndex(parsed,source){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return warnManifestRecovery(`[rove] tasks.json at ${source} is not an object; recovering with empty index.`,source),{version:CURRENT_VERSION,tasks:[]};let obj=parsed,version=obj.version;if(version!==void 0&&!SUPPORTED_VERSIONS.has(version))return warnManifestRecovery(`[rove] tasks.json at ${source} has unsupported version=${String(version)}; recovering with empty index.`,source),{version:CURRENT_VERSION,tasks:[]};let rawTasks=Array.isArray(obj.tasks)?obj.tasks:[],tasks=[];for(let entry of rawTasks){let task=coerceTask(entry);if(task)tasks.push(task);else console.warn(`[rove] dropping malformed task entry from ${source}: ${JSON.stringify(entry)}`)}return{version:CURRENT_VERSION,tasks}}var TOMBSTONE_TTL_MS=2592000000;function readableLegacyIndexPath(canonicalPath,legacyPath){return existsSync(join(dirname(canonicalPath),DAEMON_MIGRATION_MARKER))?void 0:legacyPath}async function readDiskIndex(path,legacyPath){let raw,sourcePath=path;try{raw=await readFile(sourcePath,"utf8")}catch(err){if(err.code!=="ENOENT")throw err;let legacy=readableLegacyIndexPath(path,legacyPath);if(!legacy)return{tasks:[],removed:[]};sourcePath=legacy;try{raw=await readFile(sourcePath,"utf8")}catch(legacyErr){if(legacyErr.code==="ENOENT")return{tasks:[],removed:[]};throw legacyErr}}let parsed;try{parsed=JSON.parse(raw)}catch{return await backupCorruptManifest(sourcePath),{tasks:[],removed:[]}}if(await recoverUnsupportedVersion(parsed,sourcePath))return{tasks:[],removed:[]};return{tasks:normalizeIndex(parsed,sourcePath).tasks,removed:coerceTombstones(parsed)}}function coerceTombstones(parsed){if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))return[];let raw=parsed.removed;if(!Array.isArray(raw))return[];let out=[];for(let entry of raw){if(!entry||typeof entry!=="object")continue;let v=entry;if(typeof v.id==="string"&&v.id.length>0&&typeof v.at==="string")out.push({id:v.id,at:v.at})}return out}function mergeTasksWithDisk(cacheTasks,diskTasks,dirty,removed,diskRemoved=[],now=Date.now()){let tombstones=new Map;for(let t of diskRemoved){let at=Date.parse(t.at);if(!Number.isFinite(at)||now-at>TOMBSTONE_TTL_MS)continue;tombstones.set(t.id,t.at)}for(let[id,at]of removed)tombstones.set(id,at);let diskById=new Map(diskTasks.map((t)=>[t.id,t])),result=[],included=new Set;for(let task of cacheTasks){if(tombstones.has(task.id))continue;if(dirty.has(task.id))result.push(task);else{let onDisk=diskById.get(task.id);if(onDisk===void 0)continue;result.push(onDisk)}included.add(task.id)}for(let task of diskTasks){if(included.has(task.id)||tombstones.has(task.id))continue;result.push(task),included.add(task.id)}return{tasks:result,removed:[...tombstones].map(([id,at])=>({id,at}))}}async function recoverIndexFromDisk(path,legacyPath){let raw,sourcePath=path;try{raw=await readFile(path,"utf8")}catch(err){if(err.code!=="ENOENT")throw err;let legacy=readableLegacyIndexPath(path,legacyPath),legacyRaw;if(legacy)try{legacyRaw=await readFile(legacy,"utf8"),sourcePath=legacy}catch(legacyErr){if(legacyErr.code!=="ENOENT")throw legacyErr}if(legacyRaw===void 0)return{version:CURRENT_VERSION,tasks:[]};raw=legacyRaw}let parsed;try{parsed=JSON.parse(raw)}catch(err){let backup=await backupCorruptManifest(sourcePath);return warnManifestRecovery(`[rove] tasks.json at ${sourcePath} is corrupted (${err.message}); recovering with empty index.${backup?` Original bytes backed up to ${backup}.`:" Backup copy failed; the stale file is left in place."}`,sourcePath),{version:CURRENT_VERSION,tasks:[]}}if(await recoverUnsupportedVersion(parsed,sourcePath))return{version:CURRENT_VERSION,tasks:[]};return normalizeIndex(parsed,sourcePath)}
|
|
3
3
|
export{acquireWithRetry,readableLegacyIndexPath,readDiskIndex,mergeTasksWithDisk,recoverIndexFromDisk};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{buildPaneArgv}from"./chunk-
|
|
3
|
-
`))}function loadAll(){return loadPluginRegistry().plugins.map((entry)=>{try{return{entry,manifest:readPluginManifest(entry.root).manifest}}catch{return{entry,manifest:void 0}}})}function requireEntry(id){let entry=loadPluginRegistry().plugins.find((p)=>p.id===id);if(!entry)throw new PluginCliError(`no plugin registered as \`${id}\`; see \`${CLI_NAME} plugin list\``);return entry}function listPlugins(){let all=loadAll();if(all.length===0){console.log(`no plugins installed. Try: ${CLI_NAME} plugin install <owner/repo> \u2014 browse the \`rove-plugin\` GitHub topic.`);return}for(let{entry,manifest}of all){let state=entry.enabled?"enabled":"disabled",kind=entry.source.kind==="link"?`linked ${entry.root}`:entry.source.spec,broken=manifest?"":" [manifest unreadable]";console.log(`${entry.id} v${entry.version} ${state} (${kind})${broken}`)}}function setEnabled(id,enabled){let entry=requireEntry(id),registry=loadPluginRegistry();savePluginRegistry({plugins:registry.plugins.map((p)=>p.id===id?{...entry,enabled}:p)}),console.log(`${enabled?"enabled":"disabled"} ${id}`)}function unlink(id){let entry=requireEntry(id);if(entry.source.kind!=="link")throw new PluginCliError(`\`${id}\` is a GitHub install; use uninstall`);savePluginRegistry(removePluginEntry(loadPluginRegistry(),id)),console.log(`unlinked ${id} (files untouched at ${entry.root})`)}function uninstall(idOrSpec){let registry=loadPluginRegistry(),entry=registry.plugins.find((p)=>p.id===idOrSpec||p.source.kind==="github"&&p.source.spec===idOrSpec);if(!entry)throw new PluginCliError(`no plugin registered as \`${idOrSpec}\``);if(entry.source.kind==="link")throw new PluginCliError(`\`${entry.id}\` is linked; use unlink`);savePluginRegistry(removePluginEntry(registry,entry.id)),rmSync(pluginCheckoutDir(entry.id),{recursive:!0,force:!0}),console.log(`uninstalled ${entry.id} (config/state kept under ~/.rove/plugins/${entry.id}/)`)}function listActions(pluginFilter){for(let{entry,manifest}of loadAll()){if(!manifest||pluginFilter&&entry.id!==pluginFilter)continue;for(let action of manifest.actions)console.log(`${qualifiedActionId(entry.id,action.id)} ${action.title}`)}}function findByLongestPluginPrefix(qualified,options,findItem){for(let{entry,manifest}of loadAll().filter(({entry:entry2,manifest:manifest2})=>Boolean(manifest2&&(!options.enabledOnly||entry2.enabled)&&qualified.startsWith(`${entry2.id}.`))).sort((a,b)=>b.entry.id.length-a.entry.id.length)){let item=findItem(manifest,qualified.slice(entry.id.length+1));if(item!==void 0)return{entry,manifest,item}}return}function assertPlatformSupported(label,item,manifest){if(supportsPlatform(item,manifest,currentPluginPlatform()))return;let declared=(item.platforms??manifest.platforms??[]).join(", ");throw new PluginCliError(`\`${label}\` is not supported on this platform (declares ${declared})`)}function invokeAction(qualified,extraArgs){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!0},(manifest,actionId)=>manifest.actions.find((a)=>a.id===actionId));if(!hit)throw new PluginCliError(`no action \`${qualified}\`; see \`${CLI_NAME} plugin action list\``);assertPlatformSupported(qualified,hit.item,hit.manifest);let action=hit.item,[cmd,...args]=[...action.command,...extraArgs],res=spawnSync(cmd,args,{cwd:hit.entry.root,stdio:"inherit",env:buildPluginEnv({socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),pluginId:hit.entry.id,pluginRoot:hit.entry.root,extra:{ROVE_PLUGIN_ACTION_ID:action.id,ROVE_PLUGIN_INVOKE_CWD:process.cwd()}})});process.exit(res.status??1)}function resolvePaneQualified(qualified){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!1},(manifest,entrypoint)=>manifest.panes.find((p)=>p.id===entrypoint));if(!hit)throw new PluginCliError(`no pane \`${qualified}\`; see \`${CLI_NAME} plugin list\``);return{pluginId:hit.entry.id,entrypoint:hit.item.id}}async function openPane(pluginId,entrypoint,taskFlag){let loaded=loadAll().find(({entry})=>entry.id===pluginId);if(!loaded?.manifest)throw new PluginCliError(`no plugin \`${pluginId}\` (or its manifest is unreadable)`);if(!loaded.entry.enabled)throw new PluginCliError(`\`${pluginId}\` is disabled`);let pane=loaded.manifest.panes.find((p)=>p.id===entrypoint);if(!pane)throw new PluginCliError(`no pane \`${entrypoint}\` in \`${pluginId}\`; declare it under [[panes]]`);assertPlatformSupported(`${pluginId}.${pane.id}`,pane,loaded.manifest);let{openDaemonSession,resolveActiveTaskId}=await import("./chunk-
|
|
4
|
-
`);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-
|
|
2
|
+
import{buildPaneArgv}from"./chunk-ffs26p85.js";import{PluginCliError,installPlugin,linkPlugin}from"./chunk-cmcn8e8x.js";import{resolvePluginBinPath}from"./chunk-b0ssvpht.js";import{buildPluginEnv}from"./chunk-axsm0gn5.js";import{currentPluginPlatform,loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginLogPath,qualifiedActionId,readPluginManifest,removePluginEntry,savePluginRegistry,supportsPlatform}from"./chunk-rqyaf0dw.js";import"./chunk-vjvkkrzc.js";import"./chunk-w7zv47mp.js";import{flagValue}from"./chunk-zsfyj36g.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import"./chunk-7cce0st1.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-0422g8ac.js";import{defaultDaemonSocketPath}from"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{readFileSync,rmSync}from"fs";var CLI_NAME=ROVE_PRODUCT_NAME;function printUsage(out){out.write([`usage: ${CLI_NAME} plugin <command>`,""," install <owner/repo[/subdir]> [--yes] [--ref <rev>] clone from GitHub, preview, build, register"," link <dir> register a local plugin directory (dev)"," list installed + linked plugins"," search [query] browse the marketplace (GitHub topic rove-plugin)"," outdated check GitHub-installed plugins against upstream"," update <id\u2026> | --all [--yes] reinstall stale plugins from GitHub"," enable <id> | disable <id> toggle a plugin without unregistering it"," unlink <id> unregister a linked plugin (files untouched)"," uninstall <id-or-spec> unregister + remove the managed checkout"," config-dir <id> print the plugin's config directory"," log <id> [-n <count>] tail the plugin's command-run log"," action list [--plugin <id>] declared actions"," action invoke <plugin-id.action-id> run an action now"," pane open <plugin-id.pane-id> [--task <task-id>] open a plugin pane as a terminal tab (JSON:"," clients \u2014 0 = no attached UI performed the split)","","Marketplace: https://github.com/topics/rove-plugin",""].join(`
|
|
3
|
+
`))}function loadAll(){return loadPluginRegistry().plugins.map((entry)=>{try{return{entry,manifest:readPluginManifest(entry.root).manifest}}catch{return{entry,manifest:void 0}}})}function requireEntry(id){let entry=loadPluginRegistry().plugins.find((p)=>p.id===id);if(!entry)throw new PluginCliError(`no plugin registered as \`${id}\`; see \`${CLI_NAME} plugin list\``);return entry}function listPlugins(){let all=loadAll();if(all.length===0){console.log(`no plugins installed. Try: ${CLI_NAME} plugin install <owner/repo> \u2014 browse the \`rove-plugin\` GitHub topic.`);return}for(let{entry,manifest}of all){let state=entry.enabled?"enabled":"disabled",kind=entry.source.kind==="link"?`linked ${entry.root}`:entry.source.spec,broken=manifest?"":" [manifest unreadable]";console.log(`${entry.id} v${entry.version} ${state} (${kind})${broken}`)}}function setEnabled(id,enabled){let entry=requireEntry(id),registry=loadPluginRegistry();savePluginRegistry({plugins:registry.plugins.map((p)=>p.id===id?{...entry,enabled}:p)}),console.log(`${enabled?"enabled":"disabled"} ${id}`)}function unlink(id){let entry=requireEntry(id);if(entry.source.kind!=="link")throw new PluginCliError(`\`${id}\` is a GitHub install; use uninstall`);savePluginRegistry(removePluginEntry(loadPluginRegistry(),id)),console.log(`unlinked ${id} (files untouched at ${entry.root})`)}function uninstall(idOrSpec){let registry=loadPluginRegistry(),entry=registry.plugins.find((p)=>p.id===idOrSpec||p.source.kind==="github"&&p.source.spec===idOrSpec);if(!entry)throw new PluginCliError(`no plugin registered as \`${idOrSpec}\``);if(entry.source.kind==="link")throw new PluginCliError(`\`${entry.id}\` is linked; use unlink`);savePluginRegistry(removePluginEntry(registry,entry.id)),rmSync(pluginCheckoutDir(entry.id),{recursive:!0,force:!0}),console.log(`uninstalled ${entry.id} (config/state kept under ~/.rove/plugins/${entry.id}/)`)}function listActions(pluginFilter){for(let{entry,manifest}of loadAll()){if(!manifest||pluginFilter&&entry.id!==pluginFilter)continue;for(let action of manifest.actions)console.log(`${qualifiedActionId(entry.id,action.id)} ${action.title}`)}}function findByLongestPluginPrefix(qualified,options,findItem){for(let{entry,manifest}of loadAll().filter(({entry:entry2,manifest:manifest2})=>Boolean(manifest2&&(!options.enabledOnly||entry2.enabled)&&qualified.startsWith(`${entry2.id}.`))).sort((a,b)=>b.entry.id.length-a.entry.id.length)){let item=findItem(manifest,qualified.slice(entry.id.length+1));if(item!==void 0)return{entry,manifest,item}}return}function assertPlatformSupported(label,item,manifest){if(supportsPlatform(item,manifest,currentPluginPlatform()))return;let declared=(item.platforms??manifest.platforms??[]).join(", ");throw new PluginCliError(`\`${label}\` is not supported on this platform (declares ${declared})`)}function invokeAction(qualified,extraArgs){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!0},(manifest,actionId)=>manifest.actions.find((a)=>a.id===actionId));if(!hit)throw new PluginCliError(`no action \`${qualified}\`; see \`${CLI_NAME} plugin action list\``);assertPlatformSupported(qualified,hit.item,hit.manifest);let action=hit.item,[cmd,...args]=[...action.command,...extraArgs],res=spawnSync(cmd,args,{cwd:hit.entry.root,stdio:"inherit",env:buildPluginEnv({socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),pluginId:hit.entry.id,pluginRoot:hit.entry.root,extra:{ROVE_PLUGIN_ACTION_ID:action.id,ROVE_PLUGIN_INVOKE_CWD:process.cwd()}})});process.exit(res.status??1)}function resolvePaneQualified(qualified){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!1},(manifest,entrypoint)=>manifest.panes.find((p)=>p.id===entrypoint));if(!hit)throw new PluginCliError(`no pane \`${qualified}\`; see \`${CLI_NAME} plugin list\``);return{pluginId:hit.entry.id,entrypoint:hit.item.id}}async function openPane(pluginId,entrypoint,taskFlag){let loaded=loadAll().find(({entry})=>entry.id===pluginId);if(!loaded?.manifest)throw new PluginCliError(`no plugin \`${pluginId}\` (or its manifest is unreadable)`);if(!loaded.entry.enabled)throw new PluginCliError(`\`${pluginId}\` is disabled`);let pane=loaded.manifest.panes.find((p)=>p.id===entrypoint);if(!pane)throw new PluginCliError(`no pane \`${entrypoint}\` in \`${pluginId}\`; declare it under [[panes]]`);assertPlatformSupported(`${pluginId}.${pane.id}`,pane,loaded.manifest);let{openDaemonSession,resolveActiveTaskId}=await import("./chunk-yvjgwnb9.js"),session=await openDaemonSession({mode:"start"});try{let taskId=taskFlag??await resolveActiveTaskId(session.client);if(!taskId)throw new PluginCliError("no active task; pass --task <id>");let argv=buildPaneArgv(loaded.entry.id,loaded.entry.root,pane,{socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),taskId}),reply=await session.client.request("tab.open",{taskId,argv,title:pane.title,placement:pane.placement});console.log(JSON.stringify({...reply,ok:!0,pane:`${pluginId}.${pane.id}`,taskId,title:pane.title}))}finally{session.close()}}function tailLog(id,count){requireEntry(id);let text;try{text=readFileSync(pluginLogPath(id),"utf8")}catch{console.log("(no runs logged yet)");return}let lines=text.trimEnd().split(`
|
|
4
|
+
`);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-nem2x959.js");await searchMarketplace(args.find((a)=>!a.startsWith("-")));return}case"outdated":{let{printOutdated}=await import("./chunk-wfhnbnbw.js");printOutdated();return}case"update":{let{updatePlugins}=await import("./chunk-wfhnbnbw.js");await updatePlugins(args.filter((a)=>!a.startsWith("-")),{all:args.includes("--all"),yes:args.includes("--yes")});return}case"enable":case"disable":{if(!args[0])throw new PluginCliError(`${command} needs a plugin id`);setEnabled(args[0],command==="enable");return}case"unlink":{if(!args[0])throw new PluginCliError("unlink needs a plugin id");unlink(args[0]);return}case"uninstall":{if(!args[0])throw new PluginCliError("uninstall needs a plugin id or owner/repo spec");uninstall(args[0]);return}case"config-dir":{if(!args[0])throw new PluginCliError("config-dir needs a plugin id");requireEntry(args[0]),console.log(pluginConfigDir(args[0]));return}case"log":{if(!args[0])throw new PluginCliError("log needs a plugin id");tailLog(args[0],Number.parseInt(flagValue(args,"-n")??"20",10)||20);return}case"pane":{let[sub,...paneArgs]=args;if(sub==="open"){let positional=paneArgs.find((a)=>!a.startsWith("-")&&a!==flagValue(paneArgs,"--task")),pluginId=flagValue(paneArgs,"--plugin"),entrypoint=flagValue(paneArgs,"--entrypoint");if(!pluginId||!entrypoint){if(!positional)throw new PluginCliError("pane open needs <plugin-id.pane-id> (or --plugin <id> --entrypoint <pane-id>) [--task <task-id>]");({pluginId,entrypoint}=resolvePaneQualified(positional))}await openPane(pluginId,entrypoint,flagValue(paneArgs,"--task"));return}printUsage(process.stderr),process.exit(2);return}case"action":{let[sub,...actionArgs]=args;if(sub==="list"){listActions(flagValue(actionArgs,"--plugin"));return}if(sub==="invoke"){if(!actionArgs[0])throw new PluginCliError("action invoke needs <plugin-id.action-id>");invokeAction(actionArgs[0],actionArgs.slice(1));return}printUsage(process.stderr),process.exit(2);return}default:{let isHelp=command===void 0||command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}}}catch(err){if(err instanceof PluginCliError)console.error(`${CLI_NAME} plugin: ${err.message}`),process.exit(1);console.error(`${CLI_NAME} plugin: ${errorMessage(err)}`),process.exit(1)}}export{runPluginSubcommand};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{parse}from"./chunk-w7zv47mp.js";import{OWNER_ONLY_FILE_MODE}from"./chunk-yt15y085.js";import{PLUGIN_EVENT_NAMES}from"./chunk-0422g8ac.js";import{preRenameStateDir}from"./chunk-b39sdtt0.js";import{ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import{existsSync,readFileSync}from"fs";import{basename,join}from"path";var PLUGIN_PLATFORMS=["macos","linux","windows"];class ManifestError extends Error{}function fail(message){throw new ManifestError(`rove-plugin.toml: ${message}`)}function asString(value,field){if(typeof value!=="string"||value.length===0)fail(`\`${field}\` must be a non-empty string`);return value}function asSettingDefault(value,field){if(value===void 0||value===!1)return;if(value===!0)return"1";if(typeof value==="number"&&Number.isFinite(value))return String(value);return asString(value,field)}var TIMEOUT_MIN_MS=100,TIMEOUT_MAX_MS=600000;function asTimeoutMs(value,field){if(value===void 0)return;if(typeof value!=="number"||!Number.isInteger(value)||value<TIMEOUT_MIN_MS||value>TIMEOUT_MAX_MS)fail(`\`${field}\` must be a whole number of milliseconds between ${TIMEOUT_MIN_MS} and ${TIMEOUT_MAX_MS}`);return value}function asCommand(value,field){if(!Array.isArray(value)||value.length===0||!value.every((v)=>typeof v==="string"&&v.length>0))fail(`\`${field}\` must be a non-empty array of strings (argv form)`);return value}function asPlatforms(value,field){if(value===void 0)return;if(!Array.isArray(value)||!value.every((v)=>PLUGIN_PLATFORMS.includes(v)))fail(`\`${field}\` must be an array drawn from ${PLUGIN_PLATFORMS.join(", ")}`);return value}function asTableArray(value,field){if(value===void 0)return[];if(!Array.isArray(value)||!value.every((v)=>typeof v==="object"&&v!==null&&!Array.isArray(v)))fail(`\`[[${field}]]\` must be an array of tables`);return value}function asStringArray(value,field){if(value===void 0)return;if(!Array.isArray(value)||!value.every((v)=>typeof v==="string"&&v.length>0))fail(`\`${field}\` must be a non-empty array of strings`);return value}var SETTING_KEY_RE=/^[A-Za-z_][A-Za-z0-9_]*$/,RESERVED_SETTING_KEYS=["PATH","HOME","SHELL","IFS","LD_PRELOAD","LD_LIBRARY_PATH","LD_AUDIT","DYLD_INSERT_LIBRARIES","DYLD_LIBRARY_PATH","DYLD_FRAMEWORK_PATH","NODE_OPTIONS","BUN_INSPECT","PYTHONPATH","PYTHONSTARTUP","PERL5OPT","PERL5LIB","RUBYOPT","BASH_ENV","ENV","GIT_SSH_COMMAND","GIT_SSH","GIT_EXTERNAL_DIFF","GIT_PAGER","PAGER","EDITOR","VISUAL"];function settingKeyRejection(key){if(!SETTING_KEY_RE.test(key))return`\`${key}\` is not a valid env var name (${SETTING_KEY_RE.source})`;if(RESERVED_SETTING_KEYS.includes(key))return`\`${key}\` is reserved; it steers how the plugin's own process runs`;return null}var PLUGIN_MANIFEST_FILENAME="rove-plugin.toml",PLUGIN_MANIFEST_FILENAMES=[PLUGIN_MANIFEST_FILENAME],RESERVED_ENGINE_IDS=["claude","codex","copilot","kimi","pi","omp","gemini","opencode","cursor","grok","droid","amp","devin","qodercli","cline","kiro","maki","antigravity","bob"];function pluginManifestPath(root){for(let filename of PLUGIN_MANIFEST_FILENAMES){let path=join(root,filename);if(existsSync(path))return path}return null}function readPluginManifest(root){let path=pluginManifestPath(root);if(!path)throw new ManifestError(`no ${PLUGIN_MANIFEST_FILENAMES.join(" or ")} found at ${root}`);return parsePluginManifest(readFileSync(path,"utf8"),basename(path))}var PLUGIN_ID_RE=/^[A-Za-z0-9][A-Za-z0-9._:-]*$/,LOCAL_ID_RE=/^[A-Za-z0-9][A-Za-z0-9_:-]*$/;function qualifiedActionId(pluginId,actionId){return`${pluginId}.${actionId}`}function currentPluginPlatform(platform=process.platform){if(platform==="darwin")return"macos";if(platform==="linux")return"linux";if(platform==="win32")return"windows";return}function supportsPlatform(item,manifest,platform){let declared=item.platforms??manifest.platforms;if(!declared)return!0;return platform!==void 0&&declared.includes(platform)}function parsePluginManifest(text,filename=PLUGIN_MANIFEST_FILENAME){try{return parseCanonicalPluginManifest(text)}catch(err){if(filename!==PLUGIN_MANIFEST_FILENAME&&err instanceof ManifestError)throw new ManifestError(err.message.replace(/^rove-plugin\.toml:/,`${filename}:`));throw err}}function parseCanonicalPluginManifest(text){let raw;try{raw=parse(text)}catch(err){fail(`invalid TOML \u2014 ${err instanceof Error?err.message:String(err)}`)}let warnings=[],id=asString(raw.id,"id");if(!PLUGIN_ID_RE.test(id))fail(`plugin id \`${id}\` may use ASCII letters, digits, dot, colon, underscore, hyphen`);let name=asString(raw.name,"name"),version=asString(raw.version,"version"),rawMinVersion=raw.min_rove_version,minRoveVersion=asString(rawMinVersion,"min_rove_version"),description=raw.description===void 0?void 0:asString(raw.description,"description"),platforms=asPlatforms(raw.platforms,"platforms");if(!platforms)warnings.push("no top-level `platforms` declared; assuming the plugin runs everywhere");let build=asTableArray(raw.build,"build").map((t,i)=>({command:asCommand(t.command,`build[${i}].command`),platforms:asPlatforms(t.platforms,`build[${i}].platforms`)})),startup=asTableArray(raw.startup,"startup").map((t,i)=>({command:asCommand(t.command,`startup[${i}].command`),platforms:asPlatforms(t.platforms,`startup[${i}].platforms`),timeoutMs:asTimeoutMs(t.timeout_ms,`startup[${i}].timeout_ms`)})),shutdown=asTableArray(raw.shutdown,"shutdown").map((t,i)=>({command:asCommand(t.command,`shutdown[${i}].command`),platforms:asPlatforms(t.platforms,`shutdown[${i}].platforms`),timeoutMs:asTimeoutMs(t.timeout_ms,`shutdown[${i}].timeout_ms`)})),actions=asTableArray(raw.actions,"actions").map((t,i)=>{let actionId=asString(t.id,`actions[${i}].id`);if(t.timeout_ms!==void 0)warnings.push(`actions[${i}] declares \`timeout_ms\`; actions are user-invoked and are never killed on a deadline`);if(!LOCAL_ID_RE.test(actionId))fail(`action id \`${actionId}\` may not contain dots`);return{id:actionId,title:asString(t.title,`actions[${i}].title`),command:asCommand(t.command,`actions[${i}].command`),platforms:asPlatforms(t.platforms,`actions[${i}].platforms`)}}),seen=new Set;for(let a of actions){if(seen.has(a.id))fail(`duplicate action id \`${a.id}\``);seen.add(a.id)}let panes=asTableArray(raw.panes,"panes").map((t,i)=>{let paneId=asString(t.id,`panes[${i}].id`);if(!LOCAL_ID_RE.test(paneId))fail(`pane id \`${paneId}\` may not contain dots`);if(t.timeout_ms!==void 0)warnings.push(`panes[${i}] declares \`timeout_ms\`; a pane is a terminal the user closes, not a bounded hook`);if(t.placement!==void 0&&t.placement!=="tab"&&t.placement!=="split")warnings.push(`pane \`${paneId}\` placement \`${String(t.placement)}\` is not supported yet; opening as a split`);return{id:paneId,title:asString(t.title,`panes[${i}].title`),placement:t.placement==="tab"?"tab":"split",command:asCommand(t.command,`panes[${i}].command`),platforms:asPlatforms(t.platforms,`panes[${i}].platforms`)}}),paneSeen=new Set;for(let p of panes){if(paneSeen.has(p.id))fail(`duplicate pane id \`${p.id}\``);paneSeen.add(p.id)}let events=asTableArray(raw.events,"events").flatMap((t,i)=>{let on=asString(t.on,`events[${i}].on`),hook={on,command:asCommand(t.command,`events[${i}].command`),platforms:asPlatforms(t.platforms,`events[${i}].platforms`),timeoutMs:asTimeoutMs(t.timeout_ms,`events[${i}].timeout_ms`)};if(!PLUGIN_EVENT_NAMES.includes(on))warnings.push(`unknown event \`${on}\`; this hook will never fire on this Rove version`);return[hook]}),settings=asTableArray(raw.settings,"settings").map((t,i)=>{let type=asString(t.type,`settings[${i}].type`);if(type!=="string"&&type!=="number"&&type!=="boolean"&&type!=="enum"&&type!=="secret")fail(`settings[${i}].type must be string | number | boolean | enum | secret`);let options=t.options===void 0?void 0:Array.isArray(t.options)&&t.options.every((o)=>typeof o==="string"&&o.length>0)?t.options:fail(`settings[${i}].options must be an array of strings`);if(type==="enum"&&(!options||options.length===0))fail(`settings[${i}] enum needs \`options\``);let settingDefault=asSettingDefault(t.default,`settings[${i}].default`),key=asString(t.key,`settings[${i}].key`),rejection=settingKeyRejection(key);if(rejection)fail(`settings[${i}].key ${rejection}`);return{key,label:asString(t.label,`settings[${i}].label`),type,...options?{options}:{},...settingDefault===void 0?{}:{default:settingDefault}}}),fileHandlers=asTableArray(raw.file_handlers,"file_handlers").map((t,i)=>{let pattern=asString(t.pattern,`file_handlers[${i}].pattern`);try{new RegExp(pattern)}catch{fail(`file_handlers[${i}].pattern is not a valid regex`)}let action=asString(t.action,`file_handlers[${i}].action`);if(!actions.some((a)=>a.id===action))fail(`file_handlers[${i}] names unknown action \`${action}\``);return{pattern,action}}),engines=asTableArray(raw.engines,"engines").map((t,i)=>{let engineId=asString(t.id,`engines[${i}].id`);if(!LOCAL_ID_RE.test(engineId))fail(`engine id \`${engineId}\` may not contain dots`);if(RESERVED_ENGINE_IDS.includes(engineId))fail(`engine id \`${engineId}\` shadows a built-in or shipped engine`);let rules=asTableArray(t.rules,`engines[${i}].rules`).map((r,j)=>{let state=asString(r.state,`engines[${i}].rules[${j}].state`);if(state!=="working"&&state!=="blocked"&&state!=="idle")fail(`engines[${i}].rules[${j}].state must be working | blocked | idle`);let lineRegex=asStringArray(r.line_regex,`engines[${i}].rules[${j}].line_regex`);for(let re of lineRegex??[])try{new RegExp(re)}catch{fail(`engines[${i}].rules[${j}].line_regex \`${re}\` is not a valid regex`)}let all=asStringArray(r.all,`engines[${i}].rules[${j}].all`),any=asStringArray(r.any,`engines[${i}].rules[${j}].any`);if(!all&&!any&&!lineRegex)fail(`engines[${i}].rules[${j}] needs at least one of all/any/line_regex`);return{state,...typeof r.bottom_lines==="number"?{bottomLines:r.bottom_lines}:{},...all?{all}:{},...any?{any}:{},...lineRegex?{lineRegex}:{}}}),identityRaw=t.identity,identity;if(identityRaw!==void 0){if(typeof identityRaw!=="object"||identityRaw===null||Array.isArray(identityRaw))fail(`engines[${i}].identity must be a table`);let idt=identityRaw,shortName=((key)=>idt[key]===void 0?void 0:asString(idt[key],`engines[${i}].identity.${key}`))("short_name");identity={...shortName!==void 0?{shortName}:{}}}let firstMessageDelivery;if(t.first_message_delivery!==void 0){let raw2=asString(t.first_message_delivery,`engines[${i}].first_message_delivery`);if(raw2!=="argv"&&raw2!=="paste")fail(`engines[${i}].first_message_delivery must be argv | paste`);firstMessageDelivery=raw2}return{id:engineId,name:asString(t.name,`engines[${i}].name`),command:asCommand(t.command,`engines[${i}].command`),...t.process_names===void 0?{}:{processNames:asCommand(t.process_names,`engines[${i}].process_names`)},rules,...identity?{identity}:{},...firstMessageDelivery?{firstMessageDelivery}:{}}}),engineSeen=new Set;for(let e of engines){if(engineSeen.has(e.id))fail(`duplicate engine id \`${e.id}\``);engineSeen.add(e.id)}return{manifest:{id,name,version,minRoveVersion,description,platforms,build,startup,shutdown,actions,events,panes,settings,fileHandlers,engines},warnings}}import{homedir}from"os";import{join as join2}from"path";function stateRoot(homeDir){let home=homeDir??readRoveHomeDirEnv()??homedir();return join2(home,ROVE_STATE_DIR_BASENAME)}function pluginRegistryPath(homeDir){return join2(stateRoot(homeDir),"plugins.json")}function pluginsRootDir(homeDir){return join2(stateRoot(homeDir),"plugins")}function legacyPluginsRootDir(homeDir){let home=homeDir??readRoveHomeDirEnv()??homedir();return join2(preRenameStateDir(home),"plugins")}function pluginDataDir(id,homeDir){return join2(pluginsRootDir(homeDir),id)}function pluginCheckoutDir(id,homeDir){return join2(pluginDataDir(id,homeDir),"checkout")}function pluginConfigDir(id,homeDir){return join2(pluginDataDir(id,homeDir),"config")}function pluginStateDir(id,homeDir){return join2(pluginDataDir(id,homeDir),"state")}function pluginLogPath(id,homeDir){return join2(pluginDataDir(id,homeDir),"log.jsonl")}function pluginsOutdatedCachePath(homeDir){return join2(stateRoot(homeDir),"plugins-outdated.json")}import{mkdirSync,readFileSync as readFileSync2,writeFileSync}from"fs";import{dirname,join as join3,relative}from"path";var EMPTY={plugins:[]};function loadPluginRegistry(homeDir){let text;try{text=readFileSync2(pluginRegistryPath(homeDir),"utf8")}catch{return EMPTY}try{let raw=JSON.parse(text);if(!Array.isArray(raw.plugins))return EMPTY;return{plugins:raw.plugins.filter(isEntry).map((entry)=>withCanonicalRoot(entry,homeDir))}}catch{return EMPTY}}function withCanonicalRoot(entry,homeDir){if(entry.source.kind!=="github")return entry;let legacy=legacyPluginsRootDir(homeDir),canonical=pluginsRootDir(homeDir);if(legacy===canonical)return entry;let inside=relative(legacy,entry.root);if(inside===""||inside.startsWith("..")||inside.startsWith("/"))return entry;return{...entry,root:join3(canonical,inside)}}function isEntry(v){if(typeof v!=="object"||v===null)return!1;let e=v,source=e.source;return typeof e.id==="string"&&typeof e.root==="string"&&typeof e.enabled==="boolean"&&typeof e.version==="string"&&typeof e.installedAt==="number"&&typeof source==="object"&&source!==null&&(source.kind==="link"||source.kind==="github"&&typeof source.spec==="string")}function savePluginRegistry(registry,homeDir){let path=pluginRegistryPath(homeDir);mkdirSync(dirname(path),{recursive:!0}),writeFileSync(path,`${JSON.stringify(registry,null,2)}
|
|
3
|
+
`,{mode:OWNER_ONLY_FILE_MODE})}function upsertPluginEntry(registry,entry){return{plugins:[...registry.plugins.filter((p)=>p.id!==entry.id),entry]}}function removePluginEntry(registry,id){return{plugins:registry.plugins.filter((p)=>p.id!==id)}}
|
|
4
|
+
export{PLUGIN_MANIFEST_FILENAMES,pluginManifestPath,readPluginManifest,qualifiedActionId,currentPluginPlatform,supportsPlatform,parsePluginManifest,pluginRegistryPath,pluginsRootDir,pluginDataDir,pluginCheckoutDir,pluginConfigDir,pluginStateDir,pluginLogPath,pluginsOutdatedCachePath,loadPluginRegistry,savePluginRegistry,upsertPluginEntry,removePluginEntry};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{getGlobalDefaultVendor,getRepoLastActiveVendor,resolvePreferredVendor,setGlobalDefaultVendor,setRepoLastActiveVendor}from"./chunk-xv8fhxxm.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.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-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{setRepoLastActiveVendor,setGlobalDefaultVendor,resolvePreferredVendor,getRepoLastActiveVendor,getGlobalDefaultVendor};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{spawnSync}from"child_process";import{platform}from"os";var defaultDeps={run(argv){let[cmd,...rest]=argv,proc=spawnSync(cmd??"",rest,{encoding:"utf8",shell:!1});return{stdout:proc.stdout??"",exitCode:proc.status??-1}},platform(){return platform()}},
|
|
2
|
+
import{spawnSync}from"child_process";import{platform}from"os";var defaultDeps={run(argv){let[cmd,...rest]=argv,proc=spawnSync(cmd??"",rest,{encoding:"utf8",shell:!1});return{stdout:proc.stdout??"",exitCode:proc.status??-1}},platform(){return platform()}},ROVE_KEYCHAIN_SERVICE="rove-remote-ssh";function remoteKeychainRef(host,user,port){return{service:ROVE_KEYCHAIN_SERVICE,account:port?`${user}@${host}:${port}`:`${user}@${host}`}}function isKeychainSupported(deps=defaultDeps){return deps.platform()==="darwin"}function setKeychainPassword(ref,password,deps=defaultDeps){if(deps.platform()!=="darwin")return!1;let{exitCode}=deps.run(["security","add-generic-password","-U","-s",ref.service,"-a",ref.account,"-w",password]);return exitCode===0}function getKeychainPassword(ref,deps=defaultDeps){if(deps.platform()!=="darwin")return null;let{stdout,exitCode}=deps.run(["security","find-generic-password","-s",ref.service,"-a",ref.account,"-w"]);if(exitCode!==0)return null;return stdout.replace(/\n$/,"")}function deleteKeychainPassword(ref,deps=defaultDeps){if(deps.platform()!=="darwin")return!1;let{exitCode}=deps.run(["security","delete-generic-password","-s",ref.service,"-a",ref.account]);return exitCode===0}
|
|
3
3
|
export{remoteKeychainRef,isKeychainSupported,setKeychainPassword,getKeychainPassword,deleteKeychainPassword};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{CATALOGS,DEFAULT_LOCALE,LOCALES}from"./chunk-
|
|
2
|
+
import{CATALOGS,DEFAULT_LOCALE,LOCALES}from"./chunk-zt49bbg9.js";import{createStateCell}from"./chunk-nhakrm1f.js";function lookup(catalog,key){let node=catalog;for(let part of key.split("."))if(node&&typeof node==="object"&&part in node)node=node[part];else return;return typeof node==="string"?node:void 0}function interpolate(template,params){if(!params)return template;return template.replace(/\{(\w+)\}/g,(whole,name)=>(name in params)?String(params[name]):whole)}function lookupKeys(catalog,group,key){return catalog.keys[group]?.[key]}var langState=createStateCell(DEFAULT_LOCALE);function setLocaleLang(lang){if(CATALOGS[lang])langState.set(lang)}function currentLang(){return langState.get()}function intlLocale(){return LOCALES.find((locale)=>locale.id===langState.get())?.intl??"en-US"}function localeState(){return langState}function t(key,params){let lang=langState.get(),resolved=lookup(CATALOGS[lang],key)??lookup(CATALOGS.en,key)??key;return interpolate(resolved,params)}function tKeys(group,key){let lang=langState.get();return lookupKeys(CATALOGS[lang],group,key)??lookupKeys(CATALOGS.en,group,key)??key}
|
|
3
3
|
export{setLocaleLang,currentLang,intlLocale,localeState,t,tKeys};
|
|
@@ -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-7cce0st1.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{protocolEntry}from"./chunk-
|
|
2
|
+
import{protocolEntry}from"./chunk-x9s14ppv.js";import{getPersistedString,getPersistedValue}from"./chunk-h9cg0j3a.js";import{acquireSync,releaseSync}from"./chunk-mw0ysrpd.js";import{secretsPath}from"./chunk-prqeddy7.js";function bottomRegion(captureText,lines){return captureText.split(`
|
|
3
3
|
`).filter((l)=>l.trim().length>0).slice(-lines)}function ruleMatches(rule,region){let haystack=region.join(`
|
|
4
4
|
`).toLowerCase();if(rule.all&&!rule.all.every((s)=>haystack.includes(s.toLowerCase())))return!1;if(rule.any&&!rule.any.some((s)=>haystack.includes(s.toLowerCase())))return!1;if(rule.lineRegex){let regexes=rule.lineRegex.map((r)=>new RegExp(r,"i"));if(!region.some((line)=>regexes.some((re)=>re.test(line))))return!1}return Boolean(rule.all||rule.any||rule.lineRegex)}function classifyScreen(manifest,captureText){for(let rule of manifest.rules){let region=bottomRegion(captureText,rule.bottomLines??12);if(region.length===0)continue;if(ruleMatches(rule,region))return rule.state}return null}var MAX_ERROR_ROWS=6;function screenErrorLine(errorLine,rows,opts={}){let filled=rows.flatMap((row,index)=>row.trim()?[index]:[]),window=filled.slice(-12);for(let k=window.length-1;k>=0;k--){let start=window[k];if(!errorLine.test(rows[start]??""))continue;let end=start+1;while(end<rows.length&&end-start<MAX_ERROR_ROWS&&rows[end]?.trim())end++;if(opts.last&&filled.some((index)=>index>=end))return;return rows.slice(start,end).map((row)=>row.trim()).join(" ")}return}var AUTO_ROUTING_TIERS=["swift","standard","deep"];function isAutoRoutingTier(value){return AUTO_ROUTING_TIERS.includes(value??"")}var DEFAULT_AUTO_ROUTING={swift:{engine:"claude",model:"sonnet"},standard:{engine:"claude",model:"opus"},deep:{engine:"claude",model:"fable"}};function autoRoutingKey(tier,field){return`autoRouting.${tier}.${field}`}function stringAt(get,key){let raw=get(key);return typeof raw==="string"?raw:void 0}function readAutoRoutingTable(get=getPersistedString){let table={};for(let tier of AUTO_ROUTING_TIERS){let base=DEFAULT_AUTO_ROUTING[tier],engine=stringAt(get,autoRoutingKey(tier,"engine"));if(engine!==void 0&&!engine.trim())return null;let model=stringAt(get,autoRoutingKey(tier,"model")),effort=stringAt(get,autoRoutingKey(tier,"effort")),resolvedModel=model===void 0?base.model:model.trim()||void 0,resolvedEffort=effort===void 0?base.effort:effort.trim()||void 0;table[tier]={engine:engine?.trim()||base.engine,...resolvedModel?{model:resolvedModel}:{},...resolvedEffort?{effort:resolvedEffort}:{}}}return table}function tierBlock(target,deps){let{engine}=target;if(!deps.engineIds.has(engine))return{kind:"engine",engine};if(deps.accountKind(engine)==="none")return{kind:"account",engine};let entry=protocolEntry(engine);if(target.model&&!entry.modelArgv)return{kind:"model",engine,model:target.model};if(target.effort){let levels=entry.effortLevels??[];if(!levels.includes(target.effort))return{kind:"effort",engine,effort:target.effort,levels}}return null}function describeTierBlock(block){switch(block.kind){case"engine":return`engine ${block.engine} is not one engine-list names`;case"account":return`engine ${block.engine} is not logged in`;case"model":return`engine ${block.engine} declares no model flag, so model ${JSON.stringify(block.model)} cannot be passed`;case"effort":return block.levels.length===0?`engine ${block.engine} declares no reasoning effort levels`:`engine ${block.engine} does not accept effort ${JSON.stringify(block.effort)} \u2014 it declares ${block.levels.join(", ")}`}}import{mkdirSync,readFileSync,readdirSync,renameSync,unlinkSync,writeFileSync}from"fs";import{basename,dirname,join}from"path";var HINT_TAIL=4;function readStored(path){let raw;try{raw=readFileSync(path,"utf8")}catch{return{}}try{let parsed=JSON.parse(raw);if(typeof parsed==="object"&&parsed!==null&&!Array.isArray(parsed))return parsed}catch{}return"corrupt"}function readAll(){let stored=readStored(secretsPath());if(stored==="corrupt")return{};let out={};for(let[k,v]of Object.entries(stored))if(typeof v==="string")out[k]=v;return out}function stagingPath(path){return`${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`}function sweepStagingFiles(path){let dir=dirname(path),prefix=`${basename(path)}.`,entries;try{entries=readdirSync(dir)}catch{return}for(let entry of entries){if(!entry.startsWith(prefix)||!entry.endsWith(".tmp"))continue;try{unlinkSync(join(dir,entry))}catch{}}}function transact(mutate){let path=secretsPath();mkdirSync(dirname(path),{recursive:!0,mode:448});let lockPath=`${path}.lock`,token=acquireSync(lockPath);try{sweepStagingFiles(path);let secrets=readStored(path);if(secrets==="corrupt")renameSync(path,`${path}.corrupt-${Date.now()}`),secrets={};if(mutate(secrets),Object.keys(secrets).length===0){try{unlinkSync(path)}catch(err){if(err?.code!=="ENOENT")throw err}return}let tmp=stagingPath(path);writeFileSync(tmp,JSON.stringify(secrets),{encoding:"utf8",mode:384}),renameSync(tmp,path)}finally{releaseSync(lockPath,token)}}function readSecret(name){let v=readAll()[name];return v?.trim()?v.trim():void 0}function resolveSecret(name,env=process.env){return env[name]?.trim()||readSecret(name)}function secretStatus(name,env=process.env){let stored=readAll()[name]?.trim(),hint=stored?secretHint(stored):"";if(env[name]?.trim())return{source:"env",hint};return{source:stored?"file":"none",hint}}function secretHint(value){let v=value.trim();return v.length<=HINT_TAIL?"\u2026":`\u2026${v.slice(-HINT_TAIL)}`}function writeSecret(name,value){transact((secrets)=>{let v=value.trim();if(v)secrets[name]=v;else delete secrets[name]})}var SUM_TOLERANCE=0.02,bad=(why)=>({ok:!1,why});function isRecord(v){return typeof v==="object"&&v!==null&&!Array.isArray(v)}function readConfidence(v){return typeof v==="number"&&Number.isFinite(v)&&v>=0&&v<=1?v:void 0}function readChoiceAnswer(answer){if(!isRecord(answer))return bad("answer is not an object");let choice=answer.choice;if(typeof choice!=="string"||!isAutoRoutingTier(choice))return bad(`choice ${JSON.stringify(choice)} is not one of the offered tiers`);let probs=answer.probabilities;if(!isRecord(probs))return bad("probabilities is not an object");let keys=Object.keys(probs).sort(),expected=[...AUTO_ROUTING_TIERS].sort();if(keys.length!==expected.length||keys.some((k,i)=>k!==expected[i]))return bad(`probabilities keys ${keys.join(",")} do not match the offered tiers`);let values={},sum=0;for(let tier of AUTO_ROUTING_TIERS){let p=probs[tier];if(typeof p!=="number"||!Number.isFinite(p)||p<0||p>1)return bad(`probability for ${tier} is not a number in [0,1]`);values[tier]=p,sum+=p}if(Math.abs(sum-1)>SUM_TOLERANCE)return bad(`probabilities sum to ${sum.toFixed(3)}`);for(let tier of AUTO_ROUTING_TIERS)if(values[tier]>values[choice])return bad(`choice ${choice} is not the most likely tier`);let confidence=readConfidence(answer.confidence);if(confidence===void 0)return bad("confidence is missing or out of range");return{ok:!0,value:{tier:choice,confidence,probabilities:values}}}function readJevAnswer(payload){if(!isRecord(payload))return bad("response is not an object");let answers=payload.answers;if(!isRecord(answers))return bad("response has no answers");return readChoiceAnswer(answers.verdict)}function readPlainAnswer(payload){if(!isRecord(payload))return bad("response is not an object");let tier=payload.tier;if(typeof tier!=="string"||!isAutoRoutingTier(tier))return bad(`tier ${JSON.stringify(tier)} is not one of ${AUTO_ROUTING_TIERS.join(", ")}`);let confidence=readConfidence(payload.confidence);if(confidence===void 0)return bad("confidence is missing or not a number in [0,1]");return{ok:!0,value:{tier,confidence}}}var DEFAULT_TIER_RUBRIC={role:"\u4F60\u5728\u7ED9\u4E00\u6761\u300C\u7528\u6237\u65B0\u5EFA coding task \u65F6\u5199\u7684\u7B2C\u4E00\u53E5\u8BDD\u300D\u6253\u6DF1\u5EA6\u6863\u3002",criterion:"\u53EA\u6709\u4E00\u4E2A\u5224\u636E\uFF1A\u7528\u6237\u7684\u6307\u4EE4\u91CC\uFF0C\u6709\u591A\u5C11\u6D41\u7A0B\u9700\u8981\u6A21\u578B\u81EA\u5DF1\u63A8\u7406\u51FA\u6765\u3002\u4E0D\u770B\u5DE5\u4F5C\u91CF\uFF0C\u4E0D\u770B\u96BE\u5EA6\uFF0C\u4E0D\u770B\u6587\u672C\u957F\u77ED\uFF0C\u4E0D\u770B\u8BED\u8A00\u3002\u4E09\u6863\u6CA1\u6709\u76EE\u6807\u6BD4\u4F8B\u3002",criteria:{swift:{what:`- \u8BF4\u4E86\u600E\u4E48\u505A\uFF1Astep-by-step\u3001\u6307\u5230\u4E86\u6587\u4EF6/\u914D\u7F6E/\u9009\u9879\u3001\u7ED9\u4E86\u53C2\u8003\u5B9E\u73B0\uFF08\u300C\u53C2\u8003 vuetify \u540C\u540D prop\u300D\u300C\u50CF fzf \u90A3\u6837\u300D\uFF09\u3002
|
|
5
5
|
- \u7528\u6237\u5DF2\u7ECF\u5B9A\u4F4D\u8FC7\u4E86\uFF1A\u300Cprofile \u4E86\u4E00\u4E0B\u53D1\u73B0\u662F X\uFF0C\u7F13\u5B58\u4E00\u4E0B\u5427\u300D\u2014\u2014\u539F\u56E0\u627E\u5230\u4E86\uFF0C\u5269\u4E0B\u7167\u505A\u3002
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{DEFAULT_BASE_REF_CANDIDATES}from"./chunk-
|
|
2
|
+
import{DEFAULT_BASE_REF_CANDIDATES}from"./chunk-kg9kmwt9.js";import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";var NONE={baseRef:null,ahead:null,behind:null,diff:null};function git(cwd,args){try{let out=spawnSync("git",[...args],{cwd,encoding:"utf8",stdio:["ignore","pipe","pipe"],env:readOnlyGitProcessEnv()});return out.status===0?out.stdout.trim():null}catch{return null}}function sharesHistory(worktreePath,ref){return git(worktreePath,["merge-base",ref,"HEAD"])!==null}function baseCheckoutBranch(worktreePath){let out=git(worktreePath,["worktree","list","--porcelain"]);if(!out)return null;let line=(out.split(`
|
|
3
3
|
|
|
4
4
|
`,1)[0]??"").split(`
|
|
5
5
|
`).find((l)=>l.startsWith("branch "));if(!line)return null;return line.slice(7).trim().replace(/^refs\/heads\//,"")||null}function resolveBaseRef(worktreePath){let head=git(worktreePath,["symbolic-ref","--short","refs/remotes/origin/HEAD"]);for(let guess of[...head?[head]:[],...DEFAULT_BASE_REF_CANDIDATES]){if(git(worktreePath,["rev-parse","--verify","--quiet",guess])===null)continue;if(sharesHistory(worktreePath,guess))return guess}let base=baseCheckoutBranch(worktreePath);return base&&sharesHistory(worktreePath,base)?base:null}function resolveMeasureBase(worktreePath,recordedBaseRef){if(recordedBaseRef&&git(worktreePath,["rev-parse","--verify","--quiet",recordedBaseRef])!==null)return recordedBaseRef;return resolveBaseRef(worktreePath)}function parseShortstat(text){let num=(re)=>{let m=text.match(re);return m?Number.parseInt(m[1]??"0",10):0};return{files:num(/(\d+) files? changed/),insertions:num(/(\d+) insertions?\(\+\)/),deletions:num(/(\d+) deletions?\(-\)/)}}function readBranchSignals(worktreePath,recordedBaseRef){if(!worktreePath)return NONE;let baseRef=resolveMeasureBase(worktreePath,recordedBaseRef);if(!baseRef)return NONE;let count=(range)=>{let out=git(worktreePath,["rev-list","--count",range]);if(out===null)return null;let n=Number.parseInt(out,10);return Number.isNaN(n)?null:n},ahead=count(`${baseRef}..HEAD`),behind=count(`HEAD..${baseRef}`),statOut=git(worktreePath,["diff","--shortstat",`${baseRef}...HEAD`]),diff=statOut===null?null:parseShortstat(statOut);return{baseRef,ahead,behind,diff}}export{resolveBaseRef,readBranchSignals,parseShortstat};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{ROVE_CONFIG_DIR_BASENAME,ROVE_STATE_DIR_BASENAME}from"./chunk-zt7wfnva.js";import{preRenameConfigDir,preRenameStateDir}from"./chunk-b39sdtt0.js";import{readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import{randomUUID}from"crypto";import{lstatSync,mkdirSync,readFileSync,readdirSync,renameSync,rmdirSync}from"fs";import{join}from"path";function stat(path){try{return lstatSync(path)}catch(error){if(error instanceof Error&&"code"in error&&error.code==="ENOENT")return;throw error}}function hasLiveOwner(pidPath){let entry=stat(pidPath);if(!entry||entry.isSymbolicLink())return!1;try{let pid=Number(readFileSync(pidPath,"utf8").trim());if(!Number.isSafeInteger(pid)||pid<=1)return!0;return process.kill(pid,0),!0}catch(error){return!(error instanceof Error&&("code"in error)&&error.code==="ESRCH")}}var PTY_ENTRIES=new Set(["pty.sock","pty.pid","pty.log","pty-exits.json","pty-sessions"]),ADDRESSES=new Set(["daemon.sock","daemon.pid","daemon.log","pty.sock","pty.pid","pty.log"]);function retirePreRenameLayout(home){let state=preRenameStateDir(home),config=preRenameConfigDir(home),canonical=join(home,".rove"),retained=[],warnings=[],retired=0;try{let daemonLive=hasLiveOwner(join(state,"daemon.pid")),ptyLive=hasLiveOwner(join(state,"pty.pid"));for(let[sourceRoot,targetRoot,group]of[[state,canonical,"state"],[config,join(home,".config","rove"),"config"]]){let rootStat=stat(sourceRoot);if(!rootStat)continue;if(!rootStat.isDirectory()||rootStat.isSymbolicLink()){retained.push(sourceRoot);continue}for(let name of readdirSync(sourceRoot)){let source=join(sourceRoot,name),entry=stat(source);if(!entry)continue;if(daemonLive||group==="state"&&(name==="worktrees"||ptyLive&&PTY_ENTRIES.has(name)&&!entry.isSymbolicLink())){retained.push(source);continue}try{let target=join(targetRoot,name);if(stat(target)||group==="state"&&ADDRESSES.has(name)){let archive=join(canonical,"migration-conflicts",group);mkdirSync(archive,{recursive:!0});let preferred=join(archive,name);renameSync(source,stat(preferred)?`${preferred}-${randomUUID()}`:preferred)}else mkdirSync(targetRoot,{recursive:!0}),renameSync(source,target);retired+=1}catch(error){warnings.push(`retire ${source}: ${error instanceof Error?error.message:String(error)}`)}}if(readdirSync(sourceRoot).length===0)rmdirSync(sourceRoot)}}catch(error){warnings.push(`state retirement: ${error instanceof Error?error.message:String(error)}`)}return{retired,retained,warnings}}import{randomUUID as randomUUID2}from"crypto";import{constants,chmodSync,closeSync,copyFileSync,fsyncSync,linkSync,lstatSync as lstatSync2,mkdirSync as mkdirSync2,openSync,readdirSync as readdirSync2,readlinkSync,renameSync as renameSync2,statSync,symlinkSync,unlinkSync,writeFileSync}from"fs";import{homedir}from"os";import{dirname,join as join2}from"path";var CLIENT_MIGRATION_MARKER=".layout-client-migration-v1",PLUGIN_MIGRATION_MARKER=".layout-plugins-migration-v1",DAEMON_MIGRATION_MARKER=".layout-daemon-migration-v1",CLIENT_STATE_ENTRIES=["attachments","settings","themes"],DAEMON_STATE_ENTRIES=["attention-inbox.json","automations.json","issue-assets","issues.json","notes","notes.json","tasks.json","worktree-init"];function errorText(err){return err instanceof Error?err.message:String(err)}function lstatIfExists(path){try{return lstatSync2(path)}catch(err){if(err.code==="ENOENT")return;throw err}}function removeTemp(path){try{unlinkSync(path)}catch(err){if(err.code!=="ENOENT")throw err}}function syncFile(path){let mode=statSync(path).mode,writable=(mode&128)!==0;if(!writable)chmodSync(path,mode|128);try{let handle=openSync(path,"r+");try{fsyncSync(handle)}finally{closeSync(handle)}}finally{if(!writable)chmodSync(path,mode)}}function publishTemp(temp,destination){try{return linkSync(temp,destination),!0}catch(err){if(err.code==="EEXIST")return!1;throw err}}function copyRegularFile(source,destination){let temp=`${destination}.migration-${process.pid}-${randomUUID2()}.tmp`;try{return copyFileSync(source,temp,constants.COPYFILE_EXCL),syncFile(temp),publishTemp(temp,destination)?1:0}finally{removeTemp(temp)}}function writeMarker(destination){let temp=`${destination}.migration-${process.pid}-${randomUUID2()}.tmp`;try{writeFileSync(temp,`legacy rove state copied without overwrite
|
|
3
|
+
`,{flag:"wx"}),syncFile(temp),publishTemp(temp,destination)}finally{removeTemp(temp)}}function copyMissing(source,destination){let sourceStat=lstatIfExists(source);if(!sourceStat)return 0;let destinationStat=lstatIfExists(destination);if(destinationStat){if(!sourceStat.isDirectory()||!destinationStat.isDirectory())return 0;let copied=0;for(let name of readdirSync2(source))copied+=copyMissing(join2(source,name),join2(destination,name));return copied}if(mkdirSync2(dirname(destination),{recursive:!0}),sourceStat.isDirectory()){mkdirSync2(destination,{recursive:!0,mode:sourceStat.mode});let copied=0;for(let name of readdirSync2(source))copied+=copyMissing(join2(source,name),join2(destination,name));return copied}if(sourceStat.isSymbolicLink())try{return symlinkSync(readlinkSync(source),destination),1}catch(err){if(err.code==="EEXIST")return 0;throw err}return copyRegularFile(source,destination)}function migrateStateEntries(entries,markerName,includeConfig,env){let home=readRoveHomeDirEnv(env)??homedir(),legacyState=preRenameStateDir(home),roveState=join2(home,ROVE_STATE_DIR_BASENAME),legacyConfig=join2(preRenameConfigDir(home),"state.json"),roveConfig=join2(home,".config",ROVE_CONFIG_DIR_BASENAME,"state.json"),marker=join2(roveState,markerName),hasSource;try{if(lstatIfExists(marker))return{attempted:!1,copied:0,warnings:[]};hasSource=Boolean(lstatIfExists(legacyState)||includeConfig&&lstatIfExists(legacyConfig))}catch(err){return{attempted:!0,copied:0,warnings:[`migration preflight: ${err instanceof Error?err.message:String(err)}`]}}if(!hasSource)return{attempted:!1,copied:0,warnings:[]};let copied=0,warnings=[];for(let name of entries)try{copied+=copyMissing(join2(legacyState,name),join2(roveState,name))}catch(err){warnings.push(`${name}: ${err instanceof Error?err.message:String(err)}`)}if(includeConfig)try{copied+=copyMissing(legacyConfig,roveConfig)}catch(err){warnings.push(`state.json: ${err instanceof Error?err.message:String(err)}`)}if(warnings.length===0){mkdirSync2(roveState,{recursive:!0});try{writeMarker(marker)}catch(err){warnings.push(`migration marker: ${err instanceof Error?err.message:String(err)}`)}}return{attempted:!0,copied,warnings}}var PLUGIN_ENTRIES=["plugins.json","plugins","plugins-outdated.json"];function migrateLegacyPluginTree(env){let home=readRoveHomeDirEnv(env)??homedir(),legacyState=preRenameStateDir(home),roveState=join2(home,ROVE_STATE_DIR_BASENAME),marker=join2(roveState,PLUGIN_MIGRATION_MARKER);try{if(lstatIfExists(marker))return{attempted:!1,copied:0,warnings:[]};if(!lstatIfExists(join2(legacyState,"plugins.json"))&&!lstatIfExists(join2(roveState,"plugins.json")))return{attempted:!1,copied:0,warnings:[]}}catch(err){return{attempted:!0,copied:0,warnings:[`plugin migration preflight: ${errorText(err)}`]}}mkdirSync2(roveState,{recursive:!0});let moved=0,warnings=[];for(let name of PLUGIN_ENTRIES){let source=join2(legacyState,name),destination=join2(roveState,name);try{if(!lstatIfExists(source)||lstatIfExists(destination))continue;renameSync2(source,destination),moved+=1}catch(err){warnings.push(`${name}: ${errorText(err)}`)}}if(warnings.length===0)try{writeMarker(marker)}catch(err){warnings.push(`plugin migration marker: ${errorText(err)}`)}return{attempted:!0,copied:moved,warnings}}function migrateRoveClientStateLayout(env=process.env){return migrateStateEntries(CLIENT_STATE_ENTRIES,CLIENT_MIGRATION_MARKER,!0,env)}function migrateRoveDaemonStateLayout(env=process.env){let state=migrateStateEntries(DAEMON_STATE_ENTRIES,DAEMON_MIGRATION_MARKER,!1,env),plugins=migrateLegacyPluginTree(env),retirement=state.warnings.length+plugins.warnings.length===0?retirePreRenameLayout(readRoveHomeDirEnv(env)??homedir()):{retired:0,warnings:[]};return{attempted:state.attempted||plugins.attempted||retirement.retired>0,copied:state.copied+plugins.copied,warnings:[...state.warnings,...plugins.warnings,...retirement.warnings]}}
|
|
4
|
+
export{DAEMON_MIGRATION_MARKER,migrateRoveClientStateLayout,migrateRoveDaemonStateLayout};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{__require}from"./chunk-wqfp8d9w.js";var welcomeWrite=Promise.resolve();function trackWelcomeWrite(write){welcomeWrite=write}async function launchTui(){let{startTui}=await import("./chunk-p6qr8sen.js");await startTui(),await welcomeWrite;let{runPendingWelcomeInstalls}=await import("./chunk-0n7w8t48.js");runPendingWelcomeInstalls()}
|
|
3
|
+
export{trackWelcomeWrite,launchTui};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{resolveLoginShell}from"./chunk-
|
|
2
|
+
import{resolveLoginShell}from"./chunk-vjvkkrzc.js";import{recommendedGlobalInstallCommand}from"./chunk-7cce0st1.js";function updaterShell(deps={}){let platform=deps.platform??process.platform;if(platform!=="win32")return"sh";return resolveLoginShell({fallback:"/bin/sh",platform,env:deps.env,exists:deps.exists})}function updaterShellFailureHint(deps={}){if((deps.platform??process.platform)!=="win32")return null;return["The update script is POSIX shell. Rove runs it through Git for Windows'","bash \u2014 the same shell every engine and terminal tab launches through.","Install Git for Windows (https://git-scm.com/download/win), or update","by hand:",` ${recommendedGlobalInstallCommand()}`,""].join(`
|
|
3
3
|
`)}
|
|
4
4
|
export{updaterShell,updaterShellFailureHint};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{canonicalize}from"./chunk-
|
|
2
|
+
import{canonicalize}from"./chunk-qvfdqrbf.js";import{applyJitter,exponentialBackoff}from"./chunk-2tfnscxk.js";import{getRemoteRepoConfig,isRemoteRepoKey,resolveRepoRoot}from"./chunk-h9cg0j3a.js";var canonPath=canonicalize;function randomDirTaskSuffix(){return Math.random().toString(36).slice(2,6).padEnd(4,"0")}function titleFromRepo(repo){let segs=repo.split(/[/\\]/).filter(Boolean);return segs.length>0?segs[segs.length-1]??repo:repo}function normalizeMainRepo(repo){let normalized=resolveRepoRoot(repo);return{repo:normalized,key:isRemoteRepoKey(normalized)?normalized:canonPath(normalized)}}function repoWorkingDir(repo){return getRemoteRepoConfig(repo)?.basePath??repo}var GH_PR_VIEW_FIELDS="number,url,title,state,baseRefName,reviewDecision,mergeable,statusCheckRollup";function lifecycleFromState(state,reviewDecision){switch((state??"").toUpperCase()){case"MERGED":return"merged";case"CLOSED":return"closed";case"OPEN":return(reviewDecision??"").toUpperCase()==="APPROVED"?"ready_to_merge":"open";default:return"unknown"}}function entryCheckState(entry){let status=(entry.status??"").toUpperCase(),conclusion=(entry.conclusion??"").toUpperCase(),contextState=(entry.state??"").toUpperCase();if(status&&status!=="COMPLETED")return"pending";if(conclusion){if(conclusion==="SUCCESS"||conclusion==="NEUTRAL"||conclusion==="SKIPPED")return"passing";return"failing"}if(contextState==="SUCCESS")return"passing";if(contextState==="PENDING"||contextState==="EXPECTED")return"pending";if(contextState==="FAILURE"||contextState==="ERROR")return"failing";return"unknown"}function checkStateFromRollup(rollup){if(!rollup||rollup.length===0)return"none";let sawPending=!1,sawUnknown=!1;for(let entry of rollup){let s=entryCheckState(entry);if(s==="failing")return"failing";if(s==="pending")sawPending=!0;else if(s==="unknown")sawUnknown=!0}if(sawPending)return"pending";if(sawUnknown)return"unknown";return"passing"}function mapGhPrView(view,at){if(!view||typeof view.number!=="number")return null;return{provider:"github",lifecycle:lifecycleFromState(view.state,view.reviewDecision),checkState:checkStateFromRollup(view.statusCheckRollup),number:view.number,url:view.url,title:view.title,baseRef:view.baseRefName,reviewDecision:view.reviewDecision||void 0,mergeable:view.mergeable||void 0,lastCheckedAt:at}}function samePrStatus(a,b){if(a===b)return!0;if(!a||!b)return!1;return a.provider===b.provider&&a.lifecycle===b.lifecycle&&a.checkState===b.checkState&&a.number===b.number&&a.url===b.url&&a.title===b.title&&a.baseRef===b.baseRef&&a.reviewDecision===b.reviewDecision&&a.mergeable===b.mergeable}var NO_REMOTE_PATTERNS=["none of the git remotes","no git remote","to use github cli in a github repository","not a github repository"],AUTH_PATTERNS=["gh auth login","authentication required","not logged in","http 401","bad credentials","requires authentication"],NETWORK_PATTERNS=["could not resolve host","no such host","dial tcp","connection refused","connection reset","network is unreachable","i/o timeout","timeout","tls handshake","http 5","rate limit","try again"];function matchesAny(haystack,needles){return needles.some((n)=>haystack.includes(n))}function classifyGhFailure(s){if(s.parseError)return{kind:"error",error:"parse"};if(s.timedOut)return{kind:"error",error:"timeout"};if(s.spawnError)return{kind:"error",error:"missing-binary"};let err=(s.stderr??"").toLowerCase();if(matchesAny(err,NO_REMOTE_PATTERNS))return{kind:"error",error:"no-remote"};if(matchesAny(err,AUTH_PATTERNS))return{kind:"error",error:"auth"};if(matchesAny(err,NETWORK_PATTERNS))return{kind:"error",error:"network"};return{kind:"error",error:"unknown"}}function nextPrPoll(outcome,prevFailures,now,cfg,rand=Math.random){let at=(delay)=>now+applyJitter(delay,cfg.jitterRatio,rand);if(outcome.kind==="pr")return{nextAllowedAt:at(outcome.settled?cfg.settledMs:cfg.tickMs),failures:0};if(outcome.kind==="empty")return{nextAllowedAt:at(cfg.noPrMs),failures:0};if(outcome.error==="no-remote")return{nextAllowedAt:at(cfg.noRemoteMs),failures:0};let failures=prevFailures+1;return{nextAllowedAt:at(exponentialBackoff(cfg.failureBaseMs,failures-1,cfg.failureCapMs)),failures}}function checkResolutionNotify(prev,next){if(prev!=="pending")return null;if(next==="passing"||next==="failing")return next;return null}
|
|
3
3
|
export{GH_PR_VIEW_FIELDS,mapGhPrView,samePrStatus,classifyGhFailure,nextPrPoll,checkResolutionNotify,canonPath,randomDirTaskSuffix,titleFromRepo,normalizeMainRepo,repoWorkingDir};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{expandTilde}from"./chunk-
|
|
2
|
+
import{expandTilde}from"./chunk-ag3txfg2.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-pn5ygqn6.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-wqfp8d9w.js";import{readFileSync}from"fs";import{resolve}from"path";var CLI_NAME=ROVE_PRODUCT_NAME,REPO_USAGE=[`Usage: ${CLI_NAME} repo <show|set|unset> [path] [options]`,"","Manage a repo's per-user init override (state.json fallback for repos","that don't ship .rove/init.sh / .rove/init-prompt.md).","","Commands:"," show [path] Print the override + repo convention files"," set [path] <options> Set the init script and/or first prompt"," unset [path] [--init-script] [--init-prompt] Clear one or both (default: both)","","Set options (later wins; *-file reads from disk):"," --init-script <text> Inline shell to run before the engine"," --init-script-file <path> Read the init script from a file"," --init-prompt <text> Inline first prompt for the engine"," --init-prompt-file <path> Read the first prompt from a file",""," path defaults to the current directory (resolved to its git toplevel).",""].join(`
|
|
3
3
|
`);function usageError(message){process.stderr.write(`${CLI_NAME} repo: ${message}
|
|
4
4
|
|
|
5
5
|
${REPO_USAGE}
|
|
6
6
|
`),process.exit(2)}function readArgFile(path){try{return readFileSync(resolve(process.cwd(),expandTilde(path)),"utf8")}catch(err){usageError(`cannot read ${path}: ${errorMessage(err)}`)}}function parseRepoArgs(args){let out={};for(let i=0;i<args.length;i++){let a=args[i],need=()=>{let v=args[++i];if(v===void 0)usageError(`${a} requires a value`);return v};if(a==="--init-script")out.initScript=need();else if(a==="--init-script-file")out.initScript=readArgFile(need());else if(a==="--init-prompt")out.initPrompt=need();else if(a==="--init-prompt-file")out.initPrompt=readArgFile(need());else if(a.startsWith("-"))usageError(`unknown flag "${a}"`);else if(out.path===void 0)out.path=a;else usageError(`unexpected argument "${a}"`)}return out}function parseUnsetArgs(args){let path,clearScript=!1,clearPrompt=!1;for(let a of args)if(a==="--init-script")clearScript=!0;else if(a==="--init-prompt")clearPrompt=!0;else if(a.startsWith("-"))usageError(`unknown flag "${a}"`);else if(path===void 0)path=a;else usageError(`unexpected argument "${a}"`);if(!clearScript&&!clearPrompt)clearScript=!0,clearPrompt=!0;return{path,clearScript,clearPrompt}}async function runRepoSubcommand(args){let[verb,...rest]=args;if(verb===void 0||verb==="--help"||verb==="-h"||verb==="help"){process.stdout.write(`${REPO_USAGE}
|
|
7
|
-
`);return}if(!SUBCOMMAND_VERBS.repo.includes(verb))usageError(`unknown verb "${verb}"`);let{getRepoInitOverride,setRepoInitOverride,resolveRepoRoot}=await import("./chunk-
|
|
7
|
+
`);return}if(!SUBCOMMAND_VERBS.repo.includes(verb))usageError(`unknown verb "${verb}"`);let{getRepoInitOverride,setRepoInitOverride,resolveRepoRoot}=await import("./chunk-ng12dprz.js");if(verb==="show"){let[pathArg]=rest.filter((a)=>!a.startsWith("-")),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(pathArg??"."))),override=getRepoInitOverride(repo),{describeRepoInitSources}=await import("./chunk-2andp9gs.js"),sources=describeRepoInitSources(repo);console.log(`repo: ${repo}`);for(let group of[sources.script,sources.prompt])group.forEach((source,index)=>{console.log(` ${`${source.rel}:`.padEnd(22)}${describeSource(group,index)}`)});console.log(` override initScript: ${override.initScript?quotePreview(override.initScript):"(unset)"}`),console.log(` override initPrompt: ${override.initPrompt?quotePreview(override.initPrompt):"(unset)"}`);return}if(verb==="set"){let flags=parseRepoArgs(rest);if(flags.initScript===void 0&&flags.initPrompt===void 0)usageError("set needs at least one of --init-script(-file) / --init-prompt(-file)");let repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(flags.path??"."))),next=setRepoInitOverride(repo,{...flags.initScript!==void 0?{initScript:flags.initScript}:{},...flags.initPrompt!==void 0?{initPrompt:flags.initPrompt}:{}});console.log(`updated override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}if(verb==="unset"){let{path,clearScript,clearPrompt}=parseUnsetArgs(rest),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(path??"."))),next=setRepoInitOverride(repo,{...clearScript?{initScript:""}:{},...clearPrompt?{initPrompt:""}:{}});console.log(`cleared override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}usageError(`unknown verb "${verb}"`)}function describeSource(group,index){let source=group[index];if(!source)return"absent";if(source.effective)return"present (wins)";if(!source.present)return"absent";return group.slice(0,index).some((earlier)=>earlier.effective)?"present (shadowed)":"present but empty (ignored)"}function quotePreview(value){let oneLine=value.replace(/\s+/g," ").trim();return oneLine.length>60?`"${oneLine.slice(0,57)}\u2026"`:`"${oneLine}"`}export{runRepoSubcommand};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{displayWidth}from"./chunk-dvcb6mk4.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";import{
|
|
2
|
+
import{displayWidth}from"./chunk-dvcb6mk4.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-wqfp8d9w.js";var CLI_NAME=ROVE_PRODUCT_NAME,EXPORT_USAGE=[`Usage: ${CLI_NAME} export [--json | --csv | --format <json|csv|table>]`,"","Print the task list (from ~/.rove/tasks.json) to stdout. Read-only and","daemon-free \u2014 works with the Rove daemon down.","","Options:"," --json JSON array of tasks (default)"," --csv CSV with a header row"," --format <fmt> One of: json, csv, table"," -h, --help Print this help",""].join(`
|
|
3
3
|
`),COLUMNS=["id","title","status","vendor","branch","repo","worktreePath"];function toRow(task){return{id:task.id,title:task.title,status:task.status,vendor:task.vendor??DEFAULT_TASK_VENDOR,branch:task.branch,repo:task.repo,worktreePath:task.worktreePath}}function usageError(message){process.stderr.write(`${CLI_NAME} export: ${message}
|
|
4
4
|
|
|
5
5
|
${EXPORT_USAGE}
|
|
6
6
|
`),process.exit(2)}function parseFormat(args){let format="json";for(let i=0;i<args.length;i++){let a=args[i];if(a==="--json")format="json";else if(a==="--csv")format="csv";else if(a==="--format"){let v=args[++i];if(v===void 0)usageError("--format requires a value (json, csv, or table)");format=coerceFormat(v)}else if(a.startsWith("--format="))format=coerceFormat(a.slice(9));else usageError(`unexpected argument "${a}"`)}return format}function coerceFormat(value){if(value==="json"||value==="csv"||value==="table")return value;usageError(`unknown format "${value}" (expected json, csv, or table)`)}function csvCell(value){if(/[",\r\n]/.test(value))return`"${value.replace(/"/g,'""')}"`;return value}function renderCsv(rows){let lines=[COLUMNS.join(",")];for(let row of rows)lines.push(COLUMNS.map((c)=>csvCell(row[c])).join(","));return lines.join(`
|
|
7
7
|
`)}function padCell(cell,width){return cell+" ".repeat(Math.max(0,width-displayWidth(cell)))}function renderTable(rows){let widths={};for(let c of COLUMNS)widths[c]=Math.max(displayWidth(c),...rows.map((r)=>displayWidth(r[c])));let line=(cells)=>COLUMNS.map((c)=>padCell(cells[c],widths[c])).join(" ").trimEnd(),header={};for(let c of COLUMNS)header[c]=c;return[line(header),...rows.map(line)].join(`
|
|
8
8
|
`)}function renderExport(tasks,format){let rows=tasks.map(toRow);if(format==="json")return JSON.stringify(rows,null,2);if(format==="csv")return renderCsv(rows);return renderTable(rows)}async function runExportSubcommand(args){if(args.includes("--help")||args.includes("-h")||args.includes("help")){process.stdout.write(`${EXPORT_USAGE}
|
|
9
|
-
`);return}let format=parseFormat(args),{TaskIndexStore}=await import("./chunk-
|
|
9
|
+
`);return}let format=parseFormat(args),{TaskIndexStore}=await import("./chunk-pe6wnsww.js"),store=new TaskIndexStore;await store.load();let tasks=store.list();if(tasks.length===0&&format==="table"){process.stdout.write(`no tasks
|
|
10
10
|
`);return}process.stdout.write(`${renderExport(tasks,format)}
|
|
11
11
|
`)}export{runExportSubcommand,renderExport};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{stripTerminalControls,terminalRows}from"./chunk-etfh8f4z.js";import{OWNER_ONLY_FILE_MODE}from"./chunk-yt15y085.js";import{defaultPtyExitsPath}from"./chunk-npwzmmv9.js";import{randomUUID}from"crypto";import{mkdirSync,readFileSync,renameSync,writeFileSync}from"fs";import{dirname}from"path";var MAX_RECORDS=50,TAIL_LINES=40,TAIL_LINE_CHARS=500;function plainTail(raw){let lines=terminalRows(raw,TAIL_LINE_CHARS);while(lines.length>0&&(lines[lines.length-1]??"").trim()==="")lines.pop();return lines.slice(-TAIL_LINES)}function engineExitCodeFromTail(tail){for(let i=tail.length-1;i>=0;i--){let m=ENGINE_EXIT_BANNER.exec(tail[i]??"");if(m?.[1])return Number.parseInt(m[1],10)}return null}var ENGINE_EXIT_BANNER=/Engine exited \(code (\d+)\)/;function healTails(records){let out={};for(let[key,record]of Object.entries(records)){let tail=record?.tail;out[key]=Array.isArray(tail)?{...record,tail:tail.map((line)=>stripTerminalControls(String(line)))}:record}return out}function compareByExitAtDesc(a,b){if(a.at===b.at)return 0;return a.at<b.at?1:-1}function readPtyExitStore(path=defaultPtyExitsPath()){let read=(status,records={})=>({records,status,readable:status==="ok"||status==="absent"}),raw;try{raw=readFileSync(path,"utf8")}catch(err){return read(err.code==="ENOENT"?"absent":"unreadable")}try{let parsed=JSON.parse(raw);if(parsed===null||typeof parsed!=="object"||Array.isArray(parsed))return read("unparsable");return read("ok",healTails(parsed))}catch{return read("unparsable")}}function readPtyExitRecords(path=defaultPtyExitsPath()){return readPtyExitStore(path).records}function recordPtyExit(info,path=defaultPtyExitsPath()){if(info.key.startsWith("::"))return;if(info.exit.code===0&&info.exit.signal===null)return;let tail=plainTail(info.tail);writeRecord(info.key,{key:info.key,pid:info.pid,code:info.exit.code??engineExitCodeFromTail(tail),signal:info.exit.signal,at:info.exit.at,tail,layer:"pty"},path)}function recordEngineExit(info,path=defaultPtyExitsPath()){if(info.key.startsWith("::"))return;let tail=plainTail(info.tail);writeRecord(`${info.key}#engine`,{key:info.key,pid:info.pid,code:engineExitCodeFromTail(tail),signal:null,at:info.at,tail,layer:"engine",...info.vendor?{vendor:info.vendor}:{},...info.atApproximate?{atApproximate:!0}:{},parentAlive:!0},path)}function writeRecord(storeKey,record,path){let store=readPtyExitStore(path);if(store.status==="unreadable")throw Error(`pty-exits store is unreadable (${path}) \u2014 refusing to overwrite it`);let records=store.records;records[storeKey]=record;let newest=Object.entries(records).sort(([,a],[,b])=>compareByExitAtDesc(a,b)).slice(0,MAX_RECORDS);mkdirSync(dirname(path),{recursive:!0});let tmp=`${path}.tmp-${process.pid}-${randomUUID()}`;writeFileSync(tmp,JSON.stringify(Object.fromEntries(newest),null,2),{encoding:"utf8",mode:OWNER_ONLY_FILE_MODE}),renameSync(tmp,path)}
|
|
3
|
+
export{plainTail,engineExitCodeFromTail,ENGINE_EXIT_BANNER,compareByExitAtDesc,readPtyExitStore,readPtyExitRecords,recordPtyExit,recordEngineExit};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{writeOutdatedCache}from"./chunk-atmaakwp.js";import{PluginCliError,installPlugin}from"./chunk-cmcn8e8x.js";import{loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginDataDir,pluginStateDir,removePluginEntry,savePluginRegistry}from"./chunk-rqyaf0dw.js";import"./chunk-w7zv47mp.js";import"./chunk-7cce0st1.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-0422g8ac.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";import{execFileSync}from"child_process";import{existsSync,mkdirSync,readdirSync,renameSync}from"fs";import{join}from"path";function gitOut(args,cwd){try{return execFileSync("git",args,{cwd,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return null}}function checkEntry(entry){let repoSpec=entry.source.spec.split("/").slice(0,2).join("/"),localSha=gitOut(["rev-parse","HEAD"],pluginCheckoutDir(entry.id)),remote=gitOut(["ls-remote",`https://github.com/${repoSpec}.git`,"HEAD"]),remoteSha=remote?remote.split(/\s+/)[0]??null:null;return{id:entry.id,spec:entry.source.spec,version:entry.version,localSha,remoteSha,behind:Boolean(localSha&&remoteSha&&localSha!==remoteSha)}}function listOutdated(){let rows=loadPluginRegistry().plugins.filter((p)=>p.source.kind==="github").map(checkEntry);return writeOutdatedCache(rows.filter((r)=>r.behind).map((r)=>r.id)),rows}function printOutdated(){let rows=listOutdated();if(rows.length===0){console.log("no GitHub-installed plugins.");return}for(let r of rows){let status=r.behind?"update available":r.remoteSha===null?"remote unreachable":r.localSha===null?"local sha unreadable":"up to date";console.log(`${r.id} v${r.version} ${status}`)}}function migrateRenamedPlugin(oldId,newId){for(let dirOf of[pluginConfigDir,pluginStateDir]){let from=dirOf(oldId),to=dirOf(newId);if(!existsSync(from))continue;mkdirSync(to,{recursive:!0});for(let entry of readdirSync(from)){if(existsSync(join(to,entry)))continue;renameSync(join(from,entry),join(to,entry))}}savePluginRegistry(removePluginEntry(loadPluginRegistry(),oldId)),console.log(`renamed ${oldId} \u2192 ${newId}: settings and state carried over, old entry unregistered`),console.log(` leftover checkout (safe to remove): ${pluginDataDir(oldId)}`)}async function updatePlugins(ids,opts){let rows=listOutdated(),targets;if(opts.all){if(targets=rows.filter((r)=>r.behind),targets.length===0){console.log("all plugins up to date.");return}}else{if(ids.length===0)throw new PluginCliError("update takes plugin ids or --all");targets=ids.map((id)=>{let row=rows.find((r)=>r.id===id);if(!row)throw new PluginCliError(`\`${id}\` is not a GitHub-installed plugin; see \`${ROVE_PRODUCT_NAME} plugin list\``);return row})}for(let target of targets){if(!target.behind&&!ids.includes(target.id))continue;console.log(`updating ${target.id} (${target.spec})\u2026`);let installedId=await installPlugin(target.spec,{yes:opts.yes});if(installedId!==target.id)migrateRenamedPlugin(target.id,installedId)}listOutdated()}export{updatePlugins,printOutdated};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{defaultDaemonLogPath,defaultPtyHostLogPath}from"./chunk-
|
|
2
|
+
import{defaultDaemonLogPath,defaultPtyHostLogPath}from"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";import{mkdirSync,readFileSync,writeFileSync}from"fs";import{dirname,join}from"path";var REPORT_ENV_SUFFIXES=["HOME_DIR","DAEMON_SOCKET_PATH","SOCKET_PATH","PTY_SOCKET_PATH","PTY_PORT","WEB_HOST","BIN_PATH","DEV","DEBUG","TERMINAL_BACKEND","TASK_ID","TAB_ID"],REPORT_ENV_KEYS=["SHELL","TERM","TERM_PROGRAM","TERM_PROGRAM_VERSION","COLORTERM","VISUAL","EDITOR",...REPORT_ENV_SUFFIXES.flatMap((suffix)=>[`ROVE_${suffix}`,`ROVE_${suffix}`]),"ROVE_INVOKED_AS"],LOG_TAIL_LINES=200;function logTail(path,count){try{return readFileSync(path,"utf8").split(`
|
|
3
3
|
`).filter((line)=>line.trim().length>0).slice(-count).join(`
|
|
4
|
-
`)}catch{return""}}function reportEnvLines(env){let shown=new Set(REPORT_ENV_KEYS),keys=new Set(shown);for(let key of Object.keys(env))if(key.startsWith("ROVE_")||key.startsWith("
|
|
4
|
+
`)}catch{return""}}function reportEnvLines(env){let shown=new Set(REPORT_ENV_KEYS),keys=new Set(shown);for(let key of Object.keys(env))if(key.startsWith("ROVE_")||key.startsWith("ROVE_"))keys.add(key);return[...keys].sort().map((key)=>{let value=env[key];if(value===void 0)return`${key}=(unset)`;return shown.has(key)?`${key}=${value}`:`${key}=(set)`})}function buildReportBundle(doctorLines,parts){return["# Rove doctor report",`generated: ${parts.generatedAt}`,"","## diagnosis",...doctorLines,"","## environment",...reportEnvLines(parts.env),"",`## daemon.log (last ${LOG_TAIL_LINES} lines)`,parts.daemonLog||"(empty or absent)","",`## pty.log (last ${LOG_TAIL_LINES} lines)`,parts.ptyLog||"(empty or absent)",""].join(`
|
|
5
5
|
`)}function writeReportBundle(doctorLines){let dir=dirname(defaultDaemonLogPath());mkdirSync(dir,{recursive:!0});let path=join(dir,"rove-doctor-report.txt");return writeFileSync(path,buildReportBundle(doctorLines,{generatedAt:new Date().toISOString(),env:process.env,daemonLog:logTail(defaultDaemonLogPath(),LOG_TAIL_LINES),ptyLog:logTail(defaultPtyHostLogPath(),LOG_TAIL_LINES)})),path}export{writeReportBundle,reportEnvLines,buildReportBundle};
|