@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
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-t3wwsz29.js";import{GitWorktreeManager,defaultExecDeps,isDirtyOutput,parseDirtyPaths}from"./chunk-gmgsxdrf.js";import{readLastActiveTaskId,writeLastActiveTaskId}from"./chunk-2cwb64fj.js";import{PLACEHOLDER_TASK_TITLE,isPlaceholderDerivedBranch,sanitizeTaskTitle}from"./chunk-ch0ehc06.js";import{CannotDeleteMainTaskError,DirtyWorktreeError,EmptyBranchDirtyWorktreeError,EmptyBranchError,GitCommandFailedError,IllegalTransitionError,InvalidWorktreeNameError,LandConflictError,MainCheckoutDirtyError,MissingRefError,TaskDeletingError,TaskNotFoundError,WorktreeNameTakenError,WorktreeRemoveFailedError,canonicalize,listWorktreeDirNames}from"./chunk-mppda1wq.js";import{detectLanguage}from"./chunk-hape5vwj.js";import{resolvePreferredVendor}from"./chunk-dq2mh3b3.js";import{READ_ONLY_GIT_ENV}from"./chunk-6xppe9bj.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";import{addSavedRepo,getSavedRepos,isGitRepo,removeSavedRepo,resolveRepoRoot}from"./chunk-32mv1yy6.js";import{projectRejection,rejectionReason}from"./chunk-mkksdcsw.js";import{createStateCell}from"./chunk-nhakrm1f.js";import{pathIdentity,pathWithin,samePath}from"./chunk-f10n6063.js";async function createTaskRow(deps,input){if(!input.repo)throw Error("createTask: repo is required");let repo=(await deps.mainTasks.ensureIfEligible(input.repo,input.projectIntent??"explicit"))?.repo??normalizeMainRepo(input.repo).repo,title=sanitizeTaskTitle(input.title??PLACEHOLDER_TASK_TITLE)||PLACEHOLDER_TASK_TITLE,worktreeName=input.worktreeName?.trim();if(worktreeName)await deps.claimWorktreeName(repo,worktreeName);return await deps.store.create({repo,title,branch:input.branch??"",worktreePath:"",status:"backlog",kind:"task",vendor:input.vendor??DEFAULT_TASK_VENDOR,...input.command?.trim()?{command:input.command.trim()}:{},...input.modelEffort?{modelEffort:input.modelEffort}:{},...input.model?.trim()?{model:input.model.trim()}:{},...input.tier?.trim()?{tier:input.tier.trim()}:{},...input.groupId?{groupId:input.groupId}:{},...input.dispatcher?{dispatcher:input.dispatcher}:{},...input.routine?{routine:input.routine}:{},...input.baseRef?.trim()?{baseRef:input.baseRef.trim()}:{},...worktreeName?{worktreeName}:{}})}async function openDirectoryTaskRow(deps,input){if(!input.dir)throw Error("openDirectoryTask: dir is required");let dir=canonPath(input.dir);return deps.store.create({repo:dir,title:input.scratch?"":`${titleFromRepo(dir)}-${randomDirTaskSuffix()}`,branch:"",worktreePath:dir,status:"backlog",kind:"dir",...input.scratch?{scratch:!0}:{},vendor:input.vendor??resolvePreferredVendor()})}async function adoptScratchRepoRow(deps,id,repo){let task=deps.store.get(id);if(!task||task.kind!=="dir"||task.scratch!==!0)return;let dir=canonPath(repo);await deps.store.update(id,{repo:dir,worktreePath:dir,scratch:!1,title:titleFromRepo(dir)})}function baseRepoCtx(repo,deps){let basePath=deps.remoteBasePath(repo);return{exec:deps.execForRepo(repo),dir:basePath??repo}}async function landGit(exec,dir,args,opts){let r=await exec.run(["git",...args],{cwd:dir,env:opts?.readOnly?READ_ONLY_GIT_ENV:void 0});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}async function isDirty(exec,dir){return isDirtyOutput((await landGit(exec,dir,["status","--porcelain"],{readOnly:!0})).stdout)}async function landPreflight(task,deps=defaultExecDeps){let refuse=(pf,refusal)=>{let refused={...pf,refusal};return{...refused,message:landRefusalError(task,refused).message}},branch=task.branch.trim();if(!branch)throw Error(`landPreflight: task ${task.id} has no branch to land (never materialised)`);let{exec,dir}=baseRepoCtx(task.repo,deps),headOut=await landGit(exec,dir,["symbolic-ref","--short","HEAD"],{readOnly:!0}),landedOn=headOut.stdout.trim();if(headOut.exitCode!==0||!landedOn){let headCommit=await landGit(exec,dir,["rev-parse","--verify","--quiet","HEAD"],{readOnly:!0}),detached=headCommit.exitCode===0&&headCommit.stdout.trim().length>0;return refuse({branch,landedOn:"",baseDir:dir},detached?"DETACHED_HEAD":"UNREADABLE_BASE")}if(landedOn===branch)return refuse({branch,landedOn,baseDir:dir},"SAME_BRANCH");let baseDirty=await isDirty(exec,dir),aheadOut=await landGit(exec,dir,["rev-list","--count",`${landedOn}..${branch}`],{readOnly:!0});if(aheadOut.exitCode!==0){let baseHead=await landGit(exec,dir,["rev-parse","--verify","--quiet","HEAD"],{readOnly:!0});if(baseHead.exitCode!==0||!baseHead.stdout.trim())return refuse({branch,landedOn,baseDirty,baseDir:dir},"UNBORN_BASE");return refuse({branch,landedOn,baseDirty,baseDir:dir},baseDirty?"MAIN_CHECKOUT_DIRTY":"MISSING_REF")}let parsed=Number.parseInt(aheadOut.stdout.trim(),10),base={branch,landedOn,baseDirty,baseDir:dir,...Number.isFinite(parsed)?{ahead:parsed}:{}};if(baseDirty)return refuse(base,"MAIN_CHECKOUT_DIRTY");if(base.ahead!==0)return base;let worktreePath=task.worktreePath.trim();if(worktreePath){let manager=new GitWorktreeManager(deps),dirty=!1;try{dirty=await manager.isDirty(worktreePath)}catch{dirty=!1}if(dirty){let wtExec=deps.execForPath(worktreePath),files=parseDirtyPaths((await landGit(wtExec,worktreePath,["status","--porcelain"],{readOnly:!0})).stdout);return refuse({...base,dirtyFiles:files},"EMPTY_BRANCH_DIRTY_WORKTREE")}}return refuse(base,"EMPTY_BRANCH")}function landRefusalError(task,pf){switch(pf.refusal){case"DETACHED_HEAD":return Error(`landTask: base checkout at ${pf.baseDir} is in detached-HEAD state; check out a branch first`);case"UNREADABLE_BASE":return Error(`landTask: could not read HEAD of the base checkout at ${pf.baseDir} \u2014 is it still a git repo?`);case"UNBORN_BASE":return Error(`landTask: base checkout at ${pf.baseDir} is on '${pf.landedOn}' but has no commits yet, so there is nothing to merge '${pf.branch}' into; make the first commit there (or \`git merge --ff-only ${pf.branch}\`) and land again`);case"SAME_BRANCH":return Error(`landTask: base checkout is already on '${pf.branch}' \u2014 nothing to land onto`);case"MAIN_CHECKOUT_DIRTY":return new MainCheckoutDirtyError(task.repo,pf.baseDir);case"MISSING_REF":return new MissingRefError(pf.branch,pf.landedOn,pf.baseDir);case"EMPTY_BRANCH_DIRTY_WORKTREE":return new EmptyBranchDirtyWorktreeError(pf.branch,pf.landedOn,task.worktreePath.trim(),[...pf.dirtyFiles??[]]);case"EMPTY_BRANCH":return new EmptyBranchError(pf.branch,pf.landedOn)}}async function landTaskWithCleanup(task,opts,deps){if(task.kind==="main")throw Error("landTask: a main task has no branch to land");if(task.kind==="dir")throw Error("landTask: a directory task has no Rove-managed branch to land");let result=await landTask(task,{strategy:opts.strategy}),worktree=opts.removeWorktree===!1?void 0:await removeLandedWorktree(task,opts.callerCwd,deps),branchAnchor=null,branchKept,worktreeGone=!task.worktreePath.trim()||worktree?.removed===!0;if(opts.deleteBranch&&!worktreeGone)branchKept={reason:worktree?.reason??`worktree ${task.worktreePath} was kept, and still has the branch checked out`};else if(opts.deleteBranch){let outcome=await deps.worktrees.deleteBranch(task.repo,result.branch,{force:!0,onAnchor:(record)=>{branchAnchor=record}});if(!outcome.deleted)branchKept={reason:outcome.reason}}return{...result,...worktree?{worktree}:{},...branchAnchor?{branchAnchor}:{},...branchKept?{branchKept}:{}}}async function removeLandedWorktree(task,callerCwd,deps){let worktreePath=task.worktreePath.trim();if(!worktreePath)return{removed:!1,reason:"task has no worktree on disk (never materialised)"};let wt=canonicalize(worktreePath);if(samePath(wt,canonicalize(task.repo)))return{removed:!1,reason:"refusing to remove the base checkout"};if(callerCwd){if(pathWithin(wt,canonicalize(callerCwd))!==null)return{removed:!1,reason:`refusing to remove the caller's own worktree (${worktreePath}) \u2014 re-run from outside it`}}if(deps.tearDownSession)try{await deps.tearDownSession(task.id)}catch{}let residue;try{await deps.worktrees.remove(worktreePath,{onResidue:(r)=>{residue=r}})}catch(err){return{removed:!1,reason:errText(err)}}try{await deps.clearWorktreePath(task.id)}catch(err){return{removed:!0,reason:`worktree removed, but clearing the task's worktree path failed: ${errText(err)}`,...residue?{residue}:{}}}return{removed:!0,...residue?{residue}:{}}}function errText(err){return err instanceof Error?err.message:String(err)}async function conflictedFiles(exec,dir){return(await landGit(exec,dir,["diff","--name-only","--diff-filter=U"],{readOnly:!0})).stdout.split(`
|
|
3
|
-
`).map((l)=>l.trim()).filter((l)=>l.length>0)}async function landTask(task,input={},deps=defaultExecDeps){let strategy=input.strategy??"merge",preflight=await landPreflight(task,deps);if(preflight.refusal)throw landRefusalError(task,{...preflight,refusal:preflight.refusal});let{branch,landedOn}=preflight,{exec,dir}=baseRepoCtx(task.repo,deps);if(strategy==="squash"){if((await landGit(exec,dir,["merge","--squash",branch])).exitCode!==0){let files=await conflictedFiles(exec,dir);throw await landGit(exec,dir,["merge","--abort"]).catch(()=>{}),await landGit(exec,dir,["reset","--hard","HEAD"]).catch(()=>{}),new LandConflictError(task.id,branch,files)}let commit=await landGit(exec,dir,["commit","--no-edit","-m",`Land ${branch} (squash)`]);if(commit.exitCode!==0){if((await landGit(exec,dir,["diff","--cached","--quiet"],{readOnly:!0})).exitCode===0)throw await landGit(exec,dir,["reset","--hard","HEAD"]).catch(()=>{}),Error(`landTask: '${branch}' has nothing to land onto '${landedOn}' (already merged or empty)`);throw new GitCommandFailedError(`commit (squash-landing '${branch}' onto '${landedOn}')`,commit.stderr,"the squashed merge is left STAGED in the base checkout \u2014 fix the cause and `git commit` it, or `git reset --hard HEAD` to discard")}}else{let before=(await landGit(exec,dir,["rev-parse","HEAD"],{readOnly:!0})).stdout.trim(),merge=await landGit(exec,dir,["merge","--no-ff","-m",`Land ${branch}`,branch]);if(merge.exitCode!==0){let files=await conflictedFiles(exec,dir);if(await landGit(exec,dir,["merge","--abort"]).catch(()=>{}),files.length===0)throw new GitCommandFailedError(`merge --no-ff (landing '${branch}' onto '${landedOn}')`,merge.stderr,"the merge was aborted, so the base checkout is unchanged");throw new LandConflictError(task.id,branch,files)}let after=(await landGit(exec,dir,["rev-parse","HEAD"],{readOnly:!0})).stdout.trim();if(before===after)throw Error(`landTask: '${branch}' has nothing to land onto '${landedOn}' (already merged or empty)`)}let shaOut=await landGit(exec,dir,["rev-parse","--short","HEAD"],{readOnly:!0});return{branch,strategy,landedOn,commit:shaOut.stdout.trim()}}class MainTaskCoordinator{store;forgetWorktree;locks=new Map;constructor(store,forgetWorktree){this.store=store;this.forgetWorktree=forgetWorktree}async ensure(repo){let task=await this.ensureIfEligible(repo,"explicit");if(task)return task;let{repo:normalizedRepo}=normalizeMainRepo(repo),rejected=projectRejection(normalizedRepo,isGitRepo,"explicit")??"notGitRepo";throw Error(`cannot add ${normalizedRepo} as a project: ${rejectionReason(rejected)}`)}async ensureIfEligible(repo,intent="derived"){let{repo:normalizedRepo,key}=normalizeMainRepo(repo),onThisRoot=(task)=>normalizeMainRepo(task.repo).key===key,existing=this.store.list().find((task)=>task.kind==="main"&&onThisRoot(task));if(existing)return existing;if(projectRejection(normalizedRepo,isGitRepo,intent))return null;let inflight=this.locks.get(key);if(inflight)return inflight;let promise=(async()=>{addSavedRepo(normalizedRepo,{intent:"explicit"});let adoptable=this.store.list().find((task)=>task.kind==="dir"&&task.scratch!==!0&&onThisRoot(task));if(adoptable)return await this.store.update(adoptable.id,this.mainShape(normalizedRepo));return await this.store.create({...this.mainShape(normalizedRepo),status:"backlog",vendor:resolvePreferredVendor(normalizedRepo)})})();this.locks.set(key,promise);try{return await promise}finally{this.locks.delete(key)}}mainShape(normalizedRepo){return{kind:"main",title:titleFromRepo(normalizedRepo),repo:normalizedRepo,branch:"",worktreePath:repoWorkingDir(normalizedRepo)}}async forget(repo){if(!repo)throw Error("forgetProject: repo is required");let key=normalizeMainRepo(repo).key;for(let saved of getSavedRepos())if(normalizeMainRepo(saved).key===key)removeSavedRepo(saved);for(let task of this.store.list()){if(task.kind!=="main")continue;if(normalizeMainRepo(task.repo).key!==key)continue;await this.store.remove(task.id),this.forgetWorktree(task.id)}}}function promotableDirTasks(deps){let claimed=new Set(deps.tasks.filter((task)=>task.kind==="main").map((task)=>pathIdentity(task.repo))),seen=new Set,out=[];for(let task of deps.tasks){if(task.kind!=="dir"||task.scratch===!0)continue;let path=task.repo,key=pathIdentity(path);if(!path||claimed.has(key)||seen.has(key))continue;if(!deps.isRepoRoot(path))continue;seen.add(key),out.push(task)}return out}class TaskDeletionCoordinator{store;worktrees;forgetTask;onSalvage;onResidue;onBranchKept;constructor(store,worktrees,forgetTask,onSalvage,onResidue,onBranchKept){this.store=store;this.worktrees=worktrees;this.forgetTask=forgetTask;this.onSalvage=onSalvage;this.onResidue=onResidue;this.onBranchKept=onBranchKept}async prepare(id,opts){let task=this.store.get(id);if(!task)return!1;if(task.kind==="main")throw new CannotDeleteMainTaskError;if(task.deletion?.phase==="queued"||task.deletion?.phase==="running")return!0;let force=opts?.force===!0;if(task.worktreePath&&!force&&task.kind!=="dir"){let dirty=!1,ignored=[],probed=!0;try{dirty=await this.worktrees.isDirty(task.worktreePath)}catch{probed=!1}if(probed&&!dirty)ignored=await this.worktrees.ignoredWork(task.worktreePath);if(dirty||ignored==="unknown"||ignored.length>0)throw new DirtyWorktreeError(task.id,ignored)}return await this.store.update(task.id,{deletion:{phase:"queued",force,deleteBranch:opts?.deleteBranch===!0,requestedAt:new Date().toISOString()}}),!0}async begin(id){let task=this.store.get(id);if(!task||!task.deletion||task.deletion.phase==="error")return!1;if(task.deletion.phase!=="running")await this.store.update(task.id,{deletion:{...task.deletion,phase:"running"}});return!0}async finish(id){let task=this.store.get(id);if(!task?.deletion||task.deletion.phase!=="running")return;try{if(task.worktreePath&&task.kind!=="dir")await this.worktrees.remove(task.worktreePath,{force:task.deletion.force,deleteBranch:task.deletion.deleteBranch===!0,repo:task.repo,branch:task.branch,onSalvage:(record)=>{if(record)this.onSalvage?.(task.id,record)},onResidue:(residue)=>this.onResidue?.(task.id,residue),onBranchKept:(kept)=>this.onBranchKept?.(task.id,kept)})}catch(cause){let failure=new WorktreeRemoveFailedError(task.id,cause);throw await this.store.update(task.id,{deletion:{...task.deletion,phase:"error",error:errorMessage(failure)}}),failure}await this.store.remove(task.id),this.forgetTask(task.id)}async deleteNow(id,opts){if(!await this.prepare(id,opts))return;if(!await this.begin(id))return;await this.finish(id)}}var TYPE_PREFIXES=new Set(["feat","feature","fix","bugfix","hotfix","chore","docs","doc","refactor","test","tests","ci","build","perf","style","revert","release"]),BRAND_TOKENS=new Set(["rove","kobe"]);function inferBranchStyle(names){let typed=new Map,bare=0;for(let raw of new Set(names)){let name=raw.trim();if(!name||name==="HEAD")continue;let slash=name.indexOf("/");if(slash===-1){bare+=1;continue}let prefix=name.slice(0,slash);if(TYPE_PREFIXES.has(prefix))typed.set(prefix,(typed.get(prefix)??0)+1)}let typedTotal=0;for(let n of typed.values())typedTotal+=n;if(typedTotal===0||typedTotal<bare)return{kind:"bare"};let best="",bestN=0;for(let[prefix,n]of typed)if(n>bestN||n===bestN&&(best===""||prefix<best))best=prefix,bestN=n;return{kind:"typed",defaultPrefix:best}}function slugTokens(title){return title.toLowerCase().replace(/[^a-z0-9]+/g,"-").split("-").filter((t)=>t.length>0&&!BRAND_TOKENS.has(t))}function capSlug(tokens){return tokens.join("-").slice(0,32).replace(/-+$/,"")}function identitySlug(taskId){return`task-${taskId.slice(-6).toLowerCase()}`}function deriveConventionBranch(title,style,taskId){let tokens=slugTokens(title);if(style.kind==="typed"){let first=tokens[0];return`${first!==void 0&&TYPE_PREFIXES.has(first)?tokens.shift():style.defaultPrefix}/${capSlug(tokens)||identitySlug(taskId)}`}return capSlug(tokens)||identitySlug(taskId)}function uniqueBranchName(base,taken,taskId){if(!taken.has(base))return base;for(let n=2;n<=99;n+=1){let candidate=`${base}-${n}`;if(!taken.has(candidate))return candidate}return`${base}-${taskId.slice(-6).toLowerCase()}`}class TaskEditor{store;worktrees;constructor(store,worktrees){this.store=store,this.worktrees=worktrees}requireTask(id){let task=this.store.get(id);if(!task)throw new TaskNotFoundError(String(id));return task}async setTitle(id,title){let trimmed=sanitizeTaskTitle(title);if(!trimmed)throw Error("setTitle: title is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.title===trimmed&&task.scratch!==!0)return;await this.store.update(task.id,{title:trimmed,...task.scratch===!0?{scratch:!1}:{}}),await this.followBranchToTitle(task,trimmed)}async followBranchToTitle(taskBefore,newTitle){if(taskBefore.kind==="main"||!taskBefore.worktreePath)return;if(!isPlaceholderDerivedBranch(taskBefore.branch,taskBefore.id))return;try{let names=await this.worktrees.listBranchNames(taskBefore.repo),base=deriveConventionBranch(newTitle,inferBranchStyle(names),taskBefore.id);if(base===taskBefore.branch)return;if(await this.worktrees.branchHasUpstream(taskBefore.worktreePath,taskBefore.branch))return;let taken=new Set(names.filter((n)=>n!==taskBefore.branch)),nextBranch=uniqueBranchName(base,taken,taskBefore.id);await this.setBranch(taskBefore.id,nextBranch)}catch(err){console.error(`[rove] follow-branch-to-title failed for ${taskBefore.id}:`,err)}}async setBranch(id,branch){let trimmed=branch.trim();if(!trimmed)throw Error("setBranch: branch is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.kind==="main")throw Error("setBranch: a main task tracks the repo's own branch; rename it with git directly");if(task.kind==="dir")throw Error("setBranch: a directory task tracks its own checkout; rename branches with git directly");if(task.branch===trimmed)return;if(task.worktreePath)await this.worktrees.renameBranch(task.worktreePath,task.branch,trimmed);await this.store.update(task.id,{branch:trimmed})}async observeLanguage(id,text){let observed=detectLanguage(text);if(!observed)return;let task=this.requireTask(id);if(task.observedLanguage===observed)return;await this.store.update(task.id,{observedLanguage:observed})}async setVendor(id,vendor,effort,model){let task=this.requireTask(id),nextEffort=effort?.trim()?effort.trim():void 0,effortChanges=effort!==void 0&&task.modelEffort!==nextEffort,nextModel=model?.trim()?model.trim():void 0,modelChanges=model!==void 0&&task.model!==nextModel;if(task.vendor===vendor&&!effortChanges&&!modelChanges)return;await this.store.update(task.id,{vendor,...effort!==void 0?{modelEffort:nextEffort}:{},...model!==void 0?{model:nextModel}:{}})}async setCommand(id,command,vendor){let trimmed=command.trim();if(!trimmed)throw Error("setCommand: command is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.command===trimmed&&(vendor===void 0||task.vendor===vendor))return;await this.store.update(task.id,{command:trimmed,...vendor?{vendor}:{}})}async setPinned(id,pinned){let task=this.requireTask(id);if(task.kind==="main")return;let next=pinned??!task.pinned;if((task.pinned??!1)===next)return;await this.store.update(task.id,{pinned:next})}async moveTask(id,delta){let task=this.requireTask(id),isMain=task.kind==="main",groupIds=this.store.list().filter((t)=>isMain?(t.kind??"task")==="main":(t.kind??"task")!=="main"&&samePath(t.repo,task.repo)&&(t.pinned??!1)===(task.pinned??!1)).map((t)=>String(t.id));await this.store.move(task.id,delta,groupIds)}async setStatus(id,status){let task=this.requireTask(id);if(task.status===status)return;if(task.status==="done"&&status==="error"||task.status==="error"&&status==="done")throw new IllegalTransitionError(task.status,status,task.id);await this.store.update(task.id,{status})}async setWorkerReport(id,report){let task=this.requireTask(id),next={...task.report,...report,at:new Date().toISOString()};await this.store.update(task.id,{report:next})}async setPRStatus(id,prStatus){let task=this.requireTask(id);if((task.prStatus?.lastError??null)===(prStatus?.lastError??null)&&samePrStatus(task.prStatus,prStatus??void 0))return;await this.store.update(task.id,{prStatus:prStatus??void 0})}async setQuotaResume(id,state){let task=this.requireTask(id);if((task.quotaResume?.resumeAt??null)===(state?.resumeAt??null))return;await this.store.update(task.id,{quotaResume:state??void 0})}async setLinkedWorkItem(id,item){let task=this.requireTask(id);if((task.linkedWorkItem?.url??null)===(item?.url??null))return;await this.store.update(task.id,{linkedWorkItem:item??void 0})}async setPrompt(id,prompt){if(prompt.trim().length===0)throw Error("setPrompt: prompt is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.prompt===prompt)return;await this.store.update(task.id,{prompt})}}import{basename}from"path";var ANIMAL_NAMES=["aardvark","addax","adder","agouti","albatross","alpaca","anaconda","anchovy","anglerfish","anole","anteater","antelope","ape","argali","armadillo","avocet","axolotl","baboon","badger","banteng","barracuda","basilisk","bass","bat","beagle","bear","beaver","bee","beetle","beluga","betta","bison","blackbird","blenny","bluebird","bluegill","boar","bobcat","bonito","bovid","buffalo","bullfrog","bunting","bushbuck","butterfly","buzzard","caiman","camel","canary","capybara","caracal","cardinal","caribou","carp","cassowary","caterpillar","catfish","chameleon","chamois","char","cheetah","chickadee","chimp","chinchilla","chipmunk","chough","cicada","civet","clam","clownfish","cobra","cockatoo","condor","coot","copperhead","coral","cormorant","cougar","coyote","crab","crane","crawfish","crayfish","cricket","crocodile","crow","cuckoo","curlew","cuttlefish","deer","dikdik","dingo","dolphin","donkey","dormouse","dotterel","dove","dragonfly","dromedary","duck","dugong","dunlin","eagle","echidna","eel","egret","eider","eland","elephant","elk","emu","ermine","falcon","fawn","ferret","finch","firefly","flamingo","flounder","fox","frog","gadwall","gannet","gaur","gazelle","gecko","gemsbok","gerbil","gharial","gibbon","gnu","goat","goby","godwit","goldfish","goose","gopher","goral","gorilla","goshawk","grackle","grasshopper","grayling","grebe","grouse","guanaco","guillemot","guineafowl","guppy","halibut","hammerhead","hamster","hare","harrier","hartebeest","hawk","hedgehog","heron","herring","hippo","hornbill","hornet","horse","hummingbird","hyena","ibex","ibis","iguana","impala","indri","jacana","jackal","jaguar","jay","jellyfish","jerboa","junco","kakapo","kangaroo","kestrel","killdeer","kingfisher","kinglet","kite","kiwi","koala","kookaburra","krait","krill","kudu","ladybug","lamprey","langur","lapwing","lark","lemming","lemur","leopard","limpet","lion","lionfish","lizard","llama","lobster","locust","loon","lorikeet","loris","lynx","macaque","macaw","mackerel","magpie","mallard","mamba","mammoth","manatee","mandrill","manta","mantis","marlin","marmoset","marmot","marten","meerkat","merganser","mink","minnow","mole","mongoose","monitor","monkey","moose","moth","mouflon","mouse","mudpuppy","mule","muntjac","musk","muskox","muskrat","mussel","mustang","narwhal","newt","nightingale","numbat","nuthatch","nyala","ocelot","octopus","okapi","opossum","orangutan","orca","oriole","oryx","osprey","ostrich","otter","owl","oyster","oystercatcher","paca","panda","pangolin","panther","parakeet","parrot","parrotfish","partridge","peafowl","pelican","penguin","perch","petrel","pheasant","pigeon","pika","pike","pintail","pipefish","platypus","plover","pollock","pony","porcupine","porpoise","possum","ptarmigan","puffin","puma","pupfish","python","quail","quetzal","quokka","quoll","rabbit","raccoon","rail","rat","rattler","raven","ray","redpoll","reindeer","remora","rhino","roadrunner","robin","rook","sable","sailfish","salamander","salmon","sandpiper","sardine","scallop","scaup","scorpion","seahorse","seal","serval","shark","shearwater","shrew","shrike","shrimp","siskin","sitatunga","skate","skink","skua","skunk","sloth","smelt","snail","snipe","solenodon","sparrow","spider","springbok","squid","squirrel","starfish","starling","stilt","stingray","stoat","stork","sunbird","sunfish","swallow","swan","swift","swordfish","tahr","takin","tamarin","tanager","tapir","tarantula","tarpon","tarsier","teal","tenrec","terrapin","tern","tetra","thrasher","thrush","tiger","toad","tortoise","toucan","treecreeper","treefrog","trout","tuatara","tuna","turkey","turtle","urchin","urial","vicuna","viper","vole","vulture","wagtail","wallaby","walleye","walrus","warbler","warthog","waterbuck","weasel","wildebeest","wolf","wolverine","wombat","woodcock","woodpecker","wrasse","wren","yak","zebra","zebu","zorilla"];class SlugAllocator{activeSlugs;random;pool;pendingByRepo=new Map;chain=Promise.resolve();constructor(activeSlugs,options={}){this.activeSlugs=activeSlugs;if(this.random=options.random??Math.random,this.pool=options.pool??ANIMAL_NAMES,this.pool.length===0)throw Error("SlugAllocator: animal pool cannot be empty")}async allocate(repo){let previous=this.chain,release;this.chain=new Promise((resolve)=>{release=resolve}),await previous;try{return await this.pickLocked(repo)}finally{release()}}async claim(repo,slug){let previous=this.chain,release;this.chain=new Promise((resolve)=>{release=resolve}),await previous;try{if((await this.occupiedSlugs(repo)).has(slug))throw new WorktreeNameTakenError(slug);return this.addPending(repo,slug),slug}finally{release()}}commit(repo,slug){this.deletePending(repo,slug)}cancel(repo,slug){this.deletePending(repo,slug)}async pickLocked(repo){let occupied=await this.occupiedSlugs(repo),candidates=this.pool.filter((n)=>!occupied.has(n));if(candidates.length>0){let pick=candidates[Math.floor(this.random()*candidates.length)];return this.addPending(repo,pick),pick}let base=this.pool[Math.floor(this.random()*this.pool.length)];for(let v=2;;v++){let candidate=`${base}-v${v}`;if(!occupied.has(candidate))return this.addPending(repo,candidate),candidate}}async occupiedSlugs(repo){let set=new Set(this.pendingByRepo.get(repo)??[]);for(let slug of this.activeSlugs(repo))if(slug)set.add(slug);for(let dir of await listWorktreeDirNames(repo))set.add(dir);return set}addPending(repo,slug){let pending=this.pendingByRepo.get(repo);if(!pending)pending=new Set,this.pendingByRepo.set(repo,pending);pending.add(slug)}deletePending(repo,slug){let pending=this.pendingByRepo.get(repo);if(!pending)return;if(pending.delete(slug),pending.size===0)this.pendingByRepo.delete(repo)}}var WORKTREE_NAME_RE=/^[A-Za-z0-9_][A-Za-z0-9._-]*$/;class WorktreeCoordinator{store;worktrees;canonPath;ensureProject;slugs;worktreeLocks=new Map;adoptLocks=new Map;reservedBranches=new Set;constructor(store,worktrees,canonPath2,ensureProject){this.store=store,this.worktrees=worktrees,this.canonPath=canonPath2,this.ensureProject=ensureProject,this.slugs=new SlugAllocator((repo)=>this.store.list().filter((t)=>samePath(t.repo,repo)&&t.kind!=="main").map((t)=>{return t.worktreePath.match(/([^/\\]+)[/\\]*$/)?.[1]??""}).filter((s)=>s.length>0))}async claimWorktreeName(repo,name){if(!WORKTREE_NAME_RE.test(name))throw new InvalidWorktreeNameError(name);return await this.slugs.claim(repo,name)}forget(id){this.worktreeLocks.delete(id)}async ensure(task){let inflight=this.worktreeLocks.get(task.id);if(inflight)return inflight;let work=this.createWorktree(task);this.worktreeLocks.set(task.id,work);try{return await work}finally{this.worktreeLocks.delete(task.id)}}async createWorktree(task){let slug=task.worktreeName||await this.slugs.allocate(task.repo),branch=task.branch||await this.deriveAutoBranch(task),baseRef=task.baseRef,info;try{info=await this.worktrees.createForTask({repo:task.repo,slug,branch,baseRef})}catch(err){throw this.slugs.cancel(task.repo,slug),err}finally{this.reservedBranches.delete(branch)}try{await this.store.update(task.id,{worktreePath:info.path,branch})}catch(err){throw await this.rollbackWorktree(info.path),this.slugs.cancel(task.repo,slug),err}return this.slugs.commit(task.repo,slug),info.path}async deriveAutoBranch(task){let names=await this.worktrees.listBranchNames(task.repo),base=deriveConventionBranch(task.title,inferBranchStyle(names),task.id),taken=new Set([...names,...this.reservedBranches]),branch=uniqueBranchName(base,taken,task.id);return this.reservedBranches.add(branch),branch}async rollbackWorktree(worktreePath){try{await this.worktrees.remove(worktreePath,{force:!0})}catch(err){console.error(`[rove] ensureWorktree rollback failed for ${worktreePath}:`,err)}}async discoverAdoptable(repo){let all=await this.worktrees.listAll(repo),linked=new Set(this.store.list().filter((t)=>t.worktreePath).map((t)=>this.canonPath(t.worktreePath)));return all.filter((wt)=>!linked.has(this.canonPath(wt.path)))}async adopt(input){let target=this.canonPath(input.worktreePath),inflight=this.adoptLocks.get(target);if(inflight)return inflight;let work=this.adoptLocked(input,target);this.adoptLocks.set(target,work);try{return await work}finally{this.adoptLocks.delete(target)}}async adoptLocked(input,target){let existing=this.store.list().find((t)=>t.worktreePath&&this.canonPath(t.worktreePath)===target);if(existing){if(input.ifExists==="return")return existing;throw Error(`adoptWorktree: ${input.worktreePath} is already adopted as a task`)}let match=(await this.worktrees.listAdoptablePaths(input.repo)).find((wt)=>this.canonPath(wt.path)===target);if(!match)throw Error(`adoptWorktree: ${input.worktreePath} is not an adoptable git worktree of ${input.repo} (unknown, detached, or the main checkout)`);let branch=input.branch?.trim()||match.branch,title=(input.title??basename(match.path)).trim()||PLACEHOLDER_TASK_TITLE;return await this.ensureProject(input.repo),this.store.create({repo:input.repo,title,branch,worktreePath:match.path,status:"backlog",kind:"task",vendor:input.vendor??DEFAULT_TASK_VENDOR})}}class Orchestrator{store;worktrees;worktreeCoordinator;editor;deletions;tasksAcc;activeTaskAcc;unsubscribeStore;mainTasks;tearDownSession;constructor(deps){this.store=deps.store,this.worktrees=deps.worktrees,this.tearDownSession=deps.tearDownSession,this.worktreeCoordinator=new WorktreeCoordinator(this.store,this.worktrees,canonPath,(repo)=>this.mainTasks.ensureIfEligible(repo)),this.mainTasks=new MainTaskCoordinator(this.store,(id)=>this.worktreeCoordinator.forget(id)),this.editor=new TaskEditor(this.store,this.worktrees),this.deletions=new TaskDeletionCoordinator(this.store,this.worktrees,(id)=>this.worktreeCoordinator.forget(id),deps.onSalvage,deps.onWorktreeResidue,deps.onBranchKept),this.tasksAcc=createStateCell(this.store.list());let persistedFocus=readLastActiveTaskId();this.activeTaskAcc=createStateCell(persistedFocus&&this.store.get(persistedFocus)?persistedFocus:null),this.unsubscribeStore=this.store.subscribe((snapshot)=>{this.tasksAcc.set(snapshot.slice())})}async init(){try{let promotable=promotableDirTasks({tasks:this.store.list(),isRepoRoot:(path)=>isGitRepo(path)&&samePath(resolveRepoRoot(path),path)});for(let task of promotable)await this.mainTasks.ensureIfEligible(task.repo,"explicit")}catch{}}activeTaskSignal(){return this.activeTaskAcc}async setActiveTask(id){let next=id===null?null:String(id);if(next&&this.store.get(next)?.deletion)throw new TaskDeletingError(next);if(this.activeTaskAcc.set(next),next&&this.store.get(next))writeLastActiveTaskId(next),this.store.touchRecency(next)}tasksSignal(){return this.tasksAcc}subscribeTasks(listener){return this.store.subscribe(listener)}dispose(){this.unsubscribeStore()}listTasks(){return this.store.list()}getTask(id){return this.store.get(id)}createTask=(input)=>createTaskRow({store:this.store,mainTasks:this.mainTasks,claimWorktreeName:(repo,name)=>this.worktreeCoordinator.claimWorktreeName(repo,name)},input);openDirectoryTask=(input)=>openDirectoryTaskRow({store:this.store},input);adoptScratchRepo=(id,repo)=>adoptScratchRepoRow({store:this.store},id,repo);async ensureMainTask(repo){return await this.mainTasks.ensure(repo)}async ensureWorktree(id){let task=this.requireTask(id);if(task.deletion)throw new TaskDeletingError(String(task.id));if(task.kind==="main")return repoWorkingDir(task.repo);if(task.kind==="dir")return task.worktreePath;if(task.worktreePath){if(await this.worktrees.pathExists(task.worktreePath))return task.worktreePath;return await this.worktrees.pruneWorktrees(task.repo),await this.store.update(task.id,{worktreePath:""}),this.worktreeCoordinator.ensure({...task,worktreePath:""})}return this.worktreeCoordinator.ensure(task)}async clearWorktreePath(id){let task=this.store.get(id);if(!task||!task.worktreePath)return;if(task.kind==="main"||task.kind==="dir")return;await this.store.update(task.id,{worktreePath:""}),this.worktreeCoordinator.forget(task.id)}setTitle=(id,title)=>this.editor.setTitle(id,title);setBranch=(id,branch)=>this.editor.setBranch(id,branch);observeLanguage=(id,text)=>this.editor.observeLanguage(id,text);setVendor=(id,vendor,effort,model)=>this.editor.setVendor(id,vendor,effort,model);setCommand=(id,command,vendor)=>this.editor.setCommand(id,command,vendor);setPinned=(id,pinned)=>this.editor.setPinned(id,pinned);moveTask=(id,delta)=>this.editor.moveTask(id,delta);setStatus=(id,status)=>this.editor.setStatus(id,status);setWorkerReport=(id,report)=>this.editor.setWorkerReport(id,report);setPRStatus=(id,prStatus)=>this.editor.setPRStatus(id,prStatus);setLinkedWorkItem=(id,item)=>this.editor.setLinkedWorkItem(id,item);setQuotaResume=(id,state)=>this.editor.setQuotaResume(id,state);setPrompt=(id,prompt)=>this.editor.setPrompt(id,prompt);async deleteTask(id,opts){await this.deletions.deleteNow(id,opts)}async prepareTaskDeletion(id,opts){return this.deletions.prepare(id,opts)}async beginTaskDeletion(id){return this.deletions.begin(id)}async finishTaskDeletion(id){return this.deletions.finish(id)}async landPreflight(id){let task=this.requireTask(id);if(task.kind==="main")throw Error("landTask: a main task has no branch to land");if(task.kind==="dir")throw Error("landTask: a directory task has no Rove-managed branch to land");if(task.deletion)throw new TaskDeletingError(String(task.id));return landPreflight(task)}async landTask(id,opts){let task=this.requireTask(id);if(task.deletion)throw new TaskDeletingError(String(task.id));return landTaskWithCleanup(task,opts??{},{worktrees:this.worktrees,clearWorktreePath:(tid)=>this.clearWorktreePath(tid),tearDownSession:this.tearDownSession})}async forgetProject(repo){await this.mainTasks.forget(repo)}async discoverAdoptableWorktrees(repo){if(!repo)throw Error("discoverAdoptableWorktrees: repo is required");return this.worktreeCoordinator.discoverAdoptable(repo)}async adoptWorktree(input){if(!input.repo)throw Error("adoptWorktree: repo is required");if(!input.worktreePath)throw Error("adoptWorktree: worktreePath is required");return this.worktreeCoordinator.adopt(input)}requireTask(id){let task=this.store.get(id);if(!task)throw new TaskNotFoundError(String(id));return task}}
|
|
4
|
-
export{Orchestrator};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{activeCliName}from"./chunk-ppwpjm39.js";import{constants,accessSync,statSync}from"fs";import{isAbsolute}from"path";function isRunnableFile(path){try{if(!statSync(path).isFile())return!1;return accessSync(path,constants.X_OK),!0}catch{return!1}}function resolvePluginBinPath(argv=process.argv,moduleUrl=import.meta.url){if(moduleUrl.includes("/$bunfs/")||moduleUrl.includes("B:\\~BUN"))return process.execPath;let entry=argv[1];if(entry&&isAbsolute(entry)&&isRunnableFile(entry))return entry;return activeCliName()}
|
|
3
|
-
export{resolvePluginBinPath};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{addRemoteRepo,addSavedRepo,backfillSavedReposFromProjects,getCustomEngineIds,getDisabledEngineIds,getPersistedString,getPersistedValue,getRemoteRepoConfig,getRemoteRepos,getRepoInitOverride,getSavedRepos,isGitRepo,isRemoteProjectsEnabled,isRemoteRepoKey,isValidBranchName,normalizeSavedRepos,remoteRepoKey,removeSavedRepo,resolveMainRepoRoot,resolveRepoRoot,setPersistedString,setRepoInitOverride,statePath}from"./chunk-32mv1yy6.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{statePath,setRepoInitOverride,setPersistedString,resolveRepoRoot,resolveMainRepoRoot,removeSavedRepo,remoteRepoKey,normalizeSavedRepos,isValidBranchName,isRemoteRepoKey,isRemoteProjectsEnabled,isGitRepo,getSavedRepos,getRepoInitOverride,getRemoteRepos,getRemoteRepoConfig,getPersistedValue,getPersistedString,getDisabledEngineIds,getCustomEngineIds,backfillSavedReposFromProjects,addSavedRepo,addRemoteRepo};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{defaultUiPrefsStatePath,resolveProductHomeDir}from"./chunk-8hbtca1g.js";import{LEGACY_KOBE_STATE_DIR_BASENAME,ROVE_STATE_DIR_BASENAME}from"./chunk-hq4b3fca.js";import{createHash}from"crypto";import{readFileSync}from"fs";import path from"path";var WORKTREE_ROOT_DIR="worktrees",REPO_LOCAL_ROVE_WORKTREE_ROOT_SUBPATH=".rove/worktrees",REPO_LOCAL_KOBE_WORKTREE_ROOT_SUBPATH=".kobe/worktrees",LEGACY_KOBE_WORKTREE_ROOT_SUBPATH=".claude/worktrees",REPO_LOCAL_MANAGED_WORKTREE_ROOT_SUBPATHS=[REPO_LOCAL_ROVE_WORKTREE_ROOT_SUBPATH,REPO_LOCAL_KOBE_WORKTREE_ROOT_SUBPATH,LEGACY_KOBE_WORKTREE_ROOT_SUBPATH],WORKTREE_BASE_KEY="worktree.basePath",PROJECT_DIR_TOKEN="$project_dir";function repoWorktreeDirName(repo){let safeBase=(path.basename(repo)||"repo").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"repo",hash=createHash("sha1").update(path.resolve(repo)).digest("hex").slice(0,12);return`${safeBase}-${hash}`}function hasProjectDirToken(raw){let trimmed=raw.trim();return trimmed===PROJECT_DIR_TOKEN||trimmed.startsWith(`${PROJECT_DIR_TOKEN}/`)||process.platform==="win32"&&trimmed.startsWith(`${PROJECT_DIR_TOKEN}\\`)}function normalizeWorktreeBase(raw,projectDir){if(typeof raw!=="string")return null;let trimmed=raw.trim();if(!trimmed)return null;if(hasProjectDirToken(trimmed)){if(!projectDir)return null;let rest=trimmed.slice(PROJECT_DIR_TOKEN.length).replace(process.platform==="win32"?/^[/\\]+/:/^\/+/,"");return path.resolve(projectDir,rest)}let home=resolveProductHomeDir();if(trimmed==="~")return home;let expanded=trimmed.startsWith("~/")||process.platform==="win32"&&trimmed.startsWith("~\\")?path.join(home,trimmed.slice(2)):trimmed;return path.isAbsolute(expanded)?expanded:path.resolve(home,expanded)}function readWorktreeBaseOverride(projectDir){try{let raw=JSON.parse(readFileSync(defaultUiPrefsStatePath(),"utf8"));if(!raw||typeof raw!=="object"||Array.isArray(raw))return null;let value=raw[WORKTREE_BASE_KEY];return normalizeWorktreeBase(typeof value==="string"?value:null,projectDir)}catch{return null}}function defaultLocalWorktreesRoot(){return path.join(resolveProductHomeDir(),ROVE_STATE_DIR_BASENAME,WORKTREE_ROOT_DIR)}function legacyLocalWorktreesRoot(){return path.join(resolveProductHomeDir(),LEGACY_KOBE_STATE_DIR_BASENAME,WORKTREE_ROOT_DIR)}function worktreeRootFor(repo,override){if(!path.isAbsolute(repo))throw Error(`worktreeRootFor: repo must be an absolute path, got: ${repo}`);return path.join(override??defaultLocalWorktreesRoot(),repoWorktreeDirName(repo))}function managedWorktreeRootsFor(repo,override){if(!path.isAbsolute(repo))throw Error(`managedWorktreeRootsFor: repo must be an absolute path, got: ${repo}`);let dirName=repoWorktreeDirName(repo);return[...new Set([worktreeRootFor(repo,override),path.join(defaultLocalWorktreesRoot(),dirName),path.join(legacyLocalWorktreesRoot(),dirName),...REPO_LOCAL_MANAGED_WORKTREE_ROOT_SUBPATHS.map((subpath)=>path.join(repo,subpath))])]}
|
|
3
|
-
export{WORKTREE_BASE_KEY,PROJECT_DIR_TOKEN,hasProjectDirToken,normalizeWorktreeBase,readWorktreeBaseOverride,defaultLocalWorktreesRoot,legacyLocalWorktreesRoot,worktreeRootFor,managedWorktreeRootsFor};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{LEGACY_KOBE_CONFIG_DIR_BASENAME,LEGACY_KOBE_STATE_DIR_BASENAME,ROVE_STATE_DIR_BASENAME as ROVE_STATE_DIR_BASENAME2}from"./chunk-sb0ns0c7.js";import{ROVE_CONFIG_DIR_BASENAME,ROVE_STATE_DIR_BASENAME,readRoveEnv,readRoveHomeDirEnv}from"./chunk-hq4b3fca.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 legacyKobeStateDir(){return join2(homeDir(),LEGACY_KOBE_STATE_DIR_BASENAME)}function kvStatePath(){return defaultUiPrefsStatePath(homeDir())}function legacyKobeKvStatePath(){return join2(homeDir(),".config",LEGACY_KOBE_CONFIG_DIR_BASENAME,"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,legacyKobeStateDir,kvStatePath,legacyKobeKvStatePath,secretsPath,keybindingsConfigPath,promptAttachmentsDir,remoteControlSocketPath,worktreeInitMarkerPath};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{binaryAvailable,resolveEditorCommand}from"./chunk-h4qv19v8.js";import"./chunk-6xppe9bj.js";import"./chunk-7kysxgbq.js";import"./chunk-32mv1yy6.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import{activeCliName}from"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import{kvStatePath}from"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";import{existsSync,mkdirSync,writeFileSync}from"fs";import{dirname}from"path";var CLI_NAME=activeCliName();function printUsage(out){out.write([`Usage: ${CLI_NAME} config [--path]`,"","Open Rove's user config (state.json \u2014 theme, locale, engine + editor prefs)","in your editor. The editor is your configured one (Settings \u2192 General \u2192","Editor); left on Auto it is $VISUAL / $EDITOR, else the first of","nvim / vim / emacs / nano.","Rove re-reads the file on its next launch.","","Options:"," --path Print the config file path and exit (don't open an editor)"," -h, --help Print this help",""].join(`
|
|
3
|
-
`))}async function runConfigSubcommand(argv=[]){if(argv.some((a)=>a==="-h"||a==="--help"||a==="help")){printUsage(process.stdout);return}let path=kvStatePath();if(argv.some((a)=>a==="--path"||a==="path")){console.log(path);return}let unknown=argv.find((a)=>a.length>0);if(unknown!==void 0)process.stderr.write(`${CLI_NAME} config: unexpected argument "${unknown}"
|
|
4
|
-
`),printUsage(process.stderr),process.exit(2);if(!existsSync(path))mkdirSync(dirname(path),{recursive:!0}),writeFileSync(path,`{}
|
|
5
|
-
`);let resolved=await resolveEditorCommand(path);if(!resolved||!await binaryAvailable(resolved.bin))process.stderr.write(`${CLI_NAME} config: no editor found \u2014 set $EDITOR (or Settings \u2192 General \u2192 Editor), or edit directly:
|
|
6
|
-
${path}
|
|
7
|
-
`),process.exit(1);let proc=Bun.spawn(["sh","-c",resolved.command],{stdin:"inherit",stdout:"inherit",stderr:"inherit"});process.exit(await proc.exited)}export{runConfigSubcommand};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{generateCompletions,isShellKind,mergeSubVerbs,shippedCompletionsPath}from"./chunk-yybpg7fh.js";import"./chunk-fhch0x0q.js";import{activeCliName}from"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{existsSync,readFileSync}from"fs";var HELP_WORDS=["--help","-h","help"];function completionUsage(cliName){return[`Usage: ${cliName} completions <bash|zsh|fish> [--path|--install]`,"",`Print a shell completion script for ${cliName}, or locate the copy shipped`,"with this install.","",` ${cliName} completions zsh --path print the shipped script's path`,` ${cliName} completions zsh --install hook it into your shell config`,"","Install:",` zsh source <(${cliName} completions zsh) # one-off, or in ~/.zshrc after compinit`," # with no process start per shell \u2014 what the first-run wizard writes:",` # ${cliName} completions zsh --install`,` bash ${cliName} completions bash --install # appends to ~/.bashrc`,` fish ${cliName} completions fish --install # writes ~/.config/fish/completions/${cliName}.fish`," # the manual way, any shell:",` # ${cliName} completions zsh > ~/.zsh/completions/_${cliName}`," # fpath=(~/.zsh/completions $fpath) # in ~/.zshrc, BEFORE compinit"," # rm -f ~/.zcompdump && exec zsh # rebuild the completion cache",""].join(`
|
|
3
|
-
`)}async function runCompletionsSubcommand(rest,cliName=activeCliName(),deps={}){let usage=completionUsage(cliName),fail=(message)=>{process.stderr.write(`${cliName} completions: ${message}
|
|
4
|
-
|
|
5
|
-
${usage}`),process.exit(2)};if(rest.some((arg)=>HELP_WORDS.includes(arg))){process.stdout.write(usage);return}let flags=rest.filter((arg)=>arg.startsWith("-")),shells=rest.filter((arg)=>!arg.startsWith("-")),unknownFlag=flags.find((flag)=>flag!=="--path"&&flag!=="--install");if(unknownFlag)fail(`unknown option "${unknownFlag}"`);if(new Set(flags).size>1)fail("--path and --install are different things; pass one");let shell=shells.length===1?shells[0]:void 0;if(!isShellKind(shell))fail(`unknown shell "${shells.join(" ")}"`);let scriptPath=shippedCompletionsPath(shell,cliName,deps.shippedDir),shipped=existsSync(scriptPath)?scriptPath:null;if(flags[0]==="--path"){if(!shipped)fail(`no pre-generated ${shell} script at ${scriptPath}
|
|
6
|
-
${cliName} completions ${shell} # print the script to stdout instead`);process.stdout.write(`${shipped}
|
|
7
|
-
`);return}if(flags[0]==="--install"){let[{installCompletions},{t}]=await Promise.all([import("./chunk-67ev8k22.js"),import("./chunk-bkbmqec2.js")]),completion=installCompletions(shell,deps.home,cliName,shipped),line=completion.installed?"onboarding.appliedCompletions":"onboarding.keptCompletions";process.stdout.write(`${t(line,{path:completion.path})}
|
|
8
|
-
`);return}if(shipped){process.stdout.write(readFileSync(shipped,"utf8"));return}let{API_VERBS}=await import("./chunk-yj5pjxx2.js");process.stdout.write(generateCompletions(shell,cliName,mergeSubVerbs(API_VERBS)))}export{runCompletionsSubcommand};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{GitWorktreeManager}from"./chunk-gmgsxdrf.js";import"./chunk-mppda1wq.js";import"./chunk-85mk6j0s.js";import"./chunk-dnbh8hsm.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-6xppe9bj.js";import"./chunk-2brn8e1y.js";import"./chunk-7kysxgbq.js";import"./chunk-32mv1yy6.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{GitWorktreeManager};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{pathRejection,projectRejection,rejectionReason}from"./chunk-mkksdcsw.js";import"./chunk-8hbtca1g.js";import"./chunk-sb0ns0c7.js";import"./chunk-f10n6063.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{rejectionReason,projectRejection,pathRejection};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{BREAKING_VERSIONS,CURRENT_VERSION,DEFAULT_RELEASE_CHANNEL,PACKAGE_NAME,RELEASE_CHANNELS,UPDATE_COMMAND,UPDATE_SCRIPT_URL,breakingVersionsCrossed,channelOf,checkLatestVersion,compareSemver,fetchReleaseNotes,fetchReleaseNotesRange,fetchReleaseSummaries,isNewerSemver,owningNpmPrefix,recommendedGlobalInstallCommand,releasePageUrl,repoSlug}from"./chunk-be757xzj.js";import"./chunk-8hbtca1g.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{repoSlug,releasePageUrl,recommendedGlobalInstallCommand,owningNpmPrefix,isNewerSemver,fetchReleaseSummaries,fetchReleaseNotesRange,fetchReleaseNotes,compareSemver,checkLatestVersion,channelOf,breakingVersionsCrossed,UPDATE_SCRIPT_URL,UPDATE_COMMAND,RELEASE_CHANNELS,PACKAGE_NAME,DEFAULT_RELEASE_CHANNEL,CURRENT_VERSION,BREAKING_VERSIONS};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{KobeDaemonClient,RpcTimeoutError}from"./chunk-qagek3wg.js";import"./chunk-544bwsss.js";import"./chunk-hqbmzz4t.js";import"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{RpcTimeoutError,KobeDaemonClient};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{fetchMarketplace,searchMarketplace}from"./chunk-bc18gat5.js";import"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{searchMarketplace,fetchMarketplace};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{activeCliName}from"./chunk-ppwpjm39.js";var SEARCH_TIMEOUT_MS=5000,CLI_NAME=activeCliName(),FIRST_PARTY=[{ref:"Sma1lboy/rove-plugins/notify",desc:"Desktop/ntfy notifications when an agent finishes or needs input"},{ref:"Sma1lboy/rove-plugins/github-start",desc:"Start a Rove task from a GitHub issue or PR"},{ref:"Sma1lboy/rove-plugins/worktree-include",desc:"Copy .worktreeinclude-matched files into new worktrees"},{ref:"Sma1lboy/rove-plugins/linear-start",desc:"Pick a Linear issue (fzf) and start a task on its branch"},{ref:"Sma1lboy/rove-plugins/lazygit",desc:"lazygit on the task worktree, as a pane tab"},{ref:"Sma1lboy/rove-plugins/browser",desc:"Chromium rendered as terminal cells (carbonyl) in a pane tab"}];async function fetchTopic(topic,query){let q=encodeURIComponent(`topic:${topic}${query?` ${query}`:""}`),ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),SEARCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/search/repositories?q=${q}&sort=stars&order=desc&per_page=50`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json"}});if(!res.ok)return null;let body=await res.json();if(!Array.isArray(body.items))return null;return body.items.filter((r)=>typeof r.full_name==="string").map((r)=>({ref:r.full_name,desc:r.description??"",stars:r.stargazers_count}))}catch{return null}finally{clearTimeout(timer)}}async function fetchMarketplace(query){let topicResults=await Promise.all([fetchTopic("rove-plugin",query),fetchTopic("kobe-plugin",query)]),lower=query?.toLowerCase(),seeds=FIRST_PARTY.filter((s)=>!lower||`${s.ref} ${s.desc}`.toLowerCase().includes(lower)).map((s)=>({...s,firstParty:!0}));return{entries:dedupeEntries([...seeds,...topicResults.flatMap((result)=>result??[])]),offline:topicResults.every((result)=>result===null)}}async function searchMarketplace(query){let{entries,offline}=await fetchMarketplace(query);if(offline)console.error("(GitHub search unreachable \u2014 showing first-party plugins only)");if(entries.length===0){console.log(query?`no plugins match \`${query}\``:"no plugins found");return}let width=Math.min(48,Math.max(...entries.map((e)=>e.ref.length))+2);for(let e of entries){let stars=e.stars!==void 0?`\u2605${e.stars}`:e.firstParty?"first-party":"";console.log(`${e.ref.padEnd(width)}${stars.padEnd(12)}${e.desc}`)}console.log(`
|
|
3
|
-
install: ${CLI_NAME} plugin install <owner/repo[/subdir]> \u2014 browse: https://rove.run/plugins`)}function dedupeEntries(entries){let seen=new Set;return entries.filter((entry)=>{let key=entry.ref.toLowerCase();if(seen.has(key))return!1;return seen.add(key),!0})}
|
|
4
|
-
export{fetchMarketplace,searchMarketplace};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{isDev}from"./chunk-8hbtca1g.js";import{fileURLToPath}from"url";var package_default={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.238",description:"Rove \u2014 the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:rubric":"bun run scripts/build-tier-rubric.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun scripts/render-track.mjs",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.21.3"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.19","@tsconfig/bun":"1.0.11","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var CURRENT_VERSION=package_default.version,PACKAGE_NAME=package_default.name;function repoSlug(){let url=package_default.repository?.url;if(!url)return null;let m=url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);if(!m||!m[1]||!m[2])return null;return`${m[1]}/${m[2]}`}var UPDATE_SCRIPT_URL="https://raw.githubusercontent.com/Sma1lboy/rove/main/scripts/update.sh",UPDATE_COMMAND=`curl -fsSL ${UPDATE_SCRIPT_URL} | sh`;function owningNpmPrefix(modulePath=fileURLToPath(import.meta.url)){let at=modulePath.indexOf("/lib/node_modules/");if(at<=0)return null;return modulePath.slice(0,at)}function recommendedGlobalInstallCommand(prefix=owningNpmPrefix()){let target=`${PACKAGE_NAME}@latest`;return prefix===null?`npm install -g ${target}`:`npm install -g --prefix ${prefix} ${target}`}var BREAKING_VERSIONS=[];function breakingVersionsCrossed(from,to,breaking=BREAKING_VERSIONS){let[lo,hi]=compareSemver(from,to)<=0?[from,to]:[to,from];return breaking.filter((b)=>compareSemver(b,lo)>0&&compareSemver(b,hi)<=0)}var FETCH_TIMEOUT_MS=3000,RELEASE_CHANNELS=["latest","nightly"],DEFAULT_RELEASE_CHANNEL="latest";function channelOf(version=CURRENT_VERSION){return prereleaseOf(version)?.split(".")[0]==="nightly"?"nightly":DEFAULT_RELEASE_CHANNEL}async function fetchLatestFromRegistry(packageName,channel){let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let encoded=packageName.replace("/","%2F"),res=await fetch(`https://registry.npmjs.org/${encoded}/${channel}`,{signal:ctrl.signal,headers:{accept:"application/json"}});if(!res.ok)return null;let body=await res.json();if(typeof body.version!=="string")return null;return body.version}catch{return null}finally{clearTimeout(timer)}}function isNewerSemver(latest,current){let core=compareSemver(latest,current);if(core!==0)return core>0;return comparePrerelease(prereleaseOf(latest),prereleaseOf(current))>0}function prereleaseOf(version){let dash=version.indexOf("-");return dash===-1?void 0:version.slice(dash+1)||void 0}function comparePrerelease(a,b){if(a===b)return 0;if(a===void 0)return 1;if(b===void 0)return-1;let aParts=a.split("."),bParts=b.split(".");for(let i=0;i<Math.max(aParts.length,bParts.length);i++){let av=aParts[i],bv=bParts[i];if(av===void 0)return-1;if(bv===void 0)return 1;if(av===bv)continue;let an=/^\d+$/.test(av)?Number.parseInt(av,10):null,bn=/^\d+$/.test(bv)?Number.parseInt(bv,10):null;if(an!==null&&bn!==null)return an>bn?1:-1;if(an!==null)return-1;if(bn!==null)return 1;return av>bv?1:-1}return 0}function compareSemver(aVersion,bVersion){let norm=(v)=>v.split("-")[0]??v,a=norm(aVersion).split(".").map((s)=>Number.parseInt(s,10)),b=norm(bVersion).split(".").map((s)=>Number.parseInt(s,10));for(let i=0;i<3;i++){let av=a[i]??0,bv=b[i]??0;if(Number.isNaN(av)||Number.isNaN(bv))return 0;if(av>bv)return 1;if(av<bv)return-1}return 0}async function checkLatestVersion(opts={}){let channel=opts.channel??channelOf(),fake=process.env.KOBE_FAKE_UPDATE;if(fake)return{current:CURRENT_VERSION,latest:fake,hasUpdate:isNewerSemver(fake,CURRENT_VERSION),channel};if(isDev()&&!opts.force)return null;let latest=await fetchLatestFromRegistry(PACKAGE_NAME,channel);if(!latest)return null;return{current:CURRENT_VERSION,latest,hasUpdate:isNewerSemver(latest,CURRENT_VERSION),channel}}function versionFromTagName(tagName){if(typeof tagName!=="string")return null;return tagName.match(/^v(\d+\.\d+\.\d+)$/)?.[1]??null}async function fetchReleaseNotes(version){let slug=repoSlug();if(!slug)return null;let tag=`v${version}`,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases/tags/${tag}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return null;let body=await res.json();if(typeof body.body!=="string"||typeof body.html_url!=="string")return null;return{body:body.body,url:body.html_url,version}}catch{return null}finally{clearTimeout(timer)}}async function fetchReleaseNotesRange(args){let slug=repoSlug();if(!slug)return[];let limit=args.limit??100,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string"||typeof release.body!=="string")return null;if(compareSemver(version,args.current)<=0)return null;if(compareSemver(version,args.latest)>0)return null;return{version,url:release.html_url,body:release.body}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}async function fetchReleaseSummaries(limit=12){let slug=repoSlug();if(!slug)return[];let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string")return null;return{version,url:release.html_url}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}function releasePageUrl(version){let slug=repoSlug();if(!slug)return null;return`https://github.com/${slug}/releases/tag/v${version}`}
|
|
3
|
-
export{package_default,CURRENT_VERSION,PACKAGE_NAME,repoSlug,UPDATE_SCRIPT_URL,UPDATE_COMMAND,owningNpmPrefix,recommendedGlobalInstallCommand,BREAKING_VERSIONS,breakingVersionsCrossed,RELEASE_CHANNELS,DEFAULT_RELEASE_CHANNEL,channelOf,isNewerSemver,compareSemver,checkLatestVersion,fetchReleaseNotes,fetchReleaseNotesRange,fetchReleaseSummaries,releasePageUrl};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{quoteShellArgv}from"./chunk-7kysxgbq.js";import{acquireWithRetry}from"./chunk-2xsem13q.js";import{activeCliName}from"./chunk-ppwpjm39.js";import{roveStateDir}from"./chunk-8hbtca1g.js";import{acquireSync,release,releaseSync}from"./chunk-hq2n27y1.js";import{LEGACY_KOBE_PRODUCT_NAME,ROVE_PRODUCT_NAME}from"./chunk-sb0ns0c7.js";import{fileURLToPath}from"url";function roveCliInvocation(){let cliName=activeCliName();if(import.meta.url.endsWith(".js"))return[cliName];let entry=fileURLToPath(new URL(`./${cliName===ROVE_PRODUCT_NAME?"rove.ts":"kobe.ts"}`,import.meta.url));return[process.execPath,"--conditions=browser",entry]}function kobeHookInvocation(){if(import.meta.url.endsWith(".js"))return[LEGACY_KOBE_PRODUCT_NAME];if(Bun.which(LEGACY_KOBE_PRODUCT_NAME))return[LEGACY_KOBE_PRODUCT_NAME];return roveCliInvocation()}var ROVE_HOOK_VERSION=1;function roveHookArgs(vendor){return["--engine",vendor,"--hook-version",String(ROVE_HOOK_VERSION)]}var GATED_TOOL_VERBS=new Set(["tool-pre","tool-post","tool-failed"]);function isObject(v){return!!v&&typeof v==="object"&&!Array.isArray(v)}function parseHookSettings(raw){if(raw===void 0)return{ok:!0,doc:{}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{ok:!1,reason:`not valid JSON (${err instanceof Error?err.message:String(err)})`}}if(!isObject(parsed))return{ok:!1,reason:"top level is not a JSON object"};if(parsed.hooks===void 0)return{ok:!0,doc:parsed};if(!isObject(parsed.hooks))return{ok:!1,reason:'"hooks" is not an object'};for(let[event,groups]of Object.entries(parsed.hooks)){if(!Array.isArray(groups))return{ok:!1,reason:`"hooks.${event}" is not an array`};let bad=groups.findIndex((group)=>!isObject(group)||!Array.isArray(group.hooks));if(bad>=0)return{ok:!1,reason:`"hooks.${event}[${bad}]" is not an object with a "hooks" array`}}return{ok:!0,doc:parsed}}var HOOK_WORD=String.raw`(?:'(?:[^']|'\\'')*'|"[^"$\x60\\]*"|[A-Za-z0-9_./:=+-]+)`,HOOK_ARGV=new RegExp(`^${HOOK_WORD}(?:[ ]+${HOOK_WORD})*$`),ROVE_HOOK_FLAGS={"--engine":/^[a-z][a-z0-9-]*$/,"--hook-version":/^\d+$/};function isRoveHook(hook,verbs){if(!isObject(hook)||typeof hook.command!=="string")return!1;if(hook.type!==void 0&&hook.type!=="command")return!1;let command=hook.command.replace(/^[ \t]+|[ \t]+$/g,"");if(HOOK_ARGV.exec(command)?.[0]!==command)return!1;let argv=(command.match(new RegExp(HOOK_WORD,"g"))??[]).map((word)=>{if(word.startsWith("'"))return word.slice(1,-1).replaceAll("'\\''","'");if(word.startsWith('"'))return word.slice(1,-1);return word}),executable=argv[0]?.split("/").at(-1),offset=1;if(executable==="bun"||executable==="node"){if(argv[offset]==="--conditions=browser")offset++;let entry=argv[offset]??"";if(!/(?:^|\/)(?:src|dist)\/cli\/(?:rove|kobe)\.(?:ts|js)$/.test(entry))return!1;offset++}else if(executable!=="rove"&&executable!=="kobe")return!1;if(argv[offset]!=="hook"||!verbs.includes(argv[offset+1]))return!1;let rest=argv.slice(offset+2);for(let i=0;i<rest.length;i+=2){let value=rest[i+1],pattern=ROVE_HOOK_FLAGS[rest[i]??""];if(!pattern||value===void 0||!pattern.test(value))return!1}return!0}function removeRoveHooks(groups,verbs){return groups.flatMap((group)=>{if(!isObject(group)||!Array.isArray(group.hooks))return[group];let kept=group.hooks.filter((hook)=>!isRoveHook(hook,verbs));if(kept.length===group.hooks.length)return[group];return kept.length>0?[{...group,hooks:kept}]:[]})}function hasKobeActivityHooks(current,eventMap){let verbs=eventMap.map((spec)=>spec.verb),hooks=isObject(current.hooks)?current.hooks:{};return Object.values(hooks).some((groups)=>Array.isArray(groups)&&groups.some((group)=>isObject(group)&&Array.isArray(group.hooks)&&group.hooks.some((hook)=>isRoveHook(hook,verbs))))}function hookCommandQuoting(platform=process.platform){return{bareSafe:!0,windows:platform==="win32"}}function buildActivityHooks(eventMap,inv=kobeHookInvocation(),opts={}){let out={},quoting=hookCommandQuoting();for(let spec of eventMap){if(opts.buildFilter&&!opts.buildFilter(spec))continue;let{event,matcher,verb}=spec,group={hooks:[{type:"command",command:quoteShellArgv([...inv,"hook",verb,...opts.extraArgs??[]],quoting)}]};if(matcher)group.matcher=matcher;let previous=out[event],groups=Array.isArray(previous)?previous:[];groups.push(group),out[event]=groups}return out}function mergeActivityHooks(current,install,eventMap,inv=kobeHookInvocation(),opts={}){let verbs=eventMap.map((spec)=>spec.verb),{hooks:rawHooks,...restSettings}=current,hooks=isObject(rawHooks)?{...rawHooks}:{},built=install?buildActivityHooks(eventMap,inv,opts):{};for(let{event}of eventMap){let groups=hooks[event],prior=Array.isArray(groups)?groups:[],kept=removeRoveHooks(prior,verbs),additions=built[event];if(install&&Array.isArray(additions))kept.push(...additions);if(kept.length>0)hooks[event]=kept;else delete hooks[event]}return Object.keys(hooks).length>0?{...restSettings,hooks}:{...restSettings}}var RETIRED_WATCH_EVENT="PostToolUse";function removeWorktreeWatchHook(current){let{hooks:rawHooks,...restSettings}=current,hooks=isObject(rawHooks)?{...rawHooks}:{},groups=hooks[RETIRED_WATCH_EVENT],prior=Array.isArray(groups)?groups:[],kept=removeRoveHooks(prior,["worktree-created"]);if(kept.length>0)hooks[RETIRED_WATCH_EVENT]=kept;else delete hooks[RETIRED_WATCH_EVENT];return Object.keys(hooks).length>0?{...restSettings,hooks}:{...restSettings}}import{constants,closeSync,fstatSync,openSync,readSync}from"fs";import{open}from"fs/promises";var MAX_ENGINE_FILE_BYTES=104857600,MAX_JSONL_LINE_CHARS=8388608,READ_CHUNK_BYTES=65536,READ_FLAGS=constants.O_RDONLY|constants.O_NONBLOCK;async function readTextFileIfRegular(p,maxBytes=MAX_ENGINE_FILE_BYTES){let file=await open(p,READ_FLAGS);try{let info=await file.stat();if(!info.isFile()||info.size>maxBytes)return null;let chunks=[],total=0;while(total<=maxBytes){let buffer=Buffer.allocUnsafe(Math.min(READ_CHUNK_BYTES,maxBytes+1-total)),{bytesRead}=await file.read(buffer);if(bytesRead===0)return Buffer.concat(chunks,total).toString("utf8");chunks.push(buffer.subarray(0,bytesRead)),total+=bytesRead}return null}finally{await file.close()}}async function readTextFileBounded(p,maxBytes=MAX_ENGINE_FILE_BYTES){return await readTextFileIfRegular(p,maxBytes)??""}async function readFirstLineBounded(p,maxBytes=MAX_JSONL_LINE_CHARS){let file=await open(p,READ_FLAGS);try{if(!(await file.stat()).isFile())return"";let chunks=[],total=0,start=0,nonblank=!1;while(total<=maxBytes){let buffer=Buffer.allocUnsafe(Math.min(16384,maxBytes+1-total)),{bytesRead}=await file.read(buffer);if(!bytesRead)return Buffer.concat(chunks,total).subarray(start).toString("utf8");chunks.push(buffer.subarray(0,bytesRead));let segment=0;for(let i=0;i<bytesRead;i++){if(buffer[i]!==10)continue;nonblank||=buffer.subarray(segment,i).toString("utf8").trim().length>0;let end=total+i;if(end>maxBytes)return"";if(nonblank)return Buffer.concat(chunks,total+bytesRead).subarray(start,end).toString("utf8");start=end+1,segment=i+1}nonblank||=buffer.subarray(segment,bytesRead).toString("utf8").trim().length>0,total+=bytesRead}return""}finally{await file.close()}}function readTextFileSyncBounded(p,maxBytes=MAX_ENGINE_FILE_BYTES){try{return readTextFileIfRegularSync(p,maxBytes)}catch(err){if(err instanceof Error&&"code"in err&&err.code==="ENOENT")return null;throw err}}function readTextFileIfRegularSync(p,maxBytes=MAX_ENGINE_FILE_BYTES){let fd=openSync(p,READ_FLAGS);try{let info=fstatSync(fd);if(!info.isFile()||info.size>maxBytes)return null;let chunks=[],total=0;while(total<=maxBytes){let buffer=Buffer.allocUnsafe(Math.min(READ_CHUNK_BYTES,maxBytes+1-total)),bytesRead=readSync(fd,buffer);if(!bytesRead)return Buffer.concat(chunks,total).toString("utf8");chunks.push(buffer.subarray(0,bytesRead)),total+=bytesRead}return null}finally{closeSync(fd)}}function isJsonlLineWithinBound(line,maxChars=MAX_JSONL_LINE_CHARS){return line.length<=maxChars}import{createHash,randomBytes}from"crypto";import{mkdirSync,renameSync,unlinkSync,writeFileSync}from"fs";import{mkdir,rename,unlink,writeFile}from"fs/promises";import{dirname,join}from"path";var MAX_SHARED_CONFIG_BYTES=8388608;function stagingPath(file){return`${file}.rove-${process.pid}-${randomBytes(6).toString("hex")}.tmp`}function sharedConfigLockPath(file){return join(roveStateDir(),`shared-config-${createHash("sha256").update(file).digest("hex").slice(0,16)}.lock`)}var MAX_ATTEMPTS=5;function readSharedConfigSync(file){try{let raw=readTextFileIfRegularSync(file,MAX_SHARED_CONFIG_BYTES);if(raw===null)throw Error(`Refusing non-regular or oversized config: ${file}`);return raw}catch(err){if(err instanceof Error&&"code"in err&&err.code==="ENOENT")return;throw err}}async function readRaw(file){try{let raw=await readTextFileIfRegular(file,MAX_SHARED_CONFIG_BYTES);if(raw===null)throw Error(`Refusing non-regular or oversized config: ${file}`);return raw}catch(err){if(err instanceof Error&&"code"in err&&err.code==="ENOENT")return;throw err}}function updateSharedJsonSync(file,load,build){let lockPath=sharedConfigLockPath(file),lockToken=acquireSync(lockPath);try{for(let attempt=0;attempt<MAX_ATTEMPTS;attempt++){let before=readSharedConfigSync(file),doc=load(before);if(!doc)return;let text=build(doc);if(text===void 0)return;let tmp=stagingPath(file);try{if(mkdirSync(dirname(file),{recursive:!0}),writeFileSync(tmp,text,{mode:384,flag:"wx"}),readSharedConfigSync(file)===before){renameSync(tmp,file);return}}finally{try{unlinkSync(tmp)}catch{}}}throw Error(`gave up updating ${file} after ${MAX_ATTEMPTS} concurrent writes`)}finally{releaseSync(lockPath,lockToken)}}async function updateSharedJson(file,load,build){let lockPath=sharedConfigLockPath(file),lockToken=await acquireWithRetry(lockPath);try{for(let attempt=0;attempt<MAX_ATTEMPTS;attempt++){let before=await readRaw(file),doc=load(before);if(!doc)return;let text=build(doc);if(text===void 0)return;let tmp=stagingPath(file);try{if(await mkdir(dirname(file),{recursive:!0}),await writeFile(tmp,text,{mode:384,flag:"wx"}),await readRaw(file)===before){await rename(tmp,file);return}}finally{await unlink(tmp).catch(()=>{})}}throw Error(`gave up updating ${file} after ${MAX_ATTEMPTS} concurrent writes`)}finally{await release(lockPath,lockToken)}}async function editJsonSettings(settingsFilePath,transform,parse=parseHookSettings){let rejected;try{await updateSharedJson(settingsFilePath,(raw)=>{let parsed=parse(raw);if(parsed.ok)return parsed.doc;rejected=parsed.reason;return},(current)=>{let next=transform(current),json=JSON.stringify(next,null,2);return json===JSON.stringify(current,null,2)?void 0:`${json}
|
|
3
|
-
`})}catch(err){return{ok:!1,file:settingsFilePath,reason:err instanceof Error?err.message:String(err)}}if(rejected!==void 0)return{ok:!1,file:settingsFilePath,reason:rejected};return{ok:!0}}class JsonHookAdapter{supportsHooks(){return!0}activityDetailFromPayload(_kind,_payload){return}sessionFromPayload(_payload){return}supportsWorktreeSync(){return!1}async removeWorktreeSyncHook(_settingsFilePath){}gatedVerbs(){return GATED_TOOL_VERBS}async installActivityHooks(settingsFilePath,opts={}){let gated=this.gatedVerbs(),outcome=await editJsonSettings(settingsFilePath,(cur)=>mergeActivityHooks(cur,!0,this.eventMap,void 0,{extraArgs:roveHookArgs(this.vendor),buildFilter:(spec)=>opts.toolEvents===!0||!gated.has(spec.verb)}));if(!outcome.ok&&!opts.quiet)process.stderr.write(`[rove hooks] ${this.vendor}: skipped ${outcome.file}: ${outcome.reason}
|
|
4
|
-
`);return outcome}async removeActivityHooks(settingsFilePath){await editJsonSettings(settingsFilePath,(cur)=>mergeActivityHooks(cur,!1,this.eventMap))}async removeWorktreeWatchHook(settingsFilePath){await editJsonSettings(settingsFilePath,removeWorktreeWatchHook)}hookConfigRefusal(raw){let parsed=parseHookSettings(raw);return parsed.ok?void 0:parsed.reason}}import{homedir}from"os";import path from"path";var VENDOR_HOMES={claude:{envVar:"CLAUDE_CONFIG_DIR",dirName:".claude"},codex:{envVar:"CODEX_HOME",dirName:".codex"},copilot:{envVar:"COPILOT_HOME",dirName:".copilot"},kimi:{envVar:"KIMI_CODE_HOME",dirName:".kimi-code"}},AGENT_DIR_VENDORS={pi:{envVar:"PI_CODING_AGENT_DIR",dirName:".pi"},omp:{envVar:"PI_CODING_AGENT_DIR",dirName:".omp"}},defaultVendorHomeDeps={env:(name)=>process.env[name],home:()=>homedir()};function vendorWriteHomeDeps(home){return home===void 0?defaultVendorHomeDeps:{env:()=>{return},home:()=>home}}function vendorConfigHome(vendor,deps=defaultVendorHomeDeps){let{envVar,dirName}=VENDOR_HOMES[vendor],override=deps.env(envVar)?.trim();if(override)return override;return path.join(deps.home(),dirName)}function vendorAgentDir(vendor,deps=defaultVendorHomeDeps){let{envVar,dirName}=AGENT_DIR_VENDORS[vendor],override=deps.env(envVar)?.trim();if(override)return override;return path.join(deps.home(),dirName,"agent")}function depsOf(env,home){return{env,home:()=>home}}function claudeGlobalConfigPath(env,home){let override=env("CLAUDE_CONFIG_DIR")?.trim();if(override)return path.join(override,".claude.json");return path.join(home,".claude.json")}function codexAuthPath(env,home){return path.join(vendorConfigHome("codex",depsOf(env,home)),"auth.json")}function copilotConfigPath(env,home){return path.join(vendorConfigHome("copilot",depsOf(env,home)),"config.json")}function kimiCredentialsPath(env,home){return path.join(vendorConfigHome("kimi",depsOf(env,home)),"credentials","kimi-code.json")}
|
|
5
|
-
export{roveCliInvocation,kobeHookInvocation,ROVE_HOOK_VERSION,roveHookArgs,GATED_TOOL_VERBS,isObject,isRoveHook,removeRoveHooks,hasKobeActivityHooks,hookCommandQuoting,readTextFileIfRegular,readTextFileBounded,readFirstLineBounded,readTextFileSyncBounded,isJsonlLineWithinBound,readSharedConfigSync,updateSharedJsonSync,editJsonSettings,JsonHookAdapter,vendorWriteHomeDeps,vendorConfigHome,vendorAgentDir,claudeGlobalConfigPath,codexAuthPath,copilotConfigPath,kimiCredentialsPath};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{PS_PROBE_TIMEOUT_MS,engineProcessIn,foregroundEngine,foregroundEngineIn,hasAncestor,parsePsSnapshot,psSnapshot,psSnapshotWith,vendorFromArgv}from"./chunk-j6kataan.js";import"./chunk-ssfj9td0.js";import"./chunk-zwej00t0.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-2brn8e1y.js";import"./chunk-y3k1accw.js";import"./chunk-bw73t1zw.js";import"./chunk-7kysxgbq.js";import"./chunk-2xsem13q.js";import"./chunk-xy8be792.js";import"./chunk-05jej26n.js";import"./chunk-32mv1yy6.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import{PsProbeUnavailableError}from"./chunk-pxk2c2vj.js";import"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{vendorFromArgv,psSnapshotWith,psSnapshot,parsePsSnapshot,hasAncestor,foregroundEngineIn,foregroundEngine,engineProcessIn,PsProbeUnavailableError,PS_PROBE_TIMEOUT_MS};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{isEngineActivityKind}from"./chunk-17e2tgyg.js";import{loadPluginRegistry,readPluginManifest}from"./chunk-1da3bqjc.js";import{activityHookAdapters}from"./chunk-ssfj9td0.js";import{flagValue}from"./chunk-jvxh93nz.js";import{connectIfRunning}from"./chunk-wtqxv2rv.js";import{getPersistedString,setPersistedString}from"./chunk-32mv1yy6.js";import{activeCliName}from"./chunk-ppwpjm39.js";import{readRoveEnv}from"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{join,resolve}from"path";var STDIN_READ_TIMEOUT_MS=500;async function readTextWithTimeout(read,timeoutMs=STDIN_READ_TIMEOUT_MS){let raceTimer;try{return await Promise.race([read(),new Promise((resolve2)=>{raceTimer=setTimeout(()=>resolve2(""),timeoutMs)})])}finally{if(raceTimer!==void 0)clearTimeout(raceTimer)}}async function readStdinText(){let bun=globalThis.Bun;if(bun)return bun.stdin.text();if(process.stdin.isTTY)return"";let chunks=[];try{for await(let chunk of process.stdin)chunks.push(chunk)}finally{process.stdin.destroy()}return Buffer.concat(chunks).toString("utf8")}async function readStdinPayload(){try{let text=await readTextWithTimeout(readStdinText);if(!text.trim())return{};let parsed=JSON.parse(text);return parsed&&typeof parsed==="object"&&!Array.isArray(parsed)?parsed:{}}catch{return{}}}async function runHookSubcommand(argv){let[verb,...rest]=argv;if(verb==="setup"){await runHookSetup(rest);return}if(verb==="cleanup"){await runHookCleanup();return}try{if(!verb||!isEngineActivityKind(verb))return;let payload=await readStdinPayload(),payloadFlag=flagValue(rest,"--payload");if(payloadFlag)try{let extra=JSON.parse(payloadFlag);if(extra&&typeof extra==="object"&&!Array.isArray(extra))Object.assign(payload,extra)}catch{}let taskId=flagValue(rest,"--task-id"),envTaskId=process.env.KOBE_TASK_ID,envTabId=process.env.KOBE_TAB_ID,engine=flagValue(rest,"--engine"),adapters=activityHookAdapters().filter((a)=>!engine||a.vendor===engine);if(!taskId&&adapters.some((a)=>a.isUnattendedSession?.(process.env)===!0))return;let cwd=typeof payload.cwd==="string"&&payload.cwd?payload.cwd:void 0;for(let adapter of adapters){if(cwd)break;cwd=adapter.cwdFromPayload?.(payload)}cwd||=process.cwd();let detail;for(let adapter of adapters)if(detail=adapter.activityDetailFromPayload(verb,payload),detail)break;let session;for(let adapter of adapters)if(session=adapter.sessionFromPayload(payload),session)break;let client=await connectIfRunning();if(!client)return;try{let effectiveTaskId=taskId??envTaskId;await client.request("engine.reportEvent",{...effectiveTaskId?{taskId:effectiveTaskId}:{cwd},kind:verb,...engine?{engine}:{},...envTabId?{tabId:envTabId}:{},...detail?{detail}:{},...session?{sessionId:session.sessionId}:{},...session?.transcriptPath?{transcriptPath:session.transcriptPath}:{}})}finally{client.close()}}catch(err){if(readRoveEnv("HOOK_DEBUG"))console.error(`[rove hook] ${verb} failed:`,err instanceof Error?err.message:String(err))}}var SYNC_SETTING_KEY="externalWorktreeSync";function worktreeSyncAdapters(){return activityHookAdapters().filter((a)=>a.supportsWorktreeSync())}function globalSettingsPath(){return worktreeSyncAdapters()[0]?.globalSettingsPath()}function persistedSyncPath(stored){if(!stored||stored==="off")return;if(stored==="global")return globalSettingsPath();if(stored.startsWith("repo:"))return join(resolve(stored.slice(5)),".claude","settings.json");return stored}async function ensureGlobalKobeHooks(opts={}){try{let{isRovePluginEnabled,detectLegacyInstalls,migrationHint}=await import("./chunk-079cyb2e.js"),pluginMode=isRovePluginEnabled();if(pluginMode){let hint=migrationHint(detectLegacyInstalls(),activeCliName());if(hint)process.stderr.write(`
|
|
3
|
-
${hint}
|
|
4
|
-
`)}let toolEvents=pluginsWantToolEvents();for(let a of activityHookAdapters()){if(pluginMode&&a.vendor==="claude")continue;let enginePath=a.globalSettingsPath();if(!enginePath)continue;await a.installActivityHooks(enginePath,{toolEvents,quiet:opts.quiet}),await a.removeWorktreeWatchHook(enginePath)}await cleanupWorktreeSyncHook()}catch{}}function pluginsWantToolEvents(){try{for(let entry of loadPluginRegistry().plugins){if(!entry.enabled)continue;try{if(readPluginManifest(entry.root).manifest.events.some((e)=>e.on.startsWith("tool.")))return!0}catch{}}}catch{}return!1}async function cleanupWorktreeSyncHook(){let adapters=worktreeSyncAdapters();if(adapters.length===0)return;let stored=getPersistedString(SYNC_SETTING_KEY),paths=new Set;for(let adapter of adapters){let file=adapter.globalSettingsPath();if(file)paths.add(file)}let prev=persistedSyncPath(stored);if(prev)paths.add(prev);for(let a of adapters)for(let p of paths)await a.removeWorktreeSyncHook(p);if(stored!=="off")setPersistedString(SYNC_SETTING_KEY,"off")}async function runHookCleanup(){let claude=activityHookAdapters().find((a)=>a.vendor==="claude"),path=claude?.globalSettingsPath();if(!claude||!path){process.stdout.write(`rove hook cleanup: no Claude hook adapter \u2014 nothing to do.
|
|
5
|
-
`);return}await claude.removeActivityHooks(path),await claude.removeWorktreeWatchHook(path),process.stdout.write([`rove hook cleanup: removed Rove's settings-managed hooks from ${path}.`,"Only Rove's own entries were touched; your other hooks are intact.","The Claude Code plugin's hooks.json now carries these events (if the plugin","is not installed, the next Rove launch reinstalls the settings-managed set).",""].join(`
|
|
6
|
-
`))}async function runHookSetup(_argv){await cleanupWorktreeSyncHook(),process.stdout.write(["rove hook setup is deprecated and now a no-op (cleanup only).","","The old external-worktree sync used a global WorktreeCreate hook, which is","a VCS provider hook \u2014 its presence broke `claude --worktree` / EnterWorktree","in every repo. Any hook Rove previously installed has been removed.","","Sync is now automatic: a `claude --worktree` (or any session) started in a","worktree under a repo Rove already tracks is adopted as a task on launch.","To adopt existing worktrees on demand, use the New Task dialog or `rove adopt`.",""].join(`
|
|
7
|
-
`))}
|
|
8
|
-
export{readTextWithTimeout,readStdinText,runHookSubcommand,ensureGlobalKobeHooks};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ENGINE_EXIT_BANNER,engineExitCodeFromTail,plainTail,readPtyExitRecords,readPtyExitStore,recordEngineExit,recordPtyExit}from"./chunk-g3r1dwy9.js";import"./chunk-w25b7xxz.js";import"./chunk-9prawccj.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{recordPtyExit,recordEngineExit,readPtyExitStore,readPtyExitRecords,plainTail,engineExitCodeFromTail,ENGINE_EXIT_BANNER};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ensureForwards}from"./chunk-7txq91d9.js";import{dedupeMachines,listMachines,localDaemonSocketPath}from"./chunk-bs7v83x0.js";import{ApiError}from"./chunk-f7zjggfv.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import{KobeDaemonClient}from"./chunk-qagek3wg.js";import"./chunk-544bwsss.js";import"./chunk-hqbmzz4t.js";import"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";function remoteTaskUnsupported(taskId,machineId){return new ApiError(`task ${taskId} lives on machine "${machineId}". Rove can list it, but acting on a remote task is not supported yet.`,"NOT_YET_SUPPORTED_REMOTE",{taskId,machineId,hint:`run the command on ${machineId} itself; remote writes arrive in a later release`,nextCommandArgs:["machine","list"]})}async function machineTasks(entry){let socketPath=localDaemonSocketPath(entry.alias),direct=await tasksOf(socketPath);if(direct)return direct;if(!entry.sockets)return null;return await ensureForwards({alias:entry.alias,config:entry,remoteDaemonSocket:entry.sockets.daemon,remotePtySocket:entry.sockets.pty})?await tasksOf(socketPath):null}async function tasksOf(socketPath){let client=new KobeDaemonClient(socketPath);try{return await client.request("hello",{}),(await client.request("task.list")).tasks??[]}catch{return null}finally{client.close()}}async function mergeTaskList(local){let machines=dedupeMachines(listMachines());if(machines.length===0)return local;let tasks=(local.tasks??[]).map((task)=>({...task,origin:{machineId:"local",hostLabel:"local"}}));for(let entry of machines){let remote=await machineTasks(entry);if(!remote)continue;let hostLabel=entry.alias;for(let task of remote)tasks.push({...task,origin:{machineId:entry.alias,hostLabel}})}return{tasks}}async function assertLocalTask(taskId){if(!taskId)return;let machines=dedupeMachines(listMachines());if(machines.length===0)return;for(let entry of machines){let remote=await machineTasks(entry);if(!remote)continue;if(remote.some((task)=>task.id===taskId))throw remoteTaskUnsupported(taskId,entry.alias)}}export{mergeTaskList,assertLocalTask};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{detectLanguage}from"./chunk-hape5vwj.js";import{getRepoInitOverride}from"./chunk-32mv1yy6.js";import{existsSync}from"fs";import{join as join2}from"path";import{readFileSync}from"fs";import{join}from"path";var REPO_CONFIG_DIRS=[".rove",".kobe"];function repoConfigCandidates(repoDir,filename){return REPO_CONFIG_DIRS.map((dir)=>join(repoDir,dir,filename))}function readFirstNonEmptyRepoFile(repoDir,filename){for(let candidate of repoConfigCandidates(repoDir,filename))if(isNonEmptyRepoFile(candidate))return readFileSync(candidate,"utf8");return}function isNonEmptyRepoFile(absolutePath){try{return readFileSync(absolutePath,"utf8").trim().length>0}catch{return!1}}var LOCKFILE_DEPENDENCY_DIRS=[["bun.lock","node_modules"],["bun.lockb","node_modules"],["package-lock.json","node_modules"],["yarn.lock","node_modules"],["pnpm-lock.yaml","node_modules"],["Cargo.lock","target"],["poetry.lock",".venv"],["uv.lock",".venv"]];function missingDependenciesCoda(worktreePath,language){let missing=new Set;for(let[lockfile,dependencyDir]of LOCKFILE_DEPENDENCY_DIRS){if(!existsSync(join2(worktreePath,lockfile)))continue;if(existsSync(join2(worktreePath,dependencyDir)))continue;missing.add(dependencyDir)}if(missing.size===0)return;let dirs=[...missing].join(", ");if(language==="zh")return`\u8865\u5145\uFF1A\u8FD9\u4E2A worktree \u6CA1\u6709\u88C5\u4F9D\u8D56\uFF08\u4ED3\u5E93\u91CC\u6709 lockfile\uFF0C\u4F46 ${dirs} \u4E0D\u5B58\u5728\uFF09\u3002\u5728\u76F8\u4FE1\u4EFB\u4F55\u6784\u5EFA / \u6D4B\u8BD5\u7ED3\u679C\u4E4B\u524D\uFF0C\u5148\u8DD1\u4E00\u904D\u672C\u4ED3\u5E93\u7684\u5B89\u88C5\u6B65\u9AA4\u2014\u2014\u8FD9\u91CC\u7684\u5931\u8D25\u591A\u534A\u662F\u56E0\u4E3A\u6CA1\u88C5\u4F9D\u8D56\uFF0C\u800C\u4E0D\u662F\u4EE3\u7801\u56DE\u5F52\u3002\u5982\u679C\u8FD9\u4E2A\u4ED3\u5E93\u6BCF\u6B21\u90FD\u9700\u8981\u88C5\uFF0C\u53EF\u4EE5\u8003\u8651\u52A0\u4E00\u4E2A \`.rove/init.sh\`\u3002`;return`PS: this worktree has no installed dependencies (${dirs} missing beside a committed lockfile). Run the repo's install step before trusting build/test results \u2014 a failure here is most likely the missing install, not a regression. If this repo always needs one, consider adding \`.rove/init.sh\`.`}var INIT_SCRIPT_FILENAME="init.sh",INIT_PROMPT_FILENAME="init-prompt.md";function repoFileScript(worktreePath){for(let dir of REPO_CONFIG_DIRS)if(existsSync(join2(worktreePath,dir,INIT_SCRIPT_FILENAME)))return`sh ${dir}/${INIT_SCRIPT_FILENAME}`;return}function repoFilePrompt(worktreePath){return readFirstNonEmptyRepoFile(worktreePath,INIT_PROMPT_FILENAME)}function describeRepoInitSources(repoRoot){let describe=(filename,counts)=>{let taken=!1;return REPO_CONFIG_DIRS.map((dir)=>{let absolute=join2(repoRoot,dir,filename),effective=!taken&&counts(absolute);if(effective)taken=!0;return{rel:`${dir}/${filename}`,present:existsSync(absolute),effective}})};return{script:describe(INIT_SCRIPT_FILENAME,existsSync),prompt:describe(INIT_PROMPT_FILENAME,isNonEmptyRepoFile)}}function resolveRepoInit(repoRoot,worktreePath){let override=repoRoot?getRepoInitOverride(repoRoot):{},initScript=repoFileScript(worktreePath)??override.initScript,initPrompt=repoFilePrompt(worktreePath)??override.initPrompt;return{initScript:initScript&&initScript.trim().length>0?initScript:void 0,initPrompt:initPrompt&&initPrompt.trim().length>0?initPrompt:void 0}}function firstMessageFor(intent,init,worktreePath){if(intent.kind==="none")return;if(intent.kind==="explicit")return{source:"explicit",text:intent.prompt};if(intent.kind==="new-task"){let deps=init.initScript?void 0:missingDependenciesCoda(worktreePath,detectLanguage(intent.prompt)??void 0);return{source:"explicit",text:[intent.prompt,deps].filter(Boolean).join(`
|
|
3
|
-
|
|
4
|
-
`)}}let text=init.initPrompt?.trim();return text?{source:"repo-init",text}:void 0}function resolveEngineLaunchInit(repoRoot,worktreePath,intent={kind:"repo-init"}){let init=resolveRepoInit(repoRoot,worktreePath);return{initScript:init.initScript,firstMessage:firstMessageFor(intent,init,worktreePath)}}
|
|
5
|
-
export{readFirstNonEmptyRepoFile,missingDependenciesCoda,describeRepoInitSources,resolveRepoInit,resolveEngineLaunchInit};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{getGlobalDefaultVendor,getRepoLastActiveVendor,resolvePreferredVendor,setGlobalDefaultVendor,setRepoLastActiveVendor}from"./chunk-dq2mh3b3.js";import"./chunk-xy8be792.js";import"./chunk-05jej26n.js";import"./chunk-32mv1yy6.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{setRepoLastActiveVendor,setGlobalDefaultVendor,resolvePreferredVendor,getRepoLastActiveVendor,getGlobalDefaultVendor};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{openDaemonSession,resolveActiveTaskId}from"./chunk-snjte1rd.js";import"./chunk-wtqxv2rv.js";import"./chunk-pz907kve.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-qagek3wg.js";import"./chunk-544bwsss.js";import"./chunk-hqbmzz4t.js";import"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{resolveActiveTaskId,openDaemonSession};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ensureForwards,startTunnel}from"./chunk-7txq91d9.js";import"./chunk-bs7v83x0.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{startTunnel,ensureForwards};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{LEGACY_KOBE_CONFIG_DIR_BASENAME,LEGACY_KOBE_STATE_DIR_BASENAME,ROVE_CONFIG_DIR_BASENAME,ROVE_STATE_DIR_BASENAME}from"./chunk-sb0ns0c7.js";import{readRoveHomeDirEnv}from"./chunk-hq4b3fca.js";import{randomUUID}from"crypto";import{constants,chmodSync,closeSync,copyFileSync,fsyncSync,linkSync,lstatSync,mkdirSync,openSync,readdirSync,readlinkSync,renameSync,statSync,symlinkSync,unlinkSync,writeFileSync}from"fs";import{homedir}from"os";import{dirname,join}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 lstatSync(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}-${randomUUID()}.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}-${randomUUID()}.tmp`;try{writeFileSync(temp,`legacy kobe 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 readdirSync(source))copied+=copyMissing(join(source,name),join(destination,name));return copied}if(mkdirSync(dirname(destination),{recursive:!0}),sourceStat.isDirectory()){mkdirSync(destination,{recursive:!0,mode:sourceStat.mode});let copied=0;for(let name of readdirSync(source))copied+=copyMissing(join(source,name),join(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=join(home,LEGACY_KOBE_STATE_DIR_BASENAME),roveState=join(home,ROVE_STATE_DIR_BASENAME),legacyConfig=join(home,".config",LEGACY_KOBE_CONFIG_DIR_BASENAME,"state.json"),roveConfig=join(home,".config",ROVE_CONFIG_DIR_BASENAME,"state.json"),marker=join(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(join(legacyState,name),join(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){mkdirSync(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=join(home,LEGACY_KOBE_STATE_DIR_BASENAME),roveState=join(home,ROVE_STATE_DIR_BASENAME),marker=join(roveState,PLUGIN_MIGRATION_MARKER);try{if(lstatIfExists(marker)||lstatIfExists(join(roveState,"plugins.json")))return{attempted:!1,copied:0,warnings:[]};if(!lstatIfExists(join(legacyState,"plugins.json")))return{attempted:!1,copied:0,warnings:[]}}catch(err){return{attempted:!0,copied:0,warnings:[`plugin migration preflight: ${errorText(err)}`]}}mkdirSync(roveState,{recursive:!0});let moved=0,warnings=[];for(let name of PLUGIN_ENTRIES){let source=join(legacyState,name),destination=join(roveState,name);try{if(!lstatIfExists(source)||lstatIfExists(destination))continue;renameSync(source,destination),moved+=1;try{symlinkSync(destination,source)}catch{}}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);return{attempted:state.attempted||plugins.attempted,copied:state.copied+plugins.copied,warnings:[...state.warnings,...plugins.warnings]}}
|
|
4
|
-
export{DAEMON_MIGRATION_MARKER,migrateRoveClientStateLayout,migrateRoveDaemonStateLayout};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{stripTerminalControls,terminalRows}from"./chunk-w25b7xxz.js";import{OWNER_ONLY_FILE_MODE}from"./chunk-9prawccj.js";import{defaultPtyExitsPath}from"./chunk-y8fqdnh3.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 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])=>a.at<b.at?1:-1).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,readPtyExitStore,readPtyExitRecords,recordPtyExit,recordEngineExit};
|