@sma1lboy/rove 0.9.179 → 0.9.181
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-wdzhfbye.js → chunk-1f071tjz.js} +1 -1
- package/dist/cli/{chunk-z5x3cd7j.js → chunk-1jbznr12.js} +1 -1
- package/dist/cli/{chunk-bkba9c4n.js → chunk-2apszxn2.js} +1 -1
- package/dist/cli/{chunk-3p5yjwjs.js → chunk-2htnatha.js} +1 -1
- package/dist/cli/{chunk-1vpsb31h.js → chunk-2jnkfg4v.js} +1 -1
- package/dist/cli/{chunk-esgxxnwn.js → chunk-2pv5vb5a.js} +1 -1
- package/dist/cli/{chunk-nnscywzf.js → chunk-3ft463z9.js} +1 -1
- package/dist/cli/{chunk-4kweezsh.js → chunk-42h7m08p.js} +2 -2
- package/dist/cli/{chunk-3dexjt11.js → chunk-4s6j1hv9.js} +1 -1
- package/dist/cli/{chunk-y9bgn622.js → chunk-5nn763sy.js} +1 -1
- package/dist/cli/{chunk-nqkcrhpp.js → chunk-658hahan.js} +1 -1
- package/dist/cli/{chunk-cnre6fbm.js → chunk-6d4xwg7m.js} +1 -1
- package/dist/cli/{chunk-8npdrpq2.js → chunk-6tt33a84.js} +1 -1
- package/dist/cli/{chunk-nnmpben9.js → chunk-6y88a3b4.js} +2 -2
- package/dist/cli/{chunk-hcsfp7z7.js → chunk-6zwnwbd4.js} +1 -1
- package/dist/cli/{chunk-80hf0bbr.js → chunk-71k66b8f.js} +2 -2
- package/dist/cli/chunk-7kysxgbq.js +3 -0
- package/dist/cli/{chunk-kweffk7w.js → chunk-82p0wh0h.js} +1 -1
- package/dist/cli/{chunk-0vrv03qn.js → chunk-847gwrx2.js} +1 -1
- package/dist/cli/{chunk-r2r5krab.js → chunk-8gavx8g1.js} +1 -1
- package/dist/cli/{chunk-0s7e3cnc.js → chunk-8qx8gtfr.js} +2 -2
- package/dist/cli/{chunk-534se0f6.js → chunk-a7e6a754.js} +1 -1
- package/dist/cli/{chunk-cv6zwad5.js → chunk-bsg826q0.js} +1 -1
- package/dist/cli/{chunk-fa7s3d1e.js → chunk-bwrb6c2h.js} +1 -1
- package/dist/cli/{chunk-8znc46fw.js → chunk-cb082qmy.js} +1 -1
- package/dist/cli/{chunk-6f18r6vf.js → chunk-cwzhqjke.js} +1 -1
- package/dist/cli/{chunk-8qx3959c.js → chunk-d51xktn8.js} +1 -1
- package/dist/cli/{chunk-emkfynn5.js → chunk-d6x4gama.js} +1 -1
- package/dist/cli/{chunk-frdr9bjy.js → chunk-d8hcpwr6.js} +2 -2
- package/dist/cli/{chunk-rwkbxtpe.js → chunk-eahj40hv.js} +1 -1
- package/dist/cli/{chunk-wz421xna.js → chunk-erzb2kq5.js} +1 -1
- package/dist/cli/{chunk-0xgd6as7.js → chunk-ey9xbdpm.js} +1 -1
- package/dist/cli/{chunk-zkj59kkd.js → chunk-fprjrr5e.js} +3 -3
- package/dist/cli/{chunk-ne34zknk.js → chunk-g9vz4dma.js} +1 -1
- package/dist/cli/{chunk-9sa6vtp0.js → chunk-hex5xwyk.js} +1 -1
- package/dist/cli/{chunk-d8nmt9zt.js → chunk-hssrp88v.js} +1 -1
- package/dist/cli/{chunk-615s6xjd.js → chunk-hvm1aqjv.js} +1 -1
- package/dist/cli/{chunk-wvq6kgcp.js → chunk-j0jb8kav.js} +1 -1
- package/dist/cli/{chunk-t0bfjapm.js → chunk-k53xe8jg.js} +3 -3
- package/dist/cli/{chunk-gpt8mj16.js → chunk-k7hfh7m3.js} +1 -1
- package/dist/cli/{chunk-hfpmeck1.js → chunk-mc33ba6j.js} +1 -1
- package/dist/cli/{chunk-v5dmc2r6.js → chunk-md0q657y.js} +1 -1
- package/dist/cli/{chunk-br6dggaa.js → chunk-n4bhegyh.js} +1 -1
- package/dist/cli/{chunk-pspw5k9e.js → chunk-p9b3cp59.js} +2 -2
- package/dist/cli/{chunk-v61s3fps.js → chunk-pdnq8dbm.js} +2 -2
- package/dist/cli/{chunk-8cdrt8zx.js → chunk-pnb48jrh.js} +1 -1
- package/dist/cli/{chunk-6tvs0r4z.js → chunk-ptfe9a1h.js} +1 -1
- package/dist/cli/{chunk-q8v9zad9.js → chunk-q6bhnxw9.js} +1 -1
- package/dist/cli/chunk-qqh9aef5.js +3 -0
- package/dist/cli/{chunk-bg16r4yh.js → chunk-qrdjqwn7.js} +1 -1
- package/dist/cli/{chunk-ccwc3h8y.js → chunk-r8j5zpt9.js} +1 -1
- package/dist/cli/{chunk-jg61s3ce.js → chunk-rc0sqhdh.js} +1 -1
- package/dist/cli/{chunk-xswrw836.js → chunk-rtdz71g6.js} +1 -1
- package/dist/cli/{chunk-pcrv3eyw.js → chunk-t0qqabdw.js} +1 -1
- package/dist/cli/{chunk-s0gqxhk7.js → chunk-ts77enjd.js} +5 -5
- package/dist/cli/{chunk-g7baby60.js → chunk-vhq2dhx2.js} +1 -1
- package/dist/cli/{chunk-km4hx6kc.js → chunk-wdrgfezn.js} +1 -1
- package/dist/cli/{chunk-k0xgtzm2.js → chunk-x4hss5rp.js} +1 -1
- package/dist/cli/{chunk-zx7fkp8y.js → chunk-yn8pahva.js} +1 -1
- package/dist/cli/{chunk-xr30vfgt.js → chunk-yrmj16b9.js} +1 -1
- package/dist/cli/{chunk-1ngaph89.js → chunk-z0fbsvs0.js} +1 -1
- package/dist/cli/{chunk-yvmz8cts.js → chunk-zj8y4f4x.js} +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/cli/kobe.js +1 -1
- package/dist/cli/rove.js +1 -1
- package/dist/pulse-ynhb2ave.wav +0 -0
- package/package.json +1 -1
- package/dist/cli/chunk-2fypr41w.js +0 -3
- package/dist/cli/chunk-dazqahfp.js +0 -3
- package/dist/pulse-n3cq1btw.wav +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{canonicalize}from"./chunk-
|
|
2
|
+
import{canonicalize}from"./chunk-vhq2dhx2.js";import{applyJitter,exponentialBackoff}from"./chunk-khj0apc7.js";import{getRemoteRepoConfig,isRemoteRepoKey,resolveRepoRoot}from"./chunk-ejqs2ta9.js";var canonPath=canonicalize;function randomDirTaskSuffix(){return Math.random().toString(36).slice(2,6).padEnd(4,"0")}function titleFromRepo(repo){let segs=repo.split(/[/\\]/).filter(Boolean);return segs.length>0?segs[segs.length-1]??repo:repo}function normalizeMainRepo(repo){let normalized=resolveRepoRoot(repo);return{repo:normalized,key:isRemoteRepoKey(normalized)?normalized:canonPath(normalized)}}function repoWorkingDir(repo){return getRemoteRepoConfig(repo)?.basePath??repo}var GH_PR_VIEW_FIELDS="number,url,title,state,baseRefName,reviewDecision,mergeable,statusCheckRollup";function lifecycleFromState(state,reviewDecision){switch((state??"").toUpperCase()){case"MERGED":return"merged";case"CLOSED":return"closed";case"OPEN":return(reviewDecision??"").toUpperCase()==="APPROVED"?"ready_to_merge":"open";default:return"unknown"}}function entryCheckState(entry){let status=(entry.status??"").toUpperCase(),conclusion=(entry.conclusion??"").toUpperCase(),contextState=(entry.state??"").toUpperCase();if(status&&status!=="COMPLETED")return"pending";if(conclusion){if(conclusion==="SUCCESS"||conclusion==="NEUTRAL"||conclusion==="SKIPPED")return"passing";return"failing"}if(contextState==="SUCCESS")return"passing";if(contextState==="PENDING"||contextState==="EXPECTED")return"pending";if(contextState==="FAILURE"||contextState==="ERROR")return"failing";return"unknown"}function checkStateFromRollup(rollup){if(!rollup||rollup.length===0)return"none";let sawPending=!1,sawPassing=!1;for(let entry of rollup){let s=entryCheckState(entry);if(s==="failing")return"failing";if(s==="pending")sawPending=!0;else if(s==="passing")sawPassing=!0}if(sawPending)return"pending";if(sawPassing)return"passing";return"unknown"}function mapGhPrView(view,at){if(!view||typeof view.number!=="number")return null;return{provider:"github",lifecycle:lifecycleFromState(view.state,view.reviewDecision),checkState:checkStateFromRollup(view.statusCheckRollup),number:view.number,url:view.url,title:view.title,baseRef:view.baseRefName,reviewDecision:view.reviewDecision||void 0,mergeable:view.mergeable||void 0,lastCheckedAt:at}}function samePrStatus(a,b){if(a===b)return!0;if(!a||!b)return!1;return a.provider===b.provider&&a.lifecycle===b.lifecycle&&a.checkState===b.checkState&&a.number===b.number&&a.url===b.url&&a.title===b.title&&a.baseRef===b.baseRef&&a.reviewDecision===b.reviewDecision&&a.mergeable===b.mergeable}var NO_REMOTE_PATTERNS=["none of the git remotes","no git remote","to use github cli in a github repository","not a github repository"],AUTH_PATTERNS=["gh auth login","authentication required","not logged in","http 401","bad credentials","requires authentication"],NETWORK_PATTERNS=["could not resolve host","no such host","dial tcp","connection refused","connection reset","network is unreachable","i/o timeout","timeout","tls handshake","http 5","rate limit","try again"];function matchesAny(haystack,needles){return needles.some((n)=>haystack.includes(n))}function classifyGhFailure(s){if(s.parseError)return{kind:"error",error:"parse"};if(s.timedOut)return{kind:"error",error:"timeout"};if(s.spawnError)return{kind:"error",error:"missing-binary"};let err=(s.stderr??"").toLowerCase();if(matchesAny(err,NO_REMOTE_PATTERNS))return{kind:"error",error:"no-remote"};if(matchesAny(err,AUTH_PATTERNS))return{kind:"error",error:"auth"};if(matchesAny(err,NETWORK_PATTERNS))return{kind:"error",error:"network"};return{kind:"error",error:"unknown"}}function nextPrPoll(outcome,prevFailures,now,cfg,rand=Math.random){let at=(delay)=>now+applyJitter(delay,cfg.jitterRatio,rand);if(outcome.kind==="pr")return{nextAllowedAt:at(outcome.settled?cfg.settledMs:cfg.tickMs),failures:0};if(outcome.kind==="empty")return{nextAllowedAt:at(cfg.noPrMs),failures:0};if(outcome.error==="no-remote")return{nextAllowedAt:at(cfg.noRemoteMs),failures:0};let failures=prevFailures+1;return{nextAllowedAt:at(exponentialBackoff(cfg.failureBaseMs,failures-1,cfg.failureCapMs)),failures}}function checkResolutionNotify(prev,next){if(prev!=="pending")return null;if(next==="passing"||next==="failing")return next;return null}
|
|
3
3
|
export{GH_PR_VIEW_FIELDS,mapGhPrView,samePrStatus,classifyGhFailure,nextPrPoll,checkResolutionNotify,canonPath,randomDirTaskSuffix,titleFromRepo,normalizeMainRepo,repoWorkingDir};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{embeddedTerminalEnv}from"./chunk-ef39ym8f.js";import{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{writeTextAtomic}from"./chunk-xsrcwcjc.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,clearFrozenSessions,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-2cy0c03r.js";import{recordPtyExit}from"./chunk-a74pa16c.js";import{CURRENT_VERSION}from"./chunk-nnscywzf.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{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{writeTextAtomic}from"./chunk-xsrcwcjc.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,clearFrozenSessions,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-2cy0c03r.js";import{recordPtyExit}from"./chunk-a74pa16c.js";import{CURRENT_VERSION}from"./chunk-3ft463z9.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,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{listPresetIds}from"./chunk-
|
|
2
|
+
import{listPresetIds}from"./chunk-yrmj16b9.js";import{interactiveEngineCommand}from"./chunk-wdrgfezn.js";import{engineEntry}from"./chunk-71k66b8f.js";import{installedEngineIds}from"./chunk-5zh5fcpe.js";import{spawnSync}from"child_process";import{statSync}from"fs";import path from"path";function whichOnPath(bin){let bunWhich=globalThis.Bun?.which;if(bunWhich)return bunWhich(bin);let out=spawnSync(process.platform==="win32"?"where":"which",[bin],{encoding:"utf8"});if(out.status!==0)return null;return out.stdout.split(`
|
|
3
3
|
`).map((l)=>l.trim()).find(Boolean)??null}var defaultDeps={which:whichOnPath,command:(vendor)=>interactiveEngineCommand(vendor)};function probeLaunchBinary(argv,which){let bin=argv[0]?.trim();if(!bin)return{found:!1,error:"no launch command"};if(bin.includes(path.sep)||bin.startsWith(".")){try{if(statSync(bin).isFile())return{found:!0,path:bin}}catch{}return{found:!1,error:`not found at ${bin}`}}let found=which(bin);return found?{found:!0,path:found}:{found:!1,error:"not found on PATH"}}async function detectEngineStatus(vendor,over={}){let deps={...defaultDeps,...over},detector=engineEntry(vendor).detectAccount;if(!detector)return{vendor,binary:probeLaunchBinary(deps.command(vendor),deps.which),account:null};let status=await detector(deps.accountDeps),binary=status.binary.found?status.binary:probeLaunchBinary(deps.command(vendor),deps.which);return{vendor,binary,account:status.account,accountError:status.accountError}}function detectEngineStatuses(vendors,over={}){return Promise.all(vendors.map((v)=>detectEngineStatus(v,over)))}function describeAccount(account){if(account===null)return"login not detectable";switch(account.kind){case"oauth":return"email"in account?`logged in (${account.email}${account.organization?`, ${account.organization}`:""})`:"logged in";case"chatgpt":return`logged in (${account.email}${account.plan?`, ${account.plan}`:""})`;case"apikey":return"API key";case"token":return`token (${account.source})`;default:return"no account"}}function engineUsable(status){return status.binary.found&&status.account?.kind!=="none"}async function probeableEngineIds(){return[...new Set([...listPresetIds(),...await installedEngineIds()])]}function summarizeEngines(statuses){let usable=[],signedOut=[];for(let status of statuses)if(engineUsable(status))usable.push(status.vendor);else if(status.binary.found)signedOut.push(status.vendor);return{usable,signedOut}}
|
|
4
4
|
export{detectEngineStatuses,describeAccount,probeableEngineIds,summarizeEngines};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{buildPaneArgv}from"./chunk-1x7xjh3h.js";import{PluginCliError,installPlugin,linkPlugin}from"./chunk-
|
|
2
|
+
import{buildPaneArgv}from"./chunk-1x7xjh3h.js";import{PluginCliError,installPlugin,linkPlugin}from"./chunk-658hahan.js";import{resolvePluginBinPath}from"./chunk-7nndmapz.js";import{buildPluginEnv}from"./chunk-jpdf97cx.js";import{currentPluginPlatform,loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginLogPath,qualifiedActionId,readPluginManifest,removePluginEntry,savePluginRegistry,supportsPlatform}from"./chunk-g2e1dmxh.js";import{SUBCOMMAND_VERBS}from"./chunk-s76r56rj.js";import"./chunk-3ft463z9.js";import"./chunk-b99tf0jr.js";import{flagValue}from"./chunk-jvxh93nz.js";import"./chunk-mnqxgvyb.js";import"./chunk-w7zv47mp.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-q5jhy3t8.js";import"./chunk-9prawccj.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import{defaultDaemonSocketPath}from"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{readFileSync,rmSync}from"fs";var CLI_NAME=activeCliName();function printUsage(out){out.write([`usage: ${CLI_NAME} plugin <command>`,""," install <owner/repo[/subdir]> [--yes] [--ref <rev>] clone from GitHub, preview, build, register"," link <dir> register a local plugin directory (dev)"," list installed + linked plugins"," search [query] browse the marketplace (GitHub topic rove-plugin)"," outdated check GitHub-installed plugins against upstream"," update <id\u2026> | --all [--yes] reinstall stale plugins from GitHub"," enable <id> | disable <id> toggle a plugin without unregistering it"," unlink <id> unregister a linked plugin (files untouched)"," uninstall <id-or-spec> unregister + remove the managed checkout"," config-dir <id> print the plugin's config directory"," log <id> [-n <count>] tail the plugin's command-run log"," action list [--plugin <id>] declared actions"," action invoke <plugin-id.action-id> run an action now"," pane open <plugin-id.pane-id> [--task <task-id>] open a plugin pane as a terminal tab (JSON:"," clients \u2014 0 = no attached UI performed the split)","","Marketplace: https://github.com/topics/rove-plugin (legacy kobe-plugin is included)",""].join(`
|
|
3
3
|
`))}function loadAll(){return loadPluginRegistry().plugins.map((entry)=>{try{return{entry,manifest:readPluginManifest(entry.root).manifest}}catch{return{entry,manifest:void 0}}})}function requireEntry(id){let entry=loadPluginRegistry().plugins.find((p)=>p.id===id);if(!entry)throw new PluginCliError(`no plugin registered as \`${id}\`; see \`${CLI_NAME} plugin list\``);return entry}function listPlugins(){let all=loadAll();if(all.length===0){console.log(`no plugins installed. Try: ${CLI_NAME} plugin install <owner/repo> \u2014 browse the \`rove-plugin\` GitHub topic.`);return}for(let{entry,manifest}of all){let state=entry.enabled?"enabled":"disabled",kind=entry.source.kind==="link"?`linked ${entry.root}`:entry.source.spec,broken=manifest?"":" [manifest unreadable]";console.log(`${entry.id} v${entry.version} ${state} (${kind})${broken}`)}}function setEnabled(id,enabled){let entry=requireEntry(id),registry=loadPluginRegistry();savePluginRegistry({plugins:registry.plugins.map((p)=>p.id===id?{...entry,enabled}:p)}),console.log(`${enabled?"enabled":"disabled"} ${id}`)}function unlink(id){let entry=requireEntry(id);if(entry.source.kind!=="link")throw new PluginCliError(`\`${id}\` is a GitHub install; use uninstall`);savePluginRegistry(removePluginEntry(loadPluginRegistry(),id)),console.log(`unlinked ${id} (files untouched at ${entry.root})`)}function uninstall(idOrSpec){let registry=loadPluginRegistry(),entry=registry.plugins.find((p)=>p.id===idOrSpec||p.source.kind==="github"&&p.source.spec===idOrSpec);if(!entry)throw new PluginCliError(`no plugin registered as \`${idOrSpec}\``);if(entry.source.kind==="link")throw new PluginCliError(`\`${entry.id}\` is linked; use unlink`);savePluginRegistry(removePluginEntry(registry,entry.id)),rmSync(pluginCheckoutDir(entry.id),{recursive:!0,force:!0}),console.log(`uninstalled ${entry.id} (config/state kept under ~/.rove/plugins/${entry.id}/)`)}function listActions(pluginFilter){for(let{entry,manifest}of loadAll()){if(!manifest||pluginFilter&&entry.id!==pluginFilter)continue;for(let action of manifest.actions)console.log(`${qualifiedActionId(entry.id,action.id)} ${action.title}`)}}function findByLongestPluginPrefix(qualified,options,findItem){for(let{entry,manifest}of loadAll().filter(({entry:entry2,manifest:manifest2})=>Boolean(manifest2&&(!options.enabledOnly||entry2.enabled)&&qualified.startsWith(`${entry2.id}.`))).sort((a,b)=>b.entry.id.length-a.entry.id.length)){let item=findItem(manifest,qualified.slice(entry.id.length+1));if(item!==void 0)return{entry,manifest,item}}return}function assertPlatformSupported(label,item,manifest){if(supportsPlatform(item,manifest,currentPluginPlatform()))return;let declared=(item.platforms??manifest.platforms??[]).join(", ");throw new PluginCliError(`\`${label}\` is not supported on this platform (declares ${declared})`)}function invokeAction(qualified,extraArgs){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!0},(manifest,actionId)=>manifest.actions.find((a)=>a.id===actionId));if(!hit)throw new PluginCliError(`no action \`${qualified}\`; see \`${CLI_NAME} plugin action list\``);assertPlatformSupported(qualified,hit.item,hit.manifest);let action=hit.item,[cmd,...args]=[...action.command,...extraArgs],res=spawnSync(cmd,args,{cwd:hit.entry.root,stdio:"inherit",env:buildPluginEnv({socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),pluginId:hit.entry.id,pluginRoot:hit.entry.root,extra:{ROVE_PLUGIN_ACTION_ID:action.id,ROVE_PLUGIN_INVOKE_CWD:process.cwd()}})});process.exit(res.status??1)}function resolvePaneQualified(qualified){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!1},(manifest,entrypoint)=>manifest.panes.find((p)=>p.id===entrypoint));if(!hit)throw new PluginCliError(`no pane \`${qualified}\`; see \`${CLI_NAME} plugin list\``);return{pluginId:hit.entry.id,entrypoint:hit.item.id}}async function openPane(pluginId,entrypoint,taskFlag){let loaded=loadAll().find(({entry})=>entry.id===pluginId);if(!loaded?.manifest)throw new PluginCliError(`no plugin \`${pluginId}\` (or its manifest is unreadable)`);if(!loaded.entry.enabled)throw new PluginCliError(`\`${pluginId}\` is disabled`);let pane=loaded.manifest.panes.find((p)=>p.id===entrypoint);if(!pane)throw new PluginCliError(`no pane \`${entrypoint}\` in \`${pluginId}\`; declare it under [[panes]]`);assertPlatformSupported(`${pluginId}.${pane.id}`,pane,loaded.manifest);let{openDaemonSession,resolveActiveTaskId}=await import("./chunk-9d4tfysz.js"),session=await openDaemonSession({mode:"start"});try{let taskId=taskFlag??await resolveActiveTaskId(session.client);if(!taskId)throw new PluginCliError("no active task; pass --task <id>");let argv=buildPaneArgv(loaded.entry.id,loaded.entry.root,pane,{socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),taskId}),reply=await session.client.request("tab.open",{taskId,argv,title:pane.title,placement:pane.placement});console.log(JSON.stringify({...reply,ok:!0,pane:`${pluginId}.${pane.id}`,taskId,title:pane.title}))}finally{session.close()}}function tailLog(id,count){requireEntry(id);let text;try{text=readFileSync(pluginLogPath(id),"utf8")}catch{console.log("(no runs logged yet)");return}let lines=text.trimEnd().split(`
|
|
4
|
-
`);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-9xkc34rf.js");await searchMarketplace(args.find((a)=>!a.startsWith("-")));return}case"outdated":{let{printOutdated}=await import("./chunk-
|
|
4
|
+
`);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-9xkc34rf.js");await searchMarketplace(args.find((a)=>!a.startsWith("-")));return}case"outdated":{let{printOutdated}=await import("./chunk-cwzhqjke.js");printOutdated();return}case"update":{let{updatePlugins}=await import("./chunk-cwzhqjke.js");await updatePlugins(args.filter((a)=>!a.startsWith("-")),{all:args.includes("--all"),yes:args.includes("--yes")});return}case"enable":case"disable":{if(!args[0])throw new PluginCliError(`${command} needs a plugin id`);setEnabled(args[0],command==="enable");return}case"unlink":{if(!args[0])throw new PluginCliError("unlink needs a plugin id");unlink(args[0]);return}case"uninstall":{if(!args[0])throw new PluginCliError("uninstall needs a plugin id or owner/repo spec");uninstall(args[0]);return}case"config-dir":{if(!args[0])throw new PluginCliError("config-dir needs a plugin id");requireEntry(args[0]),console.log(pluginConfigDir(args[0]));return}case"log":{if(!args[0])throw new PluginCliError("log needs a plugin id");tailLog(args[0],Number.parseInt(flagValue(args,"-n")??"20",10)||20);return}case"pane":{let[sub,...paneArgs]=args;if(sub==="open"){let positional=paneArgs.find((a)=>!a.startsWith("-")&&a!==flagValue(paneArgs,"--task")),pluginId=flagValue(paneArgs,"--plugin"),entrypoint=flagValue(paneArgs,"--entrypoint");if(!pluginId||!entrypoint){if(!positional)throw new PluginCliError("pane open needs <plugin-id.pane-id> (or --plugin <id> --entrypoint <pane-id>) [--task <task-id>]");({pluginId,entrypoint}=resolvePaneQualified(positional))}await openPane(pluginId,entrypoint,flagValue(paneArgs,"--task"));return}printUsage(process.stderr),process.exit(2);return}case"action":{let[sub,...actionArgs]=args;if(sub==="list"){listActions(flagValue(actionArgs,"--plugin"));return}if(sub==="invoke"){if(!actionArgs[0])throw new PluginCliError("action invoke needs <plugin-id.action-id>");invokeAction(actionArgs[0],actionArgs.slice(1));return}printUsage(process.stderr),process.exit(2);return}default:{let isHelp=command===void 0||command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}}}catch(err){if(err instanceof PluginCliError)console.error(`${CLI_NAME} plugin: ${err.message}`),process.exit(1);console.error(`${CLI_NAME} plugin: ${errorMessage(err)}`),process.exit(1)}}export{runPluginSubcommand};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{readTextFileIfRegular,readTextFileIfRegularSync,vendorConfigHome}from"./chunk-7jkf3tvr.js";import{quoteShellArgv}from"./chunk-
|
|
2
|
+
import{readTextFileIfRegular,readTextFileIfRegularSync,vendorConfigHome}from"./chunk-7jkf3tvr.js";import{quoteShellArgv}from"./chunk-7kysxgbq.js";import{acquireWithRetry}from"./chunk-r9gfh1zz.js";import{acquireSync,release,releaseSync}from"./chunk-ddcxvbme.js";import{roveStateDir}from"./chunk-q5jhy3t8.js";import{activeCliName}from"./chunk-00ehck55.js";import{LEGACY_KOBE_PRODUCT_NAME,ROVE_PRODUCT_NAME}from"./chunk-sb0ns0c7.js";import{fileURLToPath}from"url";function roveCliInvocation(){let cliName=activeCliName();if(import.meta.url.endsWith(".js"))return[cliName];let entry=fileURLToPath(new URL(`./${cliName===ROVE_PRODUCT_NAME?"rove.ts":"kobe.ts"}`,import.meta.url));return[process.execPath,"--conditions=browser",entry]}function kobeHookInvocation(){if(import.meta.url.endsWith(".js"))return[LEGACY_KOBE_PRODUCT_NAME];if(Bun.which(LEGACY_KOBE_PRODUCT_NAME))return[LEGACY_KOBE_PRODUCT_NAME];return roveCliInvocation()}var GATED_TOOL_VERBS=new Set(["tool-pre","tool-post","tool-failed"]);function isObject(v){return!!v&&typeof v==="object"&&!Array.isArray(v)}function parseHookSettings(raw){if(raw===void 0)return{ok:!0,doc:{}};let parsed;try{parsed=JSON.parse(raw)}catch(err){return{ok:!1,reason:`not valid JSON (${err instanceof Error?err.message:String(err)})`}}if(!isObject(parsed))return{ok:!1,reason:"top level is not a JSON object"};if(parsed.hooks===void 0)return{ok:!0,doc:parsed};if(!isObject(parsed.hooks))return{ok:!1,reason:'"hooks" is not an object'};for(let[event,groups]of Object.entries(parsed.hooks)){if(!Array.isArray(groups))return{ok:!1,reason:`"hooks.${event}" is not an array`};let bad=groups.findIndex((group)=>!isObject(group)||!Array.isArray(group.hooks));if(bad>=0)return{ok:!1,reason:`"hooks.${event}[${bad}]" is not an object with a "hooks" array`}}return{ok:!0,doc:parsed}}var HOOK_WORD=String.raw`(?:'(?:[^']|'\\'')*'|"[^"$\x60\\]*"|[A-Za-z0-9_./:=+-]+)`,HOOK_ARGV=new RegExp(`^${HOOK_WORD}(?:[ ]+${HOOK_WORD})*$`);function isRoveHook(hook,verbs){if(!isObject(hook)||hook.type!=="command"||typeof hook.command!=="string")return!1;let command=hook.command.replace(/^[ \t]+|[ \t]+$/g,"");if(HOOK_ARGV.exec(command)?.[0]!==command)return!1;let argv=(command.match(new RegExp(HOOK_WORD,"g"))??[]).map((word)=>{if(word.startsWith("'"))return word.slice(1,-1).replaceAll("'\\''","'");if(word.startsWith('"'))return word.slice(1,-1);return word}),executable=argv[0]?.split("/").at(-1),offset=1;if(executable==="bun"||executable==="node"){if(argv[offset]==="--conditions=browser")offset++;let entry=argv[offset]??"";if(!/(?:^|\/)(?:src|dist)\/cli\/(?:rove|kobe)\.(?:ts|js)$/.test(entry))return!1;offset++}else if(executable!=="rove"&&executable!=="kobe")return!1;if(argv[offset]!=="hook"||!verbs.includes(argv[offset+1]))return!1;let rest=argv.slice(offset+2);return rest.length===0||rest.length===2&&rest[0]==="--engine"&&/^[a-z][a-z0-9-]*$/.test(rest[1])}function removeRoveHooks(groups,verbs){return groups.flatMap((group)=>{if(!isObject(group)||!Array.isArray(group.hooks))return[group];let kept=group.hooks.filter((hook)=>!isRoveHook(hook,verbs));if(kept.length===group.hooks.length)return[group];return kept.length>0?[{...group,hooks:kept}]:[]})}function hasKobeActivityHooks(current,eventMap){let verbs=eventMap.map((spec)=>spec.verb),hooks=isObject(current.hooks)?current.hooks:{};return Object.values(hooks).some((groups)=>Array.isArray(groups)&&groups.some((group)=>isObject(group)&&Array.isArray(group.hooks)&&group.hooks.some((hook)=>isRoveHook(hook,verbs))))}function hookCommandQuoting(platform=process.platform){return{bareSafe:!0,windows:platform==="win32"}}function buildActivityHooks(eventMap,inv=kobeHookInvocation(),opts={}){let out={},quoting=hookCommandQuoting();for(let spec of eventMap){if(opts.buildFilter&&!opts.buildFilter(spec))continue;let{event,matcher,verb}=spec,group={hooks:[{type:"command",command:quoteShellArgv([...inv,"hook",verb,...opts.extraArgs??[]],quoting)}]};if(matcher)group.matcher=matcher;let previous=out[event],groups=Array.isArray(previous)?previous:[];groups.push(group),out[event]=groups}return out}function mergeActivityHooks(current,install,eventMap,inv=kobeHookInvocation(),opts={}){let verbs=eventMap.map((spec)=>spec.verb),{hooks:rawHooks,...restSettings}=current,hooks=isObject(rawHooks)?{...rawHooks}:{},built=install?buildActivityHooks(eventMap,inv,opts):{};for(let{event}of eventMap){let groups=hooks[event],prior=Array.isArray(groups)?groups:[],kept=removeRoveHooks(prior,verbs),additions=built[event];if(install&&Array.isArray(additions))kept.push(...additions);if(kept.length>0)hooks[event]=kept;else delete hooks[event]}return Object.keys(hooks).length>0?{...restSettings,hooks}:{...restSettings}}var RETIRED_WATCH_EVENT="PostToolUse";function removeWorktreeWatchHook(current){let{hooks:rawHooks,...restSettings}=current,hooks=isObject(rawHooks)?{...rawHooks}:{},groups=hooks[RETIRED_WATCH_EVENT],prior=Array.isArray(groups)?groups:[],kept=removeRoveHooks(prior,["worktree-created"]);if(kept.length>0)hooks[RETIRED_WATCH_EVENT]=kept;else delete hooks[RETIRED_WATCH_EVENT];return Object.keys(hooks).length>0?{...restSettings,hooks}:{...restSettings}}import{join as join2}from"path";import{createHash,randomBytes}from"crypto";import{mkdirSync,renameSync,unlinkSync,writeFileSync}from"fs";import{mkdir,rename,unlink,writeFile}from"fs/promises";import{dirname,join}from"path";var MAX_SHARED_CONFIG_BYTES=8388608;function stagingPath(file){return`${file}.rove-${process.pid}-${randomBytes(6).toString("hex")}.tmp`}function sharedConfigLockPath(file){return join(roveStateDir(),`shared-config-${createHash("sha256").update(file).digest("hex").slice(0,16)}.lock`)}var MAX_ATTEMPTS=5;function readSharedConfigSync(file){try{let raw=readTextFileIfRegularSync(file,MAX_SHARED_CONFIG_BYTES);if(raw===null)throw Error(`Refusing non-regular or oversized config: ${file}`);return raw}catch(err){if(err instanceof Error&&"code"in err&&err.code==="ENOENT")return;throw err}}async function readRaw(file){try{let raw=await readTextFileIfRegular(file,MAX_SHARED_CONFIG_BYTES);if(raw===null)throw Error(`Refusing non-regular or oversized config: ${file}`);return raw}catch(err){if(err instanceof Error&&"code"in err&&err.code==="ENOENT")return;throw err}}function updateSharedJsonSync(file,load,build){let lockPath=sharedConfigLockPath(file),lockToken=acquireSync(lockPath);try{for(let attempt=0;attempt<MAX_ATTEMPTS;attempt++){let before=readSharedConfigSync(file),doc=load(before);if(!doc)return;let text=build(doc);if(text===void 0)return;let tmp=stagingPath(file);try{if(mkdirSync(dirname(file),{recursive:!0}),writeFileSync(tmp,text,{mode:384,flag:"wx"}),readSharedConfigSync(file)===before){renameSync(tmp,file);return}}finally{try{unlinkSync(tmp)}catch{}}}throw Error(`gave up updating ${file} after ${MAX_ATTEMPTS} concurrent writes`)}finally{releaseSync(lockPath,lockToken)}}async function updateSharedJson(file,load,build){let lockPath=sharedConfigLockPath(file),lockToken=await acquireWithRetry(lockPath);try{for(let attempt=0;attempt<MAX_ATTEMPTS;attempt++){let before=await readRaw(file),doc=load(before);if(!doc)return;let text=build(doc);if(text===void 0)return;let tmp=stagingPath(file);try{if(await mkdir(dirname(file),{recursive:!0}),await writeFile(tmp,text,{mode:384,flag:"wx"}),await readRaw(file)===before){await rename(tmp,file);return}}finally{await unlink(tmp).catch(()=>{})}}throw Error(`gave up updating ${file} after ${MAX_ATTEMPTS} concurrent writes`)}finally{await release(lockPath,lockToken)}}async function editJsonSettings(settingsFilePath,transform){let rejected;try{await updateSharedJson(settingsFilePath,(raw)=>{let parsed=parseHookSettings(raw);if(parsed.ok)return parsed.doc;rejected=parsed.reason;return},(current)=>{let next=transform(current),json=JSON.stringify(next,null,2);return json===JSON.stringify(current,null,2)?void 0:`${json}
|
|
3
3
|
`})}catch(err){return{ok:!1,file:settingsFilePath,reason:err instanceof Error?err.message:String(err)}}if(rejected!==void 0)return{ok:!1,file:settingsFilePath,reason:rejected};return{ok:!0}}class JsonHookAdapter{supportsHooks(){return!0}activityDetailFromPayload(_kind,_payload){return}sessionFromPayload(_payload){return}supportsWorktreeSync(){return!1}async removeWorktreeSyncHook(_settingsFilePath){}gatedVerbs(){return GATED_TOOL_VERBS}async installActivityHooks(settingsFilePath,opts={}){let gated=this.gatedVerbs(),outcome=await editJsonSettings(settingsFilePath,(cur)=>mergeActivityHooks(cur,!0,this.eventMap,void 0,{extraArgs:["--engine",this.vendor],buildFilter:(spec)=>opts.toolEvents===!0||!gated.has(spec.verb)}));if(!outcome.ok)process.stderr.write(`[rove hooks] ${this.vendor}: skipped ${outcome.file}: ${outcome.reason}
|
|
4
4
|
`);return outcome}async removeActivityHooks(settingsFilePath){await editJsonSettings(settingsFilePath,(cur)=>mergeActivityHooks(cur,!1,this.eventMap))}async removeWorktreeWatchHook(settingsFilePath){await editJsonSettings(settingsFilePath,removeWorktreeWatchHook)}}var CLAUDE_HOOK_EVENT_MAP=[{event:"SessionStart",verb:"session-start"},{event:"UserPromptSubmit",verb:"turn-start"},{event:"Stop",verb:"turn-complete"},{event:"StopFailure",verb:"turn-failed"},{event:"Notification",matcher:"permission_prompt",verb:"awaiting-input"},{event:"Notification",matcher:"elicitation_dialog",verb:"awaiting-input"},{event:"SessionEnd",verb:"session-end"},{event:"PreCompact",verb:"pre-compact"},{event:"PostCompact",verb:"post-compact"},{event:"SubagentStart",verb:"subagent-start"},{event:"SubagentStop",verb:"subagent-stop"},{event:"PreToolUse",verb:"tool-pre"},{event:"PostToolUse",verb:"tool-post"},{event:"PostToolUseFailure",verb:"tool-failed"}],KOBE_HOOK_EVENTS=[...new Set(CLAUDE_HOOK_EVENT_MAP.map((e)=>e.event))];function failureFromErrorType(errorType){if(typeof errorType!=="string")return"other";if(errorType==="rate_limit"||errorType==="overloaded")return"rate_limit";if(errorType==="billing_error")return"billing";return"other"}function claudeSettingsPath(){return join2(vendorConfigHome("claude"),"settings.json")}var WORKTREE_SYNC_VERB="worktree-created";function mergeWorktreeSyncHook(current,command){let{hooks:rawHooks,...restSettings}=current,{WorktreeCreate,...otherHooks}=isObject(rawHooks)?rawHooks:{},prior=Array.isArray(WorktreeCreate)?WorktreeCreate:[],kept=removeRoveHooks(prior,[WORKTREE_SYNC_VERB]);if(command!==null)kept.push({hooks:[{type:"command",command}]});let nextHooks={...otherHooks};if(kept.length>0)nextHooks.WorktreeCreate=kept;return Object.keys(nextHooks).length>0?{...restSettings,hooks:nextHooks}:{...restSettings}}class ClaudeHookAdapter extends JsonHookAdapter{vendor="claude";eventMap=CLAUDE_HOOK_EVENT_MAP;globalSettingsPath(){return claudeSettingsPath()}activityDetailFromPayload(kind,payload){if(kind==="turn-failed")return{failure:failureFromErrorType(payload.error_type)};if(kind==="awaiting-input")return{waiting:payload.notification_type==="elicitation_dialog"?"input":"permission"};if(kind==="tool-pre"||kind==="tool-post"||kind==="tool-failed")return{tool:{...typeof payload.tool_name==="string"?{name:payload.tool_name}:{},...typeof payload.tool_use_id==="string"?{id:payload.tool_use_id}:{}}};if(kind==="pre-compact"||kind==="post-compact")return{compact:{trigger:payload.trigger==="manual"?"manual":"auto"}};if(kind==="subagent-start"||kind==="subagent-stop")return{subagent:{...typeof payload.agent_type==="string"?{type:payload.agent_type}:{},...typeof payload.agent_id==="string"?{id:payload.agent_id}:{}}};return}sessionFromPayload(payload){if(typeof payload.session_id!=="string"||!payload.session_id)return;return{sessionId:payload.session_id,...typeof payload.transcript_path==="string"&&payload.transcript_path?{transcriptPath:payload.transcript_path}:{}}}supportsWorktreeSync(){return!0}async removeWorktreeSyncHook(settingsFilePath){await editJsonSettings(settingsFilePath,(cur)=>mergeWorktreeSyncHook(cur,null))}}
|
|
5
|
-
export{roveCliInvocation,kobeHookInvocation,GATED_TOOL_VERBS,isObject,parseHookSettings,hasKobeActivityHooks,readSharedConfigSync,updateSharedJsonSync,JsonHookAdapter,CLAUDE_HOOK_EVENT_MAP,claudeSettingsPath,ClaudeHookAdapter};
|
|
5
|
+
export{roveCliInvocation,kobeHookInvocation,GATED_TOOL_VERBS,isObject,parseHookSettings,hasKobeActivityHooks,hookCommandQuoting,readSharedConfigSync,updateSharedJsonSync,JsonHookAdapter,CLAUDE_HOOK_EVENT_MAP,claudeSettingsPath,ClaudeHookAdapter};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{closeTab,engineTabArgv,initialTabs,setTabTitle,terminalTabsKey}from"./chunk-0vrv03qn.js";import{awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,enginePresence,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,initMarkerSaysFinished,isHostedTaskKey,killHostedSessions,listHostedSessions,listHostedSessionsOrNull,openHostedSessionHost,pastePromptWhenEngineUp,readPersistedTerminalDefaultColors,writeHostedPromptIfLive}from"./chunk-frdr9bjy.js";import{engineLaunchArgv}from"./chunk-xr30vfgt.js";import{loadStateFile,patchStateFile,updateStateFile}from"./chunk-3jh78dmc.js";function taskEngineArgv(task){return engineLaunchArgv({command:task.command,vendor:task.vendor})}function readTabsSnapshot(taskId){try{let snap=loadStateFile()[terminalTabsKey(taskId)];return snap&&Array.isArray(snap.tabs)?snap:void 0}catch{return}}function closeTabsSnapshot(taskId,tabId){let closing,key=terminalTabsKey(taskId);return updateStateFile((store)=>{let state=store[key];if(!state||!Array.isArray(state.tabs))return!1;if(closing=state.tabs.find((tab)=>tab.id===tabId),!closing)return!1;let{state:next,closedId}=closeTab(state,tabId,{allowEmpty:!0});if(!closedId)return closing=void 0,!1;store[key]=next;return}),closing}function renameTabsSnapshot(taskId,tabId,title){let found=!1,key=terminalTabsKey(taskId);return updateStateFile((store)=>{let state=store[key];if(!state||!Array.isArray(state.tabs))return!1;if(!state.tabs.some((tab)=>tab.id===tabId))return!1;found=!0;let next=setTabTitle(state,tabId,title);if(next===state)return!1;store[key]=next;return}),found}var aliveKeysOf=(sessions)=>new Set(sessions.filter((s)=>s.alive).map((s)=>s.key));function unregisteredTabIds(snapshot,taskId,sessions){let known=new Set((snapshot?.tabs??[]).map((t)=>t.id)),prefix=`${taskId}::`,out=[];for(let s of sessions){if(!s.alive||!s.key.startsWith(prefix))continue;let tabId=s.key.slice(prefix.length);if(tabId.includes("::"))continue;if(!known.has(tabId)&&!out.includes(tabId))out.push(tabId)}return out}var abnormalExit=(exit)=>exit&&(exit.code!==0||exit.signal!==null)?exit:null;function joinTaskTabs(snapshot,taskId,sessions,persistedExits={},liveVendors,engineAlive){let unknown=sessions===null,rows0=sessions??[],alive=aliveKeysOf(rows0),sessionExits=new Map(rows0.map((s)=>[s.key,s.exit])),deadExit=(key)=>{let ex=abnormalExit(sessionExits.get(key)??persistedExits[key]);if(!ex)return null;let record=persistedExits[key],sameDeath=record?.at===ex.at,tail=sameDeath?record?.tail:void 0,code=ex.code??(sameDeath?record?.code??null:null),layer=record?.layer??"pty";return{code,signal:ex.signal,at:ex.at,layer,...tail&&tail.length>0?{tail}:{}}},engineExit=(key)=>{let record=persistedExits[`${key}#engine`];if(!record)return null;let{code,signal,at,tail,atApproximate}=record;return{code,signal,at,layer:"engine",...atApproximate?{atApproximate}:{},...tail&&tail.length>0?{tail}:{}}},rows=(snapshot?.tabs??[]).map((t)=>{let key=`${taskId}::${t.id}`,isAlive=unknown?null:alive.has(key),walked=isAlive===!0&&liveVendors?.has(key)===!0?liveVendors.get(key)??null:void 0,engineIsAlive=engineAliveOf(key,isAlive,engineAlive);return{id:t.id,kind:t.kind,title:t.title??null,vendor:t.vendor??null,liveVendor:walked!==void 0?walked:t.liveVendor??null,lastTitle:t.lastTitle??null,autoTitle:t.autoTitle??null,alive:isAlive,engineAlive:engineIsAlive,exit:isAlive===!1?deadExit(key):engineIsAlive===!1?engineExit(key):null}});for(let tabId of unregisteredTabIds(snapshot,taskId,rows0))rows.push({id:tabId,kind:"engine",title:null,vendor:null,liveVendor:null,lastTitle:null,autoTitle:null,alive:!0,engineAlive:engineAliveOf(`${taskId}::${tabId}`,!0,engineAlive),exit:null,unregistered:!0});return rows}function engineAliveOf(key,isAlive,engineAlive){if(isAlive===null)return null;if(!isAlive)return!1;return engineAlive?.has(key)===!0?engineAlive.get(key)??null:null}function publishCliTabSnapshot(taskId,sessionId){if(!taskId)return;try{let key=terminalTabsKey(taskId);if(loadStateFile()[key]!==void 0)return;let seeded=initialTabs();patchStateFile({[key]:sessionId?{...seeded,tabs:seeded.tabs.map((t)=>t.kind==="engine"?{...t,sessionId,spawned:!0}:t)}:seeded})}catch{}}function markCliTabSession(taskId,tabId,sessionId){try{let key=terminalTabsKey(taskId),existing=loadStateFile()[key];if(!existing||!Array.isArray(existing.tabs))return;patchStateFile({[key]:{...existing,tabs:existing.tabs.map((t)=>t.id===tabId&&t.kind==="engine"?{...t,sessionId,spawned:!0}:t)}})}catch{}}function mintCliTab(taskId,vendor,command){let tabId="tab-1";try{let key=terminalTabsKey(taskId),existing=loadStateFile()[key],state=existing&&Array.isArray(existing.tabs)&&existing.tabs.length>0?existing:initialTabs(),ordinal=typeof state.nextOrdinal==="number"&&state.nextOrdinal>1?state.nextOrdinal:2;tabId=`tab-${ordinal}`,patchStateFile({[key]:{...state,tabs:[...state.tabs,{kind:"engine",id:tabId,title:null,ordinal,...vendor?{vendor}:{},...command?{engineCommand:command}:{}}],activeId:tabId,nextOrdinal:ordinal+1}})}catch{tabId=`tab-cli-${Date.now().toString(36)}`}return tabId}function restoredTabsOf(sessions,taskId,exceptKey){let prefix=`${taskId}::`,ids=[];for(let s of sessions){if(s.alive||s.restored!==!0||s.key===exceptKey||!s.key.startsWith(prefix))continue;let tab=s.key.slice(prefix.length);if(tab.includes("::"))continue;if(!ids.includes(tab))ids.push(tab)}let tabs=readTabsSnapshot(taskId)?.tabs??[];return ids.map((tab)=>{let sessionId=tabs.find((t)=>t.id===tab)?.sessionId;return sessionId?{tab,sessionId}:{tab}})}function restoredTabLaunch(task,tabId,worktreePath,shell){let tab=readTabsSnapshot(task.id)?.tabs.find((t)=>t.id===tabId&&t.kind==="engine");if(!tab)return null;let base=engineLaunchArgv({command:tab.engineCommand??(tab.vendor?void 0:task.command),vendor:tab.vendor??task.vendor,effort:task.modelEffort});return buildEngineSessionLaunch({task:{id:task.id,kind:task.kind??"task",vendor:tab.vendor??task.vendor,repo:task.repo},worktreePath,shell,argv:engineTabArgv(tab,base,!1,task.vendor),promptIntent:{kind:"none"},tabId})}class ApiError extends Error{code;data;constructor(message,code,data){super(message);this.code=code;this.data=data}}var DAEMON_CODE_PREFIX=/^([A-Z][A-Z0-9_]{2,}): /;function splitDaemonCode(message){let match=DAEMON_CODE_PREFIX.exec(message);if(!match?.[1])return null;return{code:match[1],rest:message.slice(match[0].length)}}function helpStep(verbName){return{hint:"run the verb's --help for its exact flag contract, then retry",nextCommandArgs:["api",verbName,"--help"]}}var VERB_GROUP_IDS=["discover","read","create","drive","edit","issues","workitems","routine","lifecycle","worktree","feedback"];var isTaskKey=isHostedTaskKey,findEngineKey=findHostedEngineKey,taskKeys=hostedTaskKeys,openPtyHost=openHostedSessionHost,ensurePtyHost=ensureHostedSessionHost,listSessions=listHostedSessions,listSessionsOrNull=listHostedSessionsOrNull,deliverToKey=deliverToHostedKey,writePrompt=writeHostedPromptIfLive,ENGINE_START_PROBE_MS=3000,ENGINE_START_POLL_MS=150,ENGINE_NOT_OBSERVED_REASON=`no engine process appeared in the session within ${ENGINE_START_PROBE_MS}ms`;function outcomeFields(outcome){if(!outcome)return{engineReady:!1,delivered:!1};return{engineReady:outcome.ready,delivered:!0,bytes:outcome.bytes,promptEcho:outcome.confirmed?"confirmed":"unconfirmed"}}async function deliverHostedPrompt(rpc,target,cwd,prompt,launch,opts){let{sessions=[]}=await rpc.request("pty.list",{}),existingKey=opts?.forceNew?null:findEngineKey(sessions,target.id,target.engineBin);if(existingKey){let pid=sessions.find((s)=>s.key===existingKey)?.pid,presence=await enginePresence(pid,target.engineBin,opts?.snapshot);if(presence==="unknown")throw new ApiError(`could not read the process table, so task ${target.id}'s engine tab (${existingKey}) could not be checked for a live engine`,"ENGINE_PROBE_FAILED",{hint:"the `ps` probe failed or timed out; retry, or check the machine's process table",nextCommandArgs:["api","pty-list"]});if(presence!=="engine")throw new ApiError(`task ${target.id}'s engine tab (${existingKey}) has no live engine process \u2014 its engine exited into a plain shell`,"ENGINE_NOT_RUNNING",{hint:"spawn a fresh engine tab for this prompt with --tab new",nextCommandArgs:["api","send","--task-id",target.id,"--tab","new","--prompt",prompt]});let outcome=await deliverToKey(rpc,existingKey,prompt);return{session:existingKey,pane:existingKey,started:!1,...outcomeFields(outcome)}}if(!opts?.forceNew){let aliveTabs=sessions.filter((s)=>s.alive&&isTaskKey(s.key,target.id)).map((s)=>s.key);if(aliveTabs.length>0)throw new ApiError(`task ${target.id} has live tabs (${aliveTabs.join(", ")}) but none resolves as its engine tab \u2014 refusing to spawn a new engine`,"NO_ENGINE_TAB",{hint:"address a live engine tab explicitly with --tab <tab-N> (see pty-list), or spawn a fresh engine tab with --tab new",nextCommandArgs:["api","pty-list"]})}let frozen=restoredTabsOf(sessions,target.id,launch.key),disclose=frozen.length>0?{frozenTabs:frozen}:{},staleCanonical=sessions.find((session)=>session.key===launch.key&&!session.alive);if(staleCanonical&&staleCanonical.restored!==!0)await rpc.request("pty.kill",{key:launch.key});let open=await rpc.request("pty.open",{key:launch.key,cwd,command:launch.command,defaultColors:readPersistedTerminalDefaultColors()});try{if(!open.alive)return{session:launch.key,pane:launch.key,started:open.created!==!1||open.respawned===!0,engineReady:!1,delivered:!1,...disclose};if(launch.firstMessage){let outcome=await pastePromptWhenEngineUp(rpc,launch.key,target.engineBin,launch.firstMessage,{initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs});return{session:launch.key,pane:launch.key,started:open.created!==!1||open.respawned===!0,...outcomeFields(outcome),...disclose}}let started=open.created!==!1||open.respawned===!0;if(open.created===!1&&open.respawned!==!0){let outcome=await writePrompt(rpc,launch.key,prompt);return{session:launch.key,pane:launch.key,started,...outcomeFields(outcome),...disclose}}let pendingInit={session:launch.key,pane:launch.key,started,engineReady:!1,delivered:!0,reason:"repo init script is still running; the engine has not started yet",...disclose};if(launch.initMarkerPath&&!initMarkerSaysFinished(launch.initMarkerPath))return pendingInit;if(await awaitEngineProcess(rpc,launch.key,target.engineBin,{timeoutMs:ENGINE_START_PROBE_MS,intervalMs:ENGINE_START_POLL_MS,snapshot:opts?.snapshot})===null){if(launch.initMarkerPath&&!initMarkerSaysFinished(launch.initMarkerPath)&&(await listSessions(rpc)).some((session)=>session.key===launch.key&&session.alive)&&!initMarkerSaysFinished(launch.initMarkerPath))return pendingInit;return{session:launch.key,pane:launch.key,started,engineReady:!1,delivered:!1,reason:await hostedSessionFailureLine(rpc,launch.key)??ENGINE_NOT_OBSERVED_REASON,...disclose}}return{session:launch.key,pane:launch.key,started,engineReady:!0,delivered:!0,...disclose}}finally{await rpc.request("pty.detach",{key:launch.key}).catch(()=>{})}}var killTaskSessions=killHostedSessions;
|
|
2
|
+
import{closeTab,engineTabArgv,initialTabs,setTabTitle,terminalTabsKey}from"./chunk-847gwrx2.js";import{awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,enginePresence,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,initMarkerSaysFinished,isHostedTaskKey,killHostedSessions,listHostedSessions,listHostedSessionsOrNull,openHostedSessionHost,pastePromptWhenEngineUp,readPersistedTerminalDefaultColors,writeHostedPromptIfLive}from"./chunk-d8hcpwr6.js";import{engineLaunchArgv}from"./chunk-yrmj16b9.js";import{loadStateFile,patchStateFile,updateStateFile}from"./chunk-3jh78dmc.js";function taskEngineArgv(task){return engineLaunchArgv({command:task.command,vendor:task.vendor})}function readTabsSnapshot(taskId){try{let snap=loadStateFile()[terminalTabsKey(taskId)];return snap&&Array.isArray(snap.tabs)?snap:void 0}catch{return}}function closeTabsSnapshot(taskId,tabId){let closing,key=terminalTabsKey(taskId);return updateStateFile((store)=>{let state=store[key];if(!state||!Array.isArray(state.tabs))return!1;if(closing=state.tabs.find((tab)=>tab.id===tabId),!closing)return!1;let{state:next,closedId}=closeTab(state,tabId,{allowEmpty:!0});if(!closedId)return closing=void 0,!1;store[key]=next;return}),closing}function renameTabsSnapshot(taskId,tabId,title){let found=!1,key=terminalTabsKey(taskId);return updateStateFile((store)=>{let state=store[key];if(!state||!Array.isArray(state.tabs))return!1;if(!state.tabs.some((tab)=>tab.id===tabId))return!1;found=!0;let next=setTabTitle(state,tabId,title);if(next===state)return!1;store[key]=next;return}),found}var aliveKeysOf=(sessions)=>new Set(sessions.filter((s)=>s.alive).map((s)=>s.key));function unregisteredTabIds(snapshot,taskId,sessions){let known=new Set((snapshot?.tabs??[]).map((t)=>t.id)),prefix=`${taskId}::`,out=[];for(let s of sessions){if(!s.alive||!s.key.startsWith(prefix))continue;let tabId=s.key.slice(prefix.length);if(tabId.includes("::"))continue;if(!known.has(tabId)&&!out.includes(tabId))out.push(tabId)}return out}var abnormalExit=(exit)=>exit&&(exit.code!==0||exit.signal!==null)?exit:null;function joinTaskTabs(snapshot,taskId,sessions,persistedExits={},liveVendors,engineAlive){let unknown=sessions===null,rows0=sessions??[],alive=aliveKeysOf(rows0),sessionExits=new Map(rows0.map((s)=>[s.key,s.exit])),deadExit=(key)=>{let ex=abnormalExit(sessionExits.get(key)??persistedExits[key]);if(!ex)return null;let record=persistedExits[key],sameDeath=record?.at===ex.at,tail=sameDeath?record?.tail:void 0,code=ex.code??(sameDeath?record?.code??null:null),layer=record?.layer??"pty";return{code,signal:ex.signal,at:ex.at,layer,...tail&&tail.length>0?{tail}:{}}},engineExit=(key)=>{let record=persistedExits[`${key}#engine`];if(!record)return null;let{code,signal,at,tail,atApproximate}=record;return{code,signal,at,layer:"engine",...atApproximate?{atApproximate}:{},...tail&&tail.length>0?{tail}:{}}},rows=(snapshot?.tabs??[]).map((t)=>{let key=`${taskId}::${t.id}`,isAlive=unknown?null:alive.has(key),walked=isAlive===!0&&liveVendors?.has(key)===!0?liveVendors.get(key)??null:void 0,engineIsAlive=engineAliveOf(key,isAlive,engineAlive);return{id:t.id,kind:t.kind,title:t.title??null,vendor:t.vendor??null,liveVendor:walked!==void 0?walked:t.liveVendor??null,lastTitle:t.lastTitle??null,autoTitle:t.autoTitle??null,alive:isAlive,engineAlive:engineIsAlive,exit:isAlive===!1?deadExit(key):engineIsAlive===!1?engineExit(key):null}});for(let tabId of unregisteredTabIds(snapshot,taskId,rows0))rows.push({id:tabId,kind:"engine",title:null,vendor:null,liveVendor:null,lastTitle:null,autoTitle:null,alive:!0,engineAlive:engineAliveOf(`${taskId}::${tabId}`,!0,engineAlive),exit:null,unregistered:!0});return rows}function engineAliveOf(key,isAlive,engineAlive){if(isAlive===null)return null;if(!isAlive)return!1;return engineAlive?.has(key)===!0?engineAlive.get(key)??null:null}function publishCliTabSnapshot(taskId,sessionId){if(!taskId)return;try{let key=terminalTabsKey(taskId);if(loadStateFile()[key]!==void 0)return;let seeded=initialTabs();patchStateFile({[key]:sessionId?{...seeded,tabs:seeded.tabs.map((t)=>t.kind==="engine"?{...t,sessionId,spawned:!0}:t)}:seeded})}catch{}}function markCliTabSession(taskId,tabId,sessionId){try{let key=terminalTabsKey(taskId),existing=loadStateFile()[key];if(!existing||!Array.isArray(existing.tabs))return;patchStateFile({[key]:{...existing,tabs:existing.tabs.map((t)=>t.id===tabId&&t.kind==="engine"?{...t,sessionId,spawned:!0}:t)}})}catch{}}function mintCliTab(taskId,vendor,command){let tabId="tab-1";try{let key=terminalTabsKey(taskId),existing=loadStateFile()[key],state=existing&&Array.isArray(existing.tabs)&&existing.tabs.length>0?existing:initialTabs(),ordinal=typeof state.nextOrdinal==="number"&&state.nextOrdinal>1?state.nextOrdinal:2;tabId=`tab-${ordinal}`,patchStateFile({[key]:{...state,tabs:[...state.tabs,{kind:"engine",id:tabId,title:null,ordinal,...vendor?{vendor}:{},...command?{engineCommand:command}:{}}],activeId:tabId,nextOrdinal:ordinal+1}})}catch{tabId=`tab-cli-${Date.now().toString(36)}`}return tabId}function restoredTabsOf(sessions,taskId,exceptKey){let prefix=`${taskId}::`,ids=[];for(let s of sessions){if(s.alive||s.restored!==!0||s.key===exceptKey||!s.key.startsWith(prefix))continue;let tab=s.key.slice(prefix.length);if(tab.includes("::"))continue;if(!ids.includes(tab))ids.push(tab)}let tabs=readTabsSnapshot(taskId)?.tabs??[];return ids.map((tab)=>{let sessionId=tabs.find((t)=>t.id===tab)?.sessionId;return sessionId?{tab,sessionId}:{tab}})}function restoredTabLaunch(task,tabId,worktreePath,shell){let tab=readTabsSnapshot(task.id)?.tabs.find((t)=>t.id===tabId&&t.kind==="engine");if(!tab)return null;let base=engineLaunchArgv({command:tab.engineCommand??(tab.vendor?void 0:task.command),vendor:tab.vendor??task.vendor,effort:task.modelEffort});return buildEngineSessionLaunch({task:{id:task.id,kind:task.kind??"task",vendor:tab.vendor??task.vendor,repo:task.repo},worktreePath,shell,argv:engineTabArgv(tab,base,!1,task.vendor),promptIntent:{kind:"none"},tabId})}class ApiError extends Error{code;data;constructor(message,code,data){super(message);this.code=code;this.data=data}}var DAEMON_CODE_PREFIX=/^([A-Z][A-Z0-9_]{2,}): /;function splitDaemonCode(message){let match=DAEMON_CODE_PREFIX.exec(message);if(!match?.[1])return null;return{code:match[1],rest:message.slice(match[0].length)}}function helpStep(verbName){return{hint:"run the verb's --help for its exact flag contract, then retry",nextCommandArgs:["api",verbName,"--help"]}}var VERB_GROUP_IDS=["discover","read","create","drive","edit","issues","workitems","routine","lifecycle","worktree","feedback"];var isTaskKey=isHostedTaskKey,findEngineKey=findHostedEngineKey,taskKeys=hostedTaskKeys,openPtyHost=openHostedSessionHost,ensurePtyHost=ensureHostedSessionHost,listSessions=listHostedSessions,listSessionsOrNull=listHostedSessionsOrNull,deliverToKey=deliverToHostedKey,writePrompt=writeHostedPromptIfLive,ENGINE_START_PROBE_MS=3000,ENGINE_START_POLL_MS=150,ENGINE_NOT_OBSERVED_REASON=`no engine process appeared in the session within ${ENGINE_START_PROBE_MS}ms`;function outcomeFields(outcome){if(!outcome)return{engineReady:!1,delivered:!1};return{engineReady:outcome.ready,delivered:!0,bytes:outcome.bytes,promptEcho:outcome.confirmed?"confirmed":"unconfirmed",...outcome.queued?{queued:!0}:{}}}async function deliverHostedPrompt(rpc,target,cwd,prompt,launch,opts){let{sessions=[]}=await rpc.request("pty.list",{}),existingKey=opts?.forceNew?null:findEngineKey(sessions,target.id,target.engineBin);if(existingKey){let pid=sessions.find((s)=>s.key===existingKey)?.pid,presence=await enginePresence(pid,target.engineBin,opts?.snapshot);if(presence==="unknown")throw new ApiError(`could not read the process table, so task ${target.id}'s engine tab (${existingKey}) could not be checked for a live engine`,"ENGINE_PROBE_FAILED",{hint:"the `ps` probe failed or timed out; retry, or check the machine's process table",nextCommandArgs:["api","pty-list"]});if(presence!=="engine")throw new ApiError(`task ${target.id}'s engine tab (${existingKey}) has no live engine process \u2014 its engine exited into a plain shell`,"ENGINE_NOT_RUNNING",{hint:"spawn a fresh engine tab for this prompt with --tab new",nextCommandArgs:["api","send","--task-id",target.id,"--tab","new","--prompt",prompt]});let outcome=await deliverToKey(rpc,existingKey,prompt);return{session:existingKey,pane:existingKey,started:!1,...outcomeFields(outcome)}}if(!opts?.forceNew){let aliveTabs=sessions.filter((s)=>s.alive&&isTaskKey(s.key,target.id)).map((s)=>s.key);if(aliveTabs.length>0)throw new ApiError(`task ${target.id} has live tabs (${aliveTabs.join(", ")}) but none resolves as its engine tab \u2014 refusing to spawn a new engine`,"NO_ENGINE_TAB",{hint:"address a live engine tab explicitly with --tab <tab-N> (see pty-list), or spawn a fresh engine tab with --tab new",nextCommandArgs:["api","pty-list"]})}let frozen=restoredTabsOf(sessions,target.id,launch.key),disclose=frozen.length>0?{frozenTabs:frozen}:{},staleCanonical=sessions.find((session)=>session.key===launch.key&&!session.alive);if(staleCanonical&&staleCanonical.restored!==!0)await rpc.request("pty.kill",{key:launch.key});let open=await rpc.request("pty.open",{key:launch.key,cwd,command:launch.command,defaultColors:readPersistedTerminalDefaultColors()});try{if(!open.alive)return{session:launch.key,pane:launch.key,started:open.created!==!1||open.respawned===!0,engineReady:!1,delivered:!1,...disclose};if(launch.firstMessage){let outcome=await pastePromptWhenEngineUp(rpc,launch.key,target.engineBin,launch.firstMessage,{initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs});return{session:launch.key,pane:launch.key,started:open.created!==!1||open.respawned===!0,...outcomeFields(outcome),...disclose}}let started=open.created!==!1||open.respawned===!0;if(open.created===!1&&open.respawned!==!0){let outcome=await writePrompt(rpc,launch.key,prompt);return{session:launch.key,pane:launch.key,started,...outcomeFields(outcome),...disclose}}let pendingInit={session:launch.key,pane:launch.key,started,engineReady:!1,delivered:!0,reason:"repo init script is still running; the engine has not started yet",...disclose};if(launch.initMarkerPath&&!initMarkerSaysFinished(launch.initMarkerPath))return pendingInit;if(await awaitEngineProcess(rpc,launch.key,target.engineBin,{timeoutMs:ENGINE_START_PROBE_MS,intervalMs:ENGINE_START_POLL_MS,snapshot:opts?.snapshot})===null){if(launch.initMarkerPath&&!initMarkerSaysFinished(launch.initMarkerPath)&&(await listSessions(rpc)).some((session)=>session.key===launch.key&&session.alive)&&!initMarkerSaysFinished(launch.initMarkerPath))return pendingInit;return{session:launch.key,pane:launch.key,started,engineReady:!1,delivered:!1,reason:await hostedSessionFailureLine(rpc,launch.key)??ENGINE_NOT_OBSERVED_REASON,...disclose}}return{session:launch.key,pane:launch.key,started,engineReady:!0,delivered:!0,...disclose}}finally{await rpc.request("pty.detach",{key:launch.key}).catch(()=>{})}}var killTaskSessions=killHostedSessions;
|
|
3
3
|
export{ApiError,splitDaemonCode,helpStep,VERB_GROUP_IDS,taskEngineArgv,readTabsSnapshot,closeTabsSnapshot,renameTabsSnapshot,unregisteredTabIds,joinTaskTabs,publishCliTabSnapshot,markCliTabSession,mintCliTab,restoredTabLaunch,isTaskKey,findEngineKey,taskKeys,openPtyHost,ensurePtyHost,listSessions,listSessionsOrNull,deliverToKey,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON,outcomeFields,deliverHostedPrompt,killTaskSessions};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{BUNDLED_THEME_JSONS}from"./chunk-z7c6nap0.js";import{DEFAULT_LOCALE,isLocaleId}from"./chunk-
|
|
2
|
+
import{BUNDLED_THEME_JSONS}from"./chunk-z7c6nap0.js";import{DEFAULT_LOCALE,isLocaleId}from"./chunk-qqh9aef5.js";import{kvStatePath}from"./chunk-q5jhy3t8.js";import{RGBA as RGBA2}from"@opentui/core";import{RGBA}from"@opentui/core";var HOST_TEXT_MIN_CONTRAST=4.5;function srgbChannelToLinear(c){let v=c/255;return v<=0.04045?v/12.92:((v+0.055)/1.055)**2.4}function relativeLuminance([r,g,b]){return 0.2126*srgbChannelToLinear(r)+0.7152*srgbChannelToLinear(g)+0.0722*srgbChannelToLinear(b)}function contrastRatioTriplet(fg,bg){let l1=relativeLuminance(fg),l2=relativeLuminance(bg),lighter=Math.max(l1,l2),darker=Math.min(l1,l2);return(lighter+0.05)/(darker+0.05)}function rgbToHsl([r,g,b]){let rn=r/255,gn=g/255,bn=b/255,max=Math.max(rn,gn,bn),min=Math.min(rn,gn,bn),l=(max+min)/2;if(max===min)return[0,0,l];let d=max-min,s=l>0.5?d/(2-max-min):d/(max+min),h;if(max===rn)h=((gn-bn)/d+(gn<bn?6:0))*60;else if(max===gn)h=((bn-rn)/d+2)*60;else h=((rn-gn)/d+4)*60;return[h,s,l]}function hslToRgb(h,s,l){if(s===0){let v=Math.round(l*255);return[v,v,v]}let q=l<0.5?l*(1+s):l+s-l*s,p=2*l-q,channel=(t)=>{let tn=t;if(tn<0)tn+=1;if(tn>1)tn-=1;let c=tn<0.16666666666666666?p+(q-p)*6*tn:tn<0.5?q:tn<0.6666666666666666?p+(q-p)*(0.6666666666666666-tn)*6:p;return Math.round(c*255)};return[channel(h/360+0.3333333333333333),channel(h/360),channel(h/360-0.3333333333333333)]}var MID_HOST_LUMINANCE=0.5;function ensureContrast(fg,bg,minRatio=HOST_TEXT_MIN_CONTRAST){let fgInts=fg.toInts(),bgInts=bg.toInts(),fgTriplet=[fgInts[0],fgInts[1],fgInts[2]],bgTriplet=[bgInts[0],bgInts[1],bgInts[2]];if(contrastRatioTriplet(fgTriplet,bgTriplet)>=minRatio)return fg;let[h,s,l]=rgbToHsl(fgTriplet),lighten=relativeLuminance(bgTriplet)<=MID_HOST_LUMINANCE,at=(lightness)=>contrastRatioTriplet(hslToRgb(h,s,lightness),bgTriplet),lo=lighten?l:0,hi=lighten?1:l;for(let i=0;i<32;i++){let mid=(lo+hi)/2;if(at(mid)>=minRatio)if(lighten)hi=mid;else lo=mid;else if(lighten)lo=mid;else hi=mid}let[r,g,b]=hslToRgb(h,s,lighten?hi:lo);return RGBA.fromInts(r,g,b,fgInts[3])}var BUNDLED_THEMES=BUNDLED_THEME_JSONS,DEFAULT_THEME="claude";function hasBundledTheme(name){return Boolean(BUNDLED_THEMES[name])}var FOCUS_ACCENT_SLOTS=["primary","success","info"];function resolveTheme(theme,mode="dark"){let defs=theme.defs??{};function resolve(c,chain=[]){if(typeof c==="string"){if(c==="transparent"||c==="none")return RGBA2.fromInts(0,0,0,0);if(c.startsWith("#"))return RGBA2.fromHex(c);if(chain.includes(c))return RGBA2.fromInts(0,0,0);let next=defs[c]??theme.theme[c];if(next===void 0)return RGBA2.fromInts(0,0,0);return resolve(next,[...chain,c])}return resolve(c[mode],chain)}let out={};for(let[k,v]of Object.entries(theme.theme))out[k]=resolve(v);let text=out.text??RGBA2.fromHex("#ffffff"),background=out.background??RGBA2.fromHex("#000000");return{...{primary:out.primary??text,secondary:out.secondary??text,accent:out.accent??out.primary??text,error:out.error??text,warning:out.warning??text,warningOnHost:out.warning??text,success:out.success??text,info:out.info??text,text,textMuted:out.textMuted??text,background,backgroundPanel:out.backgroundPanel??background,backgroundElement:out.backgroundElement??background,backgroundMenu:out.backgroundMenu??out.backgroundElement??background,backgroundDialog:out.backgroundDialog??out.backgroundPanel??background,border:out.border??text,borderActive:out.borderActive??out.border??text,borderSubtle:out.borderSubtle??out.border??text,diffAdded:out.diffAdded??out.success??text,diffRemoved:out.diffRemoved??out.error??text,diffContext:out.diffContext??out.textMuted??text,diffHunkHeader:out.diffHunkHeader??out.textMuted??text,diffAddedBg:out.diffAddedBg??background,diffRemovedBg:out.diffRemovedBg??background,selectedListItemText:out.selectedListItemText??background},...out}}function applyDisplayOverlay(base,focusAccent,transparentBackground,hostBackground){let v={...base,focusAccent:base[focusAccent]??base.primary,warningOnHost:base.warning};if(!transparentBackground)return v;let[backgroundR,backgroundG,backgroundB]=base.background.toInts(),[panelR,panelG,panelB]=base.backgroundPanel.toInts(),transparent={...v,background:RGBA2.fromInts(backgroundR,backgroundG,backgroundB,0),backgroundPanel:RGBA2.fromInts(panelR,panelG,panelB,0)};if(!hostBackground)return transparent;return{...transparent,text:ensureContrast(transparent.text,hostBackground),textMuted:ensureContrast(transparent.textMuted,hostBackground),warningOnHost:ensureContrast(transparent.warning,hostBackground)}}import{readFileSync}from"fs";var LOCALE_KEY="locale";function defaultTransparentBackground(platform=process.platform){return platform!=="win32"}function readPersistedUiPrefs(fallbackTheme,isKnownTheme=hasBundledTheme){try{let parsed=JSON.parse(readFileSync(kvStatePath(),"utf8")),theme=typeof parsed.activeTheme==="string"&&isKnownTheme(parsed.activeTheme)?parsed.activeTheme:fallbackTheme,transparent=typeof parsed.transparentBackground==="boolean"?parsed.transparentBackground:defaultTransparentBackground(),focusAccent=typeof parsed.focusAccent==="string"&&FOCUS_ACCENT_SLOTS.includes(parsed.focusAccent)?parsed.focusAccent:null,locale=isLocaleId(parsed[LOCALE_KEY])?parsed[LOCALE_KEY]:DEFAULT_LOCALE;return{theme,transparent,focusAccent,locale}}catch{return{theme:fallbackTheme,transparent:defaultTransparentBackground(),focusAccent:null,locale:DEFAULT_LOCALE}}}
|
|
3
3
|
export{BUNDLED_THEMES,DEFAULT_THEME,FOCUS_ACCENT_SLOTS,resolveTheme,applyDisplayOverlay,LOCALE_KEY,readPersistedUiPrefs};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{findBinding,formatChord}from"./chunk-
|
|
2
|
+
import{findBinding,formatChord}from"./chunk-fprjrr5e.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};
|