@sma1lboy/rove 0.9.188 → 0.9.190
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{chunk-kffgmnfz.js → chunk-0pazt6mk.js} +1 -1
- package/dist/cli/{chunk-1xrry8mn.js → chunk-0rsjdc2p.js} +1 -1
- package/dist/cli/{chunk-9bbrbgf9.js → chunk-0waq0d0k.js} +1 -1
- package/dist/cli/{chunk-262x4qr9.js → chunk-16rt509n.js} +1 -1
- package/dist/cli/{chunk-8ybpxrbt.js → chunk-18rdsr2j.js} +1 -1
- package/dist/cli/{chunk-9xvzjs9d.js → chunk-1mdah6n8.js} +1 -1
- package/dist/cli/{chunk-mme4hff3.js → chunk-2w9pqcc3.js} +1 -1
- package/dist/cli/{chunk-n64paahm.js → chunk-61ak2y9n.js} +4 -4
- package/dist/cli/chunk-86938f2g.js +4 -0
- package/dist/cli/{chunk-q3rf6gkh.js → chunk-8s5yzt7z.js} +2 -2
- package/dist/cli/{chunk-511csjr9.js → chunk-9nngww22.js} +2 -2
- package/dist/cli/{chunk-j6pvrkh1.js → chunk-ar48zb4b.js} +1 -1
- package/dist/cli/{chunk-8a080b82.js → chunk-bveqt1bn.js} +1 -1
- package/dist/cli/{chunk-6brqrpqa.js → chunk-c2aqag1z.js} +1 -1
- package/dist/cli/{chunk-49ykmne0.js → chunk-d3qmrnc6.js} +1 -1
- package/dist/cli/{chunk-yrmj16b9.js → chunk-dc8hk7a7.js} +1 -1
- package/dist/cli/{chunk-1g7e29sv.js → chunk-ectyq178.js} +1 -1
- package/dist/cli/{chunk-0cm7e5qg.js → chunk-ex0tesmv.js} +1 -1
- package/dist/cli/{chunk-g7bp57ge.js → chunk-f01z7hw8.js} +1 -1
- package/dist/cli/{chunk-1f071tjz.js → chunk-f62n9xqs.js} +1 -1
- package/dist/cli/{chunk-1qbgvkpy.js → chunk-gc1x5v4n.js} +1 -1
- package/dist/cli/{chunk-gq4nkteg.js → chunk-h3gqr77q.js} +1 -1
- package/dist/cli/{chunk-nsg5dtyk.js → chunk-hm1fg4b1.js} +1 -1
- package/dist/cli/{chunk-wr2ynhkf.js → chunk-hz8ynrv6.js} +1 -1
- package/dist/cli/{chunk-eaa24va5.js → chunk-j6tmzwc9.js} +1 -1
- package/dist/cli/{chunk-n4bhegyh.js → chunk-jj4x05y6.js} +1 -1
- package/dist/cli/{chunk-9xyksvt2.js → chunk-mamm5f66.js} +1 -1
- package/dist/cli/{chunk-2f409xdj.js → chunk-mrszjfxd.js} +1 -1
- package/dist/cli/{chunk-15gxe843.js → chunk-myewhxvp.js} +1 -1
- package/dist/cli/{chunk-mw9qkt91.js → chunk-nk1d8t3a.js} +1 -1
- package/dist/cli/{chunk-qqd34s04.js → chunk-nn099hrx.js} +2 -2
- package/dist/cli/{chunk-r8vajxt3.js → chunk-p0zrjj7n.js} +3 -3
- package/dist/cli/{chunk-6n7n1vr7.js → chunk-p3stdyd2.js} +1 -1
- package/dist/cli/{chunk-gwxep0x4.js → chunk-p9gnqtfe.js} +1 -1
- package/dist/cli/{chunk-rgcr3gx6.js → chunk-pjk7jxjb.js} +1 -1
- package/dist/cli/{chunk-apkn54rn.js → chunk-vvyg65jf.js} +1 -1
- package/dist/cli/{chunk-t0swwy8z.js → chunk-w4y5cmbs.js} +1 -1
- package/dist/cli/{chunk-nwbbjkrj.js → chunk-w7a39tk8.js} +1 -1
- package/dist/cli/{chunk-qx2ph8jr.js → chunk-wm14aqwc.js} +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/cli/kobe.js +1 -1
- package/dist/cli/rove.js +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-1jbznr12.js +0 -4
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{embeddedTerminalEnv}from"./chunk-ef39ym8f.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,clearFrozenSessions,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-2cy0c03r.js";import{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{writeTextAtomic}from"./chunk-xsrcwcjc.js";import{recordPtyExit}from"./chunk-a74pa16c.js";import{CURRENT_VERSION}from"./chunk-mw9qkt91.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-rcyasw34.js";import{DEFAULT_TERMINAL_COLORS,foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors}from"./chunk-7q67dz4c.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import"./chunk-w25b7xxz.js";import{DAEMON_PROTOCOL_VERSION,frameToLine}from"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-q5jhy3t8.js";import{listenOnUnixSocket}from"./chunk-t915by6w.js";import{ensureOwnerOnlyStateDir}from"./chunk-9prawccj.js";import"./chunk-sb0ns0c7.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,isWindowsPipePath,legacyPtyHostPidPath,legacyPtyHostSocketPath,resolveDaemonHomeDir}from"./chunk-8cjr5ypt.js";import{COMPAT_STATE_DIR_BASENAME,ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";function formatPtyHostLine(event,message,now=new Date){return`[${now.toISOString()}] pty-host [${event}]: ${message}`}import{readFileSync}from"fs";import{mkdir,unlink}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync,symlinkSync}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=join(homeDir,COMPAT_STATE_DIR_BASENAME);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);try{symlinkSync(canonical,legacy)}catch{}}catch{}}return moved}import{randomUUID as randomUUID2}from"crypto";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:"xterm-256color",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)}}}import{randomUUID}from"crypto";import{StringDecoder}from"string_decoder";function freshSessionState(key,spec,argv){return{key,generation:randomUUID(),cwd:spec.cwd,proc:null,alive:!0,chunks:[],bytes:0,totalBytes:0,cols:spec.cols??80,rows:spec.rows??24,command:argv,title:"",titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:parseTerminalDefaultColors(spec.defaultColors)??DEFAULT_TERMINAL_COLORS,sinks:new Map,parked:!1,parkedScreenBytes:0,exit:null,restored:!1,lastFreezeAtMs:0,frozenTotalBytes:0}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,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(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??resolveLoginShell()],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=randomUUID2();try{session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...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",KOBE_TERMINAL_PTY:"1"}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0,session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session))}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;session.alive=!1;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)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,buf.toString("latin1"));session.colorQueryCarry=colorQueries.carry;for(let slot of colorQueries.slots)try{session.proc?.write(formatDefaultColorReply(slot,session.defaultColors))}catch{}scanOscTitle(session,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)session.bytes-=dropped.byteLength}this.deps.onOutput?.(session,buf)}}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??resolveLoginShell();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??resolveLoginShell()];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;class PtyHost{sessions=new Map;opts;scrollbackCap;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,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")}};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){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;session.sinks.set(token,sink),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++;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;return this.sessions.delete(from),session.key=to,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),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(!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){return peekRing(this.sessions.get(key),sinceOffset)}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();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)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}}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.KOBE_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.KOBE_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,wipeFreezeOnStop=!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=readFileSync(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({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;if(stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown(),wipeFreezeOnStop)clearFrozenSessions(freezeDir);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?.()}function dispatch(req,client){switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.open":{let payload=objectPayload(req.payload);return 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)=>writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0)}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"));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.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),stats:ptys.stats(),...options.version?{version:options.version}:{}};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 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"daemon.stop":return wipeFreezeOnStop=!0,setTimeout(()=>void stop(),0).unref(),{};default:throw Error(`unknown pty-host request: ${req.name}`)}}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 try{writeFrame(client,{type:"response",id:frame.id,name:frame.name,payload:dispatch(frame,client)})}catch(err){writeFrame(client,{type:"response",id:frame.id,name:frame.name,error:{message:err instanceof Error?err.message:String(err)}})}}}if(await listenOnUnixSocket(server,socketPath),await writeTextAtomic(pidPath,`${process.pid}
|
|
2
|
+
import{embeddedTerminalEnv}from"./chunk-ef39ym8f.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,clearFrozenSessions,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-2cy0c03r.js";import{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{writeTextAtomic}from"./chunk-xsrcwcjc.js";import{recordPtyExit}from"./chunk-a74pa16c.js";import{CURRENT_VERSION}from"./chunk-nk1d8t3a.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-rcyasw34.js";import{DEFAULT_TERMINAL_COLORS,foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors}from"./chunk-7q67dz4c.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import"./chunk-w25b7xxz.js";import{DAEMON_PROTOCOL_VERSION,frameToLine}from"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-q5jhy3t8.js";import{listenOnUnixSocket}from"./chunk-t915by6w.js";import{ensureOwnerOnlyStateDir}from"./chunk-9prawccj.js";import"./chunk-sb0ns0c7.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,isWindowsPipePath,legacyPtyHostPidPath,legacyPtyHostSocketPath,resolveDaemonHomeDir}from"./chunk-8cjr5ypt.js";import{COMPAT_STATE_DIR_BASENAME,ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";function formatPtyHostLine(event,message,now=new Date){return`[${now.toISOString()}] pty-host [${event}]: ${message}`}import{readFileSync}from"fs";import{mkdir,unlink}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync,symlinkSync}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=join(homeDir,COMPAT_STATE_DIR_BASENAME);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);try{symlinkSync(canonical,legacy)}catch{}}catch{}}return moved}import{randomUUID as randomUUID2}from"crypto";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:"xterm-256color",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)}}}import{randomUUID}from"crypto";import{StringDecoder}from"string_decoder";function freshSessionState(key,spec,argv){return{key,generation:randomUUID(),cwd:spec.cwd,proc:null,alive:!0,chunks:[],bytes:0,totalBytes:0,cols:spec.cols??80,rows:spec.rows??24,command:argv,title:"",titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:parseTerminalDefaultColors(spec.defaultColors)??DEFAULT_TERMINAL_COLORS,sinks:new Map,parked:!1,parkedScreenBytes:0,exit:null,restored:!1,lastFreezeAtMs:0,frozenTotalBytes:0}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,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(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??resolveLoginShell()],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=randomUUID2();try{session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...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",KOBE_TERMINAL_PTY:"1"}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0,session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session))}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;session.alive=!1;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)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,buf.toString("latin1"));session.colorQueryCarry=colorQueries.carry;for(let slot of colorQueries.slots)try{session.proc?.write(formatDefaultColorReply(slot,session.defaultColors))}catch{}scanOscTitle(session,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)session.bytes-=dropped.byteLength}this.deps.onOutput?.(session,buf)}}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??resolveLoginShell();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??resolveLoginShell()];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;class PtyHost{sessions=new Map;opts;scrollbackCap;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,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")}};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){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;session.sinks.set(token,sink),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++;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;return this.sessions.delete(from),session.key=to,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),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(!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){return peekRing(this.sessions.get(key),sinceOffset)}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();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)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}}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.KOBE_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.KOBE_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,wipeFreezeOnStop=!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=readFileSync(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({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;if(stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown(),wipeFreezeOnStop)clearFrozenSessions(freezeDir);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?.()}function dispatch(req,client){switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.open":{let payload=objectPayload(req.payload);return 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)=>writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0)}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"));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.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),stats:ptys.stats(),...options.version?{version:options.version}:{}};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 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"daemon.stop":return wipeFreezeOnStop=!0,setTimeout(()=>void stop(),0).unref(),{};default:throw Error(`unknown pty-host request: ${req.name}`)}}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 try{writeFrame(client,{type:"response",id:frame.id,name:frame.name,payload:dispatch(frame,client)})}catch(err){writeFrame(client,{type:"response",id:frame.id,name:frame.name,error:{message:err instanceof Error?err.message:String(err)}})}}}if(await listenOnUnixSocket(server,socketPath),await writeTextAtomic(pidPath,`${process.pid}
|
|
3
3
|
`),!pipeSocket){let home=resolveDaemonHomeDir();await linkLegacyRuntimePath(socketPath,legacyPtyHostSocketPath(home)),await linkLegacyRuntimePath(pidPath,legacyPtyHostPidPath(home))}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,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{findBinding,formatChord}from"./chunk-
|
|
2
|
+
import{findBinding,formatChord}from"./chunk-h3gqr77q.js";function capOf(row){return row.hint?.keys??row.keys[0]}function legendCap(id){let row=findBinding(id);if(!row)return null;let cap=capOf(row);return cap&&cap.length>0?cap:null}function directCap(row){if(row.keys.length>0)return row.hint?.keys??row.keys[0]??null;return row.prefixKeys?.length?null:row.hint?.keys??null}function availableOn(row,surface){if(row.scope==="global")return!0;if(surface===null)return!1;if(row.scope===surface)return!0;return surface==="terminal"&&row.scope==="workspace"}function grammarHelpSections(keymap,surface,prefixKey,reachability){let here=[],direct=[],prefix=[],other=new Map;for(let binding of keymap){let cap=directCap(binding),staticallyAvailable=availableOn(binding,surface),directAvailable=reachability?reachability.direct.has(binding.id):staticallyAvailable,prefixAvailable=reachability?reachability.prefix.has(binding.id):staticallyAvailable;if(cap){let row={binding,primary:cap,aliases:binding.keys.filter((key)=>key!==cap)};if(directAvailable&&(staticallyAvailable||binding.presentation==="onePress"))if(binding.presentation==="onePress")direct.push(row);else here.push(row);else if(!staticallyAvailable&&binding.scope!=="global"){let rows=other.get(binding.scope);if(rows)rows.push(row);else other.set(binding.scope,[row])}}if(prefixKey&&prefixAvailable&&binding.prefixKeys?.length)prefix.push({binding,primary:`${prefixKey} + ${binding.prefixKeys[0]}`,aliases:binding.prefixKeys.slice(1).map((key)=>`${prefixKey} + ${key}`)})}let sections=[];if(here.length)sections.push({kind:"here",scope:surface??void 0,rows:here});if(direct.length)sections.push({kind:"direct",rows:direct});if(prefix.length)sections.push({kind:"prefix",rows:prefix});for(let[scope,rows]of other)sections.push({kind:"other",scope,rows});return sections}var SCOPE_CATEGORY={global:"Global",sidebar:"Sidebar",workspace:"Workspace",files:"Files",inbox:"Inbox",terminal:"Terminal"};function scopeCategory(scope){return scope?SCOPE_CATEGORY[scope]:"Global"}function guideCategory(action){if(["kanban.open","automations.open","workItems.open"].includes(action))return"Views";if(action.startsWith("focus."))return"Navigation";if(action.startsWith("inbox.")||action.startsWith("attention."))return"Attention";if(action.startsWith("chat.tab.")||action.startsWith("chat.session."))return"Sessions";if(action.startsWith("chat.fork.")||action.startsWith("task."))return"Tasks";if(action.startsWith("settings.")||action==="workspace.zenToggle")return"Tools";return findBinding(action)?.category??"Global"}var KEY_HINTS_ENABLED_KEY="hints.keyboard.enabled",PANE_HINT_USED_KEYS={sidebar:"hints.sidebar.used",files:"hints.files.used"};function keyHintsEnabled(raw){return raw!==!1}function keyHintsToggleOn(kv){return keyHintsEnabled(kv.get(KEY_HINTS_ENABLED_KEY,!0))}function toggleKeyHints(kv){let next=!keyHintsToggleOn(kv);if(kv.set(KEY_HINTS_ENABLED_KEY,next),next)for(let key of Object.values(PANE_HINT_USED_KEYS))kv.set(key,!1)}function paneHintVisible(enabledRaw,usedRaw){return keyHintsEnabled(enabledRaw)&&usedRaw!==!0}function statusHintTokens(reach,prefixKey){let tokens=[];if(prefixKey!==null&&reach.prefix.size>0)tokens.push({chord:prefixKey,msg:"commands"});else if(reach.inputPassthrough){let cap=reach.direct.has("focus.sidebar")?legendCap("focus.sidebar"):null;if(cap)tokens.push({chord:cap,msg:"sidebar"})}if(reach.direct.has("help.open")){let cap=legendCap("help.open");if(cap)tokens.push({chord:cap,msg:"help"})}return tokens}var PANE_HINT_ROWS={sidebar:[{id:"sidebar.nav",msg:"move"},{id:"sidebar.select",msg:"open"}],files:[{id:"files.nav",msg:"move"},{id:"files.hierarchy",msg:"collapse"},{id:"files.open",msg:"open",always:!0},{id:"files.diff",msg:"diff",always:!0}]};function paneHintTokens(pane,mode){return PANE_HINT_ROWS[pane].flatMap((row)=>{if(mode==="always"&&row.always!==!0)return[];let cap=legendCap(row.id);return cap?[{cap,msg:row.msg}]:[]})}function wizardKeyLines(prefixKey){let lines=[],nav=legendCap("sidebar.nav"),open=legendCap("sidebar.select");if(nav&&open)lines.push({msg:"keysBare",params:{nav:formatChord(nav),open:formatChord(open)}});let newTab=legendCap("chat.tab.new"),focusNext=legendCap("focus.next");if(newTab&&focusNext)lines.push({msg:"keysOnePress",params:{newTab:formatChord(newTab),focusNext:formatChord(focusNext)}});if(prefixKey!==null)lines.push({msg:"keysPrefix",params:{prefix:formatChord(prefixKey)}});let help=legendCap("help.open");if(help)lines.push({msg:"keysHelp",params:{help:formatChord(help)}});return lines}
|
|
3
3
|
export{legendCap,grammarHelpSections,scopeCategory,guideCategory,KEY_HINTS_ENABLED_KEY,PANE_HINT_USED_KEYS,keyHintsEnabled,keyHintsToggleOn,toggleKeyHints,paneHintVisible,statusHintTokens,paneHintTokens,wizardKeyLines};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
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-
|
|
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-ar48zb4b.js";import"./chunk-pjk7jxjb.js";import"./chunk-hz8ynrv6.js";import"./chunk-rc0sqhdh.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-gsy8xfh6.js";import"./chunk-dc8hk7a7.js";import"./chunk-rcyasw34.js";import"./chunk-7q67dz4c.js";import"./chunk-92d2t5sk.js";import"./chunk-hape5vwj.js";import"./chunk-wdrgfezn.js";import"./chunk-r85jw4qg.js";import"./chunk-qvf2zh14.js";import"./chunk-t6mq1dnw.js";import"./chunk-sdyzxayr.js";import"./chunk-b99tf0jr.js";import"./chunk-z7c6nap0.js";import"./chunk-w25b7xxz.js";import"./chunk-f7zjggfv.js";import"./chunk-jvxh93nz.js";import"./chunk-fczqwtmq.js";import"./chunk-te8g5azg.js";import"./chunk-y13681dw.js";import"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-86938f2g.js";import"./chunk-71k66b8f.js";import"./chunk-khj0apc7.js";import"./chunk-5zh5fcpe.js";import"./chunk-w7zv47mp.js";import"./chunk-pdnq8dbm.js";import"./chunk-7jkf3tvr.js";import"./chunk-7kysxgbq.js";import"./chunk-r9gfh1zz.js";import"./chunk-xy8be792.js";import"./chunk-ejqs2ta9.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-2brn8e1y.js";import"./chunk-bq3fyc0p.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-9prawccj.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-pxk2c2vj.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.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};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{envReadyForTasks}from"./chunk-
|
|
2
|
+
import{envReadyForTasks}from"./chunk-9nngww22.js";import{wizardKeyLines}from"./chunk-0rsjdc2p.js";import"./chunk-mrszjfxd.js";import"./chunk-jj4x05y6.js";import"./chunk-18rdsr2j.js";import"./chunk-xqdhp9y5.js";import{$Fragment,$jsx,$jsxs,bootPaneHost,currentPrefixConfiguration,pageCloseBindings,useBindings,useRenderer,useT,useTheme}from"./chunk-h3gqr77q.js";import"./chunk-wm14aqwc.js";import{require_react_production}from"./chunk-a82ec09z.js";import"./chunk-764bsyb0.js";import"./chunk-xqw5d5rv.js";import"./chunk-h4n8ffqy.js";import"./chunk-6xppe9bj.js";import"./chunk-nk1d8t3a.js";import"./chunk-dc8hk7a7.js";import"./chunk-wdrgfezn.js";import"./chunk-r85jw4qg.js";import"./chunk-qvf2zh14.js";import"./chunk-t6mq1dnw.js";import"./chunk-sdyzxayr.js";import"./chunk-z7c6nap0.js";import"./chunk-jvxh93nz.js";import"./chunk-fczqwtmq.js";import"./chunk-te8g5azg.js";import"./chunk-y13681dw.js";import"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-86938f2g.js";import"./chunk-71k66b8f.js";import"./chunk-khj0apc7.js";import"./chunk-5zh5fcpe.js";import"./chunk-w7zv47mp.js";import"./chunk-pdnq8dbm.js";import"./chunk-7jkf3tvr.js";import"./chunk-7kysxgbq.js";import"./chunk-r9gfh1zz.js";import"./chunk-xy8be792.js";import"./chunk-ejqs2ta9.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-2brn8e1y.js";import"./chunk-bq3fyc0p.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-9prawccj.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-pxk2c2vj.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import{__toESM}from"./chunk-wqfp8d9w.js";import{TextAttributes}from"@opentui/core";var import_react2=__toESM(require_react_production(),1);function inlineRowsFor(env){return 15+env.engines.lines.length+envActionKeys(env).length}function envActionKeys(env){let keys=[];if(!env.engines.anyUsable)keys.push("doctor.fix.noEngineAction");if(!env.git.found)keys.push("doctor.fix.gitAction");return keys}function WizardPage(props){let{theme}=useTheme(),t=useT(),renderer=useRenderer(),steps=(props.mode??"full")==="primer"?[]:props.shell===null?["skill"]:["completions","skill"],[stepIndex,setStepIndex]=import_react2.useState(0),[yes,setYes]=import_react2.useState(!0),[answers,setAnswers]=import_react2.useState({}),[page,setPage]=import_react2.useState(steps.length===0?"env":"questions"),step=steps[stepIndex];function finish(finalAnswers){renderer?.destroy(),props.onDone({completions:finalAnswers.completions??!1,skill:finalAnswers.skill??!1})}function confirm(choice=yes){if(page==="env"){setPage("keys");return}if(page==="keys"){finish(answers);return}let next={...answers,[step]:choice};if(setAnswers(next),stepIndex+1>=steps.length){setPage("env");return}setStepIndex(stepIndex+1),setYes(!0)}useBindings(()=>({bindings:[{key:"up",cmd:()=>setYes(!0)},{key:"k",cmd:()=>setYes(!0)},{key:"down",cmd:()=>setYes(!1)},{key:"j",cmd:()=>setYes(!1)},{key:"return",cmd:()=>confirm()},...pageCloseBindings(()=>finish(answers))]}));function questionFor(s){return s==="completions"?t("onboarding.completionsQuestion",{shell:props.shell??""}):t("onboarding.skillQuestion")}let explain=step==="completions"?t("onboarding.completionsExplain"):t("onboarding.skillExplain"),ready=envReadyForTasks(props.env);return $jsxs("box",{flexDirection:"column",flexGrow:1,paddingTop:1,paddingLeft:2,paddingRight:2,children:[$jsx("text",{fg:theme.primary,attributes:TextAttributes.BOLD,wrapMode:"none",children:t("onboarding.title")}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("onboarding.subtitle")}),$jsxs("box",{flexDirection:"column",paddingTop:1,children:[steps.slice(0,page==="questions"?stepIndex:steps.length).map((answered)=>$jsxs("box",{flexDirection:"row",gap:1,children:[$jsx("text",{fg:theme.success,wrapMode:"none",children:"\u2713"}),$jsx("text",{fg:theme.textMuted,wrapMode:"none",children:questionFor(answered)}),$jsx("text",{fg:theme.text,wrapMode:"none",children:answers[answered]?t("onboarding.optionYes"):t("onboarding.optionNo")})]},answered)),page==="env"?$jsxs("box",{flexDirection:"column",onMouseUp:()=>confirm(),children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:t("onboarding.envTitle")}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("onboarding.envExplain")}),$jsxs("box",{flexDirection:"column",paddingTop:1,children:[$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:props.env.git.line}),props.env.engines.lines.map((line)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:line},line))]}),$jsxs("box",{paddingTop:1,flexDirection:"column",children:[$jsx("text",{fg:ready?theme.success:theme.error,wrapMode:"word",children:ready?t("onboarding.envReady"):t("onboarding.envNotReady")}),envActionKeys(props.env).map((key)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:`\u2192 ${t(key)}`},key))]})]}):null,page==="keys"?$jsxs("box",{flexDirection:"column",onMouseUp:()=>confirm(),children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:t("onboarding.keysTitle")}),wizardKeyLines(currentPrefixConfiguration().key).map((line)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t(`onboarding.${line.msg}`,line.params)},line.msg))]}):null,page==="questions"?$jsxs($Fragment,{children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:questionFor(step)}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:explain}),[!0,!1].map((option)=>{let active=yes===option;return $jsxs("box",{flexDirection:"row",gap:1,paddingLeft:1,onMouseUp:()=>confirm(option),children:[$jsx("text",{fg:active?theme.primary:theme.textMuted,wrapMode:"none",children:active?"\u276F":" "}),$jsx("text",{fg:active?theme.primary:theme.textMuted,attributes:active?TextAttributes.BOLD:void 0,wrapMode:"none",children:option?t("onboarding.optionYes"):t("onboarding.optionNo")})]},String(option))})]}):null]}),$jsx("box",{paddingTop:1,children:$jsx("text",{fg:theme.textMuted,attributes:TextAttributes.DIM,wrapMode:"none",children:t(page==="keys"?"onboarding.keysLegend":page==="env"?"onboarding.envLegend":"onboarding.legend")})})]})}async function runOnboardingWizard(shell,env,mode){return await new Promise((resolve)=>{bootPaneHost({inlineRows:inlineRowsFor(env),setup:()=>({root:()=>$jsx(WizardPage,{shell,env,mode,onDone:resolve})})})})}export{runOnboardingWizard,WizardPage};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{BREAKING_VERSIONS,CURRENT_VERSION,compareSemver}from"./chunk-
|
|
2
|
+
import{BREAKING_VERSIONS,CURRENT_VERSION,compareSemver}from"./chunk-nk1d8t3a.js";import{loadStateFile,patchStateFile}from"./chunk-3jh78dmc.js";import{activeCliName}from"./chunk-00ehck55.js";var LAST_RUN_VERSION_KEY="app.lastRunVersion";function resetGateBlockers(lastRun,current=CURRENT_VERSION,breaking=BREAKING_VERSIONS){if(typeof lastRun!=="string"||lastRun.length===0)return[];let[lo,hi]=compareSemver(lastRun,current)<=0?[lastRun,current]:[current,lastRun];return breaking.filter((b)=>compareSemver(b,lo)>0&&compareSemver(b,hi)<=0)}function enforceResetGate(){let cliName=activeCliName(),lastRun=loadStateFile()[LAST_RUN_VERSION_KEY],blockers=resetGateBlockers(lastRun);if(blockers.length>0){let from=typeof lastRun==="string"?lastRun:"unknown";console.error([`${cliName} ${CURRENT_VERSION}: cannot start \u2014 version ${blockers.join(", ")} introduced breaking changes`,`(last run: ${from}). Your daemon/session state may be incompatible.`,"","Run:",` ${cliName} reset # stop daemon + PTY host + sessions (tasks kept)`,` ${cliName} reset --hard # additionally wipe the task index + UI state`,"","Then relaunch Rove. Worktrees are never touched."].join(`
|
|
3
3
|
`)),process.exit(1)}if(lastRun!==CURRENT_VERSION)stampResetGate()}function stampResetGate(){try{patchStateFile({[LAST_RUN_VERSION_KEY]:CURRENT_VERSION})}catch{}}
|
|
4
4
|
export{LAST_RUN_VERSION_KEY,enforceResetGate,stampResetGate};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{recommendedGlobalInstallCommand}from"./chunk-
|
|
2
|
+
import{recommendedGlobalInstallCommand}from"./chunk-nk1d8t3a.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";function updaterShell(deps={}){let platform=deps.platform??process.platform;if(platform!=="win32")return"sh";return resolveLoginShell({fallback:"/bin/sh",platform,env:deps.env,exists:deps.exists})}function updaterShellFailureHint(deps={}){if((deps.platform??process.platform)!=="win32")return null;return["The update script is POSIX shell. Rove runs it through Git for Windows'","bash \u2014 the same shell every engine and terminal tab launches through.","Install Git for Windows (https://git-scm.com/download/win), or update","by hand:",` ${recommendedGlobalInstallCommand()}`,""].join(`
|
|
3
3
|
`)}
|
|
4
4
|
export{updaterShell,updaterShellFailureHint};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{SUBCOMMAND_VERBS,TOP_LEVEL_SUBCOMMANDS}from"./chunk-fhch0x0q.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";async function collectSubVerbs(){let{API_VERBS}=await import("./chunk-
|
|
2
|
+
import{SUBCOMMAND_VERBS,TOP_LEVEL_SUBCOMMANDS}from"./chunk-fhch0x0q.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";async function collectSubVerbs(){let{API_VERBS}=await import("./chunk-w7a39tk8.js"),merged={...SUBCOMMAND_VERBS,api:API_VERBS};return Object.keys(merged).sort().map((command)=>[command,merged[command]??[]])}function completionUsage(cliName){return[`Usage: ${cliName} completions <bash|zsh|fish>`,"",`Generate a shell completion script for ${cliName} and print it to stdout.`,"","Install:",` zsh source <(${cliName} completions zsh) # one-off, or in ~/.zshrc after compinit`," # or the fpath way:",` # ${cliName} completions zsh > ~/.zsh/completions/_${cliName}`," # fpath=(~/.zsh/completions $fpath) # in ~/.zshrc, BEFORE compinit"," # rm -f ~/.zcompdump && exec zsh # rebuild the completion cache",` bash ${cliName} completions bash > ~/.bash_completion.d/${cliName} # source it from ~/.bashrc`,` fish ${cliName} completions fish > ~/.config/fish/completions/${cliName}.fish`,""].join(`
|
|
3
3
|
`)}function generateBashCompletions(cliName,subVerbs){let subcommands=TOP_LEVEL_SUBCOMMANDS.join(" "),fn=`_${cliName}`;return[`# ${cliName} bash completions`,`# Source: ${cliName} completions bash`,"",`${fn}() {`," local cur prev"," COMPREPLY=()",' cur="${COMP_WORDS[COMP_CWORD]}"',' prev="${COMP_WORDS[COMP_CWORD-1]}"'," if [[ ${COMP_CWORD} -eq 1 ]]; then",` COMPREPLY=( $(compgen -W "${subcommands}" -- "\${cur}") )`," return"," fi"," if [[ ${COMP_CWORD} -eq 2 ]]; then",' case "${prev}" in',...subVerbs.map(([command,verbs])=>` ${command}) COMPREPLY=( $(compgen -W "${verbs.join(" ")}" -- "\${cur}") ) ;;`)," esac"," fi","}",`complete -F ${fn} ${cliName}`,""].join(`
|
|
4
4
|
`)}function generateZshCompletions(cliName,subVerbs){let subcommandsList=TOP_LEVEL_SUBCOMMANDS.map((s)=>`"${s}"`).join(" "),fn=`_${cliName}`;return[`#compdef ${cliName}`,`# ${cliName} zsh completions`,`# Source: ${cliName} completions zsh`,"",`${fn}() {`," local -a subcommands verbs",` subcommands=(${subcommandsList})`,""," if (( CURRENT == 2 )); then"," _describe -t commands 'subcommand' subcommands"," return"," fi",""," verbs=()",' case "${words[2]}" in',...subVerbs.map(([command,verbs])=>` ${command}) verbs=(${verbs.map((v)=>`"${v}"`).join(" ")}) ;;`)," esac"," if (( CURRENT == 3 && ${#verbs} > 0 )); then"," _describe -t verbs 'verb' verbs"," fi","}","","# Autoloaded from $fpath -> run as the completion function;","# sourced directly -> register with compdef instead.",`if [ "\${funcstack[1]}" = "${fn}" ]; then`,` ${fn} "$@"`,"elif (( $+functions[compdef] )); then",` compdef ${fn} ${cliName}`,"fi",""].join(`
|
|
5
5
|
`)}function generateFishCompletions(cliName,subVerbs){let lines=[...TOP_LEVEL_SUBCOMMANDS.map((s)=>`complete -c ${cliName} -f -n __fish_use_subcommand -a ${s}`),...subVerbs.map(([command,verbs])=>`complete -c ${cliName} -f -n "__fish_seen_subcommand_from ${command}" -a "${verbs.join(" ")}"`)];return`# ${cliName} fish completions
|