@sma1lboy/rove 0.9.230 → 0.9.231
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{chunk-ca5g8vdg.js → chunk-079cyb2e.js} +1 -1
- package/dist/cli/{chunk-ntfv1dwn.js → chunk-1erdbkyt.js} +1 -1
- package/dist/cli/{chunk-hg87p5n8.js → chunk-32mv1yy6.js} +1 -1
- package/dist/cli/{chunk-2gk4hw2f.js → chunk-37zse6x1.js} +1 -1
- package/dist/cli/{chunk-gjtyxam6.js → chunk-3hz2v172.js} +1 -1
- package/dist/cli/{chunk-b1kg21v2.js → chunk-3sg5v7cg.js} +1 -1
- package/dist/cli/{chunk-vh5bkm9k.js → chunk-4d54zgc7.js} +1 -1
- package/dist/cli/{chunk-cpt1cg44.js → chunk-4hhee3vk.js} +2 -2
- package/dist/cli/{chunk-pdx9keeg.js → chunk-4rgy3ccz.js} +1 -1
- package/dist/cli/{chunk-k41s39aj.js → chunk-659fk8gs.js} +2 -2
- package/dist/cli/{chunk-1ksrew4v.js → chunk-6s5mev2n.js} +1 -1
- package/dist/cli/{chunk-4vsrjqz8.js → chunk-76gqd96j.js} +1 -1
- package/dist/cli/{chunk-j7gt47dd.js → chunk-7ded3me8.js} +1 -1
- package/dist/cli/{chunk-epj4jps9.js → chunk-7gbjyt24.js} +1 -1
- package/dist/cli/{chunk-frrjz0dr.js → chunk-7s1kx9ez.js} +1 -1
- package/dist/cli/{chunk-sjwre940.js → chunk-8041pnt0.js} +1 -1
- package/dist/cli/{chunk-n3a4ffgd.js → chunk-89y20805.js} +1 -1
- package/dist/cli/{chunk-3htqngp4.js → chunk-8pa1ph1s.js} +1 -1
- package/dist/cli/{chunk-mwf7v41t.js → chunk-8ze8f69d.js} +1 -1
- package/dist/cli/{chunk-mv2wxz2h.js → chunk-9jz2z1v9.js} +1 -1
- package/dist/cli/{chunk-57q6gykd.js → chunk-9k47xr7m.js} +1 -1
- package/dist/cli/{chunk-4m8kfaey.js → chunk-avy6jenq.js} +1 -1
- package/dist/cli/{chunk-x93antc5.js → chunk-b127p4wa.js} +1 -1
- package/dist/cli/{chunk-fc9bvzds.js → chunk-cfk8ntfc.js} +1 -1
- package/dist/cli/chunk-ch0ehc06.js +3 -0
- package/dist/cli/{chunk-28wqt1yd.js → chunk-cv1kaq8a.js} +2 -2
- package/dist/cli/{chunk-ctn9bd5z.js → chunk-d4kh54nc.js} +1 -1
- package/dist/cli/{chunk-5zgrym8y.js → chunk-d9sv5x1j.js} +1 -1
- package/dist/cli/{chunk-5fqdbk78.js → chunk-d9trak46.js} +1 -1
- package/dist/cli/{chunk-zm2f0d23.js → chunk-dnbh8hsm.js} +1 -1
- package/dist/cli/{chunk-3wb64q0p.js → chunk-dq2mh3b3.js} +1 -1
- package/dist/cli/{chunk-c46jm1nj.js → chunk-e4a8pvek.js} +1 -1
- package/dist/cli/{chunk-nnz4r6p4.js → chunk-egx76ah2.js} +1 -1
- package/dist/cli/{chunk-bm1z1zsp.js → chunk-ex1a2djb.js} +1 -1
- package/dist/cli/{chunk-857xzvfh.js → chunk-ffvn17at.js} +1 -1
- package/dist/cli/{chunk-r84kan7b.js → chunk-gmgsxdrf.js} +1 -1
- package/dist/cli/{chunk-ntr5zmav.js → chunk-h4qv19v8.js} +1 -1
- package/dist/cli/{chunk-qqkw8v6p.js → chunk-hnfp317x.js} +1 -1
- package/dist/cli/{chunk-rhczy26f.js → chunk-j1ms7bdj.js} +3 -3
- package/dist/cli/{chunk-sh0amz8z.js → chunk-jdph7s6t.js} +3 -3
- package/dist/cli/{chunk-bx2m48tf.js → chunk-jgq6dw3f.js} +1 -1
- package/dist/cli/{chunk-9wyr389k.js → chunk-jjt87qcx.js} +8 -8
- package/dist/cli/{chunk-ghxhqkey.js → chunk-k8tspshr.js} +1 -1
- package/dist/cli/{chunk-q70h7675.js → chunk-kn7g7j09.js} +2 -2
- package/dist/cli/{chunk-m9y3ehq9.js → chunk-ma6m37fe.js} +1 -1
- package/dist/cli/{chunk-fx127943.js → chunk-md8k7c5w.js} +1 -1
- package/dist/cli/{chunk-7sd9m43a.js → chunk-mppda1wq.js} +1 -1
- package/dist/cli/{chunk-1arwygap.js → chunk-ngjqajxa.js} +3 -3
- package/dist/cli/chunk-nh4wvyz3.js +3 -0
- package/dist/cli/chunk-p2c6qka0.js +4 -0
- package/dist/cli/{chunk-rdj6ffbz.js → chunk-pd8bnca7.js} +1 -1
- package/dist/cli/{chunk-fdf4cx4p.js → chunk-pj1mbjwx.js} +1 -1
- package/dist/cli/{chunk-12n1vt01.js → chunk-pvw2y93q.js} +2 -2
- package/dist/cli/{chunk-wapcw2dp.js → chunk-q06z22dy.js} +1 -1
- package/dist/cli/{chunk-71hnc45w.js → chunk-q2197tc1.js} +1 -1
- package/dist/cli/{chunk-d1a1kw0c.js → chunk-s1p650mm.js} +1 -1
- package/dist/cli/{chunk-h9gh63kp.js → chunk-t3wwsz29.js} +1 -1
- package/dist/cli/{chunk-d0dqgk8f.js → chunk-t5srf5gy.js} +1 -1
- package/dist/cli/{chunk-qdf1zd98.js → chunk-tgrzz3pv.js} +1 -1
- package/dist/cli/{chunk-1r7fmapn.js → chunk-th3ff61b.js} +1 -1
- package/dist/cli/{chunk-wx8s1cxr.js → chunk-tj5a3sfy.js} +1 -1
- package/dist/cli/{chunk-3y7qszq1.js → chunk-tndtdhy7.js} +1 -1
- package/dist/cli/{chunk-4jgegyt3.js → chunk-vqsrtavd.js} +3 -3
- package/dist/cli/{chunk-ggq4vsdv.js → chunk-ww4fbx8h.js} +1 -1
- package/dist/cli/{chunk-y5y0sc9a.js → chunk-ynbfqbn9.js} +1 -1
- package/dist/cli/{chunk-mr1etb82.js → chunk-z1htxy4a.js} +1 -1
- package/dist/cli/{chunk-kemcgh1c.js → chunk-z6yqkkgj.js} +1 -1
- package/dist/cli/{chunk-gbqmwpgw.js → chunk-zk7z3b36.js} +1 -1
- package/dist/cli/{chunk-7mfjczcz.js → chunk-zwej00t0.js} +1 -1
- package/dist/cli/index.js +7 -7
- package/dist/cli/kobe.js +1 -1
- package/dist/cli/rove.js +1 -1
- package/dist/web-ui/assets/{harness-DiS1yHqA.js → harness-C1oE8ZEf.js} +1 -1
- package/dist/web-ui/assets/index-DQjknI0o.js +11 -0
- package/dist/web-ui/index.html +1 -1
- package/dist/web-ui/pty-server.mjs +4 -1
- package/dist/web-ui/pty-session-lifecycle.mjs +35 -0
- package/package.json +3 -3
- package/dist/cli/chunk-59xc6m1q.js +0 -3
- package/dist/cli/chunk-chmhmxmc.js +0 -4
- package/dist/cli/chunk-xb9b93ts.js +0 -3
- package/dist/web-ui/assets/index-DxszcdCE.js +0 -10
- /package/dist/cli/{chunk-pdj8kqa1.js → chunk-85q2tgmg.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{CLAUDE_HOOK_EVENT_MAP,claudeSettingsPath}from"./chunk-y3k1accw.js";import{hasKobeActivityHooks,isObject}from"./chunk-bw73t1zw.js";import"./chunk-7kysxgbq.js";import"./chunk-2xsem13q.js";import"./chunk-xy8be792.js";import"./chunk-05jej26n.js";import{installedSkillDirs}from"./chunk-
|
|
2
|
+
import{CLAUDE_HOOK_EVENT_MAP,claudeSettingsPath}from"./chunk-y3k1accw.js";import{hasKobeActivityHooks,isObject}from"./chunk-bw73t1zw.js";import"./chunk-7kysxgbq.js";import"./chunk-2xsem13q.js";import"./chunk-xy8be792.js";import"./chunk-05jej26n.js";import{installedSkillDirs}from"./chunk-pvw2y93q.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"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";import{readFileSync}from"fs";import{homedir}from"os";var PLUGIN_NAME="rove";function readSettings(path){try{let parsed=JSON.parse(readFileSync(path,"utf8"));return isObject(parsed)?parsed:null}catch{return null}}function isRovePluginEnabled(settingsFilePath=claudeSettingsPath()){let settings=readSettings(settingsFilePath);if(!settings||!isObject(settings.enabledPlugins))return!1;return Object.entries(settings.enabledPlugins).some(([key,on])=>on===!0&&key.split("@")[0]===PLUGIN_NAME)}function detectLegacyInstalls(opts={}){let settingsFilePath=opts.settingsFilePath??claudeSettingsPath(),home=opts.home??homedir(),settings=readSettings(settingsFilePath),legacyHooks=settings!==null&&(hasKobeActivityHooks(settings,CLAUDE_HOOK_EVENT_MAP)||settingsHasWorktreeWatch(settings)),legacySkillDirs=installedSkillDirs(home);return{legacyHooks,legacySkillDirs}}function settingsHasWorktreeWatch(settings){let hooks=isObject(settings.hooks)?settings.hooks:{};return Object.values(hooks).some((groups)=>Array.isArray(groups)&&groups.some((g)=>isObject(g)&&Array.isArray(g.hooks)&&g.hooks.some((h)=>isObject(h)&&typeof h.command==="string"&&h.command.includes("worktree-created")&&!h.command.includes("CLAUDE_PLUGIN_ROOT"))))}function migrationHint(findings,cliName){if(!findings.legacyHooks&&findings.legacySkillDirs.length===0)return null;let lines=[`${cliName}: the Rove Claude Code plugin is enabled, but legacy installs remain:`];if(findings.legacyHooks)lines.push(" \u2022 ~/.claude/settings.json still has the settings-managed Rove hooks (every event fires TWICE).",` Run \`${cliName} hook cleanup\` to remove them (only Rove's own entries are touched).`);for(let dir of findings.legacySkillDirs)lines.push(` \u2022 legacy skill copy at ${dir} (the plugin bundles the skill \u2014 two copies double-register).`," Remove that directory to keep the plugin's copy only.");return lines.push(" Reading this inside a session? Just ask your agent to run the cleanup for you."),`${lines.join(`
|
|
3
3
|
`)}
|
|
4
4
|
`}export{migrationHint,isRovePluginEnabled,detectLegacyInstalls};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{formatBytes,hookConfigIssues}from"./chunk-
|
|
2
|
+
import{formatBytes,hookConfigIssues}from"./chunk-3hz2v172.js";import{inspectLegacyTmux,legacyTmuxDoctorLines}from"./chunk-dqndd97s.js";import"./chunk-ngjqajxa.js";import"./chunk-85pk7c74.js";import"./chunk-53afdybj.js";import"./chunk-rz8zs7j8.js";import{describeAccount,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-ffvn17at.js";import"./chunk-mhg40es1.js";import"./chunk-r2pztgm6.js";import"./chunk-1da3bqjc.js";import"./chunk-85mk6j0s.js";import"./chunk-xsrcwcjc.js";import"./chunk-nh4wvyz3.js";import{resolveNodeBinary}from"./chunk-pd8bnca7.js";import{formatDaemonInfo}from"./chunk-rcyasw34.js";import"./chunk-exfyqsdd.js";import"./chunk-p2c6qka0.js";import"./chunk-j1ms7bdj.js";import"./chunk-zwej00t0.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-g3r1dwy9.js";import"./chunk-w25b7xxz.js";import"./chunk-h4n8ffqy.js";import"./chunk-vyb5a2rh.js";import"./chunk-jvxh93nz.js";import{isStaleInstallError,resolveKobeSpawn}from"./chunk-wtqxv2rv.js";import"./chunk-pz907kve.js";import"./chunk-2brn8e1y.js";import"./chunk-y3k1accw.js";import"./chunk-bw73t1zw.js";import"./chunk-7kysxgbq.js";import{readableLegacyIndexPath}from"./chunk-2xsem13q.js";import"./chunk-xy8be792.js";import"./chunk-05jej26n.js";import{CURRENT_VERSION,package_default}from"./chunk-th3ff61b.js";import{kobeSkillState,skillInstallCommand}from"./chunk-pvw2y93q.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{homeDir,kvStatePath,roveStateDir}from"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import{LEGACY_KOBE_STATE_DIR_BASENAME}from"./chunk-sb0ns0c7.js";import{readPidFile}from"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import{t}from"./chunk-vhhje5qd.js";import"./chunk-tj5qmh2g.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.js";import{KobeDaemonClient}from"./chunk-qagek3wg.js";import{isForeignDaemonHome}from"./chunk-544bwsss.js";import"./chunk-hqbmzz4t.js";import"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath}from"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{existsSync,readFileSync as readFileSync2,statSync as statSync2}from"fs";import{join as join2}from"path";var MIN_BUN_VERSION=package_default.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0";function parseBunVersion(raw){return raw.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function isBunAtLeast(raw,minimum=MIN_BUN_VERSION){let found=parseBunVersion(raw),floor=parseBunVersion(minimum);if(!found||!floor)return!0;let a=found.split(".").map(Number),b=floor.split(".").map(Number);for(let i=0;i<3;i++){let av=a[i]??0,bv=b[i]??0;if(av!==bv)return av>bv}return!0}import{createInterface}from"readline";function daemonRestartFix(cliName,reason){return{kind:"run",id:"daemon-restart",label:t(`doctor.fix.${reason}`),command:[cliName,"daemon","restart"],why:t("doctor.fix.daemonRestartWhy")}}function skillInstallFix(installCommand,stale){return{kind:"run",id:"skill-install",label:t(stale?"doctor.fix.skillStale":"doctor.fix.skillMissing"),command:installCommand.split(" "),why:t("doctor.fix.skillInstallWhy")}}function resetManualFix(cliName,reason){return{kind:"manual",id:`reset:${reason}`,label:t(`doctor.fix.${reason}`),action:`${cliName} reset`,why:t("doctor.fix.resetWhy")}}function killOrphansManualFix(cliName,count){return{kind:"manual",id:"kill-orphans",label:t("doctor.fix.orphans",{count}),action:`${cliName} doctor --kill-orphans`,why:t("doctor.fix.orphansWhy")}}function engineTabsManualFix(){return{kind:"manual",id:"engine-tabs",label:t("doctor.fix.engineTabs"),action:t("doctor.fix.engineTabsAction"),why:t("doctor.fix.engineTabsWhy")}}function reinstallManualFix(){return{kind:"manual",id:"reinstall",label:t("doctor.fix.staleInstall"),action:t("doctor.fix.staleInstallAction"),why:t("doctor.fix.staleInstallWhy")}}function spawnHelperFix(paths){return{kind:"run",id:"spawn-helper-chmod",label:t("doctor.fix.spawnHelper"),command:["chmod","755",...paths],why:t("doctor.fix.spawnHelperWhy")}}function humanOnlyFix(reason,vars){return{kind:"manual",id:reason,label:t(`doctor.fix.${reason}`),action:t(`doctor.fix.${reason}Action`,vars),why:t("doctor.fix.humanOnlyWhy")}}function noEngineFix(signedOut){return signedOut.length>0?humanOnlyFix("noEngineLogin",{list:signedOut.join(", ")}):humanOnlyFix("noEngine")}function dedupeFixes(fixes){let seen=new Set;return fixes.filter((fix)=>{if(seen.has(fix.id))return!1;return seen.add(fix.id),!0})}async function applyFixes(collected,rt){let fixes=dedupeFixes(collected);if(fixes.length===0){rt.out(""),rt.out(t("doctor.fix.none"));return}let runnable=fixes.filter((fix)=>fix.kind==="run");if(runnable.length>0){rt.out(""),rt.out(t("doctor.fix.header"));for(let fix of runnable){if(rt.out(` ${fix.label}`),rt.out(` ${t("doctor.fix.willRun",{command:fix.command.join(" ")})}`),rt.out(` ${fix.why}`),!rt.interactive)continue;if(!await rt.confirm(` ${t("doctor.fix.confirmPrompt")}`)){rt.out(` ${t("doctor.fix.skipped")}`);continue}let code=await rt.exec(fix.command);rt.out(code===0?` ${t("doctor.fix.done")}`:` ${t("doctor.fix.failed",{code})}`)}if(!rt.interactive)rt.out(` ${t("doctor.fix.nonInteractive")}`)}let manual=fixes.filter((fix)=>fix.kind==="manual");if(manual.length>0){rt.out(""),rt.out(t("doctor.fix.manualHeader"));for(let fix of manual)rt.out(` ${fix.label}`),rt.out(` \u2192 ${fix.action}`),rt.out(` ${fix.why}`)}}async function confirmTty(question){let readline=createInterface({input:process.stdin,output:process.stdout});try{let answer=await new Promise((resolve)=>readline.question(question,resolve));return answer.trim().toLowerCase()==="y"||answer.trim().toLowerCase()==="yes"}finally{readline.close()}}async function execInherited(command){try{return await Bun.spawn([...command],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited}catch{return 127}}function defaultFixRuntime(){return{confirm:confirmTty,exec:execInherited,out:(line)=>console.log(line),interactive:process.stdin.isTTY===!0}}function classifyHookChannel(input){let total=0,hooked=0;for(let tabs of Object.values(input.tabs))for(let entry of Object.values(tabs))if(total++,entry.source==="hook")hooked++;if(total===0)return{kind:"no-tabs"};if(hooked===0)return{kind:"down",totalTabs:total};return{kind:"live",hookTabs:hooked,totalTabs:total}}function hookChannelDoctorLines(verdict,input,cliName){let configLines=(input.configIssues??[]).flatMap((issue)=>[` \u26A0 hook install skipped: ${issue.file}`,` ${issue.reason} \u2014 fix the file, then relaunch Rove`]);if(verdict.kind==="no-tabs")return["hooks: \u2014 no engine tabs yet (nothing to check)",...configLines];if(verdict.kind==="live")return[`hooks: \u2713 engine hook channel live (${verdict.hookTabs}/${verdict.totalTabs} tab(s) hook-sourced)`,...configLines];let out=[`hooks: \u2717 NO hook events reaching the daemon (0/${verdict.totalTabs} tab(s) hook-sourced)`," badges fall back to a ~10s poll, so activity looks seconds late",` daemon socket: ${input.socketPath}`,...configLines];return out.push(' \u2192 compare with an engine tab\'s own path: `ps eww -p <engine-pid> | tr " " "\\n" | grep DAEMON_SOCKET_PATH`',` \u2192 restart the engine tabs (they may hold a stale socket path), or run \`${cliName} daemon restart\``,` \u2192 debug one hook directly: \`KOBE_HOOK_DEBUG=1 echo '{}' | ${cliName} hook turn-start --engine claude\``),out}import{readdirSync,statSync}from"fs";import{createRequire}from"module";import{dirname,join}from"path";function installedSpawnHelpers(){let pkg;try{pkg=dirname(createRequire(import.meta.url).resolve("node-pty/package.json"))}catch{return[]}let prebuilds=join(pkg,"prebuilds"),arches;try{arches=readdirSync(prebuilds).filter((name)=>name.startsWith("darwin-"))}catch{return[]}let helpers=[];for(let arch of arches){let path=join(prebuilds,arch,"spawn-helper");try{helpers.push({path,executable:(statSync(path).mode&64)!==0})}catch{}}return helpers}function spawnHelperDoctorLines(helpers){let broken=helpers.filter((helper)=>!helper.executable).map((helper)=>helper.path);if(helpers.length===0)return{lines:["node-pty: ? no darwin spawn-helper found next to node-pty"],broken};if(broken.length===0)return{lines:[`node-pty: \u2713 spawn-helper executable (${helpers.length} arch)`],broken};return{lines:["node-pty: \u2717 spawn-helper is not executable \u2014 every node-pty PTY spawn fails",...broken.map((path)=>` ${path}`),` \u2192 chmod 755 ${broken.join(" ")}`],broken}}import{appendFileSync,readFileSync}from"fs";var PTY_MARKER="KOBE_TERMINAL_PTY=1",run=async(argv)=>{try{let proc=Bun.spawn([...argv],{stdin:"ignore",stdout:"pipe",stderr:"ignore"}),[stdout,code]=await Promise.all([new Response(proc.stdout).text().catch(()=>""),proc.exited]);return{code,stdout}}catch{return{code:127,stdout:""}}};function parsePsRows(output){let rows=[];for(let line of output.split(`
|
|
3
3
|
`)){let parts=line.trim().split(/\s+/);if(parts.length<6)continue;let[pid,ppid,pgid]=[parts[0],parts[1],parts[2]].map((value)=>Number.parseInt(value??"",10)),rssKb=Number.parseInt(parts[4]??"",10);if(!Number.isFinite(pid)||!Number.isFinite(ppid)||!Number.isFinite(pgid)||!Number.isFinite(rssKb))continue;rows.push({pid,ppid,pgid,etime:parts[3]??"",rssKb,command:parts.slice(5).join(" ")})}return rows}function pidAlive(pid,rows){return rows.some((row)=>row.pid===pid)}function orphanCandidates(rows,selfPgid,liveSessionPids){return rows.filter((row)=>row.ppid===1&&row.pgid!==selfPgid&&!liveSessionPids.has(row.pgid)&&!pidAlive(row.pgid,rows))}async function markedPids(pids,deps={}){let runProbe=deps.run??run,readEnviron=deps.readEnviron??((pid)=>readFileSync(`/proc/${pid}/environ`,"utf8")),marked=new Set;if(pids.length===0)return{marked,failed:null};if((deps.platform??process.platform)==="linux"){let refused=null;for(let pid of pids)try{if(readEnviron(pid).split("\x00").includes(PTY_MARKER))marked.add(pid)}catch(err){let code=err.code;if(code!=="ENOENT"&&code!=="ESRCH")refused??=`/proc/${pid}/environ: ${code??"unreadable"}`}return{marked,failed:refused}}let result=await runProbe(["ps","eww","-o","pid=,command=","-p",pids.join(",")]);if(result.code!==0)return{marked,failed:`ps eww exited ${result.code}`};let marker=new RegExp(`(^|\\s)${PTY_MARKER}(\\s|$)`);for(let line of result.stdout.split(`
|
|
4
4
|
`)){let pid=Number.parseInt(line.trim().split(/\s+/)[0]??"",10);if(Number.isFinite(pid)&&marker.test(line))marked.add(pid)}return{marked,failed:null}}async function ownPgid(runProbe){let result=await runProbe(["ps","-o","pgid=","-p",String(process.pid)]),pgid=Number.parseInt(result.stdout.trim(),10);return Number.isFinite(pgid)?pgid:-1}async function collectOrphans(liveSessionPids,deps={}){let runProbe=deps.run??run;if((deps.platform??process.platform)==="win32")return{orphans:[],error:null};let ps=await runProbe(["ps","-A","-o","pid=,ppid=,pgid=,etime=,rss=,command="]);if(ps.code!==0)return{orphans:[],error:`could not read the process table \u2014 ps exited ${ps.code}`};let rows=parsePsRows(ps.stdout),candidates=orphanCandidates(rows,await ownPgid(runProbe),liveSessionPids),{marked,failed}=await markedPids(candidates.map((row)=>row.pid),deps);if(failed)return{orphans:[],error:`could not read process environments \u2014 ${failed}`};return{orphans:candidates.filter((row)=>marked.has(row.pid)),error:null}}function formatMb(rssKb){return`${(rssKb/1024).toFixed(0)} MB`}function orphanDoctorLines(orphans,error,cliName,killing=!1){if(error)return[`orphans: \u2717 ${error}`];if(orphans.length===0)return["orphans: \u2713 none \u2014 no processes left behind by a dead PTY session"];let totalMb=orphans.reduce((sum,row)=>sum+row.rssKb,0)/1024,lines=[`orphans: \u26A0 ${orphans.length} process(es) outlived the PTY session that spawned them (${totalMb.toFixed(0)} MB RSS)`," each is reparented to init, carries Rove's PTY marker, and its process"," group leader is gone \u2014 no live task owns them"];for(let row of[...orphans].sort((a,b)=>b.rssKb-a.rssKb))lines.push(` pid ${row.pid} (group ${row.pgid}) up ${row.etime}, ${formatMb(row.rssKb)}: ${row.command.slice(0,90)}`);if(!killing)lines.push(` \u2192 \`${cliName} doctor --kill-orphans\` ends those process groups (SIGTERM, then SIGKILL)`," read the list first: something you backgrounded from a Rove terminal and then"," closed the tab on looks exactly like a leak, and doctor cannot tell them apart");return lines}var GROUP_EXIT_GRACE_MS=2000,GROUP_POLL_MS=100;function logOrphanKill(pgid,signal,logPath=defaultDaemonLogPath()){try{appendFileSync(logPath,formatDaemonInfo("doctor-kill-orphans",`${signal} process group ${pgid}`))}catch{}}function groupAlive(pgid){try{return process.kill(-pgid,0),!0}catch(err){return err.code!=="ESRCH"}}async function killOrphanGroups(orphans){let groups=[...new Set(orphans.map((row)=>row.pgid))];for(let pgid of groups)try{process.kill(-pgid,"SIGTERM"),logOrphanKill(pgid,"SIGTERM")}catch{}let deadline=Date.now()+GROUP_EXIT_GRACE_MS,survivors=groups.filter(groupAlive);while(survivors.length>0&&Date.now()<deadline)await new Promise((resolve)=>setTimeout(resolve,GROUP_POLL_MS)),survivors=survivors.filter(groupAlive);for(let pgid of survivors)try{process.kill(-pgid,"SIGKILL"),logOrphanKill(pgid,"SIGKILL")}catch{}return await new Promise((resolve)=>setTimeout(resolve,GROUP_POLL_MS)),{groups,survivors:survivors.filter(groupAlive)}}function multiplexerLabel(env){if(env.TMUX)return"tmux";if(env.ZELLIJ)return"zellij";if(env.STY)return"screen";return"no"}function terminalEnvLines(env){let show=(v)=>v&&v.length>0?v:"(unset)",program=env.TERM_PROGRAM?`${env.TERM_PROGRAM}${env.TERM_PROGRAM_VERSION?` v${env.TERM_PROGRAM_VERSION}`:""}`:"(unset)";return[`terminal: TERM=${show(env.TERM)} TERM_PROGRAM=${program} COLORTERM=${show(env.COLORTERM)}`,` running inside a multiplexer: ${multiplexerLabel(env)}`]}function parseKittyProbeReply(data){let kitty=data.match(/\x1b\[\?(\d+)u/);if(kitty?.[1]!==void 0)return{kind:"supported",flags:Number.parseInt(kitty[1],10)};if(/\x1b\[\?[\d;]*c/.test(data))return{kind:"unsupported"};return null}function kittyProbeLine(result){switch(result.kind){case"supported":return` kitty keyboard protocol: \u2713 answered (flags=${result.flags})`;case"unsupported":return[" kitty keyboard protocol: \u2717 not supported \u2014 legacy key path"," (ctrl+h/ctrl+j arrive as C0 backspace/linefeed bytes; the"," split chords ctrl+\\ and ctrl+= cannot be encoded at all)"].join(`
|
|
5
5
|
`);case"no-response":return" kitty keyboard protocol: ? no reply (terminal ignored both the kitty query and DA1)";case"skipped":return` kitty keyboard protocol: skipped (${result.reason})`}}async function probeKittyKeyboard(timeoutMs=300){let stdin=process.stdin;if(!stdin.isTTY||!process.stdout.isTTY)return{kind:"skipped",reason:"not an interactive terminal"};let wasRaw=stdin.isRaw===!0,buffer="";return await new Promise((resolve)=>{let done=!1,finish=(result)=>{if(done)return;if(done=!0,clearTimeout(timer),stdin.off("data",onData),stdin.pause(),!wasRaw)stdin.setRawMode(!1);resolve(result)},onData=(chunk)=>{buffer+=chunk.toString("latin1");let decided=parseKittyProbeReply(buffer);if(decided)finish(decided)},timer=setTimeout(()=>finish({kind:"no-response"}),timeoutMs);stdin.setRawMode(!0),stdin.resume(),stdin.on("data",onData),process.stdout.write("\x1B[?u\x1B[c")})}async function terminalDoctorLines(){return[...terminalEnvLines(process.env),kittyProbeLine(await probeKittyKeyboard())]}async function probeGit(){try{let proc=Bun.spawn(["git","--version"],{stdin:"ignore",stdout:"pipe",stderr:"ignore"}),text=(await new Response(proc.stdout).text()).trim();if(await proc.exited===0&&text)return{line:`git: \u2713 ${text}`,found:!0}}catch{}return{line:"git: \u2717 not found on PATH",found:!1}}function binaryLabel(binary){return binary.found?`\u2713 ${binary.path}`:`\u2717 ${binary.error}`}async function probeEngines(){let statuses=await detectEngineStatuses(await probeableEngineIds()),lines=["engines:"];for(let status of statuses){let account=describeAccount(status.account),name=`${status.vendor.padEnd(7)} `;if(lines.push(` ${name}${binaryLabel(status.binary)}${status.binary.found?` \u2014 ${account}`:""}`),status.accountError)lines.push(` \u26A0 ${status.accountError}`)}let{usable,signedOut}=summarizeEngines(statuses);return{lines,anyUsable:usable.length>0,signedOut}}var CLI_NAME=activeCliName();function isProcessAlive(pid){try{return process.kill(pid,0),!0}catch(err){return err.code==="EPERM"}}async function requestIfReachable(socketPath,name){let client=new KobeDaemonClient(socketPath);try{return await client.request(name,{})}catch{return null}finally{client.close()}}function fmtDuration(ms){let seconds=Math.floor(ms/1000);if(seconds<60)return`${seconds}s`;let minutes=Math.floor(seconds/60);if(minutes<60)return`${minutes}m ${seconds%60}s`;return`${Math.floor(minutes/60)}h ${minutes%60}m`}function describeFile(path){try{let stat=statSync2(path);return`present (${formatBytes(stat.size)}, modified ${stat.mtime.toISOString()})`}catch{return"absent"}}function taskCount(path){try{let parsed=JSON.parse(readFileSync2(path,"utf8"));return Array.isArray(parsed.tasks)?parsed.tasks.length:null}catch{return null}}function tailFile(path,count){try{return readFileSync2(path,"utf8").split(`
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{recordSpawn}from"./chunk-40dgv828.js";import{projectRejection}from"./chunk-mkksdcsw.js";import{getPersistedBool,loadStateFile,patchStateFile,readSavedRepos,updateStateFile}from"./chunk-zyd6k6ak.js";import{kvStatePath}from"./chunk-8hbtca1g.js";import{pathIdentity,samePath}from"./chunk-f10n6063.js";import{spawnSync}from"child_process";import{realpathSync}from"fs";function isRemoteRepoKey(key){return key.startsWith("ssh://")}function isRemoteProjectsEnabled(){return getPersistedBool("experimental.remoteProjects",!1)}function remoteRepoKey(host,user,port,basePath){let authority=port?`${user}@${host}:${port}`:`${user}@${host}`,base=(basePath??"").trim().replace(/\/+$/,"");if(!base)return`ssh://${authority}`;return`ssh://${authority}${base.startsWith("/")?base:`/${base}`}`}function readRemoteRepos(state){let raw=state.remoteRepos;if(!raw||typeof raw!=="object"||Array.isArray(raw))return{};return raw}function getRemoteRepoConfig(key){return readRemoteRepos(loadStateFile())[key]??null}function getRemoteRepos(){return readRemoteRepos(loadStateFile())}function addRemoteRepo(config){let key=remoteRepoKey(config.host,config.user,config.port,config.basePath),added=!1;return updateStateFile((state)=>{let repos={...readRemoteRepos(state)},legacyKey=remoteRepoKey(config.host,config.user,config.port);if(key!==legacyKey&&repos[legacyKey]?.basePath===config.basePath)key=legacyKey;repos[key]=config,state.remoteRepos=repos;let saved=readSavedRepos(state);if(added=!saved.includes(key),added)state.savedRepos=[...saved,key];return}),{key,added}}function resolveRepoRoot(absPath){if(isRemoteRepoKey(absPath))return absPath;recordSpawn("repos.resolveRepoRoot",["git","rev-parse","--show-toplevel"],absPath);let r=spawnSync("git",["rev-parse","--show-toplevel"],{cwd:absPath,encoding:"utf8",shell:!1});if(r.status!==0)return absPath;let top=(r.stdout??"").trim();if(!top)return absPath;try{if(realpathSync(absPath)===realpathSync(top))return absPath}catch{}return top}function isGitRepo(absPath){if(isRemoteRepoKey(absPath))return!1;recordSpawn("repos.isGitRepo",["git","rev-parse","--is-inside-work-tree"],absPath);let r=spawnSync("git",["rev-parse","--is-inside-work-tree"],{cwd:absPath,encoding:"utf8",shell:!1});return r.status===0&&(r.stdout??"").trim()==="true"}function isValidBranchName(branch){return spawnSync("git",["check-ref-format","--branch",branch],{encoding:"utf8",shell:!1}).status===0}function resolveMainRepoRoot(absPath){if(isRemoteRepoKey(absPath))return absPath;recordSpawn("repos.resolveMainRepoRoot",["git","worktree","list","--porcelain"],absPath);let r=spawnSync("git",["worktree","list","--porcelain"],{cwd:absPath,encoding:"utf8",shell:!1});if(r.status!==0)return resolveRepoRoot(absPath);return(r.stdout??"").split(/\r?\n/).find((line)=>line.startsWith("worktree "))?.slice(9).trim()||resolveRepoRoot(absPath)}function statePath(){return kvStatePath()}function getSavedRepos(){return readSavedRepos(loadStateFile())}function getPersistedString(key){let value=loadStateFile()[key];return typeof value==="string"?value:void 0}function getPersistedValue(key){return loadStateFile()[key]}function setPersistedString(key,value){patchStateFile({[key]:value})}function getCustomEngineIds(){let raw=loadStateFile().customEngineIds;if(!Array.isArray(raw))return[];return raw.filter((s)=>typeof s==="string"&&s.trim().length>0)}function getDisabledEngineIds(){let raw=loadStateFile().disabledEngineIds;if(!Array.isArray(raw))return[];return raw.filter((s)=>typeof s==="string"&&s.trim().length>0)}function addSavedRepo(absPath,opts={}){let normalized=resolveMainRepoRoot(absPath),rejected=opts.skipGate?null:projectRejection(normalized,isGitRepo,opts.intent??"explicit");if(rejected)return{added:!1,path:normalized,total:getSavedRepos().length,rejected};let result={added:!1,path:normalized,total:0};return updateStateFile((state)=>{let cur=readSavedRepos(state);if(cur.some((repo)=>samePath(repo,normalized)))return result={added:!1,path:normalized,total:cur.length},!1;state.savedRepos=[...cur,normalized],result={added:!0,path:normalized,total:cur.length+1};return}),result}function backfillSavedReposFromProjects(mainRepos){let added=[];for(let repo of mainRepos)if(addSavedRepo(repo,{intent:"explicit"}).added)added.push(repo);return added}function normalizeSavedRepos(){let cur=getSavedRepos(),seen=new Set,next=[],changed=!1;for(let p of cur){let top=resolveMainRepoRoot(p);if(top!==p)changed=!0;if(seen.has(pathIdentity(top))){changed=!0;continue}seen.add(pathIdentity(top)),next.push(top)}if(!changed)return;patchStateFile({savedRepos:next})}function readRepoConfigs(state){let raw=state.repoConfigs;if(!raw||typeof raw!=="object"||Array.isArray(raw))return{};return raw}function coerceOverride(entry){if(!entry||typeof entry!=="object")return{};let e=entry;return{initScript:typeof e.initScript==="string"&&e.initScript.length>0?e.initScript:void 0,initPrompt:typeof e.initPrompt==="string"&&e.initPrompt.length>0?e.initPrompt:void 0}}function getRepoInitOverride(repoRoot){let configs=readRepoConfigs(loadStateFile()),normalized=resolveRepoRoot(repoRoot),key=
|
|
2
|
+
import{recordSpawn}from"./chunk-40dgv828.js";import{projectRejection}from"./chunk-mkksdcsw.js";import{getPersistedBool,loadStateFile,patchStateFile,readSavedRepos,updateStateFile}from"./chunk-zyd6k6ak.js";import{kvStatePath}from"./chunk-8hbtca1g.js";import{pathIdentity,samePath}from"./chunk-f10n6063.js";import{spawnSync}from"child_process";import{realpathSync}from"fs";function isRemoteRepoKey(key){return key.startsWith("ssh://")}function isRemoteProjectsEnabled(){return getPersistedBool("experimental.remoteProjects",!1)}function remoteRepoKey(host,user,port,basePath){let authority=port?`${user}@${host}:${port}`:`${user}@${host}`,base=(basePath??"").trim().replace(/\/+$/,"");if(!base)return`ssh://${authority}`;return`ssh://${authority}${base.startsWith("/")?base:`/${base}`}`}function readRemoteRepos(state){let raw=state.remoteRepos;if(!raw||typeof raw!=="object"||Array.isArray(raw))return{};return raw}function getRemoteRepoConfig(key){return readRemoteRepos(loadStateFile())[key]??null}function getRemoteRepos(){return readRemoteRepos(loadStateFile())}function addRemoteRepo(config){let key=remoteRepoKey(config.host,config.user,config.port,config.basePath),added=!1;return updateStateFile((state)=>{let repos={...readRemoteRepos(state)},legacyKey=remoteRepoKey(config.host,config.user,config.port);if(key!==legacyKey&&repos[legacyKey]?.basePath===config.basePath)key=legacyKey;repos[key]=config,state.remoteRepos=repos;let saved=readSavedRepos(state);if(added=!saved.includes(key),added)state.savedRepos=[...saved,key];return}),{key,added}}function resolveRepoRoot(absPath){if(isRemoteRepoKey(absPath))return absPath;recordSpawn("repos.resolveRepoRoot",["git","rev-parse","--show-toplevel"],absPath);let r=spawnSync("git",["rev-parse","--show-toplevel"],{cwd:absPath,encoding:"utf8",shell:!1});if(r.status!==0)return absPath;let top=(r.stdout??"").trim();if(!top)return absPath;try{if(realpathSync(absPath)===realpathSync(top))return absPath}catch{}return top}function isGitRepo(absPath){if(isRemoteRepoKey(absPath))return!1;recordSpawn("repos.isGitRepo",["git","rev-parse","--is-inside-work-tree"],absPath);let r=spawnSync("git",["rev-parse","--is-inside-work-tree"],{cwd:absPath,encoding:"utf8",shell:!1});return r.status===0&&(r.stdout??"").trim()==="true"}function isValidBranchName(branch){return spawnSync("git",["check-ref-format","--branch",branch],{encoding:"utf8",shell:!1}).status===0}function resolveMainRepoRoot(absPath){if(isRemoteRepoKey(absPath))return absPath;recordSpawn("repos.resolveMainRepoRoot",["git","worktree","list","--porcelain"],absPath);let r=spawnSync("git",["worktree","list","--porcelain"],{cwd:absPath,encoding:"utf8",shell:!1});if(r.status!==0)return resolveRepoRoot(absPath);return(r.stdout??"").split(/\r?\n/).find((line)=>line.startsWith("worktree "))?.slice(9).trim()||resolveRepoRoot(absPath)}function statePath(){return kvStatePath()}function getSavedRepos(){return readSavedRepos(loadStateFile())}function getPersistedString(key){let value=loadStateFile()[key];return typeof value==="string"?value:void 0}function getPersistedValue(key){return loadStateFile()[key]}function setPersistedString(key,value){patchStateFile({[key]:value})}function getCustomEngineIds(){let raw=loadStateFile().customEngineIds;if(!Array.isArray(raw))return[];return raw.filter((s)=>typeof s==="string"&&s.trim().length>0)}function getDisabledEngineIds(){let raw=loadStateFile().disabledEngineIds;if(!Array.isArray(raw))return[];return raw.filter((s)=>typeof s==="string"&&s.trim().length>0)}function addSavedRepo(absPath,opts={}){let normalized=resolveMainRepoRoot(absPath),rejected=opts.skipGate?null:projectRejection(normalized,isGitRepo,opts.intent??"explicit");if(rejected)return{added:!1,path:normalized,total:getSavedRepos().length,rejected};let result={added:!1,path:normalized,total:0};return updateStateFile((state)=>{let cur=readSavedRepos(state);if(cur.some((repo)=>samePath(repo,normalized)))return result={added:!1,path:normalized,total:cur.length},!1;state.savedRepos=[...cur,normalized],result={added:!0,path:normalized,total:cur.length+1};return}),result}function backfillSavedReposFromProjects(mainRepos){let added=[];for(let repo of mainRepos)if(addSavedRepo(repo,{intent:"explicit"}).added)added.push(repo);return added}function normalizeSavedRepos(){let cur=getSavedRepos(),seen=new Set,next=[],changed=!1;for(let p of cur){let top=resolveMainRepoRoot(p);if(top!==p)changed=!0;if(seen.has(pathIdentity(top))){changed=!0;continue}seen.add(pathIdentity(top)),next.push(top)}if(!changed)return;patchStateFile({savedRepos:next})}function readRepoConfigs(state){let raw=state.repoConfigs;if(!raw||typeof raw!=="object"||Array.isArray(raw))return{};return raw}function coerceOverride(entry){if(!entry||typeof entry!=="object")return{};let e=entry;return{initScript:typeof e.initScript==="string"&&e.initScript.length>0?e.initScript:void 0,initPrompt:typeof e.initPrompt==="string"&&e.initPrompt.length>0?e.initPrompt:void 0}}function getRepoInitOverride(repoRoot){let configs=readRepoConfigs(loadStateFile()),keys=Object.keys(configs);if(keys.length===0)return{};let direct=keys.find((key2)=>samePath(key2,repoRoot));if(direct)return coerceOverride(configs[direct]);let normalized=resolveRepoRoot(repoRoot),key=keys.find((key2)=>samePath(key2,normalized))??normalized;return coerceOverride(configs[key])}function setRepoInitOverride(repoRoot,patch){let resolved=resolveRepoRoot(repoRoot),next={};return updateStateFile((state)=>{let configs={...readRepoConfigs(state)},normalized=Object.keys(configs).find((key)=>samePath(key,resolved))??resolved,cur=coerceOverride(configs[normalized]),nextScript=patch.initScript===void 0?cur.initScript:patch.initScript||void 0,nextPrompt=patch.initPrompt===void 0?cur.initPrompt:patch.initPrompt||void 0;if(next={...nextScript?{initScript:nextScript}:{},...nextPrompt?{initPrompt:nextPrompt}:{}},!next.initScript&&!next.initPrompt){let{[normalized]:_dropped,...rest}=configs;state.repoConfigs=rest}else configs[normalized]=next,state.repoConfigs=configs;return}),next}function removeSavedRepo(absPath){let result={removed:!1,path:absPath,total:0};return updateStateFile((state)=>{let cur=readSavedRepos(state);if(!cur.some((repo)=>samePath(repo,absPath)))return result={removed:!1,path:absPath,total:cur.length},!1;let remaining=cur.filter((p)=>!samePath(p,absPath));if(state.savedRepos=remaining,isRemoteRepoKey(absPath)){let remotes=readRemoteRepos(state);if(absPath in remotes){let next={...remotes};delete next[absPath],state.remoteRepos=next}}result={removed:!0,path:absPath,total:remaining.length};return}),result}
|
|
3
3
|
export{isRemoteRepoKey,isRemoteProjectsEnabled,remoteRepoKey,getRemoteRepoConfig,getRemoteRepos,addRemoteRepo,resolveRepoRoot,isGitRepo,isValidBranchName,resolveMainRepoRoot,statePath,getSavedRepos,getPersistedString,getPersistedValue,setPersistedString,getCustomEngineIds,getDisabledEngineIds,addSavedRepo,backfillSavedReposFromProjects,normalizeSavedRepos,getRepoInitOverride,setRepoInitOverride,removeSavedRepo};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{API_SCHEMA_VERSION,API_VERBS,VERBS,VERB_GROUPS,VerbArgs,apiUsage,buildCountPlan,defaultApiRuntime,deliverPrompt,findVerb,fullSchema,parseAgentsSpec,parseFlags,schemaIndex,takeIdentityWarning,unknownVerbError,validateAgainstSpec,verbHelp,verbSchema}from"./chunk-
|
|
2
|
+
import{API_SCHEMA_VERSION,API_VERBS,VERBS,VERB_GROUPS,VerbArgs,apiUsage,buildCountPlan,defaultApiRuntime,deliverPrompt,findVerb,fullSchema,parseAgentsSpec,parseFlags,schemaIndex,takeIdentityWarning,unknownVerbError,validateAgainstSpec,verbHelp,verbSchema}from"./chunk-jdph7s6t.js";import"./chunk-ma6m37fe.js";import{ensurePluginEnginesLoaded}from"./chunk-ynbfqbn9.js";import"./chunk-ffvn17at.js";import{openDaemonSession}from"./chunk-snjte1rd.js";import"./chunk-8ze8f69d.js";import"./chunk-17e2tgyg.js";import"./chunk-ch0ehc06.js";import"./chunk-mppda1wq.js";import"./chunk-mhg40es1.js";import"./chunk-r2pztgm6.js";import"./chunk-1da3bqjc.js";import"./chunk-85mk6j0s.js";import"./chunk-xsrcwcjc.js";import"./chunk-nh4wvyz3.js";import"./chunk-qkehg2c1.js";import"./chunk-d4kh54nc.js";import"./chunk-7gbjyt24.js";import"./chunk-e4a8pvek.js";import"./chunk-dnbh8hsm.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-pd8bnca7.js";import"./chunk-rcyasw34.js";import"./chunk-7q67dz4c.js";import"./chunk-pqwvpz53.js";import"./chunk-exfyqsdd.js";import"./chunk-s278gjet.js";import{ApiError,splitDaemonCode}from"./chunk-f7zjggfv.js";import"./chunk-egx76ah2.js";import"./chunk-hape5vwj.js";import"./chunk-p2c6qka0.js";import"./chunk-j1ms7bdj.js";import"./chunk-zwej00t0.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-w25b7xxz.js";import"./chunk-6xppe9bj.js";import"./chunk-jvxh93nz.js";import"./chunk-wtqxv2rv.js";import"./chunk-pz907kve.js";import"./chunk-nvqdmx7q.js";import{errorMessage}from"./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-th3ff61b.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"./chunk-vhhje5qd.js";import"./chunk-tj5qmh2g.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.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{__require}from"./chunk-wqfp8d9w.js";function emit(value,pretty){let warning=takeIdentityWarning(),payload=warning&&value&&typeof value==="object"&&!Array.isArray(value)?{...value,identityWarning:warning}:value,text=pretty?JSON.stringify(payload,null,2):JSON.stringify(payload);process.stdout.write(`${text}
|
|
3
3
|
`)}function fail(message,code,exitCode=1,data){process.stderr.write(`${JSON.stringify({error:{message,code,...data}})}
|
|
4
4
|
`),process.exit(exitCode)}function makeContext(verb,flags,client,runtime){return{args:new VerbArgs(verb,flags),client,runtime}}var USAGE_ERROR_CODES=new Set(["BAD_VERB","UNKNOWN_VERB","BAD_FLAG","MISSING_FLAG","MISSING_VERB","BAD_DAEMON"]);function toApiError(err){if(err instanceof ApiError)return err;let message=errorMessage(err);if(/task not found/i.test(message))return new ApiError(message,"TASK_NOT_FOUND",{hint:"that task id does not exist (deleted or mistyped) \u2014 list live tasks and retry with a real id",nextCommandArgs:["api","list"]});if(/unknown daemon request:/i.test(message))return versionSkewError(message);let coded=splitDaemonCode(message);if(coded)return new ApiError(coded.rest,coded.code);return new ApiError(message,"RPC_ERROR")}function versionSkewError(message){return new ApiError(message,"DAEMON_VERSION_SKEW",{hint:"the running daemon is a different build than this CLI, so it does not serve this verb \u2014 restart the daemon to pick up this build, then retry (if the verb is gone for good, `rove api schema` lists what this daemon actually serves)",nextCommandArgs:["daemon","restart"]})}async function invokeVerb(verbName,argv,deps){let verb=findVerb(verbName);if(!verb)throw unknownVerbError(verbName);let booleanFlags=new Set(verb.flags.filter((f)=>f.type==="bool").map((f)=>f.name)),parsed=parseFlags(argv,booleanFlags);validateAgainstSpec(verb,parsed.flags);try{return await verb.handler(makeContext(verb,parsed.flags,deps.client,deps.runtime??defaultApiRuntime))}catch(err){throw toApiError(err)}}async function runApiSubcommand(argv){let[verbName,...rest]=argv;if(!verbName||verbName==="--help"||verbName==="-h"||verbName==="help"){if(!verbName)fail(apiUsage(),"MISSING_VERB",2);process.stdout.write(`${apiUsage()}
|
|
5
5
|
`);return}ensurePluginEnginesLoaded();let verb=findVerb(verbName);if(!verb){let err=unknownVerbError(verbName);fail(`${err.message}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{activityHookAdapters}from"./chunk-
|
|
2
|
+
import{activityHookAdapters}from"./chunk-j1ms7bdj.js";import{readFileSync}from"fs";function hookConfigIssues(){let issues=[];for(let adapter of activityHookAdapters()){if(!adapter.hookConfigRefusal)continue;let file=adapter.globalSettingsPath();if(!file)continue;let raw;try{raw=readFileSync(file,"utf8")}catch{continue}let reason=adapter.hookConfigRefusal(raw);if(reason)issues.push({file,reason})}return issues}function formatBytes(n){if(n<1024)return`${n} B`;let units=["KB","MB","GB","TB"],v=n/1024,i=0;while(v>=1023.5&&i<units.length-1)v/=1024,i++;let oneDecimal=v.toFixed(1);return`${Number(oneDecimal)>=100?Math.round(v):oneDecimal} ${units[i]}`}
|
|
3
3
|
export{hookConfigIssues,formatBytes};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{discoverMachine}from"./chunk-
|
|
2
|
+
import{discoverMachine}from"./chunk-ww4fbx8h.js";import{addMachine,defaultMachineAlias,duplicateAliasOf,getMachine,isValidMachineAlias,listMachines,machineSocketDir,parseSshTarget,readMachines,removeMachine,sanitizeAlias,setMachineIdentity,sshTargetOf}from"./chunk-bs7v83x0.js";import{activeCliName}from"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import{loadStateFile}from"./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";var CLI_NAME=activeCliName(),MACHINE_USAGE=[`Usage: ${CLI_NAME} machine <add|remove|list> [options]`,"","Manage the other computers running Rove. Each one is reached over SSH;","its tasks appear in the sidebar under a row of its own.","","Commands:"," add <ssh-target> Register a machine (verifies it before saving)"," remove <alias> Forget a machine (nothing on it is touched)"," list Show registered machines","","Add options:"," --alias <name> Local name for the machine (default: the target you typed)"," --port <n> SSH port (default: whatever ssh_config says)"," --identity <file> SSH private key (default: ssh-agent / ssh_config)",""," <ssh-target> is [user@]host[:port] \u2014 usually just an ssh_config Host alias."," The machine must already have Rove installed (`npm i -g @sma1lboy/rove`).",""].join(`
|
|
3
3
|
`);function usageError(message){process.stderr.write(`${CLI_NAME} machine: ${message}
|
|
4
4
|
|
|
5
5
|
${MACHINE_USAGE}
|
|
@@ -4,4 +4,4 @@ import{expandTilde}from"./chunk-nvqdmx7q.js";import{errorMessage}from"./chunk-2b
|
|
|
4
4
|
|
|
5
5
|
${REPO_USAGE}
|
|
6
6
|
`),process.exit(2)}function readArgFile(path){try{return readFileSync(resolve(process.cwd(),expandTilde(path)),"utf8")}catch(err){usageError(`cannot read ${path}: ${errorMessage(err)}`)}}function parseRepoArgs(args){let out={};for(let i=0;i<args.length;i++){let a=args[i],need=()=>{let v=args[++i];if(v===void 0)usageError(`${a} requires a value`);return v};if(a==="--init-script")out.initScript=need();else if(a==="--init-script-file")out.initScript=readArgFile(need());else if(a==="--init-prompt")out.initPrompt=need();else if(a==="--init-prompt-file")out.initPrompt=readArgFile(need());else if(a.startsWith("-"))usageError(`unknown flag "${a}"`);else if(out.path===void 0)out.path=a;else usageError(`unexpected argument "${a}"`)}return out}function parseUnsetArgs(args){let path,clearScript=!1,clearPrompt=!1;for(let a of args)if(a==="--init-script")clearScript=!0;else if(a==="--init-prompt")clearPrompt=!0;else if(a.startsWith("-"))usageError(`unknown flag "${a}"`);else if(path===void 0)path=a;else usageError(`unexpected argument "${a}"`);if(!clearScript&&!clearPrompt)clearScript=!0,clearPrompt=!0;return{path,clearScript,clearPrompt}}async function runRepoSubcommand(args){let[verb,...rest]=args;if(verb===void 0||verb==="--help"||verb==="-h"||verb==="help"){process.stdout.write(`${REPO_USAGE}
|
|
7
|
-
`);return}if(!SUBCOMMAND_VERBS.repo.includes(verb))usageError(`unknown verb "${verb}"`);let{getRepoInitOverride,setRepoInitOverride,resolveRepoRoot}=await import("./chunk-
|
|
7
|
+
`);return}if(!SUBCOMMAND_VERBS.repo.includes(verb))usageError(`unknown verb "${verb}"`);let{getRepoInitOverride,setRepoInitOverride,resolveRepoRoot}=await import("./chunk-7s1kx9ez.js");if(verb==="show"){let[pathArg]=rest.filter((a)=>!a.startsWith("-")),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(pathArg??"."))),override=getRepoInitOverride(repo),{describeRepoInitSources}=await import("./chunk-hnfp317x.js"),sources=describeRepoInitSources(repo);console.log(`repo: ${repo}`);for(let group of[sources.script,sources.prompt])group.forEach((source,index)=>{console.log(` ${`${source.rel}:`.padEnd(22)}${describeSource(group,index)}`)});console.log(` override initScript: ${override.initScript?quotePreview(override.initScript):"(unset)"}`),console.log(` override initPrompt: ${override.initPrompt?quotePreview(override.initPrompt):"(unset)"}`);return}if(verb==="set"){let flags=parseRepoArgs(rest);if(flags.initScript===void 0&&flags.initPrompt===void 0)usageError("set needs at least one of --init-script(-file) / --init-prompt(-file)");let repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(flags.path??"."))),next=setRepoInitOverride(repo,{...flags.initScript!==void 0?{initScript:flags.initScript}:{},...flags.initPrompt!==void 0?{initPrompt:flags.initPrompt}:{}});console.log(`updated override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}if(verb==="unset"){let{path,clearScript,clearPrompt}=parseUnsetArgs(rest),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(path??"."))),next=setRepoInitOverride(repo,{...clearScript?{initScript:""}:{},...clearPrompt?{initPrompt:""}:{}});console.log(`cleared override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}usageError(`unknown verb "${verb}"`)}function describeSource(group,index){let source=group[index];if(!source)return"absent";if(source.effective)return"present (wins)";if(!source.present)return"absent";return group.slice(0,index).some((earlier)=>earlier.effective)?"present (shadowed)":"present but empty (ignored)"}function quotePreview(value){let oneLine=value.replace(/\s+/g," ").trim();return oneLine.length>60?`"${oneLine.slice(0,57)}\u2026"`:`"${oneLine}"`}export{runRepoSubcommand};
|
|
@@ -4,5 +4,5 @@ import{generateCompletions,isShellKind,mergeSubVerbs,shippedCompletionsPath}from
|
|
|
4
4
|
|
|
5
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
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-
|
|
8
|
-
`);return}if(shipped){process.stdout.write(readFileSync(shipped,"utf8"));return}let{API_VERBS}=await import("./chunk-
|
|
7
|
+
`);return}if(flags[0]==="--install"){let[{installCompletions},{t}]=await Promise.all([import("./chunk-7ded3me8.js"),import("./chunk-nrzes9c0.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-4rgy3ccz.js");process.stdout.write(generateCompletions(shell,cliName,mergeSubVerbs(API_VERBS)))}export{runCompletionsSubcommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{API_VERBS,VERBS,VERB_ALIASES,VERB_GROUPS,findVerb,unknownVerbError}from"./chunk-
|
|
2
|
+
import{API_VERBS,VERBS,VERB_ALIASES,VERB_GROUPS,findVerb,unknownVerbError}from"./chunk-jdph7s6t.js";import"./chunk-ma6m37fe.js";import"./chunk-ynbfqbn9.js";import"./chunk-ffvn17at.js";import"./chunk-snjte1rd.js";import"./chunk-8ze8f69d.js";import"./chunk-17e2tgyg.js";import"./chunk-ch0ehc06.js";import"./chunk-mppda1wq.js";import"./chunk-mhg40es1.js";import"./chunk-r2pztgm6.js";import"./chunk-1da3bqjc.js";import"./chunk-85mk6j0s.js";import"./chunk-xsrcwcjc.js";import"./chunk-nh4wvyz3.js";import"./chunk-qkehg2c1.js";import"./chunk-d4kh54nc.js";import"./chunk-7gbjyt24.js";import"./chunk-e4a8pvek.js";import"./chunk-dnbh8hsm.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-pd8bnca7.js";import"./chunk-rcyasw34.js";import"./chunk-7q67dz4c.js";import"./chunk-pqwvpz53.js";import"./chunk-exfyqsdd.js";import"./chunk-s278gjet.js";import"./chunk-f7zjggfv.js";import"./chunk-egx76ah2.js";import"./chunk-hape5vwj.js";import"./chunk-p2c6qka0.js";import"./chunk-j1ms7bdj.js";import"./chunk-zwej00t0.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-w25b7xxz.js";import"./chunk-6xppe9bj.js";import"./chunk-jvxh93nz.js";import"./chunk-wtqxv2rv.js";import"./chunk-pz907kve.js";import"./chunk-nvqdmx7q.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-th3ff61b.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"./chunk-vhhje5qd.js";import"./chunk-tj5qmh2g.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.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{unknownVerbError,findVerb,VERB_GROUPS,VERB_ALIASES,VERBS,API_VERBS};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{buildPaneArgv}from"./chunk-cv6r89jp.js";import{PluginCliError,installPlugin,linkPlugin}from"./chunk-
|
|
2
|
+
import{buildPaneArgv}from"./chunk-cv6r89jp.js";import{PluginCliError,installPlugin,linkPlugin}from"./chunk-zk7z3b36.js";import{resolvePluginBinPath}from"./chunk-6x5vzzpx.js";import{buildPluginEnv}from"./chunk-53afdybj.js";import{currentPluginPlatform,loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginLogPath,qualifiedActionId,readPluginManifest,removePluginEntry,savePluginRegistry,supportsPlatform}from"./chunk-1da3bqjc.js";import"./chunk-exfyqsdd.js";import"./chunk-w7zv47mp.js";import{flagValue}from"./chunk-jvxh93nz.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import"./chunk-th3ff61b.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-hqbmzz4t.js";import{defaultDaemonSocketPath}from"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{readFileSync,rmSync}from"fs";var CLI_NAME=activeCliName();function printUsage(out){out.write([`usage: ${CLI_NAME} plugin <command>`,""," install <owner/repo[/subdir]> [--yes] [--ref <rev>] clone from GitHub, preview, build, register"," link <dir> register a local plugin directory (dev)"," list installed + linked plugins"," search [query] browse the marketplace (GitHub topic rove-plugin)"," outdated check GitHub-installed plugins against upstream"," update <id\u2026> | --all [--yes] reinstall stale plugins from GitHub"," enable <id> | disable <id> toggle a plugin without unregistering it"," unlink <id> unregister a linked plugin (files untouched)"," uninstall <id-or-spec> unregister + remove the managed checkout"," config-dir <id> print the plugin's config directory"," log <id> [-n <count>] tail the plugin's command-run log"," action list [--plugin <id>] declared actions"," action invoke <plugin-id.action-id> run an action now"," pane open <plugin-id.pane-id> [--task <task-id>] open a plugin pane as a terminal tab (JSON:"," clients \u2014 0 = no attached UI performed the split)","","Marketplace: https://github.com/topics/rove-plugin (legacy kobe-plugin is included)",""].join(`
|
|
3
3
|
`))}function loadAll(){return loadPluginRegistry().plugins.map((entry)=>{try{return{entry,manifest:readPluginManifest(entry.root).manifest}}catch{return{entry,manifest:void 0}}})}function requireEntry(id){let entry=loadPluginRegistry().plugins.find((p)=>p.id===id);if(!entry)throw new PluginCliError(`no plugin registered as \`${id}\`; see \`${CLI_NAME} plugin list\``);return entry}function listPlugins(){let all=loadAll();if(all.length===0){console.log(`no plugins installed. Try: ${CLI_NAME} plugin install <owner/repo> \u2014 browse the \`rove-plugin\` GitHub topic.`);return}for(let{entry,manifest}of all){let state=entry.enabled?"enabled":"disabled",kind=entry.source.kind==="link"?`linked ${entry.root}`:entry.source.spec,broken=manifest?"":" [manifest unreadable]";console.log(`${entry.id} v${entry.version} ${state} (${kind})${broken}`)}}function setEnabled(id,enabled){let entry=requireEntry(id),registry=loadPluginRegistry();savePluginRegistry({plugins:registry.plugins.map((p)=>p.id===id?{...entry,enabled}:p)}),console.log(`${enabled?"enabled":"disabled"} ${id}`)}function unlink(id){let entry=requireEntry(id);if(entry.source.kind!=="link")throw new PluginCliError(`\`${id}\` is a GitHub install; use uninstall`);savePluginRegistry(removePluginEntry(loadPluginRegistry(),id)),console.log(`unlinked ${id} (files untouched at ${entry.root})`)}function uninstall(idOrSpec){let registry=loadPluginRegistry(),entry=registry.plugins.find((p)=>p.id===idOrSpec||p.source.kind==="github"&&p.source.spec===idOrSpec);if(!entry)throw new PluginCliError(`no plugin registered as \`${idOrSpec}\``);if(entry.source.kind==="link")throw new PluginCliError(`\`${entry.id}\` is linked; use unlink`);savePluginRegistry(removePluginEntry(registry,entry.id)),rmSync(pluginCheckoutDir(entry.id),{recursive:!0,force:!0}),console.log(`uninstalled ${entry.id} (config/state kept under ~/.rove/plugins/${entry.id}/)`)}function listActions(pluginFilter){for(let{entry,manifest}of loadAll()){if(!manifest||pluginFilter&&entry.id!==pluginFilter)continue;for(let action of manifest.actions)console.log(`${qualifiedActionId(entry.id,action.id)} ${action.title}`)}}function findByLongestPluginPrefix(qualified,options,findItem){for(let{entry,manifest}of loadAll().filter(({entry:entry2,manifest:manifest2})=>Boolean(manifest2&&(!options.enabledOnly||entry2.enabled)&&qualified.startsWith(`${entry2.id}.`))).sort((a,b)=>b.entry.id.length-a.entry.id.length)){let item=findItem(manifest,qualified.slice(entry.id.length+1));if(item!==void 0)return{entry,manifest,item}}return}function assertPlatformSupported(label,item,manifest){if(supportsPlatform(item,manifest,currentPluginPlatform()))return;let declared=(item.platforms??manifest.platforms??[]).join(", ");throw new PluginCliError(`\`${label}\` is not supported on this platform (declares ${declared})`)}function invokeAction(qualified,extraArgs){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!0},(manifest,actionId)=>manifest.actions.find((a)=>a.id===actionId));if(!hit)throw new PluginCliError(`no action \`${qualified}\`; see \`${CLI_NAME} plugin action list\``);assertPlatformSupported(qualified,hit.item,hit.manifest);let action=hit.item,[cmd,...args]=[...action.command,...extraArgs],res=spawnSync(cmd,args,{cwd:hit.entry.root,stdio:"inherit",env:buildPluginEnv({socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),pluginId:hit.entry.id,pluginRoot:hit.entry.root,extra:{ROVE_PLUGIN_ACTION_ID:action.id,ROVE_PLUGIN_INVOKE_CWD:process.cwd()}})});process.exit(res.status??1)}function resolvePaneQualified(qualified){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!1},(manifest,entrypoint)=>manifest.panes.find((p)=>p.id===entrypoint));if(!hit)throw new PluginCliError(`no pane \`${qualified}\`; see \`${CLI_NAME} plugin list\``);return{pluginId:hit.entry.id,entrypoint:hit.item.id}}async function openPane(pluginId,entrypoint,taskFlag){let loaded=loadAll().find(({entry})=>entry.id===pluginId);if(!loaded?.manifest)throw new PluginCliError(`no plugin \`${pluginId}\` (or its manifest is unreadable)`);if(!loaded.entry.enabled)throw new PluginCliError(`\`${pluginId}\` is disabled`);let pane=loaded.manifest.panes.find((p)=>p.id===entrypoint);if(!pane)throw new PluginCliError(`no pane \`${entrypoint}\` in \`${pluginId}\`; declare it under [[panes]]`);assertPlatformSupported(`${pluginId}.${pane.id}`,pane,loaded.manifest);let{openDaemonSession,resolveActiveTaskId}=await import("./chunk-f5e3dcxe.js"),session=await openDaemonSession({mode:"start"});try{let taskId=taskFlag??await resolveActiveTaskId(session.client);if(!taskId)throw new PluginCliError("no active task; pass --task <id>");let argv=buildPaneArgv(loaded.entry.id,loaded.entry.root,pane,{socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),taskId}),reply=await session.client.request("tab.open",{taskId,argv,title:pane.title,placement:pane.placement});console.log(JSON.stringify({...reply,ok:!0,pane:`${pluginId}.${pane.id}`,taskId,title:pane.title}))}finally{session.close()}}function tailLog(id,count){requireEntry(id);let text;try{text=readFileSync(pluginLogPath(id),"utf8")}catch{console.log("(no runs logged yet)");return}let lines=text.trimEnd().split(`
|
|
4
|
-
`);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-ahnk6zx3.js");await searchMarketplace(args.find((a)=>!a.startsWith("-")));return}case"outdated":{let{printOutdated}=await import("./chunk-
|
|
4
|
+
`);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-ahnk6zx3.js");await searchMarketplace(args.find((a)=>!a.startsWith("-")));return}case"outdated":{let{printOutdated}=await import("./chunk-8041pnt0.js");printOutdated();return}case"update":{let{updatePlugins}=await import("./chunk-8041pnt0.js");await updatePlugins(args.filter((a)=>!a.startsWith("-")),{all:args.includes("--all"),yes:args.includes("--yes")});return}case"enable":case"disable":{if(!args[0])throw new PluginCliError(`${command} needs a plugin id`);setEnabled(args[0],command==="enable");return}case"unlink":{if(!args[0])throw new PluginCliError("unlink needs a plugin id");unlink(args[0]);return}case"uninstall":{if(!args[0])throw new PluginCliError("uninstall needs a plugin id or owner/repo spec");uninstall(args[0]);return}case"config-dir":{if(!args[0])throw new PluginCliError("config-dir needs a plugin id");requireEntry(args[0]),console.log(pluginConfigDir(args[0]));return}case"log":{if(!args[0])throw new PluginCliError("log needs a plugin id");tailLog(args[0],Number.parseInt(flagValue(args,"-n")??"20",10)||20);return}case"pane":{let[sub,...paneArgs]=args;if(sub==="open"){let positional=paneArgs.find((a)=>!a.startsWith("-")&&a!==flagValue(paneArgs,"--task")),pluginId=flagValue(paneArgs,"--plugin"),entrypoint=flagValue(paneArgs,"--entrypoint");if(!pluginId||!entrypoint){if(!positional)throw new PluginCliError("pane open needs <plugin-id.pane-id> (or --plugin <id> --entrypoint <pane-id>) [--task <task-id>]");({pluginId,entrypoint}=resolvePaneQualified(positional))}await openPane(pluginId,entrypoint,flagValue(paneArgs,"--task"));return}printUsage(process.stderr),process.exit(2);return}case"action":{let[sub,...actionArgs]=args;if(sub==="list"){listActions(flagValue(actionArgs,"--plugin"));return}if(sub==="invoke"){if(!actionArgs[0])throw new PluginCliError("action invoke needs <plugin-id.action-id>");invokeAction(actionArgs[0],actionArgs.slice(1));return}printUsage(process.stderr),process.exit(2);return}default:{let isHelp=command===void 0||command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}}}catch(err){if(err instanceof PluginCliError)console.error(`${CLI_NAME} plugin: ${err.message}`),process.exit(1);console.error(`${CLI_NAME} plugin: ${errorMessage(err)}`),process.exit(1)}}export{runPluginSubcommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-
|
|
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
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
4
|
export{Orchestrator};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{NoopHookAdapter,activityHookAdapters,createEngineHookAdapter}from"./chunk-
|
|
2
|
+
import{NoopHookAdapter,activityHookAdapters,createEngineHookAdapter}from"./chunk-j1ms7bdj.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"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{createEngineHookAdapter,activityHookAdapters,NoopHookAdapter};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{detectShell,installCompletions,recordWelcomeChoices,runPendingWelcomeInstalls}from"./chunk-
|
|
2
|
+
import{detectShell,installCompletions,recordWelcomeChoices,runPendingWelcomeInstalls}from"./chunk-d9trak46.js";import"./chunk-z6yqkkgj.js";import"./chunk-yybpg7fh.js";import"./chunk-fhch0x0q.js";import"./chunk-th3ff61b.js";import"./chunk-pvw2y93q.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"./chunk-vhhje5qd.js";import"./chunk-tj5qmh2g.js";import"./chunk-nhakrm1f.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{runPendingWelcomeInstalls,recordWelcomeChoices,installCompletions,detectShell};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{buildEngineSessionLaunch,trustEngineWorktree}from"./chunk-c46jm1nj.js";import{engineForkArgv,engineResumeArgv,withPinnedSessionId}from"./chunk-rdj6ffbz.js";import{engineEntry,engineStatusPrefixes,isEnginePlaceholderTitle,stripEngineStatusPrefix}from"./chunk-rhczy26f.js";import{tildify}from"./chunk-nvqdmx7q.js";import{t}from"./chunk-vhhje5qd.js";import{pathSyntax}from"./chunk-f10n6063.js";function engineTabArgv(tab,base,live,fallbackVendor){if(tab.forkFrom&&!tab.spawned&&!live){let forked=tab.vendor?engineForkArgv(base,tab.vendor,tab.forkFrom,tab.sessionId??null):null;if(forked)return forked}if(!tab.sessionId)return base;let vendor=tab.vendor??fallbackVendor;if(tab.spawned&&!live)return engineResumeArgv(base,vendor,tab.sessionId)??base;return withPinnedSessionId(base,vendor,()=>tab.sessionId).argv}function engineTabSpawnFor(state,tab,base,opts){let{live,shell,prompt}=opts,firstEngine=state.tabs.find((t2)=>t2.kind==="engine"),fresh=!tab.spawned&&!live,tabPrompt=fresh?tab.initialPrompt?.trim():void 0,wantsPrompt=!!prompt&&tab.id===firstEngine?.id&&fresh,isFreshFirstEngine=tab.id===firstEngine?.id&&fresh,promptIntent=tabPrompt?{kind:"explicit",prompt:tabPrompt}:wantsPrompt?{kind:"new-task",prompt}:isFreshFirstEngine?{kind:"repo-init"}:{kind:"none"},ref=tab.ptyTask;trustEngineWorktree(tab.vendor??opts.task.vendor,ref?.worktree??opts.worktreePath);let launch=buildEngineSessionLaunch({task:ref?{...opts.task,id:ref.id,kind:"task"}:opts.task,worktreePath:ref?.worktree??opts.worktreePath,shell,argv:engineTabArgv(tab,base,live,opts.task.vendor),promptIntent,protocolGates:opts.protocolGates,tabId:ref?"tab-1":tab.id});return{command:launch.command,...launch.firstMessage?{firstMessage:launch.firstMessage,engineBin:base[0]}:{}}}function tabExitAction(tab,deadOnAttach,resumeTried){if(tab.kind==="engine"&&deadOnAttach&&!!tab.sessionId&&tab.spawned&&!resumeTried)return"resume";return"close"}import*as fs from"fs";import*as os from"os";function pathLeaf(p){return p.slice(lastSeparator(p)+1)}function lastSeparator(p){return pathSyntax(p).sep==="\\"||process.platform==="win32"&&!p.startsWith("/")?Math.max(p.lastIndexOf("/"),p.lastIndexOf("\\")):p.lastIndexOf("/")}function expandHome(p){if(p==="~")return os.homedir();if(p.startsWith("~/")||process.platform==="win32"&&p.startsWith("~\\"))return os.homedir()+p.slice(1);return p}function stripTrailingSlash(p){let root=pathSyntax(p).parse(p).root,end=p.length;while(end>root.length&&lastSeparator(p.slice(0,end))===end-1)end--;return p.slice(0,end)}function splitPathForDirSuggest(value){if(!value)return{base:"",filter:""};let expanded=expandHome(value==="~"?"~/":value),lastSlash=lastSeparator(expanded);if(lastSlash===-1)return{base:"",filter:expanded};return{base:expanded.slice(0,lastSlash+1),filter:expanded.slice(lastSlash+1)}}function listSubdirs(base){if(!base)return[];try{let entries=fs.readdirSync(base,{withFileTypes:!0}),out=[];for(let e of entries)if(e.isDirectory())out.push(e.name);return out.sort((a,b)=>a.localeCompare(b))}catch{return[]}}function filterSubdirs(all,filter){let f=filter.toLowerCase(),visible=f.startsWith(".")?all:all.filter((n)=>!n.startsWith("."));if(!f)return visible;return visible.filter((n)=>n.toLowerCase().startsWith(f))}function joinDrill(typedValue,baseExpanded,name){let out=`${baseExpanded+name}/`;if(typedValue.startsWith("~")){let short=tildify(out);if(short.startsWith("~"))return short==="~"?"~/":`${short}/`}return out}function joinPicked(typedValue,baseExpanded,name){let out=baseExpanded+name;if(typedValue.startsWith("~"))return tildify(out);return out}function depth(node){return node.kind==="leaf"?0:1+Math.max(...node.children.map(depth))}function siblingCount(root,id,orientation){let find=(node)=>{if(node.kind==="leaf")return null;if(node.orientation===orientation&&node.children.some((c)=>c.kind==="leaf"&&c.id===id))return node.children.length;for(let child of node.children){let n=find(child);if(n!==null)return n}return null};return find(root)??1}function splitFits(state,orientation,activeSize){let extent=orientation==="row"?activeSize.cols:activeSize.rows,min=orientation==="row"?20:6,n=siblingCount(state.root,state.activeLeafId,orientation);return Math.floor(extent*n/(n+1))-1>=min}function initialSplit(content){return{root:{kind:"leaf",id:"leaf-1",content},activeLeafId:"leaf-1",nextOrdinal:2}}function leaves(node){return node.kind==="leaf"?[node]:node.children.flatMap(leaves)}function splitActive(state,orientation,content,activeSize){if(activeSize&&!splitFits(state,orientation,activeSize))return state;let leaf={kind:"leaf",id:`leaf-${state.nextOrdinal}`,content},insert=(node)=>{if(node.kind==="leaf"){if(node.id!==state.activeLeafId)return node;return{kind:"group",orientation,children:[node,leaf]}}if(node.orientation===orientation){let i=node.children.findIndex((c)=>c.kind==="leaf"&&c.id===state.activeLeafId);if(i>=0){let children=[...node.children.slice(0,i+1),leaf,...node.children.slice(i+1)];return{...node,children}}}return{...node,children:node.children.map(insert)}},root=insert(state.root);if(!activeSize&&depth(root)>4)return state;return{root,activeLeafId:leaf.id,nextOrdinal:state.nextOrdinal+1}}function removeLeaf(state,id){let all=leaves(state.root);if(all.length<=1)return null;let prune=(node)=>{if(node.kind==="leaf")return node.id===id?null:node;let children=node.children.map(prune).filter((c)=>c!==null);if(children.length===0)return null;if(children.length===1)return children[0];return{...node,children}},root=prune(state.root);if(root===null)return null;if(leaves(root).length===all.length)return state;let order=all.map((l)=>l.id),removedIdx=order.indexOf(id),fallback=order[removedIdx>0?removedIdx-1:removedIdx+1],activeLeafId=state.activeLeafId===id?fallback:state.activeLeafId;return{...state,root,activeLeafId}}function renameLeaf(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,walk=(node)=>node.kind==="leaf"?node.id===id?{...node,title:next}:node:{...node,children:node.children.map(walk)};if(!leaves(state.root).some((l)=>l.id===id))return state;return{...state,root:walk(state.root)}}function cycleLeaf(state,delta){let order=leaves(state.root).map((l)=>l.id);if(order.length<=1)return state;let i=order.indexOf(state.activeLeafId),next=order[(i+delta+order.length)%order.length];return{...state,activeLeafId:next}}function hasEngineLeaf(tree){return!tree||leaves(tree.root).some((l)=>l.id==="leaf-1")}function isTabSplit(tree){return tree?leaves(tree.root).length>1:!1}function collapseSplit(next){let ls=leaves(next.root);return ls.length===1&&ls[0]?.id==="leaf-1"?null:next}function splitLeafPtyKey(tabKey,leafId){return leafId==="leaf-1"?tabKey:`${tabKey}::${leafId}`}var SHELL_LEAF_NAME="shell";function splitLeafNames(leafList,tabCommand,engineTitle,liveTitles){let basename=(argv)=>{let head=(argv??tabCommand)[0]??"",name=pathLeaf(head);return name.length>0?name:"?"},seen=new Map,out=new Map;for(let leaf of leafList){if(leaf.title){out.set(leaf.id,leaf.title);continue}let name=leaf.content===null?engineTitle||liveTitles?.get(leaf.id)||basename(leaf.content):liveTitles?.get(leaf.id)||SHELL_LEAF_NAME,n=(seen.get(name)??0)+1;seen.set(name,n),out.set(leaf.id,n===1?name:`${name} ${n}`)}return out}function meaningfulAutoTitle(autoTitle){let trimmed=(autoTitle??"").trim();if(trimmed.length<3)return null;if(/^[\d\s\p{P}\p{S}]+$/u.test(trimmed))return null;return trimmed}function stableRecordedTitle(raw,vendor){let recorded=raw?.trim();if(!recorded)return null;let cleaned=stripEngineStatusPrefix(recorded,vendor);if(cleaned===recorded&&isEngineDecoration(recorded,vendor))return null;if(isEnginePlaceholderTitle(cleaned,vendor))return null;return cleaned||null}function isEngineDecoration(text,vendor){let glyphs=new Set(engineStatusPrefixes(vendor));return[...text].every((ch)=>ch.trim().length===0||glyphs.has(ch))}function tabTitleStable(tab,taskVendor,liveVendor,liveTitle){if(liveVendor===null&&tab.kind==="engine")return tabTitle({...tab,kind:"command",lastTitle:null},taskVendor);let vendor=liveVendor??tab.liveVendor??(tab.kind==="engine"?tab.vendor??taskVendor:void 0)??void 0,source=liveTitle?.trim()||tab.lastTitle,named=vendor?stableRecordedTitle(source,vendor):source??null;if(!vendor||engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return tabTitle({...tab,...vendor?{kind:"engine",vendor}:{},lastTitle:named},taskVendor);return tabTitle({...tab,kind:"engine",vendor,lastTitle:named},taskVendor)}function titleVendor(tab,taskVendor){return tab.liveVendor??(tab.kind==="engine"?tab.vendor:void 0)??taskVendor}function tabTitle(tab,taskVendor,liveName){if(tab.title)return tab.title;let ls=tab.splitTree?leaves(tab.splitTree.root):[];if(ls.length>1)return t("terminal.tab.groupTitle",{n:tab.ordinal});let sole=ls.length===1?ls[0]:void 0;if(sole&&sole.id!=="leaf-1")return sole.title??`${liveName??SHELL_LEAF_NAME} ${tab.ordinal}`;let vendor=titleVendor(tab,taskVendor);if(liveName&&!isEnginePlaceholderTitle(liveName,vendor))return`${liveName} ${tab.ordinal}`;if(tab.lastTitle&&!isEnginePlaceholderTitle(tab.lastTitle,vendor))return`${tab.lastTitle} ${tab.ordinal}`;let auto=meaningfulAutoTitle(tab.autoTitle);if(auto)return auto;return`${tab.kind==="engine"?engineEntry(tab.vendor??taskVendor).defaultCommand[0]??SHELL_LEAF_NAME:SHELL_LEAF_NAME} ${tab.ordinal}`}function visibleNativeStatus(tab,taskVendor,vendor,liveName){if(!vendor||!liveName)return!1;if(engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return!1;return tabTitle(tab,taskVendor,liveName)===`${liveName} ${tab.ordinal}`}function initialTabs(){return{tabs:[{kind:"engine",id:"tab-1",title:null,ordinal:1}],activeId:"tab-1",nextOrdinal:2}}function reopenHintFor(closed){if(closed?.kind==="command")return{kind:"command"};if(closed?.kind==="engine"&&closed.vendor)return{kind:"engine",vendor:closed.vendor};return{kind:"engine"}}function reopenTabs(state,shell){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,next=state.nextOrdinal+1;if(state.reopenAs?.kind==="command")return{tabs:[{kind:"command",id,title:null,ordinal,command:[shell]}],activeId:id,nextOrdinal:next};let vendor=state.reopenAs?.kind==="engine"?state.reopenAs.vendor:void 0;return{tabs:[{kind:"engine",id,title:null,ordinal,...vendor?{vendor}:{}}],activeId:id,nextOrdinal:next}}function initialShellTabs(shell){return{tabs:[{kind:"command",id:"tab-1",title:null,ordinal:1,command:[shell]}],activeId:"tab-1",nextOrdinal:2}}function rehydrateTabs(persisted,shell,opts={}){let tabs=persisted.tabs.map((t2)=>t2.kind==="command"?{...t2,command:shell,purpose:void 0}:t2);if(tabs.length===0)return opts.allowEmpty?persisted:initialTabs();let activeId=tabs.some((t2)=>t2.id===persisted.activeId)?persisted.activeId:tabs[0].id,maxOrdinal=tabs.reduce((max,t2)=>Math.max(max,t2.ordinal),0);return{tabs,activeId,nextOrdinal:Math.max(persisted.nextOrdinal,maxOrdinal+1)}}function recycleTabs(state,prev){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,pinned=prev.kind==="engine"?prev:void 0;return{tabs:[{kind:"engine",id,ordinal,title:prev.title,autoTitle:prev.autoTitle,...pinned?.vendor?{vendor:pinned.vendor}:{},...pinned?.engineCommand?{engineCommand:pinned.engineCommand}:{}}],activeId:id,nextOrdinal:ordinal+1}}var SHELL_SAFE_ARG=/^[A-Za-z0-9@%+=:,./_-]+$/;function shellCommandLine(argv){return argv.map((a)=>SHELL_SAFE_ARG.test(a)?a:`'${a.replaceAll("'","'\\''")}'`).join(" ")}function shellIdentityInput(taskId,tabId){let task=shellCommandLine([taskId]),tab=shellCommandLine([tabId]);return` export ROVE_TASK_ID=${task} KOBE_TASK_ID=${task} ROVE_TAB_ID=${tab} KOBE_TAB_ID=${tab} && clear\r`}function insertAfterActive(state,tab){let i=state.tabs.findIndex((t2)=>t2.id===state.activeId);return{tabs:[...state.tabs.slice(0,i+1),tab,...state.tabs.slice(i+1)],activeId:tab.id,nextOrdinal:state.nextOrdinal+1}}function addTab(state,vendor){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"engine",id:`tab-${ordinal}`,title:null,ordinal,vendor})}function openCommandTab(state,command,label){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command})}function findEditorTab(state){return state.tabs.find((tab)=>tab.kind==="command"&&tab.purpose==="editor")}function openEditorTab(state,command,label){let existing=findEditorTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command,purpose:"editor"})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,command,splitTree:null}:tab);return{...state,tabs,activeId:existing.id}}function findContentTab(state){return state.tabs.find((tab)=>tab.kind==="content")}function openContentTab(state,relPath,label,base){let existing=findContentTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"content",id:`tab-${ordinal}`,title:label,ordinal,relPath,base})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,relPath,base}:tab);return{...state,tabs,activeId:existing.id}}function closeTab(state,id,opts={}){if(state.tabs.length<=1&&!opts.allowEmpty)return{state,closedId:null};let i=state.tabs.findIndex((t2)=>t2.id===id);if(i<0)return{state,closedId:null};let tabs=state.tabs.filter((t2)=>t2.id!==id);if(state.activeId!==id)return{state:{...state,tabs},closedId:id};if(tabs.length===0)return{state:{...state,tabs,activeId:id,reopenAs:reopenHintFor(state.tabs[i])},closedId:id};let next=tabs[Math.max(0,i-1)];return{state:{...state,tabs,activeId:(next??tabs[0]).id},closedId:id}}function closeActiveTab(state){return closeTab(state,state.activeId)}function renameActiveTab(state,title){return setTabTitle(state,state.activeId,title)}function setTabTitle(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.title??null)===next)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,title:next}:t2);return{...state,tabs}}function setTabSessionId(state,id,sessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,sessionId}:t2);return{...state,tabs}}function setTabForkFrom(state,id,sourceSessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,forkFrom:sourceSessionId}:t2);return{...state,tabs}}function setTabEngineCommand(state,id,command){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,engineCommand:command}:t2);return{...state,tabs}}function setTabInitialPrompt(state,id,prompt){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,initialPrompt:prompt}:t2);return{...state,tabs}}function setTabLastTitle(state,id,lastTitle){if(lastTitle.length===0)return state;let current=state.tabs.find((t2)=>t2.id===id);if(!current||current.lastTitle===lastTitle)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,lastTitle}:t2);return{...state,tabs}}function setTabLiveVendor(state,id,liveVendor){let current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.liveVendor??null)===liveVendor)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,liveVendor}:t2);return{...state,tabs}}function setTabAutoTitle(state,id,autoTitle){let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,autoTitle}:t2);return{...state,tabs}}function setTabSpawned(state,id,spawned){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"&&!t2.spawned!==!spawned?{...t2,spawned}:t2);return{...state,tabs}}function cycleTab(state,delta){let n=state.tabs.length;if(n<=1)return state;let i=state.tabs.findIndex((t2)=>t2.id===state.activeId),next=state.tabs[(i+delta+n)%n];return{...state,activeId:next.id}}function gotoTab(state,index){let target=state.tabs[index];return target&&target.id!==state.activeId?{...state,activeId:target.id}:state}function moveTab(state,id,delta){let i=state.tabs.findIndex((t2)=>t2.id===id),j=i+delta;if(i<0||j<0||j>=state.tabs.length)return state;let tabs=[...state.tabs],a=tabs[i];return tabs[i]=tabs[j],tabs[j]=a,{...state,tabs}}function selectTab(state,id){if(state.activeId===id||!state.tabs.some((t2)=>t2.id===id))return state;return{...state,activeId:id}}function setTabSplit(state,id,tree){if(!state.tabs.some((t2)=>t2.id===id))return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,splitTree:tree}:t2);return{...state,tabs}}function tabPtyKey(taskId,tabId){return`${taskId}::${tabId}`}function tabPtyKeyFor(taskId,tab){if(tab.kind==="engine"&&tab.ptyTask)return tabPtyKey(tab.ptyTask.id,"tab-1");return tabPtyKey(taskId,tab.id)}function tabCwdFor(tab,taskWorktree){if(tab.kind==="engine"&&tab.ptyTask)return tab.ptyTask.worktree;return taskWorktree}function terminalTabsKey(taskId){return`terminalTabs.${taskId}`}function forgetTaskTabsSnapshot(kv,taskId){let key=terminalTabsKey(taskId);if(kv.store[key]===void 0)return;kv.set(key,void 0)}function sweepOrphanTabsSnapshots(kv,liveTaskIds){let live=new Set(liveTaskIds),swept=0;for(let key of Object.keys(kv.store)){if(!key.startsWith("terminalTabs."))continue;let taskId=key.slice(13);if(live.has(taskId))continue;kv.set(key,void 0),swept++}return swept}
|
|
2
|
+
import{buildEngineSessionLaunch,trustEngineWorktree}from"./chunk-e4a8pvek.js";import{engineForkArgv,engineResumeArgv,withPinnedSessionId}from"./chunk-pd8bnca7.js";import{engineEntry,engineStatusPrefixes,isEnginePlaceholderTitle,stripEngineStatusPrefix}from"./chunk-j1ms7bdj.js";import{tildify}from"./chunk-nvqdmx7q.js";import{t}from"./chunk-vhhje5qd.js";import{pathSyntax}from"./chunk-f10n6063.js";function engineTabArgv(tab,base,live,fallbackVendor){if(tab.forkFrom&&!tab.spawned&&!live){let forked=tab.vendor?engineForkArgv(base,tab.vendor,tab.forkFrom,tab.sessionId??null):null;if(forked)return forked}if(!tab.sessionId)return base;let vendor=tab.vendor??fallbackVendor;if(tab.spawned&&!live)return engineResumeArgv(base,vendor,tab.sessionId)??base;return withPinnedSessionId(base,vendor,()=>tab.sessionId).argv}function engineTabSpawnFor(state,tab,base,opts){let{live,shell,prompt}=opts,firstEngine=state.tabs.find((t2)=>t2.kind==="engine"),fresh=!tab.spawned&&!live,tabPrompt=fresh?tab.initialPrompt?.trim():void 0,wantsPrompt=!!prompt&&tab.id===firstEngine?.id&&fresh,isFreshFirstEngine=tab.id===firstEngine?.id&&fresh,promptIntent=tabPrompt?{kind:"explicit",prompt:tabPrompt}:wantsPrompt?{kind:"new-task",prompt}:isFreshFirstEngine?{kind:"repo-init"}:{kind:"none"},ref=tab.ptyTask;trustEngineWorktree(tab.vendor??opts.task.vendor,ref?.worktree??opts.worktreePath);let launch=buildEngineSessionLaunch({task:ref?{...opts.task,id:ref.id,kind:"task"}:opts.task,worktreePath:ref?.worktree??opts.worktreePath,shell,argv:engineTabArgv(tab,base,live,opts.task.vendor),promptIntent,protocolGates:opts.protocolGates,tabId:ref?"tab-1":tab.id});return{command:launch.command,...launch.firstMessage?{firstMessage:launch.firstMessage,engineBin:base[0]}:{}}}function tabExitAction(tab,deadOnAttach,resumeTried){if(tab.kind==="engine"&&deadOnAttach&&!!tab.sessionId&&tab.spawned&&!resumeTried)return"resume";return"close"}import*as fs from"fs";import*as os from"os";function pathLeaf(p){return p.slice(lastSeparator(p)+1)}function lastSeparator(p){return pathSyntax(p).sep==="\\"||process.platform==="win32"&&!p.startsWith("/")?Math.max(p.lastIndexOf("/"),p.lastIndexOf("\\")):p.lastIndexOf("/")}function expandHome(p){if(p==="~")return os.homedir();if(p.startsWith("~/")||process.platform==="win32"&&p.startsWith("~\\"))return os.homedir()+p.slice(1);return p}function stripTrailingSlash(p){let root=pathSyntax(p).parse(p).root,end=p.length;while(end>root.length&&lastSeparator(p.slice(0,end))===end-1)end--;return p.slice(0,end)}function splitPathForDirSuggest(value){if(!value)return{base:"",filter:""};let expanded=expandHome(value==="~"?"~/":value),lastSlash=lastSeparator(expanded);if(lastSlash===-1)return{base:"",filter:expanded};return{base:expanded.slice(0,lastSlash+1),filter:expanded.slice(lastSlash+1)}}function listSubdirs(base){if(!base)return[];try{let entries=fs.readdirSync(base,{withFileTypes:!0}),out=[];for(let e of entries)if(e.isDirectory())out.push(e.name);return out.sort((a,b)=>a.localeCompare(b))}catch{return[]}}function filterSubdirs(all,filter){let f=filter.toLowerCase(),visible=f.startsWith(".")?all:all.filter((n)=>!n.startsWith("."));if(!f)return visible;return visible.filter((n)=>n.toLowerCase().startsWith(f))}function joinDrill(typedValue,baseExpanded,name){let out=`${baseExpanded+name}/`;if(typedValue.startsWith("~")){let short=tildify(out);if(short.startsWith("~"))return short==="~"?"~/":`${short}/`}return out}function joinPicked(typedValue,baseExpanded,name){let out=baseExpanded+name;if(typedValue.startsWith("~"))return tildify(out);return out}function depth(node){return node.kind==="leaf"?0:1+Math.max(...node.children.map(depth))}function siblingCount(root,id,orientation){let find=(node)=>{if(node.kind==="leaf")return null;if(node.orientation===orientation&&node.children.some((c)=>c.kind==="leaf"&&c.id===id))return node.children.length;for(let child of node.children){let n=find(child);if(n!==null)return n}return null};return find(root)??1}function splitFits(state,orientation,activeSize){let extent=orientation==="row"?activeSize.cols:activeSize.rows,min=orientation==="row"?20:6,n=siblingCount(state.root,state.activeLeafId,orientation);return Math.floor(extent*n/(n+1))-1>=min}function initialSplit(content){return{root:{kind:"leaf",id:"leaf-1",content},activeLeafId:"leaf-1",nextOrdinal:2}}function leaves(node){return node.kind==="leaf"?[node]:node.children.flatMap(leaves)}function splitActive(state,orientation,content,activeSize){if(activeSize&&!splitFits(state,orientation,activeSize))return state;let leaf={kind:"leaf",id:`leaf-${state.nextOrdinal}`,content},insert=(node)=>{if(node.kind==="leaf"){if(node.id!==state.activeLeafId)return node;return{kind:"group",orientation,children:[node,leaf]}}if(node.orientation===orientation){let i=node.children.findIndex((c)=>c.kind==="leaf"&&c.id===state.activeLeafId);if(i>=0){let children=[...node.children.slice(0,i+1),leaf,...node.children.slice(i+1)];return{...node,children}}}return{...node,children:node.children.map(insert)}},root=insert(state.root);if(!activeSize&&depth(root)>4)return state;return{root,activeLeafId:leaf.id,nextOrdinal:state.nextOrdinal+1}}function removeLeaf(state,id){let all=leaves(state.root);if(all.length<=1)return null;let prune=(node)=>{if(node.kind==="leaf")return node.id===id?null:node;let children=node.children.map(prune).filter((c)=>c!==null);if(children.length===0)return null;if(children.length===1)return children[0];return{...node,children}},root=prune(state.root);if(root===null)return null;if(leaves(root).length===all.length)return state;let order=all.map((l)=>l.id),removedIdx=order.indexOf(id),fallback=order[removedIdx>0?removedIdx-1:removedIdx+1],activeLeafId=state.activeLeafId===id?fallback:state.activeLeafId;return{...state,root,activeLeafId}}function renameLeaf(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,walk=(node)=>node.kind==="leaf"?node.id===id?{...node,title:next}:node:{...node,children:node.children.map(walk)};if(!leaves(state.root).some((l)=>l.id===id))return state;return{...state,root:walk(state.root)}}function cycleLeaf(state,delta){let order=leaves(state.root).map((l)=>l.id);if(order.length<=1)return state;let i=order.indexOf(state.activeLeafId),next=order[(i+delta+order.length)%order.length];return{...state,activeLeafId:next}}function hasEngineLeaf(tree){return!tree||leaves(tree.root).some((l)=>l.id==="leaf-1")}function isTabSplit(tree){return tree?leaves(tree.root).length>1:!1}function collapseSplit(next){let ls=leaves(next.root);return ls.length===1&&ls[0]?.id==="leaf-1"?null:next}function splitLeafPtyKey(tabKey,leafId){return leafId==="leaf-1"?tabKey:`${tabKey}::${leafId}`}var SHELL_LEAF_NAME="shell";function splitLeafNames(leafList,tabCommand,engineTitle,liveTitles){let basename=(argv)=>{let head=(argv??tabCommand)[0]??"",name=pathLeaf(head);return name.length>0?name:"?"},seen=new Map,out=new Map;for(let leaf of leafList){if(leaf.title){out.set(leaf.id,leaf.title);continue}let name=leaf.content===null?engineTitle||liveTitles?.get(leaf.id)||basename(leaf.content):liveTitles?.get(leaf.id)||SHELL_LEAF_NAME,n=(seen.get(name)??0)+1;seen.set(name,n),out.set(leaf.id,n===1?name:`${name} ${n}`)}return out}function meaningfulAutoTitle(autoTitle){let trimmed=(autoTitle??"").trim();if(trimmed.length<3)return null;if(/^[\d\s\p{P}\p{S}]+$/u.test(trimmed))return null;return trimmed}function stableRecordedTitle(raw,vendor){let recorded=raw?.trim();if(!recorded)return null;let cleaned=stripEngineStatusPrefix(recorded,vendor);if(cleaned===recorded&&isEngineDecoration(recorded,vendor))return null;if(isEnginePlaceholderTitle(cleaned,vendor))return null;return cleaned||null}function isEngineDecoration(text,vendor){let glyphs=new Set(engineStatusPrefixes(vendor));return[...text].every((ch)=>ch.trim().length===0||glyphs.has(ch))}function tabTitleStable(tab,taskVendor,liveVendor,liveTitle){if(liveVendor===null&&tab.kind==="engine")return tabTitle({...tab,kind:"command",lastTitle:null},taskVendor);let vendor=liveVendor??tab.liveVendor??(tab.kind==="engine"?tab.vendor??taskVendor:void 0)??void 0,source=liveTitle?.trim()||tab.lastTitle,named=vendor?stableRecordedTitle(source,vendor):source??null;if(!vendor||engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return tabTitle({...tab,...vendor?{kind:"engine",vendor}:{},lastTitle:named},taskVendor);return tabTitle({...tab,kind:"engine",vendor,lastTitle:named},taskVendor)}function titleVendor(tab,taskVendor){return tab.liveVendor??(tab.kind==="engine"?tab.vendor:void 0)??taskVendor}function tabTitle(tab,taskVendor,liveName){if(tab.title)return tab.title;let ls=tab.splitTree?leaves(tab.splitTree.root):[];if(ls.length>1)return t("terminal.tab.groupTitle",{n:tab.ordinal});let sole=ls.length===1?ls[0]:void 0;if(sole&&sole.id!=="leaf-1")return sole.title??`${liveName??SHELL_LEAF_NAME} ${tab.ordinal}`;let vendor=titleVendor(tab,taskVendor);if(liveName&&!isEnginePlaceholderTitle(liveName,vendor))return`${liveName} ${tab.ordinal}`;if(tab.lastTitle&&!isEnginePlaceholderTitle(tab.lastTitle,vendor))return`${tab.lastTitle} ${tab.ordinal}`;let auto=meaningfulAutoTitle(tab.autoTitle);if(auto)return auto;return`${tab.kind==="engine"?engineEntry(tab.vendor??taskVendor).defaultCommand[0]??SHELL_LEAF_NAME:SHELL_LEAF_NAME} ${tab.ordinal}`}function visibleNativeStatus(tab,taskVendor,vendor,liveName){if(!vendor||!liveName)return!1;if(engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return!1;return tabTitle(tab,taskVendor,liveName)===`${liveName} ${tab.ordinal}`}function initialTabs(){return{tabs:[{kind:"engine",id:"tab-1",title:null,ordinal:1}],activeId:"tab-1",nextOrdinal:2}}function reopenHintFor(closed){if(closed?.kind==="command")return{kind:"command"};if(closed?.kind==="engine"&&closed.vendor)return{kind:"engine",vendor:closed.vendor};return{kind:"engine"}}function reopenTabs(state,shell){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,next=state.nextOrdinal+1;if(state.reopenAs?.kind==="command")return{tabs:[{kind:"command",id,title:null,ordinal,command:[shell]}],activeId:id,nextOrdinal:next};let vendor=state.reopenAs?.kind==="engine"?state.reopenAs.vendor:void 0;return{tabs:[{kind:"engine",id,title:null,ordinal,...vendor?{vendor}:{}}],activeId:id,nextOrdinal:next}}function initialShellTabs(shell){return{tabs:[{kind:"command",id:"tab-1",title:null,ordinal:1,command:[shell]}],activeId:"tab-1",nextOrdinal:2}}function rehydrateTabs(persisted,shell,opts={}){let tabs=persisted.tabs.map((t2)=>t2.kind==="command"?{...t2,command:shell,purpose:void 0}:t2);if(tabs.length===0)return opts.allowEmpty?persisted:initialTabs();let activeId=tabs.some((t2)=>t2.id===persisted.activeId)?persisted.activeId:tabs[0].id,maxOrdinal=tabs.reduce((max,t2)=>Math.max(max,t2.ordinal),0);return{tabs,activeId,nextOrdinal:Math.max(persisted.nextOrdinal,maxOrdinal+1)}}function recycleTabs(state,prev){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,pinned=prev.kind==="engine"?prev:void 0;return{tabs:[{kind:"engine",id,ordinal,title:prev.title,autoTitle:prev.autoTitle,...pinned?.vendor?{vendor:pinned.vendor}:{},...pinned?.engineCommand?{engineCommand:pinned.engineCommand}:{}}],activeId:id,nextOrdinal:ordinal+1}}var SHELL_SAFE_ARG=/^[A-Za-z0-9@%+=:,./_-]+$/;function shellCommandLine(argv){return argv.map((a)=>SHELL_SAFE_ARG.test(a)?a:`'${a.replaceAll("'","'\\''")}'`).join(" ")}function shellIdentityInput(taskId,tabId){let task=shellCommandLine([taskId]),tab=shellCommandLine([tabId]);return` export ROVE_TASK_ID=${task} KOBE_TASK_ID=${task} ROVE_TAB_ID=${tab} KOBE_TAB_ID=${tab} && clear\r`}function insertAfterActive(state,tab){let i=state.tabs.findIndex((t2)=>t2.id===state.activeId);return{tabs:[...state.tabs.slice(0,i+1),tab,...state.tabs.slice(i+1)],activeId:tab.id,nextOrdinal:state.nextOrdinal+1}}function addTab(state,vendor){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"engine",id:`tab-${ordinal}`,title:null,ordinal,vendor})}function openCommandTab(state,command,label){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command})}function findEditorTab(state){return state.tabs.find((tab)=>tab.kind==="command"&&tab.purpose==="editor")}function openEditorTab(state,command,label){let existing=findEditorTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command,purpose:"editor"})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,command,splitTree:null}:tab);return{...state,tabs,activeId:existing.id}}function findContentTab(state){return state.tabs.find((tab)=>tab.kind==="content")}function openContentTab(state,relPath,label,base){let existing=findContentTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"content",id:`tab-${ordinal}`,title:label,ordinal,relPath,base})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,relPath,base}:tab);return{...state,tabs,activeId:existing.id}}function closeTab(state,id,opts={}){if(state.tabs.length<=1&&!opts.allowEmpty)return{state,closedId:null};let i=state.tabs.findIndex((t2)=>t2.id===id);if(i<0)return{state,closedId:null};let tabs=state.tabs.filter((t2)=>t2.id!==id);if(state.activeId!==id)return{state:{...state,tabs},closedId:id};if(tabs.length===0)return{state:{...state,tabs,activeId:id,reopenAs:reopenHintFor(state.tabs[i])},closedId:id};let next=tabs[Math.max(0,i-1)];return{state:{...state,tabs,activeId:(next??tabs[0]).id},closedId:id}}function closeActiveTab(state){return closeTab(state,state.activeId)}function renameActiveTab(state,title){return setTabTitle(state,state.activeId,title)}function setTabTitle(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.title??null)===next)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,title:next}:t2);return{...state,tabs}}function setTabSessionId(state,id,sessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,sessionId}:t2);return{...state,tabs}}function setTabForkFrom(state,id,sourceSessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,forkFrom:sourceSessionId}:t2);return{...state,tabs}}function setTabEngineCommand(state,id,command){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,engineCommand:command}:t2);return{...state,tabs}}function setTabInitialPrompt(state,id,prompt){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,initialPrompt:prompt}:t2);return{...state,tabs}}function setTabLastTitle(state,id,lastTitle){if(lastTitle.length===0)return state;let current=state.tabs.find((t2)=>t2.id===id);if(!current||current.lastTitle===lastTitle)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,lastTitle}:t2);return{...state,tabs}}function setTabLiveVendor(state,id,liveVendor){let current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.liveVendor??null)===liveVendor)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,liveVendor}:t2);return{...state,tabs}}function setTabAutoTitle(state,id,autoTitle){let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,autoTitle}:t2);return{...state,tabs}}function setTabSpawned(state,id,spawned){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"&&!t2.spawned!==!spawned?{...t2,spawned}:t2);return{...state,tabs}}function cycleTab(state,delta){let n=state.tabs.length;if(n<=1)return state;let i=state.tabs.findIndex((t2)=>t2.id===state.activeId),next=state.tabs[(i+delta+n)%n];return{...state,activeId:next.id}}function gotoTab(state,index){let target=state.tabs[index];return target&&target.id!==state.activeId?{...state,activeId:target.id}:state}function moveTab(state,id,delta){let i=state.tabs.findIndex((t2)=>t2.id===id),j=i+delta;if(i<0||j<0||j>=state.tabs.length)return state;let tabs=[...state.tabs],a=tabs[i];return tabs[i]=tabs[j],tabs[j]=a,{...state,tabs}}function selectTab(state,id){if(state.activeId===id||!state.tabs.some((t2)=>t2.id===id))return state;return{...state,activeId:id}}function setTabSplit(state,id,tree){if(!state.tabs.some((t2)=>t2.id===id))return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,splitTree:tree}:t2);return{...state,tabs}}function tabPtyKey(taskId,tabId){return`${taskId}::${tabId}`}function tabPtyKeyFor(taskId,tab){if(tab.kind==="engine"&&tab.ptyTask)return tabPtyKey(tab.ptyTask.id,"tab-1");return tabPtyKey(taskId,tab.id)}function tabCwdFor(tab,taskWorktree){if(tab.kind==="engine"&&tab.ptyTask)return tab.ptyTask.worktree;return taskWorktree}function terminalTabsKey(taskId){return`terminalTabs.${taskId}`}function forgetTaskTabsSnapshot(kv,taskId){let key=terminalTabsKey(taskId);if(kv.store[key]===void 0)return;kv.set(key,void 0)}function sweepOrphanTabsSnapshots(kv,liveTaskIds){let live=new Set(liveTaskIds),swept=0;for(let key of Object.keys(kv.store)){if(!key.startsWith("terminalTabs."))continue;let taskId=key.slice(13);if(live.has(taskId))continue;kv.set(key,void 0),swept++}return swept}
|
|
3
3
|
export{pathLeaf,expandHome,stripTrailingSlash,splitPathForDirSuggest,listSubdirs,filterSubdirs,joinDrill,joinPicked,initialSplit,leaves,splitActive,removeLeaf,renameLeaf,cycleLeaf,hasEngineLeaf,isTabSplit,collapseSplit,splitLeafPtyKey,splitLeafNames,tabTitleStable,tabTitle,visibleNativeStatus,initialTabs,reopenTabs,initialShellTabs,rehydrateTabs,recycleTabs,engineTabArgv,engineTabSpawnFor,tabExitAction,shellIdentityInput,addTab,openCommandTab,findEditorTab,openEditorTab,openContentTab,closeTab,closeActiveTab,renameActiveTab,setTabTitle,setTabSessionId,setTabForkFrom,setTabEngineCommand,setTabInitialPrompt,setTabLastTitle,setTabLiveVendor,setTabAutoTitle,setTabSpawned,cycleTab,gotoTab,moveTab,selectTab,setTabSplit,tabPtyKey,tabPtyKeyFor,tabCwdFor,terminalTabsKey,forgetTaskTabsSnapshot,sweepOrphanTabsSnapshots};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
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-
|
|
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,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{writeOutdatedCache}from"./chunk-2rg6aw59.js";import{PluginCliError,installPlugin}from"./chunk-
|
|
2
|
+
import{writeOutdatedCache}from"./chunk-2rg6aw59.js";import{PluginCliError,installPlugin}from"./chunk-zk7z3b36.js";import{loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginDataDir,pluginStateDir,removePluginEntry,savePluginRegistry}from"./chunk-1da3bqjc.js";import"./chunk-w7zv47mp.js";import"./chunk-th3ff61b.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-hqbmzz4t.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";import{execFileSync}from"child_process";import{existsSync,mkdirSync,readdirSync,renameSync}from"fs";import{join}from"path";function gitOut(args,cwd){try{return execFileSync("git",args,{cwd,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return null}}function checkEntry(entry){let repoSpec=entry.source.spec.split("/").slice(0,2).join("/"),localSha=gitOut(["rev-parse","HEAD"],pluginCheckoutDir(entry.id)),remote=gitOut(["ls-remote",`https://github.com/${repoSpec}.git`,"HEAD"]),remoteSha=remote?remote.split(/\s+/)[0]??null:null;return{id:entry.id,spec:entry.source.spec,version:entry.version,localSha,remoteSha,behind:Boolean(localSha&&remoteSha&&localSha!==remoteSha)}}function listOutdated(){let rows=loadPluginRegistry().plugins.filter((p)=>p.source.kind==="github").map(checkEntry);return writeOutdatedCache(rows.filter((r)=>r.behind).map((r)=>r.id)),rows}function printOutdated(){let rows=listOutdated();if(rows.length===0){console.log("no GitHub-installed plugins.");return}for(let r of rows){let status=r.behind?"update available":r.remoteSha===null?"remote unreachable":r.localSha===null?"local sha unreadable":"up to date";console.log(`${r.id} v${r.version} ${status}`)}}function migrateRenamedPlugin(oldId,newId){for(let dirOf of[pluginConfigDir,pluginStateDir]){let from=dirOf(oldId),to=dirOf(newId);if(!existsSync(from))continue;mkdirSync(to,{recursive:!0});for(let entry of readdirSync(from)){if(existsSync(join(to,entry)))continue;renameSync(join(from,entry),join(to,entry))}}savePluginRegistry(removePluginEntry(loadPluginRegistry(),oldId)),console.log(`renamed ${oldId} \u2192 ${newId}: settings and state carried over, old entry unregistered`),console.log(` leftover checkout (safe to remove): ${pluginDataDir(oldId)}`)}async function updatePlugins(ids,opts){let rows=listOutdated(),targets;if(opts.all){if(targets=rows.filter((r)=>r.behind),targets.length===0){console.log("all plugins up to date.");return}}else{if(ids.length===0)throw new PluginCliError("update takes plugin ids or --all");targets=ids.map((id)=>{let row=rows.find((r)=>r.id===id);if(!row)throw new PluginCliError(`\`${id}\` is not a GitHub-installed plugin; see \`${activeCliName()} plugin list\``);return row})}for(let target of targets){if(!target.behind&&!ids.includes(target.id))continue;console.log(`updating ${target.id} (${target.spec})\u2026`);let installedId=await installPlugin(target.spec,{yes:opts.yes});if(installedId!==target.id)migrateRenamedPlugin(target.id,installedId)}listOutdated()}export{updatePlugins,printOutdated};
|