@sma1lboy/rove 0.9.192 → 0.9.194
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-n4zhfjrv.js → chunk-00t0rc5r.js} +1 -1
- package/dist/cli/{chunk-ts0078by.js → chunk-01knbyag.js} +1 -1
- package/dist/cli/chunk-1ve1cdmr.js +8 -0
- package/dist/cli/{chunk-42sc0emk.js → chunk-27xs13g3.js} +1 -1
- package/dist/cli/{chunk-9qf62gnc.js → chunk-3dv9vdpj.js} +3 -3
- package/dist/cli/{chunk-738d2s48.js → chunk-3hw8k6kt.js} +2 -2
- package/dist/cli/{chunk-vas2mpdv.js → chunk-45qdhgq4.js} +1 -1
- package/dist/cli/{chunk-hxmzxn22.js → chunk-4qasm68c.js} +1 -1
- package/dist/cli/{chunk-xdc8zk9x.js → chunk-54jkwkrp.js} +1 -1
- package/dist/cli/{chunk-65b2xnba.js → chunk-58hejzp4.js} +1 -1
- package/dist/cli/{chunk-6e07s3qj.js → chunk-5mbv38x2.js} +1 -1
- package/dist/cli/{chunk-zw9q9da9.js → chunk-5r2b93v1.js} +1 -1
- package/dist/cli/{chunk-sceaevbq.js → chunk-5t03tk3n.js} +2 -2
- package/dist/cli/{chunk-6ymf66mq.js → chunk-6dgyb7sq.js} +1 -1
- package/dist/cli/{chunk-frprsqdw.js → chunk-71czj7z7.js} +1 -1
- package/dist/cli/{chunk-9756pmqx.js → chunk-7wehmetm.js} +1 -1
- package/dist/cli/{chunk-whe3w5jh.js → chunk-94ej2x6m.js} +2 -2
- package/dist/cli/{chunk-e4804kqb.js → chunk-a57x834f.js} +1 -1
- package/dist/cli/{chunk-ms69jdrr.js → chunk-aas47qdk.js} +1 -1
- package/dist/cli/{chunk-6d7rjjbb.js → chunk-ajtw0hkk.js} +1 -1
- package/dist/cli/{chunk-kks0vy2x.js → chunk-cxzm2fp7.js} +1 -1
- package/dist/cli/{chunk-9kf9v85y.js → chunk-cyz8gvph.js} +1 -1
- package/dist/cli/chunk-e4dmvkd7.js +3 -0
- package/dist/cli/{chunk-psgaps88.js → chunk-e788rssd.js} +1 -1
- package/dist/cli/{chunk-day3fqg9.js → chunk-fba42xg6.js} +1 -1
- package/dist/cli/{chunk-pkckq6ns.js → chunk-fg7s9rcf.js} +1 -1
- package/dist/cli/{chunk-qadaqgnz.js → chunk-fx98pmwf.js} +1 -1
- package/dist/cli/{chunk-yqffntmy.js → chunk-gfma7jt9.js} +1 -1
- package/dist/cli/{chunk-7vjv237v.js → chunk-h6mmcf6y.js} +2 -2
- package/dist/cli/{chunk-tgafcwp9.js → chunk-j19ax03g.js} +1 -1
- package/dist/cli/{chunk-ejbhw0y1.js → chunk-jrkaf2yf.js} +1 -1
- package/dist/cli/{chunk-zb55a46t.js → chunk-kav5p2qb.js} +1 -1
- package/dist/cli/chunk-kmsnrf9m.js +3 -0
- package/dist/cli/{chunk-gg6p708e.js → chunk-pnjn7zfk.js} +1 -1
- package/dist/cli/{chunk-np8mrc2m.js → chunk-qnj7vk5g.js} +1 -1
- package/dist/cli/{chunk-d7bdt1td.js → chunk-qzhkpjx4.js} +1 -1
- package/dist/cli/{chunk-c60a4k2q.js → chunk-rrv7p1bn.js} +1 -1
- package/dist/cli/{chunk-ms9pzccb.js → chunk-s8xg3et8.js} +1 -1
- package/dist/cli/{chunk-4kyjgysj.js → chunk-sgrbaynq.js} +1 -1
- package/dist/cli/{chunk-pf4jey48.js → chunk-t0q7pezp.js} +1 -1
- package/dist/cli/{chunk-8gmwa1fs.js → chunk-vcfvq6yy.js} +1 -1
- package/dist/cli/{chunk-p4wqpc6a.js → chunk-vqra03tc.js} +4 -4
- package/dist/cli/{chunk-r120ye6v.js → chunk-w8f54sr1.js} +1 -1
- package/dist/cli/{chunk-9vqkh1jv.js → chunk-weyjw7zs.js} +1 -1
- package/dist/cli/{chunk-674es6he.js → chunk-yfkr1fem.js} +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/cli/kobe.js +1 -1
- package/dist/cli/rove.js +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-646ss2m1.js +0 -3
- package/dist/cli/chunk-f60f0zqm.js +0 -8
- package/dist/cli/chunk-g1jhm3pb.js +0 -3
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{describeAccount,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-
|
|
2
|
+
import{describeAccount,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-5mbv38x2.js";import{t}from"./chunk-x2c7ehve.js";import{createInterface}from"readline";function daemonRestartFix(cliName,reason){return{kind:"run",id:"daemon-restart",label:t(`doctor.fix.${reason}`),command:[cliName,"daemon","restart"],why:t("doctor.fix.daemonRestartWhy")}}function skillInstallFix(installCommand,stale){return{kind:"run",id:"skill-install",label:t(stale?"doctor.fix.skillStale":"doctor.fix.skillMissing"),command:installCommand.split(" "),why:t("doctor.fix.skillInstallWhy")}}function resetManualFix(cliName,reason){return{kind:"manual",id:`reset:${reason}`,label:t(`doctor.fix.${reason}`),action:`${cliName} reset`,why:t("doctor.fix.resetWhy")}}function killOrphansManualFix(cliName,count){return{kind:"manual",id:"kill-orphans",label:t("doctor.fix.orphans",{count}),action:`${cliName} doctor --kill-orphans`,why:t("doctor.fix.orphansWhy")}}function engineTabsManualFix(){return{kind:"manual",id:"engine-tabs",label:t("doctor.fix.engineTabs"),action:t("doctor.fix.engineTabsAction"),why:t("doctor.fix.engineTabsWhy")}}function reinstallManualFix(){return{kind:"manual",id:"reinstall",label:t("doctor.fix.staleInstall"),action:t("doctor.fix.staleInstallAction"),why:t("doctor.fix.staleInstallWhy")}}function spawnHelperFix(paths){return{kind:"run",id:"spawn-helper-chmod",label:t("doctor.fix.spawnHelper"),command:["chmod","755",...paths],why:t("doctor.fix.spawnHelperWhy")}}function humanOnlyFix(reason,vars){return{kind:"manual",id:reason,label:t(`doctor.fix.${reason}`),action:t(`doctor.fix.${reason}Action`,vars),why:t("doctor.fix.humanOnlyWhy")}}function noEngineFix(signedOut){return signedOut.length>0?humanOnlyFix("noEngineLogin",{list:signedOut.join(", ")}):humanOnlyFix("noEngine")}function noEngineAction(signedOut){return signedOut.length>0?t("doctor.fix.noEngineLoginAction",{list:signedOut.join(", ")}):t("doctor.fix.noEngineAction")}function dedupeFixes(fixes){let seen=new Set;return fixes.filter((fix)=>{if(seen.has(fix.id))return!1;return seen.add(fix.id),!0})}async function applyFixes(collected,rt){let fixes=dedupeFixes(collected);if(fixes.length===0){rt.out(""),rt.out(t("doctor.fix.none"));return}let runnable=fixes.filter((fix)=>fix.kind==="run");if(runnable.length>0){rt.out(""),rt.out(t("doctor.fix.header"));for(let fix of runnable){if(rt.out(` ${fix.label}`),rt.out(` ${t("doctor.fix.willRun",{command:fix.command.join(" ")})}`),rt.out(` ${fix.why}`),!rt.interactive)continue;if(!await rt.confirm(` ${t("doctor.fix.confirmPrompt")}`)){rt.out(` ${t("doctor.fix.skipped")}`);continue}let code=await rt.exec(fix.command);rt.out(code===0?` ${t("doctor.fix.done")}`:` ${t("doctor.fix.failed",{code})}`)}if(!rt.interactive)rt.out(` ${t("doctor.fix.nonInteractive")}`)}let manual=fixes.filter((fix)=>fix.kind==="manual");if(manual.length>0){rt.out(""),rt.out(t("doctor.fix.manualHeader"));for(let fix of manual)rt.out(` ${fix.label}`),rt.out(` \u2192 ${fix.action}`),rt.out(` ${fix.why}`)}}async function confirmTty(question){let readline=createInterface({input:process.stdin,output:process.stdout});try{let answer=await new Promise((resolve)=>readline.question(question,resolve));return answer.trim().toLowerCase()==="y"||answer.trim().toLowerCase()==="yes"}finally{readline.close()}}async function execInherited(command){try{return await Bun.spawn([...command],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited}catch{return 127}}function defaultFixRuntime(){return{confirm:confirmTty,exec:execInherited,out:(line)=>console.log(line),interactive:process.stdin.isTTY===!0}}async function probeGit(){try{let proc=Bun.spawn(["git","--version"],{stdin:"ignore",stdout:"pipe",stderr:"ignore"}),text=(await new Response(proc.stdout).text()).trim();if(await proc.exited===0&&text)return{line:`git: \u2713 ${text}`,found:!0}}catch{}return{line:"git: \u2717 not found on PATH",found:!1}}function binaryLabel(binary){return binary.found?`\u2713 ${binary.path}`:`\u2717 ${binary.error}`}async function probeEngines(){let statuses=await detectEngineStatuses(await probeableEngineIds()),lines=["engines:"];for(let status of statuses){let account=describeAccount(status.account),name=`${status.vendor.padEnd(7)} `;if(lines.push(` ${name}${binaryLabel(status.binary)}${status.binary.found?` \u2014 ${account}`:""}`),status.accountError)lines.push(` \u26A0 ${status.accountError}`)}let{usable,signedOut}=summarizeEngines(statuses);return{lines,anyUsable:usable.length>0,signedOut}}async function checkOnboardingEnv(){let[git,engines]=await Promise.all([probeGit(),probeEngines()]);return{git,engines}}
|
|
3
3
|
export{daemonRestartFix,skillInstallFix,resetManualFix,killOrphansManualFix,engineTabsManualFix,reinstallManualFix,spawnHelperFix,humanOnlyFix,noEngineFix,noEngineAction,applyFixes,defaultFixRuntime,probeGit,probeEngines,checkOnboardingEnv};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{applyOnboardingChoices,detectShell,envReadyForTasks,installCompletions,maybeRunOnboarding}from"./chunk-
|
|
2
|
+
import{applyOnboardingChoices,detectShell,envReadyForTasks,installCompletions,maybeRunOnboarding}from"./chunk-h6mmcf6y.js";import"./chunk-ajtw0hkk.js";import"./chunk-5mbv38x2.js";import"./chunk-j19ax03g.js";import"./chunk-yybpg7fh.js";import"./chunk-fhch0x0q.js";import"./chunk-00t0rc5r.js";import"./chunk-yfkr1fem.js";import"./chunk-x2c7ehve.js";import"./chunk-22jgttzv.js";import"./chunk-sdyzxayr.js";import"./chunk-qnj7vk5g.js";import"./chunk-kav5p2qb.js";import"./chunk-kx3kydwv.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-sgrbaynq.js";import"./chunk-jvxh93nz.js";import"./chunk-2brn8e1y.js";import"./chunk-th4jd4sd.js";import"./chunk-r92b9j14.js";import"./chunk-aep7gvh4.js";import"./chunk-7kysxgbq.js";import"./chunk-krpsfcda.js";import"./chunk-xy8be792.js";import"./chunk-9ydhv2zb.js";import"./chunk-40dgv828.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-05jej26n.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import"./chunk-9prawccj.js";import"./chunk-8cjr5ypt.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import"./chunk-pxk2c2vj.js";import"./chunk-wqfp8d9w.js";export{maybeRunOnboarding,installCompletions,envReadyForTasks,detectShell,applyOnboardingChoices};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{embeddedTerminalEnv}from"./chunk-ef39ym8f.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,clearFrozenSessions,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-2cy0c03r.js";import{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{writeTextAtomic}from"./chunk-xsrcwcjc.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-rcyasw34.js";import{DEFAULT_TERMINAL_COLORS,foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors}from"./chunk-7q67dz4c.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{recordPtyExit}from"./chunk-a74pa16c.js";import"./chunk-w25b7xxz.js";import{DAEMON_PROTOCOL_VERSION,frameToLine}from"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import{CURRENT_VERSION}from"./chunk-4kyjgysj.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import"./chunk-q5jhy3t8.js";import{listenOnUnixSocket}from"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import{ensureOwnerOnlyStateDir}from"./chunk-9prawccj.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,isWindowsPipePath,legacyPtyHostPidPath,legacyPtyHostSocketPath,resolveDaemonHomeDir}from"./chunk-8cjr5ypt.js";import"./chunk-sb0ns0c7.js";import{COMPAT_STATE_DIR_BASENAME,ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";function formatPtyHostLine(event,message,now=new Date){return`[${now.toISOString()}] pty-host [${event}]: ${message}`}import{readFileSync}from"fs";import{mkdir,unlink}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync,symlinkSync}from"fs";import{homedir}from"os";import{join}from"path";var PTY_HOST_DATA_ENTRIES=["pty-exits.json","pty-sessions"];function lstatIfExists(path){try{return lstatSync(path)}catch{return}}function migrateLegacyPtyHostData(homeDir=readRoveHomeDirEnv()??homedir()){let canonicalDir=join(homeDir,ROVE_STATE_DIR_BASENAME),legacyDir=join(homeDir,COMPAT_STATE_DIR_BASENAME);if(canonicalDir===legacyDir)return[];let moved=[];for(let name of PTY_HOST_DATA_ENTRIES){let canonical=join(canonicalDir,name),legacy=join(legacyDir,name);try{if(existsSync(canonical))continue;let stat=lstatIfExists(legacy);if(!stat||stat.isSymbolicLink())continue;mkdirSync(canonicalDir,{recursive:!0}),renameSync(legacy,canonical),moved.push(name);try{symlinkSync(canonical,legacy)}catch{}}catch{}}return moved}import{randomUUID as randomUUID2}from"crypto";function bunTerminalDriver(spawn){let spawnTerminal=spawn??((argv,options)=>Bun.spawn(argv,options));return(request)=>{let proc=spawnTerminal([...request.argv],{cwd:request.cwd,env:request.env,terminal:{cols:request.cols,rows:request.rows,name:"xterm-256color",data:(_terminal,data)=>request.onData(data)}});return{pid:proc.pid,exited:proc.exited.then(()=>({code:proc.exitCode??null,signal:proc.signalCode??null}),()=>({code:null,signal:null})),write:(data)=>proc.terminal?.write(data),resize:(cols,rows)=>proc.terminal?.resize(cols,rows),close:()=>proc.terminal?.close(),kill:(signal)=>proc.kill(signal)}}}import{randomUUID}from"crypto";import{StringDecoder}from"string_decoder";function freshSessionState(key,spec,argv){return{key,generation:randomUUID(),cwd:spec.cwd,proc:null,alive:!0,chunks:[],bytes:0,totalBytes:0,cols:spec.cols??80,rows:spec.rows??24,command:argv,title:"",titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:parseTerminalDefaultColors(spec.defaultColors)??DEFAULT_TERMINAL_COLORS,sinks:new Map,parked:!1,parkedScreenBytes:0,exit:null,restored:!1,lastFreezeAtMs:0,frozenTotalBytes:0}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,totalBytes:s.totalBytes,parked:s.parked,parkedScreenBytes:s.parkedScreenBytes,exit:s.exit,restored:s.restored||void 0}}function describeExit(exit){if(exit?.signal)return` (signal ${exit.signal})`;if(exit&&exit.code!==null)return` (code ${exit.code})`;return" (cause unknown)"}function ringTail(chunks,bytes,maxBytes){let skip=Math.max(0,bytes-maxBytes),seen=0,parts=[];for(let chunk of chunks){if(seen+chunk.byteLength>skip)parts.push(seen>=skip?chunk:chunk.subarray(skip-seen));seen+=chunk.byteLength}return Buffer.concat(parts).toString("utf8")}function hostStats(sessions,perSessionCap,parkRestoreDeltas,parkRestoreFallbacks){let ringBytes=0,count=0,parkedSessions=0,parkedScreenBytes=0;for(let session of sessions)if(count++,ringBytes+=session.bytes,session.parked)parkedSessions++,parkedScreenBytes+=session.parkedScreenBytes;return{ringBytes,ringCapacityBytes:count*perSessionCap,parkedSessions,parkedScreenBytes,parkRestoreDeltas,parkRestoreFallbacks}}var OSC_TITLE_RE=/\x1b\][02];([^\x07\x1b]*)(?:\x07|\x1b\\)/g,TITLE_CARRY_CAP=1024;function titleCarryFrom(rest){let osc=rest.lastIndexOf("\x1B]");if(osc!==-1)return rest.slice(osc,osc+TITLE_CARRY_CAP);return rest.endsWith("\x1B")?"\x1B":""}function foldOscTitle(prevCarry,chunkText){let text=prevCarry+chunkText,title=null,end=0;OSC_TITLE_RE.lastIndex=0;for(let match=OSC_TITLE_RE.exec(text);match;match=OSC_TITLE_RE.exec(text))title=match[1]??"",end=match.index+match[0].length;return{title,carry:titleCarryFrom(text.slice(end))}}function scanOscTitle(session,buf){let{title,carry}=foldOscTitle(session.titleCarry,session.titleDecoder.write(buf));if(title!==null)session.title=title;session.titleCarry=carry}function peekRing(session,sinceOffset){if(!session)return{exists:!1,alive:!1,pid:null,offset:0,data:"",sinceValid:!1,exit:null};let windowStart=session.totalBytes-session.bytes,buf=Buffer.concat(session.chunks),sinceValid=!1;if(sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes)buf=buf.subarray(sinceOffset-windowStart),sinceValid=!0;return{exists:!0,alive:session.alive,pid:session.proc?.pid??null,offset:session.totalBytes,data:buf.toString("base64"),sinceValid,exit:session.exit??null}}async function settledWithin(exited,ms){let timer,settled=await Promise.race([exited.then(()=>!0,()=>!0),new Promise((resolve)=>{timer=setTimeout(()=>resolve(!1),ms)})]);if(timer)clearTimeout(timer);return settled}function signalProcessGroup(pid,signal,fallback,platform=process.platform,onSignal){if(platform!=="win32"&&pid>1)try{process.kill(-pid,signal),onSignal?.(`sent ${signal} to process group -${pid}`);return}catch{}try{fallback(),onSignal?.(`sent ${signal} to pid ${pid} (per-process fallback)`)}catch{}}var TERMINATION_GRACE_MS=500;async function terminatePtyChild(proc,onSettled,onSignal){if(signalProcessGroup(proc.pid,"SIGTERM",()=>proc.kill("SIGTERM"),process.platform,onSignal),!await settledWithin(proc.exited,TERMINATION_GRACE_MS))signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS);onSettled()}class PtyChildController{deps;constructor(deps){this.deps=deps}spawn(key,spec,spare=!1){let argv=spec.command&&spec.command.length>0?[...spec.command]:[spec.shell??resolveLoginShell()],session=freshSessionState(key,spec,argv);if(this.startChild(session),session.alive)this.deps.log?.("pty",`spawned ${argv[0]} for ${key} (pid ${session.proc?.pid})`),this.deps.onSessionStart?.(spare);return session}startChild(session){session.generation=randomUUID2();try{session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...session.command],cwd:session.cwd,env:embeddedTerminalEnv(process.env,{TERM:"xterm-256color",COLUMNS:String(session.cols),LINES:String(session.rows),BASH_SILENCE_DEPRECATION_WARNING:"1",KOBE_TERMINAL_PTY:"1"}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0,session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session))}catch(err){session.alive=!1,this.deps.log?.("pty",`spawn failed for ${session.key}: ${err instanceof Error?err.message:String(err)}`)}}async endChild(session){if(!session.alive)return;let proc=session.proc;if(!proc){this.markExited(session);return}await terminatePtyChild(proc,()=>this.markExited(session),(line)=>this.deps.log?.("pty-signal",`${session.key}: ${line}`))}markExited(session,exit){if(!session.alive)return;session.alive=!1;let sessionExit={code:exit?.code??null,signal:exit?.signal??null,at:new Date().toISOString()};session.exit=sessionExit;try{session.proc?.close()}catch{}this.deps.onExit?.(session,sessionExit)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,buf.toString("latin1"));session.colorQueryCarry=colorQueries.carry;for(let slot of colorQueries.slots)try{session.proc?.write(formatDefaultColorReply(slot,session.defaultColors))}catch{}scanOscTitle(session,buf),session.chunks.push(buf),session.bytes+=buf.byteLength,session.totalBytes+=buf.byteLength;while(session.bytes>this.deps.scrollbackCap&&session.chunks.length>1){let dropped=session.chunks.shift();if(dropped)session.bytes-=dropped.byteLength}this.deps.onOutput?.(session,buf)}}function shouldFreeze(session,now){let appended=session.totalBytes-(session.frozenTotalBytes??0);if(appended<=0)return!1;let since=now-session.lastFreezeAtMs;if(since<5000)return!1;return appended>=65536||since>=60000}class WarmSpare{deps;spare=null;constructor(deps){this.deps=deps}warm(cwd,shell,cols=80,rows=24){let argv0=shell??resolveLoginShell();if(this.spare?.alive&&this.spare.cwd===cwd&&this.spare.command[0]===argv0)return;let old=this.spare;if(this.spare=null,old)this.deps.endChild(old);let session=this.deps.spawn("::spare",{cwd,command:[argv0],cols,rows},!0);this.spare=session.alive?session:null}adopt(key,spec){let spare=this.spare;if(!spare?.alive||spare.cwd!==spec.cwd)return null;let want=spec.command&&spec.command.length>0?spec.command:[spec.shell??resolveLoginShell()];if(want.length!==1||want[0]!==spare.command[0])return null;this.spare=null,spare.key=key,spare.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??spare.defaultColors;let cols=spec.cols??spare.cols,rows=spec.rows??spare.rows;if(spare.cols!==cols||spare.rows!==rows){spare.cols=cols,spare.rows=rows;try{spare.proc?.resize(cols,rows)}catch{return this.deps.markExited(spare),null}}return this.deps.log?.("pty",`adopted warm shell for ${key} (pid ${spare.proc?.pid})`),this.deps.onSessionStart?.(),this.warm(spec.cwd,spare.command[0],cols,rows),spare}async end(){let spare=this.spare;if(this.spare=null,spare)await this.deps.endChild(spare)}}var LOGGED_WRITE_BYTES=1024,DEFAULT_SCROLLBACK_CAP=524288,EXIT_TAIL_BYTES=16384;class PtyHost{sessions=new Map;opts;scrollbackCap;parkRestoreDeltas=0;parkRestoreFallbacks=0;childController;warmSpare;constructor(opts={}){this.opts=opts,this.scrollbackCap=opts.scrollbackCap??DEFAULT_SCROLLBACK_CAP,this.childController=new PtyChildController({driver:opts.driver,scrollbackCap:this.scrollbackCap,onSessionStart:(spare)=>{if(!spare)this.opts.onSessionStart?.()},onOutput:(session,data)=>{if(session.sinks.size===0){this.maybeFreeze(session);return}let frame={type:"event",name:"pty.data",payload:{key:session.key,data:data.toString("base64")}};for(let sink of session.sinks.values())sink(frame);this.maybeFreeze(session)},onExit:(session,exit)=>{let frame={type:"event",name:"pty.exit",payload:{key:session.key,pid:session.proc?.pid??null,...exit}};for(let sink of session.sinks.values())sink(frame);if(this.opts.log?.("pty",`session ${session.key} exited${describeExit(exit)}`),this.maybeFreeze(session,!0),!session.closedByRequest)try{this.opts.onSessionExit?.({key:session.key,pid:session.proc?.pid??null,exit,tail:ringTail(session.chunks,session.bytes,EXIT_TAIL_BYTES)})}catch{}this.opts.onSessionEnd?.()},log:(event,message)=>this.opts.log?.(event,message)}),this.warmSpare=new WarmSpare({spawn:(key,spec,spare)=>this.childController.spawn(key,spec,spare),endChild:(session)=>this.childController.endChild(session),markExited:(session)=>this.childController.markExited(session),log:(event,message)=>this.opts.log?.(event,message),onSessionStart:()=>this.opts.onSessionStart?.()})}open(key,spec,token,sink,sinceOffset,sincePid){let session=this.sessions.get(key),created=!1,respawned=!1;if(!session)created=!0,session=this.warmSpare.adopt(key,spec)??this.childController.spawn(key,spec),this.sessions.set(key,session);else if(!session.alive&&session.restored)this.respawn(session,spec),respawned=session.alive;else if(session.alive&&spec.cols!==void 0&&spec.rows!==void 0&&(session.cols!==spec.cols||session.rows!==spec.rows))this.resize(key,spec.cols,spec.rows);let defaultColors=parseTerminalDefaultColors(spec.defaultColors);if(defaultColors)session.defaultColors=defaultColors;session.sinks.set(token,sink),session.parked=!1,session.parkedScreenBytes=0;let windowStart=session.totalBytes-session.bytes,replay=Buffer.concat(session.chunks),sinceValid=!1;if(!created&&sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes&&sincePid!==void 0&&sincePid===session.proc?.pid)replay=replay.subarray(sinceOffset-windowStart),sinceValid=!0;if(sinceOffset!==void 0&&sincePid!==void 0)if(sinceValid)this.parkRestoreDeltas++;else this.parkRestoreFallbacks++;return{replay:replay.toString("base64"),alive:session.alive,pid:session.proc?.pid??null,created,respawned,offset:session.totalBytes,sinceValid}}warm(cwd,shell,cols=80,rows=24){this.warmSpare.warm(cwd,shell,cols,rows)}write(key,data){let session=this.sessions.get(key);if(!session?.alive||data.length===0)return;if(data.length>=LOGGED_WRITE_BYTES)this.opts.log?.("pty",`wrote ${data.length} bytes to ${key}`);try{session.proc?.write(data)}catch(error){this.opts.log?.("pty",`write failed on ${key} (${data.length} bytes): ${String(error)}`)}}resize(key,cols,rows){let session=this.sessions.get(key);if(!session?.alive)return;session.cols=cols,session.rows=rows;try{session.proc?.resize(cols,rows)}catch{}}killIfGeneration(key,expectedGeneration){let session=this.sessions.get(key);if(!session)return{accepted:!1,reason:"missing-session"};if(session.generation!==expectedGeneration)return{accepted:!1,reason:"generation-mismatch"};return this.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}kill(key){let session=this.sessions.get(key);if(!session)return Promise.resolve();return this.sessions.delete(key),session.closedByRequest=!0,this.opts.freeze?.drop(key),this.childController.endChild(session)}rename(from,to){let session=this.sessions.get(from);if(!session||from===to||this.sessions.has(to))return!1;return this.sessions.delete(from),session.key=to,this.sessions.set(to,session),this.opts.freeze?.drop(from),this.maybeFreeze(session,!0),this.opts.log?.("pty",`renamed session ${from} \u2192 ${to}`),!0}detach(key,token,parked=!1,parkedScreenBytes=0){let session=this.sessions.get(key);if(!session)return;session.sinks.delete(token),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(!session.sinks.delete(token))continue;this.applyParkedOnDetach(session)}}applyParkedOnDetach(session,parked=!1,parkedScreenBytes=0){if(session.sinks.size!==0)return;session.parked=parked,session.parkedScreenBytes=parked?Math.max(0,parkedScreenBytes):0}list(){return Array.from(this.sessions.values(),(s)=>sessionInfo(s))}peek(key,sinceOffset){return peekRing(this.sessions.get(key),sinceOffset)}stats(){return hostStats(this.sessions.values(),this.scrollbackCap,this.parkRestoreDeltas,this.parkRestoreFallbacks)}async killAll(){let sessions=Array.from(this.sessions.keys(),(key)=>this.kill(key));sessions.push(this.warmSpare.end()),await Promise.all(sessions)}async shutdown(){this.flushFrozen();let endings=Array.from(this.sessions.values(),(session)=>this.childController.endChild(session));endings.push(this.warmSpare.end()),await Promise.all(endings)}flushFrozen(){for(let session of this.sessions.values())this.maybeFreeze(session,!0)}restoreFrozen(records){let restoredCount=0;for(let record of records){if(this.sessions.has(record.key))continue;let session=thawSession(record,this.scrollbackCap);if(!session)continue;this.sessions.set(record.key,session),restoredCount++}if(restoredCount>0)this.opts.log?.("pty",`restored ${restoredCount} frozen session(s) from disk`);return restoredCount}respawn(session,spec){if(session.restored=!1,session.exit=null,spec.command&&spec.command.length>0)session.command=[...spec.command];if(session.cols=spec.cols??session.cols,session.rows=spec.rows??session.rows,session.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??session.defaultColors,this.childController.startChild(session),!session.alive)return;this.opts.log?.("pty",`respawned restored session ${session.key} (pid ${session.proc?.pid})`),this.opts.onSessionStart?.()}maybeFreeze(session,force=!1){let freeze=this.opts.freeze;if(!freeze||session.key.startsWith("::"))return;if(session.closedByRequest)return;let now=Date.now();if(!force&&!shouldFreeze(session,now))return;session.lastFreezeAtMs=now,session.frozenTotalBytes=session.totalBytes,freeze.save(freezeSession(session))}liveCount(){let n=0;for(let session of this.sessions.values())if(session.alive)n++;return n}}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.KOBE_PTY_MAX_LIFETIME_MS;if(raw===void 0)return null;let n=Number(raw);return Number.isFinite(n)&&n>0?n:null}function resolveIdleExitMs(){let raw=process.env.KOBE_PTY_IDLE_EXIT_MS;if(raw===void 0)return DEFAULT_IDLE_EXIT_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_IDLE_EXIT_MS}async function startPtyHostServer(options={}){migrateLegacyPtyHostData();let socketPath=options.socketPath??defaultPtyHostSocketPath(),pidPath=options.pidPath??defaultPtyHostPidPath(),freezeDir=options.freezeDir??defaultPtyFreezeDir(),idleExitMs=options.idleExitMs||resolveIdleExitMs(),orphanCheckMs=options.orphanCheckMs||DEFAULT_ORPHAN_CHECK_MS,maxLifetimeMs=options.maxLifetimeMs??resolveMaxLifetimeMs(),bootedAtMs=Date.now(),log=options.log??(()=>{}),clients=new Set,stopping=!1,wipeFreezeOnStop=!1,idleTimer=null,cancelIdle=()=>{if(idleTimer)clearTimeout(idleTimer);idleTimer=null},armIdle=()=>{if(stopping)return;cancelIdle(),idleTimer=setTimeout(()=>{if(stopping||ptys.liveCount()>0)return;log("idle",`no live sessions for ${idleExitMs}ms \u2014 exiting`),stop()},idleExitMs)},orphaned=()=>{if(maxLifetimeMs!==null&&Date.now()-bootedAtMs>=maxLifetimeMs)return`exceeded its ${maxLifetimeMs}ms lifetime ceiling`;let owner;try{owner=readFileSync(pidPath,"utf8").trim()}catch{return`pidfile ${pidPath} is gone`}let pid=Number.parseInt(owner,10);if(pid===process.pid)return null;return Number.isInteger(pid)?`pidfile ${pidPath} now names pid ${pid}`:`pidfile ${pidPath} is unreadable`},orphanTimer=setInterval(()=>{if(stopping)return;let reason=orphaned();if(!reason)return;log("orphan",`${reason} \u2014 exiting rather than outliving my owner`),stop()},orphanCheckMs);orphanTimer.unref?.();let ptys=new PtyHost({onSessionStart:cancelIdle,onSessionEnd:()=>{if(ptys.liveCount()===0)armIdle()},onSessionExit:(info)=>{try{recordPtyExit(info)}catch(err){log("pty",`exit record write failed for ${info.key}: ${err instanceof Error?err.message:String(err)}`)}},freeze:fileFreezeSink(freezeDir),driver:options.driver,log});ptys.restoreFrozen(loadFrozenSessions(freezeDir,Date.now(),(s)=>{let mib=(bytes)=>`${Math.round(bytes/1048576)}MB`,notes=[`restored ${s.restored} (${mib(s.bytesRead)})`];if(s.deferred>0)notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);if(s.expired>0)notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS/86400000}-day TTL`);if(s.unreadable>0)notes.push(`${s.unreadable} unreadable`);log("freeze",notes.join(", "))}));let pipeSocket=isWindowsPipePath(socketPath);if(await ensureOwnerOnlyStateDir(resolveDaemonHomeDir()),!pipeSocket)await mkdir(dirname(socketPath),{recursive:!0});await mkdir(dirname(pidPath),{recursive:!0});let server=createServer((socket)=>{let client={socket,writer:new ClientWriter(socket,{onOverflow:()=>{log("backpressure","disconnecting PTY client whose critical queue exceeded 8MiB"),socket.destroy()}})};clients.add(client);let receiver=new LineReceiver;socket.on("data",(chunk)=>{if(!receiver.push(chunk,(line)=>handleLine(client,line)))log("framing","disconnecting PTY client whose request exceeded 8MiB"),socket.destroy()}),socket.on("error",()=>{}),socket.on("close",()=>{clients.delete(client),ptys.detachClient(client)})}),api={socketPath,pidPath,async close(){if(stopping)return;if(stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown(),wipeFreezeOnStop)clearFrozenSessions(freezeDir);for(let client of Array.from(clients))client.socket.destroy();if(await new Promise((resolve)=>server.close(()=>resolve())),!pipeSocket)await unlink(socketPath).catch(()=>{});await unlink(pidPath).catch(()=>{})}};async function stop(){await api.close().catch((err)=>logDaemonError("pty-host-shutdown",err)),options.onStop?.()}function dispatch(req,client){switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.open":{let payload=objectPayload(req.payload);return ptys.open(requireString(payload,"key"),{cwd:requireString(payload,"cwd"),command:Array.isArray(payload.command)?payload.command.filter((c)=>typeof c==="string"):void 0,shell:typeof payload.shell==="string"?payload.shell:void 0,cols:typeof payload.cols==="number"?payload.cols:void 0,rows:typeof payload.rows==="number"?payload.rows:void 0,defaultColors:parseTerminalDefaultColors(payload.defaultColors)??void 0},client,(frame)=>writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0)}case"pty.write":{let payload=objectPayload(req.payload);return ptys.write(requireString(payload,"key"),typeof payload.data==="string"?payload.data:""),{}}case"pty.resize":{let payload=objectPayload(req.payload);return ptys.resize(requireString(payload,"key"),typeof payload.cols==="number"?payload.cols:80,typeof payload.rows==="number"?payload.rows:24),{}}case"pty.kill":{let payload=objectPayload(req.payload),key=requireString(payload,"key");if("expectedGeneration"in payload)return ptys.killIfGeneration(key,requireString(payload,"expectedGeneration"));return ptys.kill(key).catch((err)=>logDaemonError("pty-kill",err)),{accepted:!0}}case"pty.rename":{let payload=objectPayload(req.payload);return{renamed:ptys.rename(requireString(payload,"from"),requireString(payload,"to"))}}case"pty.detach":{let payload=objectPayload(req.payload);ptys.detach(requireString(payload,"key"),client,payload.parked===!0,typeof payload.parkedScreenBytes==="number"?payload.parkedScreenBytes:0)}return{};case"pty.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),stats:ptys.stats(),...options.version?{version:options.version}:{}};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0)}case"pty.warm":{let payload=objectPayload(req.payload);return ptys.warm(requireString(payload,"cwd"),typeof payload.shell==="string"?payload.shell:void 0,typeof payload.cols==="number"?payload.cols:void 0,typeof payload.rows==="number"?payload.rows:void 0),{}}case"daemon.stop":return wipeFreezeOnStop=!0,setTimeout(()=>void stop(),0).unref(),{};default:throw Error(`unknown pty-host request: ${req.name}`)}}function handleLine(client,line){if(line.trim().length>0){let frame=null;try{frame=JSON.parse(line)}catch{writeFrame(client,{type:"response",id:"parse-error",error:{message:"malformed frame"}})}if(frame)if(frame.type!=="request")writeFrame(client,{type:"response",id:"parse-error",error:{message:"requests only"}});else try{writeFrame(client,{type:"response",id:frame.id,name:frame.name,payload:dispatch(frame,client)})}catch(err){writeFrame(client,{type:"response",id:frame.id,name:frame.name,error:{message:err instanceof Error?err.message:String(err)}})}}}if(await listenOnUnixSocket(server,socketPath),await writeTextAtomic(pidPath,`${process.pid}
|
|
2
|
+
import{embeddedTerminalEnv}from"./chunk-ef39ym8f.js";import{FREEZE_RESTORE_MAX_BYTES,FREEZE_TTL_MS,clearFrozenSessions,fileFreezeSink,freezeSession,loadFrozenSessions,thawSession}from"./chunk-2cy0c03r.js";import{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{writeTextAtomic}from"./chunk-xsrcwcjc.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-rcyasw34.js";import{DEFAULT_TERMINAL_COLORS,foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors}from"./chunk-7q67dz4c.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{recordPtyExit}from"./chunk-a74pa16c.js";import"./chunk-w25b7xxz.js";import{DAEMON_PROTOCOL_VERSION,frameToLine}from"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import{CURRENT_VERSION}from"./chunk-sgrbaynq.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import"./chunk-q5jhy3t8.js";import{listenOnUnixSocket}from"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import{ensureOwnerOnlyStateDir}from"./chunk-9prawccj.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,isWindowsPipePath,legacyPtyHostPidPath,legacyPtyHostSocketPath,resolveDaemonHomeDir}from"./chunk-8cjr5ypt.js";import"./chunk-sb0ns0c7.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};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{closeTab,engineTabArgv,initialTabs,setTabTitle,terminalTabsKey}from"./chunk-6dgyb7sq.js";import{awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,enginePresence,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,initMarkerSaysFinished,isHostedTaskKey,killHostedSessions,listHostedSessions,listHostedSessionsOrNull,openHostedSessionHost,pastePromptWhenEngineUp,readPersistedTerminalDefaultColors}from"./chunk-3dv9vdpj.js";import{ApiError}from"./chunk-f7zjggfv.js";import{engineLaunchArgv}from"./chunk-00t0rc5r.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})}var isTaskKey=isHostedTaskKey,findEngineKey=findHostedEngineKey,taskKeys=hostedTaskKeys,openPtyHost=openHostedSessionHost,ensurePtyHost=ensureHostedSessionHost,listSessions=listHostedSessions,listSessionsOrNull=listHostedSessionsOrNull,deliverToKey=deliverToHostedKey,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.kind==="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.kind!=="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,{vendor:presence.vendor});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 pastePromptWhenEngineUp(rpc,launch.key,target.engineBin,prompt,{snapshot:opts?.snapshot});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
|
+
export{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,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,deriveTitleFromSession,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,tearDownTaskSessionAdapter}from"./chunk-
|
|
2
|
+
import{deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,deriveTitleFromSession,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,tearDownTaskSessionAdapter}from"./chunk-kmsnrf9m.js";import{resolvePluginBinPath}from"./chunk-7nndmapz.js";import{Orchestrator}from"./chunk-yhhkw0az.js";import{GH_PR_VIEW_FIELDS,classifyGhFailure,mapGhPrView,nextPrPoll,samePrStatus}from"./chunk-grdk12w7.js";import"./chunk-2kb4z64z.js";import{GitWorktreeManager,parseDirtyPaths}from"./chunk-4jrad3q0.js";import{auditDeletionBranchKept,auditDeletionResidue,auditDeletionSalvaged,auditWorktreeResidue,auditWorktreeSalvaged,parseAheadBehind,startDaemonServer}from"./chunk-sz0fjg3e.js";import"./chunk-9fc0j6ng.js";import"./chunk-xd9kw4hh.js";import"./chunk-rz8zs7j8.js";import"./chunk-xsrcwcjc.js";import{DEFAULT_BASE_REF_CANDIDATES,readHeadSha,readRefSha,resolveGitDirs}from"./chunk-vyb5a2rh.js";import{affectsActivityState,isEngineActivityKind}from"./chunk-3e5n28t6.js";import{PLACEHOLDER_TASK_TITLE}from"./chunk-xb9b93ts.js";import"./chunk-ztwz2465.js";import"./chunk-r2pztgm6.js";import"./chunk-bq9shn2d.js";import"./chunk-63wmhbqs.js";import{TaskIndexStore}from"./chunk-06agxrff.js";import"./chunk-qkehg2c1.js";import{autoStatusEnabled}from"./chunk-3dv9vdpj.js";import{execHostForWorktreePath}from"./chunk-dg8bsyb9.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-gsy8xfh6.js";import{installDaemonCrashHandlers,logDaemonInfo}from"./chunk-rcyasw34.js";import"./chunk-7q67dz4c.js";import"./chunk-v3fqkype.js";import"./chunk-hape5vwj.js";import"./chunk-b99tf0jr.js";import"./chunk-a74pa16c.js";import"./chunk-w25b7xxz.js";import"./chunk-j5przd8x.js";import{parsePorcelain}from"./chunk-k6nxyxyh.js";import"./chunk-h4n8ffqy.js";import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import"./chunk-072m1jjt.js";import"./chunk-z7c6nap0.js";import{connectOrStartDaemon,daemonSpawnReason}from"./chunk-te8g5azg.js";import{stopDaemonProcess}from"./chunk-y13681dw.js";import{KobeDaemonClient}from"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import{GENERIC_PROTOCOL,engineProtocolKey,getEngineProtocol,protocolEntry,resolveCommandProtocol,sessionProtocol}from"./chunk-00t0rc5r.js";import{engineDisplayName,kobeApiInvocation}from"./chunk-yfkr1fem.js";import"./chunk-22jgttzv.js";import"./chunk-sdyzxayr.js";import{foregroundEngineIn,parsePsSnapshot,psSnapshot}from"./chunk-qnj7vk5g.js";import{createEngineTurnDetector,engineEntry,engineTitleTurnHint,vendorsWithQuotaProbe}from"./chunk-kav5p2qb.js";import{availableEngineIds}from"./chunk-kx3kydwv.js";import"./chunk-w7zv47mp.js";import{spawnCapture}from"./chunk-khj0apc7.js";import{CURRENT_VERSION,checkLatestVersion}from"./chunk-sgrbaynq.js";import"./chunk-jvxh93nz.js";import"./chunk-2brn8e1y.js";import"./chunk-r92b9j14.js";import"./chunk-aep7gvh4.js";import"./chunk-7kysxgbq.js";import"./chunk-krpsfcda.js";import{DEFAULT_TASK_VENDOR,isTaskStatus}from"./chunk-xy8be792.js";import{backfillSavedReposFromProjects,getCustomEngineIds,getPersistedString,getRemoteRepoConfig,getSavedRepos,setPersistedString}from"./chunk-9ydhv2zb.js";import"./chunk-40dgv828.js";import"./chunk-3jh78dmc.js";import{releaseSync}from"./chunk-ddcxvbme.js";import"./chunk-0q6h4vt4.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import{BUILTIN_VENDORS,isBuiltinVendor}from"./chunk-05jej26n.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import{isProcessAlive,readPidFile}from"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import"./chunk-9prawccj.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath}from"./chunk-8cjr5ypt.js";import{activeCliName}from"./chunk-00ehck55.js";import{migrateRoveDaemonStateLayout}from"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import{readRoveHomeDirEnv}from"./chunk-hq4b3fca.js";import"./chunk-pxk2c2vj.js";import"./chunk-wqfp8d9w.js";function sniffProtocolFromTitle(title){let trimmed=title?.trim();if(!trimmed)return null;let owners=new Map;for(let vendor of BUILTIN_VENDORS)for(let glyph of engineEntry(vendor).terminalTitle?.statusPrefixes??[])owners.set(glyph,[...owners.get(glyph)??[],vendor]);for(let glyph of[...owners.keys()].sort((a,b)=>b.length-a.length)){if(!trimmed.startsWith(glyph))continue;if(trimmed.slice(glyph.length).trim().length===0)continue;let vendors=owners.get(glyph)??[];if(vendors.length===1)return vendors[0];return null}return null}function protocolUpgradeFromLiveSession(task,evidence){let command=task.command?.trim();if(!command)return null;if(task.vendor&&isBuiltinVendor(task.vendor))return null;if(resolveCommandProtocol(command)!==GENERIC_PROTOCOL)return null;let walk=evidence.walkVendor,vendor=walk!==null&&isBuiltinVendor(walk)?walk:sniffProtocolFromTitle(evidence.title);return vendor?{command,vendor}:null}function protocolWriteBackFromLiveSession(task,evidence,customEngineIds){let id=task.vendor?.trim();if(!id)return null;if(getEngineProtocol(id)!==void 0)return null;if(!customEngineIds.includes(id))return null;let walk=evidence.walkVendor;return walk!==null&&isBuiltinVendor(walk)?{id,protocol:walk}:null}async function latestTranscriptMtime(vendor,worktree){if(!worktree)return 0;return protocolEntry(vendor).history.latestTranscriptMtimeForWorktree(worktree)}async function maybeAutoStart(orch,taskId,enabled=autoStatusEnabled){if(!enabled())return"skipped";let task=orch.getTask(taskId);if(!task)return"skipped";if((task.kind??"task")==="main")return"skipped";if(task.status!=="backlog")return"skipped";return await orch.setStatus(taskId,"in_progress"),"moved"}var SYNC_TIMEOUT_MS=60000,SYNC_CONFLICT="SYNC_CONFLICT",SYNC_DIRTY="SYNC_WORKTREE_DIRTY";async function git(cwd,args,signal,write=!1){return spawnCapture("git",args,{cwd,env:write?process.env:readOnlyGitProcessEnv(),signal})}function parseConflictedPaths(stdout){return stdout.split(`
|
|
3
3
|
`).map((line)=>line.trim()).filter((line)=>line.length>0)}async function syncWorktreeWithBase(worktreePath,baseRef,signal){let status=await git(worktreePath,["status","--porcelain=v1"],signal);if(status.status!==0)throw Error("git status failed");let dirty=parseDirtyPaths(status.stdout);if(dirty.length>0)throw Error(`${SYNC_DIRTY}: ${dirty.join(", ")}`);let before=await git(worktreePath,["rev-parse","HEAD"],signal),merge=await git(worktreePath,["merge","--no-edit",baseRef],signal,!0);if(merge.status!==0){let conflicted=await git(worktreePath,["diff","--name-only","--diff-filter=U"],signal),paths=parseConflictedPaths(conflicted.stdout);if(paths.length>0)throw Error(`${SYNC_CONFLICT}: ${paths.join(", ")}`);let detail=merge.stderr?.trim();throw Error(detail?`git merge ${baseRef} failed \u2014 ${detail}`:`git merge ${baseRef} failed`)}let after=await git(worktreePath,["rev-parse","HEAD"],signal);return{baseRef,alreadyCurrent:before.status===0&&before.stdout.trim()===after.stdout.trim()}}import{readFileSync}from"fs";import{join}from"path";var BASE_REF_TTL_MS=300000,cache=new Map;async function git2(worktreePath,args,signal){return await spawnCapture("git",[...args],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal})}async function refExists(worktreePath,ref,signal){return(await git2(worktreePath,["rev-parse","--verify","--quiet",ref],signal)).status===0}async function sharesHistory(worktreePath,ref,signal){return(await git2(worktreePath,["merge-base",ref,"HEAD"],signal)).status===0}async function baseCheckoutBranchFromGit(worktreePath,signal){let out=await git2(worktreePath,["worktree","list","--porcelain"],signal);if(out.status!==0)return null;return(out.stdout.split(`
|
|
4
4
|
|
|
5
5
|
`,1)[0]??"").split(`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{PLUGIN_MANIFEST_FILENAMES,currentPluginPlatform,loadPluginRegistry,parsePluginManifest,pluginCheckoutDir,pluginConfigDir,pluginManifestPath,pluginStateDir,pluginsRootDir,savePluginRegistry,supportsPlatform,upsertPluginEntry}from"./chunk-bq9shn2d.js";import{CURRENT_VERSION,compareSemver}from"./chunk-
|
|
2
|
+
import{PLUGIN_MANIFEST_FILENAMES,currentPluginPlatform,loadPluginRegistry,parsePluginManifest,pluginCheckoutDir,pluginConfigDir,pluginManifestPath,pluginStateDir,pluginsRootDir,savePluginRegistry,supportsPlatform,upsertPluginEntry}from"./chunk-bq9shn2d.js";import{CURRENT_VERSION,compareSemver}from"./chunk-sgrbaynq.js";import{spawnSync}from"child_process";import{cpSync,existsSync,mkdirSync,readFileSync,renameSync,rmSync}from"fs";import{mkdtempSync}from"fs";import{basename,join,resolve}from"path";import{createInterface}from"readline/promises";var GITHUB_SPEC_RE=/^([A-Za-z0-9-]+)\/([A-Za-z0-9._-]+)(\/.+)?$/;class PluginCliError extends Error{}function fail(message){throw new PluginCliError(message)}function readManifestAt(root){let path=pluginManifestPath(root);if(!path)fail(`no ${PLUGIN_MANIFEST_FILENAMES.join(" or ")} found at ${root}`);let source=readFileSync(path,"utf8");return{...parsePluginManifest(source,basename(path)),manifestPath:path,manifestSource:source}}function checkVersionGate(parsed){let min=parsed.manifest.minKobeVersion;if(compareSemver(CURRENT_VERSION,min)<0)fail(`plugin requires Rove >= ${min} (this is ${CURRENT_VERSION}); update Rove first`)}function printPreview(parsed,source){let m=parsed.manifest;console.log(`
|
|
3
3
|
${m.name} (${m.id}) v${m.version} \u2014 ${m.description??"no description"}`),console.log(`source: ${source}`);let show=(label,commands)=>{for(let c of commands)console.log(` ${label}: ${c.command.join(" ")}`)};show("build",m.build),show("startup",m.startup);for(let a of m.actions)console.log(` action ${a.id}: ${a.command.join(" ")}`);for(let e of m.events)console.log(` on ${e.on}: ${e.command.join(" ")}`);for(let w of parsed.warnings)console.log(` warning: ${w}`);console.log("")}async function confirmOrBail(yes){if(yes)return;if(!process.stdin.isTTY)fail("refusing to install without confirmation in a non-interactive terminal; pass --yes");let rl=createInterface({input:process.stdin,output:process.stdout}),answer=(await rl.question("Install this plugin and run its build commands? [y/N] ")).trim().toLowerCase();if(rl.close(),answer!=="y"&&answer!=="yes")fail("aborted")}function git(args,cwd){if(spawnSync("git",args,{cwd,stdio:["ignore","inherit","inherit"]}).status!==0)fail(`git ${args[0]} failed`)}function runBuildCommands(parsed,root){let platform=currentPluginPlatform();for(let[i,step]of parsed.manifest.build.entries()){if(!supportsPlatform(step,parsed.manifest,platform))continue;let[cmd,...args]=step.command;console.log(`build[${i}]: ${step.command.join(" ")}`);let res=spawnSync(cmd,args,{cwd:root,stdio:["ignore","inherit","inherit"]});if(res.status!==0)fail(`build[${i}] failed (exit ${res.status??"spawn error"}); plugin not registered`)}}function makeStagingDir(){let root=pluginsRootDir();return mkdirSync(root,{recursive:!0}),mkdtempSync(join(root,".staging-"))}function movePluginTree(from,to){try{renameSync(from,to)}catch(err){if(err.code!=="EXDEV")throw err;cpSync(from,to,{recursive:!0,verbatimSymlinks:!0}),rmSync(from,{recursive:!0,force:!0})}}function register(entry){savePluginRegistry(upsertPluginEntry(loadPluginRegistry(),entry)),mkdirSync(pluginConfigDir(entry.id),{recursive:!0,mode:448}),mkdirSync(pluginStateDir(entry.id),{recursive:!0,mode:448})}async function installPlugin(spec,opts){let match=spec.match(GITHUB_SPEC_RE);if(!match)fail(`install takes GitHub shorthand (owner/repo[/subdir]), got \`${spec}\``);let[,owner,repo,subdirRaw]=match,subdir=subdirRaw?.replace(/^\//,""),tmp=makeStagingDir();try{let url=`https://github.com/${owner}/${repo}.git`;if(console.log(`cloning ${url}${opts.ref?` @ ${opts.ref}`:""}`),opts.ref)git(["clone","--quiet",url,tmp]),git(["checkout","--quiet",opts.ref],tmp);else git(["clone","--quiet","--depth","1",url,tmp]);let rootInClone=subdir?join(tmp,subdir):tmp,parsed=readManifestAt(rootInClone);checkVersionGate(parsed);let id=parsed.manifest.id,existing=loadPluginRegistry().plugins.find((p)=>p.id===id);if(existing?.source.kind==="link")fail(`\`${id}\` is locally linked at ${existing.root}; unlink it first`);if(!supportsPlatform({},parsed.manifest,currentPluginPlatform()))fail(`plugin declares platforms [${parsed.manifest.platforms?.join(", ")}]; this machine is unsupported`);printPreview(parsed,`github.com/${owner}/${repo}${subdir?`/${subdir}`:""}`),await confirmOrBail(opts.yes),runBuildCommands(parsed,rootInClone);let manifestPath=pluginManifestPath(rootInClone);if(!manifestPath)fail("manifest disappeared during build; aborting");if(manifestPath!==parsed.manifestPath)fail("manifest changed during build; aborting");if(readFileSync(manifestPath,"utf8")!==parsed.manifestSource)fail("manifest changed during build; aborting");let checkout=pluginCheckoutDir(id);return rmSync(checkout,{recursive:!0,force:!0}),mkdirSync(join(checkout,".."),{recursive:!0}),movePluginTree(tmp,checkout),register({id,source:{kind:"github",spec},root:subdir?join(checkout,subdir):checkout,enabled:!0,version:parsed.manifest.version,installedAt:Date.now()}),console.log(`installed ${id} v${parsed.manifest.version}`),id}finally{rmSync(tmp,{recursive:!0,force:!0})}}function linkPlugin(dir){let root=resolve(dir);if(!existsSync(root))fail(`no such directory: ${root}`);let parsed=readManifestAt(root);checkVersionGate(parsed);let id=parsed.manifest.id;if(loadPluginRegistry().plugins.find((p)=>p.id===id)?.source.kind==="github")fail(`\`${id}\` is installed from GitHub; uninstall it before linking a local copy`);for(let w of parsed.warnings)console.log(`warning: ${w}`);if(!supportsPlatform({},parsed.manifest,currentPluginPlatform()))console.log(`warning: declares platforms [${parsed.manifest.platforms?.join(", ")}]; nothing will run on this machine`);register({id,source:{kind:"link"},root,enabled:!0,version:parsed.manifest.version,installedAt:Date.now()}),console.log(`linked ${id} v${parsed.manifest.version} \u2192 ${root}`)}
|
|
4
4
|
export{PluginCliError,installPlugin,linkPlugin};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{API_SCHEMA_VERSION,API_VERBS,VERBS,VERB_GROUPS,VerbArgs,apiUsage,buildCountPlan,defaultApiRuntime,deliverPrompt,findVerb,fullSchema,parseAgentsSpec,parseFlags,schemaIndex,takeIdentityWarning,unknownVerbError,validateAgainstSpec,verbHelp,verbSchema}from"./chunk-
|
|
2
|
+
import{API_SCHEMA_VERSION,API_VERBS,VERBS,VERB_GROUPS,VerbArgs,apiUsage,buildCountPlan,defaultApiRuntime,deliverPrompt,findVerb,fullSchema,parseAgentsSpec,parseFlags,schemaIndex,takeIdentityWarning,unknownVerbError,validateAgainstSpec,verbHelp,verbSchema}from"./chunk-1ve1cdmr.js";import{ensurePluginEnginesLoaded}from"./chunk-c8xm2s8h.js";import{openDaemonSession}from"./chunk-ac0yv0v4.js";import"./chunk-fx98pmwf.js";import"./chunk-3e5n28t6.js";import"./chunk-xb9b93ts.js";import"./chunk-ztwz2465.js";import"./chunk-r2pztgm6.js";import"./chunk-bq9shn2d.js";import"./chunk-63wmhbqs.js";import"./chunk-qkehg2c1.js";import"./chunk-e4dmvkd7.js";import"./chunk-6dgyb7sq.js";import"./chunk-3dv9vdpj.js";import"./chunk-dg8bsyb9.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-gsy8xfh6.js";import"./chunk-rcyasw34.js";import"./chunk-7q67dz4c.js";import"./chunk-v3fqkype.js";import"./chunk-hape5vwj.js";import"./chunk-b99tf0jr.js";import{ApiError,splitDaemonCode}from"./chunk-f7zjggfv.js";import"./chunk-w25b7xxz.js";import"./chunk-6xppe9bj.js";import"./chunk-072m1jjt.js";import"./chunk-z7c6nap0.js";import"./chunk-fczqwtmq.js";import"./chunk-te8g5azg.js";import"./chunk-y13681dw.js";import"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-00t0rc5r.js";import"./chunk-yfkr1fem.js";import"./chunk-x2c7ehve.js";import"./chunk-22jgttzv.js";import"./chunk-sdyzxayr.js";import"./chunk-qnj7vk5g.js";import"./chunk-kav5p2qb.js";import"./chunk-kx3kydwv.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-sgrbaynq.js";import"./chunk-jvxh93nz.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-r92b9j14.js";import"./chunk-aep7gvh4.js";import"./chunk-7kysxgbq.js";import"./chunk-krpsfcda.js";import"./chunk-xy8be792.js";import"./chunk-9ydhv2zb.js";import"./chunk-40dgv828.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-05jej26n.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import"./chunk-9prawccj.js";import"./chunk-8cjr5ypt.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import"./chunk-pxk2c2vj.js";import{__require}from"./chunk-wqfp8d9w.js";function emit(value,pretty){let warning=takeIdentityWarning(),payload=warning&&value&&typeof value==="object"&&!Array.isArray(value)?{...value,identityWarning:warning}:value,text=pretty?JSON.stringify(payload,null,2):JSON.stringify(payload);process.stdout.write(`${text}
|
|
3
3
|
`)}function fail(message,code,exitCode=1,data){process.stderr.write(`${JSON.stringify({error:{message,code,...data}})}
|
|
4
4
|
`),process.exit(exitCode)}function makeContext(verb,flags,client,runtime){return{args:new VerbArgs(verb,flags),client,runtime}}var USAGE_ERROR_CODES=new Set(["BAD_VERB","UNKNOWN_VERB","BAD_FLAG","MISSING_FLAG","MISSING_VERB","BAD_DAEMON"]);function toApiError(err){if(err instanceof ApiError)return err;let message=errorMessage(err);if(/task not found/i.test(message))return new ApiError(message,"TASK_NOT_FOUND",{hint:"that task id does not exist (deleted or mistyped) \u2014 list live tasks and retry with a real id",nextCommandArgs:["api","list"]});if(/unknown daemon request:/i.test(message))return versionSkewError(message);let coded=splitDaemonCode(message);if(coded)return new ApiError(coded.rest,coded.code);return new ApiError(message,"RPC_ERROR")}function versionSkewError(message){return new ApiError(message,"DAEMON_VERSION_SKEW",{hint:"the running daemon is a different build than this CLI, so it does not serve this verb \u2014 restart the daemon to pick up this build, then retry (if the verb is gone for good, `rove api schema` lists what this daemon actually serves)",nextCommandArgs:["daemon","restart"]})}async function invokeVerb(verbName,argv,deps){let verb=findVerb(verbName);if(!verb)throw unknownVerbError(verbName);let booleanFlags=new Set(verb.flags.filter((f)=>f.type==="bool").map((f)=>f.name)),parsed=parseFlags(argv,booleanFlags);validateAgainstSpec(verb,parsed.flags);try{return await verb.handler(makeContext(verb,parsed.flags,deps.client,deps.runtime??defaultApiRuntime))}catch(err){throw toApiError(err)}}async function runApiSubcommand(argv){let[verbName,...rest]=argv;if(!verbName||verbName==="--help"||verbName==="-h"||verbName==="help"){if(!verbName)fail(apiUsage(),"MISSING_VERB",2);process.stdout.write(`${apiUsage()}
|
|
5
5
|
`);return}ensurePluginEnginesLoaded();let verb=findVerb(verbName);if(!verb){let err=unknownVerbError(verbName);fail(`${err.message}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{CURRENT_VERSION,repoSlug}from"./chunk-
|
|
2
|
+
import{CURRENT_VERSION,repoSlug}from"./chunk-sgrbaynq.js";import{spawnSync}from"child_process";var DEFAULT_FEEDBACK_CATEGORY_SLUG="feedback",DISCUSSION_CATEGORY_QUERY=`
|
|
3
3
|
query($owner: String!, $name: String!) {
|
|
4
4
|
repository(owner: $owner, name: $name) {
|
|
5
5
|
id
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{wizardKeyLines}from"./chunk-
|
|
2
|
+
import{wizardKeyLines}from"./chunk-w8f54sr1.js";import{$Fragment,$jsx,$jsxs,bootPaneHost,currentPrefixConfiguration,pageCloseBindings,useBindings,useRenderer,useT,useTheme}from"./chunk-27xs13g3.js";import"./chunk-58hejzp4.js";import{require_react_production}from"./chunk-a82ec09z.js";import"./chunk-k6nxyxyh.js";import"./chunk-h4n8ffqy.js";import"./chunk-6xppe9bj.js";import"./chunk-072m1jjt.js";import"./chunk-z7c6nap0.js";import"./chunk-fczqwtmq.js";import"./chunk-te8g5azg.js";import"./chunk-y13681dw.js";import"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-764bsyb0.js";import{envReadyForTasks}from"./chunk-h6mmcf6y.js";import"./chunk-ajtw0hkk.js";import"./chunk-5mbv38x2.js";import"./chunk-j19ax03g.js";import"./chunk-yybpg7fh.js";import"./chunk-fhch0x0q.js";import"./chunk-00t0rc5r.js";import"./chunk-yfkr1fem.js";import"./chunk-x2c7ehve.js";import"./chunk-22jgttzv.js";import"./chunk-sdyzxayr.js";import"./chunk-qnj7vk5g.js";import"./chunk-kav5p2qb.js";import"./chunk-kx3kydwv.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-sgrbaynq.js";import"./chunk-jvxh93nz.js";import"./chunk-2brn8e1y.js";import"./chunk-th4jd4sd.js";import"./chunk-r92b9j14.js";import"./chunk-aep7gvh4.js";import"./chunk-7kysxgbq.js";import"./chunk-krpsfcda.js";import"./chunk-xy8be792.js";import"./chunk-9ydhv2zb.js";import"./chunk-40dgv828.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-05jej26n.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import"./chunk-9prawccj.js";import"./chunk-8cjr5ypt.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import"./chunk-pxk2c2vj.js";import{__toESM}from"./chunk-wqfp8d9w.js";import{TextAttributes}from"@opentui/core";var import_react2=__toESM(require_react_production(),1);function inlineRowsFor(env){return 15+env.engines.lines.length+envActionKeys(env).length}function envActionKeys(env){let keys=[];if(!env.engines.anyUsable)keys.push("doctor.fix.noEngineAction");if(!env.git.found)keys.push("doctor.fix.gitAction");return keys}function WizardPage(props){let{theme}=useTheme(),t=useT(),renderer=useRenderer(),steps=(props.mode??"full")==="primer"?[]:props.shell===null?["skill"]:["completions","skill"],[stepIndex,setStepIndex]=import_react2.useState(0),[yes,setYes]=import_react2.useState(!0),[answers,setAnswers]=import_react2.useState({}),[page,setPage]=import_react2.useState(steps.length===0?"env":"questions"),step=steps[stepIndex];function finish(finalAnswers){renderer?.destroy(),props.onDone({completions:finalAnswers.completions??!1,skill:finalAnswers.skill??!1})}function confirm(choice=yes){if(page==="env"){setPage("keys");return}if(page==="keys"){finish(answers);return}let next={...answers,[step]:choice};if(setAnswers(next),stepIndex+1>=steps.length){setPage("env");return}setStepIndex(stepIndex+1),setYes(!0)}useBindings(()=>({bindings:[{key:"up",cmd:()=>setYes(!0)},{key:"k",cmd:()=>setYes(!0)},{key:"down",cmd:()=>setYes(!1)},{key:"j",cmd:()=>setYes(!1)},{key:"return",cmd:()=>confirm()},...pageCloseBindings(()=>finish(answers))]}));function questionFor(s){return s==="completions"?t("onboarding.completionsQuestion",{shell:props.shell??""}):t("onboarding.skillQuestion")}let explain=step==="completions"?t("onboarding.completionsExplain"):t("onboarding.skillExplain"),ready=envReadyForTasks(props.env);return $jsxs("box",{flexDirection:"column",flexGrow:1,paddingTop:1,paddingLeft:2,paddingRight:2,children:[$jsx("text",{fg:theme.primary,attributes:TextAttributes.BOLD,wrapMode:"none",children:t("onboarding.title")}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("onboarding.subtitle")}),$jsxs("box",{flexDirection:"column",paddingTop:1,children:[steps.slice(0,page==="questions"?stepIndex:steps.length).map((answered)=>$jsxs("box",{flexDirection:"row",gap:1,children:[$jsx("text",{fg:theme.success,wrapMode:"none",children:"\u2713"}),$jsx("text",{fg:theme.textMuted,wrapMode:"none",children:questionFor(answered)}),$jsx("text",{fg:theme.text,wrapMode:"none",children:answers[answered]?t("onboarding.optionYes"):t("onboarding.optionNo")})]},answered)),page==="env"?$jsxs("box",{flexDirection:"column",onMouseUp:()=>confirm(),children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:t("onboarding.envTitle")}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("onboarding.envExplain")}),$jsxs("box",{flexDirection:"column",paddingTop:1,children:[$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:props.env.git.line}),props.env.engines.lines.map((line)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:line},line))]}),$jsxs("box",{paddingTop:1,flexDirection:"column",children:[$jsx("text",{fg:ready?theme.success:theme.error,wrapMode:"word",children:ready?t("onboarding.envReady"):t("onboarding.envNotReady")}),envActionKeys(props.env).map((key)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:`\u2192 ${t(key)}`},key))]})]}):null,page==="keys"?$jsxs("box",{flexDirection:"column",onMouseUp:()=>confirm(),children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:t("onboarding.keysTitle")}),wizardKeyLines(currentPrefixConfiguration().key).map((line)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t(`onboarding.${line.msg}`,line.params)},line.msg))]}):null,page==="questions"?$jsxs($Fragment,{children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:questionFor(step)}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:explain}),[!0,!1].map((option)=>{let active=yes===option;return $jsxs("box",{flexDirection:"row",gap:1,paddingLeft:1,onMouseUp:()=>confirm(option),children:[$jsx("text",{fg:active?theme.primary:theme.textMuted,wrapMode:"none",children:active?"\u276F":" "}),$jsx("text",{fg:active?theme.primary:theme.textMuted,attributes:active?TextAttributes.BOLD:void 0,wrapMode:"none",children:option?t("onboarding.optionYes"):t("onboarding.optionNo")})]},String(option))})]}):null]}),$jsx("box",{paddingTop:1,children:$jsx("text",{fg:theme.textMuted,attributes:TextAttributes.DIM,wrapMode:"none",children:t(page==="keys"?"onboarding.keysLegend":page==="env"?"onboarding.envLegend":"onboarding.legend")})})]})}async function runOnboardingWizard(shell,env,mode){return await new Promise((resolve)=>{bootPaneHost({inlineRows:inlineRowsFor(env),setup:()=>({root:()=>$jsx(WizardPage,{shell,env,mode,onDone:resolve})})})})}export{runOnboardingWizard,WizardPage};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{checkOnboardingEnv,noEngineAction}from"./chunk-
|
|
2
|
+
import{checkOnboardingEnv,noEngineAction}from"./chunk-ajtw0hkk.js";import{LAST_RUN_VERSION_KEY}from"./chunk-j19ax03g.js";import{shippedCompletionsPath}from"./chunk-yybpg7fh.js";import{t}from"./chunk-x2c7ehve.js";import{isNpxMissing,markSkillHintSeen,npxSkillsArgv,npxSkillsCommand}from"./chunk-th4jd4sd.js";import{getPersistedBool,loadStateFile,setPersistedBool}from"./chunk-3jh78dmc.js";import{activeCliName}from"./chunk-00ehck55.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{appendFileSync,existsSync,mkdirSync,readFileSync,writeFileSync}from"fs";import{homedir}from"os";import{basename,join}from"path";var ONBOARDED_KEY="onboarded",PRIMER_KEY="onboardedPrimer";function detectShell(env=process.env){let shell=basename(env.SHELL??"");return shell==="zsh"||shell==="bash"||shell==="fish"?shell:null}function completionHook(shell,cli,shipped){if(shipped===null)return legacyCompletionHook(shell,cli);return shell==="fish"?`test -f "${shipped}"; and source "${shipped}"`:`[ -f "${shipped}" ] && source "${shipped}"`}function legacyCompletionHook(shell,cli){return shell==="fish"?`${cli} completions fish | source`:`command -v ${cli} >/dev/null && source <(${cli} completions ${shell})`}function shippedScriptFor(shell,cli){let path=shippedCompletionsPath(shell,cli);return existsSync(path)?path:null}function installCompletions(shell,home=homedir(),cli=activeCliName(),shipped=shippedScriptFor(shell,cli)){let hook=completionHook(shell,cli,shipped);if(shell==="fish"){let dir=join(home,".config","fish","completions"),path=join(dir,`${cli}.fish`);return mkdirSync(dir,{recursive:!0}),writeFileSync(path,`${hook}
|
|
3
3
|
`),{path,installed:!0}}let rc=join(home,shell==="zsh"?".zshrc":".bashrc"),existing=existsSync(rc)?readFileSync(rc,"utf8"):"";if(existing.includes(hook))return{path:rc,installed:!1};let legacy=legacyCompletionHook(shell,cli);if(existing.includes(legacy))return writeFileSync(rc,existing.replace(legacy,hook)),{path:rc,installed:!0};if(existing.includes(`${cli} completions`))return{path:rc,installed:!1};return appendFileSync(rc,`
|
|
4
4
|
# ${cli} completions
|
|
5
5
|
${hook}
|
|
6
6
|
`),{path:rc,installed:!0}}function isOnboarded(){return getPersistedBool(ONBOARDED_KEY,!1)}function markOnboarded(){setPersistedBool(ONBOARDED_KEY,!0)}function isPrimerDone(){return getPersistedBool(PRIMER_KEY,!1)}function markPrimerDone(){setPersistedBool(PRIMER_KEY,!0)}function backfillPrimerForExistingUsers(){if(typeof loadStateFile()[LAST_RUN_VERSION_KEY]!=="string")return!1;return markPrimerDone(),!0}function envReadyForTasks(env){return env.engines.anyUsable&&env.git.found}function applyOnboardingChoices(choices,shell,env){let cli=activeCliName(),completionsHelp=`${cli} completions --help`,skillInstall=`${cli} skill install`,out=(line)=>process.stdout.write(`${line}
|
|
7
|
-
`);if(shell!==null)if(choices.completions){let completion=installCompletions(shell);out(t(completion.installed?"onboarding.appliedCompletions":"onboarding.keptCompletions",{path:completion.path}))}else out(t("onboarding.skippedCompletions",{command:completionsHelp}));if(choices.skill){if(isNpxMissing())out(t("onboarding.skillNeedsNode",{command:skillInstall}));else if(out(t("onboarding.installingSkill",{command:npxSkillsCommand()})),spawnSync("npx",npxSkillsArgv(),{stdio:"inherit"}).status!==0)out(t("onboarding.skillFailed",{command:skillInstall}))}else out(t("onboarding.skippedSkill",{command:skillInstall})),markSkillHintSeen();out(""),out(env.git.line);for(let line of env.engines.lines)out(line);if(out(""),envReadyForTasks(env))out(t("onboarding.ready")),out(t("onboarding.readyHint",{command:cli}));else{if(out(t("onboarding.notReadyHeader")),!env.engines.anyUsable)out(` \u2192 ${noEngineAction(env.engines.signedOut)}`);if(!env.git.found)out(` \u2192 ${t("doctor.fix.gitAction")}`)}}async function maybeRunOnboarding(){if(!process.stdout.isTTY||!process.stdin.isTTY)return!1;let seen=isOnboarded();if(seen&&(isPrimerDone()||backfillPrimerForExistingUsers()))return!1;markOnboarded();let shell=detectShell(),env=await checkOnboardingEnv(),{runOnboardingWizard}=await import("./chunk-
|
|
7
|
+
`);if(shell!==null)if(choices.completions){let completion=installCompletions(shell);out(t(completion.installed?"onboarding.appliedCompletions":"onboarding.keptCompletions",{path:completion.path}))}else out(t("onboarding.skippedCompletions",{command:completionsHelp}));if(choices.skill){if(isNpxMissing())out(t("onboarding.skillNeedsNode",{command:skillInstall}));else if(out(t("onboarding.installingSkill",{command:npxSkillsCommand()})),spawnSync("npx",npxSkillsArgv(),{stdio:"inherit"}).status!==0)out(t("onboarding.skillFailed",{command:skillInstall}))}else out(t("onboarding.skippedSkill",{command:skillInstall})),markSkillHintSeen();out(""),out(env.git.line);for(let line of env.engines.lines)out(line);if(out(""),envReadyForTasks(env))out(t("onboarding.ready")),out(t("onboarding.readyHint",{command:cli}));else{if(out(t("onboarding.notReadyHeader")),!env.engines.anyUsable)out(` \u2192 ${noEngineAction(env.engines.signedOut)}`);if(!env.git.found)out(` \u2192 ${t("doctor.fix.gitAction")}`)}}async function maybeRunOnboarding(){if(!process.stdout.isTTY||!process.stdin.isTTY)return!1;let seen=isOnboarded();if(seen&&(isPrimerDone()||backfillPrimerForExistingUsers()))return!1;markOnboarded();let shell=detectShell(),env=await checkOnboardingEnv(),{runOnboardingWizard}=await import("./chunk-gfma7jt9.js"),choices=await runOnboardingWizard(shell,env,seen?"primer":"full");return markPrimerDone(),applyOnboardingChoices(choices,shell,env),!0}
|
|
8
8
|
export{detectShell,installCompletions,envReadyForTasks,applyOnboardingChoices,maybeRunOnboarding};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{BREAKING_VERSIONS,CURRENT_VERSION,compareSemver}from"./chunk-
|
|
2
|
+
import{BREAKING_VERSIONS,CURRENT_VERSION,compareSemver}from"./chunk-sgrbaynq.js";import{loadStateFile,patchStateFile}from"./chunk-3jh78dmc.js";import{activeCliName}from"./chunk-00ehck55.js";var LAST_RUN_VERSION_KEY="app.lastRunVersion";function resetGateBlockers(lastRun,current=CURRENT_VERSION,breaking=BREAKING_VERSIONS){if(typeof lastRun!=="string"||lastRun.length===0)return[];let[lo,hi]=compareSemver(lastRun,current)<=0?[lastRun,current]:[current,lastRun];return breaking.filter((b)=>compareSemver(b,lo)>0&&compareSemver(b,hi)<=0)}function enforceResetGate(){let cliName=activeCliName(),lastRun=loadStateFile()[LAST_RUN_VERSION_KEY],blockers=resetGateBlockers(lastRun);if(blockers.length>0){let from=typeof lastRun==="string"?lastRun:"unknown";console.error([`${cliName} ${CURRENT_VERSION}: cannot start \u2014 version ${blockers.join(", ")} introduced breaking changes`,`(last run: ${from}). Your daemon/session state may be incompatible.`,"","Run:",` ${cliName} reset # stop daemon + PTY host + sessions (tasks kept)`,` ${cliName} reset --hard # additionally wipe the task index + UI state`,"","Then relaunch Rove. Worktrees are never touched."].join(`
|
|
3
3
|
`)),process.exit(1)}if(lastRun!==CURRENT_VERSION)stampResetGate()}function stampResetGate(){try{patchStateFile({[LAST_RUN_VERSION_KEY]:CURRENT_VERSION})}catch{}}
|
|
4
4
|
export{LAST_RUN_VERSION_KEY,enforceResetGate,stampResetGate};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{discoverMachine}from"./chunk-z9hgw8hw.js";import{startTunnel}from"./chunk-k371m3p6.js";import{dedupeMachines,duplicateAliasOf,listMachines,readMachines,setMachineIdentity,updateMachine}from"./chunk-qjaqvn88.js";import{RemoteOrchestrator}from"./chunk-
|
|
2
|
+
import{discoverMachine}from"./chunk-z9hgw8hw.js";import{startTunnel}from"./chunk-k371m3p6.js";import{dedupeMachines,duplicateAliasOf,listMachines,readMachines,setMachineIdentity,updateMachine}from"./chunk-qjaqvn88.js";import{RemoteOrchestrator}from"./chunk-58hejzp4.js";import"./chunk-k6nxyxyh.js";import"./chunk-h4n8ffqy.js";import"./chunk-6xppe9bj.js";import"./chunk-te8g5azg.js";import"./chunk-y13681dw.js";import{KobeDaemonClient}from"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import{createStateCell}from"./chunk-sdyzxayr.js";import"./chunk-sgrbaynq.js";import"./chunk-xy8be792.js";import"./chunk-40dgv828.js";import{loadStateFile}from"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import{logClient,logClientError}from"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import"./chunk-9prawccj.js";import"./chunk-8cjr5ypt.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";class MachineHub{local;slots=new Map;machinesAcc=createStateCell([],"machines.status");mergedAcc=createStateCell([],"machines.tasks");localUnsubscribe=null;disposed=!1;constructor(local){this.local=local}machinesSignal(){return this.machinesAcc}tasksSignal(){if(this.slots.size===0)return this.local.tasksSignal();return this.mergedAcc}remoteTaskIds(){let ids=new Set;for(let slot of this.slots.values())for(let task of slot.tasks)ids.add(String(task.id));return ids}attach(){let entries=dedupeMachines(listMachines());if(entries.length===0)return;for(let entry of entries)this.slots.set(entry.alias,{entry,tasks:[]});this.publishStatuses(),this.localUnsubscribe=this.local.tasksSignal().subscribe(()=>this.republishTasks()),this.republishTasks();for(let entry of entries)this.connect(entry)}async connect(entry){let slot=this.slots.get(entry.alias);if(!slot||this.disposed)return;let found=await discoverMachine(entry.alias,entry);if(this.disposed)return;let sockets=found.ok?{daemon:found.status.socketPath,pty:found.status.ptySocketPath}:entry.sockets;if(!sockets){this.setStatus(entry.alias,{state:"offline",error:found.ok?void 0:found.message});return}if(found.ok)updateMachine(entry.alias,{sockets});let tunnel=startTunnel({alias:entry.alias,config:entry,remoteDaemonSocket:sockets.daemon,remotePtySocket:sockets.pty});if(slot.tunnel=tunnel,tunnel.state()==="unsupported"){this.setStatus(entry.alias,{state:"unsupported",error:"SSH unix-socket forwarding is not available on Windows"});return}if(tunnel.onState((state)=>{if(state==="online")this.openOrchestrator(entry,tunnel);else if(state==="offline")this.setStatus(entry.alias,{state:"offline"}),this.republishTasks()}),tunnel.state()==="online")await this.openOrchestrator(entry,tunnel)}async openOrchestrator(entry,tunnel){let slot=this.slots.get(entry.alias);if(!slot||this.disposed||slot.orchestrator)return;let client=new KobeDaemonClient(tunnel.daemonSocketPath),orchestrator=new RemoteOrchestrator(client,{role:"gui",expectForeignHome:!0,onPeerIdentity:(peer)=>this.onPeerIdentity(entry.alias,peer)});slot.orchestrator=orchestrator;try{await orchestrator.init()}catch(err){let message=err instanceof Error?err.message:String(err);this.setStatus(entry.alias,{state:classifyHandshakeFailure(message),error:message}),logClientError("machines",err);return}let stopTasks=orchestrator.tasksSignal().subscribe(()=>{slot.tasks=orchestrator.tasksSignal().get(),this.republishTasks()}),stopConnection=orchestrator.connectionStateSignal().subscribe(()=>{let connected=orchestrator.connectionStateSignal().get()==="online";if(this.slots.get(entry.alias)!==slot)return;this.setStatus(entry.alias,{state:connected?"online":"offline"}),this.republishTasks()});slot.unsubscribe=()=>{stopTasks(),stopConnection()},slot.tasks=orchestrator.tasksSignal().get(),this.setStatus(entry.alias,{state:"online",version:orchestrator.daemonVersionSignal().get()??void 0}),this.republishTasks(),logClient("machines",`${entry.alias} online (${slot.tasks.length} tasks)`)}onPeerIdentity(alias,peer){if(!peer.hostname&&!peer.homeDir)return;let identity={hostname:peer.hostname,homeDir:peer.homeDir,daemonPid:peer.daemonPid};setMachineIdentity(alias,identity);let duplicate=duplicateAliasOf(readMachines(loadStateFile()),alias,identity);this.setStatus(alias,{hostname:peer.hostname||void 0,version:peer.kobeVersion||void 0,...duplicate?{duplicateOf:duplicate}:{}})}setStatus(alias,patch){let next=this.machinesAcc.get().map((row)=>row.alias===alias?{...row,...patch}:row);this.machinesAcc.set(next)}publishStatuses(){this.machinesAcc.set([...this.slots.values()].map((slot)=>({alias:slot.entry.alias,hostLabel:slot.entry.alias,state:"connecting"})))}republishTasks(){let merged=this.local.tasksSignal().get().map((task)=>stampOrigin(task,"local","local"));for(let slot of this.slots.values()){let status=this.machinesAcc.get().find((row)=>row.alias===slot.entry.alias);if(status?.duplicateOf)continue;let hostLabel=status?.hostLabel||slot.entry.alias,stale=status?.state!=="online";for(let task of slot.tasks)merged.push(stampOrigin(task,slot.entry.alias,hostLabel,stale))}this.mergedAcc.set(merged)}dispose(){this.disposed=!0,this.localUnsubscribe?.();for(let slot of this.slots.values())slot.unsubscribe?.(),slot.orchestrator?.dispose(),slot.tunnel?.stop();this.slots.clear()}}function classifyHandshakeFailure(message){return/protocol v\d/i.test(message)?"mismatch":"offline"}function stampOrigin(task,machineId,hostLabel,stale=!1){return{...task,origin:{machineId,hostLabel,...stale?{stale:!0}:{}}}}export{stampOrigin,classifyHandshakeFailure,MachineHub};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import{CONTRIB_ENGINE_IDS,contribEngineEntry,detectClaudeAccount,detectCodexAccount,detectCopilotAccount,detectKimiAccount,isContribEngine,pluginEngineIds}from"./chunk-kx3kydwv.js";import{TomlError,parse}from"./chunk-w7zv47mp.js";import{spawnCapture}from"./chunk-khj0apc7.js";import{ClaudeHookAdapter,GATED_TOOL_VERBS,JsonHookAdapter,hookCommandQuoting,isObject,kobeHookInvocation,readSharedConfigSync,updateSharedJsonSync}from"./chunk-r92b9j14.js";import{claudeGlobalConfigPath,copilotConfigPath,isJsonlLineWithinBound,readFirstLineBounded,readTextFileBounded,readTextFileIfRegular,vendorAgentDir,vendorConfigHome,vendorWriteHomeDeps}from"./chunk-aep7gvh4.js";import{quoteShellArgv}from"./chunk-7kysxgbq.js";import{BUILTIN_VENDORS,isBuiltinVendor}from"./chunk-05jej26n.js";import{samePath}from"./chunk-f10n6063.js";var claudeCapabilities={interruptSequence:"\x1B"},claudeIdentity={shortName:"Claude"};import{homedir,userInfo}from"os";import path from"path";var OAUTH_USAGE_URL="https://api.anthropic.com/api/oauth/usage",OAUTH_BETA_HEADER="oauth-2025-04-20",OAUTH_USER_AGENT="claude-cli/2.1.198 (external, cli)",USAGE_TIMEOUT_MS=1e4,KEYCHAIN_SERVICE="Claude Code-credentials";function parseResetsAtMs(value){if(value==null)return null;let numeric=typeof value==="number"?value:/^\d+(?:\.\d+)?$/.test(value.trim())?Number(value):null;if(numeric!=null){if(!Number.isFinite(numeric)||numeric<=0)return null;return numeric<1000000000000?numeric*1000:numeric}let parsed=Date.parse(String(value));return Number.isNaN(parsed)?null:parsed}var clampPercent=(value)=>Math.min(100,Math.max(0,Math.round(value)));function windowLabel(kind,scopeModel){if(kind==="weekly_scoped"&&scopeModel)return scopeModel;return kind.startsWith("weekly")||kind.startsWith("seven_day")?"7d":"5h"}function usageFromClaudePayload(payload,capturedAt){let windows=[];if(payload.limits?.length)for(let limit of payload.limits){if(typeof limit.kind!=="string"||typeof limit.percent!=="number")continue;windows.push({kind:limit.kind,label:windowLabel(limit.kind,limit.scope?.model?.display_name),percent:clampPercent(limit.percent),resetsAt:parseResetsAtMs(limit.resets_at)})}else{if(typeof payload.five_hour?.utilization==="number")windows.push({kind:"session",label:"5h",percent:clampPercent(payload.five_hour.utilization),resetsAt:parseResetsAtMs(payload.five_hour.resets_at)});if(typeof payload.seven_day?.utilization==="number")windows.push({kind:"weekly_all",label:"7d",percent:clampPercent(payload.seven_day.utilization),resetsAt:parseResetsAtMs(payload.seven_day.resets_at)})}return{windows,capturedAt}}function parseCredentials(raw){try{let oauth=JSON.parse(raw)?.claudeAiOauth;if(!oauth||typeof oauth.accessToken!=="string"||!oauth.accessToken)return null;return{accessToken:oauth.accessToken,...typeof oauth.expiresAt==="number"&&Number.isFinite(oauth.expiresAt)?{expiresAt:oauth.expiresAt}:{}}}catch{return null}}var isFresh=(c)=>c.expiresAt===void 0||c.expiresAt>Date.now();async function readFileCredentials(dir){try{return parseCredentials(await readTextFileBounded(path.join(dir,".credentials.json")))}catch{return null}}async function readKeychainCredentials(){if(process.platform!=="darwin")return null;let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),3000);try{let result=await spawnCapture("security",["find-generic-password","-a",userInfo().username,"-w","-s",KEYCHAIN_SERVICE],{cwd:homedir(),signal:controller.signal});return result.status===0?parseCredentials(result.stdout.trim()):null}finally{clearTimeout(timeout)}}async function readAccessToken(){let configDir=process.env.CLAUDE_CONFIG_DIR?.trim();if(configDir){let fromFile=await readFileCredentials(configDir);return fromFile&&isFresh(fromFile)?fromFile.accessToken:null}return[await readKeychainCredentials(),await readFileCredentials(vendorConfigHome("claude"))].find((c)=>c!=null&&isFresh(c))?.accessToken??null}async function fetchClaudeQuotaUsage(now=Date.now){let token=await readAccessToken().catch(()=>null);if(!token)return null;let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),USAGE_TIMEOUT_MS);try{let response=await fetch(OAUTH_USAGE_URL,{headers:{Authorization:`Bearer ${token}`,"Content-Type":"application/json","User-Agent":OAUTH_USER_AGENT,"anthropic-beta":OAUTH_BETA_HEADER},signal:controller.signal});if(!response.ok)return null;return usageFromClaudePayload(await response.json(),now())}catch{return null}finally{clearTimeout(timeout)}}function trustClaudeWorktree(worktreePath,home){let deps=vendorWriteHomeDeps(home);updateSharedJsonSync(claudeGlobalConfigPath(deps.env,deps.home()),(raw)=>{if(raw===void 0)return{};let doc=JSON.parse(raw);if(!isObject(doc))throw Error("Claude trust config must be a JSON object");return doc},(doc)=>{if(doc.projects!==void 0&&!isObject(doc.projects))throw Error("Claude trust projects must be an object");let projects={...doc.projects},existing=Object.hasOwn(projects,worktreePath)?projects[worktreePath]:{};if(!isObject(existing))throw Error("Claude trust project must be an object");if(existing.hasTrustDialogAccepted===!0)return;return projects[worktreePath]={...existing,hasTrustDialogAccepted:!0,hasCompletedProjectOnboarding:!0},JSON.stringify({...doc,projects},null,2)})}function isSyntheticClaudeRecord(record){return record.isMeta===!0||record.isCompactSummary===!0}function isClaudeCommandBreadcrumb(blocks){if(blocks.length===0)return!1;for(let b of blocks){if(b.type!=="text")return!1;let t=b.text.trim();if(!t.startsWith("<command-name>")&&!t.startsWith("<command-message>")&&!t.startsWith("<local-command"))return!1}return!0}function isObject2(v){return typeof v==="object"&&v!==null&&!Array.isArray(v)}function opensTurn(content){if(typeof content==="string")return content.trim().length>0;if(!Array.isArray(content))return!1;return content.some((b)=>!isObject2(b)||b.type!=="tool_result")}function num(v){return typeof v==="number"&&Number.isFinite(v)?v:0}function readUsage(v){if(!isObject2(v))return;return{input_tokens:num(v.input_tokens),output_tokens:num(v.output_tokens),cache_read_input_tokens:num(v.cache_read_input_tokens),cache_creation_input_tokens:num(v.cache_creation_input_tokens)}}function finish(draft){if(!draft.id)return null;let totals={input_tokens:0,output_tokens:0,cache_read_input_tokens:0,cache_creation_input_tokens:0};for(let u of draft.usageByMessage.values())totals.input_tokens+=u.input_tokens,totals.output_tokens+=u.output_tokens,totals.cache_read_input_tokens+=u.cache_read_input_tokens,totals.cache_creation_input_tokens+=u.cache_creation_input_tokens;return{id:draft.id,sessionId:draft.sessionId,...draft.model?{model:draft.model}:{},startedAt:draft.startedAt,endedAt:draft.endedAt,...draft.usageByMessage.size>0?{usage:totals}:{}}}function parseClaudeTurns(raw,fallbackSessionId=""){let out=[],draft=null;for(let line of raw.split(`
|
|
3
|
-
`)){let trimmed=line.trim();if(!trimmed||!isJsonlLineWithinBound(trimmed))continue;let record;try{record=JSON.parse(trimmed)}catch{continue}if(!isObject2(record)||isSyntheticClaudeRecord(record))continue;let inner=isObject2(record.message)?record.message:record,at=typeof record.timestamp==="string"?Date.parse(record.timestamp):Number.NaN;if(!Number.isFinite(at))continue;let sessionId=typeof record.sessionId==="string"?record.sessionId:fallbackSessionId;if(inner.role==="user"){if(!opensTurn(inner.content))continue;if(draft){let done=finish(draft);if(done)out.push(done)}draft={id:"",sessionId,startedAt:at,endedAt:at,usageByMessage:new Map};continue}if(inner.role!=="assistant"||!draft)continue;if(draft.endedAt=at,typeof inner.model==="string")draft.model=inner.model;let messageId=typeof inner.id==="string"?inner.id:"";if(messageId)draft.id=messageId;let usage=readUsage(inner.usage);if(usage&&messageId)draft.usageByMessage.set(messageId,usage)}if(draft){let done=finish(draft);if(done)out.push(done)}return out}async function readClaudeTurns(transcriptPath){try{let raw=await readTextFileBounded(transcriptPath);return parseClaudeTurns(raw)}catch{return[]}}var HEX_RE=/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;function parseHex(value){let match=HEX_RE.exec(value);if(!match)return[0,0,0];return[Number.parseInt(match[1],16),Number.parseInt(match[2],16),Number.parseInt(match[3],16)]}function luminance([red,green,blue]){return(red*0.2126+green*0.7152+blue*0.0722)/255}function blend(from,to,amount){return[Math.round(from[0]+(to[0]-from[0])*amount),Math.round(from[1]+(to[1]-from[1])*amount),Math.round(from[2]+(to[2]-from[2])*amount)]}function codexUserMessageBackground(background){return luminance(background)>0.5?blend(background,[0,0,0],0.04):blend(background,[255,255,255],0.12)}function transcriptRewrite(palette){let foreground=parseHex(palette.foreground),background=parseHex(palette.background),backgroundIsLight=luminance(background)>0.5;return{matchBackground:codexUserMessageBackground(background),foreground:backgroundIsLight?foreground:background,background:backgroundIsLight?background:foreground}}var codexTerminalPresentation={alternateScreenStyleRewrites:(palette)=>[transcriptRewrite(palette)]};var codexCapabilities={terminalPresentation:codexTerminalPresentation,interruptSequence:"\x1B"},codexIdentity={shortName:"Codex"};import{join}from"path";var EVENT_MAP=[{event:"SessionStart",verb:"session-start"},{event:"UserPromptSubmit",verb:"turn-start"},{event:"Stop",verb:"turn-complete"},{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"}],KOBE_CODEX_HOOK_EVENTS=EVENT_MAP.map((e)=>e.event);function codexHooksPath(){return join(vendorConfigHome("codex"),"hooks.json")}class CodexHookAdapter extends JsonHookAdapter{vendor="codex";eventMap=EVENT_MAP;globalSettingsPath(){return codexHooksPath()}activityDetailFromPayload(kind,payload){if(kind==="tool-pre"||kind==="tool-post")return{tool:{...typeof payload.tool_name==="string"?{name:payload.tool_name}:{}}};if(kind==="pre-compact"||kind==="post-compact")return{compact:{trigger:payload.trigger==="manual"?"manual":"auto"}};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}:{}}}}import{createHash}from"crypto";function createAppendParseCache(opts){let maxFiles=opts.maxFiles??8,cache=new Map;function remember(filePath,entry){if(cache.delete(filePath),cache.set(filePath,entry),cache.size>maxFiles){let oldest=cache.keys().next().value;if(oldest!==void 0)cache.delete(oldest)}}return function(filePath,raw,ctx){let stableLength=raw.lastIndexOf(`
|
|
3
|
+
`)){let trimmed=line.trim();if(!trimmed||!isJsonlLineWithinBound(trimmed))continue;let record;try{record=JSON.parse(trimmed)}catch{continue}if(!isObject2(record)||isSyntheticClaudeRecord(record))continue;let inner=isObject2(record.message)?record.message:record,at=typeof record.timestamp==="string"?Date.parse(record.timestamp):Number.NaN;if(!Number.isFinite(at))continue;let sessionId=typeof record.sessionId==="string"?record.sessionId:fallbackSessionId;if(inner.role==="user"){if(!opensTurn(inner.content))continue;if(draft){let done=finish(draft);if(done)out.push(done)}draft={id:"",sessionId,startedAt:at,endedAt:at,usageByMessage:new Map};continue}if(inner.role!=="assistant"||!draft)continue;if(draft.endedAt=at,typeof inner.model==="string")draft.model=inner.model;let messageId=typeof inner.id==="string"?inner.id:"";if(messageId)draft.id=messageId;let usage=readUsage(inner.usage);if(usage&&messageId)draft.usageByMessage.set(messageId,usage)}if(draft){let done=finish(draft);if(done)out.push(done)}return out}async function readClaudeTurns(transcriptPath){try{let raw=await readTextFileBounded(transcriptPath);return parseClaudeTurns(raw)}catch{return[]}}var HEX_RE=/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;function parseHex(value){let match=HEX_RE.exec(value);if(!match)return[0,0,0];return[Number.parseInt(match[1],16),Number.parseInt(match[2],16),Number.parseInt(match[3],16)]}function luminance([red,green,blue]){return(red*0.2126+green*0.7152+blue*0.0722)/255}function blend(from,to,amount){return[Math.round(from[0]+(to[0]-from[0])*amount),Math.round(from[1]+(to[1]-from[1])*amount),Math.round(from[2]+(to[2]-from[2])*amount)]}function codexUserMessageBackground(background){return luminance(background)>0.5?blend(background,[0,0,0],0.04):blend(background,[255,255,255],0.12)}function transcriptRewrite(palette){let foreground=parseHex(palette.foreground),background=parseHex(palette.background),backgroundIsLight=luminance(background)>0.5;return{matchBackground:codexUserMessageBackground(background),foreground:backgroundIsLight?foreground:background,background:backgroundIsLight?background:foreground}}var codexTerminalPresentation={alternateScreenStyleRewrites:(palette)=>[transcriptRewrite(palette)]};var codexCapabilities={preparePromptSubmission:(prompt)=>{return{text:/^[\/!]/.test(prompt.trimStart())?prompt:`${prompt} `,key:"\r"}},terminalPresentation:codexTerminalPresentation,interruptSequence:"\x1B"},codexIdentity={shortName:"Codex"};import{join}from"path";var EVENT_MAP=[{event:"SessionStart",verb:"session-start"},{event:"UserPromptSubmit",verb:"turn-start"},{event:"Stop",verb:"turn-complete"},{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"}],KOBE_CODEX_HOOK_EVENTS=EVENT_MAP.map((e)=>e.event);function codexHooksPath(){return join(vendorConfigHome("codex"),"hooks.json")}class CodexHookAdapter extends JsonHookAdapter{vendor="codex";eventMap=EVENT_MAP;globalSettingsPath(){return codexHooksPath()}activityDetailFromPayload(kind,payload){if(kind==="tool-pre"||kind==="tool-post")return{tool:{...typeof payload.tool_name==="string"?{name:payload.tool_name}:{}}};if(kind==="pre-compact"||kind==="post-compact")return{compact:{trigger:payload.trigger==="manual"?"manual":"auto"}};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}:{}}}}import{createHash}from"crypto";function createAppendParseCache(opts){let maxFiles=opts.maxFiles??8,cache=new Map;function remember(filePath,entry){if(cache.delete(filePath),cache.set(filePath,entry),cache.size>maxFiles){let oldest=cache.keys().next().value;if(oldest!==void 0)cache.delete(oldest)}}return function(filePath,raw,ctx){let stableLength=raw.lastIndexOf(`
|
|
4
4
|
`)+1,entry=cache.get(filePath),verifiedLength=Math.min(entry?.prefixLength??0,stableLength),hash=createHash("sha256").update(raw.slice(0,verifiedLength)),unchanged=entry!==void 0&&Object.is(entry.context,ctx)&&entry.prefixLength<=stableLength&&hash.copy().digest("hex")===entry.prefixHash,prefixState;if(unchanged)prefixState=entry.prefixLength<stableLength?opts.parseChunk(raw.slice(entry.prefixLength,stableLength),entry.state,ctx):entry.state;else prefixState=opts.parseChunk(raw.slice(0,stableLength),opts.initial(ctx),ctx);if(!unchanged||entry.prefixLength!==stableLength||entry.state!==prefixState)remember(filePath,{context:ctx,prefixLength:stableLength,prefixHash:hash.update(raw.slice(verifiedLength,stableLength)).digest("hex"),state:prefixState});let tail=raw.slice(stableLength);return tail.trim().length>0?opts.parseChunk(tail,prefixState,ctx):prefixState}}var sortedMessages=new WeakMap;function sortByTimestamp(messages){let hit=sortedMessages.get(messages);if(hit)return hit;let sorted=[...messages].sort((a,b)=>a.timestamp<b.timestamp?-1:a.timestamp>b.timestamp?1:0);return sortedMessages.set(messages,sorted),sorted}function normalizeCodexContent(raw){if(typeof raw==="string")return raw.length>0?[{type:"text",text:raw}]:[];if(!Array.isArray(raw))return[];let blocks=[];for(let item of raw){if(typeof item==="string"){if(item.length>0)blocks.push({type:"text",text:item});continue}if(!isObject3(item))continue;let t=typeof item.type==="string"?item.type:void 0;if(t==="input_text"||t==="output_text"){let text=typeof item.text==="string"?item.text:"";if(text.length>0)blocks.push({type:"text",text});continue}if(t)blocks.push({type:"text",text:`[codex: ${t}]`})}return blocks}function isObject3(v){return typeof v==="object"&&v!==null&&!Array.isArray(v)}function isSyntheticCodexUserRow(blocks){if(blocks.length===0)return!1;for(let b of blocks){if(b.type!=="text")return!1;let t=(b.text??"").trim();if(!isTagEnvelope(t)&&!isInstructionsEnvelope(t))return!1}return!0}var ENVELOPE_TAGS=["environment_context","recommended_plugins","user_instructions"];function isTagEnvelope(text){return ENVELOPE_TAGS.some((tag)=>text.startsWith(`<${tag}>`)&&text.endsWith(`</${tag}>`))}function isInstructionsEnvelope(text){return text.startsWith("# AGENTS.md instructions")&&text.includes("<INSTRUCTIONS>")}function codexUsageToSnapshot(usage,opts={}){let totalInput=numberOr(usage.input_tokens,0),cachedInput=numberOr(usage.cached_input_tokens,0),output=numberOr(usage.output_tokens,0),nonCachedInput=Math.max(0,totalInput-cachedInput);if(totalInput<=0&&output<=0&&cachedInput<=0)return;return{input_tokens:nonCachedInput,output_tokens:output,...cachedInput>0?{cache_read_input_tokens:cachedInput}:{},...validPositive(opts.contextWindowTokens)?{context_window_tokens:opts.contextWindowTokens}:{}}}function numberOr(v,fallback){return typeof v==="number"&&Number.isFinite(v)?v:fallback}function validPositive(v){return typeof v==="number"&&Number.isFinite(v)&&v>0}var emptyState={messages:[],latestUsage:void 0,latestUsageTimestampMs:null},cache=createAppendParseCache({initial:()=>emptyState,parseChunk:foldRolloutChunk});function parseRolloutRaw(filePath,raw,sessionId){let state=cache(filePath,raw,sessionId);return{messages:sortByTimestamp(state.messages),...state.latestUsage?{usageMetrics:state.latestUsage}:{}}}function foldRolloutChunk(chunk,prev,sessionId){let updatedMessages,writableMessages=()=>{return updatedMessages??=[...prev.messages],updatedMessages},latestUsage=prev.latestUsage,latestUsageTimestampMs=prev.latestUsageTimestampMs;for(let line of chunk.split(`
|
|
5
5
|
`)){let trimmed=line.trim();if(!trimmed)continue;if(!isJsonlLineWithinBound(trimmed))continue;let parsed;try{parsed=JSON.parse(trimmed)}catch{continue}if(!isObject4(parsed))continue;if(parsed.type==="response_item"){let payload=isObject4(parsed.payload)?parsed.payload:void 0;if(!payload)continue;let ts=typeof parsed.timestamp==="string"?parsed.timestamp:new Date().toISOString(),msg=normalizeCodexResponseItem(payload,ts,sessionId);if(msg)writableMessages().push(msg);continue}let usageFields=codexUsageFields(parsed);if(!usageFields)continue;let base=codexUsageToSnapshot(usageFields.usage,{contextWindowTokens:usageFields.contextWindow});if(!base)continue;let lastPrompt=usageFields.lastUsage?numberOr2(usageFields.lastUsage.input_tokens):0,snapshot={...base,...lastPrompt>0?{context_tokens:lastPrompt}:{}},lastUsage=usageFields.lastUsage&&codexLastUsageToMessageUsage(usageFields.lastUsage);if(lastUsage){let messages=updatedMessages??prev.messages,index=messages.findLastIndex((message2)=>message2.role==="assistant"),message=messages[index];if(message)writableMessages()[index]={...message,usage:lastUsage}}let timestampMs=typeof parsed.timestamp==="string"?parseTimestampMs(parsed.timestamp):null;if(timestampMs!==null&&(latestUsageTimestampMs===null||timestampMs>latestUsageTimestampMs))latestUsageTimestampMs=timestampMs,latestUsage=snapshot;else if(latestUsageTimestampMs===null)latestUsage=snapshot}return{messages:updatedMessages??prev.messages,latestUsage,latestUsageTimestampMs}}function codexUsageFields(parsed){if(parsed.type==="event_msg"){let payload=isObject4(parsed.payload)?parsed.payload:void 0;if(payload?.type!=="token_count")return;let info=isObject4(payload.info)?payload.info:void 0,usage=info&&isObject4(info.total_token_usage)?info.total_token_usage:void 0;if(!usage)return;let lastUsage=info&&isObject4(info.last_token_usage)?info.last_token_usage:void 0,contextWindow=typeof info?.model_context_window==="number"?info.model_context_window:void 0;return{usage,lastUsage,contextWindow}}if(parsed.type==="turn.completed"){let usage=isObject4(parsed.usage)?parsed.usage:void 0;return usage?{usage,lastUsage:usage,contextWindow:void 0}:void 0}return}function codexLastUsageToMessageUsage(usage){let totalInput=numberOr2(usage.input_tokens),cachedInput=numberOr2(usage.cached_input_tokens),output=numberOr2(usage.output_tokens);if(totalInput<=0&&output<=0&&cachedInput<=0)return;return{input_tokens:Math.max(0,totalInput-cachedInput),output_tokens:output,...cachedInput>0?{cache_read_input_tokens:cachedInput}:{}}}function numberOr2(v){return typeof v==="number"&&Number.isFinite(v)?v:0}function normalizeCodexResponseItem(payload,timestamp,sessionId){if(payload.type==="message"){let role=payload.role;if(role!=="user"&&role!=="assistant"&&role!=="system")return;let blocks=normalizeCodexContent(payload.content);if(role==="user"&&isSyntheticCodexUserRow(blocks))return;return{role,blocks,timestamp,sessionId}}if(payload.type==="reasoning")return normalizeCodexReasoning(payload,timestamp,sessionId);if(payload.type==="function_call")return normalizeCodexToolCall(payload,timestamp,sessionId,{name:stringOr(payload.name,"function_call"),input:parseMaybeJson(payload.arguments)});if(payload.type==="custom_tool_call")return normalizeCodexToolCall(payload,timestamp,sessionId,{name:stringOr(payload.name,"custom_tool_call"),input:parseMaybeJson(payload.input)});if(payload.type==="tool_search_call")return normalizeCodexToolCall(payload,timestamp,sessionId,{name:"tool_search_call",input:stripPayload(payload,["type","call_id","status"])});if(payload.type==="function_call_output"||payload.type==="custom_tool_call_output")return normalizeCodexToolResult(payload,timestamp,sessionId,parseMaybeJson(payload.output));if(payload.type==="tool_search_output")return normalizeCodexToolResult(payload,timestamp,sessionId,stripPayload(payload,["type","call_id"]));if(payload.type==="web_search_call"||payload.type==="image_generation_call"||payload.type==="local_shell_call")return normalizeSingleRecordTool(payload,timestamp,sessionId);return}function normalizeCodexReasoning(payload,timestamp,sessionId){let text=reasoningTextFromItem(payload);if(text.length===0)return;return{role:"assistant",blocks:[{type:"thinking",text}],timestamp,sessionId}}function normalizeCodexToolCall(payload,timestamp,sessionId,args){let callId=typeof payload.call_id==="string"?payload.call_id:void 0;if(!callId)return;return{role:"assistant",blocks:[{type:"tool_call",callId,name:args.name,input:args.input}],timestamp,sessionId}}function normalizeCodexToolResult(payload,timestamp,sessionId,output){let callId=typeof payload.call_id==="string"?payload.call_id:void 0;if(!callId)return;return{role:"user",blocks:[{type:"tool_result",callId,output,isError:!1}],timestamp,sessionId}}var CODEX_OK_STATUSES=new Set(["completed","in_progress"]);function normalizeSingleRecordTool(payload,timestamp,sessionId){let type=typeof payload.type==="string"?payload.type:"tool",callId=typeof payload.call_id==="string"&&payload.call_id.length>0?payload.call_id:`${type}:${timestamp}`,name=stringOr(payload.name,type),input=stripPayload(payload,["type","call_id","status"]),output=stripPayload(payload,["type","call_id"]),status=payload.status,isError=typeof status==="string"&&!CODEX_OK_STATUSES.has(status);return{role:"assistant",timestamp,sessionId,blocks:[{type:"tool_call",callId,name,input},{type:"tool_result",callId,output,isError}]}}function reasoningTextFromItem(item){let content=textFromReasoningValue(item.content);if(content.length>0)return content;let text=typeof item.text==="string"?item.text:"";if(text.length>0)return text;return textFromReasoningValue(item.summary)}function textFromReasoningValue(value){if(typeof value==="string")return value;if(!Array.isArray(value))return"";let parts=[];for(let entry of value){if(typeof entry==="string"){parts.push(entry);continue}if(!isObject4(entry))continue;let text=typeof entry.text==="string"?entry.text:"";if(text.length>0)parts.push(text)}return parts.join("")}function stripPayload(payload,keys){let out={};for(let[key,value]of Object.entries(payload))if(!keys.includes(key))out[key]=value;return out}function stringOr(value,fallback){return typeof value==="string"&&value.length>0?value:fallback}function parseMaybeJson(value){if(typeof value!=="string")return value;try{return JSON.parse(value)}catch{return value}}function parseTimestampMs(value){let ms=new Date(value).getTime();return Number.isFinite(ms)?ms:null}function isObject4(v){return typeof v==="object"&&v!==null&&!Array.isArray(v)}import{readdir,stat}from"fs/promises";import path2 from"path";var defaultHistoryDeps={sessionsDir:()=>path2.join(vendorConfigHome("codex"),"sessions"),readdir:(p)=>readdir(p),readFile:readTextFileBounded,readHead:readFirstLineBounded,stat},UUID_AT_END=/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i,FULL_UUID=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,IO_CONCURRENCY=8;function sameStamp(a,b){return a.mtimeMs===b.mtimeMs&&a.size===b.size&&a.ctimeMs===b.ctimeMs&&a.ino===b.ino&&a.dev===b.dev}function rolloutCwd(raw){for(let line of raw.split(`
|
|
6
6
|
`)){if(!isJsonlLineWithinBound(line))return"";if(!line.trim())continue;try{let record=JSON.parse(line);if(typeof record!=="object"||record===null||!("type"in record)||record.type!=="session_meta")return"";if(!("payload"in record)||typeof record.payload!=="object"||record.payload===null)return"";return"cwd"in record.payload&&typeof record.payload.cwd==="string"?record.payload.cwd:""}catch{return""}}return""}class RolloutCatalog{root;deps;directories=new Map;metadata=new Map;located=new Map;refreshing;constructor(root,deps){this.root=root;this.deps=deps}async names(dir){let stamp=await this.deps.stat(dir).catch(()=>null),hit=this.directories.get(dir);if(!stamp)return this.directories.delete(dir),[];if(stamp?.ctimeMs!==void 0&&hit&&sameStamp(hit.stamp,stamp))return hit.names;let names;try{names=(await this.deps.readdir(dir)).sort().reverse()}catch{return hit?.names??[]}if(stamp)this.directories.set(dir,{stamp,names});return names}async*files(){let visited=new Set([this.root]);for(let year of await this.names(this.root)){if(!/^\d{4}$/.test(year))continue;let yp=path2.join(this.root,year);visited.add(yp);for(let month of await this.names(yp)){if(!/^(0[1-9]|1[0-2])$/.test(month))continue;let mp=path2.join(yp,month);visited.add(mp);for(let day of await this.names(mp)){if(!/^(0[1-9]|[12]\d|3[01])$/.test(day))continue;let dp=path2.join(mp,day);visited.add(dp);for(let name of await this.names(dp))if(name.startsWith("rollout-")&&name.endsWith(".jsonl"))yield path2.join(dp,name)}}}for(let dir of this.directories.keys())if(!visited.has(dir))this.directories.delete(dir)}async locate(sessionId){if(!FULL_UUID.test(sessionId))return;let id=sessionId.toLowerCase(),hit=this.located.get(id);if(hit&&await this.isFile(hit))return hit;this.located.delete(id);for await(let file of this.files()){if(path2.basename(file).match(UUID_AT_END)?.[1]?.toLowerCase()!==id||!await this.isFile(file))continue;if(this.located.size>=256){let oldest=this.located.keys().next().value;if(oldest!==void 0)this.located.delete(oldest)}return this.located.set(id,file),file}return}async isFile(file){let info=await this.deps.stat(file).catch(()=>null);return info!==null&&(info.isFile?.()??!0)}sessions(){if(!this.refreshing)this.refreshing=this.refresh().finally(()=>{this.refreshing=void 0});return this.refreshing}async refresh(){let next=new Map,files=[];for await(let file of this.files())files.push(file);let cursor=0,readNext=async()=>{while(cursor<files.length){let file=files[cursor++];if(file===void 0)break;let stamp=await this.deps.stat(file).catch(()=>null);if(!stamp)continue;let hit=this.metadata.get(file);if(hit&&sameStamp(hit.stamp,stamp)){next.set(file,hit);continue}let raw=await(this.deps.readHead??this.deps.readFile)(file).catch(()=>""),cwd=rolloutCwd(raw),sessionId=path2.basename(file).match(UUID_AT_END)?.[1];if(cwd&&sessionId)next.set(file,{path:file,sessionId,cwd,stamp})}};return await Promise.all(Array.from({length:Math.min(IO_CONCURRENCY,files.length)},readNext)),this.metadata=next,files.flatMap((file)=>{let entry=next.get(file);return entry?[entry]:[]})}}var catalogs=new WeakMap;function catalog(deps){let root=deps.sessionsDir(),current=catalogs.get(deps);if(!current||current.root!==root)current=new RolloutCatalog(root,deps),catalogs.set(deps,current);return current}async function listRolloutFiles(deps=defaultHistoryDeps){let files=[];for await(let file of catalog(deps).files())files.push(file);return files}function findRolloutFile(sessionId,deps=defaultHistoryDeps){return catalog(deps).locate(sessionId)}async function listSessionIdsForWorktree(worktree,deps=defaultHistoryDeps){if(!worktree)return[];return(await catalog(deps).sessions()).filter((file)=>samePath(file.cwd,worktree)).map((file)=>file.sessionId).reverse()}async function findLatestRolloutForWorktree(worktree,deps=defaultHistoryDeps){if(!worktree)return null;let best=null;for(let file of await catalog(deps).sessions())if(samePath(file.cwd,worktree)&&(!best||file.stamp.mtimeMs>best.mtimeMs))best={path:file.path,mtimeMs:file.stamp.mtimeMs};return best}async function latestTranscriptMtimeForWorktree(worktree,deps=defaultHistoryDeps){return(await findLatestRolloutForWorktree(worktree,deps))?.mtimeMs??0}async function readHistory(sessionId,deps=defaultHistoryDeps){return(await readHistoryWithMetrics(sessionId,deps)).messages}async function readHistoryWithMetrics(sessionId,deps=defaultHistoryDeps){let file=await findRolloutFile(sessionId,deps);if(!file)return{messages:[]};let raw;try{raw=await deps.readFile(file)}catch{return{messages:[]}}return parseRolloutRaw(file,raw,sessionId)}var MAX_ROLLOUTS_SCANNED=5;function windowLabel2(minutes){if(minutes%1440===0)return`${minutes/1440}d`;if(minutes%60===0)return`${minutes/60}h`;return`${minutes}m`}function toWindow(kind,raw,nowMs){if(!raw||typeof raw.used_percent!=="number"||typeof raw.window_minutes!=="number")return null;let resetsAt=typeof raw.resets_at==="number"&&raw.resets_at>0?raw.resets_at*1000:null;if(resetsAt==null||resetsAt<=nowMs)return null;return{kind,label:windowLabel2(raw.window_minutes),percent:Math.min(100,Math.max(0,Math.round(raw.used_percent))),resetsAt}}function usageFromRolloutRaw(raw,nowMs){let lines=raw.split(`
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{deriveTitleFromPrompt}from"./chunk-xb9b93ts.js";import{TaskDeletingError}from"./chunk-ztwz2465.js";import{awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,enginePresence,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp,trustEngineWorktree}from"./chunk-3dv9vdpj.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{engineLaunchArgv,protocolEntry}from"./chunk-00t0rc5r.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";var MAX_SESSIONS_SCANNED=8;function titleFromMessages(messages){let firstUser=messages.find((m)=>m.role==="user");if(!firstUser)return"";let text=firstUser.blocks.filter((b)=>b.type==="text").map((b)=>b.text).join(" "),title=deriveTitleFromPrompt(text);return title.length>0?Buffer.from(title,"utf8").toString("utf8"):title}async function deriveTitleFromSession(worktree,vendor=DEFAULT_TASK_VENDOR){if(!worktree)return"";let{history}=protocolEntry(vendor),ids=await history.listSessionIdsForWorktree(worktree);for(let sessionId of ids.slice(0,MAX_SESSIONS_SCANNED)){let title=titleFromMessages(await history.readHistory(sessionId));if(title)return title}return""}async function deriveTitleFromSessionId(vendor,sessionId){if(!sessionId)return"";try{return titleFromMessages(await protocolEntry(vendor).history.readHistory(sessionId))}catch{return""}}async function getTask(link,taskId){let{task}=await link.request("task.get",{taskId});return task}async function ensureTaskWorktree(link,taskId){let task=await getTask(link,taskId);if(task.deletion)throw new TaskDeletingError(taskId);if(task.worktreePath)return{task,worktreePath:task.worktreePath};let{worktreePath}=await link.request("task.ensureWorktree",{taskId});if(!worktreePath)throw Error(`task ${taskId} has no worktree`);return{task,worktreePath}}async function ensureTaskSessionAdapter(link,taskId){let{task,worktreePath}=await ensureTaskWorktree(link,taskId),launch=taskEngineLaunch(task,worktreePath,{kind:"repo-init"}),host=await ensureHostedSessionHost();try{if(!(await ensureHostedEngine(host.rpc,worktreePath,launch)).alive)throw Error(`failed to start hosted engine session for ${taskId}`);if(launch.firstMessage){let engineBin=engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort})[0];await pastePromptWhenEngineUp(host.rpc,launch.key,engineBin,launch.firstMessage,{initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs}).catch(()=>!1)}}finally{host.close()}return{session:launch.key,worktreePath}}async function startTaskSessionWithPromptAdapter(link,taskId,prompt){let{task,worktreePath}=await ensureTaskWorktree(link,taskId);await link.request("task.observeLanguage",{taskId,text:prompt}).catch(()=>{});let launch=taskEngineLaunch(task,worktreePath,{kind:"new-task",prompt}),host=await ensureHostedSessionHost();try{if(!(await ensureHostedEngine(host.rpc,worktreePath,launch)).alive)return{started:!1,error:"hosted session did not open"};let engineBin=engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort})[0],wait={initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs};if(launch.firstMessage){if(await pastePromptWhenEngineUp(host.rpc,launch.key,engineBin,launch.firstMessage,wait)!==null)return{started:!0};return{started:!1,error:await startFailureReason(host.rpc,launch.key)}}if(await awaitEngineProcess(host.rpc,launch.key,engineBin,wait)!==null)return{started:!0};return{started:!1,error:await startFailureReason(host.rpc,launch.key)}}finally{host.close()}}async function startFailureReason(rpc,key){let tail=await hostedSessionFailureLine(rpc,key),base="engine process never started";return tail?`engine process never started; last session output: ${tail}`:"engine process never started"}function taskEngineLaunch(task,worktreePath,promptIntent){return trustEngineWorktree(task.vendor,worktreePath),buildEngineSessionLaunch({task:{id:task.id,kind:task.kind,vendor:task.vendor,repo:task.repo},worktreePath,shell:resolveLoginShell({fallback:"/bin/zsh"}),argv:engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort}),promptIntent})}async function deliverPromptToLiveEngineAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return!1;try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0]);if(!key)return!1;let presence=await enginePresence(sessions.find((s)=>s.key===key)?.pid,engineArgv);if(presence.kind!=="engine")return!1;return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})!==null}catch{return!1}finally{host.close()}}function tabIdFromHostedKey(key){return key.split("::")[1]??"tab-1"}async function deliverPromptToLiveEngineDetailedAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0]);if(!key)return{outcome:"no-session"};let presence=await enginePresence(sessions.find((s)=>s.key===key)?.pid,engineArgv);if(presence.kind!=="engine")return{outcome:"no-engine",tabId:tabIdFromHostedKey(key)};return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:tabIdFromHostedKey(key)}}catch{return{outcome:"no-session"}}finally{host.close()}}async function deliverPromptToLiveEngineTabDetailedAdapter(target,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let key=`${target.id}::${target.tabId}`,sessions;try{sessions=await listHostedSessions(host.rpc)}catch{return{outcome:"no-session"}}let session=sessions.find((candidate)=>candidate.alive&&candidate.key===key);if(!session)return{outcome:"no-session"};let engineArgv=engineLaunchArgv({command:target.command,vendor:target.vendor}),presence=await enginePresence(session.pid,engineArgv);if(presence.kind!=="engine")return{outcome:"no-engine",tabId:target.tabId};return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:target.tabId}}finally{host.close()}}async function tearDownTaskSessionAdapter(taskId){let host=await openHostedSessionHost();if(!host)return;try{await killHostedSessions(host.rpc,hostedTaskKeys(await listHostedSessions(host.rpc),taskId))}catch{}finally{host.close()}}
|
|
3
|
+
export{deriveTitleFromSession,deriveTitleFromSessionId,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,tearDownTaskSessionAdapter};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{PS_PROBE_TIMEOUT_MS,engineProcessIn,foregroundEngine,foregroundEngineIn,hasAncestor,parsePsSnapshot,psSnapshot,psSnapshotWith,vendorFromArgv}from"./chunk-
|
|
2
|
+
import{PS_PROBE_TIMEOUT_MS,engineProcessIn,foregroundEngine,foregroundEngineIn,hasAncestor,parsePsSnapshot,psSnapshot,psSnapshotWith,vendorFromArgv}from"./chunk-qnj7vk5g.js";import"./chunk-kav5p2qb.js";import"./chunk-kx3kydwv.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-2brn8e1y.js";import"./chunk-r92b9j14.js";import"./chunk-aep7gvh4.js";import"./chunk-7kysxgbq.js";import"./chunk-krpsfcda.js";import"./chunk-xy8be792.js";import"./chunk-9ydhv2zb.js";import"./chunk-40dgv828.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-05jej26n.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-f10n6063.js";import"./chunk-9prawccj.js";import"./chunk-8cjr5ypt.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import{PsProbeUnavailableError}from"./chunk-pxk2c2vj.js";import"./chunk-wqfp8d9w.js";export{vendorFromArgv,psSnapshotWith,psSnapshot,parsePsSnapshot,hasAncestor,foregroundEngineIn,foregroundEngine,engineProcessIn,PsProbeUnavailableError,PS_PROBE_TIMEOUT_MS};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{engineEntry,identifiableEngineIds}from"./chunk-
|
|
2
|
+
import{engineEntry,identifiableEngineIds}from"./chunk-kav5p2qb.js";import{recordSpawn}from"./chunk-40dgv828.js";import{loadStateFile}from"./chunk-3jh78dmc.js";import{PsProbeUnavailableError}from"./chunk-pxk2c2vj.js";import{__require}from"./chunk-wqfp8d9w.js";import{basename}from"path";var WRAPPERS=new Set(["node","bun","npx","deno","sh","zsh","bash","env","script"]);function binaryName(token){return basename(token).replace(/\.(exe|js|mjs|cjs)$/,"")}function executableNameFromArgv(argv){for(let token of argv.slice(0,8)){if(/^[A-Za-z_][A-Za-z0-9_]*=/.test(token))continue;let name=binaryName(token);if(WRAPPERS.has(name))continue;return name||null}return null}function vendorFromArgv(commandLine){let name=executableNameFromArgv(commandLine.trim().split(/\s+/));if(!name)return null;return identifiableEngineIds().find((v)=>{let entry=engineEntry(v);return entry.defaultCommand[0]===name||entry.processNames?.includes(name)===!0})??null}function parsePsSnapshot(text){let rows=[];for(let line of text.split(`
|
|
3
3
|
`)){let m=/^\s*(\d+)\s+(\d+)\s+(\S.*)$/.exec(line);if(m)rows.push({pid:Number(m[1]),ppid:Number(m[2]),args:m[3]})}return rows}function childrenIndex(rows){let kids=new Map;for(let row of rows){let list=kids.get(row.ppid);if(list)list.push(row);else kids.set(row.ppid,[row])}return kids}function hasAncestor(rows,pid,ancestorPid){let parents=new Map(rows.map((r)=>[r.pid,r.ppid])),cur=pid;for(let hops=0;hops<=rows.length;hops++){if(cur===ancestorPid)return!0;let next=parents.get(cur);if(next===void 0||next<=1)return!1;cur=next}return!1}function customEngineBinaries(){let state=loadStateFile(),ids=state.customEngineIds,out=new Map;if(!Array.isArray(ids))return out;for(let id of ids){if(typeof id!=="string"||id.trim().length===0)continue;let command=state[`engineCommand.${id}`],argv=typeof command==="string"&&command.trim().length>0?command.trim().split(/\s+/):[id],name=executableNameFromArgv(argv);if(name)out.set(name,id)}return out}function walkDescendants(rows,rootPid,identify){let kids=childrenIndex(rows),queue=[...kids.get(rootPid)??[]];while(queue.length>0){let row=queue.shift();if(!row)break;let vendor=identify(row.args);if(vendor)return{vendor,argv:row.args,pid:row.pid};queue.push(...kids.get(row.pid)??[])}return null}function foregroundEngineIn(rows,rootPid){let builtin=walkDescendants(rows,rootPid,vendorFromArgv);if(builtin)return builtin;let custom=customEngineBinaries();if(custom.size===0)return null;return walkDescendants(rows,rootPid,(args)=>custom.get(executableNameFromArgv(args.trim().split(/\s+/))??"")??null)}function engineProcessIn(rows,rootPid,extraLaunch){if(foregroundEngineIn(rows,rootPid))return!0;let expected=extraLaunch?executableNameFromArgv(typeof extraLaunch==="string"?[extraLaunch]:extraLaunch):null;if(!expected)return!1;let kids=childrenIndex(rows),queue=[...kids.get(rootPid)??[]];while(queue.length>0){let row=queue.shift();if(!row)break;if(executableNameFromArgv(row.args.trim().split(/\s+/))===expected)return!0;queue.push(...kids.get(row.pid)??[])}return!1}var PS_PROBE_TIMEOUT_MS=5000,bunPsSpawn=()=>{recordSpawn("engine.foregroundWalk",["ps","-A","-o","pid=,ppid=,args="]);let proc=Bun.spawn(["ps","-A","-o","pid=,ppid=,args="],{stdout:"pipe",stderr:"ignore"});return{text:new Response(proc.stdout).text(),kill:()=>proc.kill()}};async function psSnapshotWith(spawn,timeoutMs=PS_PROBE_TIMEOUT_MS){let proc=spawn(),timer;try{let text=await Promise.race([proc.text,new Promise((_resolve,reject)=>{timer=setTimeout(()=>{try{proc.kill()}catch{}reject(new PsProbeUnavailableError(`ps did not answer within ${timeoutMs}ms`))},timeoutMs)})]);if(parsePsSnapshot(text).length===0)throw new PsProbeUnavailableError("ps returned no usable rows");return text}finally{if(timer)clearTimeout(timer)}}var psSnapshot=async(anchors)=>{if(process.platform!=="win32")return psSnapshotWith(bunPsSpawn);let{defaultWinProcessProbe,winProcessSnapshot}=await import("./chunk-hses07jj.js");return winProcessSnapshot(anchors??[],defaultWinProcessProbe())};async function foregroundEngine(rootPid,snapshot=psSnapshot){try{return foregroundEngineIn(parsePsSnapshot(await snapshot([rootPid])),rootPid)}catch{return null}}
|
|
4
4
|
export{vendorFromArgv,parsePsSnapshot,hasAncestor,foregroundEngineIn,engineProcessIn,PS_PROBE_TIMEOUT_MS,psSnapshotWith,psSnapshot,foregroundEngine};
|