@sma1lboy/rove 0.9.280 → 0.9.281

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.
Files changed (111) hide show
  1. package/dist/cli/chunk-01tghgf3.js +8 -0
  2. package/dist/cli/{chunk-jk4f0xsh.js → chunk-03fv92ya.js} +1 -1
  3. package/dist/cli/{chunk-7aaw17vr.js → chunk-08mb3qss.js} +1 -1
  4. package/dist/cli/{chunk-y7mjhjby.js → chunk-0gbg7bg8.js} +1 -1
  5. package/dist/cli/{chunk-zv0rrhck.js → chunk-0nkk13z9.js} +1 -1
  6. package/dist/cli/{chunk-zp0q931y.js → chunk-14tevt5v.js} +1 -1
  7. package/dist/cli/{chunk-1g6vhgfe.js → chunk-16e6jqq6.js} +1 -1
  8. package/dist/cli/{chunk-3hxm56h6.js → chunk-1a57ejnh.js} +1 -1
  9. package/dist/cli/{chunk-4z1a65bz.js → chunk-32y7f5dr.js} +1 -1
  10. package/dist/cli/{chunk-j54c5a0a.js → chunk-3m0ydze9.js} +1 -1
  11. package/dist/cli/{chunk-tqxbbg3k.js → chunk-3pgp6z3k.js} +1 -1
  12. package/dist/cli/{chunk-amq030gb.js → chunk-3qj9yw5c.js} +2 -2
  13. package/dist/cli/chunk-453qpfae.js +2 -0
  14. package/dist/cli/{chunk-gk8efsx0.js → chunk-46qs744w.js} +1 -1
  15. package/dist/cli/{chunk-am5cpb9n.js → chunk-4vkrv4eb.js} +1 -1
  16. package/dist/cli/{chunk-hfvzvj91.js → chunk-4yr1534j.js} +1 -1
  17. package/dist/cli/{chunk-byh32qnx.js → chunk-5swmvt20.js} +1 -1
  18. package/dist/cli/{chunk-j8d9sk5j.js → chunk-6wt08a28.js} +1 -1
  19. package/dist/cli/{chunk-f262ywvg.js → chunk-7911jkq6.js} +1 -1
  20. package/dist/cli/chunk-8ng1756g.js +3 -0
  21. package/dist/cli/{chunk-ebdp0z1d.js → chunk-95kk75wh.js} +1 -1
  22. package/dist/cli/{chunk-6mk6ceb6.js → chunk-9qpea48c.js} +2 -2
  23. package/dist/cli/chunk-9vwb9f7q.js +7 -0
  24. package/dist/cli/{chunk-nqwza8b0.js → chunk-a5xbsvx2.js} +1 -1
  25. package/dist/cli/{chunk-t7dyf50m.js → chunk-ap3fgbbt.js} +1 -1
  26. package/dist/cli/{chunk-5kgq379z.js → chunk-b5fdqynx.js} +1 -1
  27. package/dist/cli/{chunk-x85rcep5.js → chunk-bbq6wc47.js} +1 -1
  28. package/dist/cli/{chunk-np398f2a.js → chunk-bbt217yd.js} +1 -1
  29. package/dist/cli/{chunk-w2tcb3rn.js → chunk-bm6qhcck.js} +1 -1
  30. package/dist/cli/{chunk-txvjg1g9.js → chunk-btxfcc77.js} +3 -3
  31. package/dist/cli/chunk-c9ptxthj.js +2 -0
  32. package/dist/cli/{chunk-zkby63ej.js → chunk-cs410j8b.js} +1 -1
  33. package/dist/cli/{chunk-rvjnafyt.js → chunk-cx78tyg1.js} +1 -1
  34. package/dist/cli/{chunk-4drm07mp.js → chunk-cx8wnz54.js} +1 -1
  35. package/dist/cli/{chunk-t2p22ww7.js → chunk-ejfs22aq.js} +1 -1
  36. package/dist/cli/chunk-f23manyf.js +8 -0
  37. package/dist/cli/{chunk-7nnpp89t.js → chunk-ga82ras9.js} +1 -1
  38. package/dist/cli/{chunk-f7egph8g.js → chunk-gzkes5bw.js} +1 -1
  39. package/dist/cli/{chunk-xy5mrrqk.js → chunk-hmy01yg2.js} +16 -14
  40. package/dist/cli/{chunk-3a7x7jg7.js → chunk-hnxs5shy.js} +16 -17
  41. package/dist/cli/{chunk-bw2y7670.js → chunk-j2e7jgh8.js} +1 -1
  42. package/dist/cli/{chunk-qc9sj5wh.js → chunk-j5y7hhc2.js} +1 -1
  43. package/dist/cli/{chunk-qzhfs668.js → chunk-jar50zcp.js} +1 -1
  44. package/dist/cli/{chunk-r98h6b42.js → chunk-k2rmj0v3.js} +2 -2
  45. package/dist/cli/{chunk-bv050ssb.js → chunk-k3h4cpdy.js} +1 -1
  46. package/dist/cli/{chunk-wz307hf6.js → chunk-k9xabf0t.js} +1 -1
  47. package/dist/cli/{chunk-02x0ahxk.js → chunk-kp43j420.js} +1 -1
  48. package/dist/cli/{chunk-6cfs0nqe.js → chunk-kt5ngemc.js} +1 -1
  49. package/dist/cli/chunk-nkgn0bqq.js +2 -0
  50. package/dist/cli/{chunk-fkgemeww.js → chunk-q2nhmaq9.js} +2 -2
  51. package/dist/cli/{chunk-hd1szhba.js → chunk-q6cwy6v5.js} +1 -1
  52. package/dist/cli/{chunk-jkgp816v.js → chunk-q72w3dsx.js} +1 -1
  53. package/dist/cli/{chunk-hmsvt5nj.js → chunk-rqm2kn0c.js} +1 -1
  54. package/dist/cli/{chunk-q6tsx6zc.js → chunk-sm96b61g.js} +1 -1
  55. package/dist/cli/chunk-sqdmngys.js +2 -0
  56. package/dist/cli/{chunk-k2j0tg1h.js → chunk-tgv90744.js} +7 -3
  57. package/dist/cli/{chunk-vbvbwjad.js → chunk-twy9bfps.js} +1 -1
  58. package/dist/cli/{chunk-5g6v6tq5.js → chunk-v3ecphrz.js} +1 -1
  59. package/dist/cli/{chunk-mjzjah9d.js → chunk-vtay379p.js} +1 -1
  60. package/dist/cli/chunk-vx44yxra.js +3 -0
  61. package/dist/cli/{chunk-w003rpr2.js → chunk-w3kvkax7.js} +1 -1
  62. package/dist/cli/{chunk-s1xn6wav.js → chunk-w6ft4djp.js} +1 -1
  63. package/dist/cli/{chunk-8hernv9y.js → chunk-w8dmmnys.js} +1 -1
  64. package/dist/cli/{chunk-9f34p80j.js → chunk-ww0zctb7.js} +1 -1
  65. package/dist/cli/{chunk-qwwt4ch2.js → chunk-x119xqa6.js} +1 -1
  66. package/dist/cli/{chunk-nrx8pf9p.js → chunk-x35dfb1x.js} +1 -1
  67. package/dist/cli/{chunk-ggjmcqpt.js → chunk-x94e0rw4.js} +3 -3
  68. package/dist/cli/chunk-xaam0d8r.js +4 -0
  69. package/dist/cli/{chunk-azt0c2b5.js → chunk-xekk4k54.js} +1 -1
  70. package/dist/cli/{chunk-mqvkd2g1.js → chunk-xqvyzv62.js} +1 -1
  71. package/dist/cli/chunk-xxz3np4w.js +2 -0
  72. package/dist/cli/{chunk-p11emdb2.js → chunk-y07cp9mb.js} +1 -1
  73. package/dist/cli/{chunk-5dq0n3h7.js → chunk-y2v1x23z.js} +1 -1
  74. package/dist/cli/chunk-yn01fet6.js +3 -0
  75. package/dist/cli/{chunk-cakyme4s.js → chunk-z8rvxvx5.js} +1 -1
  76. package/dist/cli/chunk-zr058kbe.js +3 -0
  77. package/dist/cli/index.js +3 -3
  78. package/dist/cli/rove.js +3 -3
  79. package/dist/skills/rove/SKILL.md +4 -2
  80. package/dist/skills/rove/references/api-flags.md +7 -4
  81. package/dist/voice/asr_server.py +318 -0
  82. package/dist/voice/engine.py +174 -0
  83. package/dist/voice/fetch_model.py +30 -0
  84. package/dist/voice/learn.py +184 -0
  85. package/dist/voice/live.py +93 -0
  86. package/dist/voice/phonetic.py +87 -0
  87. package/dist/voice/polish.py +84 -0
  88. package/dist/voice/polish_prompt.md +50 -0
  89. package/dist/voice/pyproject.toml +28 -0
  90. package/dist/voice/uv.lock +815 -0
  91. package/dist/voice/vocab.py +193 -0
  92. package/dist/web/assets/index-Bo92_NP5.css +1 -0
  93. package/dist/web/assets/index-Ct8dDnCc.js +154 -0
  94. package/dist/web/dictation-worklet.js +31 -0
  95. package/dist/web/index.html +3 -3
  96. package/dist/web/relay/index.html +6 -6
  97. package/package.json +4 -3
  98. package/dist/cli/chunk-0g1h35mr.js +0 -2
  99. package/dist/cli/chunk-1wwqf6kx.js +0 -3
  100. package/dist/cli/chunk-26ydgwym.js +0 -2
  101. package/dist/cli/chunk-2pfh3zm0.js +0 -33
  102. package/dist/cli/chunk-2wrt80ft.js +0 -3
  103. package/dist/cli/chunk-7fya3y0n.js +0 -2
  104. package/dist/cli/chunk-d2wndk4q.js +0 -2
  105. package/dist/cli/chunk-mey3vksj.js +0 -2
  106. package/dist/cli/chunk-nv8eyjep.js +0 -3
  107. package/dist/cli/chunk-ve76p2mx.js +0 -3
  108. package/dist/cli/chunk-wfgrn8p2.js +0 -4
  109. package/dist/cli/chunk-xmjknfy2.js +0 -7
  110. package/dist/web/assets/index-CuglNDLi.css +0 -1
  111. package/dist/web/assets/index-DIN0Lz5C.js +0 -149
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{embeddedTerminalEnv}from"./chunk-7bgbansg.js";import{LAUNCH_PREFIX_FILE,freshSessionState}from"./chunk-4dt1gfb3.js";import{ClientWriter,LineReceiver,clearTransientStatuses,createOscSignals,objectPayload,optionalBoolean,requireString,scanOscSignals}from"./chunk-tq0h3vy6.js";import{writeTextAtomic}from"./chunk-5mhvjytn.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-w77s2df8.js";import{foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors,replayStart,scanTerminalModes,terminalModePreamble}from"./chunk-mqfvzdpr.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-rxqdw6s5.js";import{resolveSessionShell}from"./chunk-tn9gtf18.js";import{spawnDetachedDaemon,withoutPtyJob}from"./chunk-bcyex84w.js";import{recordPtyExit}from"./chunk-2w228s7t.js";import"./chunk-etfh8f4z.js";import{CURRENT_VERSION}from"./chunk-2wrt80ft.js";import{DAEMON_PROTOCOL_VERSION,PTY_STOP_REFUSED,frameToLine}from"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import{listenOnUnixSocket}from"./chunk-br8r72bf.js";import{ensureOwnerOnlyStateDir}from"./chunk-yt15y085.js";import"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import{rotateLogIfNeeded}from"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,endpointPathFor,isWindowsPipePath,resolveDaemonHomeDir}from"./chunk-eqdbfgq5.js";import{preRenameStateDir}from"./chunk-f8gg8cqh.js";import{ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";function formatPtyHostLine(event,message,now=new Date){return`[${now.toISOString()}] pty-host [${event}]: ${message}`}import{readFileSync as readFileSync2}from"fs";import{mkdir,unlink}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync}from"fs";import{homedir}from"os";import{join}from"path";var PTY_HOST_DATA_ENTRIES=["pty-exits.json","pty-sessions"];function lstatIfExists(path){try{return lstatSync(path)}catch{return}}function migrateLegacyPtyHostData(homeDir=readRoveHomeDirEnv()??homedir()){let canonicalDir=join(homeDir,ROVE_STATE_DIR_BASENAME),legacyDir=preRenameStateDir(homeDir);if(canonicalDir===legacyDir)return[];let moved=[];for(let name of PTY_HOST_DATA_ENTRIES){let canonical=join(canonicalDir,name),legacy=join(legacyDir,name);try{if(existsSync(canonical))continue;let stat=lstatIfExists(legacy);if(!stat||stat.isSymbolicLink())continue;mkdirSync(canonicalDir,{recursive:!0}),renameSync(legacy,canonical),moved.push(name)}catch{}}return moved}import{spawn}from"child_process";import{randomUUID}from"crypto";import{readFileSync}from"fs";import path from"path";var TERMINAL_NAME="xterm-256color";function bunTerminalDriver(spawn){let spawnTerminal=spawn??((argv,options)=>Bun.spawn(argv,options));return(request)=>{let proc=spawnTerminal([...request.argv],{cwd:request.cwd,env:request.env,terminal:{cols:request.cols,rows:request.rows,name:TERMINAL_NAME,data:(_terminal,data)=>request.onData(data)}});return{pid:proc.pid,exited:proc.exited.then(()=>({code:proc.exitCode??null,signal:proc.signalCode??null}),()=>({code:null,signal:null})),write:(data)=>proc.terminal?.write(data),resize:(cols,rows)=>proc.terminal?.resize(cols,rows),close:()=>proc.terminal?.close(),kill:(signal)=>proc.kill(signal)}}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,programStatusEvent:s.programStatusEvent,programStatus:s.oscSignals?.records.get(""),contexts:s.oscSignals?.contexts,totalBytes:s.totalBytes,parked:s.parked,parkedScreenBytes:s.parkedScreenBytes,exit:s.exit,restored:s.restored||void 0}}function describeExit(exit){if(exit?.signal)return` (signal ${exit.signal})`;if(exit&&exit.code!==null)return` (code ${exit.code})`;return" (cause unknown)"}function ringTail(chunks,bytes,maxBytes){let skip=Math.max(0,bytes-maxBytes),seen=0,parts=[];for(let chunk of chunks){if(seen+chunk.byteLength>skip)parts.push(seen>=skip?chunk:chunk.subarray(skip-seen));seen+=chunk.byteLength}return Buffer.concat(parts).toString("utf8")}function hostStats(sessions,perSessionCap,parkRestoreDeltas,parkRestoreFallbacks){let ringBytes=0,count=0,parkedSessions=0,parkedScreenBytes=0;for(let session of sessions)if(count++,ringBytes+=session.bytes,session.parked)parkedSessions++,parkedScreenBytes+=session.parkedScreenBytes;return{ringBytes,ringCapacityBytes:count*perSessionCap,parkedSessions,parkedScreenBytes,parkRestoreDeltas,parkRestoreFallbacks}}var OSC_TITLE_RE=/\x1b\][02];([^\x07\x1b]*)(?:\x07|\x1b\\)/g,TITLE_CARRY_CAP=1024;function titleCarryFrom(rest){let osc=rest.lastIndexOf("\x1B]");if(osc!==-1)return rest.slice(osc,osc+TITLE_CARRY_CAP);return rest.endsWith("\x1B")?"\x1B":""}function foldOscTitle(prevCarry,chunkText){let text=prevCarry+chunkText,title=null,end=0;OSC_TITLE_RE.lastIndex=0;for(let match=OSC_TITLE_RE.exec(text);match;match=OSC_TITLE_RE.exec(text))title=match[1]??"",end=match.index+match[0].length;return{title,carry:titleCarryFrom(text.slice(end))}}function scanOscTitle(session,buf){let{title,carry}=foldOscTitle(session.titleCarry,session.titleDecoder.write(buf));if(title!==null)session.title=title;session.titleCarry=carry}function peekRing(session,sinceOffset){if(!session)return{exists:!1,alive:!1,pid:null,offset:0,data:"",sinceValid:!1,exit:null};let windowStart=session.totalBytes-session.bytes,buf=Buffer.concat(session.chunks),sinceValid=!1;if(sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes)buf=buf.subarray(sinceOffset-windowStart),sinceValid=!0;return{exists:!0,alive:session.alive,pid:session.proc?.pid??null,offset:session.totalBytes,data:buf.toString("base64"),sinceValid,exit:session.exit??null}}async function settledWithin(exited,ms){let timer,settled=await Promise.race([exited.then(()=>!0,()=>!0),new Promise((resolve)=>{timer=setTimeout(()=>resolve(!1),ms)})]);if(timer)clearTimeout(timer);return settled}function signalProcessGroup(pid,signal,fallback,platform=process.platform,onSignal){if(platform!=="win32"&&pid>1)try{process.kill(-pid,signal),onSignal?.(`sent ${signal} to process group -${pid}`);return}catch{}try{fallback(),onSignal?.(`sent ${signal} to pid ${pid} (per-process fallback)`)}catch{}}var TERMINATION_GRACE_MS=500;async function terminatePtyChild(proc,onSettled,onSignal){if(proc.endTree){onSignal?.(await proc.endTree()),signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS),onSettled();return}if(signalProcessGroup(proc.pid,"SIGTERM",()=>proc.kill("SIGTERM"),process.platform,onSignal),!await settledWithin(proc.exited,TERMINATION_GRACE_MS))signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS);onSettled()}class PtyChildController{deps;constructor(deps){this.deps=deps}spawn(key,spec,spare=!1){let argv=spec.command&&spec.command.length>0?[...spec.command]:[spec.shell??resolveSessionShell()],session=freshSessionState(key,spec,argv);if(this.startChild(session),session.alive)this.deps.log?.("pty",`spawned ${argv[0]} for ${key} (pid ${session.proc?.pid})`),this.deps.onSessionStart?.(spare);return session}startChild(session){session.generation=randomUUID(),session.oscSignals=void 0,session.programStatusEvent=void 0,this.reportStatus(session,null);try{let launch=launchWrapper(session.cwd,session.generation);session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...launch.prefix,...session.command],cwd:session.cwd,env:embeddedTerminalEnv(process.env,{TERM:"xterm-256color",COLUMNS:String(session.cols),LINES:String(session.rows),BASH_SILENCE_DEPRECATION_WARNING:"1",ROVE_TERMINAL_PTY:"1",...process.env.SHELL?.trim()?{}:{SHELL:resolveSessionShell()}}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0;let reap=launch.reap;session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session)).then(()=>{if(reap.length>0)spawn(reap[0],reap.slice(1),{detached:!0,stdio:"ignore"}).unref()})}catch(err){session.alive=!1,this.deps.log?.("pty",`spawn failed for ${session.key}: ${err instanceof Error?err.message:String(err)}`)}}async endChild(session){if(!session.alive)return;let proc=session.proc;if(!proc){this.markExited(session);return}await terminatePtyChild(proc,()=>this.markExited(session),(line)=>this.deps.log?.("pty-signal",`${session.key}: ${line}`))}markExited(session,exit){if(!session.alive)return;if(session.alive=!1,session.oscSignals){let before=session.oscSignals.records.get("");if(clearTransientStatuses(session.oscSignals),before!==session.oscSignals.records.get(""))this.reportStatus(session,null)}let sessionExit={code:exit?.code??null,signal:exit?.signal??null,at:new Date().toISOString()};session.exit=sessionExit;try{session.proc?.close()}catch{}this.deps.onExit?.(session,sessionExit)}reportStatus(session,status){let event={key:session.key,generation:session.generation,revision:(session.programStatusEvent?.revision??0)+1,at:Date.now(),status};session.programStatusEvent=event,this.deps.onProgramStatus?.(event)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),text=buf.toString("latin1");session.oscSignals??=createOscSignals();let queries=scanOscSignals(session.oscSignals,buf,Date.now(),(status)=>this.reportStatus(session,status)),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,text);session.colorQueryCarry=colorQueries.carry;let replies=colorQueries.slots.map((slot)=>formatDefaultColorReply(slot,session.defaultColors));for(let i=0;i<Math.min(queries,16);i++)replies.push("\x1B]7501;?\x1B\\");let modeReplies=scanTerminalModes(session.modes,text);if(session.emulatorSinks.size===0)replies.push(...modeReplies);if(replies.length>0)try{session.proc?.write(replies.join(""))}catch{}scanOscTitle(session,buf),session.kitty.push(buf),session.chunks.push(buf),session.bytes+=buf.byteLength,session.totalBytes+=buf.byteLength;while(session.bytes>this.deps.scrollbackCap&&session.chunks.length>1){let dropped=session.chunks.shift();if(!dropped)break;session.bytes-=dropped.byteLength,scanTerminalModes(session.ringModes,dropped.toString("latin1"))}this.deps.onOutput?.(session,buf)}}function launchWrapper(cwd,id){let raw;try{raw=readFileSync(path.join(cwd,LAUNCH_PREFIX_FILE),"utf8")}catch{return{prefix:[],reap:[]}}let file=JSON.parse(raw),argv=(field,name)=>{if(field===void 0&&name==="reap")return[];if(!Array.isArray(field)||!field.every((a)=>typeof a==="string"))throw Error(`${LAUNCH_PREFIX_FILE} in ${cwd}: "${name}" is not a string array`);return field.map((a)=>a.replaceAll("{launch}",id))};return{prefix:argv(file.prefix,"prefix"),reap:argv(file.reap,"reap")}}function shouldFreeze(session,now){let appended=session.totalBytes-(session.frozenTotalBytes??0);if(appended<=0)return!1;let since=now-session.lastFreezeAtMs;if(since<5000)return!1;return appended>=65536||since>=60000}class WarmSpare{deps;spare=null;constructor(deps){this.deps=deps}warm(cwd,shell,cols=80,rows=24){let argv0=shell??resolveSessionShell();if(this.spare?.alive&&this.spare.cwd===cwd&&this.spare.command[0]===argv0)return;let old=this.spare;if(this.spare=null,old)this.deps.endChild(old);let session=this.deps.spawn("::spare",{cwd,command:[argv0],cols,rows},!0);this.spare=session.alive?session:null}adopt(key,spec){let spare=this.spare;if(!spare?.alive||spare.cwd!==spec.cwd)return null;let want=spec.command&&spec.command.length>0?spec.command:[spec.shell??resolveSessionShell()];if(want.length!==1||want[0]!==spare.command[0])return null;this.spare=null,spare.key=key,spare.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??spare.defaultColors;let cols=spec.cols??spare.cols,rows=spec.rows??spare.rows;if(spare.cols!==cols||spare.rows!==rows){spare.cols=cols,spare.rows=rows;try{spare.proc?.resize(cols,rows)}catch{return this.deps.markExited(spare),null}}return this.deps.log?.("pty",`adopted warm shell for ${key} (pid ${spare.proc?.pid})`),this.deps.onSessionStart?.(),this.warm(spec.cwd,spare.command[0],cols,rows),spare}async end(){let spare=this.spare;if(this.spare=null,spare)await this.deps.endChild(spare)}}var LOGGED_WRITE_BYTES=1024,DEFAULT_SCROLLBACK_CAP=524288,EXIT_TAIL_BYTES=16384;function fullReplay(session,ring){return Buffer.concat([Buffer.from(terminalModePreamble(session.ringModes.modes),"latin1"),session.kitty.replay(),ring.subarray(replayStart(session.ringModes,ring))])}class PtyHost{sessions=new Map;opts;scrollbackCap;shuttingDown=!1;parkRestoreDeltas=0;parkRestoreFallbacks=0;childController;warmSpare;constructor(opts={}){this.opts=opts,this.scrollbackCap=opts.scrollbackCap??DEFAULT_SCROLLBACK_CAP,this.childController=new PtyChildController({driver:opts.driver,onProgramStatus:(event)=>this.opts.onProgramStatus?.(event),scrollbackCap:this.scrollbackCap,onSessionStart:(spare)=>{if(!spare)this.opts.onSessionStart?.()},onOutput:(session,data)=>{if(session.sinks.size===0){this.maybeFreeze(session);return}let frame={type:"event",name:"pty.data",payload:{key:session.key,data:data.toString("base64"),offset:session.totalBytes}};for(let sink of session.sinks.values())sink(frame);this.maybeFreeze(session)},onExit:(session,exit)=>{let frame={type:"event",name:"pty.exit",payload:{key:session.key,pid:session.proc?.pid??null,...exit}};for(let sink of session.sinks.values())sink(frame);if(this.opts.log?.("pty",`session ${session.key} exited${describeExit(exit)}`),this.maybeFreeze(session,!0),!session.closedByRequest)try{this.opts.onSessionExit?.({key:session.key,pid:session.proc?.pid??null,exit,tail:ringTail(session.chunks,session.bytes,EXIT_TAIL_BYTES)})}catch{}this.opts.onSessionEnd?.()},log:(event,message)=>this.opts.log?.(event,message)}),this.warmSpare=new WarmSpare({spawn:(key,spec,spare)=>this.childController.spawn(key,spec,spare),endChild:(session)=>this.childController.endChild(session),markExited:(session)=>this.childController.markExited(session),log:(event,message)=>this.opts.log?.(event,message),onSessionStart:()=>this.opts.onSessionStart?.()})}open(key,spec,token,sink,sinceOffset,sincePid,answersQueries=!1){let session=this.sessions.get(key),created=!1,respawned=!1;if(!session)created=!0,session=this.warmSpare.adopt(key,spec)??this.childController.spawn(key,spec),this.sessions.set(key,session);else if(!session.alive&&session.restored)this.respawn(session,spec),respawned=session.alive;else if(session.alive&&spec.cols!==void 0&&spec.rows!==void 0&&(session.cols!==spec.cols||session.rows!==spec.rows))this.resize(key,spec.cols,spec.rows);let defaultColors=parseTerminalDefaultColors(spec.defaultColors);if(defaultColors)session.defaultColors=defaultColors;if(session.sinks.set(token,sink),answersQueries)session.emulatorSinks.add(token);else session.emulatorSinks.delete(token);session.parked=!1,session.parkedScreenBytes=0;let windowStart=session.totalBytes-session.bytes,replay=Buffer.concat(session.chunks),sinceValid=!1;if(!created&&sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes&&sincePid!==void 0&&sincePid===session.proc?.pid)replay=replay.subarray(sinceOffset-windowStart),sinceValid=!0;if(sinceOffset!==void 0&&sincePid!==void 0)if(sinceValid)this.parkRestoreDeltas++;else this.parkRestoreFallbacks++;if(!sinceValid)replay=fullReplay(session,replay);return{replay:replay.toString("base64"),alive:session.alive,pid:session.proc?.pid??null,created,respawned,offset:session.totalBytes,sinceValid}}warm(cwd,shell,cols=80,rows=24){this.warmSpare.warm(cwd,shell,cols,rows)}write(key,data){let session=this.sessions.get(key);if(!session?.alive||data.length===0)return;if(data.length>=LOGGED_WRITE_BYTES)this.opts.log?.("pty",`wrote ${data.length} bytes to ${key}`);try{session.proc?.write(data)}catch(error){this.opts.log?.("pty",`write failed on ${key} (${data.length} bytes): ${String(error)}`)}}resize(key,cols,rows){let session=this.sessions.get(key);if(!session?.alive)return;session.cols=cols,session.rows=rows;try{session.proc?.resize(cols,rows)}catch{}}killIfGeneration(key,expectedGeneration){let session=this.sessions.get(key);if(!session)return{accepted:!1,reason:"missing-session"};if(session.generation!==expectedGeneration)return{accepted:!1,reason:"generation-mismatch"};return this.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}kill(key){let session=this.sessions.get(key);if(!session)return Promise.resolve();return this.sessions.delete(key),session.closedByRequest=!0,this.opts.freeze?.drop(key),this.childController.endChild(session)}rename(from,to){let session=this.sessions.get(from);if(!session||from===to||this.sessions.has(to))return!1;if(this.sessions.delete(from),session.key=to,session.programStatusEvent){let previous=session.programStatusEvent;this.opts.onProgramStatus?.({...previous,revision:previous.revision+1,at:Date.now(),status:null}),session.programStatusEvent={...previous,key:to,revision:previous.revision+1,at:Date.now()},this.opts.onProgramStatus?.(session.programStatusEvent)}return this.sessions.set(to,session),this.opts.freeze?.drop(from),this.maybeFreeze(session,!0),this.opts.log?.("pty",`renamed session ${from} \u2192 ${to}`),!0}detach(key,token,parked=!1,parkedScreenBytes=0){let session=this.sessions.get(key);if(!session)return;session.sinks.delete(token),session.emulatorSinks.delete(token),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(session.emulatorSinks.delete(token),!session.sinks.delete(token))continue;this.applyParkedOnDetach(session)}}applyParkedOnDetach(session,parked=!1,parkedScreenBytes=0){if(session.sinks.size!==0)return;session.parked=parked,session.parkedScreenBytes=parked?Math.max(0,parkedScreenBytes):0}list(){return Array.from(this.sessions.values(),(s)=>sessionInfo(s))}peek(key,sinceOffset,preamble=!1){let session=this.sessions.get(key),peek=peekRing(session,sinceOffset);if(!preamble||!session||sinceOffset!==void 0)return peek;return{...peek,data:fullReplay(session,Buffer.from(peek.data,"base64")).toString("base64")}}stats(){return hostStats(this.sessions.values(),this.scrollbackCap,this.parkRestoreDeltas,this.parkRestoreFallbacks)}async killAll(){let sessions=Array.from(this.sessions.keys(),(key)=>this.kill(key));sessions.push(this.warmSpare.end()),await Promise.all(sessions)}async shutdown(){this.flushFrozen(),this.shuttingDown=!0;let endings=Array.from(this.sessions.values(),(session)=>this.childController.endChild(session));endings.push(this.warmSpare.end()),await Promise.all(endings)}flushFrozen(){for(let session of this.sessions.values())this.maybeFreeze(session,!0)}restoreFrozen(records){let restoredCount=0;for(let record of records){if(this.sessions.has(record.key))continue;let session=thawSession(record,this.scrollbackCap);if(!session)continue;this.sessions.set(record.key,session),restoredCount++}if(restoredCount>0)this.opts.log?.("pty",`restored ${restoredCount} frozen session(s) from disk`);return restoredCount}respawn(session,spec){if(session.restored=!1,session.exit=null,spec.command&&spec.command.length>0)session.command=[...spec.command];if(session.cols=spec.cols??session.cols,session.rows=spec.rows??session.rows,session.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??session.defaultColors,this.childController.startChild(session),!session.alive)return;this.opts.log?.("pty",`respawned restored session ${session.key} (pid ${session.proc?.pid})`),this.opts.onSessionStart?.()}maybeFreeze(session,force=!1){let freeze=this.opts.freeze;if(!freeze||session.key.startsWith("::"))return;if(session.closedByRequest||this.shuttingDown)return;let now=Date.now();if(!force&&!shouldFreeze(session,now))return;session.lastFreezeAtMs=now,session.frozenTotalBytes=session.totalBytes,freeze.save(freezeSession(session))}liveCount(){let n=0;for(let session of this.sessions.values())if(session.alive)n++;return n}}function dispatchPtyRequest(req,client,deps){let{ptys}=deps;switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.openChecked":case"pty.open":{let payload=objectPayload(req.payload);if(req.name==="pty.openChecked"&&requireString(payload,"admissionToken")!==admissionToken(ptys))return{kind:"changed"};let open=ptys.open(requireString(payload,"key"),{cwd:requireString(payload,"cwd"),command:Array.isArray(payload.command)?payload.command.filter((c)=>typeof c==="string"):void 0,shell:typeof payload.shell==="string"?payload.shell:void 0,cols:typeof payload.cols==="number"?payload.cols:void 0,rows:typeof payload.rows==="number"?payload.rows:void 0,defaultColors:parseTerminalDefaultColors(payload.defaultColors)??void 0},client,(frame)=>deps.writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0,payload.answersQueries===!0);return req.name==="pty.openChecked"?{kind:"opened",open}:open}case"pty.write":{let payload=objectPayload(req.payload);return ptys.write(requireString(payload,"key"),typeof payload.data==="string"?payload.data:""),{}}case"pty.resize":{let payload=objectPayload(req.payload);return ptys.resize(requireString(payload,"key"),typeof payload.cols==="number"?payload.cols:80,typeof payload.rows==="number"?payload.rows:24),{}}case"pty.kill":{let payload=objectPayload(req.payload),key=requireString(payload,"key");if("expectedGeneration"in payload)return ptys.killIfGeneration(key,requireString(payload,"expectedGeneration"));if(optionalBoolean(payload,"wait")===!0)return ptys.kill(key).then(()=>({accepted:!0,ended:!0}),(err)=>{return logDaemonError("pty-kill",err),{accepted:!0,ended:!1}});return ptys.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}case"pty.rename":{let payload=objectPayload(req.payload);return{renamed:ptys.rename(requireString(payload,"from"),requireString(payload,"to"))}}case"pty.detach":{let payload=objectPayload(req.payload);ptys.detach(requireString(payload,"key"),client,payload.parked===!0,typeof payload.parkedScreenBytes==="number"?payload.parkedScreenBytes:0)}return{};case"pty.watchStatus":client.watchProgramStatus=!0;for(let session of ptys.list())if(session.programStatusEvent)deps.writeFrame(client,{type:"event",name:"pty.programStatus",payload:session.programStatusEvent});return{supported:!0};case"pty.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),admissionToken:admissionToken(ptys),stats:ptys.stats(),...deps.version?{version:deps.version}:{}};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,payload.preamble===!0)}case"pty.warm":{let payload=objectPayload(req.payload);return ptys.warm(requireString(payload,"cwd"),typeof payload.shell==="string"?payload.shell:void 0,typeof payload.cols==="number"?payload.cols:void 0,typeof payload.rows==="number"?payload.rows:void 0),{}}case"spawn.detached":{if(process.platform!=="win32")throw Error("spawn.detached is Windows-only");let payload=objectPayload(req.payload),env=objectPayload(payload.env);return spawnDetachedDaemon(requireString(payload,"command"),Array.isArray(payload.args)?payload.args.filter((a)=>typeof a==="string"):[],withoutPtyJob(Object.fromEntries(Object.entries(env).filter((e)=>typeof e[1]==="string"))),requireString(payload,"logPath")),{}}case"daemon.stop":{let live=ptys.liveCount();if(live>0&&optionalBoolean(objectPayload(req.payload),"force")!==!0)throw Object.assign(Error(`pty host holds ${live} live session(s); daemon.stop needs force to end them`),{name:PTY_STOP_REFUSED});return deps.requestStop(),{}}default:throw Error(`unknown pty-host request: ${req.name}`)}}function admissionToken(ptys){return JSON.stringify(ptys.list().map((s)=>[s.key,s.generation,s.pid,s.alive]))}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.ROVE_PTY_MAX_LIFETIME_MS;if(raw===void 0)return null;let n=Number(raw);return Number.isFinite(n)&&n>0?n:null}function resolveIdleExitMs(){let raw=process.env.ROVE_PTY_IDLE_EXIT_MS;if(raw===void 0)return DEFAULT_IDLE_EXIT_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_IDLE_EXIT_MS}async function startPtyHostServer(options={}){migrateLegacyPtyHostData();let socketPath=options.socketPath??defaultPtyHostSocketPath(),pidPath=options.pidPath??defaultPtyHostPidPath(),freezeDir=options.freezeDir??defaultPtyFreezeDir(),idleExitMs=options.idleExitMs||resolveIdleExitMs(),orphanCheckMs=options.orphanCheckMs||DEFAULT_ORPHAN_CHECK_MS,maxLifetimeMs=options.maxLifetimeMs??resolveMaxLifetimeMs(),bootedAtMs=Date.now(),log=options.log??(()=>{}),clients=new Set,stopping=!1,idleTimer=null,cancelIdle=()=>{if(idleTimer)clearTimeout(idleTimer);idleTimer=null},armIdle=()=>{if(stopping)return;cancelIdle(),idleTimer=setTimeout(()=>{if(stopping||ptys.liveCount()>0)return;log("idle",`no live sessions for ${idleExitMs}ms \u2014 exiting`),stop()},idleExitMs)},orphaned=()=>{if(maxLifetimeMs!==null&&Date.now()-bootedAtMs>=maxLifetimeMs)return`exceeded its ${maxLifetimeMs}ms lifetime ceiling`;let owner;try{owner=readFileSync2(pidPath,"utf8").trim()}catch{return`pidfile ${pidPath} is gone`}let pid=Number.parseInt(owner,10);if(pid===process.pid)return null;return Number.isInteger(pid)?`pidfile ${pidPath} now names pid ${pid}`:`pidfile ${pidPath} is unreadable`},orphanTimer=setInterval(()=>{if(stopping)return;let reason=orphaned();if(!reason)return;log("orphan",`${reason} \u2014 exiting rather than outliving my owner`),stop()},orphanCheckMs);orphanTimer.unref?.();let ptys=new PtyHost({onProgramStatus:(event)=>{for(let client of clients)if(client.watchProgramStatus)writeFrame(client,{type:"event",name:"pty.programStatus",payload:event})},onSessionStart:cancelIdle,onSessionEnd:()=>{if(ptys.liveCount()===0)armIdle()},onSessionExit:(info)=>{try{recordPtyExit(info)}catch(err){log("pty",`exit record write failed for ${info.key}: ${err instanceof Error?err.message:String(err)}`)}},freeze:fileFreezeSink(freezeDir),driver:options.driver,log});ptys.restoreFrozen(loadFrozenSessions(freezeDir,Date.now(),(s)=>{let mib=(bytes)=>`${Math.round(bytes/1048576)}MB`,notes=[`restored ${s.restored} (${mib(s.bytesRead)})`];if(s.deferred>0)notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);if(s.expired>0)notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS/86400000}-day TTL`);if(s.unreadable>0)notes.push(`${s.unreadable} unreadable`);log("freeze",notes.join(", "))}));let pipeSocket=isWindowsPipePath(socketPath);if(await ensureOwnerOnlyStateDir(resolveDaemonHomeDir()),!pipeSocket)await mkdir(dirname(socketPath),{recursive:!0});await mkdir(dirname(pidPath),{recursive:!0});let server=createServer((socket)=>{let client={socket,writer:new ClientWriter(socket,{onOverflow:()=>{log("backpressure","disconnecting PTY client whose critical queue exceeded 8MiB"),socket.destroy()}})};clients.add(client);let receiver=new LineReceiver;socket.on("data",(chunk)=>{if(!receiver.push(chunk,(line)=>handleLine(client,line)))log("framing","disconnecting PTY client whose request exceeded 8MiB"),socket.destroy()}),socket.on("error",()=>{}),socket.on("close",()=>{clients.delete(client),ptys.detachClient(client)})}),api={socketPath,pidPath,async close(){if(stopping)return;stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown();for(let client of Array.from(clients))client.socket.destroy();if(await new Promise((resolve)=>server.close(()=>resolve())),!pipeSocket)await unlink(socketPath).catch(()=>{});await unlink(pidPath).catch(()=>{})}};async function stop(){await api.close().catch((err)=>logDaemonError("pty-host-shutdown",err)),options.onStop?.()}let verbDeps={ptys,writeFrame,requestStop:()=>{setTimeout(()=>void stop(),0).unref()},...options.version?{version:options.version}:{}};function handleLine(client,line){if(line.trim().length>0){let frame=null;try{frame=JSON.parse(line)}catch{writeFrame(client,{type:"response",id:"parse-error",error:{message:"malformed frame"}})}if(frame)if(frame.type!=="request")writeFrame(client,{type:"response",id:"parse-error",error:{message:"requests only"}});else{let req=frame,reply=(payload)=>writeFrame(client,{type:"response",id:req.id,name:req.name,payload}),fail=(err)=>writeFrame(client,{type:"response",id:req.id,name:req.name,error:{message:err instanceof Error?err.message:String(err),...err instanceof Error&&err.name!=="Error"?{name:err.name}:{}}});try{let payload=dispatchPtyRequest(req,client,verbDeps);if(payload instanceof Promise)payload.then(reply,fail);else reply(payload)}catch(err){fail(err)}}}}if(await listenOnUnixSocket(server,socketPath),await writeTextAtomic(pidPath,`${process.pid}
2
+ import{embeddedTerminalEnv}from"./chunk-7bgbansg.js";import{LAUNCH_PREFIX_FILE,freshSessionState}from"./chunk-4dt1gfb3.js";import{ClientWriter,LineReceiver,clearTransientStatuses,createOscSignals,objectPayload,optionalBoolean,requireString,scanOscSignals}from"./chunk-tq0h3vy6.js";import{writeTextAtomic}from"./chunk-5mhvjytn.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-w77s2df8.js";import{foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors,replayStart,scanTerminalModes,terminalModePreamble}from"./chunk-mqfvzdpr.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-rxqdw6s5.js";import{resolveSessionShell}from"./chunk-tn9gtf18.js";import{spawnDetachedDaemon,withoutPtyJob}from"./chunk-bcyex84w.js";import{recordPtyExit}from"./chunk-2w228s7t.js";import"./chunk-etfh8f4z.js";import{CURRENT_VERSION}from"./chunk-yn01fet6.js";import{DAEMON_PROTOCOL_VERSION,PTY_STOP_REFUSED,frameToLine}from"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import{listenOnUnixSocket}from"./chunk-br8r72bf.js";import{ensureOwnerOnlyStateDir}from"./chunk-yt15y085.js";import"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import{rotateLogIfNeeded}from"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,endpointPathFor,isWindowsPipePath,resolveDaemonHomeDir}from"./chunk-eqdbfgq5.js";import{preRenameStateDir}from"./chunk-f8gg8cqh.js";import{ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";function formatPtyHostLine(event,message,now=new Date){return`[${now.toISOString()}] pty-host [${event}]: ${message}`}import{readFileSync as readFileSync2}from"fs";import{mkdir,unlink}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync}from"fs";import{homedir}from"os";import{join}from"path";var PTY_HOST_DATA_ENTRIES=["pty-exits.json","pty-sessions"];function lstatIfExists(path){try{return lstatSync(path)}catch{return}}function migrateLegacyPtyHostData(homeDir=readRoveHomeDirEnv()??homedir()){let canonicalDir=join(homeDir,ROVE_STATE_DIR_BASENAME),legacyDir=preRenameStateDir(homeDir);if(canonicalDir===legacyDir)return[];let moved=[];for(let name of PTY_HOST_DATA_ENTRIES){let canonical=join(canonicalDir,name),legacy=join(legacyDir,name);try{if(existsSync(canonical))continue;let stat=lstatIfExists(legacy);if(!stat||stat.isSymbolicLink())continue;mkdirSync(canonicalDir,{recursive:!0}),renameSync(legacy,canonical),moved.push(name)}catch{}}return moved}import{spawn}from"child_process";import{randomUUID}from"crypto";import{readFileSync}from"fs";import path from"path";var TERMINAL_NAME="xterm-256color";function bunTerminalDriver(spawn){let spawnTerminal=spawn??((argv,options)=>Bun.spawn(argv,options));return(request)=>{let proc=spawnTerminal([...request.argv],{cwd:request.cwd,env:request.env,terminal:{cols:request.cols,rows:request.rows,name:TERMINAL_NAME,data:(_terminal,data)=>request.onData(data)}});return{pid:proc.pid,exited:proc.exited.then(()=>({code:proc.exitCode??null,signal:proc.signalCode??null}),()=>({code:null,signal:null})),write:(data)=>proc.terminal?.write(data),resize:(cols,rows)=>proc.terminal?.resize(cols,rows),close:()=>proc.terminal?.close(),kill:(signal)=>proc.kill(signal)}}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,programStatusEvent:s.programStatusEvent,programStatus:s.oscSignals?.records.get(""),contexts:s.oscSignals?.contexts,totalBytes:s.totalBytes,parked:s.parked,parkedScreenBytes:s.parkedScreenBytes,exit:s.exit,restored:s.restored||void 0}}function describeExit(exit){if(exit?.signal)return` (signal ${exit.signal})`;if(exit&&exit.code!==null)return` (code ${exit.code})`;return" (cause unknown)"}function ringTail(chunks,bytes,maxBytes){let skip=Math.max(0,bytes-maxBytes),seen=0,parts=[];for(let chunk of chunks){if(seen+chunk.byteLength>skip)parts.push(seen>=skip?chunk:chunk.subarray(skip-seen));seen+=chunk.byteLength}return Buffer.concat(parts).toString("utf8")}function hostStats(sessions,perSessionCap,parkRestoreDeltas,parkRestoreFallbacks){let ringBytes=0,count=0,parkedSessions=0,parkedScreenBytes=0;for(let session of sessions)if(count++,ringBytes+=session.bytes,session.parked)parkedSessions++,parkedScreenBytes+=session.parkedScreenBytes;return{ringBytes,ringCapacityBytes:count*perSessionCap,parkedSessions,parkedScreenBytes,parkRestoreDeltas,parkRestoreFallbacks}}var OSC_TITLE_RE=/\x1b\][02];([^\x07\x1b]*)(?:\x07|\x1b\\)/g,TITLE_CARRY_CAP=1024;function titleCarryFrom(rest){let osc=rest.lastIndexOf("\x1B]");if(osc!==-1)return rest.slice(osc,osc+TITLE_CARRY_CAP);return rest.endsWith("\x1B")?"\x1B":""}function foldOscTitle(prevCarry,chunkText){let text=prevCarry+chunkText,title=null,end=0;OSC_TITLE_RE.lastIndex=0;for(let match=OSC_TITLE_RE.exec(text);match;match=OSC_TITLE_RE.exec(text))title=match[1]??"",end=match.index+match[0].length;return{title,carry:titleCarryFrom(text.slice(end))}}function scanOscTitle(session,buf){let{title,carry}=foldOscTitle(session.titleCarry,session.titleDecoder.write(buf));if(title!==null)session.title=title;session.titleCarry=carry}function peekRing(session,sinceOffset){if(!session)return{exists:!1,alive:!1,pid:null,offset:0,data:"",sinceValid:!1,exit:null};let windowStart=session.totalBytes-session.bytes,buf=Buffer.concat(session.chunks),sinceValid=!1;if(sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes)buf=buf.subarray(sinceOffset-windowStart),sinceValid=!0;return{exists:!0,alive:session.alive,pid:session.proc?.pid??null,offset:session.totalBytes,data:buf.toString("base64"),sinceValid,exit:session.exit??null}}async function settledWithin(exited,ms){let timer,settled=await Promise.race([exited.then(()=>!0,()=>!0),new Promise((resolve)=>{timer=setTimeout(()=>resolve(!1),ms)})]);if(timer)clearTimeout(timer);return settled}function signalProcessGroup(pid,signal,fallback,platform=process.platform,onSignal){if(platform!=="win32"&&pid>1)try{process.kill(-pid,signal),onSignal?.(`sent ${signal} to process group -${pid}`);return}catch{}try{fallback(),onSignal?.(`sent ${signal} to pid ${pid} (per-process fallback)`)}catch{}}var TERMINATION_GRACE_MS=500;async function terminatePtyChild(proc,onSettled,onSignal){if(proc.endTree){onSignal?.(await proc.endTree()),signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS),onSettled();return}if(signalProcessGroup(proc.pid,"SIGTERM",()=>proc.kill("SIGTERM"),process.platform,onSignal),!await settledWithin(proc.exited,TERMINATION_GRACE_MS))signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS);onSettled()}class PtyChildController{deps;constructor(deps){this.deps=deps}spawn(key,spec,spare=!1){let argv=spec.command&&spec.command.length>0?[...spec.command]:[spec.shell??resolveSessionShell()],session=freshSessionState(key,spec,argv);if(this.startChild(session),session.alive)this.deps.log?.("pty",`spawned ${argv[0]} for ${key} (pid ${session.proc?.pid})`),this.deps.onSessionStart?.(spare);return session}startChild(session){session.generation=randomUUID(),session.oscSignals=void 0,session.programStatusEvent=void 0,this.reportStatus(session,null);try{let launch=launchWrapper(session.cwd,session.generation);session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...launch.prefix,...session.command],cwd:session.cwd,env:embeddedTerminalEnv(process.env,{TERM:"xterm-256color",COLUMNS:String(session.cols),LINES:String(session.rows),BASH_SILENCE_DEPRECATION_WARNING:"1",ROVE_TERMINAL_PTY:"1",...process.env.SHELL?.trim()?{}:{SHELL:resolveSessionShell()}}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0;let reap=launch.reap;session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session)).then(()=>{if(reap.length>0)spawn(reap[0],reap.slice(1),{detached:!0,stdio:"ignore"}).unref()})}catch(err){session.alive=!1,this.deps.log?.("pty",`spawn failed for ${session.key}: ${err instanceof Error?err.message:String(err)}`)}}async endChild(session){if(!session.alive)return;let proc=session.proc;if(!proc){this.markExited(session);return}await terminatePtyChild(proc,()=>this.markExited(session),(line)=>this.deps.log?.("pty-signal",`${session.key}: ${line}`))}markExited(session,exit){if(!session.alive)return;if(session.alive=!1,session.oscSignals){let before=session.oscSignals.records.get("");if(clearTransientStatuses(session.oscSignals),before!==session.oscSignals.records.get(""))this.reportStatus(session,null)}let sessionExit={code:exit?.code??null,signal:exit?.signal??null,at:new Date().toISOString()};session.exit=sessionExit;try{session.proc?.close()}catch{}this.deps.onExit?.(session,sessionExit)}reportStatus(session,status){let event={key:session.key,generation:session.generation,revision:(session.programStatusEvent?.revision??0)+1,at:Date.now(),status};session.programStatusEvent=event,this.deps.onProgramStatus?.(event)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),text=buf.toString("latin1");session.oscSignals??=createOscSignals();let queries=scanOscSignals(session.oscSignals,buf,Date.now(),(status)=>this.reportStatus(session,status)),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,text);session.colorQueryCarry=colorQueries.carry;let replies=colorQueries.slots.map((slot)=>formatDefaultColorReply(slot,session.defaultColors));for(let i=0;i<Math.min(queries,16);i++)replies.push("\x1B]7501;?\x1B\\");let modeReplies=scanTerminalModes(session.modes,text);if(session.emulatorSinks.size===0)replies.push(...modeReplies);if(replies.length>0)try{session.proc?.write(replies.join(""))}catch{}scanOscTitle(session,buf),session.kitty.push(buf),session.chunks.push(buf),session.bytes+=buf.byteLength,session.totalBytes+=buf.byteLength;while(session.bytes>this.deps.scrollbackCap&&session.chunks.length>1){let dropped=session.chunks.shift();if(!dropped)break;session.bytes-=dropped.byteLength,scanTerminalModes(session.ringModes,dropped.toString("latin1"))}this.deps.onOutput?.(session,buf)}}function launchWrapper(cwd,id){let raw;try{raw=readFileSync(path.join(cwd,LAUNCH_PREFIX_FILE),"utf8")}catch{return{prefix:[],reap:[]}}let file=JSON.parse(raw),argv=(field,name)=>{if(field===void 0&&name==="reap")return[];if(!Array.isArray(field)||!field.every((a)=>typeof a==="string"))throw Error(`${LAUNCH_PREFIX_FILE} in ${cwd}: "${name}" is not a string array`);return field.map((a)=>a.replaceAll("{launch}",id))};return{prefix:argv(file.prefix,"prefix"),reap:argv(file.reap,"reap")}}function shouldFreeze(session,now){let appended=session.totalBytes-(session.frozenTotalBytes??0);if(appended<=0)return!1;let since=now-session.lastFreezeAtMs;if(since<5000)return!1;return appended>=65536||since>=60000}class WarmSpare{deps;spare=null;constructor(deps){this.deps=deps}warm(cwd,shell,cols=80,rows=24){let argv0=shell??resolveSessionShell();if(this.spare?.alive&&this.spare.cwd===cwd&&this.spare.command[0]===argv0)return;let old=this.spare;if(this.spare=null,old)this.deps.endChild(old);let session=this.deps.spawn("::spare",{cwd,command:[argv0],cols,rows},!0);this.spare=session.alive?session:null}adopt(key,spec){let spare=this.spare;if(!spare?.alive||spare.cwd!==spec.cwd)return null;let want=spec.command&&spec.command.length>0?spec.command:[spec.shell??resolveSessionShell()];if(want.length!==1||want[0]!==spare.command[0])return null;this.spare=null,spare.key=key,spare.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??spare.defaultColors;let cols=spec.cols??spare.cols,rows=spec.rows??spare.rows;if(spare.cols!==cols||spare.rows!==rows){spare.cols=cols,spare.rows=rows;try{spare.proc?.resize(cols,rows)}catch{return this.deps.markExited(spare),null}}return this.deps.log?.("pty",`adopted warm shell for ${key} (pid ${spare.proc?.pid})`),this.deps.onSessionStart?.(),this.warm(spec.cwd,spare.command[0],cols,rows),spare}async end(){let spare=this.spare;if(this.spare=null,spare)await this.deps.endChild(spare)}}var LOGGED_WRITE_BYTES=1024,DEFAULT_SCROLLBACK_CAP=524288,EXIT_TAIL_BYTES=16384;function fullReplay(session,ring){return Buffer.concat([Buffer.from(terminalModePreamble(session.ringModes.modes),"latin1"),session.kitty.replay(),ring.subarray(replayStart(session.ringModes,ring))])}class PtyHost{sessions=new Map;opts;scrollbackCap;shuttingDown=!1;parkRestoreDeltas=0;parkRestoreFallbacks=0;childController;warmSpare;constructor(opts={}){this.opts=opts,this.scrollbackCap=opts.scrollbackCap??DEFAULT_SCROLLBACK_CAP,this.childController=new PtyChildController({driver:opts.driver,onProgramStatus:(event)=>this.opts.onProgramStatus?.(event),scrollbackCap:this.scrollbackCap,onSessionStart:(spare)=>{if(!spare)this.opts.onSessionStart?.()},onOutput:(session,data)=>{if(session.sinks.size===0){this.maybeFreeze(session);return}let frame={type:"event",name:"pty.data",payload:{key:session.key,data:data.toString("base64"),offset:session.totalBytes}};for(let sink of session.sinks.values())sink(frame);this.maybeFreeze(session)},onExit:(session,exit)=>{let frame={type:"event",name:"pty.exit",payload:{key:session.key,pid:session.proc?.pid??null,...exit}};for(let sink of session.sinks.values())sink(frame);if(this.opts.log?.("pty",`session ${session.key} exited${describeExit(exit)}`),this.maybeFreeze(session,!0),!session.closedByRequest)try{this.opts.onSessionExit?.({key:session.key,pid:session.proc?.pid??null,exit,tail:ringTail(session.chunks,session.bytes,EXIT_TAIL_BYTES)})}catch{}this.opts.onSessionEnd?.()},log:(event,message)=>this.opts.log?.(event,message)}),this.warmSpare=new WarmSpare({spawn:(key,spec,spare)=>this.childController.spawn(key,spec,spare),endChild:(session)=>this.childController.endChild(session),markExited:(session)=>this.childController.markExited(session),log:(event,message)=>this.opts.log?.(event,message),onSessionStart:()=>this.opts.onSessionStart?.()})}open(key,spec,token,sink,sinceOffset,sincePid,answersQueries=!1){let session=this.sessions.get(key),created=!1,respawned=!1;if(!session)created=!0,session=this.warmSpare.adopt(key,spec)??this.childController.spawn(key,spec),this.sessions.set(key,session);else if(!session.alive&&session.restored)this.respawn(session,spec),respawned=session.alive;else if(session.alive&&spec.cols!==void 0&&spec.rows!==void 0&&(session.cols!==spec.cols||session.rows!==spec.rows))this.resize(key,spec.cols,spec.rows);let defaultColors=parseTerminalDefaultColors(spec.defaultColors);if(defaultColors)session.defaultColors=defaultColors;if(session.sinks.set(token,sink),answersQueries)session.emulatorSinks.add(token);else session.emulatorSinks.delete(token);session.parked=!1,session.parkedScreenBytes=0;let windowStart=session.totalBytes-session.bytes,replay=Buffer.concat(session.chunks),sinceValid=!1;if(!created&&sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes&&sincePid!==void 0&&sincePid===session.proc?.pid)replay=replay.subarray(sinceOffset-windowStart),sinceValid=!0;if(sinceOffset!==void 0&&sincePid!==void 0)if(sinceValid)this.parkRestoreDeltas++;else this.parkRestoreFallbacks++;if(!sinceValid)replay=fullReplay(session,replay);return{replay:replay.toString("base64"),alive:session.alive,pid:session.proc?.pid??null,created,respawned,offset:session.totalBytes,sinceValid}}warm(cwd,shell,cols=80,rows=24){this.warmSpare.warm(cwd,shell,cols,rows)}write(key,data){let session=this.sessions.get(key);if(!session?.alive||data.length===0)return;if(data.length>=LOGGED_WRITE_BYTES)this.opts.log?.("pty",`wrote ${data.length} bytes to ${key}`);try{session.proc?.write(data)}catch(error){this.opts.log?.("pty",`write failed on ${key} (${data.length} bytes): ${String(error)}`)}}resize(key,cols,rows){let session=this.sessions.get(key);if(!session?.alive)return;session.cols=cols,session.rows=rows;try{session.proc?.resize(cols,rows)}catch{}}killIfGeneration(key,expectedGeneration){let session=this.sessions.get(key);if(!session)return{accepted:!1,reason:"missing-session"};if(session.generation!==expectedGeneration)return{accepted:!1,reason:"generation-mismatch"};return this.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}kill(key){let session=this.sessions.get(key);if(!session)return Promise.resolve();return this.sessions.delete(key),session.closedByRequest=!0,this.opts.freeze?.drop(key),this.childController.endChild(session)}rename(from,to){let session=this.sessions.get(from);if(!session||from===to||this.sessions.has(to))return!1;if(this.sessions.delete(from),session.key=to,session.programStatusEvent){let previous=session.programStatusEvent;this.opts.onProgramStatus?.({...previous,revision:previous.revision+1,at:Date.now(),status:null}),session.programStatusEvent={...previous,key:to,revision:previous.revision+1,at:Date.now()},this.opts.onProgramStatus?.(session.programStatusEvent)}return this.sessions.set(to,session),this.opts.freeze?.drop(from),this.maybeFreeze(session,!0),this.opts.log?.("pty",`renamed session ${from} \u2192 ${to}`),!0}detach(key,token,parked=!1,parkedScreenBytes=0){let session=this.sessions.get(key);if(!session)return;session.sinks.delete(token),session.emulatorSinks.delete(token),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(session.emulatorSinks.delete(token),!session.sinks.delete(token))continue;this.applyParkedOnDetach(session)}}applyParkedOnDetach(session,parked=!1,parkedScreenBytes=0){if(session.sinks.size!==0)return;session.parked=parked,session.parkedScreenBytes=parked?Math.max(0,parkedScreenBytes):0}list(){return Array.from(this.sessions.values(),(s)=>sessionInfo(s))}peek(key,sinceOffset,preamble=!1){let session=this.sessions.get(key),peek=peekRing(session,sinceOffset);if(!preamble||!session||sinceOffset!==void 0)return peek;return{...peek,data:fullReplay(session,Buffer.from(peek.data,"base64")).toString("base64")}}stats(){return hostStats(this.sessions.values(),this.scrollbackCap,this.parkRestoreDeltas,this.parkRestoreFallbacks)}async killAll(){let sessions=Array.from(this.sessions.keys(),(key)=>this.kill(key));sessions.push(this.warmSpare.end()),await Promise.all(sessions)}async shutdown(){this.flushFrozen(),this.shuttingDown=!0;let endings=Array.from(this.sessions.values(),(session)=>this.childController.endChild(session));endings.push(this.warmSpare.end()),await Promise.all(endings)}flushFrozen(){for(let session of this.sessions.values())this.maybeFreeze(session,!0)}restoreFrozen(records){let restoredCount=0;for(let record of records){if(this.sessions.has(record.key))continue;let session=thawSession(record,this.scrollbackCap);if(!session)continue;this.sessions.set(record.key,session),restoredCount++}if(restoredCount>0)this.opts.log?.("pty",`restored ${restoredCount} frozen session(s) from disk`);return restoredCount}respawn(session,spec){if(session.restored=!1,session.exit=null,spec.command&&spec.command.length>0)session.command=[...spec.command];if(session.cols=spec.cols??session.cols,session.rows=spec.rows??session.rows,session.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??session.defaultColors,this.childController.startChild(session),!session.alive)return;this.opts.log?.("pty",`respawned restored session ${session.key} (pid ${session.proc?.pid})`),this.opts.onSessionStart?.()}maybeFreeze(session,force=!1){let freeze=this.opts.freeze;if(!freeze||session.key.startsWith("::"))return;if(session.closedByRequest||this.shuttingDown)return;let now=Date.now();if(!force&&!shouldFreeze(session,now))return;session.lastFreezeAtMs=now,session.frozenTotalBytes=session.totalBytes,freeze.save(freezeSession(session))}liveCount(){let n=0;for(let session of this.sessions.values())if(session.alive)n++;return n}}function dispatchPtyRequest(req,client,deps){let{ptys}=deps;switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.openChecked":case"pty.open":{let payload=objectPayload(req.payload);if(req.name==="pty.openChecked"&&requireString(payload,"admissionToken")!==admissionToken(ptys))return{kind:"changed"};let open=ptys.open(requireString(payload,"key"),{cwd:requireString(payload,"cwd"),command:Array.isArray(payload.command)?payload.command.filter((c)=>typeof c==="string"):void 0,shell:typeof payload.shell==="string"?payload.shell:void 0,cols:typeof payload.cols==="number"?payload.cols:void 0,rows:typeof payload.rows==="number"?payload.rows:void 0,defaultColors:parseTerminalDefaultColors(payload.defaultColors)??void 0},client,(frame)=>deps.writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0,payload.answersQueries===!0);return req.name==="pty.openChecked"?{kind:"opened",open}:open}case"pty.write":{let payload=objectPayload(req.payload);return ptys.write(requireString(payload,"key"),typeof payload.data==="string"?payload.data:""),{}}case"pty.resize":{let payload=objectPayload(req.payload);return ptys.resize(requireString(payload,"key"),typeof payload.cols==="number"?payload.cols:80,typeof payload.rows==="number"?payload.rows:24),{}}case"pty.kill":{let payload=objectPayload(req.payload),key=requireString(payload,"key");if("expectedGeneration"in payload)return ptys.killIfGeneration(key,requireString(payload,"expectedGeneration"));if(optionalBoolean(payload,"wait")===!0)return ptys.kill(key).then(()=>({accepted:!0,ended:!0}),(err)=>{return logDaemonError("pty-kill",err),{accepted:!0,ended:!1}});return ptys.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}case"pty.rename":{let payload=objectPayload(req.payload);return{renamed:ptys.rename(requireString(payload,"from"),requireString(payload,"to"))}}case"pty.detach":{let payload=objectPayload(req.payload);ptys.detach(requireString(payload,"key"),client,payload.parked===!0,typeof payload.parkedScreenBytes==="number"?payload.parkedScreenBytes:0)}return{};case"pty.watchStatus":client.watchProgramStatus=!0;for(let session of ptys.list())if(session.programStatusEvent)deps.writeFrame(client,{type:"event",name:"pty.programStatus",payload:session.programStatusEvent});return{supported:!0};case"pty.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),admissionToken:admissionToken(ptys),stats:ptys.stats(),...deps.version?{version:deps.version}:{}};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,payload.preamble===!0)}case"pty.warm":{let payload=objectPayload(req.payload);return ptys.warm(requireString(payload,"cwd"),typeof payload.shell==="string"?payload.shell:void 0,typeof payload.cols==="number"?payload.cols:void 0,typeof payload.rows==="number"?payload.rows:void 0),{}}case"spawn.detached":{if(process.platform!=="win32")throw Error("spawn.detached is Windows-only");let payload=objectPayload(req.payload),env=objectPayload(payload.env);return spawnDetachedDaemon(requireString(payload,"command"),Array.isArray(payload.args)?payload.args.filter((a)=>typeof a==="string"):[],withoutPtyJob(Object.fromEntries(Object.entries(env).filter((e)=>typeof e[1]==="string"))),requireString(payload,"logPath")),{}}case"daemon.stop":{let live=ptys.liveCount();if(live>0&&optionalBoolean(objectPayload(req.payload),"force")!==!0)throw Object.assign(Error(`pty host holds ${live} live session(s); daemon.stop needs force to end them`),{name:PTY_STOP_REFUSED});return deps.requestStop(),{}}default:throw Error(`unknown pty-host request: ${req.name}`)}}function admissionToken(ptys){return JSON.stringify(ptys.list().map((s)=>[s.key,s.generation,s.pid,s.alive]))}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.ROVE_PTY_MAX_LIFETIME_MS;if(raw===void 0)return null;let n=Number(raw);return Number.isFinite(n)&&n>0?n:null}function resolveIdleExitMs(){let raw=process.env.ROVE_PTY_IDLE_EXIT_MS;if(raw===void 0)return DEFAULT_IDLE_EXIT_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_IDLE_EXIT_MS}async function startPtyHostServer(options={}){migrateLegacyPtyHostData();let socketPath=options.socketPath??defaultPtyHostSocketPath(),pidPath=options.pidPath??defaultPtyHostPidPath(),freezeDir=options.freezeDir??defaultPtyFreezeDir(),idleExitMs=options.idleExitMs||resolveIdleExitMs(),orphanCheckMs=options.orphanCheckMs||DEFAULT_ORPHAN_CHECK_MS,maxLifetimeMs=options.maxLifetimeMs??resolveMaxLifetimeMs(),bootedAtMs=Date.now(),log=options.log??(()=>{}),clients=new Set,stopping=!1,idleTimer=null,cancelIdle=()=>{if(idleTimer)clearTimeout(idleTimer);idleTimer=null},armIdle=()=>{if(stopping)return;cancelIdle(),idleTimer=setTimeout(()=>{if(stopping||ptys.liveCount()>0)return;log("idle",`no live sessions for ${idleExitMs}ms \u2014 exiting`),stop()},idleExitMs)},orphaned=()=>{if(maxLifetimeMs!==null&&Date.now()-bootedAtMs>=maxLifetimeMs)return`exceeded its ${maxLifetimeMs}ms lifetime ceiling`;let owner;try{owner=readFileSync2(pidPath,"utf8").trim()}catch{return`pidfile ${pidPath} is gone`}let pid=Number.parseInt(owner,10);if(pid===process.pid)return null;return Number.isInteger(pid)?`pidfile ${pidPath} now names pid ${pid}`:`pidfile ${pidPath} is unreadable`},orphanTimer=setInterval(()=>{if(stopping)return;let reason=orphaned();if(!reason)return;log("orphan",`${reason} \u2014 exiting rather than outliving my owner`),stop()},orphanCheckMs);orphanTimer.unref?.();let ptys=new PtyHost({onProgramStatus:(event)=>{for(let client of clients)if(client.watchProgramStatus)writeFrame(client,{type:"event",name:"pty.programStatus",payload:event})},onSessionStart:cancelIdle,onSessionEnd:()=>{if(ptys.liveCount()===0)armIdle()},onSessionExit:(info)=>{try{recordPtyExit(info)}catch(err){log("pty",`exit record write failed for ${info.key}: ${err instanceof Error?err.message:String(err)}`)}},freeze:fileFreezeSink(freezeDir),driver:options.driver,log});ptys.restoreFrozen(loadFrozenSessions(freezeDir,Date.now(),(s)=>{let mib=(bytes)=>`${Math.round(bytes/1048576)}MB`,notes=[`restored ${s.restored} (${mib(s.bytesRead)})`];if(s.deferred>0)notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);if(s.expired>0)notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS/86400000}-day TTL`);if(s.unreadable>0)notes.push(`${s.unreadable} unreadable`);log("freeze",notes.join(", "))}));let pipeSocket=isWindowsPipePath(socketPath);if(await ensureOwnerOnlyStateDir(resolveDaemonHomeDir()),!pipeSocket)await mkdir(dirname(socketPath),{recursive:!0});await mkdir(dirname(pidPath),{recursive:!0});let server=createServer((socket)=>{let client={socket,writer:new ClientWriter(socket,{onOverflow:()=>{log("backpressure","disconnecting PTY client whose critical queue exceeded 8MiB"),socket.destroy()}})};clients.add(client);let receiver=new LineReceiver;socket.on("data",(chunk)=>{if(!receiver.push(chunk,(line)=>handleLine(client,line)))log("framing","disconnecting PTY client whose request exceeded 8MiB"),socket.destroy()}),socket.on("error",()=>{}),socket.on("close",()=>{clients.delete(client),ptys.detachClient(client)})}),api={socketPath,pidPath,async close(){if(stopping)return;stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown();for(let client of Array.from(clients))client.socket.destroy();if(await new Promise((resolve)=>server.close(()=>resolve())),!pipeSocket)await unlink(socketPath).catch(()=>{});await unlink(pidPath).catch(()=>{})}};async function stop(){await api.close().catch((err)=>logDaemonError("pty-host-shutdown",err)),options.onStop?.()}let verbDeps={ptys,writeFrame,requestStop:()=>{setTimeout(()=>void stop(),0).unref()},...options.version?{version:options.version}:{}};function handleLine(client,line){if(line.trim().length>0){let frame=null;try{frame=JSON.parse(line)}catch{writeFrame(client,{type:"response",id:"parse-error",error:{message:"malformed frame"}})}if(frame)if(frame.type!=="request")writeFrame(client,{type:"response",id:"parse-error",error:{message:"requests only"}});else{let req=frame,reply=(payload)=>writeFrame(client,{type:"response",id:req.id,name:req.name,payload}),fail=(err)=>writeFrame(client,{type:"response",id:req.id,name:req.name,error:{message:err instanceof Error?err.message:String(err),...err instanceof Error&&err.name!=="Error"?{name:err.name}:{}}});try{let payload=dispatchPtyRequest(req,client,verbDeps);if(payload instanceof Promise)payload.then(reply,fail);else reply(payload)}catch(err){fail(err)}}}}if(await listenOnUnixSocket(server,socketPath),await writeTextAtomic(pidPath,`${process.pid}
3
3
  `),!pipeSocket)await writeTextAtomic(endpointPathFor(pidPath),`${socketPath}
4
4
  `);return armIdle(),log("boot",`pty host listening on ${socketPath}`),api}function writeFrame(client,frame){client.writer.write(frameToLine(frame))}async function runPtyHostSubcommand(_argv){rotateLogIfNeeded(defaultPtyHostLogPath()),installDaemonCrashHandlers();let server=await startPtyHostServer({log:(event,message)=>console.log(formatPtyHostLine(event,message)),version:CURRENT_VERSION,onStop:()=>process.exit(0)});console.log(formatPtyHostLine("listen",`v${CURRENT_VERSION} listening on ${server.socketPath}`));let shutdown=async(signal)=>{console.log(formatPtyHostLine("signal",`${signal} received \u2014 closing host, frozen sessions kept`)),await server.close(),process.exit(0)};process.once("SIGINT",()=>void shutdown("SIGINT")),process.once("SIGTERM",()=>void shutdown("SIGTERM"))}export{runPtyHostSubcommand};
@@ -1,4 +1,4 @@
1
1
  // @bun
2
2
  import{expandTilde}from"./chunk-2r1fgng9.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import{pathSyntax}from"./chunk-pn5ygqn6.js";import{__require}from"./chunk-91sykzqq.js";import{statSync}from"fs";import{resolve}from"path";function isPathLikeArg(arg){return arg==="."||arg===".."||arg.startsWith("./")||arg.startsWith("../")||arg.startsWith(".\\")||arg.startsWith("..\\")||pathSyntax(arg).isAbsolute(arg)||arg.startsWith("/")||arg==="~"||arg.startsWith("~/")||arg.startsWith("~\\")}async function projectRootFor(dir){let{isGitRepo,resolveRepoRoot}=await import("./chunk-hv79ys32.js"),{projectRejection}=await import("./chunk-qnpkhvrn.js"),top=resolveRepoRoot(dir);if(top!==dir)return null;return projectRejection(top,isGitRepo,"explicit")?null:top}async function runOpenDirectory(arg){let dir=resolve(process.cwd(),expandTilde(arg)),isDir=!1;try{isDir=statSync(dir).isDirectory()}catch{isDir=!1}if(!isDir)process.stderr.write(`${ROVE_PRODUCT_NAME}: "${arg}" is not a directory (resolved to ${dir}).
3
- `),process.exit(1);let projectRoot=await projectRootFor(dir),{withDaemonOrLocal}=await import("./chunk-mqvkd2g1.js");await withDaemonOrLocal({daemon:async(client)=>{let taskId;if(projectRoot)taskId=(await client.request("task.ensureMain",{repo:projectRoot})).task.id;else taskId=(await client.request("task.openDir",{dir})).taskId;await client.request("task.setActive",{taskId})},local:async(orch)=>{let task=projectRoot?await orch.ensureMainTask(projectRoot):await orch.openDirectoryTask({dir}),{writeLastActiveTaskId}=await import("./chunk-y8b2p44q.js");writeLastActiveTaskId(String(task.id))}});let{publishRoveTerminalTitle}=await import("./chunk-g8wrdp7n.js");publishRoveTerminalTitle();let{launchTui}=await import("./chunk-azt0c2b5.js");await launchTui()}
3
+ `),process.exit(1);let projectRoot=await projectRootFor(dir),{withDaemonOrLocal}=await import("./chunk-xqvyzv62.js");await withDaemonOrLocal({daemon:async(client)=>{let taskId;if(projectRoot)taskId=(await client.request("task.ensureMain",{repo:projectRoot})).task.id;else taskId=(await client.request("task.openDir",{dir})).taskId;await client.request("task.setActive",{taskId})},local:async(orch)=>{let task=projectRoot?await orch.ensureMainTask(projectRoot):await orch.openDirectoryTask({dir}),{writeLastActiveTaskId}=await import("./chunk-y8b2p44q.js");writeLastActiveTaskId(String(task.id))}});let{publishRoveTerminalTitle}=await import("./chunk-g8wrdp7n.js");publishRoveTerminalTitle();let{launchTui}=await import("./chunk-xekk4k54.js");await launchTui()}
4
4
  export{isPathLikeArg,runOpenDirectory};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{findVerb}from"./chunk-txvjg1g9.js";import{VERB_GROUP_IDS}from"./chunk-r5j8fycq.js";import{loadStateFile,updateStateFile}from"./chunk-32j6y5d1.js";var INBOUND_KEY="machineInbound",INBOUND_CLASSES=[...VERB_GROUP_IDS,"land","credentials"],LAND_VERBS=new Set(["land","publish"]),CREDENTIAL_VERBS={"github-login":!0,"github-logout":!0,"github-sync":!0,"github-apply":!0};function inboundClassOf(verb){if(LAND_VERBS.has(verb))return"land";if(Object.hasOwn(CREDENTIAL_VERBS,verb))return"credentials";return findVerb(verb)?.group??null}function deniedClasses(state=loadStateFile()){let raw=state[INBOUND_KEY],deny=raw&&typeof raw==="object"?raw.deny:void 0;return Array.isArray(deny)?deny.filter((c)=>typeof c==="string"):[]}function inboundRefusal(verb,state){let cls=inboundClassOf(verb);return cls&&deniedClasses(state).includes(cls)?cls:null}function setInbound(cls,allow){let next=[];return updateStateFile((state)=>{let current=new Set(deniedClasses(state));if(allow)current.delete(cls);else current.add(cls);return next=[...current].sort(),state[INBOUND_KEY]={deny:next},!0}),next}
2
+ import{findVerb}from"./chunk-btxfcc77.js";import{VERB_GROUP_IDS}from"./chunk-r5j8fycq.js";import{loadStateFile,updateStateFile}from"./chunk-32j6y5d1.js";var INBOUND_KEY="machineInbound",INBOUND_CLASSES=[...VERB_GROUP_IDS,"land","credentials"],LAND_VERBS=new Set(["land","publish"]),CREDENTIAL_VERBS={"github-login":!0,"github-logout":!0,"github-sync":!0,"github-apply":!0};function inboundClassOf(verb){if(LAND_VERBS.has(verb))return"land";if(Object.hasOwn(CREDENTIAL_VERBS,verb))return"credentials";return findVerb(verb)?.group??null}function deniedClasses(state=loadStateFile()){let raw=state[INBOUND_KEY],deny=raw&&typeof raw==="object"?raw.deny:void 0;return Array.isArray(deny)?deny.filter((c)=>typeof c==="string"):[]}function inboundRefusal(verb,state){let cls=inboundClassOf(verb);return cls&&deniedClasses(state).includes(cls)?cls:null}function setInbound(cls,allow){let next=[];return updateStateFile((state)=>{let current=new Set(deniedClasses(state));if(allow)current.delete(cls);else current.add(cls);return next=[...current].sort(),state[INBOUND_KEY]={deny:next},!0}),next}
3
3
  export{INBOUND_KEY,INBOUND_CLASSES,inboundClassOf,deniedClasses,inboundRefusal,setInbound};
@@ -1,9 +1,9 @@
1
1
  // @bun
2
- import{deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,deriveTitleFromSession,deriveTitleFromSessionId,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,tearDownTaskSessionAdapter}from"./chunk-8hernv9y.js";import{buildCIPromptForWorktree}from"./chunk-vkz6kkmm.js";import{Orchestrator}from"./chunk-bv050ssb.js";import{GH_PR_VIEW_FIELDS,classifyGhFailure,mapGhPrView,nextPrPoll,samePrStatus}from"./chunk-1wwqf6kx.js";import"./chunk-c1dz3qg3.js";import{resolvePluginBinPath}from"./chunk-b0ssvpht.js";import{GitWorktreeManager,parseDirtyPaths}from"./chunk-3x5g06mw.js";import{startChatChannels}from"./chunk-4drm07mp.js";import{auditDeletionBranchKept,auditDeletionResidue,auditDeletionSalvaged,auditWorktreeResidue,auditWorktreeSalvaged,parseAheadBehind,startDaemonServer}from"./chunk-nrx8pf9p.js";import"./chunk-1g6vhgfe.js";import"./chunk-a4hsqj1b.js";import"./chunk-6hcyvg0m.js";import{refreshOutdatedSkills}from"./chunk-y7mjhjby.js";import"./chunk-4dt1gfb3.js";import"./chunk-tq0h3vy6.js";import"./chunk-cpgnm1xr.js";import"./chunk-r3s2t9af.js";import"./chunk-6xr1prk6.js";import{preferredReleaseChannel,updateDelayHours}from"./chunk-4z1a65bz.js";import"./chunk-xmwp6je4.js";import{cancelAllLogins}from"./chunk-pm91e38v.js";import{PLACEHOLDER_TASK_TITLE}from"./chunk-2xsxcdp6.js";import{affectsActivityState,isEngineActivityKind}from"./chunk-17e2tgyg.js";import"./chunk-1vxtd8rh.js";import"./chunk-q8ffd1pc.js";import"./chunk-4hestsjp.js";import"./chunk-qgrg9a5n.js";import"./chunk-2bgmby1d.js";import"./chunk-n0rdn2fn.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import"./chunk-vp29jgbt.js";import"./chunk-gq36nzg8.js";import{RELAY_PREAMBLE}from"./chunk-sq6zj3fb.js";import{TaskIndexStore}from"./chunk-7kgcy89w.js";import"./chunk-qkehg2c1.js";import"./chunk-nv8eyjep.js";import"./chunk-z43e08kw.js";import"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import"./chunk-f7egph8g.js";import{installDaemonCrashHandlers,logDaemonError,logDaemonInfo}from"./chunk-rxqdw6s5.js";import"./chunk-kxp04jnp.js";import{autoStatusEnabled,protocolUpgradeFromLiveSession,protocolWriteBackFromLiveSession}from"./chunk-qecygh3f.js";import{engineDisplayName,engineProtocolKey,protocolEntry,roveApiInvocation,sessionProtocol}from"./chunk-rjq38twt.js";import"./chunk-r5j8fycq.js";import"./chunk-xfgqae9t.js";import"./chunk-j1z9kgyd.js";import{teardownScope}from"./chunk-g9ba25q5.js";import"./chunk-ggnq2vvk.js";import"./chunk-hpay0ax8.js";import"./chunk-catrr0z3.js";import{stateFileTabsPersistence}from"./chunk-mdc7b01e.js";import"./chunk-tn9gtf18.js";import{execHostForWorktreePath}from"./chunk-895yqjjz.js";import"./chunk-sak1tphp.js";import"./chunk-y1xnjx8x.js";import{connectOrStartDaemon,daemonSpawnReason}from"./chunk-e58kj4gm.js";import{stopDaemonProcess}from"./chunk-0a65j1zj.js";import"./chunk-bcyex84w.js";import{foregroundEngineIn,parsePsSnapshot,psSnapshot}from"./chunk-5rgrde6b.js";import{createEngineTurnDetector,engineEntry,engineTitleTurnHint,vendorsWithQuotaProbe}from"./chunk-4gjvmfa9.js";import{spawnCapture}from"./chunk-2tfnscxk.js";import{availableEngineIds}from"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-2w228s7t.js";import"./chunk-etfh8f4z.js";import"./chunk-9rj2fx6v.js";import{backfillSavedReposFromProjects,getCustomEngineIds,getPersistedString,getRemoteRepoConfig,getSavedRepos,setPersistedString}from"./chunk-rfp0ayra.js";import{parsePorcelain}from"./chunk-0r1jf8m9.js";import"./chunk-t7j8g9f6.js";import"./chunk-dmzg9zdc.js";import"./chunk-40dgv828.js";import{DEFAULT_BASE_REF_CANDIDATES,readHeadSha,readRefSha,resolveGitDirs}from"./chunk-kg9kmwt9.js";import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import{CURRENT_VERSION,checkLatestVersion}from"./chunk-2wrt80ft.js";import{argvHasFlag,switchFlag}from"./chunk-zsfyj36g.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import{SUBCOMMAND_VERBS}from"./chunk-qqr4tfhk.js";import{loadStateFile}from"./chunk-32j6y5d1.js";import"./chunk-ve76p2mx.js";import"./chunk-cmp64q4j.js";import{RoveDaemonClient}from"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import"./chunk-7bakcyes.js";import"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import"./chunk-x1jxxmtc.js";import{DEFAULT_TASK_VENDOR,isTaskStatus}from"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import{migrateRoveDaemonStateLayout}from"./chunk-8t7qbr1e.js";import{releaseSync}from"./chunk-bejhca6z.js";import{isProcessAlive,readPidFile}from"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import{rotateLogIfNeeded}from"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath}from"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import{readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import{__require}from"./chunk-91sykzqq.js";async function latestTranscriptMtime(vendor,worktree){if(!worktree)return 0;return protocolEntry(vendor).history.latestTranscriptMtimeForWorktree(worktree)}async function maybeAutoStart(orch,taskId,enabled=autoStatusEnabled){if(!enabled())return"skipped";let task=orch.getTask(taskId);if(!task)return"skipped";if((task.kind??"task")==="main")return"skipped";if(task.status!=="backlog")return"skipped";return await orch.setStatus(taskId,"in_progress"),"moved"}var SYNC_TIMEOUT_MS=60000,SYNC_CONFLICT="SYNC_CONFLICT",SYNC_DIRTY="SYNC_WORKTREE_DIRTY";async function git(cwd,args,signal,write=!1){return spawnCapture("git",args,{cwd,env:write?process.env:readOnlyGitProcessEnv(),signal})}function parseConflictedPaths(stdout){return stdout.split(`
2
+ import{deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,deriveTitleFromSession,deriveTitleFromSessionId,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,tearDownTaskSessionAdapter}from"./chunk-w8dmmnys.js";import{buildCIPromptForWorktree}from"./chunk-vkz6kkmm.js";import{Orchestrator}from"./chunk-k3h4cpdy.js";import{GH_PR_VIEW_FIELDS,classifyGhFailure,mapGhPrView,nextPrPoll,samePrStatus}from"./chunk-zr058kbe.js";import"./chunk-c1dz3qg3.js";import{resolvePluginBinPath}from"./chunk-b0ssvpht.js";import{GitWorktreeManager,parseDirtyPaths}from"./chunk-3x5g06mw.js";import{startChatChannels}from"./chunk-cx8wnz54.js";import{auditDeletionBranchKept,auditDeletionResidue,auditDeletionSalvaged,auditWorktreeResidue,auditWorktreeSalvaged,parseAheadBehind,startDaemonServer}from"./chunk-x35dfb1x.js";import"./chunk-16e6jqq6.js";import"./chunk-a4hsqj1b.js";import"./chunk-6hcyvg0m.js";import{refreshOutdatedSkills}from"./chunk-0gbg7bg8.js";import"./chunk-4dt1gfb3.js";import"./chunk-tq0h3vy6.js";import"./chunk-cpgnm1xr.js";import"./chunk-r3s2t9af.js";import"./chunk-6xr1prk6.js";import{preferredReleaseChannel,updateDelayHours}from"./chunk-32y7f5dr.js";import"./chunk-xmwp6je4.js";import{cancelAllLogins}from"./chunk-pm91e38v.js";import{PLACEHOLDER_TASK_TITLE}from"./chunk-2xsxcdp6.js";import{affectsActivityState,isEngineActivityKind}from"./chunk-17e2tgyg.js";import"./chunk-1vxtd8rh.js";import"./chunk-q8ffd1pc.js";import"./chunk-4hestsjp.js";import"./chunk-qgrg9a5n.js";import"./chunk-2bgmby1d.js";import"./chunk-n0rdn2fn.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import"./chunk-vp29jgbt.js";import"./chunk-gq36nzg8.js";import{RELAY_PREAMBLE}from"./chunk-sq6zj3fb.js";import{TaskIndexStore}from"./chunk-7kgcy89w.js";import"./chunk-qkehg2c1.js";import"./chunk-vx44yxra.js";import"./chunk-z43e08kw.js";import"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import"./chunk-gzkes5bw.js";import{installDaemonCrashHandlers,logDaemonError,logDaemonInfo}from"./chunk-rxqdw6s5.js";import"./chunk-8ng1756g.js";import"./chunk-kxp04jnp.js";import{autoStatusEnabled,protocolUpgradeFromLiveSession,protocolWriteBackFromLiveSession}from"./chunk-qecygh3f.js";import{engineDisplayName,engineProtocolKey,protocolEntry,roveApiInvocation,sessionProtocol}from"./chunk-rjq38twt.js";import"./chunk-r5j8fycq.js";import"./chunk-xfgqae9t.js";import"./chunk-j1z9kgyd.js";import{teardownScope}from"./chunk-g9ba25q5.js";import"./chunk-ggnq2vvk.js";import"./chunk-hpay0ax8.js";import"./chunk-catrr0z3.js";import{stateFileTabsPersistence}from"./chunk-mdc7b01e.js";import"./chunk-tn9gtf18.js";import{execHostForWorktreePath}from"./chunk-895yqjjz.js";import"./chunk-sak1tphp.js";import"./chunk-y1xnjx8x.js";import{connectOrStartDaemon,daemonSpawnReason}from"./chunk-e58kj4gm.js";import{stopDaemonProcess}from"./chunk-0a65j1zj.js";import"./chunk-bcyex84w.js";import{foregroundEngineIn,parsePsSnapshot,psSnapshot}from"./chunk-5rgrde6b.js";import{createEngineTurnDetector,engineEntry,engineTitleTurnHint,vendorsWithQuotaProbe}from"./chunk-4gjvmfa9.js";import{spawnCapture}from"./chunk-2tfnscxk.js";import{availableEngineIds}from"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-2w228s7t.js";import"./chunk-etfh8f4z.js";import"./chunk-9rj2fx6v.js";import{backfillSavedReposFromProjects,getCustomEngineIds,getPersistedString,getRemoteRepoConfig,getSavedRepos,setPersistedString}from"./chunk-rfp0ayra.js";import{parsePorcelain}from"./chunk-0r1jf8m9.js";import"./chunk-t7j8g9f6.js";import"./chunk-dmzg9zdc.js";import"./chunk-40dgv828.js";import{DEFAULT_BASE_REF_CANDIDATES,readHeadSha,readRefSha,resolveGitDirs}from"./chunk-kg9kmwt9.js";import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import{CURRENT_VERSION,checkLatestVersion}from"./chunk-yn01fet6.js";import{argvHasFlag,switchFlag}from"./chunk-zsfyj36g.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import{SUBCOMMAND_VERBS}from"./chunk-qqr4tfhk.js";import{loadStateFile}from"./chunk-32j6y5d1.js";import"./chunk-9vwb9f7q.js";import"./chunk-cmp64q4j.js";import{RoveDaemonClient}from"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import"./chunk-7bakcyes.js";import"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import"./chunk-x1jxxmtc.js";import{DEFAULT_TASK_VENDOR,isTaskStatus}from"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import{migrateRoveDaemonStateLayout}from"./chunk-8t7qbr1e.js";import{releaseSync}from"./chunk-bejhca6z.js";import{isProcessAlive,readPidFile}from"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import{rotateLogIfNeeded}from"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath}from"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import{readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import{__require}from"./chunk-91sykzqq.js";async function latestTranscriptMtime(vendor,worktree){if(!worktree)return 0;return protocolEntry(vendor).history.latestTranscriptMtimeForWorktree(worktree)}async function maybeAutoStart(orch,taskId,enabled=autoStatusEnabled){if(!enabled())return"skipped";let task=orch.getTask(taskId);if(!task)return"skipped";if((task.kind??"task")==="main")return"skipped";if(task.status!=="backlog")return"skipped";return await orch.setStatus(taskId,"in_progress"),"moved"}var SYNC_TIMEOUT_MS=60000,SYNC_CONFLICT="SYNC_CONFLICT",SYNC_DIRTY="SYNC_WORKTREE_DIRTY";async function git(cwd,args,signal,write=!1){return spawnCapture("git",args,{cwd,env:write?process.env:readOnlyGitProcessEnv(),signal})}function parseConflictedPaths(stdout){return stdout.split(`
3
3
  `).map((line)=>line.trim()).filter((line)=>line.length>0)}async function syncWorktreeWithBase(worktreePath,baseRef,signal){let status=await git(worktreePath,["status","--porcelain=v1"],signal);if(status.status!==0)throw Error("git status failed");let dirty=parseDirtyPaths(status.stdout);if(dirty.length>0)throw Error(`${SYNC_DIRTY}: ${dirty.join(", ")}`);let before=await git(worktreePath,["rev-parse","HEAD"],signal),merge=await git(worktreePath,["merge","--no-edit",baseRef],signal,!0);if(merge.status!==0){let conflicted=await git(worktreePath,["diff","--name-only","--diff-filter=U"],signal),paths=parseConflictedPaths(conflicted.stdout);if(paths.length>0)throw Error(`${SYNC_CONFLICT}: ${paths.join(", ")}`);let detail=merge.stderr?.trim();throw Error(detail?`git merge ${baseRef} failed \u2014 ${detail}`:`git merge ${baseRef} failed`)}let after=await git(worktreePath,["rev-parse","HEAD"],signal);return{baseRef,alreadyCurrent:before.status===0&&before.stdout.trim()===after.stdout.trim()}}import{readFileSync}from"fs";import{join}from"path";var BASE_REF_TTL_MS=300000,cache=new Map;async function git2(worktreePath,args,signal){return await spawnCapture("git",[...args],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal})}async function refExists(worktreePath,ref,signal){return(await git2(worktreePath,["rev-parse","--verify","--quiet",ref],signal)).status===0}async function sharesHistory(worktreePath,ref,signal){return(await git2(worktreePath,["merge-base",ref,"HEAD"],signal)).status===0}async function baseCheckoutBranchFromGit(worktreePath,signal){let out=await git2(worktreePath,["worktree","list","--porcelain"],signal);if(out.status!==0)return null;return(out.stdout.split(`
4
4
 
5
5
  `,1)[0]??"").split(`
6
- `).find((l)=>l.startsWith("branch "))?.slice(7).trim().replace(/^refs\/heads\//,"")||null}function readRefSymbolic(dirs,ref){for(let dir of[dirs.gitDir,dirs.commonDir])try{let target=readFileSync(join(dir,ref),"utf8").trim().match(/^ref:\s*(.+)$/)?.[1]?.trim();if(target)return target}catch{}return null}function ladderFromFiles(worktreePath){let dirs=resolveGitDirs(worktreePath);if(!dirs)return;let originHead=readRefSymbolic(dirs,"refs/remotes/origin/HEAD")?.replace(/^refs\/remotes\//,""),baseCheckout=readRefSymbolic({gitDir:dirs.commonDir,commonDir:dirs.commonDir},"HEAD")?.replace(/^refs\/heads\//,""),names=[],head=readHeadSha(dirs),parts=[`HEAD=${head}`];for(let guess of[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]]){if(names.includes(guess))continue;let sha=readRefSha(dirs,guess);if(sha===null)continue;names.push(guess),parts.push(`${guess}=${sha}`)}return{names,fingerprint:head===null?null:parts.join(",")}}async function ladderFromGit(worktreePath,signal){let head=await git2(worktreePath,["symbolic-ref","--short","refs/remotes/origin/HEAD"],signal),originHead=head.status===0?head.stdout.trim():"",baseCheckout=await baseCheckoutBranchFromGit(worktreePath,signal),names=[],candidates=[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]];for(let guess of candidates){if(names.includes(guess))continue;if(await refExists(worktreePath,guess,signal))names.push(guess)}return{names,fingerprint:null}}async function resolveBaseRefCached(worktreePath,recordedBaseRef,signal,now=Date.now()){if(recordedBaseRef){let dirs=resolveGitDirs(worktreePath);if(dirs&&readRefSha(dirs,recordedBaseRef)!==null)return recordedBaseRef;if(await refExists(worktreePath,recordedBaseRef,signal))return recordedBaseRef}let hit=cache.get(worktreePath);if(hit&&now-hit.at<BASE_REF_TTL_MS)return hit.ref;let ladder=ladderFromFiles(worktreePath)??await ladderFromGit(worktreePath,signal);if(hit&&ladder.fingerprint!==null&&hit.fingerprint===ladder.fingerprint)return cache.set(worktreePath,{...hit,at:now}),hit.ref;let ref=null;for(let candidate of ladder.names)if(await sharesHistory(worktreePath,candidate,signal)){ref=candidate;break}return cache.set(worktreePath,{ref,at:now,fingerprint:ladder.fingerprint}),ref}var cache2=new Map;function readShas(worktreePath,baseRef){let dirs=resolveGitDirs(worktreePath);if(!dirs)return null;let head=readHeadSha(dirs),base=readRefSha(dirs,baseRef);return head&&base?{head,base}:null}async function driftCached(worktreePath,baseRef,compute){let shas=readShas(worktreePath,baseRef),hit=shas?cache2.get(worktreePath):void 0;if(shas&&hit&&hit.head===shas.head&&hit.base===shas.base)return hit.value;let value=await compute();if(shas&&value!==null)cache2.set(worktreePath,{...shas,value});return value}import{statSync}from"fs";function judgeWorktree(signals,nowMs){if(signals.dirty)return{verdict:"active",reason:"dirty"};if(signals.prState==="open")return{verdict:"active",reason:"prOpen"};if(signals.prState==="merged")return{verdict:"merged",reason:"prMerged"};if(signals.aheadOfDefault===0)return{verdict:"merged",reason:"inMain"};if(signals.prState==="closed")return{verdict:"stale",reason:"prClosed"};if(signals.lastActivityMs>0&&nowMs-signals.lastActivityMs>1209600000)return{verdict:"stale",reason:"idle"};return{verdict:"fresh",reason:"fresh"}}function parseGhPrList(stdout){let entries;try{entries=JSON.parse(stdout)}catch{return null}if(!Array.isArray(entries))return null;let rank={open:3,merged:2,closed:1},map=new Map;for(let entry of entries){let branch=entry?.headRefName,rawState=entry?.state;if(typeof branch!=="string"||typeof rawState!=="string")continue;let state=rawState.toLowerCase();if(state!=="open"&&state!=="merged"&&state!=="closed")continue;let cur=map.get(branch);if(!cur||rank[state]>rank[cur])map.set(branch,state)}return map}var TIMEOUT_MS=4000,manager=new GitWorktreeManager;function createdAt(path){try{let stat=statSync(path);return stat.birthtimeMs||stat.mtimeMs}catch{return 0}}async function run(path,argv){return execHostForWorktreePath(path).run(argv,{cwd:path,signal:AbortSignal.timeout(TIMEOUT_MS)})}async function branchOnRemote(path,branch){try{let out=await run(path,["git","ls-remote","--exit-code","--heads","origin",branch]);return out.exitCode===0?!0:out.exitCode===2?!1:null}catch{return null}}async function defaultRef(repo){try{let out=await run(repo,["git","symbolic-ref","--short","refs/remotes/origin/HEAD"]);if(out.exitCode===0&&out.stdout.trim())return out.stdout.trim()}catch{}for(let guess of["origin/main","origin/master"])try{if((await run(repo,["git","rev-parse","--verify","--quiet",guess])).exitCode===0)return guess}catch{}return null}async function prStates(repo){try{let origin=await run(repo,["git","remote","get-url","origin"]);if(origin.exitCode!==0||!origin.stdout.includes("github.com"))return null;let out=await run(repo,["gh","pr","list","--state","all","--limit","200","--json","headRefName,state"]);return out.exitCode===0?parseGhPrList(out.stdout):null}catch{return null}}async function ahead(path,ref){if(!ref)return null;try{let out=await run(path,["git","rev-list","--count",`${ref}..HEAD`]),value=Number.parseInt(out.stdout.trim(),10);return out.exitCode===0&&!Number.isNaN(value)?value:null}catch{return null}}async function listWorktreeProjectsAdapter(network){let repos=getSavedRepos().filter((repo)=>!getRemoteRepoConfig(repo)),now=Date.now();return Promise.all(repos.map(async(repo)=>{let[worktrees,states,ref]=await Promise.all([manager.listAll(repo),network?prStates(repo):null,defaultRef(repo)]),rows=await Promise.all(worktrees.map(async(worktree)=>{let[remote,aheadBy]=await Promise.all([network?branchOnRemote(worktree.path,worktree.branch):null,ahead(worktree.path,ref)]),judgement=judgeWorktree({dirty:worktree.dirty===!0,prState:states?.get(worktree.branch)??null,aheadOfDefault:aheadBy,lastActivityMs:worktree.lastActivityMs},now);return{...worktree,repo,createdAtMs:createdAt(worktree.path),branchOnRemote:remote,verdict:judgement.verdict,verdictReason:judgement.reason}}));return{repo,worktrees:rows}}))}async function listUnreadableWorktreesAdapter(repo){return manager.listUnreadableWorktrees(repo)}async function removeWorktreeAdapter(path,force){let residue=null;return await manager.remove(path,{force,onSalvage:(record)=>{if(record)auditWorktreeSalvaged(path,record.ref,record.commit,record.uncaptured)},onResidue:(r)=>{residue={path:r.path,reason:r.reason},auditWorktreeResidue(r.path,r.reason)}}),residue}function resolveProtocolUpgradeAndLearnPreset(task,evidence){let preset=protocolWriteBackFromLiveSession(task,evidence,getCustomEngineIds());if(preset)setPersistedString(engineProtocolKey(preset.id),preset.protocol);return protocolUpgradeFromLiveSession(task,evidence)}var daemonRuntime={currentVersion:CURRENT_VERSION,tabsPersistence:stateFileTabsPersistence,startMachineHub(bus){let stop=null,stopped=!1;return import("./chunk-mjzjah9d.js").then(({startDaemonMachineHub})=>{if(!stopped)stop=startDaemonMachineHub(bus)}),()=>{stopped=!0,stop?.()}},async invokeApi(verb,params,socketPath,route){let[{executeVerb,errorEnvelope},{daemonCaller},{RoveDaemonClient:RoveDaemonClient2}]=await Promise.all([import("./chunk-0g1h35mr.js"),import("./chunk-34tbcjdy.js"),import("./chunk-fq2pefc5.js")]);if(route?.forwarded){let{inboundRefusal}=await import("./chunk-d2wndk4q.js"),denied=inboundRefusal(verb);if(denied){let{ApiError}=await import("./chunk-34tbcjdy.js");return errorEnvelope(new ApiError(`this machine refuses "${denied}" verbs from other machines (${verb} from ${route.from??"a hub"})`,"INBOUND_DENIED",{hint:`on this machine: rove machine inbound allow ${denied}`}))}}let client=new RoveDaemonClient2(socketPath);try{await client.connect();let{invokeRouted}=await import("./chunk-9f34p80j.js");return await invokeRouted({verb,params,machine:route?.machine,forwarded:route?.forwarded,localTasks:()=>client.request("task.list").then((res)=>res.tasks??[]),isLocalTask:(id)=>client.request("task.get",{taskId:id}).then(()=>!0,()=>!1),runHere:()=>executeVerb(verb,{params},{client,caller:daemonCaller(route?.forwarded===!0)})})}catch(err){return errorEnvelope(err)}finally{client.close()}},defaultTaskVendor:DEFAULT_TASK_VENDOR,placeholderTaskTitle:PLACEHOLDER_TASK_TITLE,isTaskStatus,isEngineActivityKind,affectsActivityState,async foregroundEngines(pids){let rows=parsePsSnapshot(await psSnapshot([...pids])),out=new Map;for(let pid of pids){let found=foregroundEngineIn(rows,pid);out.set(pid,found?{vendor:found.vendor,pid:found.pid}:null)}return out},titleTurnHint:(vendor,title)=>engineTitleTurnHint(sessionProtocol(vendor),title),sessionProtocol,resolveProtocolUpgrade:resolveProtocolUpgradeAndLearnPreset,readEngineTurns:async(vendor,transcriptPath)=>await protocolEntry(vendor).readTurns?.(transcriptPath)??[],checkLatestVersion:()=>{let state=loadStateFile();return checkLatestVersion({channel:preferredReleaseChannel(state),minAgeHours:updateDelayHours(state)})},latestTranscriptMtime,deriveTitleFromSession,deriveTitleFromSessionId,createEngineTurnDetector:(vendor)=>createEngineTurnDetector(sessionProtocol(vendor)),async runWorktreeStatus(worktreePath,signal,baseRef){let result=await spawnCapture("git",["status","--porcelain=v1"],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});if(result.status!==0)throw Error("git status failed");let counts=parsePorcelain(result.stdout),base=await resolveBaseRefCached(worktreePath,baseRef,signal);if(!base)return counts;let drift=await driftCached(worktreePath,base,async()=>{let out=await spawnCapture("git",["rev-list","--left-right","--count",`${base}...HEAD`],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});return out.status===0?parseAheadBehind(out.stdout):null});return drift===null?counts:{...counts,...drift}},maybeAutoStart:(orch,taskId)=>maybeAutoStart(orch,taskId),listWorktreeProjects:listWorktreeProjectsAdapter,listUnreadableWorktrees:listUnreadableWorktreesAdapter,removeWorktree:removeWorktreeAdapter,async syncWorktreeWithBase(worktreePath,recordedBaseRef){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),SYNC_TIMEOUT_MS);try{let baseRef=await resolveBaseRefCached(worktreePath,recordedBaseRef,controller.signal);if(!baseRef)throw Error("no base ref resolves for this worktree");return await syncWorktreeWithBase(worktreePath,baseRef,controller.signal)}finally{clearTimeout(timer)}},availableEngineIds,engineDisplayName,roveApiInvocation,engineEntry,ensureTaskSession:ensureTaskSessionAdapter,startTaskSessionWithPrompt:startTaskSessionWithPromptAdapter,tearDownTaskSession:tearDownTaskSessionAdapter,async readEngineContextUsage(vendor,sessionId){let read=protocolEntry(vendor).history.readUsageSnapshot;if(!read)return null;let snapshot=await read(sessionId);if(snapshot?.context_tokens===void 0)return null;return{contextTokens:snapshot.context_tokens,...snapshot.context_window_tokens===void 0?{}:{contextWindowTokens:snapshot.context_window_tokens},...snapshot.context_tokens_approximate?{approximate:!0}:{},...snapshot.input_tokens===void 0?{}:{inputTokens:snapshot.input_tokens},...snapshot.output_tokens===void 0?{}:{outputTokens:snapshot.output_tokens},...snapshot.cache_read_input_tokens===void 0?{}:{cacheReadTokens:snapshot.cache_read_input_tokens},...snapshot.cache_creation_input_tokens===void 0?{}:{cacheCreationTokens:snapshot.cache_creation_input_tokens},...snapshot.context_parts?{parts:snapshot.context_parts}:{}}},quotaUsage:(vendor)=>engineEntry(vendor).quotaUsage?.()??Promise.resolve(null),vendorsWithQuotaProbe,deliverPromptToLiveEngine:deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailed:deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailed:deliverPromptToLiveEngineTabDetailedAdapter,getPersistedString,buildCIPrompt:(worktree,state)=>buildCIPromptForWorktree(worktree,state),setPersistedString,getSavedRepos:()=>[...getSavedRepos()],prStatus:{viewFields:GH_PR_VIEW_FIELDS,mapView:(view,at)=>mapGhPrView(view,at),sameStatus:samePrStatus,nextPoll:(outcome,failures,now,config,random)=>nextPrPoll(outcome,failures,now,config,random),classify:classifyGhFailure}};import{homedir}from"os";async function createRoveCore(options={}){let homeDir=options.homeDir??readRoveHomeDirEnv()??homedir(),store=new TaskIndexStore({homeDir});await store.load();let worktrees=new GitWorktreeManager,orchestrator=new Orchestrator({store,worktrees,onSalvage:(taskId,salvage,repo)=>auditDeletionSalvaged(String(taskId),salvage.ref,salvage.commit,repo,salvage.uncaptured),onWorktreeResidue:(taskId,residue)=>auditDeletionResidue(String(taskId),residue.path,residue.reason),onBranchKept:(taskId,kept)=>auditDeletionBranchKept(String(taskId),kept.branch,kept.reason),tearDownSession:(taskId)=>tearDownTaskSessionAdapter(String(taskId),teardownScope(store.list(),String(taskId),new Set([String(taskId)])))}),backfilled=backfillSavedReposFromProjects(store.list().filter((task)=>task.kind==="main").map((task)=>task.repo));if(backfilled.length>0)console.error(`[rove] added ${backfilled.length} existing project(s) to the new-task picker`);return{homeDir,orchestrator,store,worktrees,async close(){orchestrator.dispose()}}}import{existsSync,readFileSync as readFileSync2,readdirSync,statSync as statSync2,unlinkSync}from"fs";import{join as join2}from"path";var TMP_MAX_AGE_MS=300000;function sweepIndexLeftovers(stateDir,now=Date.now()){let tmp=[],tmpBytes=0,entries;try{entries=readdirSync(stateDir)}catch{return{tmp,tmpBytes,lock:!1}}for(let name of entries){if(!name.startsWith("tasks.json.")||!name.endsWith(".tmp"))continue;let path=join2(stateDir,name);try{let stat=statSync2(path);if(now-stat.mtimeMs<TMP_MAX_AGE_MS)continue;unlinkSync(path),tmp.push(path),tmpBytes+=stat.size}catch{}}return{tmp,tmpBytes,lock:clearStaleLock(join2(stateDir,"tasks.json.lock"))}}function clearStaleLock(lockPath){let holder;try{holder=readFileSync2(lockPath,"utf8").trim()}catch{return!1}let pid=Number.parseInt(holder,10);if(Number.isFinite(pid)&&pid>0&&isProcessAlive(pid))return!1;return releaseSync(lockPath,holder),!existsSync(lockPath)}var CLI_NAME=ROVE_PRODUCT_NAME;function printDaemonUsage(out){out.write([`Usage: ${CLI_NAME} daemon <command>`,"","Commands:"," status Print the running daemon's status JSON (default)"," start Run the daemon in the foreground (this process becomes it)"," --resident: never idle-stop when the last TUI leaves (headless host)"," stop Ask the running daemon to shut down"," restart Stop the daemon (graceful \u2192 SIGTERM \u2192 SIGKILL) and respawn it",""].join(`
6
+ `).find((l)=>l.startsWith("branch "))?.slice(7).trim().replace(/^refs\/heads\//,"")||null}function readRefSymbolic(dirs,ref){for(let dir of[dirs.gitDir,dirs.commonDir])try{let target=readFileSync(join(dir,ref),"utf8").trim().match(/^ref:\s*(.+)$/)?.[1]?.trim();if(target)return target}catch{}return null}function ladderFromFiles(worktreePath){let dirs=resolveGitDirs(worktreePath);if(!dirs)return;let originHead=readRefSymbolic(dirs,"refs/remotes/origin/HEAD")?.replace(/^refs\/remotes\//,""),baseCheckout=readRefSymbolic({gitDir:dirs.commonDir,commonDir:dirs.commonDir},"HEAD")?.replace(/^refs\/heads\//,""),names=[],head=readHeadSha(dirs),parts=[`HEAD=${head}`];for(let guess of[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]]){if(names.includes(guess))continue;let sha=readRefSha(dirs,guess);if(sha===null)continue;names.push(guess),parts.push(`${guess}=${sha}`)}return{names,fingerprint:head===null?null:parts.join(",")}}async function ladderFromGit(worktreePath,signal){let head=await git2(worktreePath,["symbolic-ref","--short","refs/remotes/origin/HEAD"],signal),originHead=head.status===0?head.stdout.trim():"",baseCheckout=await baseCheckoutBranchFromGit(worktreePath,signal),names=[],candidates=[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]];for(let guess of candidates){if(names.includes(guess))continue;if(await refExists(worktreePath,guess,signal))names.push(guess)}return{names,fingerprint:null}}async function resolveBaseRefCached(worktreePath,recordedBaseRef,signal,now=Date.now()){if(recordedBaseRef){let dirs=resolveGitDirs(worktreePath);if(dirs&&readRefSha(dirs,recordedBaseRef)!==null)return recordedBaseRef;if(await refExists(worktreePath,recordedBaseRef,signal))return recordedBaseRef}let hit=cache.get(worktreePath);if(hit&&now-hit.at<BASE_REF_TTL_MS)return hit.ref;let ladder=ladderFromFiles(worktreePath)??await ladderFromGit(worktreePath,signal);if(hit&&ladder.fingerprint!==null&&hit.fingerprint===ladder.fingerprint)return cache.set(worktreePath,{...hit,at:now}),hit.ref;let ref=null;for(let candidate of ladder.names)if(await sharesHistory(worktreePath,candidate,signal)){ref=candidate;break}return cache.set(worktreePath,{ref,at:now,fingerprint:ladder.fingerprint}),ref}var cache2=new Map;function readShas(worktreePath,baseRef){let dirs=resolveGitDirs(worktreePath);if(!dirs)return null;let head=readHeadSha(dirs),base=readRefSha(dirs,baseRef);return head&&base?{head,base}:null}async function driftCached(worktreePath,baseRef,compute){let shas=readShas(worktreePath,baseRef),hit=shas?cache2.get(worktreePath):void 0;if(shas&&hit&&hit.head===shas.head&&hit.base===shas.base)return hit.value;let value=await compute();if(shas&&value!==null)cache2.set(worktreePath,{...shas,value});return value}import{statSync}from"fs";function judgeWorktree(signals,nowMs){if(signals.dirty)return{verdict:"active",reason:"dirty"};if(signals.prState==="open")return{verdict:"active",reason:"prOpen"};if(signals.prState==="merged")return{verdict:"merged",reason:"prMerged"};if(signals.aheadOfDefault===0)return{verdict:"merged",reason:"inMain"};if(signals.prState==="closed")return{verdict:"stale",reason:"prClosed"};if(signals.lastActivityMs>0&&nowMs-signals.lastActivityMs>1209600000)return{verdict:"stale",reason:"idle"};return{verdict:"fresh",reason:"fresh"}}function parseGhPrList(stdout){let entries;try{entries=JSON.parse(stdout)}catch{return null}if(!Array.isArray(entries))return null;let rank={open:3,merged:2,closed:1},map=new Map;for(let entry of entries){let branch=entry?.headRefName,rawState=entry?.state;if(typeof branch!=="string"||typeof rawState!=="string")continue;let state=rawState.toLowerCase();if(state!=="open"&&state!=="merged"&&state!=="closed")continue;let cur=map.get(branch);if(!cur||rank[state]>rank[cur])map.set(branch,state)}return map}var TIMEOUT_MS=4000,manager=new GitWorktreeManager;function createdAt(path){try{let stat=statSync(path);return stat.birthtimeMs||stat.mtimeMs}catch{return 0}}async function run(path,argv){return execHostForWorktreePath(path).run(argv,{cwd:path,signal:AbortSignal.timeout(TIMEOUT_MS)})}async function branchOnRemote(path,branch){try{let out=await run(path,["git","ls-remote","--exit-code","--heads","origin",branch]);return out.exitCode===0?!0:out.exitCode===2?!1:null}catch{return null}}async function defaultRef(repo){try{let out=await run(repo,["git","symbolic-ref","--short","refs/remotes/origin/HEAD"]);if(out.exitCode===0&&out.stdout.trim())return out.stdout.trim()}catch{}for(let guess of["origin/main","origin/master"])try{if((await run(repo,["git","rev-parse","--verify","--quiet",guess])).exitCode===0)return guess}catch{}return null}async function prStates(repo){try{let origin=await run(repo,["git","remote","get-url","origin"]);if(origin.exitCode!==0||!origin.stdout.includes("github.com"))return null;let out=await run(repo,["gh","pr","list","--state","all","--limit","200","--json","headRefName,state"]);return out.exitCode===0?parseGhPrList(out.stdout):null}catch{return null}}async function ahead(path,ref){if(!ref)return null;try{let out=await run(path,["git","rev-list","--count",`${ref}..HEAD`]),value=Number.parseInt(out.stdout.trim(),10);return out.exitCode===0&&!Number.isNaN(value)?value:null}catch{return null}}async function listWorktreeProjectsAdapter(network){let repos=getSavedRepos().filter((repo)=>!getRemoteRepoConfig(repo)),now=Date.now();return Promise.all(repos.map(async(repo)=>{let[worktrees,states,ref]=await Promise.all([manager.listAll(repo),network?prStates(repo):null,defaultRef(repo)]),rows=await Promise.all(worktrees.map(async(worktree)=>{let[remote,aheadBy]=await Promise.all([network?branchOnRemote(worktree.path,worktree.branch):null,ahead(worktree.path,ref)]),judgement=judgeWorktree({dirty:worktree.dirty===!0,prState:states?.get(worktree.branch)??null,aheadOfDefault:aheadBy,lastActivityMs:worktree.lastActivityMs},now);return{...worktree,repo,createdAtMs:createdAt(worktree.path),branchOnRemote:remote,verdict:judgement.verdict,verdictReason:judgement.reason}}));return{repo,worktrees:rows}}))}async function listUnreadableWorktreesAdapter(repo){return manager.listUnreadableWorktrees(repo)}async function removeWorktreeAdapter(path,force){let residue=null;return await manager.remove(path,{force,onSalvage:(record)=>{if(record)auditWorktreeSalvaged(path,record.ref,record.commit,record.uncaptured)},onResidue:(r)=>{residue={path:r.path,reason:r.reason},auditWorktreeResidue(r.path,r.reason)}}),residue}function resolveProtocolUpgradeAndLearnPreset(task,evidence){let preset=protocolWriteBackFromLiveSession(task,evidence,getCustomEngineIds());if(preset)setPersistedString(engineProtocolKey(preset.id),preset.protocol);return protocolUpgradeFromLiveSession(task,evidence)}var daemonRuntime={currentVersion:CURRENT_VERSION,tabsPersistence:stateFileTabsPersistence,startMachineHub(bus){let stop=null,stopped=!1;return import("./chunk-vtay379p.js").then(({startDaemonMachineHub})=>{if(!stopped)stop=startDaemonMachineHub(bus)}),()=>{stopped=!0,stop?.()}},async invokeApi(verb,params,socketPath,route){let[{executeVerb,errorEnvelope},{daemonCaller},{RoveDaemonClient:RoveDaemonClient2}]=await Promise.all([import("./chunk-xxz3np4w.js"),import("./chunk-34tbcjdy.js"),import("./chunk-fq2pefc5.js")]);if(route?.forwarded){let{inboundRefusal}=await import("./chunk-sqdmngys.js"),denied=inboundRefusal(verb);if(denied){let{ApiError}=await import("./chunk-34tbcjdy.js");return errorEnvelope(new ApiError(`this machine refuses "${denied}" verbs from other machines (${verb} from ${route.from??"a hub"})`,"INBOUND_DENIED",{hint:`on this machine: rove machine inbound allow ${denied}`}))}}let client=new RoveDaemonClient2(socketPath);try{await client.connect();let{invokeRouted}=await import("./chunk-ww0zctb7.js");return await invokeRouted({verb,params,machine:route?.machine,forwarded:route?.forwarded,localTasks:()=>client.request("task.list").then((res)=>res.tasks??[]),isLocalTask:(id)=>client.request("task.get",{taskId:id}).then(()=>!0,()=>!1),runHere:()=>executeVerb(verb,{params},{client,caller:daemonCaller(route?.forwarded===!0)})})}catch(err){return errorEnvelope(err)}finally{client.close()}},defaultTaskVendor:DEFAULT_TASK_VENDOR,placeholderTaskTitle:PLACEHOLDER_TASK_TITLE,isTaskStatus,isEngineActivityKind,affectsActivityState,async foregroundEngines(pids){let rows=parsePsSnapshot(await psSnapshot([...pids])),out=new Map;for(let pid of pids){let found=foregroundEngineIn(rows,pid);out.set(pid,found?{vendor:found.vendor,pid:found.pid}:null)}return out},titleTurnHint:(vendor,title)=>engineTitleTurnHint(sessionProtocol(vendor),title),sessionProtocol,resolveProtocolUpgrade:resolveProtocolUpgradeAndLearnPreset,readEngineTurns:async(vendor,transcriptPath)=>await protocolEntry(vendor).readTurns?.(transcriptPath)??[],checkLatestVersion:()=>{let state=loadStateFile();return checkLatestVersion({channel:preferredReleaseChannel(state),minAgeHours:updateDelayHours(state)})},latestTranscriptMtime,deriveTitleFromSession,deriveTitleFromSessionId,createEngineTurnDetector:(vendor)=>createEngineTurnDetector(sessionProtocol(vendor)),async runWorktreeStatus(worktreePath,signal,baseRef){let result=await spawnCapture("git",["status","--porcelain=v1"],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});if(result.status!==0)throw Error("git status failed");let counts=parsePorcelain(result.stdout),base=await resolveBaseRefCached(worktreePath,baseRef,signal);if(!base)return counts;let drift=await driftCached(worktreePath,base,async()=>{let out=await spawnCapture("git",["rev-list","--left-right","--count",`${base}...HEAD`],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});return out.status===0?parseAheadBehind(out.stdout):null});return drift===null?counts:{...counts,...drift}},maybeAutoStart:(orch,taskId)=>maybeAutoStart(orch,taskId),listWorktreeProjects:listWorktreeProjectsAdapter,listUnreadableWorktrees:listUnreadableWorktreesAdapter,removeWorktree:removeWorktreeAdapter,async syncWorktreeWithBase(worktreePath,recordedBaseRef){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),SYNC_TIMEOUT_MS);try{let baseRef=await resolveBaseRefCached(worktreePath,recordedBaseRef,controller.signal);if(!baseRef)throw Error("no base ref resolves for this worktree");return await syncWorktreeWithBase(worktreePath,baseRef,controller.signal)}finally{clearTimeout(timer)}},availableEngineIds,engineDisplayName,roveApiInvocation,engineEntry,ensureTaskSession:ensureTaskSessionAdapter,startTaskSessionWithPrompt:startTaskSessionWithPromptAdapter,tearDownTaskSession:tearDownTaskSessionAdapter,async readEngineContextUsage(vendor,sessionId){let read=protocolEntry(vendor).history.readUsageSnapshot;if(!read)return null;let snapshot=await read(sessionId);if(snapshot?.context_tokens===void 0)return null;return{contextTokens:snapshot.context_tokens,...snapshot.context_window_tokens===void 0?{}:{contextWindowTokens:snapshot.context_window_tokens},...snapshot.context_tokens_approximate?{approximate:!0}:{},...snapshot.input_tokens===void 0?{}:{inputTokens:snapshot.input_tokens},...snapshot.output_tokens===void 0?{}:{outputTokens:snapshot.output_tokens},...snapshot.cache_read_input_tokens===void 0?{}:{cacheReadTokens:snapshot.cache_read_input_tokens},...snapshot.cache_creation_input_tokens===void 0?{}:{cacheCreationTokens:snapshot.cache_creation_input_tokens},...snapshot.context_parts?{parts:snapshot.context_parts}:{}}},quotaUsage:(vendor)=>engineEntry(vendor).quotaUsage?.()??Promise.resolve(null),vendorsWithQuotaProbe,deliverPromptToLiveEngine:deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailed:deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailed:deliverPromptToLiveEngineTabDetailedAdapter,getPersistedString,buildCIPrompt:(worktree,state)=>buildCIPromptForWorktree(worktree,state),setPersistedString,getSavedRepos:()=>[...getSavedRepos()],prStatus:{viewFields:GH_PR_VIEW_FIELDS,mapView:(view,at)=>mapGhPrView(view,at),sameStatus:samePrStatus,nextPoll:(outcome,failures,now,config,random)=>nextPrPoll(outcome,failures,now,config,random),classify:classifyGhFailure}};import{homedir}from"os";async function createRoveCore(options={}){let homeDir=options.homeDir??readRoveHomeDirEnv()??homedir(),store=new TaskIndexStore({homeDir});await store.load();let worktrees=new GitWorktreeManager,orchestrator=new Orchestrator({store,worktrees,onSalvage:(taskId,salvage,repo)=>auditDeletionSalvaged(String(taskId),salvage.ref,salvage.commit,repo,salvage.uncaptured),onWorktreeResidue:(taskId,residue)=>auditDeletionResidue(String(taskId),residue.path,residue.reason),onBranchKept:(taskId,kept)=>auditDeletionBranchKept(String(taskId),kept.branch,kept.reason),tearDownSession:(taskId)=>tearDownTaskSessionAdapter(String(taskId),teardownScope(store.list(),String(taskId),new Set([String(taskId)])))}),backfilled=backfillSavedReposFromProjects(store.list().filter((task)=>task.kind==="main").map((task)=>task.repo));if(backfilled.length>0)console.error(`[rove] added ${backfilled.length} existing project(s) to the new-task picker`);return{homeDir,orchestrator,store,worktrees,async close(){orchestrator.dispose()}}}import{existsSync,readFileSync as readFileSync2,readdirSync,statSync as statSync2,unlinkSync}from"fs";import{join as join2}from"path";var TMP_MAX_AGE_MS=300000;function sweepIndexLeftovers(stateDir,now=Date.now()){let tmp=[],tmpBytes=0,entries;try{entries=readdirSync(stateDir)}catch{return{tmp,tmpBytes,lock:!1}}for(let name of entries){if(!name.startsWith("tasks.json.")||!name.endsWith(".tmp"))continue;let path=join2(stateDir,name);try{let stat=statSync2(path);if(now-stat.mtimeMs<TMP_MAX_AGE_MS)continue;unlinkSync(path),tmp.push(path),tmpBytes+=stat.size}catch{}}return{tmp,tmpBytes,lock:clearStaleLock(join2(stateDir,"tasks.json.lock"))}}function clearStaleLock(lockPath){let holder;try{holder=readFileSync2(lockPath,"utf8").trim()}catch{return!1}let pid=Number.parseInt(holder,10);if(Number.isFinite(pid)&&pid>0&&isProcessAlive(pid))return!1;return releaseSync(lockPath,holder),!existsSync(lockPath)}var CLI_NAME=ROVE_PRODUCT_NAME;function printDaemonUsage(out){out.write([`Usage: ${CLI_NAME} daemon <command>`,"","Commands:"," status Print the running daemon's status JSON (default)"," start Run the daemon in the foreground (this process becomes it)"," --resident: never idle-stop when the last TUI leaves (headless host)"," stop Ask the running daemon to shut down"," restart Stop the daemon (graceful \u2192 SIGTERM \u2192 SIGKILL) and respawn it",""].join(`
7
7
  `))}async function runDaemonSubcommand(argv){let[command="status",...flags]=argv,socketPath=defaultDaemonSocketPath(),pidPath=defaultDaemonPidPath();if(command==="--help"||command==="-h"||command==="help"){printDaemonUsage(process.stdout);return}if(!SUBCOMMAND_VERBS.daemon.includes(command))process.stderr.write(`${CLI_NAME} daemon: unknown command "${command}"
8
8
 
9
9
  `),printDaemonUsage(process.stderr),process.exit(2);if(command==="relay"){let pty=argvHasFlag(flags,"--pty"),{ensureDaemonReachable}=await import("./chunk-n2zgej1a.js"),{ensurePtyHostReachable}=await import("./chunk-bagwgxsg.js"),target=pty?await ensurePtyHostReachable():await ensureDaemonReachable(void 0,"autospawn"),{connect}=await import("net"),socket=connect(target);if(argvHasFlag(flags,"--preamble"))process.stdout.write(RELAY_PREAMBLE);process.stdin.pipe(socket),socket.pipe(process.stdout),await new Promise((resolve)=>{socket.on("close",()=>resolve()),process.stdin.on("end",()=>socket.end())}),process.exit(0)}let badFlag=flags.find((flag)=>!(command==="start"&&argvHasFlag([flag],"--resident"))&&!(command==="status"&&flag==="--json")&&!(command==="relay"&&flag==="--pty")),resident=switchFlag(flags,"--resident");if(badFlag!==void 0||resident===void 0)process.stderr.write(`${CLI_NAME} daemon ${command}: bad option "${badFlag??flags.join(" ")}"
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-1wwqf6kx.js";import{readLastActiveTaskId,writeLastActiveTaskId}from"./chunk-c1dz3qg3.js";import{CLONEFILEAT_PERL,GitWorktreeManager,defaultExecDeps,git,isDirtyOutput,parseDirtyPaths}from"./chunk-3x5g06mw.js";import{LAUNCH_PREFIX_FILE}from"./chunk-4dt1gfb3.js";import{PLACEHOLDER_TASK_TITLE,isPlaceholderDerivedBranch,sanitizeTaskTitle}from"./chunk-2xsxcdp6.js";import{CannotDeleteMainTaskError,DirtyWorktreeError,EmptyBranchDirtyWorktreeError,EmptyBranchError,ExtraRepoNotGitError,ForkUnsupportedError,GitCommandFailedError,IllegalTransitionError,InvalidWorktreeNameError,LandConflictError,MainCheckoutDirtyError,MissingRefError,MoveRefusedError,NotAGitRepoError,NotALinkedRepoError,REMOTE_PARENT_UNSUPPORTED_CODE,RemoteExtraUnsupportedError,RemoteParentUnsupportedError,ReparentRefusedError,RepoDuplicateError,TaskDeletingError,TaskNotFoundError,TooManyReposError,WorktreeNameTakenError,WorktreeRemoveFailedError,canonicalize,listWorktreeDirNames,worktreePathFor}from"./chunk-1vxtd8rh.js";import{detectLanguage}from"./chunk-hpay0ax8.js";import{resolvePreferredVendor}from"./chunk-9rj2fx6v.js";import{addSavedRepo,getPersistedString,getSavedRepos,isGitRepo,isRemoteRepoKey,removeSavedRepo,resolveMainRepoRoot,resolveRepoRoot}from"./chunk-rfp0ayra.js";import{READ_ONLY_GIT_ENV}from"./chunk-6xppe9bj.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{projectRejection,rejectionReason}from"./chunk-7mwvvj46.js";import{createStateCell}from"./chunk-cmp64q4j.js";import{MULTI_REPO_CAP,SESSION_PR_CAP,WORKSPACE_CAPABILITIES,applyTodoOps,checkNotes,childrenOf,gitRepoOf,lineageRootId,pickRepos,repoNameOf,subtreeIds,taskCwd,taskRepos,taskWorktreePaths,uniqueRepoName,workspaceBackendId,workspaceCapabilities}from"./chunk-x1jxxmtc.js";import{DEFAULT_TASK_VENDOR,toTaskId}from"./chunk-xy8be792.js";import{pathIdentity,pathWithin,samePath}from"./chunk-pn5ygqn6.js";class WorkspaceCheckpoints{store;worktrees;workspaces;requireTask;constructor(store,worktrees,workspaces,requireTask){this.store=store;this.worktrees=worktrees;this.workspaces=workspaces;this.requireTask=requireTask}workspaceOwner(id){let task=this.requireTask(id);return(task.sharesWorkspaceOf?this.store.get(task.sharesWorkspaceOf):void 0)??task}checkpointScope(id){let owner=this.workspaceOwner(id),sharers=this.store.list().filter((t)=>t.sharesWorkspaceOf===owner.id&&!t.deletion);return{ownerId:String(owner.id),sharerIds:[String(owner.id),...sharers.map((t)=>String(t.id))]}}canCheckpoint(id){if(!this.store.get(id))return!1;let owner=this.workspaceOwner(id);return workspaceCapabilities(owner).checkpoint&&!owner.deletion&&owner.worktreePath!==""}async target(id){let owner=this.workspaceOwner(id),own=this.canCheckpoint(id)?this.workspaces.get(workspaceBackendId(owner)).checkpoints:void 0,dir=owner.worktreePath;if(!this.canCheckpoint(id)||!await this.worktrees.pathExists(own?dir:`${dir}/.git`))throw Error(`NOT_CHECKPOINTABLE: ${owner.kind==="task"?"the task has no workspace on disk":`a ${owner.kind} task works in your own checkout`}`);let ownerId=String(owner.id);return{ownerId,dir,via:own??{take:(d,opts)=>this.worktrees.takeCheckpoint(d,ownerId,opts),list:(d)=>this.worktrees.listCheckpoints(d,ownerId),rewind:(d,n)=>this.worktrees.rewindToCheckpoint(d,ownerId,n)}}}async takeCheckpoint(id,opts){let{dir,via}=await this.target(id);return via.take(dir,opts)}async listCheckpoints(id){let{dir,via}=await this.target(id);return via.list(dir)}async rewindToCheckpoint(id,n){let{dir,via}=await this.target(id);return via.rewind(dir,n)}async exportBranch(id){let owner=this.workspaceOwner(id),backend=this.workspaces.get(workspaceBackendId(owner));if(!backend.exportBranch||!owner.worktreePath)throw Error("EXPORT_UNSUPPORTED: the task's branch is already in its repo (or it has no workspace yet)");return backend.exportBranch({path:owner.worktreePath,repo:gitRepoOf(owner),branch:owner.branch})}}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"]);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){let slug="";for(let token of tokens){let candidate=slug?`${slug}-${token}`:token;if(candidate.length>32)return slug||token.slice(0,32);slug=candidate}return slug}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){let dirs=new Set;for(let name of taken)for(let i=name.indexOf("/");i>0;i=name.indexOf("/",i+1))dirs.add(name.slice(0,i));let isFree=(name)=>!taken.has(name)&&!dirs.has(name),segments=base.split("/"),root=segments.slice(0,-1).some((_,i)=>taken.has(segments.slice(0,i+1).join("/")))?segments.join("-"):base;if(isFree(root))return root;for(let n=2;n<=99;n+=1){let candidate=`${root}-${n}`;if(isFree(candidate))return candidate}return`${root}-${taskId.slice(-6).toLowerCase()}`}function planExtraRepos(primary,inputs){if(inputs.length===0)return[];if(1+inputs.length>MULTI_REPO_CAP)throw new TooManyReposError(1+inputs.length,MULTI_REPO_CAP);if(isRemoteRepoKey(primary))throw new RemoteExtraUnsupportedError(primary);let seen=new Set([canonPath(primary)]),names=new Set([repoNameOf(primary)]);return inputs.map((input)=>{if(isRemoteRepoKey(input.repo))throw new RemoteExtraUnsupportedError(input.repo);let{repo}=normalizeMainRepo(input.repo);if(!isGitRepo(repo))throw new ExtraRepoNotGitError(input.repo);if(seen.has(canonPath(repo)))throw new RepoDuplicateError(repo);seen.add(canonPath(repo));let name=uniqueRepoName(repoNameOf(repo),names);names.add(name);let baseRef=input.baseRef?.trim();return{name,repo,branch:"",worktreePath:"",...baseRef?{baseRef}:{}}})}async function rollbackWorktree(backend,created){try{await backend.dispose({path:created.path,...created.fresh},created.fresh?{force:!0,deleteBranch:!0}:{force:!0})}catch(err){console.error(`[rove] ensureWorktree rollback failed for ${created.path}:`,err)}}async function extrasToMaterialise(worktrees,extras){let missing=[];for(let extra of extras??[])if(!extra.worktreePath||!await worktrees.pathExists(extra.worktreePath))missing.push(extra);return missing}function scaleProgress(onProgress,step,total){return onProgress&&((percent)=>onProgress(Math.floor((step+percent/100)/total*100)))}async function materialiseExtras(opts){let{worktrees,backend,slugs,task}=opts,callerNamed=task.branch!=="",created=[],picked=[],done=new Map,missing=await extrasToMaterialise(worktrees,task.extraRepos);try{for(let[index,extra]of missing.entries()){if(extra.worktreePath)await worktrees.pruneWorktrees(extra.repo);let names=await worktrees.listBranchNames(extra.repo),branch=extra.branch||(callerNamed||!names.includes(opts.branch)?opts.branch:uniqueBranchName(opts.branch,new Set(names),task.id)),slug=await slugs.allocate(extra.repo);picked.push({repo:extra.repo,slug});let info=await backend.materialize({repo:extra.repo,slug,branch,baseRef:extra.baseRef,onProgress:opts.progressFor(index)});created.push({path:info.path,...names.includes(branch)?{}:{fresh:{repo:extra.repo,branch}}}),done.set(extra.name,{...extra,branch,worktreePath:info.path})}}catch(err){for(let wt of created.reverse())await rollbackWorktree(backend,wt);for(let{repo,slug}of picked)slugs.cancel(repo,slug);throw err}return{extraRepos:(task.extraRepos??[]).map((e)=>done.get(e.name)??e),created,slugs:picked}}function nestingParent(store,id){let parent=store.get(id);if(!parent)throw new TaskNotFoundError(id);if(parent.deletion)throw new TaskDeletingError(String(parent.id));if(isRemoteRepoKey(parent.repo))throw new RemoteParentUnsupportedError(String(parent.id));return toTaskId(lineageRootId(store.list(),parent.id))}async function createTaskRow(deps,input){if(!input.repo)throw Error("createTask: repo is required");let extraRepos=planExtraRepos(normalizeMainRepo(input.repo).repo,input.extraRepos??[]),parentTaskId=input.parentTaskId?nestingParent(deps.store,input.parentTaskId):void 0,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}:{},...parentTaskId?{parentTaskId}:{},...input.cwdSubpath?{cwdSubpath:input.cwdSubpath}:{},...input.routine?{routine:input.routine}:{},...input.baseRef?.trim()?{baseRef:input.baseRef.trim()}:{},...extraRepos.length>0?{extraRepos}:{},...input.workspace?{workspace:input.workspace}:{},...worktreeName?{worktreeName}:{}})}async function openDirectoryTaskRow(deps,input){if(!input.dir)throw Error("openDirectoryTask: dir is required");let dir=canonPath(input.dir),title=(input.title?sanitizeTaskTitle(input.title):"")||(input.scratch?"":`${titleFromRepo(dir)}-${randomDirTaskSuffix()}`);return deps.store.create({repo:dir,title,branch:"",worktreePath:dir,status:"backlog",kind:"dir",...input.scratch?{scratch:!0}:{},...input.noProject?{noProject:!0}:{},...input.routine?{routine:input.routine}:{},...input.modelEffort?{modelEffort:input.modelEffort}:{},...input.model?.trim()?{model:input.model.trim()}:{},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)})}class BorrowedBackend{id="borrowed";capabilities=WORKSPACE_CAPABILITIES.borrowed;async materialize(spec){return{backend:this.id,path:spec.path??repoWorkingDir(spec.repo)}}async dispose(){}}import{execFile}from"child_process";import{promises as fs,statSync}from"fs";import path from"path";import{promisify}from"util";var run=promisify(execFile),CP_CHUNK=200;function cloneFlags(){if(process.platform==="darwin")return["-c","-R","-P"];if(process.platform==="linux")return["--reflink=always","-a"];return null}var cpClone=async(entries,to)=>{let flags=cloneFlags();if(!flags)throw new ForkUnsupportedError(`copy-on-write clones are not supported on ${process.platform}`);for(let i=0;i<entries.length;i+=CP_CHUNK)try{await run("cp",[...flags,...entries.slice(i,i+CP_CHUNK),`${to}${path.sep}`])}catch(err){let detail=err.stderr?.trim()||String(err);throw Error(`cloning the worktree failed: ${detail}`)}},probeCache=new Map;async function cloneOneFile(source,target){if(process.platform==="darwin")await run("/usr/bin/perl",["-e",CLONEFILEAT_PERL,source,target]);else if(process.platform==="linux")await run("cp",["--reflink=always",source,target]);else throw Error(`no clone primitive on ${process.platform}`)}var volumeProbe=(from,toDir)=>{let key=`${statSync(from).dev}:${statSync(toDir).dev}`,known=probeCache.get(key);if(!known)known=(async()=>{let probe=path.join(toDir,`.rove-clone-probe-${process.pid}`);try{return await cloneOneFile(path.join(from,".git"),probe),!0}catch{return!1}finally{await fs.rm(probe,{force:!0})}})(),probeCache.set(key,known);return known};async function git2(cwd,args){let{stdout}=await run("git",[...args],{cwd,maxBuffer:67108864});return stdout.trim()}class CowCloneBackend{plain;id="cow-clone";capabilities=WORKSPACE_CAPABILITIES["cow-clone"];probe;cloneEntries;constructor(plain,deps={}){this.plain=plain;this.probe=deps.probe??volumeProbe,this.cloneEntries=deps.cloneEntries??cpClone}async materialize(spec){let parent=spec.forkFrom;if(!parent)return{...await this.plain.materialize(spec),backend:this.id};if(isRemoteRepoKey(spec.repo))throw new ForkUnsupportedError("a remote project's worktree cannot be cloned");let target=worktreePathFor(spec.repo,spec.slug),root=path.dirname(target);if(await fs.mkdir(root,{recursive:!0}),!await this.probe(parent,root))throw new ForkUnsupportedError(`${parent} and ${root} are not on one volume that can clone files (APFS, btrfs, XFS with reflink); the fork would have to copy the whole tree`);let head=await git2(parent,["rev-parse","HEAD"]);await git2(spec.repo,["worktree","add","--no-checkout","-b",spec.branch,target,head]);try{let entries=(await fs.readdir(parent)).filter((name)=>name!==".git").map((name)=>path.join(parent,name));await this.cloneEntries(entries,target),await this.carryIndex(parent,target)}catch(err){throw await this.discard(spec.repo,target,spec.branch),err}return{backend:this.id,path:target}}async carryIndex(parent,target){let indexOf=(dir)=>git2(dir,["rev-parse","--path-format=absolute","--git-path","index"]);try{await fs.copyFile(await indexOf(parent),await indexOf(target)),await git2(target,["update-index","-q","--refresh"])}catch{await git2(target,["reset","-q"])}}async discard(repo,target,branch){await git2(repo,["worktree","remove","--force",target]).catch(()=>{}),await fs.rm(target,{recursive:!0,force:!0}),await git2(repo,["worktree","prune"]).catch(()=>{}),await git2(repo,["branch","-D",branch]).catch(()=>{})}dispose(target,opts){return this.plain.dispose(target,opts)}}class GitWorktreeBackend{worktrees;id="git-worktree";capabilities=WORKSPACE_CAPABILITIES["git-worktree"];constructor(worktrees){this.worktrees=worktrees}async materialize(spec){let info=await this.worktrees.createForTask({repo:spec.repo,slug:spec.slug,branch:spec.branch,baseRef:spec.baseRef,onProgress:spec.onProgress});return{backend:this.id,path:info.path}}async dispose(target,opts){await this.worktrees.remove(target.path,{...opts,repo:target.repo,branch:target.branch})}}import{execFile as execFile2}from"child_process";import{createHash}from"crypto";import{promises as fs2,readFileSync}from"fs";import os from"os";import path2 from"path";import{promisify as promisify2}from"util";var LAYERFS_CONFIG_KEY="experimental.layerfs",STATE_FILE=".rove-layerfs.json",SANDBOX_USER="501:20",SANDBOX_HOME="/tmp/rove-home",KILL_TAGGED=`for p in /proc/[0-9]*; do tr '\\0' '\\n' < $p/environ 2>/dev/null | grep -qx "$1" && kill -KILL \${p#/proc/}; done; true`,KILL_UNDER='for p in /proc/[0-9]*; do case $(readlink $p/cwd) in "$1"|"$1"/*) kill -KILL ${p#/proc/};; esac; done; sleep 0.2',execRun=async(file,args)=>{try{let{stdout}=await promisify2(execFile2)(file,[...args],{maxBuffer:67108864});return stdout}catch(err){let e=err;throw Error((e.stderr?.trim()||e.stdout?.trim()||e.message).slice(0,2000))}};function parseLayerfsEnv(text){let env={};for(let line of text.split(`
2
+ import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-zr058kbe.js";import{readLastActiveTaskId,writeLastActiveTaskId}from"./chunk-c1dz3qg3.js";import{CLONEFILEAT_PERL,GitWorktreeManager,defaultExecDeps,git,isDirtyOutput,parseDirtyPaths}from"./chunk-3x5g06mw.js";import{LAUNCH_PREFIX_FILE}from"./chunk-4dt1gfb3.js";import{PLACEHOLDER_TASK_TITLE,isPlaceholderDerivedBranch,sanitizeTaskTitle}from"./chunk-2xsxcdp6.js";import{CannotDeleteMainTaskError,DirtyWorktreeError,EmptyBranchDirtyWorktreeError,EmptyBranchError,ExtraRepoNotGitError,ForkUnsupportedError,GitCommandFailedError,IllegalTransitionError,InvalidWorktreeNameError,LandConflictError,MainCheckoutDirtyError,MissingRefError,MoveRefusedError,NotAGitRepoError,NotALinkedRepoError,REMOTE_PARENT_UNSUPPORTED_CODE,RemoteExtraUnsupportedError,RemoteParentUnsupportedError,ReparentRefusedError,RepoDuplicateError,TaskDeletingError,TaskNotFoundError,TooManyReposError,WorktreeNameTakenError,WorktreeRemoveFailedError,canonicalize,listWorktreeDirNames,worktreePathFor}from"./chunk-1vxtd8rh.js";import{detectLanguage}from"./chunk-hpay0ax8.js";import{resolvePreferredVendor}from"./chunk-9rj2fx6v.js";import{addSavedRepo,getPersistedString,getSavedRepos,isGitRepo,isRemoteRepoKey,removeSavedRepo,resolveMainRepoRoot,resolveRepoRoot}from"./chunk-rfp0ayra.js";import{READ_ONLY_GIT_ENV}from"./chunk-6xppe9bj.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{projectRejection,rejectionReason}from"./chunk-7mwvvj46.js";import{createStateCell}from"./chunk-cmp64q4j.js";import{MULTI_REPO_CAP,SESSION_PR_CAP,WORKSPACE_CAPABILITIES,applyTodoOps,checkNotes,childrenOf,gitRepoOf,lineageRootId,pickRepos,repoNameOf,subtreeIds,taskCwd,taskRepos,taskWorktreePaths,uniqueRepoName,workspaceBackendId,workspaceCapabilities}from"./chunk-x1jxxmtc.js";import{DEFAULT_TASK_VENDOR,toTaskId}from"./chunk-xy8be792.js";import{pathIdentity,pathWithin,samePath}from"./chunk-pn5ygqn6.js";class WorkspaceCheckpoints{store;worktrees;workspaces;requireTask;constructor(store,worktrees,workspaces,requireTask){this.store=store;this.worktrees=worktrees;this.workspaces=workspaces;this.requireTask=requireTask}workspaceOwner(id){let task=this.requireTask(id);return(task.sharesWorkspaceOf?this.store.get(task.sharesWorkspaceOf):void 0)??task}checkpointScope(id){let owner=this.workspaceOwner(id),sharers=this.store.list().filter((t)=>t.sharesWorkspaceOf===owner.id&&!t.deletion);return{ownerId:String(owner.id),sharerIds:[String(owner.id),...sharers.map((t)=>String(t.id))]}}canCheckpoint(id){if(!this.store.get(id))return!1;let owner=this.workspaceOwner(id);return workspaceCapabilities(owner).checkpoint&&!owner.deletion&&owner.worktreePath!==""}async target(id){let owner=this.workspaceOwner(id),own=this.canCheckpoint(id)?this.workspaces.get(workspaceBackendId(owner)).checkpoints:void 0,dir=owner.worktreePath;if(!this.canCheckpoint(id)||!await this.worktrees.pathExists(own?dir:`${dir}/.git`))throw Error(`NOT_CHECKPOINTABLE: ${owner.kind==="task"?"the task has no workspace on disk":`a ${owner.kind} task works in your own checkout`}`);let ownerId=String(owner.id);return{ownerId,dir,via:own??{take:(d,opts)=>this.worktrees.takeCheckpoint(d,ownerId,opts),list:(d)=>this.worktrees.listCheckpoints(d,ownerId),rewind:(d,n)=>this.worktrees.rewindToCheckpoint(d,ownerId,n)}}}async takeCheckpoint(id,opts){let{dir,via}=await this.target(id);return via.take(dir,opts)}async listCheckpoints(id){let{dir,via}=await this.target(id);return via.list(dir)}async rewindToCheckpoint(id,n){let{dir,via}=await this.target(id);return via.rewind(dir,n)}async exportBranch(id){let owner=this.workspaceOwner(id),backend=this.workspaces.get(workspaceBackendId(owner));if(!backend.exportBranch||!owner.worktreePath)throw Error("EXPORT_UNSUPPORTED: the task's branch is already in its repo (or it has no workspace yet)");return backend.exportBranch({path:owner.worktreePath,repo:gitRepoOf(owner),branch:owner.branch})}}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"]);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){let slug="";for(let token of tokens){let candidate=slug?`${slug}-${token}`:token;if(candidate.length>32)return slug||token.slice(0,32);slug=candidate}return slug}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){let dirs=new Set;for(let name of taken)for(let i=name.indexOf("/");i>0;i=name.indexOf("/",i+1))dirs.add(name.slice(0,i));let isFree=(name)=>!taken.has(name)&&!dirs.has(name),segments=base.split("/"),root=segments.slice(0,-1).some((_,i)=>taken.has(segments.slice(0,i+1).join("/")))?segments.join("-"):base;if(isFree(root))return root;for(let n=2;n<=99;n+=1){let candidate=`${root}-${n}`;if(isFree(candidate))return candidate}return`${root}-${taskId.slice(-6).toLowerCase()}`}function planExtraRepos(primary,inputs){if(inputs.length===0)return[];if(1+inputs.length>MULTI_REPO_CAP)throw new TooManyReposError(1+inputs.length,MULTI_REPO_CAP);if(isRemoteRepoKey(primary))throw new RemoteExtraUnsupportedError(primary);let seen=new Set([canonPath(primary)]),names=new Set([repoNameOf(primary)]);return inputs.map((input)=>{if(isRemoteRepoKey(input.repo))throw new RemoteExtraUnsupportedError(input.repo);let{repo}=normalizeMainRepo(input.repo);if(!isGitRepo(repo))throw new ExtraRepoNotGitError(input.repo);if(seen.has(canonPath(repo)))throw new RepoDuplicateError(repo);seen.add(canonPath(repo));let name=uniqueRepoName(repoNameOf(repo),names);names.add(name);let baseRef=input.baseRef?.trim();return{name,repo,branch:"",worktreePath:"",...baseRef?{baseRef}:{}}})}async function rollbackWorktree(backend,created){try{await backend.dispose({path:created.path,...created.fresh},created.fresh?{force:!0,deleteBranch:!0}:{force:!0})}catch(err){console.error(`[rove] ensureWorktree rollback failed for ${created.path}:`,err)}}async function extrasToMaterialise(worktrees,extras){let missing=[];for(let extra of extras??[])if(!extra.worktreePath||!await worktrees.pathExists(extra.worktreePath))missing.push(extra);return missing}function scaleProgress(onProgress,step,total){return onProgress&&((percent)=>onProgress(Math.floor((step+percent/100)/total*100)))}async function materialiseExtras(opts){let{worktrees,backend,slugs,task}=opts,callerNamed=task.branch!=="",created=[],picked=[],done=new Map,missing=await extrasToMaterialise(worktrees,task.extraRepos);try{for(let[index,extra]of missing.entries()){if(extra.worktreePath)await worktrees.pruneWorktrees(extra.repo);let names=await worktrees.listBranchNames(extra.repo),branch=extra.branch||(callerNamed||!names.includes(opts.branch)?opts.branch:uniqueBranchName(opts.branch,new Set(names),task.id)),slug=await slugs.allocate(extra.repo);picked.push({repo:extra.repo,slug});let info=await backend.materialize({repo:extra.repo,slug,branch,baseRef:extra.baseRef,onProgress:opts.progressFor(index)});created.push({path:info.path,...names.includes(branch)?{}:{fresh:{repo:extra.repo,branch}}}),done.set(extra.name,{...extra,branch,worktreePath:info.path})}}catch(err){for(let wt of created.reverse())await rollbackWorktree(backend,wt);for(let{repo,slug}of picked)slugs.cancel(repo,slug);throw err}return{extraRepos:(task.extraRepos??[]).map((e)=>done.get(e.name)??e),created,slugs:picked}}function nestingParent(store,id){let parent=store.get(id);if(!parent)throw new TaskNotFoundError(id);if(parent.deletion)throw new TaskDeletingError(String(parent.id));if(isRemoteRepoKey(parent.repo))throw new RemoteParentUnsupportedError(String(parent.id));return toTaskId(lineageRootId(store.list(),parent.id))}async function createTaskRow(deps,input){if(!input.repo)throw Error("createTask: repo is required");let extraRepos=planExtraRepos(normalizeMainRepo(input.repo).repo,input.extraRepos??[]),parentTaskId=input.parentTaskId?nestingParent(deps.store,input.parentTaskId):void 0,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}:{},...parentTaskId?{parentTaskId}:{},...input.cwdSubpath?{cwdSubpath:input.cwdSubpath}:{},...input.routine?{routine:input.routine}:{},...input.baseRef?.trim()?{baseRef:input.baseRef.trim()}:{},...extraRepos.length>0?{extraRepos}:{},...input.workspace?{workspace:input.workspace}:{},...worktreeName?{worktreeName}:{}})}async function openDirectoryTaskRow(deps,input){if(!input.dir)throw Error("openDirectoryTask: dir is required");let dir=canonPath(input.dir),title=(input.title?sanitizeTaskTitle(input.title):"")||(input.scratch?"":`${titleFromRepo(dir)}-${randomDirTaskSuffix()}`);return deps.store.create({repo:dir,title,branch:"",worktreePath:dir,status:"backlog",kind:"dir",...input.scratch?{scratch:!0}:{},...input.noProject?{noProject:!0}:{},...input.routine?{routine:input.routine}:{},...input.modelEffort?{modelEffort:input.modelEffort}:{},...input.model?.trim()?{model:input.model.trim()}:{},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)})}class BorrowedBackend{id="borrowed";capabilities=WORKSPACE_CAPABILITIES.borrowed;async materialize(spec){return{backend:this.id,path:spec.path??repoWorkingDir(spec.repo)}}async dispose(){}}import{execFile}from"child_process";import{promises as fs,statSync}from"fs";import path from"path";import{promisify}from"util";var run=promisify(execFile),CP_CHUNK=200;function cloneFlags(){if(process.platform==="darwin")return["-c","-R","-P"];if(process.platform==="linux")return["--reflink=always","-a"];return null}var cpClone=async(entries,to)=>{let flags=cloneFlags();if(!flags)throw new ForkUnsupportedError(`copy-on-write clones are not supported on ${process.platform}`);for(let i=0;i<entries.length;i+=CP_CHUNK)try{await run("cp",[...flags,...entries.slice(i,i+CP_CHUNK),`${to}${path.sep}`])}catch(err){let detail=err.stderr?.trim()||String(err);throw Error(`cloning the worktree failed: ${detail}`)}},probeCache=new Map;async function cloneOneFile(source,target){if(process.platform==="darwin")await run("/usr/bin/perl",["-e",CLONEFILEAT_PERL,source,target]);else if(process.platform==="linux")await run("cp",["--reflink=always",source,target]);else throw Error(`no clone primitive on ${process.platform}`)}var volumeProbe=(from,toDir)=>{let key=`${statSync(from).dev}:${statSync(toDir).dev}`,known=probeCache.get(key);if(!known)known=(async()=>{let probe=path.join(toDir,`.rove-clone-probe-${process.pid}`);try{return await cloneOneFile(path.join(from,".git"),probe),!0}catch{return!1}finally{await fs.rm(probe,{force:!0})}})(),probeCache.set(key,known);return known};async function git2(cwd,args){let{stdout}=await run("git",[...args],{cwd,maxBuffer:67108864});return stdout.trim()}class CowCloneBackend{plain;id="cow-clone";capabilities=WORKSPACE_CAPABILITIES["cow-clone"];probe;cloneEntries;constructor(plain,deps={}){this.plain=plain;this.probe=deps.probe??volumeProbe,this.cloneEntries=deps.cloneEntries??cpClone}async materialize(spec){let parent=spec.forkFrom;if(!parent)return{...await this.plain.materialize(spec),backend:this.id};if(isRemoteRepoKey(spec.repo))throw new ForkUnsupportedError("a remote project's worktree cannot be cloned");let target=worktreePathFor(spec.repo,spec.slug),root=path.dirname(target);if(await fs.mkdir(root,{recursive:!0}),!await this.probe(parent,root))throw new ForkUnsupportedError(`${parent} and ${root} are not on one volume that can clone files (APFS, btrfs, XFS with reflink); the fork would have to copy the whole tree`);let head=await git2(parent,["rev-parse","HEAD"]);await git2(spec.repo,["worktree","add","--no-checkout","-b",spec.branch,target,head]);try{let entries=(await fs.readdir(parent)).filter((name)=>name!==".git").map((name)=>path.join(parent,name));await this.cloneEntries(entries,target),await this.carryIndex(parent,target)}catch(err){throw await this.discard(spec.repo,target,spec.branch),err}return{backend:this.id,path:target}}async carryIndex(parent,target){let indexOf=(dir)=>git2(dir,["rev-parse","--path-format=absolute","--git-path","index"]);try{await fs.copyFile(await indexOf(parent),await indexOf(target)),await git2(target,["update-index","-q","--refresh"])}catch{await git2(target,["reset","-q"])}}async discard(repo,target,branch){await git2(repo,["worktree","remove","--force",target]).catch(()=>{}),await fs.rm(target,{recursive:!0,force:!0}),await git2(repo,["worktree","prune"]).catch(()=>{}),await git2(repo,["branch","-D",branch]).catch(()=>{})}dispose(target,opts){return this.plain.dispose(target,opts)}}class GitWorktreeBackend{worktrees;id="git-worktree";capabilities=WORKSPACE_CAPABILITIES["git-worktree"];constructor(worktrees){this.worktrees=worktrees}async materialize(spec){let info=await this.worktrees.createForTask({repo:spec.repo,slug:spec.slug,branch:spec.branch,baseRef:spec.baseRef,onProgress:spec.onProgress});return{backend:this.id,path:info.path}}async dispose(target,opts){await this.worktrees.remove(target.path,{...opts,repo:target.repo,branch:target.branch})}}import{execFile as execFile2}from"child_process";import{createHash}from"crypto";import{promises as fs2,readFileSync}from"fs";import os from"os";import path2 from"path";import{promisify as promisify2}from"util";var LAYERFS_CONFIG_KEY="experimental.layerfs",STATE_FILE=".rove-layerfs.json",SANDBOX_USER="501:20",SANDBOX_HOME="/tmp/rove-home",KILL_TAGGED=`for p in /proc/[0-9]*; do tr '\\0' '\\n' < $p/environ 2>/dev/null | grep -qx "$1" && kill -KILL \${p#/proc/}; done; true`,KILL_UNDER='for p in /proc/[0-9]*; do case $(readlink $p/cwd) in "$1"|"$1"/*) kill -KILL ${p#/proc/};; esac; done; sleep 0.2',execRun=async(file,args)=>{try{let{stdout}=await promisify2(execFile2)(file,[...args],{maxBuffer:67108864});return stdout}catch(err){let e=err;throw Error((e.stderr?.trim()||e.stdout?.trim()||e.message).slice(0,2000))}};function parseLayerfsEnv(text){let env={};for(let line of text.split(`
3
3
  `)){let m=/^\s*(?:export\s+)?([A-Z_][A-Z0-9_]*)=(.*)$/.exec(line);if(m)env[m[1]]=m[2].trim().replace(/^(["'])(.*)\1$/,"$2")}return env}class LayerfsBackend{id="layerfs";capabilities=WORKSPACE_CAPABILITIES.layerfs;run;configPath;platform;rootChecked=!1;constructor(deps={}){this.run=deps.run??execRun,this.configPath=deps.configPath??(()=>getPersistedString(LAYERFS_CONFIG_KEY)),this.platform=deps.platform??process.platform}async preflight(){this.env(),await this.requireRoot()}env(){if(this.platform!=="linux")throw unavailable(`it runs on Linux Runners only, not ${this.platform}`);let file=this.configPath();if(!file)throw unavailable(`set ${LAYERFS_CONFIG_KEY} in state.json to a LayerFS env file`);let env;try{env=parseLayerfsEnv(readFileSync(file,"utf8"))}catch(err){throw unavailable(`cannot read ${file}: ${err.message}`)}for(let key of["LAYERFS_CLI","LAYERFS_NODE","LAYERFS_HOME","LAYERFS_STORE_PATH","LAYERFS_IMAGE"])if(!env[key])throw unavailable(`${file} does not set ${key}`);return env}async requireRoot(){if(this.rootChecked)return;try{await this.run("sudo",["-n","true"])}catch{throw Error("LAYERFS_NEEDS_ROOT: LayerFS Store calls run as root, and `sudo -n` cannot (configure passwordless sudo for this user)")}this.rootChecked=!0}async lfs(project,...args){let env=this.env();await this.requireRoot();let pass=Object.entries(env).filter(([k])=>k!=="LAYERFS_CLI"&&k!=="LAYERFS_NODE").map(([k,v])=>`${k}=${v}`),out=await this.run("sudo",["-n","env",...pass,`LAYERFS_PROJECT=${project}`,env.LAYERFS_NODE,env.LAYERFS_CLI,...args]);return JSON.parse(out)}docker(...args){return this.run("docker",args)}inSandbox(s,dir,...argv){return this.docker("exec","-u",SANDBOX_USER,"-w",dir,"-e",`HOME=${SANDBOX_HOME}`,s.container,...argv)}async ensureProject(repo){let project=`rove-${createHash("sha1").update(repo).digest("hex").slice(0,12)}`;try{await this.lfs(project,"project","list_branches","--page-size","1")}catch{await this.lfs(project,"init",project,repo,"--timeout","1800000")}return project}async materialize(spec){if(spec.forkFrom||spec.path)throw unavailable("a layerfs task cannot be forked or borrow a directory");this.env();let dir=worktreePathFor(spec.repo,spec.slug),project=await this.ensureProject(spec.repo),branch=`${spec.slug}-${Date.now().toString(36)}`;await this.lfs(project,"branch","fork",branch);let{sandbox}=await this.lfs(project,"sandbox","create"),s={project,sandbox,ws:"",container:"",branch,gitBase:"",checkpoints:[]};try{s.container=await this.containerOf(project,sandbox),await this.mount(s,dir),await this.inSandbox(s,dir,"git","checkout","-q","-b",spec.branch,...spec.baseRef?[spec.baseRef]:[]),s.gitBase=(await this.inSandbox(s,dir,"git","rev-parse","HEAD")).trim();let reap=["docker","exec","-u",SANDBOX_USER,s.container,"sh","-c",KILL_TAGGED,"sh","ROVE_LAUNCH={launch}"];await fs2.writeFile(path2.join(dir,LAUNCH_PREFIX_FILE),JSON.stringify({prefix:this.launchPrefix(s,dir),reap})),await this.save(dir,s)}catch(err){throw await this.teardown(s,dir,!0).catch(()=>{}),err}return{backend:this.id,path:dir,ref:`${project}:${branch}`}}launchPrefix(s,dir){let env=["-e",`HOME=${SANDBOX_HOME}`,"-e","ROVE_LAUNCH={launch}","-e","TERM","-e","COLUMNS","-e","LINES"];return["docker","exec","-it","-u",SANDBOX_USER,"-w",dir,...env,s.container]}async containerOf(project,sandbox){let id=(await this.docker("ps","-q","--filter",`label=layerfs.project=${project}`,"--filter",`label=layerfs.sandbox=${sandbox}`)).trim();if(!id||id.includes(`
4
4
  `))throw Error(`no single container for LayerFS sandbox ${project}/${sandbox}`);return id}async mount(s,dir){s.ws=(await this.lfs(s.project,"workspace","mount",s.sandbox,s.branch)).ws,await fs2.mkdir(dir,{recursive:!0}),await this.bind(s,dir)}async bind(s,dir){let mountPath=s.ws.slice(s.ws.indexOf(":")+1),script=`mkdir -p "$1" ${SANDBOX_HOME} && chown ${SANDBOX_USER} ${SANDBOX_HOME} && mount --bind "$2" "$1"`;await this.docker("exec","-u","0",s.container,"sh","-c",script,"sh",dir,mountPath)}async unbind(s,dir){try{await this.docker("exec","-u","0",s.container,"umount",dir)}catch(err){if(!/busy/i.test(err.message))throw err;throw Error(`WORKSPACE_BUSY: a process still runs in ${dir} inside the sandbox; close the task's terminals first`)}}async unmount(s,dir,discard){await this.unbind(s,dir);try{await this.lfs(s.project,"workspace","unmount",s.ws,...discard?["--discard"]:[])}catch(err){if(await this.bind(s,dir),!/"code":"Dirty"/.test(err.message))throw err;throw Error(`WORKSPACE_DIRTY: LayerFS has uncommitted changes in ${dir}; checkpoint first, or force`)}}async teardown(s,dir,discard){if(s.ws){if(s.container)await this.docker("exec","-u",SANDBOX_USER,s.container,"sh","-c",KILL_UNDER,"sh",dir);await this.unmount(s,dir,discard)}await this.lfs(s.project,"sandbox","close",s.sandbox),await fs2.rm(path2.join(dir,STATE_FILE),{force:!0}),await fs2.rm(path2.join(dir,LAUNCH_PREFIX_FILE),{force:!0}),await fs2.rmdir(dir).catch(()=>{})}async dispose(target,opts){let s=await this.load(target.path).catch(()=>{return});if(!s){await fs2.rm(path2.join(target.path,LAUNCH_PREFIX_FILE),{force:!0}),await fs2.rmdir(target.path).catch(()=>{});return}await this.teardown(s,target.path,opts.force===!0)}async dirtyPaths(dir){let s=await this.load(dir).catch(()=>{return});if(!s?.ws)return[];let{items}=await this.lfs(s.project,"sandbox","list_workspaces",s.sandbox);return items.find((w)=>`${s.sandbox}:${w.path}`===s.ws)?.changed?["(changes since the last checkpoint, inside the LayerFS sandbox)"]:[]}checkpoints={take:(dir,opts)=>this.take(dir,opts?.tabId),list:async(dir)=>(await this.load(dir)).checkpoints,rewind:async(dir,n)=>{let target=(await this.load(dir)).checkpoints.find((c)=>c.n===n);if(!target)throw Error(`CHECKPOINT_NOT_FOUND: checkpoint ${n} does not exist`);let undo=(await this.take(dir)).checkpoint,after=await this.load(dir),fork=`${after.branch.replace(/-r[0-9a-z]+$/,"")}-r${Date.now().toString(36)}`;return await this.lfs(after.project,"branch","fork",fork,target.commit),await this.unmount(after,dir,!0),after.branch=fork,await this.mount(after,dir),await this.save(dir,after),{target,undo,uncaptured:[]}}};async take(dir,tabId){let s=await this.load(dir),latest=s.checkpoints.at(-1),reply=await this.lfs(s.project,"workspace","commit",s.ws,"-m","rove checkpoint",...latest?[]:["--force"]);if(latest&&reply.kind==="UpToDate")return{created:!1,checkpoint:latest};let checkpoint={n:(latest?.n??0)+1,ref:`layerfs:${s.project}:${s.branch}`,commit:reply.head,tree:reply.commit?.root??reply.root??reply.head,at:new Date().toISOString(),...tabId?{tabId}:{}};return s.checkpoints.push(checkpoint),await this.save(dir,s),{created:!0,checkpoint,uncaptured:[]}}async exportBranch(target){let s=await this.load(target.path),inner=`/tmp/rove-export-${process.pid}.bundle`;await this.inSandbox(s,target.path,"git","bundle","create","-q",inner,target.branch,`^${s.gitBase}`);let local=path2.join(os.tmpdir(),`rove-layerfs-${process.pid}-${Date.now()}.bundle`);try{await this.docker("cp",`${s.container}:${inner}`,local),await this.run("git",["-C",target.repo,"fetch","-q",local,`${target.branch}:refs/heads/${target.branch}`]);let commit=(await this.run("git",["-C",target.repo,"rev-parse",target.branch])).trim();return{branch:target.branch,commit}}finally{await fs2.rm(local,{force:!0})}}async load(dir){return JSON.parse(await fs2.readFile(path2.join(dir,STATE_FILE),"utf8"))}save(dir,s){return fs2.writeFile(path2.join(dir,STATE_FILE),`${JSON.stringify(s,null,2)}
5
5
  `)}}function unavailable(why){return Error(`LAYERFS_UNAVAILABLE: the layerfs workspace backend is unavailable: ${why}`)}class WorkspaceRegistry{backends=new Map;constructor(backends){for(let backend of backends)this.backends.set(backend.id,backend)}get(id){let backend=this.backends.get(id);if(!backend)throw Error(`workspace backend '${id}' is not available in this build`);return backend}}function createWorkspaceRegistry(worktrees,cowClone){let plain=new GitWorktreeBackend(worktrees);return new WorkspaceRegistry([plain,new BorrowedBackend,new CowCloneBackend(plain,cowClone),new LayerfsBackend])}async function createOrForkTask(deps,input){if(input.workspace)await deps.workspaces.get(input.workspace.backend).preflight?.();let createRow=(row)=>createTaskRow(deps,row),{forkFrom}=input;return forkFrom?forkTaskRow({...deps,createRow},{...input,forkFrom}):createRow(input)}async function forkTaskRow(deps,input){let parent=deps.store.get(input.forkFrom);if(!parent)throw new TaskNotFoundError(input.forkFrom);if(parent.deletion)throw new TaskDeletingError(String(parent.id));if(!workspaceCapabilities(parent).ownsDirectory)throw new ForkUnsupportedError("a main or directory task has no Rove-created worktree to clone");if(isRemoteRepoKey(parent.repo))throw new ForkUnsupportedError("a remote project's worktree cannot be cloned");if(parent.extraRepos?.length)throw new ForkUnsupportedError("a multi-repo task cannot be forked: only its primary repo would be cloned");let parentPath=await deps.ensureWorktree(parent.id),baseRef=git(["rev-parse","HEAD"],{cwd:parentPath,readOnly:!0}).stdout.trim(),child=await deps.createRow({...input,repo:gitRepoOf(parent),title:input.title??`${parent.title} (fork)`,baseRef,workspace:{backend:"cow-clone",ref:String(parent.id)},...parent.cwdSubpath?{cwdSubpath:parent.cwdSubpath}:{}});if(parent.gitRepo)await deps.store.update(child.id,{repo:parent.repo,gitRepo:parent.gitRepo});try{await deps.cloneInto(child,parentPath)}catch(err){throw await discard(deps,child).catch((cleanup)=>console.error(`[rove] fork rollback failed for ${child.id}:`,cleanup)),await deps.store.remove(child.id),err}return deps.store.get(child.id)??child}async function discard(deps,child){let row=deps.store.get(child.id);if(!row?.worktreePath)return;await deps.workspaces.get(workspaceBackendId(row)).dispose({path:row.worktreePath,repo:gitRepoOf(row),branch:row.branch},{force:!0,deleteBranch:!0})}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(gitRepoOf(task),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(gitRepoOf(task),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)}}function assertOwnsBranch(task){if(workspaceCapabilities(task).ownsBranch)return;throw Error(task.kind==="main"?"landTask: a main task has no branch to land":"landTask: a directory task has no Rove-managed branch to land")}async function landTaskWithCleanup(task,opts,deps){assertOwnsBranch(task);let result=await landTask(task,{strategy:opts.strategy});return finishLanded(task,result,opts,deps)}async function finishLanded(task,result,opts,deps){let 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(gitRepoOf(task),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(gitRepoOf(task))))return{removed:!1,reason:"refusing to remove the base checkout"};if(deps.sharesWorktree?.(task))return{removed:!1,reason:`kept ${worktreePath}: other tasks still run in this directory`};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(`
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{defaultFixRuntime}from"./chunk-am5cpb9n.js";import{INBOUND_CLASSES,deniedClasses,setInbound}from"./chunk-qzhfs668.js";import"./chunk-txvjg1g9.js";import"./chunk-k2j0tg1h.js";import"./chunk-kdnk8m5j.js";import"./chunk-qcjkactr.js";import"./chunk-rjfdzjhj.js";import"./chunk-zpxpwgds.js";import"./chunk-agvtzads.js";import"./chunk-pm91e38v.js";import"./chunk-2xsxcdp6.js";import"./chunk-17e2tgyg.js";import"./chunk-1vxtd8rh.js";import"./chunk-q8ffd1pc.js";import"./chunk-4hestsjp.js";import"./chunk-qgrg9a5n.js";import"./chunk-2bgmby1d.js";import"./chunk-n0rdn2fn.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import"./chunk-2pfh3zm0.js";import{primaryCheckouts,repoIdOf,repoIdentity,setPrimaryCheckout}from"./chunk-p11emdb2.js";import{addMachine,defaultMachineAlias,discoverMachine,duplicateAliasOf,getMachine,isValidMachineAlias,isWindowsMachine,learnedFrom,listMachines,machineSocketDir,machineSshArgs,parseSshTarget,readMachines,remoteRove,removeMachine,sanitizeAlias,setMachineIdentity,sshServerIsWindows,sshTargetOf,updateMachine,windowsAuthorizeKeySteps}from"./chunk-vytrhm50.js";import"./chunk-vp29jgbt.js";import"./chunk-gq36nzg8.js";import"./chunk-sq6zj3fb.js";import"./chunk-qkehg2c1.js";import"./chunk-s1xn6wav.js";import"./chunk-nv8eyjep.js";import"./chunk-z43e08kw.js";import"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import"./chunk-f7egph8g.js";import"./chunk-rxqdw6s5.js";import"./chunk-kxp04jnp.js";import"./chunk-3hxm56h6.js";import"./chunk-qecygh3f.js";import"./chunk-rjq38twt.js";import"./chunk-r5j8fycq.js";import"./chunk-xfgqae9t.js";import"./chunk-j1z9kgyd.js";import"./chunk-g9ba25q5.js";import"./chunk-ggnq2vvk.js";import"./chunk-hpay0ax8.js";import"./chunk-catrr0z3.js";import"./chunk-mdc7b01e.js";import"./chunk-tn9gtf18.js";import"./chunk-895yqjjz.js";import"./chunk-sak1tphp.js";import{shQuote}from"./chunk-y1xnjx8x.js";import"./chunk-e58kj4gm.js";import"./chunk-0a65j1zj.js";import"./chunk-bcyex84w.js";import"./chunk-5rgrde6b.js";import"./chunk-4gjvmfa9.js";import"./chunk-2tfnscxk.js";import"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-etfh8f4z.js";import"./chunk-9rj2fx6v.js";import"./chunk-rfp0ayra.js";import"./chunk-t7j8g9f6.js";import"./chunk-dmzg9zdc.js";import"./chunk-40dgv828.js";import"./chunk-kg9kmwt9.js";import"./chunk-6xppe9bj.js";import{CURRENT_VERSION}from"./chunk-2wrt80ft.js";import{argvHasFlag}from"./chunk-zsfyj36g.js";import"./chunk-2r1fgng9.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import{loadStateFile}from"./chunk-32j6y5d1.js";import"./chunk-nqwza8b0.js";import"./chunk-ve76p2mx.js";import"./chunk-cmp64q4j.js";import"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import"./chunk-7bakcyes.js";import"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import"./chunk-x1jxxmtc.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import{homeDir}from"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import{__require}from"./chunk-91sykzqq.js";import{spawn}from"child_process";import{appendFileSync,chmodSync,existsSync,mkdirSync}from"fs";import{homedir}from"os";import{dirname}from"path";function parseSshG(stdout,home=homedir()){let values=new Map;for(let line of stdout.split(`
2
+ import{defaultFixRuntime}from"./chunk-4vkrv4eb.js";import{INBOUND_CLASSES,deniedClasses,setInbound}from"./chunk-jar50zcp.js";import"./chunk-btxfcc77.js";import"./chunk-tgv90744.js";import"./chunk-kdnk8m5j.js";import"./chunk-qcjkactr.js";import"./chunk-rjfdzjhj.js";import"./chunk-zpxpwgds.js";import"./chunk-agvtzads.js";import"./chunk-pm91e38v.js";import"./chunk-2xsxcdp6.js";import"./chunk-17e2tgyg.js";import"./chunk-1vxtd8rh.js";import"./chunk-q8ffd1pc.js";import"./chunk-4hestsjp.js";import"./chunk-qgrg9a5n.js";import"./chunk-2bgmby1d.js";import"./chunk-n0rdn2fn.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import"./chunk-01tghgf3.js";import{primaryCheckouts,repoIdOf,repoIdentity,setPrimaryCheckout}from"./chunk-y07cp9mb.js";import{addMachine,defaultMachineAlias,discoverMachine,duplicateAliasOf,getMachine,isValidMachineAlias,isWindowsMachine,learnedFrom,listMachines,machineSocketDir,machineSshArgs,parseSshTarget,readMachines,remoteRove,removeMachine,sanitizeAlias,setMachineIdentity,sshServerIsWindows,sshTargetOf,updateMachine,windowsAuthorizeKeySteps}from"./chunk-vytrhm50.js";import"./chunk-vp29jgbt.js";import"./chunk-gq36nzg8.js";import"./chunk-sq6zj3fb.js";import"./chunk-qkehg2c1.js";import"./chunk-w6ft4djp.js";import"./chunk-vx44yxra.js";import"./chunk-z43e08kw.js";import"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import"./chunk-gzkes5bw.js";import"./chunk-rxqdw6s5.js";import"./chunk-8ng1756g.js";import"./chunk-kxp04jnp.js";import"./chunk-1a57ejnh.js";import"./chunk-qecygh3f.js";import"./chunk-rjq38twt.js";import"./chunk-r5j8fycq.js";import"./chunk-xfgqae9t.js";import"./chunk-j1z9kgyd.js";import"./chunk-g9ba25q5.js";import"./chunk-ggnq2vvk.js";import"./chunk-hpay0ax8.js";import"./chunk-catrr0z3.js";import"./chunk-mdc7b01e.js";import"./chunk-tn9gtf18.js";import"./chunk-895yqjjz.js";import"./chunk-sak1tphp.js";import{shQuote}from"./chunk-y1xnjx8x.js";import"./chunk-e58kj4gm.js";import"./chunk-0a65j1zj.js";import"./chunk-bcyex84w.js";import"./chunk-5rgrde6b.js";import"./chunk-4gjvmfa9.js";import"./chunk-2tfnscxk.js";import"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-etfh8f4z.js";import"./chunk-9rj2fx6v.js";import"./chunk-rfp0ayra.js";import"./chunk-t7j8g9f6.js";import"./chunk-dmzg9zdc.js";import"./chunk-40dgv828.js";import"./chunk-kg9kmwt9.js";import"./chunk-6xppe9bj.js";import{CURRENT_VERSION}from"./chunk-yn01fet6.js";import{argvHasFlag}from"./chunk-zsfyj36g.js";import"./chunk-2r1fgng9.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import{loadStateFile}from"./chunk-32j6y5d1.js";import"./chunk-a5xbsvx2.js";import"./chunk-9vwb9f7q.js";import"./chunk-cmp64q4j.js";import"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import"./chunk-7bakcyes.js";import"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import"./chunk-x1jxxmtc.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import{homeDir}from"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import{__require}from"./chunk-91sykzqq.js";import{spawn}from"child_process";import{appendFileSync,chmodSync,existsSync,mkdirSync}from"fs";import{homedir}from"os";import{dirname}from"path";function parseSshG(stdout,home=homedir()){let values=new Map;for(let line of stdout.split(`
3
3
  `)){let space=line.indexOf(" ");if(space>0)values.set(line.slice(0,space).toLowerCase(),line.slice(space+1).trim())}let hostname=values.get("hostname")??"",port=Number(values.get("port")??"22")||22,files=(key)=>(values.get(key)??"").split(/\s+/).filter((f)=>f&&f!=="none").map((f)=>f.startsWith("~/")?`${home}${f.slice(1)}`:f),alias=values.get("hostkeyalias"),proxy=(key)=>{let v=values.get(key);return v!==void 0&&v!=="none"};return{knownHostsName:alias&&alias!=="none"?alias:port===22?hostname:`[${hostname}]:${port}`,hostname,port,userKnownHosts:files("userknownhostsfile"),globalKnownHosts:files("globalknownhostsfile"),proxied:proxy("proxyjump")||proxy("proxycommand")}}async function checkHostKey(config){let target=sshTargetOf(config),resolved=await run(["ssh","-G",...config.port?["-p",String(config.port)]:[],target]);if(resolved.code!==0)return{state:"skipped",reason:"ssh -G failed"};let destination=parseSshG(resolved.stdout);if(!destination.hostname)return{state:"skipped",reason:"ssh -G named no host"};if(destination.proxied)return{state:"skipped",reason:"reached through a proxy"};for(let file of[...destination.userKnownHosts,...destination.globalKnownHosts]){if(!existsSync(file))continue;if((await run(["ssh-keygen","-F",destination.knownHostsName,"-f",file])).code===0)return{state:"known"}}let keys=(await run(["ssh-keyscan","-T","5","-p",String(destination.port),destination.hostname])).stdout.split(`
4
4
  `).filter((line)=>line.trim()&&!line.startsWith("#"));if(keys.length===0)return{state:"skipped",reason:"the host offered no key"};let named=keys.map((line)=>line.replace(/^\S+/,destination.knownHostsName)),fingerprints=(await run(["ssh-keygen","-l","-f","-"],`${named.join(`
5
5
  `)}
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{isPathLikeArg,runOpenDirectory}from"./chunk-qc9sj5wh.js";import"./chunk-2r1fgng9.js";import"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import"./chunk-pn5ygqn6.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{runOpenDirectory,isPathLikeArg};
2
+ import{isPathLikeArg,runOpenDirectory}from"./chunk-j5y7hhc2.js";import"./chunk-2r1fgng9.js";import"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import"./chunk-pn5ygqn6.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{runOpenDirectory,isPathLikeArg};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{currentLang,intlLocale,localeState,registerMessages,setLocaleLang,t,tKeys}from"./chunk-nqwza8b0.js";import"./chunk-ve76p2mx.js";import"./chunk-cmp64q4j.js";import"./chunk-91sykzqq.js";export{tKeys,t,setLocaleLang,registerMessages,localeState,intlLocale,currentLang};
2
+ import{currentLang,intlLocale,localeState,registerMessages,setLocaleLang,t,tKeys}from"./chunk-a5xbsvx2.js";import"./chunk-9vwb9f7q.js";import"./chunk-cmp64q4j.js";import"./chunk-91sykzqq.js";export{tKeys,t,setLocaleLang,registerMessages,localeState,intlLocale,currentLang};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{ENGINE_NOT_OBSERVED_REASON,ENGINE_START_POLL_MS,ENGINE_START_PROBE_MS,deliverHostedPrompt,deliverToKey,ensurePtyHost,findEngineKey,isTaskKey,killTaskSessions,listSessions,listSessionsOrNull,openPtyHost,outcomeFields,taskKeys}from"./chunk-w6ft4djp.js";import"./chunk-vx44yxra.js";import"./chunk-z43e08kw.js";import"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import"./chunk-gzkes5bw.js";import"./chunk-rxqdw6s5.js";import"./chunk-8ng1756g.js";import"./chunk-kxp04jnp.js";import"./chunk-1a57ejnh.js";import"./chunk-qecygh3f.js";import"./chunk-rjq38twt.js";import"./chunk-r5j8fycq.js";import"./chunk-xfgqae9t.js";import"./chunk-j1z9kgyd.js";import"./chunk-g9ba25q5.js";import"./chunk-ggnq2vvk.js";import"./chunk-hpay0ax8.js";import"./chunk-catrr0z3.js";import"./chunk-mdc7b01e.js";import"./chunk-tn9gtf18.js";import"./chunk-895yqjjz.js";import"./chunk-sak1tphp.js";import"./chunk-y1xnjx8x.js";import"./chunk-e58kj4gm.js";import"./chunk-0a65j1zj.js";import"./chunk-bcyex84w.js";import"./chunk-5rgrde6b.js";import"./chunk-4gjvmfa9.js";import"./chunk-2tfnscxk.js";import"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-etfh8f4z.js";import"./chunk-rfp0ayra.js";import"./chunk-40dgv828.js";import"./chunk-zsfyj36g.js";import"./chunk-2r1fgng9.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import"./chunk-32j6y5d1.js";import"./chunk-a5xbsvx2.js";import"./chunk-9vwb9f7q.js";import"./chunk-cmp64q4j.js";import"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import"./chunk-7bakcyes.js";import"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import"./chunk-x1jxxmtc.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import"./chunk-91sykzqq.js";export{taskKeys,outcomeFields,openPtyHost,listSessionsOrNull,listSessions,killTaskSessions,isTaskKey,findEngineKey,ensurePtyHost,deliverToKey,deliverHostedPrompt,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON};
@@ -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,settleWelcomeInstall},{t}]=await Promise.all([import("./chunk-w2tcb3rn.js"),import("./chunk-6cfs0nqe.js")]),completion=installCompletions(shell,deps.home,cliName,shipped);settleWelcomeInstall("completions",shell);let 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-mey3vksj.js");process.stdout.write(generateCompletions(shell,cliName,mergeSubVerbs(API_VERBS)))}export{runCompletionsSubcommand};
7
+ `);return}if(flags[0]==="--install"){let[{installCompletions,settleWelcomeInstall},{t}]=await Promise.all([import("./chunk-bm6qhcck.js"),import("./chunk-kt5ngemc.js")]),completion=installCompletions(shell,deps.home,cliName,shipped);settleWelcomeInstall("completions",shell);let 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-453qpfae.js");process.stdout.write(generateCompletions(shell,cliName,mergeSubVerbs(API_VERBS)))}export{runCompletionsSubcommand};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{stampOrigin}from"./chunk-rvjnafyt.js";import{createStateCell}from"./chunk-cmp64q4j.js";var NO_LIVE={activity:new Map,changes:new Map,tokens:new Map};function decodeMachines(payload){let p=payload;if(!p||!Array.isArray(p.machines)||!Array.isArray(p.tasks)||!p.live||typeof p.live!=="object")return null;let map=(value)=>new Map(value&&typeof value==="object"?Object.entries(value):[]);return{machines:p.machines,tasks:p.tasks,live:{activity:map(p.live.activity),changes:map(p.live.changes),tokens:map(p.live.tokens)}}}class MachineFeed{local;machinesAcc=createStateCell([],"machines.status");remoteTasksAcc=createStateCell(null,"machines.remoteTasks");tasksAcc;merged=null;liveAcc=createStateCell(NO_LIVE,"machines.live");stops;constructor(local){this.local=local;this.tasksAcc=this.mergedTasks();let raw=local.rawChannelSignal("machines"),take=()=>{let next=decodeMachines(raw.get());if(!next)return;this.machinesAcc.set(next.machines),this.liveAcc.set(next.live),this.remoteTasksAcc.set(next.machines.length===0?null:next.tasks)};this.stops=[raw.subscribe(take)],take()}machinesSignal(){return this.machinesAcc}tasksSignal(){return this.tasksAcc}liveSignal(){return this.liveAcc}mergedTasks(){let localTasks=this.local.tasksSignal(),get=()=>{let local=localTasks.get(),remote=this.remoteTasksAcc.get();if(remote===null)return local;if(this.merged?.local!==local||this.merged.remote!==remote){let value=[...local.map((task)=>stampOrigin(task,"local","local")),...remote];this.merged={local,remote,value}}return this.merged.value},state=get;return state.get=get,state.subscribe=(listener)=>{let stopLocal=localTasks.subscribe(listener),stopRemote=this.remoteTasksAcc.subscribe(listener);return()=>{stopLocal(),stopRemote()}},state}dispose(){for(let stop of this.stops)stop()}}
2
+ import{stampOrigin}from"./chunk-cx78tyg1.js";import{createStateCell}from"./chunk-cmp64q4j.js";var NO_LIVE={activity:new Map,changes:new Map,tokens:new Map};function decodeMachines(payload){let p=payload;if(!p||!Array.isArray(p.machines)||!Array.isArray(p.tasks)||!p.live||typeof p.live!=="object")return null;let map=(value)=>new Map(value&&typeof value==="object"?Object.entries(value):[]);return{machines:p.machines,tasks:p.tasks,live:{activity:map(p.live.activity),changes:map(p.live.changes),tokens:map(p.live.tokens)}}}class MachineFeed{local;machinesAcc=createStateCell([],"machines.status");remoteTasksAcc=createStateCell(null,"machines.remoteTasks");tasksAcc;merged=null;liveAcc=createStateCell(NO_LIVE,"machines.live");stops;constructor(local){this.local=local;this.tasksAcc=this.mergedTasks();let raw=local.rawChannelSignal("machines"),take=()=>{let next=decodeMachines(raw.get());if(!next)return;this.machinesAcc.set(next.machines),this.liveAcc.set(next.live),this.remoteTasksAcc.set(next.machines.length===0?null:next.tasks)};this.stops=[raw.subscribe(take)],take()}machinesSignal(){return this.machinesAcc}tasksSignal(){return this.tasksAcc}liveSignal(){return this.liveAcc}mergedTasks(){let localTasks=this.local.tasksSignal(),get=()=>{let local=localTasks.get(),remote=this.remoteTasksAcc.get();if(remote===null)return local;if(this.merged?.local!==local||this.merged.remote!==remote){let value=[...local.map((task)=>stampOrigin(task,"local","local")),...remote];this.merged={local,remote,value}}return this.merged.value},state=get;return state.get=get,state.subscribe=(listener)=>{let stopLocal=localTasks.subscribe(listener),stopRemote=this.remoteTasksAcc.subscribe(listener);return()=>{stopLocal(),stopRemote()}},state}dispose(){for(let stop of this.stops)stop()}}
3
3
  export{decodeMachines,MachineFeed};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{stampResetGate}from"./chunk-byh32qnx.js";import{stopLegacyTmux}from"./chunk-gkdfct7t.js";import{clearFrozenSessions}from"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import{stopDaemonProcess}from"./chunk-0a65j1zj.js";import"./chunk-2wrt80ft.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-32j6y5d1.js";import"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import{kvStatePath,legacyRoveKvStatePath,legacyRoveStateDir,roveStateDir}from"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import{defaultDaemonPidPath,defaultDaemonSocketPath,defaultPtyFreezeDir,defaultPtyHostPidPath,defaultPtyHostSocketPath}from"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";import{readFileSync}from"fs";import{unlink}from"fs/promises";import{join}from"path";import{createInterface}from"readline";var CLI_NAME=ROVE_PRODUCT_NAME;function printUsage(out){out.write([`Usage: ${CLI_NAME} reset [--hard] [--yes]`,"","Recover a wedged install: stop the daemon, Hosted PTY host, and any pre-v0.8 tmux sessions.","This ends background terminal and engine sessions; the next launch starts fresh.","Never touches your git worktrees.","","Options:"," --hard Also DELETE the task index and the whole settings file"," (saved projects, custom engines, theme, language, onboarding)"," -y, --yes Skip the interactive confirmation. REQUIRED without a terminal;"," a non-interactive run without it exits 2 and changes nothing."," -h, --help Print this help",""].join(`
2
+ import{stampResetGate}from"./chunk-5swmvt20.js";import{stopLegacyTmux}from"./chunk-gkdfct7t.js";import{clearFrozenSessions}from"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import{stopDaemonProcess}from"./chunk-0a65j1zj.js";import"./chunk-yn01fet6.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-32j6y5d1.js";import"./chunk-qzzmd63x.js";import"./chunk-96kvwzj8.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import{kvStatePath,legacyRoveKvStatePath,legacyRoveStateDir,roveStateDir}from"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import{defaultDaemonPidPath,defaultDaemonSocketPath,defaultPtyFreezeDir,defaultPtyHostPidPath,defaultPtyHostSocketPath}from"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";import{readFileSync}from"fs";import{unlink}from"fs/promises";import{join}from"path";import{createInterface}from"readline";var CLI_NAME=ROVE_PRODUCT_NAME;function printUsage(out){out.write([`Usage: ${CLI_NAME} reset [--hard] [--yes]`,"","Recover a wedged install: stop the daemon, Hosted PTY host, and any pre-v0.8 tmux sessions.","This ends background terminal and engine sessions; the next launch starts fresh.","Never touches your git worktrees.","","Options:"," --hard Also DELETE the task index and the whole settings file"," (saved projects, custom engines, theme, language, onboarding)"," -y, --yes Skip the interactive confirmation. REQUIRED without a terminal;"," a non-interactive run without it exits 2 and changes nothing."," -h, --help Print this help",""].join(`
3
3
  `))}function taskCount(path){try{let parsed=JSON.parse(readFileSync(path,"utf8"));return Array.isArray(parsed.tasks)?parsed.tasks.length:null}catch{return null}}function stateSummary(path){let parsed;try{parsed=JSON.parse(readFileSync(path,"utf8"))}catch{return[]}let count=(key)=>Array.isArray(parsed[key])?parsed[key].length:0,lines=[` saved projects: ${count("savedRepos")}`,` custom engines: ${count("customEngineIds")} (their launch commands live here and nowhere else)`],present=[["activeTheme","theme"],["defaultVendor","default engine"],["locale","language"],["onboarded","onboarding (the wizard runs again)"]].filter(([key])=>parsed[key]!==void 0).map(([,label])=>label);if(present.length>0)lines.push(` also set: ${present.join(", ")}`);return lines.push(` ${Object.keys(parsed).length} setting(s) in total`),lines}async function confirmTty(prompt){let readline=createInterface({input:process.stdin,output:process.stdout});try{let answer=await new Promise((resolve)=>readline.question(prompt,resolve));return/^y(es)?$/i.test(answer.trim())}finally{readline.close()}}async function removeStateFile(path,label){try{await unlink(path),console.log(` removed ${label} (${path})`)}catch(err){if(err.code==="ENOENT")console.log(` ${label}: already absent`);else throw Error(`failed to remove ${label} (${path}): ${errorMessage(err)}`)}}async function runResetSubcommand(argv){if(argv.some((arg)=>arg==="--help"||arg==="-h"||arg==="help")){printUsage(process.stdout);return}let known=new Set(["--hard","--yes","-y"]),unknown=argv.find((arg)=>!known.has(arg));if(unknown!==void 0)process.stderr.write(`${CLI_NAME} reset: unknown argument "${unknown}"
4
4
 
5
5
  `),printUsage(process.stderr),process.exit(2);let hard=argv.includes("--hard"),yes=argv.includes("--yes")||argv.includes("-y"),daemonSocket=defaultDaemonSocketPath(),tasksPath=join(roveStateDir(),"tasks.json"),legacyTasksPath=join(legacyRoveStateDir(),"tasks.json"),statePath=kvStatePath(),legacyStatePath=legacyRoveKvStatePath();if(console.log(`${CLI_NAME} reset will:`),console.log(" \u2022 stop the Rove daemon (graceful \u2192 SIGTERM \u2192 SIGKILL)"),console.log(` \u2022 remove its socket + pidfile (${daemonSocket})`),console.log(" \u2022 stop the standalone Hosted PTY host and all background terminal/engine sessions"),console.log(" \u2022 stop any pre-v0.8 tmux sessions after SIGTERM-ing their pane process groups"),hard){let count=taskCount(tasksPath)??taskCount(legacyTasksPath);console.log(` \u2022 DELETE the task index${count===null?"":` (${count} task(s))`} \u2014 ${tasksPath}`),console.log(` \u2022 DELETE the whole settings file \u2014 ${statePath}`);for(let line of stateSummary(statePath))console.log(line);console.log(" \u2022 DELETE the pre-Rove task/UI indexes too, so migration cannot restore reset state")}if(console.log(" \u2022 NOT touch your git worktrees under ~/.rove/worktrees/ or existing repo-local roots"),!hard)console.log(" (your task list, settings & worktrees are kept \u2014 add --hard to also delete the task index and settings file)");if(!yes){if(!process.stdin.isTTY){console.log(`
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{installSkillNow,refreshSkillStatus,skillMissing,startSkillStatus}from"./chunk-hfvzvj91.js";import"./chunk-y7mjhjby.js";import"./chunk-4gjvmfa9.js";import"./chunk-2tfnscxk.js";import"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-rfp0ayra.js";import"./chunk-40dgv828.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import"./chunk-32j6y5d1.js";import"./chunk-cmp64q4j.js";import"./chunk-7bakcyes.js";import"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import"./chunk-x1jxxmtc.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{startSkillStatus,skillMissing,refreshSkillStatus,installSkillNow};
2
+ import{installSkillNow,refreshSkillStatus,skillMissing,startSkillStatus}from"./chunk-4yr1534j.js";import"./chunk-0gbg7bg8.js";import"./chunk-4gjvmfa9.js";import"./chunk-2tfnscxk.js";import"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-rfp0ayra.js";import"./chunk-40dgv828.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import"./chunk-32j6y5d1.js";import"./chunk-cmp64q4j.js";import"./chunk-7bakcyes.js";import"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import"./chunk-x1jxxmtc.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import"./chunk-pn5ygqn6.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-91sykzqq.js";export{startSkillStatus,skillMissing,refreshSkillStatus,installSkillNow};