@sma1lboy/rove 0.9.162 → 0.9.164

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/cli/{chunk-0wnfq5sx.js → chunk-0gepyh6e.js} +1 -1
  2. package/dist/cli/{chunk-8z7gz4pp.js → chunk-1t4tsfrz.js} +1 -1
  3. package/dist/cli/{chunk-wzdrq5es.js → chunk-275h7b12.js} +1 -1
  4. package/dist/cli/chunk-27jrtp2v.js +2 -0
  5. package/dist/cli/{chunk-1x5wrm14.js → chunk-2fjr0ajp.js} +1 -1
  6. package/dist/cli/{chunk-hfh1wgtr.js → chunk-2jt0tbte.js} +1 -1
  7. package/dist/cli/{chunk-ykrvv6bc.js → chunk-3try2twp.js} +1 -1
  8. package/dist/cli/chunk-4ba5m3ek.js +2 -0
  9. package/dist/cli/chunk-4rabzw5d.js +3 -0
  10. package/dist/cli/{chunk-eezk0g2q.js → chunk-4ysscdvr.js} +1 -1
  11. package/dist/cli/{chunk-mqs1qvc6.js → chunk-5bbh53hr.js} +1 -1
  12. package/dist/cli/{chunk-zf45ap00.js → chunk-5ekr8x6h.js} +1 -1
  13. package/dist/cli/{chunk-rqwx8wqx.js → chunk-655y4wyd.js} +1 -1
  14. package/dist/cli/{chunk-6zvw1wp6.js → chunk-6tfx7mra.js} +1 -1
  15. package/dist/cli/chunk-6wfwskxn.js +4 -0
  16. package/dist/cli/chunk-6wpege0h.js +3 -0
  17. package/dist/cli/chunk-7mrh2js6.js +3 -0
  18. package/dist/cli/{chunk-zwaf2mzz.js → chunk-863fpykn.js} +1 -1
  19. package/dist/cli/chunk-8wv8526c.js +3 -0
  20. package/dist/cli/chunk-9kefy6ev.js +3 -0
  21. package/dist/cli/chunk-9qrvqm44.js +2 -0
  22. package/dist/cli/{chunk-qrry2qvw.js → chunk-a5e8vwvn.js} +2 -2
  23. package/dist/cli/{chunk-cjfc4hj1.js → chunk-am3ajdfk.js} +2 -2
  24. package/dist/cli/{chunk-3bcx9dyb.js → chunk-b0f0jdnb.js} +1 -1
  25. package/dist/cli/chunk-bfpvywwr.js +2 -0
  26. package/dist/cli/{chunk-7j5372wb.js → chunk-bkvr06xn.js} +2 -2
  27. package/dist/cli/{chunk-kadvep6x.js → chunk-btzh874z.js} +1 -1
  28. package/dist/cli/{chunk-g8725q49.js → chunk-bxqbw3h4.js} +1 -1
  29. package/dist/cli/{chunk-07m61r5j.js → chunk-crdag2rc.js} +3 -3
  30. package/dist/cli/{chunk-ffj7jp3k.js → chunk-cwnwj3r8.js} +1 -1
  31. package/dist/cli/{chunk-bpkg51p5.js → chunk-da9tb8av.js} +2 -2
  32. package/dist/cli/{chunk-3pwsrf4f.js → chunk-drtwnf0e.js} +1 -1
  33. package/dist/cli/chunk-dx8bkger.js +2 -0
  34. package/dist/cli/{chunk-ftpbjbg9.js → chunk-edeh4d1v.js} +1 -1
  35. package/dist/cli/{chunk-br3yby3b.js → chunk-eet4fa7h.js} +1 -1
  36. package/dist/cli/chunk-ejwcy1zp.js +7 -0
  37. package/dist/cli/chunk-etnnwbdx.js +4 -0
  38. package/dist/cli/{chunk-n55jst34.js → chunk-gfckvx2p.js} +1 -1
  39. package/dist/cli/chunk-gs9hmb43.js +2 -0
  40. package/dist/cli/{chunk-xcgb5q15.js → chunk-h8m37225.js} +1 -1
  41. package/dist/cli/{chunk-2840nxj7.js → chunk-h9mqdxvs.js} +1 -1
  42. package/dist/cli/{chunk-q0s362r7.js → chunk-hnesjhs0.js} +2 -2
  43. package/dist/cli/{chunk-x5g5rjtn.js → chunk-j3grc9ck.js} +3 -3
  44. package/dist/cli/{chunk-h7zbtt85.js → chunk-jezc63b6.js} +1 -1
  45. package/dist/cli/{chunk-gwcneg6c.js → chunk-khj0apc7.js} +1 -1
  46. package/dist/cli/{chunk-932ymm0m.js → chunk-kn3pgymw.js} +1 -1
  47. package/dist/cli/{chunk-4wswdvzj.js → chunk-kwm5x2qr.js} +1 -1
  48. package/dist/cli/{chunk-ww0rwg80.js → chunk-m4a7bram.js} +1 -1
  49. package/dist/cli/{chunk-p2s4hv7y.js → chunk-m4j20c64.js} +1 -1
  50. package/dist/cli/{chunk-epjh74m5.js → chunk-mbb0pp66.js} +4 -4
  51. package/dist/cli/{chunk-b3pxf5xd.js → chunk-me23en52.js} +1 -1
  52. package/dist/cli/chunk-mmg7m9x2.js +2 -0
  53. package/dist/cli/{chunk-ewp7xthp.js → chunk-n0evh5xh.js} +1 -1
  54. package/dist/cli/{chunk-2pezpj5y.js → chunk-nqp6pnvf.js} +1 -1
  55. package/dist/cli/{chunk-q6c30g0b.js → chunk-nrafk2b7.js} +1 -1
  56. package/dist/cli/{chunk-9esrwvqc.js → chunk-nzscq4yf.js} +1 -1
  57. package/dist/cli/{chunk-zd3wmj4d.js → chunk-p57f5fhw.js} +1 -1
  58. package/dist/cli/{chunk-tj1tjdvd.js → chunk-p5vdvv2s.js} +1 -1
  59. package/dist/cli/chunk-px3r9sh6.js +2 -0
  60. package/dist/cli/chunk-pxk2c2vj.js +4 -0
  61. package/dist/cli/{chunk-n7rhhjta.js → chunk-q4428qws.js} +1 -1
  62. package/dist/cli/chunk-qqxw72nh.js +8 -0
  63. package/dist/cli/{chunk-5ks91n60.js → chunk-r2mhx7ry.js} +2 -2
  64. package/dist/cli/{chunk-6ndddtg5.js → chunk-r3903ysy.js} +1 -1
  65. package/dist/cli/{chunk-0e04wrvh.js → chunk-rd8nrxk3.js} +1 -1
  66. package/dist/cli/{chunk-dx4xyegr.js → chunk-rhsvvdcn.js} +1 -1
  67. package/dist/cli/{chunk-8g4xwg93.js → chunk-rsf1j5da.js} +1 -1
  68. package/dist/cli/{chunk-nwe9c7x6.js → chunk-rvybphrq.js} +1 -1
  69. package/dist/cli/chunk-sd4f9che.js +16 -0
  70. package/dist/cli/{chunk-ytkx5h87.js → chunk-syxg74zr.js} +1 -1
  71. package/dist/cli/{chunk-ewj2egvk.js → chunk-td22n31y.js} +10 -7
  72. package/dist/cli/chunk-th72hnqe.js +9 -0
  73. package/dist/cli/chunk-vhhzk3xj.js +3 -0
  74. package/dist/cli/{chunk-k43kf7qa.js → chunk-vhrfe63r.js} +1 -1
  75. package/dist/cli/chunk-w25b7xxz.js +7 -0
  76. package/dist/cli/chunk-x2nxvy0s.js +2 -0
  77. package/dist/cli/chunk-xhb03ybc.js +3 -0
  78. package/dist/cli/{chunk-pktxzp2v.js → chunk-yamxckqr.js} +1 -1
  79. package/dist/cli/{chunk-gvm4ss24.js → chunk-ym78sw9a.js} +1 -1
  80. package/dist/cli/{chunk-8djkntnp.js → chunk-yq821ndn.js} +1 -1
  81. package/dist/cli/{chunk-632q2pg7.js → chunk-zfqm8rmp.js} +1 -1
  82. package/dist/cli/{chunk-y9xr3c66.js → chunk-zg3wezj6.js} +1 -1
  83. package/dist/cli/{chunk-0f6hf3bv.js → chunk-zhbws9n3.js} +1 -1
  84. package/dist/cli/index.js +7 -7
  85. package/dist/cli/kobe.js +1 -1
  86. package/dist/cli/pty-host-node.mjs +16 -4
  87. package/dist/cli/rove.js +1 -1
  88. package/package.json +1 -1
  89. package/dist/cli/chunk-13mw2v47.js +0 -2
  90. package/dist/cli/chunk-1kz2syvp.js +0 -3
  91. package/dist/cli/chunk-29xgqs7n.js +0 -16
  92. package/dist/cli/chunk-2ra4990w.js +0 -2
  93. package/dist/cli/chunk-3ye9er38.js +0 -2
  94. package/dist/cli/chunk-5h3bhg45.js +0 -3
  95. package/dist/cli/chunk-6b8zqcpq.js +0 -2
  96. package/dist/cli/chunk-7027e3rb.js +0 -4
  97. package/dist/cli/chunk-7fedb3me.js +0 -2
  98. package/dist/cli/chunk-abpzjm1b.js +0 -2
  99. package/dist/cli/chunk-gyc4fj15.js +0 -3
  100. package/dist/cli/chunk-n1r2qzvw.js +0 -9
  101. package/dist/cli/chunk-nyv7a76k.js +0 -3
  102. package/dist/cli/chunk-ptj9ng0t.js +0 -2
  103. package/dist/cli/chunk-qwsn05zz.js +0 -3
  104. package/dist/cli/chunk-r05r01nv.js +0 -3
  105. package/dist/cli/chunk-rxvbm4vt.js +0 -7
  106. package/dist/cli/chunk-s6mcrm5g.js +0 -2
  107. package/dist/cli/chunk-sx8fw2qd.js +0 -4
  108. package/dist/cli/chunk-ttd78mrr.js +0 -3
  109. package/dist/cli/chunk-xwtqz55p.js +0 -7
  110. package/dist/cli/chunk-ycdeav89.js +0 -2
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{BLOCKING_RPCS,frameToLine}from"./chunk-7j5372wb.js";import{logClientError}from"./chunk-k2ckx8zw.js";import{readRoveEnv}from"./chunk-r3k9rbwm.js";import{connect}from"net";import{StringDecoder}from"string_decoder";class RpcTimeoutError extends Error{constructor(name,timeoutMs){super(`daemon rpc "${name}" timed out after ${timeoutMs}ms (daemon wedged?)`);this.name="RpcTimeoutError"}}function rpcTimeoutMs(){let raw=readRoveEnv("RPC_TIMEOUT_MS")?.trim();if(raw){let parsed=Number.parseInt(raw,10);if(Number.isFinite(parsed))return parsed}return 20000}class KobeDaemonClient{socketPath;socket=null;buffer="";nextId=1;pending=new Map;handlers=new Map;lifecycleHandlers=new Map;connecting=null;disposed=!1;constructor(socketPath){this.socketPath=socketPath}connect(){if(this.socket)return Promise.resolve();if(this.disposed)return Promise.reject(Error("daemon client disposed"));if(this.connecting)return this.connecting;let p=this.openSocket();this.connecting=p;let cleanup=()=>{if(this.connecting===p)this.connecting=null};return p.then(cleanup,cleanup),p}get isDisposed(){return this.disposed}close(){this.disposed=!0,this.socket?.end(),this.socket=null,this.failPending()}forceDisconnect(){let socket=this.socket;if(!socket)return;this.socket=null,socket.destroy(),this.failPending()}failPending(){if(this.pending.size===0)return;let err=Error("daemon connection closed");for(let pending of this.pending.values()){if(pending.timer)clearTimeout(pending.timer);pending.reject(err)}this.pending.clear()}on(name,handler){let set=this.handlers.get(name);if(!set)set=new Set,this.handlers.set(name,set);return set.add(handler),()=>{if(set?.delete(handler),set?.size===0)this.handlers.delete(name)}}onChannel(channel,handler){return this.on(channel,(frame)=>handler(frame.payload))}subscribe(opts={}){let payload={};if(opts.channels)payload.channels=opts.channels;if(opts.role)payload.role=opts.role;return this.request("subscribe",payload)}onLifecycle(name,handler){let set=this.lifecycleHandlers.get(name);if(!set)set=new Set,this.lifecycleHandlers.set(name,set);return set.add(handler),()=>{if(set?.delete(handler),set?.size===0)this.lifecycleHandlers.delete(name)}}async request(name,payload){await this.connect();let socket=this.socket;if(!socket)throw Error("daemon connection is not open");let id=String(this.nextId++),promise=new Promise((resolve,reject)=>{let entry={resolve:(value)=>resolve(value),reject},timeoutMs=rpcTimeoutMs();if(timeoutMs>0&&!BLOCKING_RPCS.has(name))entry.timer=setTimeout(()=>this.onRequestTimeout(id,name,timeoutMs),timeoutMs);this.pending.set(id,entry)});return socket.write(frameToLine({type:"request",id,name,payload})),promise}onRequestTimeout(id,name,timeoutMs){let pending=this.pending.get(id);if(!pending)return;this.pending.delete(id),pending.reject(new RpcTimeoutError(name,timeoutMs)),this.forceDisconnect(),this.emitLifecycle("close")}openSocket(){return new Promise((resolve,reject)=>{let socket=connect(this.socketPath);this.socket=socket;let onConnect=()=>{socket.off("error",onError),socket.on("error",()=>socket.destroy()),resolve()},onError=(err)=>{if(socket.off("connect",onConnect),this.socket===socket)this.socket=null;reject(err)};socket.once("connect",onConnect),socket.once("error",onError);let decoder=new StringDecoder("utf8");this.buffer="",socket.on("data",(chunk)=>this.onData(decoder.write(chunk))),socket.on("close",()=>this.onSocketClose(socket))})}onSocketClose(which){if(this.socket!==which)return;this.socket=null,this.failPending(),this.emitLifecycle("close")}emitLifecycle(name){for(let handler of this.lifecycleHandlers.get(name)??[])try{handler()}catch(err){console.error(`[rove] lifecycle handler for "${name}" threw:`,err)}}onData(chunk){this.buffer+=chunk;let nl=this.buffer.indexOf(`
2
+ import{BLOCKING_RPCS,frameToLine}from"./chunk-bkvr06xn.js";import{logClientError}from"./chunk-k2ckx8zw.js";import{readRoveEnv}from"./chunk-r3k9rbwm.js";import{connect}from"net";import{StringDecoder}from"string_decoder";class RpcTimeoutError extends Error{constructor(name,timeoutMs){super(`daemon rpc "${name}" timed out after ${timeoutMs}ms (daemon wedged?)`);this.name="RpcTimeoutError"}}function rpcTimeoutMs(){let raw=readRoveEnv("RPC_TIMEOUT_MS")?.trim();if(raw){let parsed=Number.parseInt(raw,10);if(Number.isFinite(parsed))return parsed}return 20000}class KobeDaemonClient{socketPath;socket=null;buffer="";nextId=1;pending=new Map;handlers=new Map;lifecycleHandlers=new Map;connecting=null;disposed=!1;constructor(socketPath){this.socketPath=socketPath}connect(){if(this.socket)return Promise.resolve();if(this.disposed)return Promise.reject(Error("daemon client disposed"));if(this.connecting)return this.connecting;let p=this.openSocket();this.connecting=p;let cleanup=()=>{if(this.connecting===p)this.connecting=null};return p.then(cleanup,cleanup),p}get isDisposed(){return this.disposed}close(){this.disposed=!0,this.socket?.end(),this.socket=null,this.failPending()}forceDisconnect(){let socket=this.socket;if(!socket)return;this.socket=null,socket.destroy(),this.failPending()}failPending(){if(this.pending.size===0)return;let err=Error("daemon connection closed");for(let pending of this.pending.values()){if(pending.timer)clearTimeout(pending.timer);pending.reject(err)}this.pending.clear()}on(name,handler){let set=this.handlers.get(name);if(!set)set=new Set,this.handlers.set(name,set);return set.add(handler),()=>{if(set?.delete(handler),set?.size===0)this.handlers.delete(name)}}onChannel(channel,handler){return this.on(channel,(frame)=>handler(frame.payload))}subscribe(opts={}){let payload={};if(opts.channels)payload.channels=opts.channels;if(opts.role)payload.role=opts.role;return this.request("subscribe",payload)}onLifecycle(name,handler){let set=this.lifecycleHandlers.get(name);if(!set)set=new Set,this.lifecycleHandlers.set(name,set);return set.add(handler),()=>{if(set?.delete(handler),set?.size===0)this.lifecycleHandlers.delete(name)}}async request(name,payload){await this.connect();let socket=this.socket;if(!socket)throw Error("daemon connection is not open");let id=String(this.nextId++),promise=new Promise((resolve,reject)=>{let entry={resolve:(value)=>resolve(value),reject},timeoutMs=rpcTimeoutMs();if(timeoutMs>0&&!BLOCKING_RPCS.has(name))entry.timer=setTimeout(()=>this.onRequestTimeout(id,name,timeoutMs),timeoutMs);this.pending.set(id,entry)});return socket.write(frameToLine({type:"request",id,name,payload})),promise}onRequestTimeout(id,name,timeoutMs){let pending=this.pending.get(id);if(!pending)return;this.pending.delete(id),pending.reject(new RpcTimeoutError(name,timeoutMs)),this.forceDisconnect(),this.emitLifecycle("close")}openSocket(){return new Promise((resolve,reject)=>{let socket=connect(this.socketPath);this.socket=socket;let onConnect=()=>{socket.off("error",onError),socket.on("error",()=>socket.destroy()),resolve()},onError=(err)=>{if(socket.off("connect",onConnect),this.socket===socket)this.socket=null;reject(err)};socket.once("connect",onConnect),socket.once("error",onError);let decoder=new StringDecoder("utf8");this.buffer="",socket.on("data",(chunk)=>this.onData(decoder.write(chunk))),socket.on("close",()=>this.onSocketClose(socket))})}onSocketClose(which){if(this.socket!==which)return;this.socket=null,this.failPending(),this.emitLifecycle("close")}emitLifecycle(name){for(let handler of this.lifecycleHandlers.get(name)??[])try{handler()}catch(err){console.error(`[rove] lifecycle handler for "${name}" threw:`,err)}}onData(chunk){this.buffer+=chunk;let nl=this.buffer.indexOf(`
3
3
  `);while(nl!==-1){let line=this.buffer.slice(0,nl);if(this.buffer=this.buffer.slice(nl+1),line.trim().length>0)this.onLine(line);nl=this.buffer.indexOf(`
4
4
  `)}}onLine(line){let frame;try{frame=JSON.parse(line)}catch(err){logClientError("client-frame",err);return}if(frame.type==="event"){this.emit(frame);return}if(frame.type!=="response")return;let pending=this.pending.get(frame.id);if(!pending)return;if(this.pending.delete(frame.id),pending.timer)clearTimeout(pending.timer);if(frame.error){let err=Error(frame.error.message);if(frame.error.name)err.name=frame.error.name;pending.reject(err)}else pending.resolve(frame.payload)}emit(frame){for(let handler of this.handlers.get(frame.name)??[])try{handler(frame)}catch(err){logClientError("client-event",err)}for(let handler of this.handlers.get("*")??[])try{handler(frame)}catch(err){logClientError("client-event",err)}}}
5
5
  export{RpcTimeoutError,KobeDaemonClient};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{TaskDeletingError,deriveTitleFromPrompt}from"./chunk-r05r01nv.js";import{ComposerBusyError,awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp,sessionHasEngine,trustEngineWorktree}from"./chunk-epjh74m5.js";import{engineLaunchArgv,protocolEntry}from"./chunk-k43kf7qa.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{engineEntry}from"./chunk-07m61r5j.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;let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})!==null}catch(err){if(err instanceof ComposerBusyError)throw err;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)};let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:tabIdFromHostedKey(key)}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:tabIdFromHostedKey(key),layer:err.layer};throw err}}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};let manifest=target.vendor?engineEntry(target.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:target.tabId}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:target.tabId,layer:err.layer};throw err}}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()}}
2
+ import{TaskDeletingError,deriveTitleFromPrompt}from"./chunk-9kefy6ev.js";import{ComposerBusyError,awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp,sessionHasEngine,trustEngineWorktree}from"./chunk-mbb0pp66.js";import{engineLaunchArgv,protocolEntry}from"./chunk-vhrfe63r.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{engineEntry}from"./chunk-crdag2rc.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;let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})!==null}catch(err){if(err instanceof ComposerBusyError)throw err;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)};let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:tabIdFromHostedKey(key)}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:tabIdFromHostedKey(key),layer:err.layer};throw err}}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};let manifest=target.vendor?engineEntry(target.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:target.tabId}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:target.tabId,layer:err.layer};throw err}}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};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{GitWorktreeManager}from"./chunk-ffj7jp3k.js";import"./chunk-6xppe9bj.js";import"./chunk-b3pxf5xd.js";import"./chunk-5f80ggc3.js";import"./chunk-dx4xyegr.js";import"./chunk-bkba9c4n.js";import"./chunk-g2advs8t.js";import"./chunk-2fypr41w.js";import"./chunk-1kz2syvp.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-g56kvet6.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{GitWorktreeManager};
2
+ import{GitWorktreeManager}from"./chunk-cwnwj3r8.js";import"./chunk-6xppe9bj.js";import"./chunk-me23en52.js";import"./chunk-5f80ggc3.js";import"./chunk-rhsvvdcn.js";import"./chunk-bkba9c4n.js";import"./chunk-g2advs8t.js";import"./chunk-2fypr41w.js";import"./chunk-6wpege0h.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-g56kvet6.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{GitWorktreeManager};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{ENGINE_NOT_OBSERVED_REASON,ENGINE_START_POLL_MS,ENGINE_START_PROBE_MS,deferOrThrow,deliverHostedPrompt,deliverToKey,ensurePtyHost,findEngineKey,isTaskKey,killTaskSessions,listSessions,listSessionsOrNull,openPtyHost,outcomeFields,resolveComposerManifest,taskKeys}from"./chunk-7mrh2js6.js";import"./chunk-nrafk2b7.js";import"./chunk-mbb0pp66.js";import"./chunk-rhsvvdcn.js";import"./chunk-bkba9c4n.js";import"./chunk-g2advs8t.js";import"./chunk-zhbws9n3.js";import"./chunk-vhrfe63r.js";import"./chunk-rcyasw34.js";import"./chunk-b99tf0jr.js";import"./chunk-7q67dz4c.js";import"./chunk-h8m37225.js";import"./chunk-hape5vwj.js";import"./chunk-zg3wezj6.js";import"./chunk-ym78sw9a.js";import"./chunk-zqfbyq0a.js";import"./chunk-rvybphrq.js";import"./chunk-xhb03ybc.js";import"./chunk-sdyzxayr.js";import"./chunk-w25b7xxz.js";import"./chunk-jvxh93nz.js";import"./chunk-h9mqdxvs.js";import"./chunk-8wv8526c.js";import"./chunk-0gepyh6e.js";import"./chunk-bkvr06xn.js";import"./chunk-mnqxgvyb.js";import"./chunk-etnnwbdx.js";import"./chunk-crdag2rc.js";import"./chunk-khj0apc7.js";import"./chunk-nzscq4yf.js";import"./chunk-w7zv47mp.js";import"./chunk-6tvrvekq.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-k1qe5qqa.js";import"./chunk-xy8be792.js";import"./chunk-6wpege0h.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-2brn8e1y.js";import"./chunk-bq3fyc0p.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-v0zxyqrq.js";import"./chunk-e29hx18x.js";import"./chunk-g56kvet6.js";import"./chunk-pxk2c2vj.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{taskKeys,resolveComposerManifest,outcomeFields,openPtyHost,listSessionsOrNull,listSessions,killTaskSessions,isTaskKey,findEngineKey,ensurePtyHost,deliverToKey,deliverHostedPrompt,deferOrThrow,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{isDev}from"./chunk-ch9b1d5y.js";import{fileURLToPath}from"url";var package_default={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.162",description:"Rove \u2014 the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun test test/render --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage-render",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.19","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var CURRENT_VERSION=package_default.version,PACKAGE_NAME=package_default.name;function repoSlug(){let url=package_default.repository?.url;if(!url)return null;let m=url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);if(!m||!m[1]||!m[2])return null;return`${m[1]}/${m[2]}`}var UPDATE_SCRIPT_URL="https://raw.githubusercontent.com/Sma1lboy/rove/main/scripts/update.sh",UPDATE_COMMAND=`curl -fsSL ${UPDATE_SCRIPT_URL} | sh`;function owningNpmPrefix(modulePath=fileURLToPath(import.meta.url)){let at=modulePath.indexOf("/lib/node_modules/");if(at<=0)return null;return modulePath.slice(0,at)}function recommendedGlobalInstallCommand(prefix=owningNpmPrefix()){let target=`${PACKAGE_NAME}@latest`;return prefix===null?`npm install -g ${target}`:`npm install -g --prefix ${prefix} ${target}`}var BREAKING_VERSIONS=[];function breakingVersionsCrossed(from,to,breaking=BREAKING_VERSIONS){let[lo,hi]=compareSemver(from,to)<=0?[from,to]:[to,from];return breaking.filter((b)=>compareSemver(b,lo)>0&&compareSemver(b,hi)<=0)}var FETCH_TIMEOUT_MS=3000,RELEASE_CHANNELS=["latest","nightly"],DEFAULT_RELEASE_CHANNEL="latest";function channelOf(version=CURRENT_VERSION){return prereleaseOf(version)?.split(".")[0]==="nightly"?"nightly":DEFAULT_RELEASE_CHANNEL}async function fetchLatestFromRegistry(packageName,channel){let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let encoded=packageName.replace("/","%2F"),res=await fetch(`https://registry.npmjs.org/${encoded}/${channel}`,{signal:ctrl.signal,headers:{accept:"application/json"}});if(!res.ok)return null;let body=await res.json();if(typeof body.version!=="string")return null;return body.version}catch{return null}finally{clearTimeout(timer)}}function isNewerSemver(latest,current){let core=compareSemver(latest,current);if(core!==0)return core>0;return comparePrerelease(prereleaseOf(latest),prereleaseOf(current))>0}function prereleaseOf(version){let dash=version.indexOf("-");return dash===-1?void 0:version.slice(dash+1)||void 0}function comparePrerelease(a,b){if(a===b)return 0;if(a===void 0)return 1;if(b===void 0)return-1;let aParts=a.split("."),bParts=b.split(".");for(let i=0;i<Math.max(aParts.length,bParts.length);i++){let av=aParts[i],bv=bParts[i];if(av===void 0)return-1;if(bv===void 0)return 1;if(av===bv)continue;let an=/^\d+$/.test(av)?Number.parseInt(av,10):null,bn=/^\d+$/.test(bv)?Number.parseInt(bv,10):null;if(an!==null&&bn!==null)return an>bn?1:-1;if(an!==null)return-1;if(bn!==null)return 1;return av>bv?1:-1}return 0}function compareSemver(aVersion,bVersion){let norm=(v)=>v.split("-")[0]??v,a=norm(aVersion).split(".").map((s)=>Number.parseInt(s,10)),b=norm(bVersion).split(".").map((s)=>Number.parseInt(s,10));for(let i=0;i<3;i++){let av=a[i]??0,bv=b[i]??0;if(Number.isNaN(av)||Number.isNaN(bv))return 0;if(av>bv)return 1;if(av<bv)return-1}return 0}async function checkLatestVersion(opts={}){let channel=opts.channel??channelOf(),fake=process.env.KOBE_FAKE_UPDATE;if(fake)return{current:CURRENT_VERSION,latest:fake,hasUpdate:isNewerSemver(fake,CURRENT_VERSION),channel};if(isDev()&&!opts.force)return null;let latest=await fetchLatestFromRegistry(PACKAGE_NAME,channel);if(!latest)return null;return{current:CURRENT_VERSION,latest,hasUpdate:isNewerSemver(latest,CURRENT_VERSION),channel}}function versionFromTagName(tagName){if(typeof tagName!=="string")return null;return tagName.match(/^v(\d+\.\d+\.\d+)$/)?.[1]??null}async function fetchReleaseNotes(version){let slug=repoSlug();if(!slug)return null;let tag=`v${version}`,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases/tags/${tag}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return null;let body=await res.json();if(typeof body.body!=="string"||typeof body.html_url!=="string")return null;return{body:body.body,url:body.html_url,version}}catch{return null}finally{clearTimeout(timer)}}async function fetchReleaseNotesRange(args){let slug=repoSlug();if(!slug)return[];let limit=args.limit??100,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string"||typeof release.body!=="string")return null;if(compareSemver(version,args.current)<=0)return null;if(compareSemver(version,args.latest)>0)return null;return{version,url:release.html_url,body:release.body}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}async function fetchReleaseSummaries(limit=12){let slug=repoSlug();if(!slug)return[];let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string")return null;return{version,url:release.html_url}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}function releasePageUrl(version){let slug=repoSlug();if(!slug)return null;return`https://github.com/${slug}/releases/tag/v${version}`}
2
+ import{isDev}from"./chunk-ch9b1d5y.js";import{fileURLToPath}from"url";var package_default={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.164",description:"Rove \u2014 the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun test test/render --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage-render",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.19","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var CURRENT_VERSION=package_default.version,PACKAGE_NAME=package_default.name;function repoSlug(){let url=package_default.repository?.url;if(!url)return null;let m=url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);if(!m||!m[1]||!m[2])return null;return`${m[1]}/${m[2]}`}var UPDATE_SCRIPT_URL="https://raw.githubusercontent.com/Sma1lboy/rove/main/scripts/update.sh",UPDATE_COMMAND=`curl -fsSL ${UPDATE_SCRIPT_URL} | sh`;function owningNpmPrefix(modulePath=fileURLToPath(import.meta.url)){let at=modulePath.indexOf("/lib/node_modules/");if(at<=0)return null;return modulePath.slice(0,at)}function recommendedGlobalInstallCommand(prefix=owningNpmPrefix()){let target=`${PACKAGE_NAME}@latest`;return prefix===null?`npm install -g ${target}`:`npm install -g --prefix ${prefix} ${target}`}var BREAKING_VERSIONS=[];function breakingVersionsCrossed(from,to,breaking=BREAKING_VERSIONS){let[lo,hi]=compareSemver(from,to)<=0?[from,to]:[to,from];return breaking.filter((b)=>compareSemver(b,lo)>0&&compareSemver(b,hi)<=0)}var FETCH_TIMEOUT_MS=3000,RELEASE_CHANNELS=["latest","nightly"],DEFAULT_RELEASE_CHANNEL="latest";function channelOf(version=CURRENT_VERSION){return prereleaseOf(version)?.split(".")[0]==="nightly"?"nightly":DEFAULT_RELEASE_CHANNEL}async function fetchLatestFromRegistry(packageName,channel){let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let encoded=packageName.replace("/","%2F"),res=await fetch(`https://registry.npmjs.org/${encoded}/${channel}`,{signal:ctrl.signal,headers:{accept:"application/json"}});if(!res.ok)return null;let body=await res.json();if(typeof body.version!=="string")return null;return body.version}catch{return null}finally{clearTimeout(timer)}}function isNewerSemver(latest,current){let core=compareSemver(latest,current);if(core!==0)return core>0;return comparePrerelease(prereleaseOf(latest),prereleaseOf(current))>0}function prereleaseOf(version){let dash=version.indexOf("-");return dash===-1?void 0:version.slice(dash+1)||void 0}function comparePrerelease(a,b){if(a===b)return 0;if(a===void 0)return 1;if(b===void 0)return-1;let aParts=a.split("."),bParts=b.split(".");for(let i=0;i<Math.max(aParts.length,bParts.length);i++){let av=aParts[i],bv=bParts[i];if(av===void 0)return-1;if(bv===void 0)return 1;if(av===bv)continue;let an=/^\d+$/.test(av)?Number.parseInt(av,10):null,bn=/^\d+$/.test(bv)?Number.parseInt(bv,10):null;if(an!==null&&bn!==null)return an>bn?1:-1;if(an!==null)return-1;if(bn!==null)return 1;return av>bv?1:-1}return 0}function compareSemver(aVersion,bVersion){let norm=(v)=>v.split("-")[0]??v,a=norm(aVersion).split(".").map((s)=>Number.parseInt(s,10)),b=norm(bVersion).split(".").map((s)=>Number.parseInt(s,10));for(let i=0;i<3;i++){let av=a[i]??0,bv=b[i]??0;if(Number.isNaN(av)||Number.isNaN(bv))return 0;if(av>bv)return 1;if(av<bv)return-1}return 0}async function checkLatestVersion(opts={}){let channel=opts.channel??channelOf(),fake=process.env.KOBE_FAKE_UPDATE;if(fake)return{current:CURRENT_VERSION,latest:fake,hasUpdate:isNewerSemver(fake,CURRENT_VERSION),channel};if(isDev()&&!opts.force)return null;let latest=await fetchLatestFromRegistry(PACKAGE_NAME,channel);if(!latest)return null;return{current:CURRENT_VERSION,latest,hasUpdate:isNewerSemver(latest,CURRENT_VERSION),channel}}function versionFromTagName(tagName){if(typeof tagName!=="string")return null;return tagName.match(/^v(\d+\.\d+\.\d+)$/)?.[1]??null}async function fetchReleaseNotes(version){let slug=repoSlug();if(!slug)return null;let tag=`v${version}`,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases/tags/${tag}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return null;let body=await res.json();if(typeof body.body!=="string"||typeof body.html_url!=="string")return null;return{body:body.body,url:body.html_url,version}}catch{return null}finally{clearTimeout(timer)}}async function fetchReleaseNotesRange(args){let slug=repoSlug();if(!slug)return[];let limit=args.limit??100,ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string"||typeof release.body!=="string")return null;if(compareSemver(version,args.current)<=0)return null;if(compareSemver(version,args.latest)>0)return null;return{version,url:release.html_url,body:release.body}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}async function fetchReleaseSummaries(limit=12){let slug=repoSlug();if(!slug)return[];let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),FETCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/repos/${slug}/releases?per_page=${limit}`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});if(!res.ok)return[];let body=await res.json();if(!Array.isArray(body))return[];return body.map((release)=>{let version=versionFromTagName(release.tag_name);if(!version||typeof release.html_url!=="string")return null;return{version,url:release.html_url}}).filter((release)=>release!==null)}catch{return[]}finally{clearTimeout(timer)}}function releasePageUrl(version){let slug=repoSlug();if(!slug)return null;return`https://github.com/${slug}/releases/tag/v${version}`}
3
3
  export{package_default,CURRENT_VERSION,PACKAGE_NAME,repoSlug,UPDATE_SCRIPT_URL,UPDATE_COMMAND,owningNpmPrefix,recommendedGlobalInstallCommand,BREAKING_VERSIONS,breakingVersionsCrossed,RELEASE_CHANNELS,DEFAULT_RELEASE_CHANNEL,channelOf,isNewerSemver,compareSemver,checkLatestVersion,fetchReleaseNotes,fetchReleaseNotesRange,fetchReleaseSummaries,releasePageUrl};
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import{quoteShellArg}from"./chunk-2fypr41w.js";import{getPersistedString}from"./chunk-1kz2syvp.js";var EDITOR_KINDS=["auto","vim","nvim","nano","emacs","custom"],AUTO_EDITOR_CANDIDATES=["nvim","vim","emacs","nano"],EDITOR_KIND_KEY="editor.kind",EDITOR_CUSTOM_KEY="editor.customCommand",DEFAULT_EDITOR_KIND="auto";function normalizeEditorKind(value){return EDITOR_KINDS.includes(value)?value:"auto"}var FILE_PLACEHOLDER="{file}";function firstToken(cmd){return cmd.trim().split(/\s+/)[0]??""}function buildEditorCommand(kind,customCommand,absPath,envEditor){let file=quoteShellArg(absPath);if(kind==="vim")return{bin:"vim",command:`vim ${file}`};if(kind==="nvim")return{bin:"nvim",command:`nvim ${file}`};if(kind==="nano")return{bin:"nano",command:`nano ${file}`};if(kind==="emacs")return{bin:"emacs",command:`emacs ${file}`};let tmpl=(customCommand.trim()||(envEditor??"").trim()).trim();if(!tmpl)return null;let bin=firstToken(tmpl);if(!bin)return null;let command=tmpl.includes(FILE_PLACEHOLDER)?tmpl.split(FILE_PLACEHOLDER).join(file):`${tmpl} ${file}`;return{bin,command}}function buildNvimDiffCommand(bin,absPath,relPath){let file=quoteShellArg(absPath);return["f=$(mktemp 2>/dev/null)",`if [ -n "$f" ] && git show ${quoteShellArg(`HEAD:./${relPath}`)} > "$f" 2>/dev/null; then`,` ${bin} -d "$f" ${file} -c 'setlocal nomodifiable' -c 'wincmd l'; r=$?`,"else",` ${bin} ${file}; r=$?`,"fi",'rm -f "$f" 2>/dev/null; exit $r'].join(`
2
+ import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import{quoteShellArg}from"./chunk-2fypr41w.js";import{getPersistedString}from"./chunk-6wpege0h.js";var EDITOR_KINDS=["auto","vim","nvim","nano","emacs","custom"],AUTO_EDITOR_CANDIDATES=["nvim","vim","emacs","nano"],EDITOR_KIND_KEY="editor.kind",EDITOR_CUSTOM_KEY="editor.customCommand",DEFAULT_EDITOR_KIND="auto";function normalizeEditorKind(value){return EDITOR_KINDS.includes(value)?value:"auto"}var FILE_PLACEHOLDER="{file}";function firstToken(cmd){return cmd.trim().split(/\s+/)[0]??""}function buildEditorCommand(kind,customCommand,absPath,envEditor){let file=quoteShellArg(absPath);if(kind==="vim")return{bin:"vim",command:`vim ${file}`};if(kind==="nvim")return{bin:"nvim",command:`nvim ${file}`};if(kind==="nano")return{bin:"nano",command:`nano ${file}`};if(kind==="emacs")return{bin:"emacs",command:`emacs ${file}`};let tmpl=(customCommand.trim()||(envEditor??"").trim()).trim();if(!tmpl)return null;let bin=firstToken(tmpl);if(!bin)return null;let command=tmpl.includes(FILE_PLACEHOLDER)?tmpl.split(FILE_PLACEHOLDER).join(file):`${tmpl} ${file}`;return{bin,command}}function buildNvimDiffCommand(bin,absPath,relPath){let file=quoteShellArg(absPath);return["f=$(mktemp 2>/dev/null)",`if [ -n "$f" ] && git show ${quoteShellArg(`HEAD:./${relPath}`)} > "$f" 2>/dev/null; then`,` ${bin} -d "$f" ${file} -c 'setlocal nomodifiable' -c 'wincmd l'; r=$?`,"else",` ${bin} ${file}; r=$?`,"fi",'rm -f "$f" 2>/dev/null; exit $r'].join(`
3
3
  `)}function relativeToWorktree(worktree,absPath){let prefix=worktree.endsWith("/")?worktree:`${worktree}/`;return absPath.startsWith(prefix)?absPath.slice(prefix.length):null}async function resolveEditorCommand(absPath){let kind=normalizeEditorKind(getPersistedString(EDITOR_KIND_KEY)),custom=getPersistedString(EDITOR_CUSTOM_KEY)??"",env=(process.env.VISUAL??process.env.EDITOR??"").trim();if(kind!=="auto")return buildEditorCommand(kind,custom,absPath,env);if(env)return buildEditorCommand("custom","",absPath,env);let file=quoteShellArg(absPath);for(let bin of AUTO_EDITOR_CANDIDATES)if(await binaryAvailable(bin))return{bin,command:`${bin} ${file}`};return null}async function binaryAvailable(bin){try{return await Bun.spawn(["sh","-c",`command -v ${quoteShellArg(bin)} >/dev/null 2>&1`],{stdin:"ignore",stdout:"ignore",stderr:"ignore"}).exited===0}catch{return!1}}async function fileHasDiff(worktree,relPath){try{return await Bun.spawn(["git","diff","--quiet","HEAD","--",relPath],{cwd:worktree,stdin:"ignore",stdout:"ignore",stderr:"ignore",env:readOnlyGitProcessEnv()}).exited===1}catch{return!1}}async function resolveEditorLaunch(worktree,absPath){let resolved=await resolveEditorCommand(absPath);if(!resolved)return null;if(!await binaryAvailable(resolved.bin))return null;return{command:await maybeDiffCommand(resolved,worktree,absPath),label:editorWindowLabel(absPath)}}async function maybeDiffCommand(resolved,worktree,absPath){let{bin,command}=resolved;if(bin!=="nvim"&&bin!=="vim")return command;if(command!==`${bin} ${quoteShellArg(absPath)}`)return command;let rel=relativeToWorktree(worktree,absPath);if(!rel)return command;if(!await fileHasDiff(worktree,rel))return command;return buildNvimDiffCommand(bin,absPath,rel)}function editorWindowLabel(absPath){let base=absPath.slice(absPath.lastIndexOf("/")+1).trim();return base.length>0?base:"edit"}
4
4
  export{EDITOR_KINDS,EDITOR_KIND_KEY,EDITOR_CUSTOM_KEY,DEFAULT_EDITOR_KIND,normalizeEditorKind,resolveEditorCommand,binaryAvailable,resolveEditorLaunch};
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{installedSkillDirs}from"./chunk-bpkg51p5.js";import{CLAUDE_HOOK_EVENT_MAP,claudeSettingsPath,hasKobeActivityHooks,isObject}from"./chunk-6tvrvekq.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-1kz2syvp.js";import"./chunk-j75axe29.js";import"./chunk-k1qe5qqa.js";import"./chunk-xy8be792.js";import"./chunk-ayhhgfsz.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-bq3fyc0p.js";import"./chunk-mv7ptt5w.js";import"./chunk-v0zxyqrq.js";import"./chunk-e29hx18x.js";import"./chunk-g56kvet6.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";import{readFileSync}from"fs";import{homedir}from"os";var PLUGIN_NAME="rove";function readSettings(path){try{let parsed=JSON.parse(readFileSync(path,"utf8"));return isObject(parsed)?parsed:null}catch{return null}}function isRovePluginEnabled(settingsFilePath=claudeSettingsPath()){let settings=readSettings(settingsFilePath);if(!settings||!isObject(settings.enabledPlugins))return!1;return Object.entries(settings.enabledPlugins).some(([key,on])=>on===!0&&key.split("@")[0]===PLUGIN_NAME)}function detectLegacyInstalls(opts={}){let settingsFilePath=opts.settingsFilePath??claudeSettingsPath(),home=opts.home??homedir(),settings=readSettings(settingsFilePath),legacyHooks=settings!==null&&(hasKobeActivityHooks(settings,CLAUDE_HOOK_EVENT_MAP)||settingsHasWorktreeWatch(settings)),legacySkillDirs=installedSkillDirs(home);return{legacyHooks,legacySkillDirs}}function settingsHasWorktreeWatch(settings){let hooks=isObject(settings.hooks)?settings.hooks:{};return Object.values(hooks).some((groups)=>Array.isArray(groups)&&groups.some((g)=>isObject(g)&&Array.isArray(g.hooks)&&g.hooks.some((h)=>isObject(h)&&typeof h.command==="string"&&h.command.includes("worktree-created")&&!h.command.includes("CLAUDE_PLUGIN_ROOT"))))}function migrationHint(findings,cliName){if(!findings.legacyHooks&&findings.legacySkillDirs.length===0)return null;let lines=[`${cliName}: the Rove Claude Code plugin is enabled, but legacy installs remain:`];if(findings.legacyHooks)lines.push(" \u2022 ~/.claude/settings.json still has the settings-managed Rove hooks (every event fires TWICE).",` Run \`${cliName} hook cleanup\` to remove them (only Rove's own entries are touched).`);for(let dir of findings.legacySkillDirs)lines.push(` \u2022 legacy skill copy at ${dir} (the plugin bundles the skill \u2014 two copies double-register).`," Remove that directory to keep the plugin's copy only.");return lines.push(" Reading this inside a session? Just ask your agent to run the cleanup for you."),`${lines.join(`
2
+ import{installedSkillDirs}from"./chunk-da9tb8av.js";import{CLAUDE_HOOK_EVENT_MAP,claudeSettingsPath,hasKobeActivityHooks,isObject}from"./chunk-6tvrvekq.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-k1qe5qqa.js";import"./chunk-xy8be792.js";import"./chunk-6wpege0h.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-bq3fyc0p.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-v0zxyqrq.js";import"./chunk-e29hx18x.js";import"./chunk-g56kvet6.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";import{readFileSync}from"fs";import{homedir}from"os";var PLUGIN_NAME="rove";function readSettings(path){try{let parsed=JSON.parse(readFileSync(path,"utf8"));return isObject(parsed)?parsed:null}catch{return null}}function isRovePluginEnabled(settingsFilePath=claudeSettingsPath()){let settings=readSettings(settingsFilePath);if(!settings||!isObject(settings.enabledPlugins))return!1;return Object.entries(settings.enabledPlugins).some(([key,on])=>on===!0&&key.split("@")[0]===PLUGIN_NAME)}function detectLegacyInstalls(opts={}){let settingsFilePath=opts.settingsFilePath??claudeSettingsPath(),home=opts.home??homedir(),settings=readSettings(settingsFilePath),legacyHooks=settings!==null&&(hasKobeActivityHooks(settings,CLAUDE_HOOK_EVENT_MAP)||settingsHasWorktreeWatch(settings)),legacySkillDirs=installedSkillDirs(home);return{legacyHooks,legacySkillDirs}}function settingsHasWorktreeWatch(settings){let hooks=isObject(settings.hooks)?settings.hooks:{};return Object.values(hooks).some((groups)=>Array.isArray(groups)&&groups.some((g)=>isObject(g)&&Array.isArray(g.hooks)&&g.hooks.some((h)=>isObject(h)&&typeof h.command==="string"&&h.command.includes("worktree-created")&&!h.command.includes("CLAUDE_PLUGIN_ROOT"))))}function migrationHint(findings,cliName){if(!findings.legacyHooks&&findings.legacySkillDirs.length===0)return null;let lines=[`${cliName}: the Rove Claude Code plugin is enabled, but legacy installs remain:`];if(findings.legacyHooks)lines.push(" \u2022 ~/.claude/settings.json still has the settings-managed Rove hooks (every event fires TWICE).",` Run \`${cliName} hook cleanup\` to remove them (only Rove's own entries are touched).`);for(let dir of findings.legacySkillDirs)lines.push(` \u2022 legacy skill copy at ${dir} (the plugin bundles the skill \u2014 two copies double-register).`," Remove that directory to keep the plugin's copy only.");return lines.push(" Reading this inside a session? Just ask your agent to run the cleanup for you."),`${lines.join(`
3
3
  `)}
4
4
  `}export{migrationHint,isRovePluginEnabled,detectLegacyInstalls};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{PS_PROBE_TIMEOUT_MS,engineProcessIn,foregroundEngine,foregroundEngineIn,hasAncestor,parsePsSnapshot,psSnapshot,psSnapshotWith,vendorFromArgv}from"./chunk-etnnwbdx.js";import"./chunk-crdag2rc.js";import"./chunk-khj0apc7.js";import"./chunk-nzscq4yf.js";import"./chunk-w7zv47mp.js";import"./chunk-6tvrvekq.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-k1qe5qqa.js";import"./chunk-xy8be792.js";import"./chunk-6wpege0h.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-2brn8e1y.js";import"./chunk-bq3fyc0p.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-v0zxyqrq.js";import"./chunk-e29hx18x.js";import"./chunk-g56kvet6.js";import{PsProbeUnavailableError}from"./chunk-pxk2c2vj.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{vendorFromArgv,psSnapshotWith,psSnapshot,parsePsSnapshot,hasAncestor,foregroundEngineIn,foregroundEngine,engineProcessIn,PsProbeUnavailableError,PS_PROBE_TIMEOUT_MS};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ import{stripTerminalControls,terminalRows}from"./chunk-w25b7xxz.js";import{defaultPtyExitsPath}from"./chunk-mcdv19rs.js";import{randomUUID}from"crypto";import{mkdirSync,readFileSync,renameSync,writeFileSync}from"fs";import{dirname}from"path";var MAX_RECORDS=50,TAIL_LINES=40,TAIL_LINE_CHARS=500;function plainTail(raw){let lines=terminalRows(raw,TAIL_LINE_CHARS);while(lines.length>0&&(lines[lines.length-1]??"").trim()==="")lines.pop();return lines.slice(-TAIL_LINES)}function engineExitCodeFromTail(tail){for(let i=tail.length-1;i>=0;i--){let m=ENGINE_EXIT_BANNER.exec(tail[i]??"");if(m?.[1])return Number.parseInt(m[1],10)}return null}var ENGINE_EXIT_BANNER=/Engine exited \(code (\d+)\)/;function healTails(records){let out={};for(let[key,record]of Object.entries(records)){let tail=record?.tail;out[key]=Array.isArray(tail)?{...record,tail:tail.map((line)=>stripTerminalControls(String(line)))}:record}return out}function readPtyExitStore(path=defaultPtyExitsPath()){let read=(status,records={})=>({records,status,readable:status==="ok"||status==="absent"}),raw;try{raw=readFileSync(path,"utf8")}catch(err){return read(err.code==="ENOENT"?"absent":"unreadable")}try{let parsed=JSON.parse(raw);if(parsed===null||typeof parsed!=="object"||Array.isArray(parsed))return read("unparsable");return read("ok",healTails(parsed))}catch{return read("unparsable")}}function readPtyExitRecords(path=defaultPtyExitsPath()){return readPtyExitStore(path).records}function recordPtyExit(info,path=defaultPtyExitsPath()){if(info.key.startsWith("::"))return;if(info.exit.code===0&&info.exit.signal===null)return;let tail=plainTail(info.tail);writeRecord(info.key,{key:info.key,pid:info.pid,code:info.exit.code??engineExitCodeFromTail(tail),signal:info.exit.signal,at:info.exit.at,tail,layer:"pty"},path)}function recordEngineExit(info,path=defaultPtyExitsPath()){if(info.key.startsWith("::"))return;let tail=plainTail(info.tail);writeRecord(`${info.key}#engine`,{key:info.key,pid:info.pid,code:engineExitCodeFromTail(tail),signal:null,at:info.at,tail,layer:"engine",...info.vendor?{vendor:info.vendor}:{},...info.atApproximate?{atApproximate:!0}:{},parentAlive:!0},path)}function writeRecord(storeKey,record,path){let store=readPtyExitStore(path);if(store.status==="unreadable")throw Error(`pty-exits store is unreadable (${path}) \u2014 refusing to overwrite it`);let records=store.records;records[storeKey]=record;let newest=Object.entries(records).sort(([,a],[,b])=>a.at<b.at?1:-1).slice(0,MAX_RECORDS);mkdirSync(dirname(path),{recursive:!0});let tmp=`${path}.tmp-${process.pid}-${randomUUID()}`;writeFileSync(tmp,JSON.stringify(Object.fromEntries(newest),null,2),{encoding:"utf8",mode:384}),renameSync(tmp,path)}
3
+ export{plainTail,engineExitCodeFromTail,ENGINE_EXIT_BANNER,readPtyExitStore,readPtyExitRecords,recordPtyExit,recordEngineExit};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{findBinding,formatChord}from"./chunk-cjfc4hj1.js";function capOf(row){return row.hint?.keys??row.keys[0]}function legendCap(id){let row=findBinding(id);if(!row)return null;let cap=capOf(row);return cap&&cap.length>0?cap:null}function directCap(row){if(row.keys.length>0)return row.hint?.keys??row.keys[0]??null;return row.prefixKeys?.length?null:row.hint?.keys??null}function availableOn(row,surface){if(row.scope==="global")return!0;if(surface===null)return!1;if(row.scope===surface)return!0;return surface==="terminal"&&row.scope==="workspace"}function grammarHelpSections(keymap,surface,prefixKey,reachability){let here=[],direct=[],prefix=[],other=new Map;for(let binding of keymap){let cap=directCap(binding),staticallyAvailable=availableOn(binding,surface),directAvailable=reachability?reachability.direct.has(binding.id):staticallyAvailable,prefixAvailable=reachability?reachability.prefix.has(binding.id):staticallyAvailable;if(cap){let row={binding,primary:cap,aliases:binding.keys.filter((key)=>key!==cap)};if(directAvailable&&(staticallyAvailable||binding.presentation==="onePress"))if(binding.presentation==="onePress")direct.push(row);else here.push(row);else if(!staticallyAvailable&&binding.scope!=="global"){let rows=other.get(binding.scope);if(rows)rows.push(row);else other.set(binding.scope,[row])}}if(prefixKey&&prefixAvailable&&binding.prefixKeys?.length)prefix.push({binding,primary:`${prefixKey} + ${binding.prefixKeys[0]}`,aliases:binding.prefixKeys.slice(1).map((key)=>`${prefixKey} + ${key}`)})}let sections=[];if(here.length)sections.push({kind:"here",scope:surface??void 0,rows:here});if(direct.length)sections.push({kind:"direct",rows:direct});if(prefix.length)sections.push({kind:"prefix",rows:prefix});for(let[scope,rows]of other)sections.push({kind:"other",scope,rows});return sections}var SCOPE_CATEGORY={global:"Global",sidebar:"Sidebar",workspace:"Workspace",files:"Files",inbox:"Inbox",terminal:"Terminal"};function scopeCategory(scope){return scope?SCOPE_CATEGORY[scope]:"Global"}function guideCategory(action){if(["kanban.open","automations.open","workItems.open"].includes(action))return"Views";if(action.startsWith("focus."))return"Navigation";if(action.startsWith("inbox.")||action.startsWith("attention."))return"Attention";if(action.startsWith("chat.tab.")||action.startsWith("chat.session."))return"Sessions";if(action.startsWith("chat.fork.")||action.startsWith("task."))return"Tasks";if(action.startsWith("settings.")||action==="workspace.zenToggle")return"Tools";return findBinding(action)?.category??"Global"}var KEY_HINTS_ENABLED_KEY="hints.keyboard.enabled",PANE_HINT_USED_KEYS={sidebar:"hints.sidebar.used",files:"hints.files.used"};function keyHintsEnabled(raw){return raw!==!1}function keyHintsToggleOn(kv){return keyHintsEnabled(kv.get(KEY_HINTS_ENABLED_KEY,!0))}function toggleKeyHints(kv){let next=!keyHintsToggleOn(kv);if(kv.set(KEY_HINTS_ENABLED_KEY,next),next)for(let key of Object.values(PANE_HINT_USED_KEYS))kv.set(key,!1)}function paneHintVisible(enabledRaw,usedRaw){return keyHintsEnabled(enabledRaw)&&usedRaw!==!0}function statusHintTokens(reach,prefixKey){let tokens=[];if(prefixKey!==null&&reach.prefix.size>0)tokens.push({chord:prefixKey,msg:"commands"});else if(reach.inputPassthrough){let cap=reach.direct.has("focus.sidebar")?legendCap("focus.sidebar"):null;if(cap)tokens.push({chord:cap,msg:"sidebar"})}if(reach.direct.has("help.open")){let cap=legendCap("help.open");if(cap)tokens.push({chord:cap,msg:"help"})}return tokens}var PANE_HINT_ROWS={sidebar:[{id:"sidebar.nav",msg:"move"},{id:"sidebar.select",msg:"open"}],files:[{id:"files.nav",msg:"move"},{id:"files.hierarchy",msg:"collapse"},{id:"files.open",msg:"open",always:!0},{id:"files.diff",msg:"diff",always:!0}]};function paneHintTokens(pane,mode){return PANE_HINT_ROWS[pane].flatMap((row)=>{if(mode==="always"&&row.always!==!0)return[];let cap=legendCap(row.id);return cap?[{cap,msg:row.msg}]:[]})}function wizardKeyLines(prefixKey){let lines=[],nav=legendCap("sidebar.nav"),open=legendCap("sidebar.select");if(nav&&open)lines.push({msg:"keysBare",params:{nav:formatChord(nav),open:formatChord(open)}});let newTab=legendCap("chat.tab.new"),focusNext=legendCap("focus.next");if(newTab&&focusNext)lines.push({msg:"keysOnePress",params:{newTab:formatChord(newTab),focusNext:formatChord(focusNext)}});if(prefixKey!==null)lines.push({msg:"keysPrefix",params:{prefix:formatChord(prefixKey)}});let help=legendCap("help.open");if(help)lines.push({msg:"keysHelp",params:{help:formatChord(help)}});return lines}
2
+ import{findBinding,formatChord}from"./chunk-am3ajdfk.js";function capOf(row){return row.hint?.keys??row.keys[0]}function legendCap(id){let row=findBinding(id);if(!row)return null;let cap=capOf(row);return cap&&cap.length>0?cap:null}function directCap(row){if(row.keys.length>0)return row.hint?.keys??row.keys[0]??null;return row.prefixKeys?.length?null:row.hint?.keys??null}function availableOn(row,surface){if(row.scope==="global")return!0;if(surface===null)return!1;if(row.scope===surface)return!0;return surface==="terminal"&&row.scope==="workspace"}function grammarHelpSections(keymap,surface,prefixKey,reachability){let here=[],direct=[],prefix=[],other=new Map;for(let binding of keymap){let cap=directCap(binding),staticallyAvailable=availableOn(binding,surface),directAvailable=reachability?reachability.direct.has(binding.id):staticallyAvailable,prefixAvailable=reachability?reachability.prefix.has(binding.id):staticallyAvailable;if(cap){let row={binding,primary:cap,aliases:binding.keys.filter((key)=>key!==cap)};if(directAvailable&&(staticallyAvailable||binding.presentation==="onePress"))if(binding.presentation==="onePress")direct.push(row);else here.push(row);else if(!staticallyAvailable&&binding.scope!=="global"){let rows=other.get(binding.scope);if(rows)rows.push(row);else other.set(binding.scope,[row])}}if(prefixKey&&prefixAvailable&&binding.prefixKeys?.length)prefix.push({binding,primary:`${prefixKey} + ${binding.prefixKeys[0]}`,aliases:binding.prefixKeys.slice(1).map((key)=>`${prefixKey} + ${key}`)})}let sections=[];if(here.length)sections.push({kind:"here",scope:surface??void 0,rows:here});if(direct.length)sections.push({kind:"direct",rows:direct});if(prefix.length)sections.push({kind:"prefix",rows:prefix});for(let[scope,rows]of other)sections.push({kind:"other",scope,rows});return sections}var SCOPE_CATEGORY={global:"Global",sidebar:"Sidebar",workspace:"Workspace",files:"Files",inbox:"Inbox",terminal:"Terminal"};function scopeCategory(scope){return scope?SCOPE_CATEGORY[scope]:"Global"}function guideCategory(action){if(["kanban.open","automations.open","workItems.open"].includes(action))return"Views";if(action.startsWith("focus."))return"Navigation";if(action.startsWith("inbox.")||action.startsWith("attention."))return"Attention";if(action.startsWith("chat.tab.")||action.startsWith("chat.session."))return"Sessions";if(action.startsWith("chat.fork.")||action.startsWith("task."))return"Tasks";if(action.startsWith("settings.")||action==="workspace.zenToggle")return"Tools";return findBinding(action)?.category??"Global"}var KEY_HINTS_ENABLED_KEY="hints.keyboard.enabled",PANE_HINT_USED_KEYS={sidebar:"hints.sidebar.used",files:"hints.files.used"};function keyHintsEnabled(raw){return raw!==!1}function keyHintsToggleOn(kv){return keyHintsEnabled(kv.get(KEY_HINTS_ENABLED_KEY,!0))}function toggleKeyHints(kv){let next=!keyHintsToggleOn(kv);if(kv.set(KEY_HINTS_ENABLED_KEY,next),next)for(let key of Object.values(PANE_HINT_USED_KEYS))kv.set(key,!1)}function paneHintVisible(enabledRaw,usedRaw){return keyHintsEnabled(enabledRaw)&&usedRaw!==!0}function statusHintTokens(reach,prefixKey){let tokens=[];if(prefixKey!==null&&reach.prefix.size>0)tokens.push({chord:prefixKey,msg:"commands"});else if(reach.inputPassthrough){let cap=reach.direct.has("focus.sidebar")?legendCap("focus.sidebar"):null;if(cap)tokens.push({chord:cap,msg:"sidebar"})}if(reach.direct.has("help.open")){let cap=legendCap("help.open");if(cap)tokens.push({chord:cap,msg:"help"})}return tokens}var PANE_HINT_ROWS={sidebar:[{id:"sidebar.nav",msg:"move"},{id:"sidebar.select",msg:"open"}],files:[{id:"files.nav",msg:"move"},{id:"files.hierarchy",msg:"collapse"},{id:"files.open",msg:"open",always:!0},{id:"files.diff",msg:"diff",always:!0}]};function paneHintTokens(pane,mode){return PANE_HINT_ROWS[pane].flatMap((row)=>{if(mode==="always"&&row.always!==!0)return[];let cap=legendCap(row.id);return cap?[{cap,msg:row.msg}]:[]})}function wizardKeyLines(prefixKey){let lines=[],nav=legendCap("sidebar.nav"),open=legendCap("sidebar.select");if(nav&&open)lines.push({msg:"keysBare",params:{nav:formatChord(nav),open:formatChord(open)}});let newTab=legendCap("chat.tab.new"),focusNext=legendCap("focus.next");if(newTab&&focusNext)lines.push({msg:"keysOnePress",params:{newTab:formatChord(newTab),focusNext:formatChord(focusNext)}});if(prefixKey!==null)lines.push({msg:"keysPrefix",params:{prefix:formatChord(prefixKey)}});let help=legendCap("help.open");if(help)lines.push({msg:"keysHelp",params:{help:formatChord(help)}});return lines}
3
3
  export{legendCap,grammarHelpSections,scopeCategory,guideCategory,KEY_HINTS_ENABLED_KEY,PANE_HINT_USED_KEYS,keyHintsEnabled,keyHintsToggleOn,toggleKeyHints,paneHintVisible,statusHintTokens,paneHintTokens,wizardKeyLines};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{StaleInstallError,autospawnDaemonEnv,connectIfRunning,connectOrStartDaemon,daemonSpawnReason,detachOptions,ensureDaemonReachable,isStaleInstallError,probeDaemonSocket,resolveKobeSpawn,spawnDetachedDaemon,testDaemonResponds,tryAcquireSpawnLock}from"./chunk-2840nxj7.js";import"./chunk-gyc4fj15.js";import"./chunk-0wnfq5sx.js";import"./chunk-7j5372wb.js";import"./chunk-mnqxgvyb.js";import"./chunk-mv7ptt5w.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{tryAcquireSpawnLock,testDaemonResponds,spawnDetachedDaemon,resolveKobeSpawn,probeDaemonSocket,isStaleInstallError,ensureDaemonReachable,detachOptions,daemonSpawnReason,connectOrStartDaemon,connectIfRunning,autospawnDaemonEnv,StaleInstallError};
2
+ import{StaleInstallError,autospawnDaemonEnv,connectIfRunning,connectOrStartDaemon,daemonSpawnReason,detachOptions,ensureDaemonReachable,isStaleInstallError,probeDaemonSocket,resolveKobeSpawn,spawnDetachedDaemon,testDaemonResponds,tryAcquireSpawnLock}from"./chunk-h9mqdxvs.js";import"./chunk-8wv8526c.js";import"./chunk-0gepyh6e.js";import"./chunk-bkvr06xn.js";import"./chunk-mnqxgvyb.js";import"./chunk-mv7ptt5w.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{tryAcquireSpawnLock,testDaemonResponds,spawnDetachedDaemon,resolveKobeSpawn,probeDaemonSocket,isStaleInstallError,ensureDaemonReachable,detachOptions,daemonSpawnReason,connectOrStartDaemon,connectIfRunning,autospawnDaemonEnv,StaleInstallError};
@@ -4,4 +4,4 @@ import{SUBCOMMAND_VERBS}from"./chunk-s76r56rj.js";import{expandTilde}from"./chun
4
4
 
5
5
  ${REPO_USAGE}
6
6
  `),process.exit(2)}function readArgFile(path){try{return readFileSync(resolve(process.cwd(),expandTilde(path)),"utf8")}catch(err){usageError(`cannot read ${path}: ${errorMessage(err)}`)}}function parseRepoArgs(args){let out={};for(let i=0;i<args.length;i++){let a=args[i],need=()=>{let v=args[++i];if(v===void 0)usageError(`${a} requires a value`);return v};if(a==="--init-script")out.initScript=need();else if(a==="--init-script-file")out.initScript=readArgFile(need());else if(a==="--init-prompt")out.initPrompt=need();else if(a==="--init-prompt-file")out.initPrompt=readArgFile(need());else if(a.startsWith("-"))usageError(`unknown flag "${a}"`);else if(out.path===void 0)out.path=a;else usageError(`unexpected argument "${a}"`)}return out}function parseUnsetArgs(args){let path,clearScript=!1,clearPrompt=!1;for(let a of args)if(a==="--init-script")clearScript=!0;else if(a==="--init-prompt")clearPrompt=!0;else if(a.startsWith("-"))usageError(`unknown flag "${a}"`);else if(path===void 0)path=a;else usageError(`unexpected argument "${a}"`);if(!clearScript&&!clearPrompt)clearScript=!0,clearPrompt=!0;return{path,clearScript,clearPrompt}}async function runRepoSubcommand(args){let[verb,...rest]=args;if(verb===void 0||verb==="--help"||verb==="-h"||verb==="help"){process.stdout.write(`${REPO_USAGE}
7
- `);return}if(!SUBCOMMAND_VERBS.repo.includes(verb))usageError(`unknown verb "${verb}"`);let{getRepoInitOverride,setRepoInitOverride,resolveRepoRoot}=await import("./chunk-s6mcrm5g.js");if(verb==="show"){let[pathArg]=rest.filter((a)=>!a.startsWith("-")),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(pathArg??"."))),override=getRepoInitOverride(repo),{describeRepoInitSources}=await import("./chunk-3bcx9dyb.js"),sources=describeRepoInitSources(repo);console.log(`repo: ${repo}`);for(let group of[sources.script,sources.prompt])group.forEach((source,index)=>{console.log(` ${`${source.rel}:`.padEnd(22)}${describeSource(group,index)}`)});console.log(` override initScript: ${override.initScript?quotePreview(override.initScript):"(unset)"}`),console.log(` override initPrompt: ${override.initPrompt?quotePreview(override.initPrompt):"(unset)"}`);return}if(verb==="set"){let flags=parseRepoArgs(rest);if(flags.initScript===void 0&&flags.initPrompt===void 0)usageError("set needs at least one of --init-script(-file) / --init-prompt(-file)");let repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(flags.path??"."))),next=setRepoInitOverride(repo,{...flags.initScript!==void 0?{initScript:flags.initScript}:{},...flags.initPrompt!==void 0?{initPrompt:flags.initPrompt}:{}});console.log(`updated override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}if(verb==="unset"){let{path,clearScript,clearPrompt}=parseUnsetArgs(rest),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(path??"."))),next=setRepoInitOverride(repo,{...clearScript?{initScript:""}:{},...clearPrompt?{initPrompt:""}:{}});console.log(`cleared override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}usageError(`unknown verb "${verb}"`)}function describeSource(group,index){let source=group[index];if(!source)return"absent";if(source.effective)return"present (wins)";if(!source.present)return"absent";return group.slice(0,index).some((earlier)=>earlier.effective)?"present (shadowed)":"present but empty (ignored)"}function quotePreview(value){let oneLine=value.replace(/\s+/g," ").trim();return oneLine.length>60?`"${oneLine.slice(0,57)}\u2026"`:`"${oneLine}"`}export{runRepoSubcommand};
7
+ `);return}if(!SUBCOMMAND_VERBS.repo.includes(verb))usageError(`unknown verb "${verb}"`);let{getRepoInitOverride,setRepoInitOverride,resolveRepoRoot}=await import("./chunk-mmg7m9x2.js");if(verb==="show"){let[pathArg]=rest.filter((a)=>!a.startsWith("-")),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(pathArg??"."))),override=getRepoInitOverride(repo),{describeRepoInitSources}=await import("./chunk-b0f0jdnb.js"),sources=describeRepoInitSources(repo);console.log(`repo: ${repo}`);for(let group of[sources.script,sources.prompt])group.forEach((source,index)=>{console.log(` ${`${source.rel}:`.padEnd(22)}${describeSource(group,index)}`)});console.log(` override initScript: ${override.initScript?quotePreview(override.initScript):"(unset)"}`),console.log(` override initPrompt: ${override.initPrompt?quotePreview(override.initPrompt):"(unset)"}`);return}if(verb==="set"){let flags=parseRepoArgs(rest);if(flags.initScript===void 0&&flags.initPrompt===void 0)usageError("set needs at least one of --init-script(-file) / --init-prompt(-file)");let repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(flags.path??"."))),next=setRepoInitOverride(repo,{...flags.initScript!==void 0?{initScript:flags.initScript}:{},...flags.initPrompt!==void 0?{initPrompt:flags.initPrompt}:{}});console.log(`updated override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}if(verb==="unset"){let{path,clearScript,clearPrompt}=parseUnsetArgs(rest),repo=resolveRepoRoot(resolve(process.cwd(),expandTilde(path??"."))),next=setRepoInitOverride(repo,{...clearScript?{initScript:""}:{},...clearPrompt?{initPrompt:""}:{}});console.log(`cleared override for ${repo}`),console.log(` initScript: ${next.initScript?quotePreview(next.initScript):"(unset)"}`),console.log(` initPrompt: ${next.initPrompt?quotePreview(next.initPrompt):"(unset)"}`);return}usageError(`unknown verb "${verb}"`)}function describeSource(group,index){let source=group[index];if(!source)return"absent";if(source.effective)return"present (wins)";if(!source.present)return"absent";return group.slice(0,index).some((earlier)=>earlier.effective)?"present (shadowed)":"present but empty (ignored)"}function quotePreview(value){let oneLine=value.replace(/\s+/g," ").trim();return oneLine.length>60?`"${oneLine.slice(0,57)}\u2026"`:`"${oneLine}"`}export{runRepoSubcommand};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{ensurePluginEnginesLoaded,loadPluginEngines,registeredEngineIds,reloadPluginEngines}from"./chunk-ttd78mrr.js";import"./chunk-38272eqv.js";import"./chunk-mnqxgvyb.js";import"./chunk-9esrwvqc.js";import"./chunk-w7zv47mp.js";import"./chunk-7jkf3tvr.js";import"./chunk-1kz2syvp.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-2brn8e1y.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-g56kvet6.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{reloadPluginEngines,registeredEngineIds,loadPluginEngines,ensurePluginEnginesLoaded};
2
+ import{ensurePluginEnginesLoaded,loadPluginEngines,registeredEngineIds,reloadPluginEngines}from"./chunk-vhhzk3xj.js";import"./chunk-38272eqv.js";import"./chunk-mnqxgvyb.js";import"./chunk-nzscq4yf.js";import"./chunk-w7zv47mp.js";import"./chunk-7jkf3tvr.js";import"./chunk-6wpege0h.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-2brn8e1y.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-g56kvet6.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{reloadPluginEngines,registeredEngineIds,loadPluginEngines,ensurePluginEnginesLoaded};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{connectIfRunning,connectOrStartDaemon}from"./chunk-2840nxj7.js";async function openDaemonSession(opts={}){let client=opts.mode==="require-running"?await connectIfRunning():await connectOrStartDaemon();if(!client)return null;return{client,close:()=>client.close()}}async function resolveActiveTaskId(client){let activeId=null,off=client.onChannel("active-task",(payload)=>{activeId=payload.taskId});try{await client.subscribe()}finally{off()}return activeId}
2
+ import{connectIfRunning,connectOrStartDaemon}from"./chunk-h9mqdxvs.js";async function openDaemonSession(opts={}){let client=opts.mode==="require-running"?await connectIfRunning():await connectOrStartDaemon();if(!client)return null;return{client,close:()=>client.close()}}async function resolveActiveTaskId(client){let activeId=null,off=client.onChannel("active-task",(payload)=>{activeId=payload.taskId});try{await client.subscribe()}finally{off()}return activeId}
3
3
  export{openDaemonSession,resolveActiveTaskId};
@@ -0,0 +1,4 @@
1
+ // @bun
2
+ import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-zfqm8rmp.js";import{readLastActiveTaskId,writeLastActiveTaskId}from"./chunk-tqat428f.js";import{GitWorktreeManager,defaultExecDeps,isDirtyOutput,parseDirtyPaths}from"./chunk-cwnwj3r8.js";import{resolvePreferredVendor}from"./chunk-kn3pgymw.js";import{READ_ONLY_GIT_ENV}from"./chunk-6xppe9bj.js";import{CannotDeleteMainTaskError,DirtyWorktreeError,EmptyBranchDirtyWorktreeError,EmptyBranchError,GitCommandFailedError,IllegalTransitionError,LandConflictError,MainCheckoutDirtyError,MissingRefError,PLACEHOLDER_TASK_TITLE,TaskDeletingError,TaskNotFoundError,WorktreeRemoveFailedError,isPlaceholderDerivedBranch,sanitizeTaskTitle}from"./chunk-9kefy6ev.js";import{canonicalize,listWorktreeDirNames}from"./chunk-me23en52.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-6wpege0h.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{projectRejection,rejectionReason}from"./chunk-3wj69b0a.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;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()}:{}})}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)}}import path from"path";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(wt===canonicalize(task.repo))return{removed:!1,reason:"refusing to remove the base checkout"};if(callerCwd){let rel=path.relative(wt,canonicalize(callerCwd));if(rel===""||!rel.startsWith("..")&&!path.isAbsolute(rel))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
+ `).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)=>task.repo)),seen=new Set,out=[];for(let task of deps.tasks){if(task.kind!=="dir"||task.scratch===!0)continue;let path2=task.repo;if(!path2||claimed.has(path2)||seen.has(path2))continue;if(!deps.isRepoRoot(path2))continue;seen.add(path2),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"&&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 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()}}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)}}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)=>t.repo===repo&&t.kind!=="main").map((t)=>{return t.worktreePath.match(/([^/\\]+)[/\\]*$/)?.[1]??""}).filter((s)=>s.length>0))}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=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:(path2)=>isGitRepo(path2)&&resolveRepoRoot(path2)===path2});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},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);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
+ export{Orchestrator};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ import{getPersistedBool,loadStateFile,patchStateFile,readSavedRepos,updateStateFile}from"./chunk-j75axe29.js";import{projectRejection}from"./chunk-3wj69b0a.js";import{kvStatePath}from"./chunk-ch9b1d5y.js";import{spawnSync}from"child_process";import{realpathSync}from"fs";function isRemoteRepoKey(key){return key.startsWith("ssh://")}function isRemoteProjectsEnabled(){return getPersistedBool("experimental.remoteProjects",!1)}function remoteRepoKey(host,user,port,basePath){let authority=port?`${user}@${host}:${port}`:`${user}@${host}`,base=(basePath??"").trim().replace(/\/+$/,"");if(!base)return`ssh://${authority}`;return`ssh://${authority}${base.startsWith("/")?base:`/${base}`}`}function readRemoteRepos(state){let raw=state.remoteRepos;if(!raw||typeof raw!=="object"||Array.isArray(raw))return{};return raw}function getRemoteRepoConfig(key){return readRemoteRepos(loadStateFile())[key]??null}function getRemoteRepos(){return readRemoteRepos(loadStateFile())}function addRemoteRepo(config){let key=remoteRepoKey(config.host,config.user,config.port,config.basePath),added=!1;return updateStateFile((state)=>{let repos={...readRemoteRepos(state)},legacyKey=remoteRepoKey(config.host,config.user,config.port);if(key!==legacyKey&&repos[legacyKey]?.basePath===config.basePath)key=legacyKey;repos[key]=config,state.remoteRepos=repos;let saved=readSavedRepos(state);if(added=!saved.includes(key),added)state.savedRepos=[...saved,key];return}),{key,added}}function resolveRepoRoot(absPath){if(isRemoteRepoKey(absPath))return absPath;let r=spawnSync("git",["rev-parse","--show-toplevel"],{cwd:absPath,encoding:"utf8",shell:!1});if(r.status!==0)return absPath;let top=(r.stdout??"").trim();if(!top)return absPath;try{if(realpathSync(absPath)===realpathSync(top))return absPath}catch{}return top}function isGitRepo(absPath){if(isRemoteRepoKey(absPath))return!1;let r=spawnSync("git",["rev-parse","--is-inside-work-tree"],{cwd:absPath,encoding:"utf8",shell:!1});return r.status===0&&(r.stdout??"").trim()==="true"}function isValidBranchName(branch){return spawnSync("git",["check-ref-format","--branch",branch],{encoding:"utf8",shell:!1}).status===0}function resolveMainRepoRoot(absPath){if(isRemoteRepoKey(absPath))return absPath;let r=spawnSync("git",["worktree","list","--porcelain"],{cwd:absPath,encoding:"utf8",shell:!1});if(r.status!==0)return resolveRepoRoot(absPath);return(r.stdout??"").split(/\r?\n/).find((line)=>line.startsWith("worktree "))?.slice(9).trim()||resolveRepoRoot(absPath)}function statePath(){return kvStatePath()}function getSavedRepos(){return readSavedRepos(loadStateFile())}function getPersistedString(key){let value=loadStateFile()[key];return typeof value==="string"?value:void 0}function setPersistedString(key,value){patchStateFile({[key]:value})}function getCustomEngineIds(){let raw=loadStateFile().customEngineIds;if(!Array.isArray(raw))return[];return raw.filter((s)=>typeof s==="string"&&s.trim().length>0)}function getDisabledEngineIds(){let raw=loadStateFile().disabledEngineIds;if(!Array.isArray(raw))return[];return raw.filter((s)=>typeof s==="string"&&s.trim().length>0)}function addSavedRepo(absPath,opts={}){let normalized=resolveMainRepoRoot(absPath),rejected=opts.skipGate?null:projectRejection(normalized,isGitRepo,opts.intent??"explicit");if(rejected)return{added:!1,path:normalized,total:getSavedRepos().length,rejected};let result={added:!1,path:normalized,total:0};return updateStateFile((state)=>{let cur=readSavedRepos(state);if(cur.includes(normalized))return result={added:!1,path:normalized,total:cur.length},!1;state.savedRepos=[...cur,normalized],result={added:!0,path:normalized,total:cur.length+1};return}),result}function backfillSavedReposFromProjects(mainRepos){let added=[];for(let repo of mainRepos)if(addSavedRepo(repo,{intent:"explicit"}).added)added.push(repo);return added}function normalizeSavedRepos(){let cur=getSavedRepos(),seen=new Set,next=[],changed=!1;for(let p of cur){let top=resolveMainRepoRoot(p);if(top!==p)changed=!0;if(seen.has(top)){changed=!0;continue}seen.add(top),next.push(top)}if(!changed)return;patchStateFile({savedRepos:next})}function readRepoConfigs(state){let raw=state.repoConfigs;if(!raw||typeof raw!=="object"||Array.isArray(raw))return{};return raw}function coerceOverride(entry){if(!entry||typeof entry!=="object")return{};let e=entry;return{initScript:typeof e.initScript==="string"&&e.initScript.length>0?e.initScript:void 0,initPrompt:typeof e.initPrompt==="string"&&e.initPrompt.length>0?e.initPrompt:void 0}}function getRepoInitOverride(repoRoot){return coerceOverride(readRepoConfigs(loadStateFile())[resolveRepoRoot(repoRoot)])}function setRepoInitOverride(repoRoot,patch){let normalized=resolveRepoRoot(repoRoot),next={};return updateStateFile((state)=>{let configs={...readRepoConfigs(state)},cur=coerceOverride(configs[normalized]),nextScript=patch.initScript===void 0?cur.initScript:patch.initScript||void 0,nextPrompt=patch.initPrompt===void 0?cur.initPrompt:patch.initPrompt||void 0;if(next={...nextScript?{initScript:nextScript}:{},...nextPrompt?{initPrompt:nextPrompt}:{}},!next.initScript&&!next.initPrompt){let{[normalized]:_dropped,...rest}=configs;state.repoConfigs=rest}else configs[normalized]=next,state.repoConfigs=configs;return}),next}function removeSavedRepo(absPath){let result={removed:!1,path:absPath,total:0};return updateStateFile((state)=>{let cur=readSavedRepos(state);if(!cur.includes(absPath))return result={removed:!1,path:absPath,total:cur.length},!1;if(state.savedRepos=cur.filter((p)=>p!==absPath),isRemoteRepoKey(absPath)){let remotes=readRemoteRepos(state);if(absPath in remotes){let next={...remotes};delete next[absPath],state.remoteRepos=next}}result={removed:!0,path:absPath,total:cur.length-1};return}),result}
3
+ export{isRemoteRepoKey,isRemoteProjectsEnabled,remoteRepoKey,getRemoteRepoConfig,getRemoteRepos,addRemoteRepo,resolveRepoRoot,isGitRepo,isValidBranchName,resolveMainRepoRoot,statePath,getSavedRepos,getPersistedString,setPersistedString,getCustomEngineIds,getDisabledEngineIds,addSavedRepo,backfillSavedReposFromProjects,normalizeSavedRepos,getRepoInitOverride,setRepoInitOverride,removeSavedRepo};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ import{closeTab,engineTabArgv,initialTabs,setTabTitle,terminalTabsKey}from"./chunk-nrafk2b7.js";import{ComposerBusyError,awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,enginePresence,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,initMarkerSaysFinished,isHostedTaskKey,killHostedSessions,listHostedSessions,listHostedSessionsOrNull,openHostedSessionHost,pastePromptWhenEngineUp,readPersistedTerminalDefaultColors,writeHostedPromptIfClear}from"./chunk-mbb0pp66.js";import{engineLaunchArgv}from"./chunk-vhrfe63r.js";import{engineEntry}from"./chunk-crdag2rc.js";import{loadStateFile,patchStateFile,updateStateFile}from"./chunk-j75axe29.js";function taskEngineArgv(task){return engineLaunchArgv({command:task.command,vendor:task.vendor})}function readTabsSnapshot(taskId){try{let snap=loadStateFile()[terminalTabsKey(taskId)];return snap&&Array.isArray(snap.tabs)?snap:void 0}catch{return}}function closeTabsSnapshot(taskId,tabId){let closing,key=terminalTabsKey(taskId);return updateStateFile((store)=>{let state=store[key];if(!state||!Array.isArray(state.tabs))return!1;if(closing=state.tabs.find((tab)=>tab.id===tabId),!closing)return!1;let{state:next,closedId}=closeTab(state,tabId,{allowEmpty:!0});if(!closedId)return closing=void 0,!1;store[key]=next;return}),closing}function renameTabsSnapshot(taskId,tabId,title){let found=!1,key=terminalTabsKey(taskId);return updateStateFile((store)=>{let state=store[key];if(!state||!Array.isArray(state.tabs))return!1;if(!state.tabs.some((tab)=>tab.id===tabId))return!1;found=!0;let next=setTabTitle(state,tabId,title);if(next===state)return!1;store[key]=next;return}),found}var aliveKeysOf=(sessions)=>new Set(sessions.filter((s)=>s.alive).map((s)=>s.key));function unregisteredTabIds(snapshot,taskId,sessions){let known=new Set((snapshot?.tabs??[]).map((t)=>t.id)),prefix=`${taskId}::`,out=[];for(let s of sessions){if(!s.alive||!s.key.startsWith(prefix))continue;let tabId=s.key.slice(prefix.length);if(tabId.includes("::"))continue;if(!known.has(tabId)&&!out.includes(tabId))out.push(tabId)}return out}var abnormalExit=(exit)=>exit&&(exit.code!==0||exit.signal!==null)?exit:null;function joinTaskTabs(snapshot,taskId,sessions,persistedExits={},liveVendors,engineAlive){let unknown=sessions===null,rows0=sessions??[],alive=aliveKeysOf(rows0),sessionExits=new Map(rows0.map((s)=>[s.key,s.exit])),deadExit=(key)=>{let ex=abnormalExit(sessionExits.get(key)??persistedExits[key]);if(!ex)return null;let record=persistedExits[key],sameDeath=record?.at===ex.at,tail=sameDeath?record?.tail:void 0,code=ex.code??(sameDeath?record?.code??null:null),layer=record?.layer??"pty";return{code,signal:ex.signal,at:ex.at,layer,...tail&&tail.length>0?{tail}:{}}},engineExit=(key)=>{let record=persistedExits[`${key}#engine`];if(!record)return null;let{code,signal,at,tail,atApproximate}=record;return{code,signal,at,layer:"engine",...atApproximate?{atApproximate}:{},...tail&&tail.length>0?{tail}:{}}},rows=(snapshot?.tabs??[]).map((t)=>{let key=`${taskId}::${t.id}`,isAlive=unknown?null:alive.has(key),walked=isAlive===!0&&liveVendors?.has(key)===!0?liveVendors.get(key)??null:void 0,engineIsAlive=engineAliveOf(key,isAlive,engineAlive);return{id:t.id,kind:t.kind,title:t.title??null,vendor:t.vendor??null,liveVendor:walked!==void 0?walked:t.liveVendor??null,lastTitle:t.lastTitle??null,autoTitle:t.autoTitle??null,alive:isAlive,engineAlive:engineIsAlive,exit:isAlive===!1?deadExit(key):engineIsAlive===!1?engineExit(key):null}});for(let tabId of unregisteredTabIds(snapshot,taskId,rows0))rows.push({id:tabId,kind:"engine",title:null,vendor:null,liveVendor:null,lastTitle:null,autoTitle:null,alive:!0,engineAlive:engineAliveOf(`${taskId}::${tabId}`,!0,engineAlive),exit:null,unregistered:!0});return rows}function engineAliveOf(key,isAlive,engineAlive){if(isAlive===null)return null;if(!isAlive)return!1;return engineAlive?.has(key)===!0?engineAlive.get(key)??null:null}function publishCliTabSnapshot(taskId,sessionId){if(!taskId)return;try{let key=terminalTabsKey(taskId);if(loadStateFile()[key]!==void 0)return;let seeded=initialTabs();patchStateFile({[key]:sessionId?{...seeded,tabs:seeded.tabs.map((t)=>t.kind==="engine"?{...t,sessionId,spawned:!0}:t)}:seeded})}catch{}}function markCliTabSession(taskId,tabId,sessionId){try{let key=terminalTabsKey(taskId),existing=loadStateFile()[key];if(!existing||!Array.isArray(existing.tabs))return;patchStateFile({[key]:{...existing,tabs:existing.tabs.map((t)=>t.id===tabId&&t.kind==="engine"?{...t,sessionId,spawned:!0}:t)}})}catch{}}function mintCliTab(taskId,vendor,command){let tabId="tab-1";try{let key=terminalTabsKey(taskId),existing=loadStateFile()[key],state=existing&&Array.isArray(existing.tabs)&&existing.tabs.length>0?existing:initialTabs(),ordinal=typeof state.nextOrdinal==="number"&&state.nextOrdinal>1?state.nextOrdinal:2;tabId=`tab-${ordinal}`,patchStateFile({[key]:{...state,tabs:[...state.tabs,{kind:"engine",id:tabId,title:null,ordinal,...vendor?{vendor}:{},...command?{engineCommand:command}:{}}],activeId:tabId,nextOrdinal:ordinal+1}})}catch{tabId=`tab-cli-${Date.now().toString(36)}`}return tabId}function restoredTabsOf(sessions,taskId,exceptKey){let prefix=`${taskId}::`,ids=[];for(let s of sessions){if(s.alive||s.restored!==!0||s.key===exceptKey||!s.key.startsWith(prefix))continue;let tab=s.key.slice(prefix.length);if(tab.includes("::"))continue;if(!ids.includes(tab))ids.push(tab)}let tabs=readTabsSnapshot(taskId)?.tabs??[];return ids.map((tab)=>{let sessionId=tabs.find((t)=>t.id===tab)?.sessionId;return sessionId?{tab,sessionId}:{tab}})}function restoredTabLaunch(task,tabId,worktreePath,shell){let tab=readTabsSnapshot(task.id)?.tabs.find((t)=>t.id===tabId&&t.kind==="engine");if(!tab)return null;let base=engineLaunchArgv({command:tab.engineCommand??(tab.vendor?void 0:task.command),vendor:tab.vendor??task.vendor,effort:task.modelEffort});return buildEngineSessionLaunch({task:{id:task.id,kind:task.kind??"task",vendor:tab.vendor??task.vendor,repo:task.repo},worktreePath,shell,argv:engineTabArgv(tab,base,!1,task.vendor),promptIntent:{kind:"none"},tabId})}class ApiError extends Error{code;data;constructor(message,code,data){super(message);this.code=code;this.data=data}}var DAEMON_CODE_PREFIX=/^([A-Z][A-Z0-9_]{2,}): /;function splitDaemonCode(message){let match=DAEMON_CODE_PREFIX.exec(message);if(!match?.[1])return null;return{code:match[1],rest:message.slice(match[0].length)}}function helpStep(verbName){return{hint:"run the verb's --help for its exact flag contract, then retry",nextCommandArgs:["api",verbName,"--help"]}}var VERB_GROUP_IDS=["discover","read","create","drive","edit","issues","workitems","routine","lifecycle","worktree","feedback"];var isTaskKey=isHostedTaskKey,findEngineKey=findHostedEngineKey,taskKeys=hostedTaskKeys,openPtyHost=openHostedSessionHost,ensurePtyHost=ensureHostedSessionHost,listSessions=listHostedSessions,listSessionsOrNull=listHostedSessionsOrNull,deliverToKey=deliverToHostedKey,writePrompt=writeHostedPromptIfClear,ENGINE_START_PROBE_MS=3000,ENGINE_START_POLL_MS=150,ENGINE_NOT_OBSERVED_REASON=`no engine process appeared in the session within ${ENGINE_START_PROBE_MS}ms`;function outcomeFields(outcome){if(!outcome)return{engineReady:!1,delivered:!1};return{engineReady:outcome.ready,delivered:!0,bytes:outcome.bytes,promptEcho:outcome.confirmed?"confirmed":"unconfirmed"}}async function deliverHostedPrompt(rpc,target,cwd,prompt,launch,opts){let{sessions=[]}=await rpc.request("pty.list",{}),existingKey=opts?.forceNew?null:findEngineKey(sessions,target.id,target.engineBin);if(existingKey){let pid=sessions.find((s)=>s.key===existingKey)?.pid,presence=await enginePresence(pid,target.engineBin,opts?.snapshot);if(presence==="unknown")throw new ApiError(`could not read the process table, so task ${target.id}'s engine tab (${existingKey}) could not be checked for a live engine`,"ENGINE_PROBE_FAILED",{hint:"the `ps` probe failed or timed out; retry, or check the machine's process table",nextCommandArgs:["api","pty-list"]});if(presence!=="engine")throw new ApiError(`task ${target.id}'s engine tab (${existingKey}) has no live engine process \u2014 its engine exited into a plain shell`,"ENGINE_NOT_RUNNING",{hint:"spawn a fresh engine tab for this prompt with --tab new",nextCommandArgs:["api","send","--task-id",target.id,"--tab","new","--prompt",prompt]});let deliveryOpts={screenManifest:resolveComposerManifest(opts?.vendor)},tabId=existingKey.split("::")[1]??"tab-1",outcome;try{outcome=await deliverToKey(rpc,existingKey,prompt,deliveryOpts)}catch(err){if(err instanceof ComposerBusyError)return deferOrThrow(err,opts?.defer,target.id,tabId,prompt);throw err}return{session:existingKey,pane:existingKey,started:!1,...outcomeFields(outcome)}}if(!opts?.forceNew){let aliveTabs=sessions.filter((s)=>s.alive&&isTaskKey(s.key,target.id)).map((s)=>s.key);if(aliveTabs.length>0)throw new ApiError(`task ${target.id} has live tabs (${aliveTabs.join(", ")}) but none resolves as its engine tab \u2014 refusing to spawn a new engine`,"NO_ENGINE_TAB",{hint:"address a live engine tab explicitly with --tab <tab-N> (see pty-list), or spawn a fresh engine tab with --tab new",nextCommandArgs:["api","pty-list"]})}let frozen=restoredTabsOf(sessions,target.id,launch.key),disclose=frozen.length>0?{frozenTabs:frozen}:{},staleCanonical=sessions.find((session)=>session.key===launch.key&&!session.alive);if(staleCanonical&&staleCanonical.restored!==!0)await rpc.request("pty.kill",{key:launch.key});let open=await rpc.request("pty.open",{key:launch.key,cwd,command:launch.command,defaultColors:readPersistedTerminalDefaultColors()});try{if(!open.alive)return{session:launch.key,pane:launch.key,started:open.created!==!1||open.respawned===!0,engineReady:!1,delivered:!1,...disclose};if(launch.firstMessage){let tabId=launch.key.split("::")[1]??"tab-1",outcome;try{outcome=await pastePromptWhenEngineUp(rpc,launch.key,target.engineBin,launch.firstMessage,{initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs,screenManifest:resolveComposerManifest(opts?.vendor)})}catch(err){if(err instanceof ComposerBusyError)return deferOrThrow(err,opts?.defer,target.id,tabId,prompt);throw err}return{session:launch.key,pane:launch.key,started:open.created!==!1||open.respawned===!0,...outcomeFields(outcome),...disclose}}let started=open.created!==!1||open.respawned===!0;if(open.created===!1&&open.respawned!==!0){let tabId=launch.key.split("::")[1]??"tab-1",outcome;try{outcome=await writePrompt(rpc,launch.key,prompt,{screenManifest:resolveComposerManifest(opts?.vendor)})}catch(err){if(err instanceof ComposerBusyError)return deferOrThrow(err,opts?.defer,target.id,tabId,prompt);throw err}return{session:launch.key,pane:launch.key,started,...outcomeFields(outcome),...disclose}}let pendingInit={session:launch.key,pane:launch.key,started,engineReady:!1,delivered:!0,reason:"repo init script is still running; the engine has not started yet",...disclose};if(launch.initMarkerPath&&!initMarkerSaysFinished(launch.initMarkerPath))return pendingInit;if(await awaitEngineProcess(rpc,launch.key,target.engineBin,{timeoutMs:ENGINE_START_PROBE_MS,intervalMs:ENGINE_START_POLL_MS,snapshot:opts?.snapshot})===null){if(launch.initMarkerPath&&!initMarkerSaysFinished(launch.initMarkerPath)&&(await listSessions(rpc)).some((session)=>session.key===launch.key&&session.alive)&&!initMarkerSaysFinished(launch.initMarkerPath))return pendingInit;return{session:launch.key,pane:launch.key,started,engineReady:!1,delivered:!1,reason:await hostedSessionFailureLine(rpc,launch.key)??ENGINE_NOT_OBSERVED_REASON,...disclose}}return{session:launch.key,pane:launch.key,started,engineReady:!0,delivered:!0,...disclose}}finally{await rpc.request("pty.detach",{key:launch.key}).catch(()=>{})}}function resolveComposerManifest(vendor){return vendor?engineEntry(vendor).screenManifest:void 0}async function deferOrThrow(error,sink,taskId,tabId,prompt){if(sink){let deferred;try{deferred=await sink.defer({taskId,tabId,prompt,layer:error.layer})}catch{throw composerBusyApiError(error,taskId,prompt)}if(deferred.kind==="occupied")throw new ApiError(`task ${taskId} tab ${tabId} already has a deferred prompt`,"DEFERRED_PROMPT_PENDING",{taskId,tabId,existingId:deferred.id,hint:"a prompt is already held for this tab \u2014 deliver it with `deferred-release --id`, or drop it with `deferred-dismiss --id`, then send yours again (`deferred-list` shows the text and its expiry)",nextCommandArgs:["api","deferred-release","--id",deferred.id]});return{session:`${taskId}::${tabId}`,pane:`${taskId}::${tabId}`,started:!1,engineReady:!1,delivered:!1,deferred:{id:deferred.id,layer:error.layer,...deferred.expiresAt!==void 0?{expiresAt:deferred.expiresAt}:{}}}}throw composerBusyApiError(error,taskId,prompt)}function composerBusyApiError(error,taskId,prompt){let layerText=error.layer==="recent-human-write"?"user was typing recently":"composer has text";return new ApiError(`task ${taskId}'s composer is busy (${layerText})`,"COMPOSER_BUSY",{layer:error.layer,hint:"wait a moment and retry, or spawn a fresh engine tab with --tab new",nextCommandArgs:["api","send","--task-id",taskId,"--prompt",prompt]})}var killTaskSessions=killHostedSessions;
3
+ export{ApiError,splitDaemonCode,helpStep,VERB_GROUP_IDS,taskEngineArgv,readTabsSnapshot,closeTabsSnapshot,renameTabsSnapshot,unregisteredTabIds,joinTaskTabs,publishCliTabSnapshot,markCliTabSession,mintCliTab,restoredTabLaunch,isTaskKey,findEngineKey,taskKeys,openPtyHost,ensurePtyHost,listSessions,listSessionsOrNull,deliverToKey,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON,outcomeFields,deliverHostedPrompt,resolveComposerManifest,deferOrThrow,killTaskSessions};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{KobeDaemonClient,RpcTimeoutError}from"./chunk-0wnfq5sx.js";import"./chunk-7j5372wb.js";import"./chunk-mnqxgvyb.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{RpcTimeoutError,KobeDaemonClient};
2
+ import{KobeDaemonClient,RpcTimeoutError}from"./chunk-0gepyh6e.js";import"./chunk-bkvr06xn.js";import"./chunk-mnqxgvyb.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{RpcTimeoutError,KobeDaemonClient};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ import{KobeDaemonClient}from"./chunk-0gepyh6e.js";import{isProcessAlive,readPidFile}from"./chunk-mv7ptt5w.js";import{unlink}from"fs/promises";async function stopDaemonProcess(socketPath,pidPath,opts={}){let oldPid=await readPidFile(pidPath),targetPid=oldPid!==null&&oldPid!==process.pid?oldPid:null,wasAlive=targetPid!==null&&isProcessAlive(targetPid),method=wasAlive?"graceful":"absent",client=new KobeDaemonClient(socketPath),stopRequest=client.request("daemon.stop",{reason:opts.reason??"stop"}).catch(()=>{return}),stopTimeout=new Promise((resolve)=>setTimeout(resolve,2000));if(await Promise.race([stopRequest,stopTimeout]),client.close(),wasAlive&&targetPid!==null){let deadline=Date.now()+5000,escalated=!1;while(Date.now()<deadline){try{process.kill(targetPid,0)}catch{break}if(!escalated&&Date.now()-(deadline-5000)>2000){try{process.kill(targetPid,"SIGTERM")}catch{}method="sigterm",escalated=!0}await new Promise((resolve)=>setTimeout(resolve,50))}try{process.kill(targetPid,0),process.kill(targetPid,"SIGKILL"),method="sigkill",await new Promise((resolve)=>setTimeout(resolve,100))}catch{}}let survivor=await readPidFile(pidPath);if(survivor!==null&&survivor!==process.pid&&isProcessAlive(survivor))return{pid:oldPid,method};return await unlink(socketPath).catch(()=>{}),await unlink(pidPath).catch(()=>{}),{pid:oldPid,method}}
3
+ export{stopDaemonProcess};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ import{errorMessage}from"./chunk-2brn8e1y.js";var PLACEHOLDER_TASK_TITLE="(new task)";function sanitizeTaskTitle(title){return title.replace(/[\u0000-\u0020\u007f]+/g," ").trim()}function deriveTitleFromPrompt(prompt){if(typeof prompt!=="string")return"";let collapsed=prompt.replace(/\s+/g," ").trim();if(collapsed.length===0)return"";let points=[...collapsed];if(points.length<=40)return collapsed;return`${points.slice(0,40).join("")}\u2026`}function isPlaceholderDerivedBranch(branch,taskId){let id6=taskId.slice(-6).toLowerCase();if(branch===`rove/new-task-${id6}`||branch===`kobe/new-task-${id6}`)return!0;return/^(?:[^/]+\/)?new-task(?:-\d+)?$/.test(branch)}class IllegalTransitionError extends Error{from;to;taskId;constructor(from,to,taskId){super(`illegal transition for task ${taskId}: ${from} -> ${to}`);this.from=from;this.to=to;this.taskId=taskId;this.name="IllegalTransitionError"}}class TaskNotFoundError extends Error{constructor(taskId){super(`task not found: ${taskId}`);this.name="TaskNotFoundError"}}class CannotDeleteMainTaskError extends Error{constructor(){super("cannot delete a main task; remove the repo from saved repos instead");this.name="CannotDeleteMainTaskError"}}var DIRTY_WORKTREE_CODE="DIRTY_WORKTREE";class DirtyWorktreeError extends Error{taskId;ignored;constructor(taskId,ignored=[]){let what=ignored==="unknown"?"gitignored work this check could not read (git status --ignored failed) \u2014 nothing here can confirm it is empty":ignored.length>0?`gitignored work git status cannot see: ${ignored.join(", ")}`:"uncommitted or untracked changes";super(`${DIRTY_WORKTREE_CODE}: task ${taskId} worktree has ${what}`);this.taskId=taskId;this.ignored=ignored;this.name="DirtyWorktreeError"}}class WorktreeRemoveFailedError extends Error{taskId;cause;constructor(taskId,cause){super(`failed to remove worktree for task ${taskId}: ${errorMessage(cause)}`);this.taskId=taskId;this.cause=cause;this.name="WorktreeRemoveFailedError"}}var TASK_DELETING_CODE="TASK_DELETING";class TaskDeletingError extends Error{taskId;constructor(taskId){super(`${TASK_DELETING_CODE}: task ${taskId} is being deleted`);this.taskId=taskId;this.name="TaskDeletingError"}}var MAIN_CHECKOUT_DIRTY_CODE="MAIN_CHECKOUT_DIRTY";class MainCheckoutDirtyError extends Error{repo;dir;constructor(repo,dir){super(`${MAIN_CHECKOUT_DIRTY_CODE}: base checkout at ${dir} has uncommitted changes; commit them before landing (never git stash \u2014 the stash stack is shared by every worktree of this repo)`);this.repo=repo;this.dir=dir;this.name="MainCheckoutDirtyError"}}var EMPTY_BRANCH_CODE="EMPTY_BRANCH";class EmptyBranchError extends Error{branch;landedOn;constructor(branch,landedOn){super(`${EMPTY_BRANCH_CODE}: '${branch}' has no commits ahead of '${landedOn}' \u2014 landing it would be a no-op (the worker may not have delivered anything)`);this.branch=branch;this.landedOn=landedOn;this.name="EmptyBranchError"}}var EMPTY_BRANCH_DIRTY_WORKTREE_CODE="EMPTY_BRANCH_DIRTY_WORKTREE";class EmptyBranchDirtyWorktreeError extends Error{branch;landedOn;worktreePath;files;constructor(branch,landedOn,worktreePath,files){let list=files.length>0?files.join(", "):"(none reported)";super(`${EMPTY_BRANCH_DIRTY_WORKTREE_CODE}: '${branch}' has no commits ahead of '${landedOn}' but its worktree ${worktreePath} has uncommitted changes (${list}) \u2014 commit them in the worktree first, then land again`);this.branch=branch;this.landedOn=landedOn;this.worktreePath=worktreePath;this.files=files;this.name="EmptyBranchDirtyWorktreeError"}}var MISSING_REF_CODE="MISSING_REF";class MissingRefError extends Error{branch;landedOn;dir;constructor(branch,landedOn,dir){super(`${MISSING_REF_CODE}: '${branch}' does not resolve in the base repo at ${dir} (comparing against '${landedOn}') \u2014 the branch was renamed or deleted outside Rove; re-point the task with \`rove api set-branch\` or recreate the branch`);this.branch=branch;this.landedOn=landedOn;this.dir=dir;this.name="MissingRefError"}}var LAND_CONFLICT_CODE="LAND_CONFLICT";class LandConflictError extends Error{taskId;branch;files;constructor(taskId,branch,files){let list=files.length>0?files.join(", "):"(none reported)";super(`${LAND_CONFLICT_CODE}: merging '${branch}' hit conflicts, merge aborted \u2014 conflicted files: ${list}`);this.taskId=taskId;this.branch=branch;this.files=files;this.name="LandConflictError"}}var GIT_COMMAND_FAILED_CODE="GIT_COMMAND_FAILED";class GitCommandFailedError extends Error{command;stderr;constructor(command,stderr,hint){let detail=stderr.trim()||"(git printed nothing on stderr)";super(`${GIT_COMMAND_FAILED_CODE}: \`git ${command}\` failed \u2014 ${detail}${hint?`; ${hint}`:""}`);this.command=command;this.stderr=stderr;this.name="GitCommandFailedError"}}
3
+ export{PLACEHOLDER_TASK_TITLE,sanitizeTaskTitle,deriveTitleFromPrompt,isPlaceholderDerivedBranch,IllegalTransitionError,TaskNotFoundError,CannotDeleteMainTaskError,DIRTY_WORKTREE_CODE,DirtyWorktreeError,WorktreeRemoveFailedError,TASK_DELETING_CODE,TaskDeletingError,MainCheckoutDirtyError,EmptyBranchError,EMPTY_BRANCH_DIRTY_WORKTREE_CODE,EmptyBranchDirtyWorktreeError,MissingRefError,LandConflictError,GitCommandFailedError};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{applyOnboardingChoices,detectShell,envReadyForTasks,installCompletions,maybeRunOnboarding}from"./chunk-a5e8vwvn.js";import"./chunk-q4428qws.js";import"./chunk-edeh4d1v.js";import"./chunk-da9tb8av.js";import"./chunk-bxqbw3h4.js";import"./chunk-2fjr0ajp.js";import"./chunk-vhrfe63r.js";import"./chunk-zg3wezj6.js";import"./chunk-rvybphrq.js";import"./chunk-xhb03ybc.js";import"./chunk-sdyzxayr.js";import"./chunk-jvxh93nz.js";import"./chunk-etnnwbdx.js";import"./chunk-crdag2rc.js";import"./chunk-khj0apc7.js";import"./chunk-nzscq4yf.js";import"./chunk-w7zv47mp.js";import"./chunk-6tvrvekq.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-k1qe5qqa.js";import"./chunk-xy8be792.js";import"./chunk-6wpege0h.js";import"./chunk-j75axe29.js";import"./chunk-ayhhgfsz.js";import"./chunk-2brn8e1y.js";import"./chunk-bq3fyc0p.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-mv7ptt5w.js";import"./chunk-v0zxyqrq.js";import"./chunk-e29hx18x.js";import"./chunk-g56kvet6.js";import"./chunk-pxk2c2vj.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{maybeRunOnboarding,installCompletions,envReadyForTasks,detectShell,applyOnboardingChoices};
@@ -1,8 +1,8 @@
1
1
  // @bun
2
- import{checkOnboardingEnv,noEngineAction}from"./chunk-n7rhhjta.js";import{isNpxMissing,markSkillHintSeen,npxSkillsArgv,npxSkillsCommand}from"./chunk-bpkg51p5.js";import{LAST_RUN_VERSION_KEY}from"./chunk-g8725q49.js";import{t}from"./chunk-nwe9c7x6.js";import{getPersistedBool,loadStateFile,setPersistedBool}from"./chunk-j75axe29.js";import{activeCliName}from"./chunk-v0zxyqrq.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{appendFileSync,existsSync,mkdirSync,readFileSync,writeFileSync}from"fs";import{homedir}from"os";import{basename,join}from"path";var ONBOARDED_KEY="onboarded",PRIMER_KEY="onboardedPrimer";function detectShell(env=process.env){let shell=basename(env.SHELL??"");return shell==="zsh"||shell==="bash"||shell==="fish"?shell:null}function installCompletions(shell,home=homedir(),cli=activeCliName()){let rcMarker=`${cli} completions`;if(shell==="fish"){let dir=join(home,".config","fish","completions"),path=join(dir,`${cli}.fish`);return mkdirSync(dir,{recursive:!0}),writeFileSync(path,`${cli} completions fish | source
2
+ import{checkOnboardingEnv,noEngineAction}from"./chunk-q4428qws.js";import{isNpxMissing,markSkillHintSeen,npxSkillsArgv,npxSkillsCommand}from"./chunk-da9tb8av.js";import{LAST_RUN_VERSION_KEY}from"./chunk-bxqbw3h4.js";import{t}from"./chunk-rvybphrq.js";import{getPersistedBool,loadStateFile,setPersistedBool}from"./chunk-j75axe29.js";import{activeCliName}from"./chunk-v0zxyqrq.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{appendFileSync,existsSync,mkdirSync,readFileSync,writeFileSync}from"fs";import{homedir}from"os";import{basename,join}from"path";var ONBOARDED_KEY="onboarded",PRIMER_KEY="onboardedPrimer";function detectShell(env=process.env){let shell=basename(env.SHELL??"");return shell==="zsh"||shell==="bash"||shell==="fish"?shell:null}function installCompletions(shell,home=homedir(),cli=activeCliName()){let rcMarker=`${cli} completions`;if(shell==="fish"){let dir=join(home,".config","fish","completions"),path=join(dir,`${cli}.fish`);return mkdirSync(dir,{recursive:!0}),writeFileSync(path,`${cli} completions fish | source
3
3
  `),path}let rc=join(home,shell==="zsh"?".zshrc":".bashrc");if(!(existsSync(rc)?readFileSync(rc,"utf8"):"").includes(rcMarker)){let line=`
4
4
  # ${cli} completions
5
5
  command -v ${cli} >/dev/null && source <(${cli} completions ${shell})
6
6
  `;appendFileSync(rc,line)}return rc}function isOnboarded(){return getPersistedBool(ONBOARDED_KEY,!1)}function markOnboarded(){setPersistedBool(ONBOARDED_KEY,!0)}function isPrimerDone(){return getPersistedBool(PRIMER_KEY,!1)}function markPrimerDone(){setPersistedBool(PRIMER_KEY,!0)}function backfillPrimerForExistingUsers(){if(typeof loadStateFile()[LAST_RUN_VERSION_KEY]!=="string")return!1;return markPrimerDone(),!0}function envReadyForTasks(env){return env.engines.anyUsable&&env.git.found}function applyOnboardingChoices(choices,shell,env){let cli=activeCliName(),completionsHelp=`${cli} completions --help`,skillInstall=`${cli} skill install`,out=(line)=>process.stdout.write(`${line}
7
- `);if(shell!==null)if(choices.completions)out(t("onboarding.appliedCompletions",{path:installCompletions(shell)}));else out(t("onboarding.skippedCompletions",{command:completionsHelp}));if(choices.skill){if(isNpxMissing())out(t("onboarding.skillNeedsNode",{command:skillInstall}));else if(out(t("onboarding.installingSkill",{command:npxSkillsCommand()})),spawnSync("npx",npxSkillsArgv(),{stdio:"inherit"}).status!==0)out(t("onboarding.skillFailed",{command:skillInstall}))}else out(t("onboarding.skippedSkill",{command:skillInstall})),markSkillHintSeen();out(""),out(env.git.line);for(let line of env.engines.lines)out(line);if(out(""),envReadyForTasks(env))out(t("onboarding.ready")),out(t("onboarding.readyHint",{command:cli}));else{if(out(t("onboarding.notReadyHeader")),!env.engines.anyUsable)out(` \u2192 ${noEngineAction(env.engines.signedOut)}`);if(!env.git.found)out(` \u2192 ${t("doctor.fix.gitAction")}`)}}async function maybeRunOnboarding(){if(!process.stdout.isTTY||!process.stdin.isTTY)return!1;let seen=isOnboarded();if(seen&&(isPrimerDone()||backfillPrimerForExistingUsers()))return!1;markOnboarded();let shell=detectShell(),env=await checkOnboardingEnv(),{runOnboardingWizard}=await import("./chunk-2ra4990w.js"),choices=await runOnboardingWizard(shell,env,seen?"primer":"full");return markPrimerDone(),applyOnboardingChoices(choices,shell,env),!0}
7
+ `);if(shell!==null)if(choices.completions)out(t("onboarding.appliedCompletions",{path:installCompletions(shell)}));else out(t("onboarding.skippedCompletions",{command:completionsHelp}));if(choices.skill){if(isNpxMissing())out(t("onboarding.skillNeedsNode",{command:skillInstall}));else if(out(t("onboarding.installingSkill",{command:npxSkillsCommand()})),spawnSync("npx",npxSkillsArgv(),{stdio:"inherit"}).status!==0)out(t("onboarding.skillFailed",{command:skillInstall}))}else out(t("onboarding.skippedSkill",{command:skillInstall})),markSkillHintSeen();out(""),out(env.git.line);for(let line of env.engines.lines)out(line);if(out(""),envReadyForTasks(env))out(t("onboarding.ready")),out(t("onboarding.readyHint",{command:cli}));else{if(out(t("onboarding.notReadyHeader")),!env.engines.anyUsable)out(` \u2192 ${noEngineAction(env.engines.signedOut)}`);if(!env.git.found)out(` \u2192 ${t("doctor.fix.gitAction")}`)}}async function maybeRunOnboarding(){if(!process.stdout.isTTY||!process.stdin.isTTY)return!1;let seen=isOnboarded();if(seen&&(isPrimerDone()||backfillPrimerForExistingUsers()))return!1;markOnboarded();let shell=detectShell(),env=await checkOnboardingEnv(),{runOnboardingWizard}=await import("./chunk-px3r9sh6.js"),choices=await runOnboardingWizard(shell,env,seen?"primer":"full");return markPrimerDone(),applyOnboardingChoices(choices,shell,env),!0}
8
8
  export{detectShell,installCompletions,envReadyForTasks,applyOnboardingChoices,maybeRunOnboarding};