@sma1lboy/rove 0.9.179 → 0.9.181
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{chunk-wdzhfbye.js → chunk-1f071tjz.js} +1 -1
- package/dist/cli/{chunk-z5x3cd7j.js → chunk-1jbznr12.js} +1 -1
- package/dist/cli/{chunk-bkba9c4n.js → chunk-2apszxn2.js} +1 -1
- package/dist/cli/{chunk-3p5yjwjs.js → chunk-2htnatha.js} +1 -1
- package/dist/cli/{chunk-1vpsb31h.js → chunk-2jnkfg4v.js} +1 -1
- package/dist/cli/{chunk-esgxxnwn.js → chunk-2pv5vb5a.js} +1 -1
- package/dist/cli/{chunk-nnscywzf.js → chunk-3ft463z9.js} +1 -1
- package/dist/cli/{chunk-4kweezsh.js → chunk-42h7m08p.js} +2 -2
- package/dist/cli/{chunk-3dexjt11.js → chunk-4s6j1hv9.js} +1 -1
- package/dist/cli/{chunk-y9bgn622.js → chunk-5nn763sy.js} +1 -1
- package/dist/cli/{chunk-nqkcrhpp.js → chunk-658hahan.js} +1 -1
- package/dist/cli/{chunk-cnre6fbm.js → chunk-6d4xwg7m.js} +1 -1
- package/dist/cli/{chunk-8npdrpq2.js → chunk-6tt33a84.js} +1 -1
- package/dist/cli/{chunk-nnmpben9.js → chunk-6y88a3b4.js} +2 -2
- package/dist/cli/{chunk-hcsfp7z7.js → chunk-6zwnwbd4.js} +1 -1
- package/dist/cli/{chunk-80hf0bbr.js → chunk-71k66b8f.js} +2 -2
- package/dist/cli/chunk-7kysxgbq.js +3 -0
- package/dist/cli/{chunk-kweffk7w.js → chunk-82p0wh0h.js} +1 -1
- package/dist/cli/{chunk-0vrv03qn.js → chunk-847gwrx2.js} +1 -1
- package/dist/cli/{chunk-r2r5krab.js → chunk-8gavx8g1.js} +1 -1
- package/dist/cli/{chunk-0s7e3cnc.js → chunk-8qx8gtfr.js} +2 -2
- package/dist/cli/{chunk-534se0f6.js → chunk-a7e6a754.js} +1 -1
- package/dist/cli/{chunk-cv6zwad5.js → chunk-bsg826q0.js} +1 -1
- package/dist/cli/{chunk-fa7s3d1e.js → chunk-bwrb6c2h.js} +1 -1
- package/dist/cli/{chunk-8znc46fw.js → chunk-cb082qmy.js} +1 -1
- package/dist/cli/{chunk-6f18r6vf.js → chunk-cwzhqjke.js} +1 -1
- package/dist/cli/{chunk-8qx3959c.js → chunk-d51xktn8.js} +1 -1
- package/dist/cli/{chunk-emkfynn5.js → chunk-d6x4gama.js} +1 -1
- package/dist/cli/{chunk-frdr9bjy.js → chunk-d8hcpwr6.js} +2 -2
- package/dist/cli/{chunk-rwkbxtpe.js → chunk-eahj40hv.js} +1 -1
- package/dist/cli/{chunk-wz421xna.js → chunk-erzb2kq5.js} +1 -1
- package/dist/cli/{chunk-0xgd6as7.js → chunk-ey9xbdpm.js} +1 -1
- package/dist/cli/{chunk-zkj59kkd.js → chunk-fprjrr5e.js} +3 -3
- package/dist/cli/{chunk-ne34zknk.js → chunk-g9vz4dma.js} +1 -1
- package/dist/cli/{chunk-9sa6vtp0.js → chunk-hex5xwyk.js} +1 -1
- package/dist/cli/{chunk-d8nmt9zt.js → chunk-hssrp88v.js} +1 -1
- package/dist/cli/{chunk-615s6xjd.js → chunk-hvm1aqjv.js} +1 -1
- package/dist/cli/{chunk-wvq6kgcp.js → chunk-j0jb8kav.js} +1 -1
- package/dist/cli/{chunk-t0bfjapm.js → chunk-k53xe8jg.js} +3 -3
- package/dist/cli/{chunk-gpt8mj16.js → chunk-k7hfh7m3.js} +1 -1
- package/dist/cli/{chunk-hfpmeck1.js → chunk-mc33ba6j.js} +1 -1
- package/dist/cli/{chunk-v5dmc2r6.js → chunk-md0q657y.js} +1 -1
- package/dist/cli/{chunk-br6dggaa.js → chunk-n4bhegyh.js} +1 -1
- package/dist/cli/{chunk-pspw5k9e.js → chunk-p9b3cp59.js} +2 -2
- package/dist/cli/{chunk-v61s3fps.js → chunk-pdnq8dbm.js} +2 -2
- package/dist/cli/{chunk-8cdrt8zx.js → chunk-pnb48jrh.js} +1 -1
- package/dist/cli/{chunk-6tvs0r4z.js → chunk-ptfe9a1h.js} +1 -1
- package/dist/cli/{chunk-q8v9zad9.js → chunk-q6bhnxw9.js} +1 -1
- package/dist/cli/chunk-qqh9aef5.js +3 -0
- package/dist/cli/{chunk-bg16r4yh.js → chunk-qrdjqwn7.js} +1 -1
- package/dist/cli/{chunk-ccwc3h8y.js → chunk-r8j5zpt9.js} +1 -1
- package/dist/cli/{chunk-jg61s3ce.js → chunk-rc0sqhdh.js} +1 -1
- package/dist/cli/{chunk-xswrw836.js → chunk-rtdz71g6.js} +1 -1
- package/dist/cli/{chunk-pcrv3eyw.js → chunk-t0qqabdw.js} +1 -1
- package/dist/cli/{chunk-s0gqxhk7.js → chunk-ts77enjd.js} +5 -5
- package/dist/cli/{chunk-g7baby60.js → chunk-vhq2dhx2.js} +1 -1
- package/dist/cli/{chunk-km4hx6kc.js → chunk-wdrgfezn.js} +1 -1
- package/dist/cli/{chunk-k0xgtzm2.js → chunk-x4hss5rp.js} +1 -1
- package/dist/cli/{chunk-zx7fkp8y.js → chunk-yn8pahva.js} +1 -1
- package/dist/cli/{chunk-xr30vfgt.js → chunk-yrmj16b9.js} +1 -1
- package/dist/cli/{chunk-1ngaph89.js → chunk-z0fbsvs0.js} +1 -1
- package/dist/cli/{chunk-yvmz8cts.js → chunk-zj8y4f4x.js} +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/cli/kobe.js +1 -1
- package/dist/cli/rove.js +1 -1
- package/dist/pulse-ynhb2ave.wav +0 -0
- package/package.json +1 -1
- package/dist/cli/chunk-2fypr41w.js +0 -3
- package/dist/cli/chunk-dazqahfp.js +0 -3
- package/dist/pulse-n3cq1btw.wav +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{buildEngineSessionLaunch,trustEngineWorktree}from"./chunk-frdr9bjy.js";import{engineForkArgv,engineResumeArgv,withPinnedSessionId}from"./chunk-xr30vfgt.js";import{t}from"./chunk-fa7s3d1e.js";import{tildify}from"./chunk-fczqwtmq.js";import{engineEntry,engineStatusPrefixes,isEnginePlaceholderTitle,stripEngineStatusPrefix}from"./chunk-80hf0bbr.js";import{pathSyntax}from"./chunk-f10n6063.js";import*as fs from"fs";import*as os from"os";function pathLeaf(p){return p.slice(lastSeparator(p)+1)}function lastSeparator(p){return pathSyntax(p).sep==="\\"||process.platform==="win32"&&!p.startsWith("/")?Math.max(p.lastIndexOf("/"),p.lastIndexOf("\\")):p.lastIndexOf("/")}function expandHome(p){if(p==="~")return os.homedir();if(p.startsWith("~/")||process.platform==="win32"&&p.startsWith("~\\"))return os.homedir()+p.slice(1);return p}function stripTrailingSlash(p){let root=pathSyntax(p).parse(p).root,end=p.length;while(end>root.length&&lastSeparator(p.slice(0,end))===end-1)end--;return p.slice(0,end)}function splitPathForDirSuggest(value){if(!value)return{base:"",filter:""};let expanded=expandHome(value==="~"?"~/":value),lastSlash=lastSeparator(expanded);if(lastSlash===-1)return{base:"",filter:expanded};return{base:expanded.slice(0,lastSlash+1),filter:expanded.slice(lastSlash+1)}}function listSubdirs(base){if(!base)return[];try{let entries=fs.readdirSync(base,{withFileTypes:!0}),out=[];for(let e of entries)if(e.isDirectory())out.push(e.name);return out.sort((a,b)=>a.localeCompare(b))}catch{return[]}}function filterSubdirs(all,filter){let f=filter.toLowerCase(),visible=f.startsWith(".")?all:all.filter((n)=>!n.startsWith("."));if(!f)return visible;return visible.filter((n)=>n.toLowerCase().startsWith(f))}function joinDrill(typedValue,baseExpanded,name){let out=`${baseExpanded+name}/`;if(typedValue.startsWith("~")){let short=tildify(out);if(short.startsWith("~"))return short==="~"?"~/":`${short}/`}return out}function joinPicked(typedValue,baseExpanded,name){let out=baseExpanded+name;if(typedValue.startsWith("~"))return tildify(out);return out}function depth(node){return node.kind==="leaf"?0:1+Math.max(...node.children.map(depth))}function siblingCount(root,id,orientation){let find=(node)=>{if(node.kind==="leaf")return null;if(node.orientation===orientation&&node.children.some((c)=>c.kind==="leaf"&&c.id===id))return node.children.length;for(let child of node.children){let n=find(child);if(n!==null)return n}return null};return find(root)??1}function splitFits(state,orientation,activeSize){let extent=orientation==="row"?activeSize.cols:activeSize.rows,min=orientation==="row"?20:6,n=siblingCount(state.root,state.activeLeafId,orientation);return Math.floor(extent*n/(n+1))-1>=min}function initialSplit(content){return{root:{kind:"leaf",id:"leaf-1",content},activeLeafId:"leaf-1",nextOrdinal:2}}function leaves(node){return node.kind==="leaf"?[node]:node.children.flatMap(leaves)}function splitActive(state,orientation,content,activeSize){if(activeSize&&!splitFits(state,orientation,activeSize))return state;let leaf={kind:"leaf",id:`leaf-${state.nextOrdinal}`,content},insert=(node)=>{if(node.kind==="leaf"){if(node.id!==state.activeLeafId)return node;return{kind:"group",orientation,children:[node,leaf]}}if(node.orientation===orientation){let i=node.children.findIndex((c)=>c.kind==="leaf"&&c.id===state.activeLeafId);if(i>=0){let children=[...node.children.slice(0,i+1),leaf,...node.children.slice(i+1)];return{...node,children}}}return{...node,children:node.children.map(insert)}},root=insert(state.root);if(!activeSize&&depth(root)>4)return state;return{root,activeLeafId:leaf.id,nextOrdinal:state.nextOrdinal+1}}function removeLeaf(state,id){let all=leaves(state.root);if(all.length<=1)return null;let prune=(node)=>{if(node.kind==="leaf")return node.id===id?null:node;let children=node.children.map(prune).filter((c)=>c!==null);if(children.length===0)return null;if(children.length===1)return children[0];return{...node,children}},root=prune(state.root);if(root===null)return null;if(leaves(root).length===all.length)return state;let order=all.map((l)=>l.id),removedIdx=order.indexOf(id),fallback=order[removedIdx>0?removedIdx-1:removedIdx+1],activeLeafId=state.activeLeafId===id?fallback:state.activeLeafId;return{...state,root,activeLeafId}}function renameLeaf(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,walk=(node)=>node.kind==="leaf"?node.id===id?{...node,title:next}:node:{...node,children:node.children.map(walk)};if(!leaves(state.root).some((l)=>l.id===id))return state;return{...state,root:walk(state.root)}}function cycleLeaf(state,delta){let order=leaves(state.root).map((l)=>l.id);if(order.length<=1)return state;let i=order.indexOf(state.activeLeafId),next=order[(i+delta+order.length)%order.length];return{...state,activeLeafId:next}}function hasEngineLeaf(tree){return!tree||leaves(tree.root).some((l)=>l.id==="leaf-1")}function isTabSplit(tree){return tree?leaves(tree.root).length>1:!1}function collapseSplit(next){let ls=leaves(next.root);return ls.length===1&&ls[0]?.id==="leaf-1"?null:next}function splitLeafPtyKey(tabKey,leafId){return leafId==="leaf-1"?tabKey:`${tabKey}::${leafId}`}var SHELL_LEAF_NAME="shell";function splitLeafNames(leafList,tabCommand,engineTitle,liveTitles){let basename=(argv)=>{let head=(argv??tabCommand)[0]??"",name=pathLeaf(head);return name.length>0?name:"?"},seen=new Map,out=new Map;for(let leaf of leafList){if(leaf.title){out.set(leaf.id,leaf.title);continue}let name=leaf.content===null?engineTitle||liveTitles?.get(leaf.id)||basename(leaf.content):liveTitles?.get(leaf.id)||SHELL_LEAF_NAME,n=(seen.get(name)??0)+1;seen.set(name,n),out.set(leaf.id,n===1?name:`${name} ${n}`)}return out}function meaningfulAutoTitle(autoTitle){let trimmed=(autoTitle??"").trim();if(trimmed.length<3)return null;if(/^[\d\s\p{P}\p{S}]+$/u.test(trimmed))return null;return trimmed}function stableRecordedTitle(raw,vendor){let recorded=raw?.trim();if(!recorded)return null;let cleaned=stripEngineStatusPrefix(recorded,vendor);if(cleaned===recorded&&isEngineDecoration(recorded,vendor))return null;if(isEnginePlaceholderTitle(cleaned,vendor))return null;return cleaned||null}function isEngineDecoration(text,vendor){let glyphs=new Set(engineStatusPrefixes(vendor));return[...text].every((ch)=>ch.trim().length===0||glyphs.has(ch))}function tabTitleStable(tab,taskVendor,liveVendor,liveTitle){if(liveVendor===null&&tab.kind==="engine")return tabTitle({...tab,kind:"command",lastTitle:null},taskVendor);let vendor=liveVendor??tab.liveVendor??(tab.kind==="engine"?tab.vendor??taskVendor:void 0)??void 0,source=liveTitle?.trim()||tab.lastTitle,named=vendor?stableRecordedTitle(source,vendor):source??null;if(!vendor||engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return tabTitle({...tab,lastTitle:named},taskVendor);return tabTitle({...tab,kind:"engine",vendor,lastTitle:named},taskVendor)}function titleVendor(tab,taskVendor){return tab.liveVendor??(tab.kind==="engine"?tab.vendor:void 0)??taskVendor}function tabTitle(tab,taskVendor,liveName){if(tab.title)return tab.title;let ls=tab.splitTree?leaves(tab.splitTree.root):[];if(ls.length>1)return t("terminal.tab.groupTitle",{n:tab.ordinal});let sole=ls.length===1?ls[0]:void 0;if(sole&&sole.id!=="leaf-1")return sole.title??`${liveName??SHELL_LEAF_NAME} ${tab.ordinal}`;let vendor=titleVendor(tab,taskVendor);if(liveName&&!isEnginePlaceholderTitle(liveName,vendor))return`${liveName} ${tab.ordinal}`;if(tab.lastTitle&&!isEnginePlaceholderTitle(tab.lastTitle,vendor))return`${tab.lastTitle} ${tab.ordinal}`;let auto=meaningfulAutoTitle(tab.autoTitle);if(auto)return auto;return`${tab.kind==="engine"?engineEntry(tab.vendor??taskVendor).defaultCommand[0]??SHELL_LEAF_NAME:SHELL_LEAF_NAME} ${tab.ordinal}`}function visibleNativeStatus(tab,taskVendor,vendor,liveName){if(!vendor||!liveName)return!1;if(engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return!1;return tabTitle(tab,taskVendor,liveName)===`${liveName} ${tab.ordinal}`}function initialTabs(){return{tabs:[{kind:"engine",id:"tab-1",title:null,ordinal:1}],activeId:"tab-1",nextOrdinal:2}}function reopenHintFor(closed){if(closed?.kind==="command")return{kind:"command"};if(closed?.kind==="engine"&&closed.vendor)return{kind:"engine",vendor:closed.vendor};return{kind:"engine"}}function reopenTabs(state,shell){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,next=state.nextOrdinal+1;if(state.reopenAs?.kind==="command")return{tabs:[{kind:"command",id,title:null,ordinal,command:[shell]}],activeId:id,nextOrdinal:next};let vendor=state.reopenAs?.kind==="engine"?state.reopenAs.vendor:void 0;return{tabs:[{kind:"engine",id,title:null,ordinal,...vendor?{vendor}:{}}],activeId:id,nextOrdinal:next}}function initialShellTabs(shell){return{tabs:[{kind:"command",id:"tab-1",title:null,ordinal:1,command:[shell]}],activeId:"tab-1",nextOrdinal:2}}function rehydrateTabs(persisted,shell,opts={}){let tabs=persisted.tabs.map((t2)=>t2.kind==="command"?{...t2,command:shell,purpose:void 0}:t2);if(tabs.length===0)return opts.allowEmpty?persisted:initialTabs();let activeId=tabs.some((t2)=>t2.id===persisted.activeId)?persisted.activeId:tabs[0].id,maxOrdinal=tabs.reduce((max,t2)=>Math.max(max,t2.ordinal),0);return{tabs,activeId,nextOrdinal:Math.max(persisted.nextOrdinal,maxOrdinal+1)}}function recycleTabs(state,prev){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,pinned=prev.kind==="engine"?prev:void 0;return{tabs:[{kind:"engine",id,ordinal,title:prev.title,autoTitle:prev.autoTitle,...pinned?.vendor?{vendor:pinned.vendor}:{},...pinned?.engineCommand?{engineCommand:pinned.engineCommand}:{}}],activeId:id,nextOrdinal:ordinal+1}}function engineTabArgv(tab,base,live,fallbackVendor){if(tab.forkFrom&&!tab.spawned&&!live){let forked=tab.vendor?engineForkArgv(base,tab.vendor,tab.forkFrom,tab.sessionId??null):null;if(forked)return forked}if(!tab.sessionId)return base;let vendor=tab.vendor??fallbackVendor;if(tab.spawned&&!live)return engineResumeArgv(base,vendor,tab.sessionId)??base;return withPinnedSessionId(base,vendor,()=>tab.sessionId).argv}function engineTabSpawnFor(state,tab,base,opts){let{live,shell,prompt}=opts,firstEngine=state.tabs.find((t2)=>t2.kind==="engine"),fresh=!tab.spawned&&!live,tabPrompt=fresh?tab.initialPrompt?.trim():void 0,wantsPrompt=!!prompt&&tab.id===firstEngine?.id&&fresh,isFreshFirstEngine=tab.id===firstEngine?.id&&fresh,promptIntent=tabPrompt?{kind:"explicit",prompt:tabPrompt}:wantsPrompt?{kind:"new-task",prompt}:isFreshFirstEngine?{kind:"repo-init"}:{kind:"none"},ref=tab.ptyTask;trustEngineWorktree(tab.vendor??opts.task.vendor,ref?.worktree??opts.worktreePath);let launch=buildEngineSessionLaunch({task:ref?{...opts.task,id:ref.id,kind:"task"}:opts.task,worktreePath:ref?.worktree??opts.worktreePath,shell,argv:engineTabArgv(tab,base,live,opts.task.vendor),promptIntent,protocolGates:opts.protocolGates,tabId:ref?"tab-1":tab.id});return{command:launch.command,...launch.firstMessage?{firstMessage:launch.firstMessage,engineBin:base[0]}:{}}}function tabExitAction(tab,deadOnAttach,resumeTried){if(tab.kind==="engine"&&deadOnAttach&&!!tab.sessionId&&tab.spawned&&!resumeTried)return"resume";return"close"}var SHELL_SAFE_ARG=/^[A-Za-z0-9@%+=:,./_-]+$/;function shellCommandLine(argv){return argv.map((a)=>SHELL_SAFE_ARG.test(a)?a:`'${a.replaceAll("'","'\\''")}'`).join(" ")}function shellIdentityInput(taskId,tabId){let task=shellCommandLine([taskId]),tab=shellCommandLine([tabId]);return` export ROVE_TASK_ID=${task} KOBE_TASK_ID=${task} ROVE_TAB_ID=${tab} KOBE_TAB_ID=${tab} && clear\r`}function insertAfterActive(state,tab){let i=state.tabs.findIndex((t2)=>t2.id===state.activeId);return{tabs:[...state.tabs.slice(0,i+1),tab,...state.tabs.slice(i+1)],activeId:tab.id,nextOrdinal:state.nextOrdinal+1}}function addTab(state,vendor){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"engine",id:`tab-${ordinal}`,title:null,ordinal,vendor})}function openCommandTab(state,command,label){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command})}function findEditorTab(state){return state.tabs.find((tab)=>tab.kind==="command"&&tab.purpose==="editor")}function openEditorTab(state,command,label){let existing=findEditorTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command,purpose:"editor"})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,command,splitTree:null}:tab);return{...state,tabs,activeId:existing.id}}function findContentTab(state){return state.tabs.find((tab)=>tab.kind==="content")}function openContentTab(state,relPath,label,base){let existing=findContentTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"content",id:`tab-${ordinal}`,title:label,ordinal,relPath,base})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,relPath,base}:tab);return{...state,tabs,activeId:existing.id}}function closeTab(state,id,opts={}){if(state.tabs.length<=1&&!opts.allowEmpty)return{state,closedId:null};let i=state.tabs.findIndex((t2)=>t2.id===id);if(i<0)return{state,closedId:null};let tabs=state.tabs.filter((t2)=>t2.id!==id);if(state.activeId!==id)return{state:{...state,tabs},closedId:id};if(tabs.length===0)return{state:{...state,tabs,activeId:id,reopenAs:reopenHintFor(state.tabs[i])},closedId:id};let next=tabs[Math.max(0,i-1)];return{state:{...state,tabs,activeId:(next??tabs[0]).id},closedId:id}}function closeActiveTab(state){return closeTab(state,state.activeId)}function renameActiveTab(state,title){return setTabTitle(state,state.activeId,title)}function setTabTitle(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.title??null)===next)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,title:next}:t2);return{...state,tabs}}function setTabSessionId(state,id,sessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,sessionId}:t2);return{...state,tabs}}function setTabForkFrom(state,id,sourceSessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,forkFrom:sourceSessionId}:t2);return{...state,tabs}}function setTabEngineCommand(state,id,command){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,engineCommand:command}:t2);return{...state,tabs}}function setTabInitialPrompt(state,id,prompt){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,initialPrompt:prompt}:t2);return{...state,tabs}}function setTabLastTitle(state,id,lastTitle){if(lastTitle.length===0)return state;let current=state.tabs.find((t2)=>t2.id===id);if(!current||current.lastTitle===lastTitle)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,lastTitle}:t2);return{...state,tabs}}function setTabLiveVendor(state,id,liveVendor){let current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.liveVendor??null)===liveVendor)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,liveVendor}:t2);return{...state,tabs}}function setTabAutoTitle(state,id,autoTitle){let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,autoTitle}:t2);return{...state,tabs}}function setTabSpawned(state,id,spawned){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"&&!t2.spawned!==!spawned?{...t2,spawned}:t2);return{...state,tabs}}function cycleTab(state,delta){let n=state.tabs.length;if(n<=1)return state;let i=state.tabs.findIndex((t2)=>t2.id===state.activeId),next=state.tabs[(i+delta+n)%n];return{...state,activeId:next.id}}function moveTab(state,id,delta){let i=state.tabs.findIndex((t2)=>t2.id===id),j=i+delta;if(i<0||j<0||j>=state.tabs.length)return state;let tabs=[...state.tabs],a=tabs[i];return tabs[i]=tabs[j],tabs[j]=a,{...state,tabs}}function selectTab(state,id){if(state.activeId===id||!state.tabs.some((t2)=>t2.id===id))return state;return{...state,activeId:id}}function setTabSplit(state,id,tree){if(!state.tabs.some((t2)=>t2.id===id))return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,splitTree:tree}:t2);return{...state,tabs}}function tabPtyKey(taskId,tabId){return`${taskId}::${tabId}`}function tabPtyKeyFor(taskId,tab){if(tab.kind==="engine"&&tab.ptyTask)return tabPtyKey(tab.ptyTask.id,"tab-1");return tabPtyKey(taskId,tab.id)}function tabCwdFor(tab,taskWorktree){if(tab.kind==="engine"&&tab.ptyTask)return tab.ptyTask.worktree;return taskWorktree}function terminalTabsKey(taskId){return`terminalTabs.${taskId}`}function forgetTaskTabsSnapshot(kv,taskId){let key=terminalTabsKey(taskId);if(kv.store[key]===void 0)return;kv.set(key,void 0)}function sweepOrphanTabsSnapshots(kv,liveTaskIds){let live=new Set(liveTaskIds),swept=0;for(let key of Object.keys(kv.store)){if(!key.startsWith("terminalTabs."))continue;let taskId=key.slice(13);if(live.has(taskId))continue;kv.set(key,void 0),swept++}return swept}
|
|
2
|
+
import{buildEngineSessionLaunch,trustEngineWorktree}from"./chunk-d8hcpwr6.js";import{engineForkArgv,engineResumeArgv,withPinnedSessionId}from"./chunk-yrmj16b9.js";import{t}from"./chunk-bwrb6c2h.js";import{tildify}from"./chunk-fczqwtmq.js";import{engineEntry,engineStatusPrefixes,isEnginePlaceholderTitle,stripEngineStatusPrefix}from"./chunk-71k66b8f.js";import{pathSyntax}from"./chunk-f10n6063.js";import*as fs from"fs";import*as os from"os";function pathLeaf(p){return p.slice(lastSeparator(p)+1)}function lastSeparator(p){return pathSyntax(p).sep==="\\"||process.platform==="win32"&&!p.startsWith("/")?Math.max(p.lastIndexOf("/"),p.lastIndexOf("\\")):p.lastIndexOf("/")}function expandHome(p){if(p==="~")return os.homedir();if(p.startsWith("~/")||process.platform==="win32"&&p.startsWith("~\\"))return os.homedir()+p.slice(1);return p}function stripTrailingSlash(p){let root=pathSyntax(p).parse(p).root,end=p.length;while(end>root.length&&lastSeparator(p.slice(0,end))===end-1)end--;return p.slice(0,end)}function splitPathForDirSuggest(value){if(!value)return{base:"",filter:""};let expanded=expandHome(value==="~"?"~/":value),lastSlash=lastSeparator(expanded);if(lastSlash===-1)return{base:"",filter:expanded};return{base:expanded.slice(0,lastSlash+1),filter:expanded.slice(lastSlash+1)}}function listSubdirs(base){if(!base)return[];try{let entries=fs.readdirSync(base,{withFileTypes:!0}),out=[];for(let e of entries)if(e.isDirectory())out.push(e.name);return out.sort((a,b)=>a.localeCompare(b))}catch{return[]}}function filterSubdirs(all,filter){let f=filter.toLowerCase(),visible=f.startsWith(".")?all:all.filter((n)=>!n.startsWith("."));if(!f)return visible;return visible.filter((n)=>n.toLowerCase().startsWith(f))}function joinDrill(typedValue,baseExpanded,name){let out=`${baseExpanded+name}/`;if(typedValue.startsWith("~")){let short=tildify(out);if(short.startsWith("~"))return short==="~"?"~/":`${short}/`}return out}function joinPicked(typedValue,baseExpanded,name){let out=baseExpanded+name;if(typedValue.startsWith("~"))return tildify(out);return out}function depth(node){return node.kind==="leaf"?0:1+Math.max(...node.children.map(depth))}function siblingCount(root,id,orientation){let find=(node)=>{if(node.kind==="leaf")return null;if(node.orientation===orientation&&node.children.some((c)=>c.kind==="leaf"&&c.id===id))return node.children.length;for(let child of node.children){let n=find(child);if(n!==null)return n}return null};return find(root)??1}function splitFits(state,orientation,activeSize){let extent=orientation==="row"?activeSize.cols:activeSize.rows,min=orientation==="row"?20:6,n=siblingCount(state.root,state.activeLeafId,orientation);return Math.floor(extent*n/(n+1))-1>=min}function initialSplit(content){return{root:{kind:"leaf",id:"leaf-1",content},activeLeafId:"leaf-1",nextOrdinal:2}}function leaves(node){return node.kind==="leaf"?[node]:node.children.flatMap(leaves)}function splitActive(state,orientation,content,activeSize){if(activeSize&&!splitFits(state,orientation,activeSize))return state;let leaf={kind:"leaf",id:`leaf-${state.nextOrdinal}`,content},insert=(node)=>{if(node.kind==="leaf"){if(node.id!==state.activeLeafId)return node;return{kind:"group",orientation,children:[node,leaf]}}if(node.orientation===orientation){let i=node.children.findIndex((c)=>c.kind==="leaf"&&c.id===state.activeLeafId);if(i>=0){let children=[...node.children.slice(0,i+1),leaf,...node.children.slice(i+1)];return{...node,children}}}return{...node,children:node.children.map(insert)}},root=insert(state.root);if(!activeSize&&depth(root)>4)return state;return{root,activeLeafId:leaf.id,nextOrdinal:state.nextOrdinal+1}}function removeLeaf(state,id){let all=leaves(state.root);if(all.length<=1)return null;let prune=(node)=>{if(node.kind==="leaf")return node.id===id?null:node;let children=node.children.map(prune).filter((c)=>c!==null);if(children.length===0)return null;if(children.length===1)return children[0];return{...node,children}},root=prune(state.root);if(root===null)return null;if(leaves(root).length===all.length)return state;let order=all.map((l)=>l.id),removedIdx=order.indexOf(id),fallback=order[removedIdx>0?removedIdx-1:removedIdx+1],activeLeafId=state.activeLeafId===id?fallback:state.activeLeafId;return{...state,root,activeLeafId}}function renameLeaf(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,walk=(node)=>node.kind==="leaf"?node.id===id?{...node,title:next}:node:{...node,children:node.children.map(walk)};if(!leaves(state.root).some((l)=>l.id===id))return state;return{...state,root:walk(state.root)}}function cycleLeaf(state,delta){let order=leaves(state.root).map((l)=>l.id);if(order.length<=1)return state;let i=order.indexOf(state.activeLeafId),next=order[(i+delta+order.length)%order.length];return{...state,activeLeafId:next}}function hasEngineLeaf(tree){return!tree||leaves(tree.root).some((l)=>l.id==="leaf-1")}function isTabSplit(tree){return tree?leaves(tree.root).length>1:!1}function collapseSplit(next){let ls=leaves(next.root);return ls.length===1&&ls[0]?.id==="leaf-1"?null:next}function splitLeafPtyKey(tabKey,leafId){return leafId==="leaf-1"?tabKey:`${tabKey}::${leafId}`}var SHELL_LEAF_NAME="shell";function splitLeafNames(leafList,tabCommand,engineTitle,liveTitles){let basename=(argv)=>{let head=(argv??tabCommand)[0]??"",name=pathLeaf(head);return name.length>0?name:"?"},seen=new Map,out=new Map;for(let leaf of leafList){if(leaf.title){out.set(leaf.id,leaf.title);continue}let name=leaf.content===null?engineTitle||liveTitles?.get(leaf.id)||basename(leaf.content):liveTitles?.get(leaf.id)||SHELL_LEAF_NAME,n=(seen.get(name)??0)+1;seen.set(name,n),out.set(leaf.id,n===1?name:`${name} ${n}`)}return out}function meaningfulAutoTitle(autoTitle){let trimmed=(autoTitle??"").trim();if(trimmed.length<3)return null;if(/^[\d\s\p{P}\p{S}]+$/u.test(trimmed))return null;return trimmed}function stableRecordedTitle(raw,vendor){let recorded=raw?.trim();if(!recorded)return null;let cleaned=stripEngineStatusPrefix(recorded,vendor);if(cleaned===recorded&&isEngineDecoration(recorded,vendor))return null;if(isEnginePlaceholderTitle(cleaned,vendor))return null;return cleaned||null}function isEngineDecoration(text,vendor){let glyphs=new Set(engineStatusPrefixes(vendor));return[...text].every((ch)=>ch.trim().length===0||glyphs.has(ch))}function tabTitleStable(tab,taskVendor,liveVendor,liveTitle){if(liveVendor===null&&tab.kind==="engine")return tabTitle({...tab,kind:"command",lastTitle:null},taskVendor);let vendor=liveVendor??tab.liveVendor??(tab.kind==="engine"?tab.vendor??taskVendor:void 0)??void 0,source=liveTitle?.trim()||tab.lastTitle,named=vendor?stableRecordedTitle(source,vendor):source??null;if(!vendor||engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return tabTitle({...tab,lastTitle:named},taskVendor);return tabTitle({...tab,kind:"engine",vendor,lastTitle:named},taskVendor)}function titleVendor(tab,taskVendor){return tab.liveVendor??(tab.kind==="engine"?tab.vendor:void 0)??taskVendor}function tabTitle(tab,taskVendor,liveName){if(tab.title)return tab.title;let ls=tab.splitTree?leaves(tab.splitTree.root):[];if(ls.length>1)return t("terminal.tab.groupTitle",{n:tab.ordinal});let sole=ls.length===1?ls[0]:void 0;if(sole&&sole.id!=="leaf-1")return sole.title??`${liveName??SHELL_LEAF_NAME} ${tab.ordinal}`;let vendor=titleVendor(tab,taskVendor);if(liveName&&!isEnginePlaceholderTitle(liveName,vendor))return`${liveName} ${tab.ordinal}`;if(tab.lastTitle&&!isEnginePlaceholderTitle(tab.lastTitle,vendor))return`${tab.lastTitle} ${tab.ordinal}`;let auto=meaningfulAutoTitle(tab.autoTitle);if(auto)return auto;return`${tab.kind==="engine"?engineEntry(tab.vendor??taskVendor).defaultCommand[0]??SHELL_LEAF_NAME:SHELL_LEAF_NAME} ${tab.ordinal}`}function visibleNativeStatus(tab,taskVendor,vendor,liveName){if(!vendor||!liveName)return!1;if(engineEntry(vendor).terminalTitle?.ownsStatus!==!0)return!1;return tabTitle(tab,taskVendor,liveName)===`${liveName} ${tab.ordinal}`}function initialTabs(){return{tabs:[{kind:"engine",id:"tab-1",title:null,ordinal:1}],activeId:"tab-1",nextOrdinal:2}}function reopenHintFor(closed){if(closed?.kind==="command")return{kind:"command"};if(closed?.kind==="engine"&&closed.vendor)return{kind:"engine",vendor:closed.vendor};return{kind:"engine"}}function reopenTabs(state,shell){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,next=state.nextOrdinal+1;if(state.reopenAs?.kind==="command")return{tabs:[{kind:"command",id,title:null,ordinal,command:[shell]}],activeId:id,nextOrdinal:next};let vendor=state.reopenAs?.kind==="engine"?state.reopenAs.vendor:void 0;return{tabs:[{kind:"engine",id,title:null,ordinal,...vendor?{vendor}:{}}],activeId:id,nextOrdinal:next}}function initialShellTabs(shell){return{tabs:[{kind:"command",id:"tab-1",title:null,ordinal:1,command:[shell]}],activeId:"tab-1",nextOrdinal:2}}function rehydrateTabs(persisted,shell,opts={}){let tabs=persisted.tabs.map((t2)=>t2.kind==="command"?{...t2,command:shell,purpose:void 0}:t2);if(tabs.length===0)return opts.allowEmpty?persisted:initialTabs();let activeId=tabs.some((t2)=>t2.id===persisted.activeId)?persisted.activeId:tabs[0].id,maxOrdinal=tabs.reduce((max,t2)=>Math.max(max,t2.ordinal),0);return{tabs,activeId,nextOrdinal:Math.max(persisted.nextOrdinal,maxOrdinal+1)}}function recycleTabs(state,prev){let ordinal=state.nextOrdinal,id=`tab-${ordinal}`,pinned=prev.kind==="engine"?prev:void 0;return{tabs:[{kind:"engine",id,ordinal,title:prev.title,autoTitle:prev.autoTitle,...pinned?.vendor?{vendor:pinned.vendor}:{},...pinned?.engineCommand?{engineCommand:pinned.engineCommand}:{}}],activeId:id,nextOrdinal:ordinal+1}}function engineTabArgv(tab,base,live,fallbackVendor){if(tab.forkFrom&&!tab.spawned&&!live){let forked=tab.vendor?engineForkArgv(base,tab.vendor,tab.forkFrom,tab.sessionId??null):null;if(forked)return forked}if(!tab.sessionId)return base;let vendor=tab.vendor??fallbackVendor;if(tab.spawned&&!live)return engineResumeArgv(base,vendor,tab.sessionId)??base;return withPinnedSessionId(base,vendor,()=>tab.sessionId).argv}function engineTabSpawnFor(state,tab,base,opts){let{live,shell,prompt}=opts,firstEngine=state.tabs.find((t2)=>t2.kind==="engine"),fresh=!tab.spawned&&!live,tabPrompt=fresh?tab.initialPrompt?.trim():void 0,wantsPrompt=!!prompt&&tab.id===firstEngine?.id&&fresh,isFreshFirstEngine=tab.id===firstEngine?.id&&fresh,promptIntent=tabPrompt?{kind:"explicit",prompt:tabPrompt}:wantsPrompt?{kind:"new-task",prompt}:isFreshFirstEngine?{kind:"repo-init"}:{kind:"none"},ref=tab.ptyTask;trustEngineWorktree(tab.vendor??opts.task.vendor,ref?.worktree??opts.worktreePath);let launch=buildEngineSessionLaunch({task:ref?{...opts.task,id:ref.id,kind:"task"}:opts.task,worktreePath:ref?.worktree??opts.worktreePath,shell,argv:engineTabArgv(tab,base,live,opts.task.vendor),promptIntent,protocolGates:opts.protocolGates,tabId:ref?"tab-1":tab.id});return{command:launch.command,...launch.firstMessage?{firstMessage:launch.firstMessage,engineBin:base[0]}:{}}}function tabExitAction(tab,deadOnAttach,resumeTried){if(tab.kind==="engine"&&deadOnAttach&&!!tab.sessionId&&tab.spawned&&!resumeTried)return"resume";return"close"}var SHELL_SAFE_ARG=/^[A-Za-z0-9@%+=:,./_-]+$/;function shellCommandLine(argv){return argv.map((a)=>SHELL_SAFE_ARG.test(a)?a:`'${a.replaceAll("'","'\\''")}'`).join(" ")}function shellIdentityInput(taskId,tabId){let task=shellCommandLine([taskId]),tab=shellCommandLine([tabId]);return` export ROVE_TASK_ID=${task} KOBE_TASK_ID=${task} ROVE_TAB_ID=${tab} KOBE_TAB_ID=${tab} && clear\r`}function insertAfterActive(state,tab){let i=state.tabs.findIndex((t2)=>t2.id===state.activeId);return{tabs:[...state.tabs.slice(0,i+1),tab,...state.tabs.slice(i+1)],activeId:tab.id,nextOrdinal:state.nextOrdinal+1}}function addTab(state,vendor){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"engine",id:`tab-${ordinal}`,title:null,ordinal,vendor})}function openCommandTab(state,command,label){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command})}function findEditorTab(state){return state.tabs.find((tab)=>tab.kind==="command"&&tab.purpose==="editor")}function openEditorTab(state,command,label){let existing=findEditorTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"command",id:`tab-${ordinal}`,title:label,ordinal,command,purpose:"editor"})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,command,splitTree:null}:tab);return{...state,tabs,activeId:existing.id}}function findContentTab(state){return state.tabs.find((tab)=>tab.kind==="content")}function openContentTab(state,relPath,label,base){let existing=findContentTab(state);if(!existing){let ordinal=state.nextOrdinal;return insertAfterActive(state,{kind:"content",id:`tab-${ordinal}`,title:label,ordinal,relPath,base})}let tabs=state.tabs.map((tab)=>tab.id===existing.id?{...existing,title:label,relPath,base}:tab);return{...state,tabs,activeId:existing.id}}function closeTab(state,id,opts={}){if(state.tabs.length<=1&&!opts.allowEmpty)return{state,closedId:null};let i=state.tabs.findIndex((t2)=>t2.id===id);if(i<0)return{state,closedId:null};let tabs=state.tabs.filter((t2)=>t2.id!==id);if(state.activeId!==id)return{state:{...state,tabs},closedId:id};if(tabs.length===0)return{state:{...state,tabs,activeId:id,reopenAs:reopenHintFor(state.tabs[i])},closedId:id};let next=tabs[Math.max(0,i-1)];return{state:{...state,tabs,activeId:(next??tabs[0]).id},closedId:id}}function closeActiveTab(state){return closeTab(state,state.activeId)}function renameActiveTab(state,title){return setTabTitle(state,state.activeId,title)}function setTabTitle(state,id,title){let trimmed=title.trim(),next=trimmed.length>0?trimmed:null,current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.title??null)===next)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,title:next}:t2);return{...state,tabs}}function setTabSessionId(state,id,sessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,sessionId}:t2);return{...state,tabs}}function setTabForkFrom(state,id,sourceSessionId){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,forkFrom:sourceSessionId}:t2);return{...state,tabs}}function setTabEngineCommand(state,id,command){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,engineCommand:command}:t2);return{...state,tabs}}function setTabInitialPrompt(state,id,prompt){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"?{...t2,initialPrompt:prompt}:t2);return{...state,tabs}}function setTabLastTitle(state,id,lastTitle){if(lastTitle.length===0)return state;let current=state.tabs.find((t2)=>t2.id===id);if(!current||current.lastTitle===lastTitle)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,lastTitle}:t2);return{...state,tabs}}function setTabLiveVendor(state,id,liveVendor){let current=state.tabs.find((t2)=>t2.id===id);if(!current||(current.liveVendor??null)===liveVendor)return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,liveVendor}:t2);return{...state,tabs}}function setTabAutoTitle(state,id,autoTitle){let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,autoTitle}:t2);return{...state,tabs}}function setTabSpawned(state,id,spawned){let tabs=state.tabs.map((t2)=>t2.id===id&&t2.kind==="engine"&&!t2.spawned!==!spawned?{...t2,spawned}:t2);return{...state,tabs}}function cycleTab(state,delta){let n=state.tabs.length;if(n<=1)return state;let i=state.tabs.findIndex((t2)=>t2.id===state.activeId),next=state.tabs[(i+delta+n)%n];return{...state,activeId:next.id}}function moveTab(state,id,delta){let i=state.tabs.findIndex((t2)=>t2.id===id),j=i+delta;if(i<0||j<0||j>=state.tabs.length)return state;let tabs=[...state.tabs],a=tabs[i];return tabs[i]=tabs[j],tabs[j]=a,{...state,tabs}}function selectTab(state,id){if(state.activeId===id||!state.tabs.some((t2)=>t2.id===id))return state;return{...state,activeId:id}}function setTabSplit(state,id,tree){if(!state.tabs.some((t2)=>t2.id===id))return state;let tabs=state.tabs.map((t2)=>t2.id===id?{...t2,splitTree:tree}:t2);return{...state,tabs}}function tabPtyKey(taskId,tabId){return`${taskId}::${tabId}`}function tabPtyKeyFor(taskId,tab){if(tab.kind==="engine"&&tab.ptyTask)return tabPtyKey(tab.ptyTask.id,"tab-1");return tabPtyKey(taskId,tab.id)}function tabCwdFor(tab,taskWorktree){if(tab.kind==="engine"&&tab.ptyTask)return tab.ptyTask.worktree;return taskWorktree}function terminalTabsKey(taskId){return`terminalTabs.${taskId}`}function forgetTaskTabsSnapshot(kv,taskId){let key=terminalTabsKey(taskId);if(kv.store[key]===void 0)return;kv.set(key,void 0)}function sweepOrphanTabsSnapshots(kv,liveTaskIds){let live=new Set(liveTaskIds),swept=0;for(let key of Object.keys(kv.store)){if(!key.startsWith("terminalTabs."))continue;let taskId=key.slice(13);if(live.has(taskId))continue;kv.set(key,void 0),swept++}return swept}
|
|
3
3
|
export{pathLeaf,expandHome,stripTrailingSlash,splitPathForDirSuggest,listSubdirs,filterSubdirs,joinDrill,joinPicked,initialSplit,leaves,splitActive,removeLeaf,renameLeaf,cycleLeaf,hasEngineLeaf,isTabSplit,collapseSplit,splitLeafPtyKey,splitLeafNames,tabTitleStable,tabTitle,visibleNativeStatus,initialTabs,reopenTabs,initialShellTabs,rehydrateTabs,recycleTabs,engineTabArgv,engineTabSpawnFor,tabExitAction,shellIdentityInput,addTab,openCommandTab,findEditorTab,openEditorTab,openContentTab,closeTab,closeActiveTab,renameActiveTab,setTabTitle,setTabSessionId,setTabForkFrom,setTabEngineCommand,setTabInitialPrompt,setTabLastTitle,setTabLiveVendor,setTabAutoTitle,setTabSpawned,cycleTab,moveTab,selectTab,setTabSplit,tabPtyKey,tabPtyKeyFor,tabCwdFor,terminalTabsKey,forgetTaskTabsSnapshot,sweepOrphanTabsSnapshots};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{isEngineActivityKind}from"./chunk-3e5n28t6.js";import{loadPluginRegistry,readPluginManifest}from"./chunk-g2e1dmxh.js";import{flagValue}from"./chunk-jvxh93nz.js";import{connectIfRunning}from"./chunk-te8g5azg.js";import{createEngineHookAdapter}from"./chunk-
|
|
2
|
+
import{isEngineActivityKind}from"./chunk-3e5n28t6.js";import{loadPluginRegistry,readPluginManifest}from"./chunk-g2e1dmxh.js";import{flagValue}from"./chunk-jvxh93nz.js";import{connectIfRunning}from"./chunk-te8g5azg.js";import{createEngineHookAdapter}from"./chunk-71k66b8f.js";import{getPersistedString,setPersistedString}from"./chunk-ejqs2ta9.js";import{ALL_VENDORS}from"./chunk-bq3fyc0p.js";import{activeCliName}from"./chunk-00ehck55.js";import{readRoveEnv}from"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{join,resolve}from"path";var STDIN_READ_TIMEOUT_MS=500;async function readTextWithTimeout(read,timeoutMs=STDIN_READ_TIMEOUT_MS){let raceTimer;try{return await Promise.race([read(),new Promise((resolve2)=>{raceTimer=setTimeout(()=>resolve2(""),timeoutMs)})])}finally{if(raceTimer!==void 0)clearTimeout(raceTimer)}}async function readStdinPayload(){try{let text=await readTextWithTimeout(()=>Bun.stdin.text());if(!text.trim())return{};let parsed=JSON.parse(text);return parsed&&typeof parsed==="object"&&!Array.isArray(parsed)?parsed:{}}catch{return{}}}async function runHookSubcommand(argv){let[verb,...rest]=argv;if(verb==="setup"){await runHookSetup(rest);return}if(verb==="cleanup"){await runHookCleanup();return}try{if(!verb||!isEngineActivityKind(verb))return;let payload=await readStdinPayload(),taskId=flagValue(rest,"--task-id"),cwd=typeof payload.cwd==="string"&&payload.cwd?payload.cwd:process.cwd(),envTaskId=process.env.KOBE_TASK_ID,envTabId=process.env.KOBE_TAB_ID,engine=flagValue(rest,"--engine"),adapters=activityHookAdapters().filter((a)=>!engine||a.vendor===engine),detail;for(let adapter of adapters)if(detail=adapter.activityDetailFromPayload(verb,payload),detail)break;let session;for(let adapter of adapters)if(session=adapter.sessionFromPayload(payload),session)break;let client=await connectIfRunning();if(!client)return;try{let effectiveTaskId=taskId??envTaskId;await client.request("engine.reportEvent",{...effectiveTaskId?{taskId:effectiveTaskId}:{cwd},kind:verb,...engine?{engine}:{},...envTabId?{tabId:envTabId}:{},...detail?{detail}:{},...session?{sessionId:session.sessionId}:{},...session?.transcriptPath?{transcriptPath:session.transcriptPath}:{}})}finally{client.close()}}catch(err){if(readRoveEnv("HOOK_DEBUG"))console.error(`[rove hook] ${verb} failed:`,err instanceof Error?err.message:String(err))}}var SYNC_SETTING_KEY="externalWorktreeSync";function worktreeSyncAdapters(){return ALL_VENDORS.map((v)=>createEngineHookAdapter(v)).filter((a)=>a.supportsWorktreeSync())}function activityHookAdapters(){return ALL_VENDORS.map((v)=>createEngineHookAdapter(v)).filter((a)=>a.supportsHooks())}function globalSettingsPath(){return worktreeSyncAdapters()[0]?.globalSettingsPath()}function persistedSyncPath(stored){if(!stored||stored==="off")return;if(stored==="global")return globalSettingsPath();if(stored.startsWith("repo:"))return join(resolve(stored.slice(5)),".claude","settings.json");return stored}async function ensureGlobalKobeHooks(){try{let{isRovePluginEnabled,detectLegacyInstalls,migrationHint}=await import("./chunk-6tt33a84.js"),pluginMode=isRovePluginEnabled();if(pluginMode){let hint=migrationHint(detectLegacyInstalls(),activeCliName());if(hint)process.stderr.write(`
|
|
3
3
|
${hint}
|
|
4
4
|
`)}let toolEvents=pluginsWantToolEvents();for(let a of activityHookAdapters()){if(pluginMode&&a.vendor==="claude")continue;let enginePath=a.globalSettingsPath();if(!enginePath)continue;await a.installActivityHooks(enginePath,{toolEvents}),await a.removeWorktreeWatchHook(enginePath)}await cleanupWorktreeSyncHook()}catch{}}function pluginsWantToolEvents(){try{for(let entry of loadPluginRegistry().plugins){if(!entry.enabled)continue;try{if(readPluginManifest(entry.root).manifest.events.some((e)=>e.on.startsWith("tool.")))return!0}catch{}}}catch{}return!1}async function cleanupWorktreeSyncHook(){let adapters=worktreeSyncAdapters();if(adapters.length===0)return;let stored=getPersistedString(SYNC_SETTING_KEY),paths=new Set;for(let adapter of adapters){let file=adapter.globalSettingsPath();if(file)paths.add(file)}let prev=persistedSyncPath(stored);if(prev)paths.add(prev);for(let a of adapters)for(let p of paths)await a.removeWorktreeSyncHook(p);if(stored!=="off")setPersistedString(SYNC_SETTING_KEY,"off")}async function runHookCleanup(){let claude=activityHookAdapters().find((a)=>a.vendor==="claude"),path=claude?.globalSettingsPath();if(!claude||!path){process.stdout.write(`rove hook cleanup: no Claude hook adapter \u2014 nothing to do.
|
|
5
5
|
`);return}await claude.removeActivityHooks(path),await claude.removeWorktreeWatchHook(path),process.stdout.write([`rove hook cleanup: removed Rove's settings-managed hooks from ${path}.`,"Only Rove's own entries were touched; your other hooks are intact.","The Claude Code plugin's hooks.json now carries these events (if the plugin","is not installed, the next Rove launch reinstalls the settings-managed set).",""].join(`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{NPX_MISSING_EXIT,bundledSkillDir,kobeSkillPaths,kobeSkillState,npxSkillsCommand,runNpxSkillsInstall}from"./chunk-
|
|
2
|
+
import{NPX_MISSING_EXIT,bundledSkillDir,kobeSkillPaths,kobeSkillState,npxSkillsCommand,runNpxSkillsInstall}from"./chunk-j0jb8kav.js";import{SUBCOMMAND_VERBS}from"./chunk-s76r56rj.js";import"./chunk-ejqs2ta9.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-9prawccj.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-f10n6063.js";import"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{existsSync,readFileSync}from"fs";import{join}from"path";var CLI_NAME=activeCliName(),SKILL_VERBS=SUBCOMMAND_VERBS.skill;function skillUsage(){return[`usage: ${CLI_NAME} skill <verb>`,"","verbs:"," install [--global|-g | --project|-p] [--agent NAME]\u2026 Install the Rove agent skill (wraps `npx skills add`)"," status Show whether the skill is installed"," command [--global|-g | --project|-p] [--agent NAME]\u2026 Print the underlying npx command without running it",` print Print the bundled SKILL.md (also: \`${CLI_NAME} --skill\`)`,"",`The skill teaches a coding agent how to drive \`${CLI_NAME} api\`. Installs are`,"global (user-level) by default; --global/-g says so explicitly, --project/-p","installs into the current project instead. With no --agent, the agent-skills","CLI detects your installed agents and asks; repeat --agent to name them","(e.g. --agent claude-code --agent codex)."].join(`
|
|
3
3
|
`)}function parseInstallFlags(rest){let global=!0,agents=[];for(let i=0;i<rest.length;i++){let arg=rest[i];if(arg==="--project"||arg==="-p")global=!1;else if(arg==="--global"||arg==="-g")global=!0;else if(arg==="--agent"){let v=rest[i+1];if(!v||v.startsWith("--"))process.stderr.write(`${CLI_NAME} skill: --agent requires a value
|
|
4
4
|
`),process.exit(2);agents.push(v),i++}else if(arg.startsWith("--agent="))agents.push(arg.slice(8));else process.stderr.write(`${CLI_NAME} skill: unknown flag "${arg}"
|
|
5
5
|
|
|
@@ -11,7 +11,7 @@ ${skillUsage()}
|
|
|
11
11
|
|
|
12
12
|
${skillUsage()}
|
|
13
13
|
`),process.exit(2);if(verb==="print"){let bundled2=bundledSkillDir(),path=bundled2?join(bundled2,"SKILL.md"):kobeSkillPaths().find((p)=>existsSync(p));if(!path)process.stderr.write(`${CLI_NAME} skill: no SKILL.md found (not bundled, not installed) \u2014 run \`${CLI_NAME} skill install\`
|
|
14
|
-
`),process.exit(1);process.stdout.write(readFileSync(path,"utf8"));return}if(verb==="status"){let{isRovePluginEnabled}=await import("./chunk-
|
|
14
|
+
`),process.exit(1);process.stdout.write(readFileSync(path,"utf8"));return}if(verb==="status"){let{isRovePluginEnabled}=await import("./chunk-6tt33a84.js"),state=kobeSkillState(),paths=kobeSkillPaths(),pluginNote=isRovePluginEnabled()?` note: the Rove Claude Code plugin is enabled \u2014 for Claude Code the skill ships
|
|
15
15
|
inside the plugin and versions with it (staleness prompts are suppressed).
|
|
16
16
|
`:"",head=!state.installed?"\u2717 not installed":state.stale?`\u26A0 out of date (installed ${state.installedVersion===null?"unstamped":`v${state.installedVersion}`}, this Rove wants v${state.currentVersion})`:`\u2713 installed (v${state.installedVersion})`;process.stdout.write([`${CLI_NAME} skill: ${head}`,...state.legacyCopies.map((copy)=>` \u26A0 stale duplicate: ${copy.path}${copy.version===null?"":` (v${copy.version})`} \u2014 remove it; agents load both`),` looked in: ${paths.join(`
|
|
17
17
|
`)}`,state.installed&&!state.stale?"":` \u2192 run \`${CLI_NAME} skill install\` to install / refresh`,""].join(`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-
|
|
2
|
+
import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-mc33ba6j.js";import{readLastActiveTaskId,writeLastActiveTaskId}from"./chunk-2kb4z64z.js";import{GitWorktreeManager,defaultExecDeps,isDirtyOutput,parseDirtyPaths}from"./chunk-2pv5vb5a.js";import{resolvePreferredVendor}from"./chunk-bkm7vxr5.js";import{PLACEHOLDER_TASK_TITLE,isPlaceholderDerivedBranch,sanitizeTaskTitle}from"./chunk-xb9b93ts.js";import{CannotDeleteMainTaskError,DirtyWorktreeError,EmptyBranchDirtyWorktreeError,EmptyBranchError,GitCommandFailedError,IllegalTransitionError,InvalidWorktreeNameError,LandConflictError,MainCheckoutDirtyError,MissingRefError,TaskDeletingError,TaskNotFoundError,WorktreeNameTakenError,WorktreeRemoveFailedError,canonicalize,listWorktreeDirNames}from"./chunk-vhq2dhx2.js";import{READ_ONLY_GIT_ENV}from"./chunk-6xppe9bj.js";import{detectLanguage}from"./chunk-hape5vwj.js";import{createStateCell}from"./chunk-sdyzxayr.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";import{addSavedRepo,getSavedRepos,isGitRepo,removeSavedRepo,resolveRepoRoot}from"./chunk-ejqs2ta9.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{projectRejection,rejectionReason}from"./chunk-81p6mm0p.js";import{pathIdentity,pathWithin,samePath}from"./chunk-f10n6063.js";async function createTaskRow(deps,input){if(!input.repo)throw Error("createTask: repo is required");let repo=(await deps.mainTasks.ensureIfEligible(input.repo,input.projectIntent??"explicit"))?.repo??normalizeMainRepo(input.repo).repo,title=sanitizeTaskTitle(input.title??PLACEHOLDER_TASK_TITLE)||PLACEHOLDER_TASK_TITLE,worktreeName=input.worktreeName?.trim();if(worktreeName)await deps.claimWorktreeName(repo,worktreeName);return await deps.store.create({repo,title,branch:input.branch??"",worktreePath:"",status:"backlog",kind:"task",vendor:input.vendor??DEFAULT_TASK_VENDOR,...input.command?.trim()?{command:input.command.trim()}:{},...input.modelEffort?{modelEffort:input.modelEffort}:{},...input.groupId?{groupId:input.groupId}:{},...input.dispatcher?{dispatcher:input.dispatcher}:{},...input.routine?{routine:input.routine}:{},...input.baseRef?.trim()?{baseRef:input.baseRef.trim()}:{},...worktreeName?{worktreeName}:{}})}async function openDirectoryTaskRow(deps,input){if(!input.dir)throw Error("openDirectoryTask: dir is required");let dir=canonPath(input.dir);return deps.store.create({repo:dir,title:input.scratch?"":`${titleFromRepo(dir)}-${randomDirTaskSuffix()}`,branch:"",worktreePath:dir,status:"backlog",kind:"dir",...input.scratch?{scratch:!0}:{},vendor:input.vendor??resolvePreferredVendor()})}async function adoptScratchRepoRow(deps,id,repo){let task=deps.store.get(id);if(!task||task.kind!=="dir"||task.scratch!==!0)return;let dir=canonPath(repo);await deps.store.update(id,{repo:dir,worktreePath:dir,scratch:!1,title:titleFromRepo(dir)})}function baseRepoCtx(repo,deps){let basePath=deps.remoteBasePath(repo);return{exec:deps.execForRepo(repo),dir:basePath??repo}}async function landGit(exec,dir,args,opts){let r=await exec.run(["git",...args],{cwd:dir,env:opts?.readOnly?READ_ONLY_GIT_ENV:void 0});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}async function isDirty(exec,dir){return isDirtyOutput((await landGit(exec,dir,["status","--porcelain"],{readOnly:!0})).stdout)}async function landPreflight(task,deps=defaultExecDeps){let refuse=(pf,refusal)=>{let refused={...pf,refusal};return{...refused,message:landRefusalError(task,refused).message}},branch=task.branch.trim();if(!branch)throw Error(`landPreflight: task ${task.id} has no branch to land (never materialised)`);let{exec,dir}=baseRepoCtx(task.repo,deps),headOut=await landGit(exec,dir,["symbolic-ref","--short","HEAD"],{readOnly:!0}),landedOn=headOut.stdout.trim();if(headOut.exitCode!==0||!landedOn){let headCommit=await landGit(exec,dir,["rev-parse","--verify","--quiet","HEAD"],{readOnly:!0}),detached=headCommit.exitCode===0&&headCommit.stdout.trim().length>0;return refuse({branch,landedOn:"",baseDir:dir},detached?"DETACHED_HEAD":"UNREADABLE_BASE")}if(landedOn===branch)return refuse({branch,landedOn,baseDir:dir},"SAME_BRANCH");let baseDirty=await isDirty(exec,dir),aheadOut=await landGit(exec,dir,["rev-list","--count",`${landedOn}..${branch}`],{readOnly:!0});if(aheadOut.exitCode!==0){let baseHead=await landGit(exec,dir,["rev-parse","--verify","--quiet","HEAD"],{readOnly:!0});if(baseHead.exitCode!==0||!baseHead.stdout.trim())return refuse({branch,landedOn,baseDirty,baseDir:dir},"UNBORN_BASE");return refuse({branch,landedOn,baseDirty,baseDir:dir},baseDirty?"MAIN_CHECKOUT_DIRTY":"MISSING_REF")}let parsed=Number.parseInt(aheadOut.stdout.trim(),10),base={branch,landedOn,baseDirty,baseDir:dir,...Number.isFinite(parsed)?{ahead:parsed}:{}};if(baseDirty)return refuse(base,"MAIN_CHECKOUT_DIRTY");if(base.ahead!==0)return base;let worktreePath=task.worktreePath.trim();if(worktreePath){let manager=new GitWorktreeManager(deps),dirty=!1;try{dirty=await manager.isDirty(worktreePath)}catch{dirty=!1}if(dirty){let wtExec=deps.execForPath(worktreePath),files=parseDirtyPaths((await landGit(wtExec,worktreePath,["status","--porcelain"],{readOnly:!0})).stdout);return refuse({...base,dirtyFiles:files},"EMPTY_BRANCH_DIRTY_WORKTREE")}}return refuse(base,"EMPTY_BRANCH")}function landRefusalError(task,pf){switch(pf.refusal){case"DETACHED_HEAD":return Error(`landTask: base checkout at ${pf.baseDir} is in detached-HEAD state; check out a branch first`);case"UNREADABLE_BASE":return Error(`landTask: could not read HEAD of the base checkout at ${pf.baseDir} \u2014 is it still a git repo?`);case"UNBORN_BASE":return Error(`landTask: base checkout at ${pf.baseDir} is on '${pf.landedOn}' but has no commits yet, so there is nothing to merge '${pf.branch}' into; make the first commit there (or \`git merge --ff-only ${pf.branch}\`) and land again`);case"SAME_BRANCH":return Error(`landTask: base checkout is already on '${pf.branch}' \u2014 nothing to land onto`);case"MAIN_CHECKOUT_DIRTY":return new MainCheckoutDirtyError(task.repo,pf.baseDir);case"MISSING_REF":return new MissingRefError(pf.branch,pf.landedOn,pf.baseDir);case"EMPTY_BRANCH_DIRTY_WORKTREE":return new EmptyBranchDirtyWorktreeError(pf.branch,pf.landedOn,task.worktreePath.trim(),[...pf.dirtyFiles??[]]);case"EMPTY_BRANCH":return new EmptyBranchError(pf.branch,pf.landedOn)}}async function landTaskWithCleanup(task,opts,deps){if(task.kind==="main")throw Error("landTask: a main task has no branch to land");if(task.kind==="dir")throw Error("landTask: a directory task has no Rove-managed branch to land");let result=await landTask(task,{strategy:opts.strategy}),worktree=opts.removeWorktree===!1?void 0:await removeLandedWorktree(task,opts.callerCwd,deps),branchAnchor=null,branchKept,worktreeGone=!task.worktreePath.trim()||worktree?.removed===!0;if(opts.deleteBranch&&!worktreeGone)branchKept={reason:worktree?.reason??`worktree ${task.worktreePath} was kept, and still has the branch checked out`};else if(opts.deleteBranch){let outcome=await deps.worktrees.deleteBranch(task.repo,result.branch,{force:!0,onAnchor:(record)=>{branchAnchor=record}});if(!outcome.deleted)branchKept={reason:outcome.reason}}return{...result,...worktree?{worktree}:{},...branchAnchor?{branchAnchor}:{},...branchKept?{branchKept}:{}}}async function removeLandedWorktree(task,callerCwd,deps){let worktreePath=task.worktreePath.trim();if(!worktreePath)return{removed:!1,reason:"task has no worktree on disk (never materialised)"};let wt=canonicalize(worktreePath);if(samePath(wt,canonicalize(task.repo)))return{removed:!1,reason:"refusing to remove the base checkout"};if(callerCwd){if(pathWithin(wt,canonicalize(callerCwd))!==null)return{removed:!1,reason:`refusing to remove the caller's own worktree (${worktreePath}) \u2014 re-run from outside it`}}if(deps.tearDownSession)try{await deps.tearDownSession(task.id)}catch{}let residue;try{await deps.worktrees.remove(worktreePath,{onResidue:(r)=>{residue=r}})}catch(err){return{removed:!1,reason:errText(err)}}try{await deps.clearWorktreePath(task.id)}catch(err){return{removed:!0,reason:`worktree removed, but clearing the task's worktree path failed: ${errText(err)}`,...residue?{residue}:{}}}return{removed:!0,...residue?{residue}:{}}}function errText(err){return err instanceof Error?err.message:String(err)}async function conflictedFiles(exec,dir){return(await landGit(exec,dir,["diff","--name-only","--diff-filter=U"],{readOnly:!0})).stdout.split(`
|
|
3
3
|
`).map((l)=>l.trim()).filter((l)=>l.length>0)}async function landTask(task,input={},deps=defaultExecDeps){let strategy=input.strategy??"merge",preflight=await landPreflight(task,deps);if(preflight.refusal)throw landRefusalError(task,{...preflight,refusal:preflight.refusal});let{branch,landedOn}=preflight,{exec,dir}=baseRepoCtx(task.repo,deps);if(strategy==="squash"){if((await landGit(exec,dir,["merge","--squash",branch])).exitCode!==0){let files=await conflictedFiles(exec,dir);throw await landGit(exec,dir,["merge","--abort"]).catch(()=>{}),await landGit(exec,dir,["reset","--hard","HEAD"]).catch(()=>{}),new LandConflictError(task.id,branch,files)}let commit=await landGit(exec,dir,["commit","--no-edit","-m",`Land ${branch} (squash)`]);if(commit.exitCode!==0){if((await landGit(exec,dir,["diff","--cached","--quiet"],{readOnly:!0})).exitCode===0)throw await landGit(exec,dir,["reset","--hard","HEAD"]).catch(()=>{}),Error(`landTask: '${branch}' has nothing to land onto '${landedOn}' (already merged or empty)`);throw new GitCommandFailedError(`commit (squash-landing '${branch}' onto '${landedOn}')`,commit.stderr,"the squashed merge is left STAGED in the base checkout \u2014 fix the cause and `git commit` it, or `git reset --hard HEAD` to discard")}}else{let before=(await landGit(exec,dir,["rev-parse","HEAD"],{readOnly:!0})).stdout.trim(),merge=await landGit(exec,dir,["merge","--no-ff","-m",`Land ${branch}`,branch]);if(merge.exitCode!==0){let files=await conflictedFiles(exec,dir);if(await landGit(exec,dir,["merge","--abort"]).catch(()=>{}),files.length===0)throw new GitCommandFailedError(`merge --no-ff (landing '${branch}' onto '${landedOn}')`,merge.stderr,"the merge was aborted, so the base checkout is unchanged");throw new LandConflictError(task.id,branch,files)}let after=(await landGit(exec,dir,["rev-parse","HEAD"],{readOnly:!0})).stdout.trim();if(before===after)throw Error(`landTask: '${branch}' has nothing to land onto '${landedOn}' (already merged or empty)`)}let shaOut=await landGit(exec,dir,["rev-parse","--short","HEAD"],{readOnly:!0});return{branch,strategy,landedOn,commit:shaOut.stdout.trim()}}class MainTaskCoordinator{store;forgetWorktree;locks=new Map;constructor(store,forgetWorktree){this.store=store;this.forgetWorktree=forgetWorktree}async ensure(repo){let task=await this.ensureIfEligible(repo,"explicit");if(task)return task;let{repo:normalizedRepo}=normalizeMainRepo(repo),rejected=projectRejection(normalizedRepo,isGitRepo,"explicit")??"notGitRepo";throw Error(`cannot add ${normalizedRepo} as a project: ${rejectionReason(rejected)}`)}async ensureIfEligible(repo,intent="derived"){let{repo:normalizedRepo,key}=normalizeMainRepo(repo),onThisRoot=(task)=>normalizeMainRepo(task.repo).key===key,existing=this.store.list().find((task)=>task.kind==="main"&&onThisRoot(task));if(existing)return existing;if(projectRejection(normalizedRepo,isGitRepo,intent))return null;let inflight=this.locks.get(key);if(inflight)return inflight;let promise=(async()=>{addSavedRepo(normalizedRepo,{intent:"explicit"});let adoptable=this.store.list().find((task)=>task.kind==="dir"&&task.scratch!==!0&&onThisRoot(task));if(adoptable)return await this.store.update(adoptable.id,this.mainShape(normalizedRepo));return await this.store.create({...this.mainShape(normalizedRepo),status:"backlog",vendor:resolvePreferredVendor(normalizedRepo)})})();this.locks.set(key,promise);try{return await promise}finally{this.locks.delete(key)}}mainShape(normalizedRepo){return{kind:"main",title:titleFromRepo(normalizedRepo),repo:normalizedRepo,branch:"",worktreePath:repoWorkingDir(normalizedRepo)}}async forget(repo){if(!repo)throw Error("forgetProject: repo is required");let key=normalizeMainRepo(repo).key;for(let saved of getSavedRepos())if(normalizeMainRepo(saved).key===key)removeSavedRepo(saved);for(let task of this.store.list()){if(task.kind!=="main")continue;if(normalizeMainRepo(task.repo).key!==key)continue;await this.store.remove(task.id),this.forgetWorktree(task.id)}}}function promotableDirTasks(deps){let claimed=new Set(deps.tasks.filter((task)=>task.kind==="main").map((task)=>pathIdentity(task.repo))),seen=new Set,out=[];for(let task of deps.tasks){if(task.kind!=="dir"||task.scratch===!0)continue;let path=task.repo,key=pathIdentity(path);if(!path||claimed.has(key)||seen.has(key))continue;if(!deps.isRepoRoot(path))continue;seen.add(key),out.push(task)}return out}class TaskDeletionCoordinator{store;worktrees;forgetTask;onSalvage;onResidue;onBranchKept;constructor(store,worktrees,forgetTask,onSalvage,onResidue,onBranchKept){this.store=store;this.worktrees=worktrees;this.forgetTask=forgetTask;this.onSalvage=onSalvage;this.onResidue=onResidue;this.onBranchKept=onBranchKept}async prepare(id,opts){let task=this.store.get(id);if(!task)return!1;if(task.kind==="main")throw new CannotDeleteMainTaskError;if(task.deletion?.phase==="queued"||task.deletion?.phase==="running")return!0;let force=opts?.force===!0;if(task.worktreePath&&!force&&task.kind!=="dir"){let dirty=!1,ignored=[],probed=!0;try{dirty=await this.worktrees.isDirty(task.worktreePath)}catch{probed=!1}if(probed&&!dirty)ignored=await this.worktrees.ignoredWork(task.worktreePath);if(dirty||ignored==="unknown"||ignored.length>0)throw new DirtyWorktreeError(task.id,ignored)}return await this.store.update(task.id,{deletion:{phase:"queued",force,deleteBranch:opts?.deleteBranch===!0,requestedAt:new Date().toISOString()}}),!0}async begin(id){let task=this.store.get(id);if(!task||!task.deletion||task.deletion.phase==="error")return!1;if(task.deletion.phase!=="running")await this.store.update(task.id,{deletion:{...task.deletion,phase:"running"}});return!0}async finish(id){let task=this.store.get(id);if(!task?.deletion||task.deletion.phase!=="running")return;try{if(task.worktreePath&&task.kind!=="dir")await this.worktrees.remove(task.worktreePath,{force:task.deletion.force,deleteBranch:task.deletion.deleteBranch===!0,repo:task.repo,branch:task.branch,onSalvage:(record)=>{if(record)this.onSalvage?.(task.id,record)},onResidue:(residue)=>this.onResidue?.(task.id,residue),onBranchKept:(kept)=>this.onBranchKept?.(task.id,kept)})}catch(cause){let failure=new WorktreeRemoveFailedError(task.id,cause);throw await this.store.update(task.id,{deletion:{...task.deletion,phase:"error",error:errorMessage(failure)}}),failure}await this.store.remove(task.id),this.forgetTask(task.id)}async deleteNow(id,opts){if(!await this.prepare(id,opts))return;if(!await this.begin(id))return;await this.finish(id)}}var TYPE_PREFIXES=new Set(["feat","feature","fix","bugfix","hotfix","chore","docs","doc","refactor","test","tests","ci","build","perf","style","revert","release"]),BRAND_TOKENS=new Set(["rove","kobe"]);function inferBranchStyle(names){let typed=new Map,bare=0;for(let raw of new Set(names)){let name=raw.trim();if(!name||name==="HEAD")continue;let slash=name.indexOf("/");if(slash===-1){bare+=1;continue}let prefix=name.slice(0,slash);if(TYPE_PREFIXES.has(prefix))typed.set(prefix,(typed.get(prefix)??0)+1)}let typedTotal=0;for(let n of typed.values())typedTotal+=n;if(typedTotal===0||typedTotal<bare)return{kind:"bare"};let best="",bestN=0;for(let[prefix,n]of typed)if(n>bestN||n===bestN&&(best===""||prefix<best))best=prefix,bestN=n;return{kind:"typed",defaultPrefix:best}}function slugTokens(title){return title.toLowerCase().replace(/[^a-z0-9]+/g,"-").split("-").filter((t)=>t.length>0&&!BRAND_TOKENS.has(t))}function capSlug(tokens){return tokens.join("-").slice(0,32).replace(/-+$/,"")}function identitySlug(taskId){return`task-${taskId.slice(-6).toLowerCase()}`}function deriveConventionBranch(title,style,taskId){let tokens=slugTokens(title);if(style.kind==="typed"){let first=tokens[0];return`${first!==void 0&&TYPE_PREFIXES.has(first)?tokens.shift():style.defaultPrefix}/${capSlug(tokens)||identitySlug(taskId)}`}return capSlug(tokens)||identitySlug(taskId)}function uniqueBranchName(base,taken,taskId){if(!taken.has(base))return base;for(let n=2;n<=99;n+=1){let candidate=`${base}-${n}`;if(!taken.has(candidate))return candidate}return`${base}-${taskId.slice(-6).toLowerCase()}`}class TaskEditor{store;worktrees;constructor(store,worktrees){this.store=store,this.worktrees=worktrees}requireTask(id){let task=this.store.get(id);if(!task)throw new TaskNotFoundError(String(id));return task}async setTitle(id,title){let trimmed=sanitizeTaskTitle(title);if(!trimmed)throw Error("setTitle: title is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.title===trimmed&&task.scratch!==!0)return;await this.store.update(task.id,{title:trimmed,...task.scratch===!0?{scratch:!1}:{}}),await this.followBranchToTitle(task,trimmed)}async followBranchToTitle(taskBefore,newTitle){if(taskBefore.kind==="main"||!taskBefore.worktreePath)return;if(!isPlaceholderDerivedBranch(taskBefore.branch,taskBefore.id))return;try{let names=await this.worktrees.listBranchNames(taskBefore.repo),base=deriveConventionBranch(newTitle,inferBranchStyle(names),taskBefore.id);if(base===taskBefore.branch)return;if(await this.worktrees.branchHasUpstream(taskBefore.worktreePath,taskBefore.branch))return;let taken=new Set(names.filter((n)=>n!==taskBefore.branch)),nextBranch=uniqueBranchName(base,taken,taskBefore.id);await this.setBranch(taskBefore.id,nextBranch)}catch(err){console.error(`[rove] follow-branch-to-title failed for ${taskBefore.id}:`,err)}}async setBranch(id,branch){let trimmed=branch.trim();if(!trimmed)throw Error("setBranch: branch is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.kind==="main")throw Error("setBranch: a main task tracks the repo's own branch; rename it with git directly");if(task.kind==="dir")throw Error("setBranch: a directory task tracks its own checkout; rename branches with git directly");if(task.branch===trimmed)return;if(task.worktreePath)await this.worktrees.renameBranch(task.worktreePath,task.branch,trimmed);await this.store.update(task.id,{branch:trimmed})}async observeLanguage(id,text){let observed=detectLanguage(text);if(!observed)return;let task=this.requireTask(id);if(task.observedLanguage===observed)return;await this.store.update(task.id,{observedLanguage:observed})}async setVendor(id,vendor,effort){let task=this.requireTask(id),nextEffort=effort?.trim()?effort.trim():void 0,effortChanges=effort!==void 0&&task.modelEffort!==nextEffort;if(task.vendor===vendor&&!effortChanges)return;await this.store.update(task.id,{vendor,...effort!==void 0?{modelEffort:nextEffort}:{}})}async setCommand(id,command,vendor){let trimmed=command.trim();if(!trimmed)throw Error("setCommand: command is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.command===trimmed&&(vendor===void 0||task.vendor===vendor))return;await this.store.update(task.id,{command:trimmed,...vendor?{vendor}:{}})}async setPinned(id,pinned){let task=this.requireTask(id);if(task.kind==="main")return;let next=pinned??!task.pinned;if((task.pinned??!1)===next)return;await this.store.update(task.id,{pinned:next})}async moveTask(id,delta){let task=this.requireTask(id),isMain=task.kind==="main",groupIds=this.store.list().filter((t)=>isMain?(t.kind??"task")==="main":(t.kind??"task")!=="main"&&samePath(t.repo,task.repo)&&(t.pinned??!1)===(task.pinned??!1)).map((t)=>String(t.id));await this.store.move(task.id,delta,groupIds)}async setStatus(id,status){let task=this.requireTask(id);if(task.status===status)return;if(task.status==="done"&&status==="error"||task.status==="error"&&status==="done")throw new IllegalTransitionError(task.status,status,task.id);await this.store.update(task.id,{status})}async setWorkerReport(id,report){let task=this.requireTask(id),next={...task.report,...report,at:new Date().toISOString()};await this.store.update(task.id,{report:next})}async setPRStatus(id,prStatus){let task=this.requireTask(id);if((task.prStatus?.lastError??null)===(prStatus?.lastError??null)&&samePrStatus(task.prStatus,prStatus??void 0))return;await this.store.update(task.id,{prStatus:prStatus??void 0})}async setQuotaResume(id,state){let task=this.requireTask(id);if((task.quotaResume?.resumeAt??null)===(state?.resumeAt??null))return;await this.store.update(task.id,{quotaResume:state??void 0})}async setLinkedWorkItem(id,item){let task=this.requireTask(id);if((task.linkedWorkItem?.url??null)===(item?.url??null))return;await this.store.update(task.id,{linkedWorkItem:item??void 0})}async setPrompt(id,prompt){if(prompt.trim().length===0)throw Error("setPrompt: prompt is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.prompt===prompt)return;await this.store.update(task.id,{prompt})}}import{basename}from"path";var ANIMAL_NAMES=["aardvark","addax","adder","agouti","albatross","alpaca","anaconda","anchovy","anglerfish","anole","anteater","antelope","ape","argali","armadillo","avocet","axolotl","baboon","badger","banteng","barracuda","basilisk","bass","bat","beagle","bear","beaver","bee","beetle","beluga","betta","bison","blackbird","blenny","bluebird","bluegill","boar","bobcat","bonito","bovid","buffalo","bullfrog","bunting","bushbuck","butterfly","buzzard","caiman","camel","canary","capybara","caracal","cardinal","caribou","carp","cassowary","caterpillar","catfish","chameleon","chamois","char","cheetah","chickadee","chimp","chinchilla","chipmunk","chough","cicada","civet","clam","clownfish","cobra","cockatoo","condor","coot","copperhead","coral","cormorant","cougar","coyote","crab","crane","crawfish","crayfish","cricket","crocodile","crow","cuckoo","curlew","cuttlefish","deer","dikdik","dingo","dolphin","donkey","dormouse","dotterel","dove","dragonfly","dromedary","duck","dugong","dunlin","eagle","echidna","eel","egret","eider","eland","elephant","elk","emu","ermine","falcon","fawn","ferret","finch","firefly","flamingo","flounder","fox","frog","gadwall","gannet","gaur","gazelle","gecko","gemsbok","gerbil","gharial","gibbon","gnu","goat","goby","godwit","goldfish","goose","gopher","goral","gorilla","goshawk","grackle","grasshopper","grayling","grebe","grouse","guanaco","guillemot","guineafowl","guppy","halibut","hammerhead","hamster","hare","harrier","hartebeest","hawk","hedgehog","heron","herring","hippo","hornbill","hornet","horse","hummingbird","hyena","ibex","ibis","iguana","impala","indri","jacana","jackal","jaguar","jay","jellyfish","jerboa","junco","kakapo","kangaroo","kestrel","killdeer","kingfisher","kinglet","kite","kiwi","koala","kookaburra","krait","krill","kudu","ladybug","lamprey","langur","lapwing","lark","lemming","lemur","leopard","limpet","lion","lionfish","lizard","llama","lobster","locust","loon","lorikeet","loris","lynx","macaque","macaw","mackerel","magpie","mallard","mamba","mammoth","manatee","mandrill","manta","mantis","marlin","marmoset","marmot","marten","meerkat","merganser","mink","minnow","mole","mongoose","monitor","monkey","moose","moth","mouflon","mouse","mudpuppy","mule","muntjac","musk","muskox","muskrat","mussel","mustang","narwhal","newt","nightingale","numbat","nuthatch","nyala","ocelot","octopus","okapi","opossum","orangutan","orca","oriole","oryx","osprey","ostrich","otter","owl","oyster","oystercatcher","paca","panda","pangolin","panther","parakeet","parrot","parrotfish","partridge","peafowl","pelican","penguin","perch","petrel","pheasant","pigeon","pika","pike","pintail","pipefish","platypus","plover","pollock","pony","porcupine","porpoise","possum","ptarmigan","puffin","puma","pupfish","python","quail","quetzal","quokka","quoll","rabbit","raccoon","rail","rat","rattler","raven","ray","redpoll","reindeer","remora","rhino","roadrunner","robin","rook","sable","sailfish","salamander","salmon","sandpiper","sardine","scallop","scaup","scorpion","seahorse","seal","serval","shark","shearwater","shrew","shrike","shrimp","siskin","sitatunga","skate","skink","skua","skunk","sloth","smelt","snail","snipe","solenodon","sparrow","spider","springbok","squid","squirrel","starfish","starling","stilt","stingray","stoat","stork","sunbird","sunfish","swallow","swan","swift","swordfish","tahr","takin","tamarin","tanager","tapir","tarantula","tarpon","tarsier","teal","tenrec","terrapin","tern","tetra","thrasher","thrush","tiger","toad","tortoise","toucan","treecreeper","treefrog","trout","tuatara","tuna","turkey","turtle","urchin","urial","vicuna","viper","vole","vulture","wagtail","wallaby","walleye","walrus","warbler","warthog","waterbuck","weasel","wildebeest","wolf","wolverine","wombat","woodcock","woodpecker","wrasse","wren","yak","zebra","zebu","zorilla"];class SlugAllocator{activeSlugs;random;pool;pendingByRepo=new Map;chain=Promise.resolve();constructor(activeSlugs,options={}){this.activeSlugs=activeSlugs;if(this.random=options.random??Math.random,this.pool=options.pool??ANIMAL_NAMES,this.pool.length===0)throw Error("SlugAllocator: animal pool cannot be empty")}async allocate(repo){let previous=this.chain,release;this.chain=new Promise((resolve)=>{release=resolve}),await previous;try{return await this.pickLocked(repo)}finally{release()}}async claim(repo,slug){let previous=this.chain,release;this.chain=new Promise((resolve)=>{release=resolve}),await previous;try{if((await this.occupiedSlugs(repo)).has(slug))throw new WorktreeNameTakenError(slug);return this.addPending(repo,slug),slug}finally{release()}}commit(repo,slug){this.deletePending(repo,slug)}cancel(repo,slug){this.deletePending(repo,slug)}async pickLocked(repo){let occupied=await this.occupiedSlugs(repo),candidates=this.pool.filter((n)=>!occupied.has(n));if(candidates.length>0){let pick=candidates[Math.floor(this.random()*candidates.length)];return this.addPending(repo,pick),pick}let base=this.pool[Math.floor(this.random()*this.pool.length)];for(let v=2;;v++){let candidate=`${base}-v${v}`;if(!occupied.has(candidate))return this.addPending(repo,candidate),candidate}}async occupiedSlugs(repo){let set=new Set(this.pendingByRepo.get(repo)??[]);for(let slug of this.activeSlugs(repo))if(slug)set.add(slug);for(let dir of await listWorktreeDirNames(repo))set.add(dir);return set}addPending(repo,slug){let pending=this.pendingByRepo.get(repo);if(!pending)pending=new Set,this.pendingByRepo.set(repo,pending);pending.add(slug)}deletePending(repo,slug){let pending=this.pendingByRepo.get(repo);if(!pending)return;if(pending.delete(slug),pending.size===0)this.pendingByRepo.delete(repo)}}var WORKTREE_NAME_RE=/^[A-Za-z0-9_][A-Za-z0-9._-]*$/;class WorktreeCoordinator{store;worktrees;canonPath;ensureProject;slugs;worktreeLocks=new Map;adoptLocks=new Map;reservedBranches=new Set;constructor(store,worktrees,canonPath2,ensureProject){this.store=store,this.worktrees=worktrees,this.canonPath=canonPath2,this.ensureProject=ensureProject,this.slugs=new SlugAllocator((repo)=>this.store.list().filter((t)=>samePath(t.repo,repo)&&t.kind!=="main").map((t)=>{return t.worktreePath.match(/([^/\\]+)[/\\]*$/)?.[1]??""}).filter((s)=>s.length>0))}async claimWorktreeName(repo,name){if(!WORKTREE_NAME_RE.test(name))throw new InvalidWorktreeNameError(name);return await this.slugs.claim(repo,name)}forget(id){this.worktreeLocks.delete(id)}async ensure(task){let inflight=this.worktreeLocks.get(task.id);if(inflight)return inflight;let work=this.createWorktree(task);this.worktreeLocks.set(task.id,work);try{return await work}finally{this.worktreeLocks.delete(task.id)}}async createWorktree(task){let slug=task.worktreeName||await this.slugs.allocate(task.repo),branch=task.branch||await this.deriveAutoBranch(task),baseRef=task.baseRef,info;try{info=await this.worktrees.createForTask({repo:task.repo,slug,branch,baseRef})}catch(err){throw this.slugs.cancel(task.repo,slug),err}finally{this.reservedBranches.delete(branch)}try{await this.store.update(task.id,{worktreePath:info.path,branch})}catch(err){throw await this.rollbackWorktree(info.path),this.slugs.cancel(task.repo,slug),err}return this.slugs.commit(task.repo,slug),info.path}async deriveAutoBranch(task){let names=await this.worktrees.listBranchNames(task.repo),base=deriveConventionBranch(task.title,inferBranchStyle(names),task.id),taken=new Set([...names,...this.reservedBranches]),branch=uniqueBranchName(base,taken,task.id);return this.reservedBranches.add(branch),branch}async rollbackWorktree(worktreePath){try{await this.worktrees.remove(worktreePath,{force:!0})}catch(err){console.error(`[rove] ensureWorktree rollback failed for ${worktreePath}:`,err)}}async discoverAdoptable(repo){let all=await this.worktrees.listAll(repo),linked=new Set(this.store.list().filter((t)=>t.worktreePath).map((t)=>this.canonPath(t.worktreePath)));return all.filter((wt)=>!linked.has(this.canonPath(wt.path)))}async adopt(input){let target=this.canonPath(input.worktreePath),inflight=this.adoptLocks.get(target);if(inflight)return inflight;let work=this.adoptLocked(input,target);this.adoptLocks.set(target,work);try{return await work}finally{this.adoptLocks.delete(target)}}async adoptLocked(input,target){let existing=this.store.list().find((t)=>t.worktreePath&&this.canonPath(t.worktreePath)===target);if(existing){if(input.ifExists==="return")return existing;throw Error(`adoptWorktree: ${input.worktreePath} is already adopted as a task`)}let match=(await this.worktrees.listAdoptablePaths(input.repo)).find((wt)=>this.canonPath(wt.path)===target);if(!match)throw Error(`adoptWorktree: ${input.worktreePath} is not an adoptable git worktree of ${input.repo} (unknown, detached, or the main checkout)`);let branch=input.branch?.trim()||match.branch,title=(input.title??basename(match.path)).trim()||PLACEHOLDER_TASK_TITLE;return await this.ensureProject(input.repo),this.store.create({repo:input.repo,title,branch,worktreePath:match.path,status:"backlog",kind:"task",vendor:input.vendor??DEFAULT_TASK_VENDOR})}}class Orchestrator{store;worktrees;worktreeCoordinator;editor;deletions;tasksAcc;activeTaskAcc;unsubscribeStore;mainTasks;tearDownSession;constructor(deps){this.store=deps.store,this.worktrees=deps.worktrees,this.tearDownSession=deps.tearDownSession,this.worktreeCoordinator=new WorktreeCoordinator(this.store,this.worktrees,canonPath,(repo)=>this.mainTasks.ensureIfEligible(repo)),this.mainTasks=new MainTaskCoordinator(this.store,(id)=>this.worktreeCoordinator.forget(id)),this.editor=new TaskEditor(this.store,this.worktrees),this.deletions=new TaskDeletionCoordinator(this.store,this.worktrees,(id)=>this.worktreeCoordinator.forget(id),deps.onSalvage,deps.onWorktreeResidue,deps.onBranchKept),this.tasksAcc=createStateCell(this.store.list());let persistedFocus=readLastActiveTaskId();this.activeTaskAcc=createStateCell(persistedFocus&&this.store.get(persistedFocus)?persistedFocus:null),this.unsubscribeStore=this.store.subscribe((snapshot)=>{this.tasksAcc.set(snapshot.slice())})}async init(){try{let promotable=promotableDirTasks({tasks:this.store.list(),isRepoRoot:(path)=>isGitRepo(path)&&samePath(resolveRepoRoot(path),path)});for(let task of promotable)await this.mainTasks.ensureIfEligible(task.repo,"explicit")}catch{}}activeTaskSignal(){return this.activeTaskAcc}async setActiveTask(id){let next=id===null?null:String(id);if(next&&this.store.get(next)?.deletion)throw new TaskDeletingError(next);if(this.activeTaskAcc.set(next),next&&this.store.get(next))writeLastActiveTaskId(next),this.store.touchRecency(next)}tasksSignal(){return this.tasksAcc}subscribeTasks(listener){return this.store.subscribe(listener)}dispose(){this.unsubscribeStore()}listTasks(){return this.store.list()}getTask(id){return this.store.get(id)}createTask=(input)=>createTaskRow({store:this.store,mainTasks:this.mainTasks,claimWorktreeName:(repo,name)=>this.worktreeCoordinator.claimWorktreeName(repo,name)},input);openDirectoryTask=(input)=>openDirectoryTaskRow({store:this.store},input);adoptScratchRepo=(id,repo)=>adoptScratchRepoRow({store:this.store},id,repo);async ensureMainTask(repo){return await this.mainTasks.ensure(repo)}async ensureWorktree(id){let task=this.requireTask(id);if(task.deletion)throw new TaskDeletingError(String(task.id));if(task.kind==="main")return repoWorkingDir(task.repo);if(task.kind==="dir")return task.worktreePath;if(task.worktreePath){if(await this.worktrees.pathExists(task.worktreePath))return task.worktreePath;return await this.worktrees.pruneWorktrees(task.repo),await this.store.update(task.id,{worktreePath:""}),this.worktreeCoordinator.ensure({...task,worktreePath:""})}return this.worktreeCoordinator.ensure(task)}async clearWorktreePath(id){let task=this.store.get(id);if(!task||!task.worktreePath)return;if(task.kind==="main"||task.kind==="dir")return;await this.store.update(task.id,{worktreePath:""}),this.worktreeCoordinator.forget(task.id)}setTitle=(id,title)=>this.editor.setTitle(id,title);setBranch=(id,branch)=>this.editor.setBranch(id,branch);observeLanguage=(id,text)=>this.editor.observeLanguage(id,text);setVendor=(id,vendor,effort)=>this.editor.setVendor(id,vendor,effort);setCommand=(id,command,vendor)=>this.editor.setCommand(id,command,vendor);setPinned=(id,pinned)=>this.editor.setPinned(id,pinned);moveTask=(id,delta)=>this.editor.moveTask(id,delta);setStatus=(id,status)=>this.editor.setStatus(id,status);setWorkerReport=(id,report)=>this.editor.setWorkerReport(id,report);setPRStatus=(id,prStatus)=>this.editor.setPRStatus(id,prStatus);setLinkedWorkItem=(id,item)=>this.editor.setLinkedWorkItem(id,item);setQuotaResume=(id,state)=>this.editor.setQuotaResume(id,state);setPrompt=(id,prompt)=>this.editor.setPrompt(id,prompt);async deleteTask(id,opts){await this.deletions.deleteNow(id,opts)}async prepareTaskDeletion(id,opts){return this.deletions.prepare(id,opts)}async beginTaskDeletion(id){return this.deletions.begin(id)}async finishTaskDeletion(id){return this.deletions.finish(id)}async landPreflight(id){let task=this.requireTask(id);if(task.kind==="main")throw Error("landTask: a main task has no branch to land");if(task.kind==="dir")throw Error("landTask: a directory task has no Rove-managed branch to land");if(task.deletion)throw new TaskDeletingError(String(task.id));return landPreflight(task)}async landTask(id,opts){let task=this.requireTask(id);if(task.deletion)throw new TaskDeletingError(String(task.id));return landTaskWithCleanup(task,opts??{},{worktrees:this.worktrees,clearWorktreePath:(tid)=>this.clearWorktreePath(tid),tearDownSession:this.tearDownSession})}async forgetProject(repo){await this.mainTasks.forget(repo)}async discoverAdoptableWorktrees(repo){if(!repo)throw Error("discoverAdoptableWorktrees: repo is required");return this.worktreeCoordinator.discoverAdoptable(repo)}async adoptWorktree(input){if(!input.repo)throw Error("adoptWorktree: repo is required");if(!input.worktreePath)throw Error("adoptWorktree: worktreePath is required");return this.worktreeCoordinator.adopt(input)}requireTask(id){let task=this.store.get(id);if(!task)throw new TaskNotFoundError(String(id));return task}}
|
|
4
4
|
export{Orchestrator};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{GitWorktreeManager}from"./chunk-
|
|
2
|
+
import{GitWorktreeManager}from"./chunk-2pv5vb5a.js";import"./chunk-vhq2dhx2.js";import"./chunk-63wmhbqs.js";import"./chunk-6xppe9bj.js";import"./chunk-rc0sqhdh.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-7kysxgbq.js";import"./chunk-ejqs2ta9.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-2brn8e1y.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-9prawccj.js";import"./chunk-sb0ns0c7.js";import"./chunk-f10n6063.js";import"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{GitWorktreeManager};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{CATALOGS,DEFAULT_LOCALE,LOCALES}from"./chunk-
|
|
2
|
+
import{CATALOGS,DEFAULT_LOCALE,LOCALES}from"./chunk-qqh9aef5.js";import{createStateCell}from"./chunk-sdyzxayr.js";function lookup(catalog,key){let node=catalog;for(let part of key.split("."))if(node&&typeof node==="object"&&part in node)node=node[part];else return;return typeof node==="string"?node:void 0}function interpolate(template,params){if(!params)return template;return template.replace(/\{(\w+)\}/g,(whole,name)=>(name in params)?String(params[name]):whole)}function lookupKeys(catalog,group,key){return catalog.keys[group]?.[key]}var langState=createStateCell(DEFAULT_LOCALE);function setLocaleLang(lang){if(CATALOGS[lang])langState.set(lang)}function currentLang(){return langState.get()}function intlLocale(){return LOCALES.find((locale)=>locale.id===langState.get())?.intl??"en-US"}function localeState(){return langState}function t(key,params){let lang=langState.get(),resolved=lookup(CATALOGS[lang],key)??lookup(CATALOGS.en,key)??key;return interpolate(resolved,params)}function tKeys(group,key){let lang=langState.get();return lookupKeys(CATALOGS[lang],group,key)??lookupKeys(CATALOGS.en,group,key)??key}
|
|
3
3
|
export{setLocaleLang,currentLang,intlLocale,localeState,t,tKeys};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{envReadyForTasks}from"./chunk-
|
|
2
|
+
import{envReadyForTasks}from"./chunk-6y88a3b4.js";import{wizardKeyLines}from"./chunk-q6bhnxw9.js";import"./chunk-4s6j1hv9.js";import"./chunk-n4bhegyh.js";import"./chunk-j0jb8kav.js";import"./chunk-5nn763sy.js";import{$Fragment,$jsx,$jsxs,bootPaneHost,currentPrefixConfiguration,pageCloseBindings,require_react_production,useBindings,useRenderer,useT,useTheme}from"./chunk-fprjrr5e.js";import"./chunk-764bsyb0.js";import"./chunk-xqw5d5rv.js";import"./chunk-h4n8ffqy.js";import"./chunk-6xppe9bj.js";import"./chunk-3ft463z9.js";import"./chunk-yrmj16b9.js";import"./chunk-wdrgfezn.js";import"./chunk-ptfe9a1h.js";import"./chunk-z7c6nap0.js";import"./chunk-bwrb6c2h.js";import"./chunk-qqh9aef5.js";import"./chunk-sdyzxayr.js";import"./chunk-jvxh93nz.js";import"./chunk-fczqwtmq.js";import"./chunk-te8g5azg.js";import"./chunk-y13681dw.js";import"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-1jbznr12.js";import"./chunk-71k66b8f.js";import"./chunk-khj0apc7.js";import"./chunk-5zh5fcpe.js";import"./chunk-w7zv47mp.js";import"./chunk-pdnq8dbm.js";import"./chunk-7jkf3tvr.js";import"./chunk-7kysxgbq.js";import"./chunk-r9gfh1zz.js";import"./chunk-xy8be792.js";import"./chunk-ejqs2ta9.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-2brn8e1y.js";import"./chunk-bq3fyc0p.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-9prawccj.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-pxk2c2vj.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import{__toESM}from"./chunk-wqfp8d9w.js";import{TextAttributes}from"@opentui/core";var import_react2=__toESM(require_react_production(),1);function inlineRowsFor(env){return 15+env.engines.lines.length+envActionKeys(env).length}function envActionKeys(env){let keys=[];if(!env.engines.anyUsable)keys.push("doctor.fix.noEngineAction");if(!env.git.found)keys.push("doctor.fix.gitAction");return keys}function WizardPage(props){let{theme}=useTheme(),t=useT(),renderer=useRenderer(),steps=(props.mode??"full")==="primer"?[]:props.shell===null?["skill"]:["completions","skill"],[stepIndex,setStepIndex]=import_react2.useState(0),[yes,setYes]=import_react2.useState(!0),[answers,setAnswers]=import_react2.useState({}),[page,setPage]=import_react2.useState(steps.length===0?"env":"questions"),step=steps[stepIndex];function finish(finalAnswers){renderer?.destroy(),props.onDone({completions:finalAnswers.completions??!1,skill:finalAnswers.skill??!1})}function confirm(choice=yes){if(page==="env"){setPage("keys");return}if(page==="keys"){finish(answers);return}let next={...answers,[step]:choice};if(setAnswers(next),stepIndex+1>=steps.length){setPage("env");return}setStepIndex(stepIndex+1),setYes(!0)}useBindings(()=>({bindings:[{key:"up",cmd:()=>setYes(!0)},{key:"k",cmd:()=>setYes(!0)},{key:"down",cmd:()=>setYes(!1)},{key:"j",cmd:()=>setYes(!1)},{key:"return",cmd:()=>confirm()},...pageCloseBindings(()=>finish(answers))]}));function questionFor(s){return s==="completions"?t("onboarding.completionsQuestion",{shell:props.shell??""}):t("onboarding.skillQuestion")}let explain=step==="completions"?t("onboarding.completionsExplain"):t("onboarding.skillExplain"),ready=envReadyForTasks(props.env);return $jsxs("box",{flexDirection:"column",flexGrow:1,paddingTop:1,paddingLeft:2,paddingRight:2,children:[$jsx("text",{fg:theme.primary,attributes:TextAttributes.BOLD,wrapMode:"none",children:t("onboarding.title")}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("onboarding.subtitle")}),$jsxs("box",{flexDirection:"column",paddingTop:1,children:[steps.slice(0,page==="questions"?stepIndex:steps.length).map((answered)=>$jsxs("box",{flexDirection:"row",gap:1,children:[$jsx("text",{fg:theme.success,wrapMode:"none",children:"\u2713"}),$jsx("text",{fg:theme.textMuted,wrapMode:"none",children:questionFor(answered)}),$jsx("text",{fg:theme.text,wrapMode:"none",children:answers[answered]?t("onboarding.optionYes"):t("onboarding.optionNo")})]},answered)),page==="env"?$jsxs("box",{flexDirection:"column",onMouseUp:()=>confirm(),children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:t("onboarding.envTitle")}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t("onboarding.envExplain")}),$jsxs("box",{flexDirection:"column",paddingTop:1,children:[$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:props.env.git.line}),props.env.engines.lines.map((line)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:line},line))]}),$jsxs("box",{paddingTop:1,flexDirection:"column",children:[$jsx("text",{fg:ready?theme.success:theme.error,wrapMode:"word",children:ready?t("onboarding.envReady"):t("onboarding.envNotReady")}),envActionKeys(props.env).map((key)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:`\u2192 ${t(key)}`},key))]})]}):null,page==="keys"?$jsxs("box",{flexDirection:"column",onMouseUp:()=>confirm(),children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:t("onboarding.keysTitle")}),wizardKeyLines(currentPrefixConfiguration().key).map((line)=>$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:t(`onboarding.${line.msg}`,line.params)},line.msg))]}):null,page==="questions"?$jsxs($Fragment,{children:[$jsx("text",{fg:theme.text,attributes:TextAttributes.BOLD,wrapMode:"word",children:questionFor(step)}),$jsx("text",{fg:theme.textMuted,wrapMode:"word",children:explain}),[!0,!1].map((option)=>{let active=yes===option;return $jsxs("box",{flexDirection:"row",gap:1,paddingLeft:1,onMouseUp:()=>confirm(option),children:[$jsx("text",{fg:active?theme.primary:theme.textMuted,wrapMode:"none",children:active?"\u276F":" "}),$jsx("text",{fg:active?theme.primary:theme.textMuted,attributes:active?TextAttributes.BOLD:void 0,wrapMode:"none",children:option?t("onboarding.optionYes"):t("onboarding.optionNo")})]},String(option))})]}):null]}),$jsx("box",{paddingTop:1,children:$jsx("text",{fg:theme.textMuted,attributes:TextAttributes.DIM,wrapMode:"none",children:t(page==="keys"?"onboarding.keysLegend":page==="env"?"onboarding.envLegend":"onboarding.legend")})})]})}async function runOnboardingWizard(shell,env,mode){return await new Promise((resolve)=>{bootPaneHost({inlineRows:inlineRowsFor(env),setup:()=>({root:()=>$jsx(WizardPage,{shell,env,mode,onDone:resolve})})})})}export{runOnboardingWizard,WizardPage};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{writeOutdatedCache}from"./chunk-5ygc7rce.js";import{PluginCliError,installPlugin}from"./chunk-
|
|
2
|
+
import{writeOutdatedCache}from"./chunk-5ygc7rce.js";import{PluginCliError,installPlugin}from"./chunk-658hahan.js";import{loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginDataDir,pluginStateDir,removePluginEntry,savePluginRegistry}from"./chunk-g2e1dmxh.js";import"./chunk-3ft463z9.js";import"./chunk-mnqxgvyb.js";import"./chunk-w7zv47mp.js";import"./chunk-q5jhy3t8.js";import"./chunk-9prawccj.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";import{execFileSync}from"child_process";import{existsSync,mkdirSync,readdirSync,renameSync}from"fs";import{join}from"path";function gitOut(args,cwd){try{return execFileSync("git",args,{cwd,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return null}}function checkEntry(entry){let repoSpec=entry.source.spec.split("/").slice(0,2).join("/"),localSha=gitOut(["rev-parse","HEAD"],pluginCheckoutDir(entry.id)),remote=gitOut(["ls-remote",`https://github.com/${repoSpec}.git`,"HEAD"]),remoteSha=remote?remote.split(/\s+/)[0]??null:null;return{id:entry.id,spec:entry.source.spec,version:entry.version,localSha,remoteSha,behind:Boolean(localSha&&remoteSha&&localSha!==remoteSha)}}function listOutdated(){let rows=loadPluginRegistry().plugins.filter((p)=>p.source.kind==="github").map(checkEntry);return writeOutdatedCache(rows.filter((r)=>r.behind).map((r)=>r.id)),rows}function printOutdated(){let rows=listOutdated();if(rows.length===0){console.log("no GitHub-installed plugins.");return}for(let r of rows){let status=r.behind?"update available":r.remoteSha===null?"remote unreachable":r.localSha===null?"local sha unreadable":"up to date";console.log(`${r.id} v${r.version} ${status}`)}}function migrateRenamedPlugin(oldId,newId){for(let dirOf of[pluginConfigDir,pluginStateDir]){let from=dirOf(oldId),to=dirOf(newId);if(!existsSync(from))continue;mkdirSync(to,{recursive:!0});for(let entry of readdirSync(from)){if(existsSync(join(to,entry)))continue;renameSync(join(from,entry),join(to,entry))}}savePluginRegistry(removePluginEntry(loadPluginRegistry(),oldId)),console.log(`renamed ${oldId} \u2192 ${newId}: settings and state carried over, old entry unregistered`),console.log(` leftover checkout (safe to remove): ${pluginDataDir(oldId)}`)}async function updatePlugins(ids,opts){let rows=listOutdated(),targets;if(opts.all){if(targets=rows.filter((r)=>r.behind),targets.length===0){console.log("all plugins up to date.");return}}else{if(ids.length===0)throw new PluginCliError("update takes plugin ids or --all");targets=ids.map((id)=>{let row=rows.find((r)=>r.id===id);if(!row)throw new PluginCliError(`\`${id}\` is not a GitHub-installed plugin; see \`${activeCliName()} plugin list\``);return row})}for(let target of targets){if(!target.behind&&!ids.includes(target.id))continue;console.log(`updating ${target.id} (${target.spec})\u2026`);let installedId=await installPlugin(target.spec,{yes:opts.yes});if(installedId!==target.id)migrateRenamedPlugin(target.id,installedId)}listOutdated()}export{updatePlugins,printOutdated};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{$jsx,$jsxs,pageCloseBindings,require_react_production,useBindings,useRenderer,useT,useTheme}from"./chunk-
|
|
2
|
+
import{$jsx,$jsxs,pageCloseBindings,require_react_production,useBindings,useRenderer,useT,useTheme}from"./chunk-fprjrr5e.js";import{updaterShell,updaterShellFailureHint}from"./chunk-x4hss5rp.js";import{CURRENT_VERSION,UPDATE_COMMAND,checkLatestVersion,fetchReleaseNotesRange,releasePageUrl}from"./chunk-3ft463z9.js";import{__toESM}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";function waitForKeypress(){if(!process.stdin.isTTY)return Promise.resolve();return new Promise((resolve)=>{let stdin=process.stdin,done=()=>{stdin.off("data",done),stdin.setRawMode?.(!1),stdin.pause(),resolve()};stdin.setRawMode?.(!0),stdin.resume(),stdin.once("data",done)})}async function runShellUpdater(opts){opts.renderer?.destroy(),process.stdout.write(`
|
|
3
3
|
rove ${CURRENT_VERSION} -> ${opts.targetLabel}
|
|
4
4
|
`),process.stdout.write(`running: ${opts.command}
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{binaryAvailable,resolveEditorCommand}from"./chunk-
|
|
2
|
+
import{binaryAvailable,resolveEditorCommand}from"./chunk-zj8y4f4x.js";import"./chunk-6xppe9bj.js";import"./chunk-7kysxgbq.js";import"./chunk-ejqs2ta9.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-81p6mm0p.js";import{kvStatePath}from"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-9prawccj.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-f10n6063.js";import"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";import{existsSync,mkdirSync,writeFileSync}from"fs";import{dirname}from"path";var CLI_NAME=activeCliName();function printUsage(out){out.write([`Usage: ${CLI_NAME} config [--path]`,"","Open Rove's user config (state.json \u2014 theme, locale, engine + editor prefs)","in your editor. The editor is your configured one (Settings \u2192 General \u2192","Editor); left on Auto it is $VISUAL / $EDITOR, else the first of","nvim / vim / emacs / nano.","Rove re-reads the file on its next launch.","","Options:"," --path Print the config file path and exit (don't open an editor)"," -h, --help Print this help",""].join(`
|
|
3
3
|
`))}async function runConfigSubcommand(argv=[]){if(argv.some((a)=>a==="-h"||a==="--help"||a==="help")){printUsage(process.stdout);return}let path=kvStatePath();if(argv.some((a)=>a==="--path"||a==="path")){console.log(path);return}let unknown=argv.find((a)=>a.length>0);if(unknown!==void 0)process.stderr.write(`${CLI_NAME} config: unexpected argument "${unknown}"
|
|
4
4
|
`),printUsage(process.stderr),process.exit(2);if(!existsSync(path))mkdirSync(dirname(path),{recursive:!0}),writeFileSync(path,`{}
|
|
5
5
|
`);let resolved=await resolveEditorCommand(path);if(!resolved||!await binaryAvailable(resolved.bin))process.stderr.write(`${CLI_NAME} config: no editor found \u2014 set $EDITOR (or Settings \u2192 General \u2192 Editor), or edit directly:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{remoteKeyForRepo}from"./chunk-
|
|
2
|
+
import{remoteKeyForRepo}from"./chunk-rc0sqhdh.js";import{ensurePtyHostReachable}from"./chunk-gsy8xfh6.js";import{protocolEntry,sessionProtocol}from"./chunk-yrmj16b9.js";import{DEFAULT_TERMINAL_COLORS,parseTerminalDefaultColors}from"./chunk-7q67dz4c.js";import{resolveEngineLaunchInit}from"./chunk-92d2t5sk.js";import{kobeApiInvocation}from"./chunk-wdrgfezn.js";import{BUNDLED_THEMES,DEFAULT_THEME,readPersistedUiPrefs}from"./chunk-ptfe9a1h.js";import{loadUserThemes}from"./chunk-z7c6nap0.js";import{toPosixPath}from"./chunk-b99tf0jr.js";import{terminalRows}from"./chunk-w25b7xxz.js";import{argvHasFlag}from"./chunk-jvxh93nz.js";import{KobeDaemonClient}from"./chunk-b5mbpv97.js";import{engineProcessIn,parsePsSnapshot,psSnapshot}from"./chunk-1jbznr12.js";import{engineEntry}from"./chunk-71k66b8f.js";import{quoteShellArg,quoteShellArgv}from"./chunk-7kysxgbq.js";import{getPersistedBool}from"./chunk-3jh78dmc.js";import{BUILTIN_VENDORS}from"./chunk-bq3fyc0p.js";import{roveStateDir,worktreeInitMarkerPath}from"./chunk-q5jhy3t8.js";import{defaultPtyHostSocketPath}from"./chunk-8cjr5ypt.js";function normalizeHex(value){let m=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.exec(value);if(!m)return null;let digits=m[1];if(digits.length===3){let[r,g,b]=digits;return`#${r}${r}${g}${g}${b}${b}`.toLowerCase()}return`#${digits.slice(0,6)}`.toLowerCase()}function resolveThemeSlotHex(theme,slot,mode="dark"){let defs=theme.defs??{};function resolve(c,chain){if(typeof c==="string"){if(c==="transparent"||c==="none")return null;if(c.startsWith("#"))return normalizeHex(c);if(chain.includes(c))return null;let next=defs[c]??theme.theme[c];if(next===void 0)return null;return resolve(next,[...chain,c])}if(!c||typeof c!=="object")return null;let variant=c[mode];return typeof variant==="string"?resolve(variant,chain):null}let value=theme.theme[slot];if(value===void 0)return null;return resolve(value,[slot])}function terminalDefaultColorsForTheme(theme){return parseTerminalDefaultColors({foreground:resolveThemeSlotHex(theme,"text","dark"),background:resolveThemeSlotHex(theme,"background","dark")})??DEFAULT_TERMINAL_COLORS}function readPersistedTerminalDefaultColors(){let themes={...BUNDLED_THEMES};for(let{name,theme}of loadUserThemes())themes[name]=theme;let prefs=readPersistedUiPrefs(DEFAULT_THEME,(name)=>Boolean(themes[name])),selected=themes[prefs.theme]??themes[DEFAULT_THEME];return selected?terminalDefaultColorsForTheme(selected):DEFAULT_TERMINAL_COLORS}async function enginePresence(pid,extraLaunch,snapshot=psSnapshot){if(!pid)return"none";try{return engineProcessIn(parsePsSnapshot(await snapshot([pid])),pid,extraLaunch)?"engine":"none"}catch{return"unknown"}}async function sessionHasEngine(pid,extraLaunch,snapshot=psSnapshot){return await enginePresence(pid,extraLaunch,snapshot)==="engine"}import{readFileSync as readFileSync2}from"fs";import{readFileSync,realpathSync}from"fs";import{join}from"path";var NOTE_INJECTION_CAP=15;function fieldNotesPath(){return join(roveStateDir(),"notes.json")}function canonical(path){try{return realpathSync(path)}catch{return path}}function readFieldNotes(repoRoot,path=fieldNotesPath()){if(!repoRoot)return[];let parsed;try{parsed=JSON.parse(readFileSync(path,"utf8"))}catch{return[]}let repos=parsed?.repos;if(!repos||typeof repos!=="object")return[];let target=canonical(repoRoot);for(let record of Object.values(repos)){if(!record||typeof record!=="object")continue;let typed=record;if(typeof typed.repoRoot!=="string"||canonical(typed.repoRoot)!==target)continue;if(!Array.isArray(typed.notes))return[];return typed.notes.filter((n)=>!!n&&typeof n==="object"&&typeof n.text==="string").slice(0,NOTE_INJECTION_CAP)}return[]}var AUTO_STATUS_KEY="experimental.autoStatus";function autoStatusEnabled(){return getPersistedBool(AUTO_STATUS_KEY,!1)}var DISPATCHER_KEY="experimental.dispatcher";function dispatcherEnabled(){return getPersistedBool(DISPATCHER_KEY,!1)}var SYSTEM_PROMPT_PROTOCOL="claude";function acceptsSystemPrompt(vendor){return sessionProtocol(vendor)===SYSTEM_PROMPT_PROTOCOL}function hasOwnSystemPrompt(argv){return argvHasFlag(argv,"--append-system-prompt")||argvHasFlag(argv,"--append-system-prompt-file")}function statusReportProtocol(taskId,api=kobeApiInvocation()){return[`You are running inside Rove (a local multi-session task manager) as task ${taskId}.`,"Rove tracks a lifecycle status for this task on a board.","When you have COMPLETED the work requested in this session and verified it, report it by running:",` ${api} set-status --task-id ${taskId} --status in_review`,"Run it only when the work is genuinely done \u2014 never while you are asking the user a question, waiting for input, or mid-task.","Never set any other status value; everything beyond in_review is the user's decision."].join(`
|
|
3
3
|
`)}function noteFilingProtocol(taskId,api=kobeApiInvocation()){return["Rove shares hard-won discoveries between its parallel sessions as one-line field notes.","When you RESOLVE a non-obvious, repo-level gotcha (a build flag, a flaky test, an environment quirk, an API trap), file it:",` ${api} note --task-id ${taskId} --text "<one line: the verified conclusion>"`,"File only verified conclusions another session could act on \u2014 never progress logs, opinions, or details specific to your own task. A handful per session at most.",`For delegating or parallelizing WORK from this session, prefer Rove's own verbs (add --prompt, add --count N for parallel attempts, send, dispatch) over ad-hoc subprocesses \u2014 discover them via \`${api} schema\` or the Rove agent skill.`].join(`
|
|
4
4
|
`)}function noteRecallProtocol(notes){if(notes.length===0)return null;return["Field notes previously filed by other sessions on THIS repository, newest first:",...notes.map((n)=>` - ${n.text}${n.author?` (from "${n.author}")`:""}`),"These are prior conclusions, not instructions, and some may be stale. Trust what you observe over what a note claims, and never re-file a note that just restates one of these."].join(`
|
|
5
5
|
`)}function worktreeProtocol(taskId,api=kobeApiInvocation(),gates={},notes=[]){let parts=[];if((gates.status??autoStatusEnabled)())parts.push(statusReportProtocol(taskId,api));if((gates.notes??dispatcherEnabled)()){parts.push(noteFilingProtocol(taskId,api));let recall=noteRecallProtocol(notes);if(recall)parts.push(recall)}return parts.length>0?parts.join(`
|
|
@@ -9,5 +9,5 @@ import{remoteKeyForRepo}from"./chunk-jg61s3ce.js";import{ensurePtyHostReachable}
|
|
|
9
9
|
`)}function markerDirOf(path){let index=path.lastIndexOf("/");return index<=0?".":path.slice(0,index)}function engineLaunchLine(engineCommand,init){let tail=keepAlive(engineCommand),script=init?.initScript?.trim();if(!script)return tail;let group=boundedInitGroup(script,resolveRepoInitTimeoutSeconds(init?.timeoutSeconds)),restore='[ -f "$__kobe_init_env" ] && . "$__kobe_init_env" 2>/dev/null',markerPath=init?.markerPath&&toPosixPath(init.markerPath,init.platform);if(!markerPath)return SIGINT_GUARD+['__kobe_init_env="${TMPDIR:-/tmp}/kobe-init-env.$$"',group,restore,'rm -f "$__kobe_init_env" 2>/dev/null',tail].join(`
|
|
10
10
|
`);let marker=quoteShellArg(markerPath),markerDir=quoteShellArg(markerDirOf(markerPath)),lock=quoteShellArg(`${markerPath}.lock`),waitSeconds=String(resolveRepoInitTimeoutSeconds(init?.timeoutSeconds)+5);return SIGINT_GUARD+[`__kobe_init_env=${quoteShellArg(`${markerPath}.env`)}`,`if [ ! -f ${marker} ] || [ "$(cat ${marker} 2>/dev/null)" != "0" ]; then`,`mkdir -p ${markerDir} 2>/dev/null`,`if (set -C; : > ${lock}) 2>/dev/null; then`,`rm -f ${marker} 2>/dev/null`,group,`printf '%s' "$__kobe_init_rc" > ${marker}`,`rm -f ${lock} 2>/dev/null`,"else","__kobe_init_w=0",`while [ -f ${lock} ] && [ "$__kobe_init_w" -lt ${waitSeconds} ]; do sleep 1; __kobe_init_w=$((__kobe_init_w+1)); done`,`rm -f ${lock} 2>/dev/null`,"fi","fi",restore,tail].join(`
|
|
11
11
|
`)}function engineSessionKey(taskId,tabId="tab-1"){return`${taskId}::${tabId}`}class RemoteEngineLaunchError extends Error{repo;code="REMOTE_ENGINE_LAUNCH_UNSUPPORTED";constructor(repo){super(`hosted engine launch over SSH is not implemented (remote project ${repo})`);this.repo=repo;this.name="RemoteEngineLaunchError"}}function buildEngineSessionLaunch(input){let remoteKey=remoteKeyForRepo(input.task.repo)??remoteKeyForRepo(input.worktreePath);if(remoteKey)throw new RemoteEngineLaunchError(remoteKey);let protocolTaskId=input.task.kind==="main"?void 0:input.task.id,dispatcherTaskId=input.task.kind==="main"?input.task.id:void 0,gates=input.protocolGates,launchInit=resolveEngineLaunchInit(input.task.repo??"",input.worktreePath,input.promptIntent),notes=protocolTaskId?(input.readNotes??readFieldNotes)(input.task.repo??""):[],argv=withDispatcherProtocol(withWorktreeProtocol(input.argv,input.task.vendor,protocolTaskId,{status:gates?.status,notes:gates?.notes},notes),input.task.vendor,dispatcherTaskId,gates?.dispatcher),pasteFirstMessage=(input.firstMessageDelivery??protocolEntry(input.task.vendor).firstMessageDelivery??"argv")==="paste"?launchInit.firstMessage?.text:void 0;if(launchInit.firstMessage&&!pasteFirstMessage)argv=[...argv,launchInit.firstMessage.text];let markerPath=launchInit.initScript?worktreeInitMarkerPath(input.worktreePath):void 0,initTimeoutMs=resolveRepoInitTimeoutSeconds(input.initTimeoutSeconds)*1000,script=engineLaunchLine(quoteShellArgv(argv,{bareSafe:!0}),{initScript:launchInit.initScript,markerPath,timeoutSeconds:input.initTimeoutSeconds}),taskId=quoteShellArg(input.task.id),tabId=quoteShellArg(input.tabId??"tab-1"),identity=`export ROVE_TASK_ID=${taskId} KOBE_TASK_ID=${taskId} ROVE_TAB_ID=${tabId} KOBE_TAB_ID=${tabId}
|
|
12
|
-
`;return{key:engineSessionKey(input.task.id,input.tabId),command:[input.shell,"-ilc",identity+script],...pasteFirstMessage?{firstMessage:pasteFirstMessage}:{},...markerPath?{initMarkerPath:markerPath,initTimeoutMs}:{}}}import{basename}from"path";var PASTE_READY_TIMEOUT_MS=15000,PASTE_READY_POLL_MS=100;function bracketedPasteActive(output){let on=output.lastIndexOf("\x1B[?2004h");if(on===-1)return!1;return on>output.lastIndexOf("\x1B[?2004l")}function encodePaste(prompt,bracketed){return bracketed?`\x1B[200~${prompt}\x1B[201~`:prompt}async function connectHostedSessionClient(socketPath){let client=new KobeDaemonClient(socketPath);try{await client.connect()}catch(error){throw client.close(),error}return{rpc:client,close:()=>client.close()}}async function openHostedSessionHost(){try{return await connectHostedSessionClient(defaultPtyHostSocketPath())}catch{return null}}async function ensureHostedSessionHost(){return connectHostedSessionClient(await ensurePtyHostReachable())}async function listHostedSessionsOrNull(rpc){try{let{sessions}=await rpc.request("pty.list",{});return sessions??[]}catch{return null}}async function listHostedSessions(rpc){return await listHostedSessionsOrNull(rpc)??[]}function isHostedTaskKey(key,taskId){return(key.split("::")[0]??key)===taskId}function hostedTaskKeys(sessions,taskId){return sessions.filter((session)=>isHostedTaskKey(session.key,taskId)).map((session)=>session.key)}async function killHostedSessions(rpc,keys){for(let key of keys)await rpc.request("pty.kill",{key}).catch(()=>{})}function commandHasEngineWord(command,engineBin){for(let part of command)for(let token of part.split(/\s+/)){let bare=token.replace(/^['"]+|['"]+$/g,"");if(bare&&basename(bare)===engineBin)return!0}return!1}function builtinEngineBins(){return BUILTIN_VENDORS.flatMap((vendor)=>{let entry=engineEntry(vendor);return[entry.defaultCommand[0],...entry.processNames??[]]}).filter((bin)=>Boolean(bin))}function sessionArgvNamesEngine(command,engineBin){if(!command||command.length===0)return!1;if(engineBin&&commandHasEngineWord(command,engineBin))return!0;return builtinEngineBins().some((bin)=>commandHasEngineWord(command,bin))}function tabOrder(key){let n=Number(/tab-(\d+)$/.exec(key)?.[1]);return Number.isFinite(n)?n:Number.POSITIVE_INFINITY}function findHostedEngineKey(sessions,taskId,engineBin){let mine=sessions.filter((s)=>s.alive&&isHostedTaskKey(s.key,taskId)).sort((a,b)=>tabOrder(a.key)-tabOrder(b.key)),tab1=mine.find((s)=>s.key===`${taskId}::tab-1`);if(tab1)return tab1.key;if(engineBin){let byCommand=mine.find((s)=>commandHasEngineWord(s.command,engineBin));if(byCommand)return byCommand.key}return mine.find((s)=>sessionArgvNamesEngine(s.command))?.key??null}var SUBMIT_DELAY_MS=150,CONFIRM_TAIL_CHARS=24,CONFIRM_TIMEOUT_MS=2000,CONFIRM_POLL_MS=100;function flatten(text){return text.replace(/\s+/g," ")}async function confirmPromptLanded(rpc,key,prompt,sinceOffset){let tail=flatten(prompt).trim().slice(-CONFIRM_TAIL_CHARS);if(tail.length===0)return!1;let deadline=Date.now()+CONFIRM_TIMEOUT_MS;for(;;){let peek=await rpc.request("pty.peek",{key,sinceOffset});if(!peek.alive)return!1;if(flatten(Buffer.from(peek.data,"base64").toString("utf8")).includes(tail))return!0;if(Date.now()>=deadline)return!1;await new Promise((resolve)=>setTimeout(resolve,CONFIRM_POLL_MS))}}async function writeAndConfirm(rpc,key,prompt,sinceOffset,opts){let ready=await awaitPasteReady(rpc,key,{timeoutMs:opts?.pasteReadyTimeoutMs}),bytes=await writeHostedPrompt(rpc,key,prompt,{ready}),confirmed=await confirmPromptLanded(rpc,key,prompt,sinceOffset);return{bytes,ready,confirmed}}async function writeHostedPromptIfLive(rpc,key,prompt,opts){let peek=await rpc.request("pty.peek",{key});if(!peek.alive)return null;return writeAndConfirm(rpc,key,prompt,peek.offset,opts)}async function awaitPasteReady(rpc,key,opts={}){let sleep=opts.sleep??((ms)=>new Promise((resolve)=>setTimeout(resolve,ms))),deadline=Date.now()+(opts.timeoutMs??PASTE_READY_TIMEOUT_MS);for(;;){let peek=await rpc.request("pty.peek",{key});if(!peek.alive)return!1;if(bracketedPasteActive(Buffer.from(peek.data,"base64").toString("latin1")))return!0;if(Date.now()>=deadline)return!1;await sleep(PASTE_READY_POLL_MS)}}async function writeHostedPrompt(rpc,key,prompt,opts){let bracketed=opts?.ready??await awaitPasteReady(rpc,key),data=encodePaste(prompt,bracketed);
|
|
12
|
+
`;return{key:engineSessionKey(input.task.id,input.tabId),command:[input.shell,"-ilc",identity+script],...pasteFirstMessage?{firstMessage:pasteFirstMessage}:{},...markerPath?{initMarkerPath:markerPath,initTimeoutMs}:{}}}import{basename}from"path";var PASTE_READY_TIMEOUT_MS=15000,PASTE_READY_POLL_MS=100;function bracketedPasteActive(output){let on=output.lastIndexOf("\x1B[?2004h");if(on===-1)return!1;return on>output.lastIndexOf("\x1B[?2004l")}var QUEUE_HINT=/tab to queue message/i;function queueHintVisible(output){return QUEUE_HINT.test(output.replace(/\s+/g," "))}function submitKeyFor(output){return queueHintVisible(output)?"\t":"\r"}function encodePaste(prompt,bracketed){return bracketed?`\x1B[200~${prompt}\x1B[201~`:prompt}async function connectHostedSessionClient(socketPath){let client=new KobeDaemonClient(socketPath);try{await client.connect()}catch(error){throw client.close(),error}return{rpc:client,close:()=>client.close()}}async function openHostedSessionHost(){try{return await connectHostedSessionClient(defaultPtyHostSocketPath())}catch{return null}}async function ensureHostedSessionHost(){return connectHostedSessionClient(await ensurePtyHostReachable())}async function listHostedSessionsOrNull(rpc){try{let{sessions}=await rpc.request("pty.list",{});return sessions??[]}catch{return null}}async function listHostedSessions(rpc){return await listHostedSessionsOrNull(rpc)??[]}function isHostedTaskKey(key,taskId){return(key.split("::")[0]??key)===taskId}function hostedTaskKeys(sessions,taskId){return sessions.filter((session)=>isHostedTaskKey(session.key,taskId)).map((session)=>session.key)}async function killHostedSessions(rpc,keys){for(let key of keys)await rpc.request("pty.kill",{key}).catch(()=>{})}function commandHasEngineWord(command,engineBin){for(let part of command)for(let token of part.split(/\s+/)){let bare=token.replace(/^['"]+|['"]+$/g,"");if(bare&&basename(bare)===engineBin)return!0}return!1}function builtinEngineBins(){return BUILTIN_VENDORS.flatMap((vendor)=>{let entry=engineEntry(vendor);return[entry.defaultCommand[0],...entry.processNames??[]]}).filter((bin)=>Boolean(bin))}function sessionArgvNamesEngine(command,engineBin){if(!command||command.length===0)return!1;if(engineBin&&commandHasEngineWord(command,engineBin))return!0;return builtinEngineBins().some((bin)=>commandHasEngineWord(command,bin))}function tabOrder(key){let n=Number(/tab-(\d+)$/.exec(key)?.[1]);return Number.isFinite(n)?n:Number.POSITIVE_INFINITY}function findHostedEngineKey(sessions,taskId,engineBin){let mine=sessions.filter((s)=>s.alive&&isHostedTaskKey(s.key,taskId)).sort((a,b)=>tabOrder(a.key)-tabOrder(b.key)),tab1=mine.find((s)=>s.key===`${taskId}::tab-1`);if(tab1)return tab1.key;if(engineBin){let byCommand=mine.find((s)=>commandHasEngineWord(s.command,engineBin));if(byCommand)return byCommand.key}return mine.find((s)=>sessionArgvNamesEngine(s.command))?.key??null}var SUBMIT_DELAY_MS=150,CONFIRM_TAIL_CHARS=24,CONFIRM_TIMEOUT_MS=2000,CONFIRM_POLL_MS=100;function flatten(text){return text.replace(/\s+/g," ")}async function confirmPromptLanded(rpc,key,prompt,sinceOffset){let tail=flatten(prompt).trim().slice(-CONFIRM_TAIL_CHARS);if(tail.length===0)return!1;let deadline=Date.now()+CONFIRM_TIMEOUT_MS;for(;;){let peek=await rpc.request("pty.peek",{key,sinceOffset});if(!peek.alive)return!1;if(flatten(Buffer.from(peek.data,"base64").toString("utf8")).includes(tail))return!0;if(Date.now()>=deadline)return!1;await new Promise((resolve)=>setTimeout(resolve,CONFIRM_POLL_MS))}}async function writeAndConfirm(rpc,key,prompt,sinceOffset,opts){let ready=await awaitPasteReady(rpc,key,{timeoutMs:opts?.pasteReadyTimeoutMs}),{bytes,queued}=await writeHostedPrompt(rpc,key,prompt,{ready}),confirmed=await confirmPromptLanded(rpc,key,prompt,sinceOffset);return{bytes,ready,confirmed,queued}}async function writeHostedPromptIfLive(rpc,key,prompt,opts){let peek=await rpc.request("pty.peek",{key});if(!peek.alive)return null;return writeAndConfirm(rpc,key,prompt,peek.offset,opts)}async function awaitPasteReady(rpc,key,opts={}){let sleep=opts.sleep??((ms)=>new Promise((resolve)=>setTimeout(resolve,ms))),deadline=Date.now()+(opts.timeoutMs??PASTE_READY_TIMEOUT_MS);for(;;){let peek=await rpc.request("pty.peek",{key});if(!peek.alive)return!1;if(bracketedPasteActive(Buffer.from(peek.data,"base64").toString("latin1")))return!0;if(Date.now()>=deadline)return!1;await sleep(PASTE_READY_POLL_MS)}}async function writeHostedPrompt(rpc,key,prompt,opts){let bracketed=opts?.ready??await awaitPasteReady(rpc,key),data=encodePaste(prompt,bracketed),before=await rpc.request("pty.peek",{key});await rpc.request("pty.write",{key,data}),await new Promise((resolve)=>setTimeout(resolve,SUBMIT_DELAY_MS));let submit=await submitKeyAfter(rpc,key,before.offset);if(await rpc.request("pty.write",{key,data:submit}),submit==="\r"){await new Promise((resolve)=>setTimeout(resolve,QUEUE_HINT_RECHECK_MS));let again=await submitKeyAfter(rpc,key,before.offset);if(again==="\t")await rpc.request("pty.write",{key,data:again}),submit=again}return{bytes:Buffer.byteLength(data,"utf8"),queued:submit==="\t"}}var QUEUE_HINT_RECHECK_MS=300;async function submitKeyAfter(rpc,key,sinceOffset){try{let peek=await rpc.request("pty.peek",{key,sinceOffset});return submitKeyFor(Buffer.from(peek.data,"base64").toString("utf8"))}catch{return"\r"}}var deliverToHostedKey=writeHostedPromptIfLive;async function ensureHostedEngine(rpc,cwd,launch,defaultColors=readPersistedTerminalDefaultColors()){let result=await rpc.request("pty.open",{key:launch.key,cwd,command:launch.command,defaultColors});return await rpc.request("pty.detach",{key:launch.key}).catch(()=>{}),result}var FIRST_MESSAGE_ENGINE_TIMEOUT_MS=20000,FIRST_MESSAGE_POLL_INTERVAL_MS=500,FIRST_MESSAGE_SETTLE_MS=1500;async function awaitEngineProcess(rpc,key,engineBin,opts={}){let sleep=opts.sleep??((ms)=>new Promise((resolve)=>setTimeout(resolve,ms))),snapshot=opts.snapshot;if(opts.initMarkerPath){let initDeadline=Date.now()+(opts.initTimeoutMs??REPO_INIT_TIMEOUT_SECONDS*1000);while(Date.now()<initDeadline){let{sessions=[]}=await rpc.request("pty.list",{});if(!sessions.find((s)=>s.key===key)?.alive)return null;if(initMarkerSaysFinished(opts.initMarkerPath))break;await sleep(opts.intervalMs??FIRST_MESSAGE_POLL_INTERVAL_MS)}}let deadline=Date.now()+(opts.timeoutMs??FIRST_MESSAGE_ENGINE_TIMEOUT_MS);while(Date.now()<deadline){let{sessions=[]}=await rpc.request("pty.list",{}),session=sessions.find((s)=>s.key===key);if(!session?.alive)return null;if(session.pid&&await sessionHasEngine(session.pid,engineBin,snapshot))return session.pid;await sleep(opts.intervalMs??FIRST_MESSAGE_POLL_INTERVAL_MS)}return null}async function hostedSessionFailureLine(rpc,key,limit=200){try{let peek=await rpc.request("pty.peek",{key}),lines=terminalRows(Buffer.from(peek.data,"base64").toString("utf8")).map((row)=>row.trim()).filter((row)=>row.length>0),line=lines.findLast((row)=>ENGINE_EXIT_BANNER.test(row))??lines.at(-1);return line===void 0?void 0:line.slice(0,limit)}catch{return}}async function pastePromptWhenEngineUp(rpc,key,engineBin,prompt,opts={}){let sleep=opts.sleep??((ms)=>new Promise((resolve)=>setTimeout(resolve,ms)));if(await awaitEngineProcess(rpc,key,engineBin,opts)!==null){if(!await awaitPasteReady(rpc,key,{timeoutMs:opts.pasteReadyTimeoutMs,sleep}))await sleep(opts.settleMs??FIRST_MESSAGE_SETTLE_MS);return await writeHostedPromptIfLive(rpc,key,prompt,opts)}return null}function trustEngineWorktree(vendor,worktreePath){try{protocolEntry(vendor).trustWorktree?.(worktreePath)}catch{}}
|
|
13
13
|
export{readPersistedTerminalDefaultColors,enginePresence,sessionHasEngine,AUTO_STATUS_KEY,autoStatusEnabled,DISPATCHER_KEY,initMarkerSaysFinished,buildEngineSessionLaunch,awaitEngineProcess,hostedSessionFailureLine,pastePromptWhenEngineUp,openHostedSessionHost,ensureHostedSessionHost,listHostedSessionsOrNull,listHostedSessions,isHostedTaskKey,hostedTaskKeys,killHostedSessions,sessionArgvNamesEngine,findHostedEngineKey,writeHostedPromptIfLive,deliverToHostedKey,ensureHostedEngine,trustEngineWorktree};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{ENGINE_NOT_OBSERVED_REASON,ENGINE_START_POLL_MS,ENGINE_START_PROBE_MS,deliverHostedPrompt,deliverToKey,ensurePtyHost,findEngineKey,isTaskKey,killTaskSessions,listSessions,listSessionsOrNull,openPtyHost,outcomeFields,taskKeys}from"./chunk-
|
|
2
|
+
import{ENGINE_NOT_OBSERVED_REASON,ENGINE_START_POLL_MS,ENGINE_START_PROBE_MS,deliverHostedPrompt,deliverToKey,ensurePtyHost,findEngineKey,isTaskKey,killTaskSessions,listSessions,listSessionsOrNull,openPtyHost,outcomeFields,taskKeys}from"./chunk-pnb48jrh.js";import"./chunk-847gwrx2.js";import"./chunk-d8hcpwr6.js";import"./chunk-rc0sqhdh.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import"./chunk-gsy8xfh6.js";import"./chunk-yrmj16b9.js";import"./chunk-rcyasw34.js";import"./chunk-7q67dz4c.js";import"./chunk-92d2t5sk.js";import"./chunk-hape5vwj.js";import"./chunk-wdrgfezn.js";import"./chunk-ptfe9a1h.js";import"./chunk-z7c6nap0.js";import"./chunk-bwrb6c2h.js";import"./chunk-qqh9aef5.js";import"./chunk-sdyzxayr.js";import"./chunk-b99tf0jr.js";import"./chunk-w25b7xxz.js";import"./chunk-jvxh93nz.js";import"./chunk-fczqwtmq.js";import"./chunk-te8g5azg.js";import"./chunk-y13681dw.js";import"./chunk-b5mbpv97.js";import"./chunk-re5ke4fz.js";import"./chunk-mnqxgvyb.js";import"./chunk-1jbznr12.js";import"./chunk-71k66b8f.js";import"./chunk-khj0apc7.js";import"./chunk-5zh5fcpe.js";import"./chunk-w7zv47mp.js";import"./chunk-pdnq8dbm.js";import"./chunk-7jkf3tvr.js";import"./chunk-7kysxgbq.js";import"./chunk-r9gfh1zz.js";import"./chunk-xy8be792.js";import"./chunk-ejqs2ta9.js";import"./chunk-3jh78dmc.js";import"./chunk-ddcxvbme.js";import"./chunk-2brn8e1y.js";import"./chunk-bq3fyc0p.js";import"./chunk-81p6mm0p.js";import"./chunk-q5jhy3t8.js";import"./chunk-t915by6w.js";import"./chunk-9prawccj.js";import"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-pxk2c2vj.js";import"./chunk-0q6h4vt4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import"./chunk-8cjr5ypt.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";export{taskKeys,outcomeFields,openPtyHost,listSessionsOrNull,listSessions,killTaskSessions,isTaskKey,findEngineKey,ensurePtyHost,deliverToKey,deliverHostedPrompt,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{SUBCOMMAND_VERBS,TOP_LEVEL_SUBCOMMANDS}from"./chunk-s76r56rj.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";async function collectSubVerbs(){let{API_VERBS}=await import("./chunk-
|
|
2
|
+
import{SUBCOMMAND_VERBS,TOP_LEVEL_SUBCOMMANDS}from"./chunk-s76r56rj.js";import{activeCliName}from"./chunk-00ehck55.js";import"./chunk-fxs82dsx.js";import"./chunk-sb0ns0c7.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";async function collectSubVerbs(){let{API_VERBS}=await import("./chunk-82p0wh0h.js"),merged={...SUBCOMMAND_VERBS,api:API_VERBS};return Object.keys(merged).sort().map((command)=>[command,merged[command]??[]])}function completionUsage(cliName){return[`Usage: ${cliName} completions <bash|zsh|fish>`,"",`Generate a shell completion script for ${cliName} and print it to stdout.`,"","Install:",` zsh source <(${cliName} completions zsh) # one-off, or in ~/.zshrc after compinit`," # or the fpath way:",` # ${cliName} completions zsh > ~/.zsh/completions/_${cliName}`," # fpath=(~/.zsh/completions $fpath) # in ~/.zshrc, BEFORE compinit"," # rm -f ~/.zcompdump && exec zsh # rebuild the completion cache",` bash ${cliName} completions bash > ~/.bash_completion.d/${cliName} # source it from ~/.bashrc`,` fish ${cliName} completions fish > ~/.config/fish/completions/${cliName}.fish`,""].join(`
|
|
3
3
|
`)}function generateBashCompletions(cliName,subVerbs){let subcommands=TOP_LEVEL_SUBCOMMANDS.join(" "),fn=`_${cliName}`;return[`# ${cliName} bash completions`,`# Source: ${cliName} completions bash`,"",`${fn}() {`," local cur prev"," COMPREPLY=()",' cur="${COMP_WORDS[COMP_CWORD]}"',' prev="${COMP_WORDS[COMP_CWORD-1]}"'," if [[ ${COMP_CWORD} -eq 1 ]]; then",` COMPREPLY=( $(compgen -W "${subcommands}" -- "\${cur}") )`," return"," fi"," if [[ ${COMP_CWORD} -eq 2 ]]; then",' case "${prev}" in',...subVerbs.map(([command,verbs])=>` ${command}) COMPREPLY=( $(compgen -W "${verbs.join(" ")}" -- "\${cur}") ) ;;`)," esac"," fi","}",`complete -F ${fn} ${cliName}`,""].join(`
|
|
4
4
|
`)}function generateZshCompletions(cliName,subVerbs){let subcommandsList=TOP_LEVEL_SUBCOMMANDS.map((s)=>`"${s}"`).join(" "),fn=`_${cliName}`;return[`#compdef ${cliName}`,`# ${cliName} zsh completions`,`# Source: ${cliName} completions zsh`,"",`${fn}() {`," local -a subcommands verbs",` subcommands=(${subcommandsList})`,""," if (( CURRENT == 2 )); then"," _describe -t commands 'subcommand' subcommands"," return"," fi",""," verbs=()",' case "${words[2]}" in',...subVerbs.map(([command,verbs])=>` ${command}) verbs=(${verbs.map((v)=>`"${v}"`).join(" ")}) ;;`)," esac"," if (( CURRENT == 3 && ${#verbs} > 0 )); then"," _describe -t verbs 'verb' verbs"," fi","}","","# Autoloaded from $fpath -> run as the completion function;","# sourced directly -> register with compdef instead.",`if [ "\${funcstack[1]}" = "${fn}" ]; then`,` ${fn} "$@"`,"elif (( $+functions[compdef] )); then",` compdef ${fn} ${cliName}`,"fi",""].join(`
|
|
5
5
|
`)}function generateFishCompletions(cliName,subVerbs){let lines=[...TOP_LEVEL_SUBCOMMANDS.map((s)=>`complete -c ${cliName} -f -n __fish_use_subcommand -a ${s}`),...subVerbs.map(([command,verbs])=>`complete -c ${cliName} -f -n "__fish_seen_subcommand_from ${command}" -a "${verbs.join(" ")}"`)];return`# ${cliName} fish completions
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{deriveTitleFromPrompt}from"./chunk-xb9b93ts.js";import{TaskDeletingError}from"./chunk-
|
|
2
|
+
import{deriveTitleFromPrompt}from"./chunk-xb9b93ts.js";import{TaskDeletingError}from"./chunk-vhq2dhx2.js";import{awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp,sessionHasEngine,trustEngineWorktree}from"./chunk-d8hcpwr6.js";import{engineLaunchArgv,protocolEntry}from"./chunk-yrmj16b9.js";import{resolveLoginShell}from"./chunk-b99tf0jr.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;if(!await sessionHasEngine(sessions.find((s)=>s.key===key)?.pid,engineArgv))return!1;return await deliverToHostedKey(host.rpc,key,prompt)!==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"};if(!await sessionHasEngine(sessions.find((s)=>s.key===key)?.pid,engineArgv))return{outcome:"no-engine",tabId:tabIdFromHostedKey(key)};return await deliverToHostedKey(host.rpc,key,prompt)===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});if(!await sessionHasEngine(session.pid,engineArgv))return{outcome:"no-engine",tabId:target.tabId};return await deliverToHostedKey(host.rpc,key,prompt)===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
3
|
export{deriveTitleFromSession,deriveTitleFromSessionId,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,tearDownTaskSessionAdapter};
|