@sma1lboy/rove 0.9.283-next.83 → 0.9.283-next.87

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 (85) hide show
  1. package/dist/cli/{chunk-m1mjs3f4.js → chunk-0annhyhx.js} +1 -1
  2. package/dist/cli/{chunk-rjq38twt.js → chunk-0m8javx8.js} +1 -1
  3. package/dist/cli/{chunk-mggn3mpv.js → chunk-0xns9fat.js} +2 -2
  4. package/dist/cli/{chunk-vyf8db6m.js → chunk-1djv9khj.js} +1 -1
  5. package/dist/cli/{chunk-895yqjjz.js → chunk-22emnsn5.js} +1 -1
  6. package/dist/cli/{chunk-kdnk8m5j.js → chunk-23maf8ch.js} +1 -1
  7. package/dist/cli/{chunk-p57nmt27.js → chunk-2wbawmm7.js} +1 -1
  8. package/dist/cli/{chunk-r31m12fg.js → chunk-3dykyxev.js} +1 -1
  9. package/dist/cli/{chunk-69a12c29.js → chunk-429zca0e.js} +1 -1
  10. package/dist/cli/{chunk-f39gzktx.js → chunk-45a1xqc4.js} +1 -1
  11. package/dist/cli/{chunk-03a986ba.js → chunk-4xg2z7td.js} +1 -1
  12. package/dist/cli/{chunk-w7v71t7e.js → chunk-53pn0a9z.js} +1 -1
  13. package/dist/cli/{chunk-za8pnw78.js → chunk-5x9j58xk.js} +1 -1
  14. package/dist/cli/{chunk-p3dx82js.js → chunk-82396cad.js} +1 -1
  15. package/dist/cli/{chunk-x1ghdmp1.js → chunk-8ac8k0ba.js} +1 -1
  16. package/dist/cli/{chunk-cbde2ne7.js → chunk-8damx2w0.js} +1 -1
  17. package/dist/cli/{chunk-ph9m6y5j.js → chunk-8hk78wty.js} +1 -1
  18. package/dist/cli/{chunk-9rj2fx6v.js → chunk-8ttn73cv.js} +1 -1
  19. package/dist/cli/{chunk-ej4hxx4n.js → chunk-8ww1e4nk.js} +1 -1
  20. package/dist/cli/{chunk-j4tmz36m.js → chunk-9jjs5wev.js} +1 -1
  21. package/dist/cli/{chunk-2z2yea9t.js → chunk-9snqpah0.js} +1 -1
  22. package/dist/cli/{chunk-gqq51hqn.js → chunk-9vnbp5db.js} +1 -1
  23. package/dist/cli/{chunk-g6bybfvj.js → chunk-adsfeq6x.js} +1 -1
  24. package/dist/cli/chunk-an97ga8b.js +2 -0
  25. package/dist/cli/{chunk-hg7dcrzp.js → chunk-anabgqs3.js} +1 -1
  26. package/dist/cli/{chunk-62031m45.js → chunk-b4kt1vgx.js} +1 -1
  27. package/dist/cli/{chunk-hzz020xx.js → chunk-betn5ma1.js} +1 -1
  28. package/dist/cli/{chunk-p52m8g2j.js → chunk-bkgg6zam.js} +1 -1
  29. package/dist/cli/{chunk-p2cbtrzg.js → chunk-c8qjy6rx.js} +1 -1
  30. package/dist/cli/{chunk-agvtzads.js → chunk-cacct9gd.js} +1 -1
  31. package/dist/cli/{chunk-6nb07k2x.js → chunk-cfpnv798.js} +1 -1
  32. package/dist/cli/{chunk-p8we9f3k.js → chunk-dznh9kx4.js} +2 -2
  33. package/dist/cli/{chunk-rxh8br67.js → chunk-eae2x886.js} +1 -1
  34. package/dist/cli/{chunk-1vxtd8rh.js → chunk-ee8917py.js} +1 -1
  35. package/dist/cli/{chunk-zpxpwgds.js → chunk-eyaaaprw.js} +1 -1
  36. package/dist/cli/{chunk-49nb02t5.js → chunk-eznnpst5.js} +1 -1
  37. package/dist/cli/{chunk-6mg5zp8y.js → chunk-f0bzvv0q.js} +1 -1
  38. package/dist/cli/{chunk-p7nxvnfk.js → chunk-f7a84zv4.js} +6 -6
  39. package/dist/cli/{chunk-22h75r7p.js → chunk-ggj5ctkj.js} +1 -1
  40. package/dist/cli/chunk-gygdyf0s.js +3 -0
  41. package/dist/cli/{chunk-pqc8bnsf.js → chunk-h27064am.js} +1 -1
  42. package/dist/cli/{chunk-bvye6se6.js → chunk-ha4hfk67.js} +5 -5
  43. package/dist/cli/{chunk-4gjvmfa9.js → chunk-hgtf6yvg.js} +5 -5
  44. package/dist/cli/{chunk-nzrz817m.js → chunk-hszg99pb.js} +1 -1
  45. package/dist/cli/{chunk-3x5g06mw.js → chunk-jkssty8x.js} +1 -1
  46. package/dist/cli/{chunk-k3h4cpdy.js → chunk-jn8fkzm7.js} +1 -1
  47. package/dist/cli/{chunk-5rgrde6b.js → chunk-jnt3nf6w.js} +1 -1
  48. package/dist/cli/{chunk-5pp9pvcm.js → chunk-k77ysa7w.js} +1 -1
  49. package/dist/cli/{chunk-accvxt25.js → chunk-ktwc1sqw.js} +1 -1
  50. package/dist/cli/{chunk-7zn9xwsn.js → chunk-mcq5ykax.js} +1 -1
  51. package/dist/cli/{chunk-4w4tpsqx.js → chunk-mkb5mmmw.js} +1 -1
  52. package/dist/cli/{chunk-w5maz87g.js → chunk-mma7qne2.js} +1 -1
  53. package/dist/cli/{chunk-f2151ses.js → chunk-mn6c0wkc.js} +1 -1
  54. package/dist/cli/{chunk-qk7h3fe6.js → chunk-n3ewtd3b.js} +3 -3
  55. package/dist/cli/{chunk-dsdtq087.js → chunk-nf1gqqv8.js} +1 -1
  56. package/dist/cli/{chunk-teh40faw.js → chunk-np319fys.js} +1 -1
  57. package/dist/cli/{chunk-y8bdxdnn.js → chunk-p280v5bb.js} +1 -1
  58. package/dist/cli/{chunk-ggnq2vvk.js → chunk-paashxkd.js} +1 -1
  59. package/dist/cli/{chunk-yeq2pc68.js → chunk-pebgqr0z.js} +1 -1
  60. package/dist/cli/{chunk-ec3esgj4.js → chunk-pmz7t8xx.js} +1 -1
  61. package/dist/cli/{chunk-zr058kbe.js → chunk-qnv8ggxh.js} +1 -1
  62. package/dist/cli/{chunk-0w34a8nh.js → chunk-qt77g0de.js} +1 -1
  63. package/dist/cli/{chunk-sakkdjyn.js → chunk-qtx79czn.js} +1 -1
  64. package/dist/cli/chunk-rmnm3f9n.js +3 -0
  65. package/dist/cli/{chunk-zr6z1hm5.js → chunk-rvew27yy.js} +2 -2
  66. package/dist/cli/{chunk-s43e89pz.js → chunk-td6rb53y.js} +1 -1
  67. package/dist/cli/{chunk-f41wwawh.js → chunk-tv4mbxyj.js} +1 -1
  68. package/dist/cli/{chunk-b0avcx47.js → chunk-vswtpcz6.js} +1 -1
  69. package/dist/cli/{chunk-mz72jber.js → chunk-w4b9nc3w.js} +1 -1
  70. package/dist/cli/chunk-x7fmexjc.js +2 -0
  71. package/dist/cli/{chunk-5e6w2rd9.js → chunk-xb196wqg.js} +1 -1
  72. package/dist/cli/{chunk-ydb5bhbh.js → chunk-xehd2vx3.js} +1 -1
  73. package/dist/cli/{chunk-16e6jqq6.js → chunk-xr117xs9.js} +1 -1
  74. package/dist/cli/{chunk-z8yqymtf.js → chunk-xs6w6ekc.js} +1 -1
  75. package/dist/cli/{chunk-rncwyqgr.js → chunk-ycb9tyj3.js} +1 -1
  76. package/dist/cli/{chunk-qecygh3f.js → chunk-ypfrkpe9.js} +1 -1
  77. package/dist/cli/{chunk-jj5f4n51.js → chunk-z3hfz52n.js} +1 -1
  78. package/dist/cli/{chunk-ymv2xeq4.js → chunk-zdwtxp16.js} +1 -1
  79. package/dist/cli/index.js +7 -7
  80. package/dist/cli/pty-host-node.mjs +3 -1
  81. package/package.json +1 -1
  82. package/dist/cli/chunk-hv79ys32.js +0 -2
  83. package/dist/cli/chunk-rfp0ayra.js +0 -3
  84. package/dist/cli/chunk-tq0h3vy6.js +0 -3
  85. package/dist/cli/chunk-z8rvxvx5.js +0 -2
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{deriveTitleFromPrompt}from"./chunk-2xsxcdp6.js";import{TaskDeletingError}from"./chunk-1vxtd8rh.js";import{awaitEngineProcess,deliverToHostedKey,enginePresence,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp}from"./chunk-ydb5bhbh.js";import{buildEngineSessionLaunch,launchReposOf,trustEngineWorktree,trustExtraRepos}from"./chunk-qecygh3f.js";import{engineLaunchArgv,protocolEntry}from"./chunk-rjq38twt.js";import{hostedKeyFor}from"./chunk-g9ba25q5.js";import{resolveSessionShell}from"./chunk-tn9gtf18.js";import{taskCwd}from"./chunk-x1jxxmtc.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);let hasExtras=Boolean(task.extraRepos?.length);if(task.worktreePath&&!hasExtras){let repos=task.sharesWorkspaceOf?await launchReposOf(link,taskId):void 0;return{task,worktreePath:taskCwd(task),repos}}let{worktreePath}=await link.request("task.ensureWorktree",{taskId});if(!worktreePath)throw Error(`task ${taskId} has no worktree`);return{task,worktreePath:taskCwd({worktreePath,cwdSubpath:task.cwdSubpath}),repos:hasExtras||task.sharesWorkspaceOf?await launchReposOf(link,taskId):void 0}}async function ensureTaskSessionAdapter(link,taskId){let{task,worktreePath,repos}=await ensureTaskWorktree(link,taskId),launch=taskEngineLaunch(task,worktreePath,{kind:"repo-init"},repos),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,model:task.model})[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,repos}=await ensureTaskWorktree(link,taskId);await link.request("task.observeLanguage",{taskId,text:prompt}).catch(()=>{});let launch=taskEngineLaunch(task,worktreePath,{kind:"new-task",prompt},repos),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,model:task.model})[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,repos){return trustEngineWorktree(task.vendor,worktreePath),trustExtraRepos(task.vendor,repos),buildEngineSessionLaunch({task:{id:task.id,kind:task.kind,vendor:task.vendor,repo:task.repo,repos},worktreePath,shell:resolveSessionShell(),argv:engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort,model:task.model}),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],task.scope);if(!key)return!1;let presence=await enginePresence(sessions.find((s)=>s.key===key)?.pid,engineArgv);if(presence.kind!=="engine")return!1;return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})!==null}catch{return!1}finally{host.close()}}function tabIdFromHostedKey(key){return key.split("::")[1]??"tab-1"}async function deliverPromptToLiveEngineDetailedAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0],task.scope);if(!key)return{outcome:"no-session"};let presence=await enginePresence(sessions.find((s)=>s.key===key)?.pid,engineArgv);if(presence.kind!=="engine")return{outcome:"no-engine",tabId:tabIdFromHostedKey(key)};return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:tabIdFromHostedKey(key)}}catch{return{outcome:"no-session"}}finally{host.close()}}async function deliverPromptToLiveEngineTabDetailedAdapter(target,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let key=hostedKeyFor(target.id,target.tabId,target.scope);if(!key)return{outcome:"no-session"};let sessions;try{sessions=await listHostedSessions(host.rpc)}catch{return{outcome:"no-session"}}let session=sessions.find((candidate)=>candidate.alive&&candidate.key===key);if(!session)return{outcome:"no-session"};let engineArgv=engineLaunchArgv({command:target.command,vendor:target.vendor}),presence=await enginePresence(session.pid,engineArgv);if(presence.kind!=="engine")return{outcome:"no-engine",tabId:target.tabId};return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:target.tabId}}finally{host.close()}}async function tearDownTaskSessionAdapter(taskId,scope){let host=await openHostedSessionHost();if(!host)return;try{let keys=hostedTaskKeys(await listHostedSessions(host.rpc),taskId,scope);await killHostedSessions(host.rpc,keys,{wait:!0})}catch{}finally{host.close()}}
2
+ import{deriveTitleFromPrompt}from"./chunk-2xsxcdp6.js";import{TaskDeletingError}from"./chunk-ee8917py.js";import{awaitEngineProcess,deliverToHostedKey,enginePresence,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp}from"./chunk-xehd2vx3.js";import{buildEngineSessionLaunch,launchReposOf,trustEngineWorktree,trustExtraRepos}from"./chunk-ypfrkpe9.js";import{engineLaunchArgv,protocolEntry}from"./chunk-0m8javx8.js";import{hostedKeyFor}from"./chunk-g9ba25q5.js";import{resolveSessionShell}from"./chunk-tn9gtf18.js";import{taskCwd}from"./chunk-x1jxxmtc.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);let hasExtras=Boolean(task.extraRepos?.length);if(task.worktreePath&&!hasExtras){let repos=task.sharesWorkspaceOf?await launchReposOf(link,taskId):void 0;return{task,worktreePath:taskCwd(task),repos}}let{worktreePath}=await link.request("task.ensureWorktree",{taskId});if(!worktreePath)throw Error(`task ${taskId} has no worktree`);return{task,worktreePath:taskCwd({worktreePath,cwdSubpath:task.cwdSubpath}),repos:hasExtras||task.sharesWorkspaceOf?await launchReposOf(link,taskId):void 0}}async function ensureTaskSessionAdapter(link,taskId){let{task,worktreePath,repos}=await ensureTaskWorktree(link,taskId),launch=taskEngineLaunch(task,worktreePath,{kind:"repo-init"},repos),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,model:task.model})[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,repos}=await ensureTaskWorktree(link,taskId);await link.request("task.observeLanguage",{taskId,text:prompt}).catch(()=>{});let launch=taskEngineLaunch(task,worktreePath,{kind:"new-task",prompt},repos),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,model:task.model})[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,repos){return trustEngineWorktree(task.vendor,worktreePath),trustExtraRepos(task.vendor,repos),buildEngineSessionLaunch({task:{id:task.id,kind:task.kind,vendor:task.vendor,repo:task.repo,repos},worktreePath,shell:resolveSessionShell(),argv:engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort,model:task.model}),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],task.scope);if(!key)return!1;let presence=await enginePresence(sessions.find((s)=>s.key===key)?.pid,engineArgv);if(presence.kind!=="engine")return!1;return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})!==null}catch{return!1}finally{host.close()}}function tabIdFromHostedKey(key){return key.split("::")[1]??"tab-1"}async function deliverPromptToLiveEngineDetailedAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0],task.scope);if(!key)return{outcome:"no-session"};let presence=await enginePresence(sessions.find((s)=>s.key===key)?.pid,engineArgv);if(presence.kind!=="engine")return{outcome:"no-engine",tabId:tabIdFromHostedKey(key)};return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:tabIdFromHostedKey(key)}}catch{return{outcome:"no-session"}}finally{host.close()}}async function deliverPromptToLiveEngineTabDetailedAdapter(target,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let key=hostedKeyFor(target.id,target.tabId,target.scope);if(!key)return{outcome:"no-session"};let sessions;try{sessions=await listHostedSessions(host.rpc)}catch{return{outcome:"no-session"}}let session=sessions.find((candidate)=>candidate.alive&&candidate.key===key);if(!session)return{outcome:"no-session"};let engineArgv=engineLaunchArgv({command:target.command,vendor:target.vendor}),presence=await enginePresence(session.pid,engineArgv);if(presence.kind!=="engine")return{outcome:"no-engine",tabId:target.tabId};return await deliverToHostedKey(host.rpc,key,prompt,{vendor:presence.vendor})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:target.tabId}}finally{host.close()}}async function tearDownTaskSessionAdapter(taskId,scope){let host=await openHostedSessionHost();if(!host)return;try{let keys=hostedTaskKeys(await listHostedSessions(host.rpc),taskId,scope);await killHostedSessions(host.rpc,keys,{wait:!0})}catch{}finally{host.close()}}
3
3
  export{deriveTitleFromSession,deriveTitleFromSessionId,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,tearDownTaskSessionAdapter};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{vendorFromArgv}from"./chunk-5rgrde6b.js";import{engineEntry}from"./chunk-4gjvmfa9.js";import{isContribEngine}from"./chunk-hzz020xx.js";import{getCustomEngineIds,getPersistedString}from"./chunk-rfp0ayra.js";import{roveCliInvocation}from"./chunk-8qkyd589.js";import{BUILTIN_VENDORS,coerceVendorId,isBuiltinVendor}from"./chunk-h2m7em1e.js";function engineCommandKey(vendor){return`engineCommand.${vendor}`}function engineNameKey(vendor){return`engineName.${vendor}`}function engineDisplayName(vendor){return getPersistedString(engineNameKey(vendor))?.trim()||engineEntry(vendor).displayName}function humanizeSlug(id){return id.split(/[-_]+/).filter((word)=>word.length>0).map((word)=>word.charAt(0).toUpperCase()+word.slice(1)).join(" ")}function engineRenamedFrom(vendor,override){let name=override.trim(),base=engineEntry(vendor).displayName;if(!name||name===base||name===humanizeSlug(vendor))return;return base}function defaultEngineCommand(vendor){return engineEntry(coerceVendorId(vendor)).defaultCommand}function parseEngineCommand(command){let out=[],token="",hasToken=!1,quote=null;for(let ch of command){if(quote){if(ch===quote)quote=null;else token+=ch;continue}if(ch==='"'||ch==="'"){quote=ch,hasToken=!0;continue}if(/\s/.test(ch)){if(hasToken)out.push(token),token="",hasToken=!1;continue}token+=ch,hasToken=!0}if(hasToken)out.push(token);return out}function interactiveEngineCommand(vendor,effort,model){let v=coerceVendorId(vendor),override=getPersistedString(engineCommandKey(v))?.trim(),base=(()=>{if(override){let argv=parseEngineCommand(override);if(argv.length>0)return argv}return defaultEngineCommand(v)})();return withEngineHostedArgs(withEngineModel(withEngineEffort(base,v,effort),v,model),v)}function withEngineHostedArgs(argv,vendor){let entry=engineEntry(coerceVendorId(vendor)),args=entry.terminalTitle?.launchArgs,titled=args&&args.length>0?[...argv,...args]:argv;return entry.hostedStartArgv?.(titled)??titled}function withEngineEffort(argv,vendor,effort){let trimmed=effort?.trim();if(!trimmed)return argv;let entry=engineEntry(coerceVendorId(vendor));if(!entry.effortLevels?.includes(trimmed))return argv;return entry.effortArgv?.(argv,trimmed)??argv}function withEngineModel(argv,vendor,model){let trimmed=model?.trim();if(!trimmed)return argv;return engineEntry(coerceVendorId(vendor)).modelArgv?.(argv,trimmed)??argv}function roveApiInvocation(){let quote=(a)=>/^[A-Za-z0-9_/.:=-]+$/.test(a)?a:`'${a.replace(/'/g,"'\\''")}'`;try{return[...roveCliInvocation(),"api"].map(quote).join(" ")}catch{return"rove api"}}import{randomUUID}from"crypto";function hasFlag(argv,flag){return argv.some((a)=>a===flag||a.startsWith(`${flag}=`))}function controlsOwnSession(identity,argv){return(identity?.sessionControlFlags??[]).some((flag)=>hasFlag(argv,flag))}function pinSessionArgv(identity,argv,sessionId){if(!identity?.pinFlag)return argv;if(controlsOwnSession(identity,argv))return argv;return[...argv,identity.pinFlag,sessionId]}function acceptsPinnedSession(identity,argv){return!!identity?.pinFlag&&!controlsOwnSession(identity,argv)}function resumeSessionArgv(identity,base,sessionId){if(!sessionId||!identity?.resumeArgv)return null;if(controlsOwnSession(identity,base))return null;return identity.resumeArgv(base,sessionId)}function pickUnclaimedSessionId(ids,claimed){for(let i=ids.length-1;i>=0;i--){let id=ids[i];if(id&&!claimed.has(id))return id}return null}function forkSessionArgvFor(identity,base,sourceId,newId){if(!sourceId||!identity?.forkArgv)return null;if(controlsOwnSession(identity,base))return null;return identity.forkArgv(base,sourceId,newId)}function acceptsSessionFork(identity){return!!identity?.forkArgv}var GENERIC_PROTOCOL="generic",ENGINE_PROTOCOLS=BUILTIN_VENDORS;function engineProtocolKey(id){return`engineProtocol.${id}`}function getEngineProtocol(id){if(isBuiltinVendor(id)||isContribEngine(id))return id;let raw=getPersistedString(engineProtocolKey(id))?.trim();return raw&&ENGINE_PROTOCOLS.includes(raw)?raw:void 0}function isPresetId(id){return isBuiltinVendor(id)||isContribEngine(id)||getCustomEngineIds().includes(id)}function listPresetIds(){return[...new Set([...BUILTIN_VENDORS,...getCustomEngineIds()])]}function describePreset(id){let command=getPersistedString(engineCommandKey(id))?.trim()||defaultEngineCommand(id).join(" ");return{id,name:engineDisplayName(id),command,protocol:getEngineProtocol(id)??GENERIC_PROTOCOL,builtin:isBuiltinVendor(id)}}function listEnginePresets(){return listPresetIds().map(describePreset)}function resolveCommandProtocol(command){let trimmed=command?.trim();if(!trimmed)return GENERIC_PROTOCOL;if(isPresetId(trimmed))return getEngineProtocol(trimmed)??GENERIC_PROTOCOL;let fromArgv=vendorFromArgv(trimmed);if(fromArgv)return fromArgv;let argv0=parseEngineCommand(trimmed)[0];if(argv0)for(let id of getCustomEngineIds()){let preset=getPersistedString(engineCommandKey(id))?.trim();if(preset&&parseEngineCommand(preset)[0]===argv0)return getEngineProtocol(id)??GENERIC_PROTOCOL}return GENERIC_PROTOCOL}function engineLaunchArgv(spec){let command=spec.command?.trim();if(!command)return interactiveEngineCommand(spec.vendor,spec.effort,spec.model);let vendor=(isPresetId(command)?getEngineProtocol(command):void 0)??resolveCommandProtocol(command),base=isPresetId(command)?presetBaseArgv(command):(()=>{let argv=parseEngineCommand(command);return argv.length>0?argv:null})();if(!base)return interactiveEngineCommand(spec.vendor,spec.effort,spec.model);return withEngineHostedArgs(withEngineModel(withEngineEffort(base,vendor,spec.effort),vendor,spec.model),vendor)}function presetBaseArgv(id){let override=getPersistedString(engineCommandKey(id))?.trim();if(override){let argv=parseEngineCommand(override);if(argv.length>0)return argv}return defaultEngineCommand(id)}function sessionProtocol(vendor){let id=vendor?.trim();if(!id)return"claude";return getEngineProtocol(id)??id}function protocolEntry(vendor){return engineEntry(sessionProtocol(vendor))}function withPinnedSessionId(argv,vendor,newId=randomUUID){let identity=engineEntry(sessionProtocol(vendor)).sessionIdentity;if(!acceptsPinnedSession(identity,argv))return{argv,sessionId:null};let sessionId=newId();return{argv:pinSessionArgv(identity,argv,sessionId),sessionId}}function engineResumeArgv(base,vendor,sessionId){return resumeSessionArgv(engineEntry(sessionProtocol(vendor)).sessionIdentity,base,sessionId)}function engineCanFork(vendor){return acceptsSessionFork(engineEntry(sessionProtocol(vendor)).sessionIdentity)}function engineForkArgv(base,vendor,sourceId,newId){return forkSessionArgvFor(engineEntry(sessionProtocol(vendor)).sessionIdentity,base,sourceId,newId)}var ID_RE=/^tab-(\d+)$/;function tabOrdinalOf(id){let match=ID_RE.exec(id);return match?Number(match[1]):null}var sameValue=(a,b)=>a===b||JSON.stringify(a)===JSON.stringify(b);function insertAfter(tabs,row,after){if(after===null)return[row,...tabs];let i=after===void 0?-1:tabs.findIndex((t)=>t.id===after);return i<0?[...tabs,row]:[...tabs.slice(0,i+1),row,...tabs.slice(i+1)]}function applyTabOps(current,ops,tombstones=new Set){let state=current,changed=!1,opened=[],set=(next)=>{state=next,changed=!0};for(let op of ops)switch(op.op){case"seed":{if(state===null||state.tabs.length===0){let floor=Math.max(op.state.nextOrdinal,maxOrdinal(op.state)+1,state?.nextOrdinal??0);set({...op.state,nextOrdinal:floor})}break}case"forget":{if(state!==null)set(null);break}case"open":{let base=state??{tabs:[],nextOrdinal:1},wanted=op.row.id;if(wanted!==void 0&&(base.tabs.some((t)=>t.id===wanted)||tombstones.has(wanted))){opened.push(null);break}let ordinal=wanted!==void 0?tabOrdinalOf(wanted)??op.row.ordinal??base.nextOrdinal:base.nextOrdinal,id=wanted??`tab-${ordinal}`,row={...op.row,id,ordinal};set({...base,tabs:insertAfter(base.tabs,row,op.after),nextOrdinal:Math.max(base.nextOrdinal,ordinal+1)}),opened.push(id);break}case"patch":{if(!state)break;let i=state.tabs.findIndex((t)=>t.id===op.id),row=state.tabs[i];if(!row)break;let next={...row},rowChanged=!1;for(let[key,value]of Object.entries(op.set??{})){if(key==="id"||key==="ordinal"||sameValue(next[key],value))continue;next[key]=value,rowChanged=!0}for(let key of op.unset??[]){if(key==="id"||key==="ordinal"||key==="kind"||!(key in next))continue;delete next[key],rowChanged=!0}if(!rowChanged)break;let tabs=[...state.tabs];tabs[i]=next,set({...state,tabs});break}case"close":{if(!state||!state.tabs.some((t)=>t.id===op.id))break;tombstones.add(op.id);let tabs=state.tabs.filter((t)=>t.id!==op.id),reopen=tabs.length===0&&op.reopenAs!==void 0?{reopenAs:op.reopenAs}:{},{activeId,...rest}=state;set({...rest,tabs,...activeId!==void 0&&activeId!==op.id?{activeId}:{},...reopen});break}case"order":{if(!state)break;let byId=new Map(state.tabs.map((t)=>[t.id,t])),tabs=[...op.ids.flatMap((id)=>{let row=byId.get(id);if(!row)return[];return byId.delete(id),[row]}),...state.tabs.filter((t)=>byId.has(t.id))];if(tabs.every((t,i)=>t===state?.tabs[i]))break;set({...state,tabs});break}case"focus":{if(!state||state.activeId===op.id||!state.tabs.some((t)=>t.id===op.id))break;set({...state,activeId:op.id});break}case"meta":{if(!state||sameValue(state.reopenAs,op.reopenAs))break;let{reopenAs:_drop,...rest}=state;set(op.reopenAs===void 0?rest:{...rest,reopenAs:op.reopenAs});break}}return{state,changed,opened}}function maxOrdinal(state){return state.tabs.reduce((max,tab)=>Math.max(max,tab.ordinal),0)}function reserveOrdinals(state,count){let base=state??{tabs:[],nextOrdinal:1},from=Math.max(base.nextOrdinal,maxOrdinal(base)+1);return{state:{...base,nextOrdinal:from+count},from}}function releaseOrdinals(state,from,to){if(!state||state.nextOrdinal!==to||from>=to)return state;let floor=Math.max(from,maxOrdinal(state)+1);return floor<state.nextOrdinal?{...state,nextOrdinal:floor}:state}function diffTabs(prev,next){if(prev===null)return[{op:"seed",state:next}];let ops=[],prevById=new Map(prev.tabs.map((t)=>[t.id,t])),nextIds=new Set(next.tabs.map((t)=>t.id));for(let row of prev.tabs){let reopen=next.tabs.length===0&&next.reopenAs!==void 0?{reopenAs:next.reopenAs}:{};if(!nextIds.has(row.id))ops.push({op:"close",id:row.id,...reopen})}next.tabs.forEach((row,i)=>{let before=prevById.get(row.id);if(!before){ops.push({op:"open",row,after:i===0?null:next.tabs[i-1]?.id??null});return}if(before===row)return;let set={},unset=[];for(let[key,value]of Object.entries(row))if(key!=="id"&&key!=="ordinal"&&!sameValue(before[key],value))set[key]=value;for(let key of Object.keys(before))if(!(key in row))unset.push(key);if(Object.keys(set).length>0||unset.length>0)ops.push({op:"patch",id:row.id,...Object.keys(set).length>0?{set}:{},...unset.length>0?{unset}:{}})});let kept=next.tabs.filter((t)=>prevById.has(t.id)).map((t)=>t.id),prevKept=prev.tabs.filter((t)=>nextIds.has(t.id)).map((t)=>t.id);if(kept.some((id,i)=>id!==prevKept[i]))ops.push({op:"order",ids:next.tabs.map((t)=>t.id)});if(!sameValue(prev.reopenAs,next.reopenAs)&&next.tabs.length>0)ops.push({op:"meta",reopenAs:next.reopenAs});return ops}
2
+ import{vendorFromArgv}from"./chunk-jnt3nf6w.js";import{engineEntry}from"./chunk-hgtf6yvg.js";import{isContribEngine}from"./chunk-betn5ma1.js";import{getCustomEngineIds,getPersistedString}from"./chunk-gygdyf0s.js";import{roveCliInvocation}from"./chunk-8qkyd589.js";import{BUILTIN_VENDORS,coerceVendorId,isBuiltinVendor}from"./chunk-h2m7em1e.js";function engineCommandKey(vendor){return`engineCommand.${vendor}`}function engineNameKey(vendor){return`engineName.${vendor}`}function engineDisplayName(vendor){return getPersistedString(engineNameKey(vendor))?.trim()||engineEntry(vendor).displayName}function humanizeSlug(id){return id.split(/[-_]+/).filter((word)=>word.length>0).map((word)=>word.charAt(0).toUpperCase()+word.slice(1)).join(" ")}function engineRenamedFrom(vendor,override){let name=override.trim(),base=engineEntry(vendor).displayName;if(!name||name===base||name===humanizeSlug(vendor))return;return base}function defaultEngineCommand(vendor){return engineEntry(coerceVendorId(vendor)).defaultCommand}function parseEngineCommand(command){let out=[],token="",hasToken=!1,quote=null;for(let ch of command){if(quote){if(ch===quote)quote=null;else token+=ch;continue}if(ch==='"'||ch==="'"){quote=ch,hasToken=!0;continue}if(/\s/.test(ch)){if(hasToken)out.push(token),token="",hasToken=!1;continue}token+=ch,hasToken=!0}if(hasToken)out.push(token);return out}function interactiveEngineCommand(vendor,effort,model){let v=coerceVendorId(vendor),override=getPersistedString(engineCommandKey(v))?.trim(),base=(()=>{if(override){let argv=parseEngineCommand(override);if(argv.length>0)return argv}return defaultEngineCommand(v)})();return withEngineHostedArgs(withEngineModel(withEngineEffort(base,v,effort),v,model),v)}function withEngineHostedArgs(argv,vendor){let entry=engineEntry(coerceVendorId(vendor)),args=entry.terminalTitle?.launchArgs,titled=args&&args.length>0?[...argv,...args]:argv;return entry.hostedStartArgv?.(titled)??titled}function withEngineEffort(argv,vendor,effort){let trimmed=effort?.trim();if(!trimmed)return argv;let entry=engineEntry(coerceVendorId(vendor));if(!entry.effortLevels?.includes(trimmed))return argv;return entry.effortArgv?.(argv,trimmed)??argv}function withEngineModel(argv,vendor,model){let trimmed=model?.trim();if(!trimmed)return argv;return engineEntry(coerceVendorId(vendor)).modelArgv?.(argv,trimmed)??argv}function roveApiInvocation(){let quote=(a)=>/^[A-Za-z0-9_/.:=-]+$/.test(a)?a:`'${a.replace(/'/g,"'\\''")}'`;try{return[...roveCliInvocation(),"api"].map(quote).join(" ")}catch{return"rove api"}}import{randomUUID}from"crypto";function hasFlag(argv,flag){return argv.some((a)=>a===flag||a.startsWith(`${flag}=`))}function controlsOwnSession(identity,argv){return(identity?.sessionControlFlags??[]).some((flag)=>hasFlag(argv,flag))}function pinSessionArgv(identity,argv,sessionId){if(!identity?.pinFlag)return argv;if(controlsOwnSession(identity,argv))return argv;return[...argv,identity.pinFlag,sessionId]}function acceptsPinnedSession(identity,argv){return!!identity?.pinFlag&&!controlsOwnSession(identity,argv)}function resumeSessionArgv(identity,base,sessionId){if(!sessionId||!identity?.resumeArgv)return null;if(controlsOwnSession(identity,base))return null;return identity.resumeArgv(base,sessionId)}function pickUnclaimedSessionId(ids,claimed){for(let i=ids.length-1;i>=0;i--){let id=ids[i];if(id&&!claimed.has(id))return id}return null}function forkSessionArgvFor(identity,base,sourceId,newId){if(!sourceId||!identity?.forkArgv)return null;if(controlsOwnSession(identity,base))return null;return identity.forkArgv(base,sourceId,newId)}function acceptsSessionFork(identity){return!!identity?.forkArgv}var GENERIC_PROTOCOL="generic",ENGINE_PROTOCOLS=BUILTIN_VENDORS;function engineProtocolKey(id){return`engineProtocol.${id}`}function getEngineProtocol(id){if(isBuiltinVendor(id)||isContribEngine(id))return id;let raw=getPersistedString(engineProtocolKey(id))?.trim();return raw&&ENGINE_PROTOCOLS.includes(raw)?raw:void 0}function isPresetId(id){return isBuiltinVendor(id)||isContribEngine(id)||getCustomEngineIds().includes(id)}function listPresetIds(){return[...new Set([...BUILTIN_VENDORS,...getCustomEngineIds()])]}function describePreset(id){let command=getPersistedString(engineCommandKey(id))?.trim()||defaultEngineCommand(id).join(" ");return{id,name:engineDisplayName(id),command,protocol:getEngineProtocol(id)??GENERIC_PROTOCOL,builtin:isBuiltinVendor(id)}}function listEnginePresets(){return listPresetIds().map(describePreset)}function resolveCommandProtocol(command){let trimmed=command?.trim();if(!trimmed)return GENERIC_PROTOCOL;if(isPresetId(trimmed))return getEngineProtocol(trimmed)??GENERIC_PROTOCOL;let fromArgv=vendorFromArgv(trimmed);if(fromArgv)return fromArgv;let argv0=parseEngineCommand(trimmed)[0];if(argv0)for(let id of getCustomEngineIds()){let preset=getPersistedString(engineCommandKey(id))?.trim();if(preset&&parseEngineCommand(preset)[0]===argv0)return getEngineProtocol(id)??GENERIC_PROTOCOL}return GENERIC_PROTOCOL}function engineLaunchArgv(spec){let command=spec.command?.trim();if(!command)return interactiveEngineCommand(spec.vendor,spec.effort,spec.model);let vendor=(isPresetId(command)?getEngineProtocol(command):void 0)??resolveCommandProtocol(command),base=isPresetId(command)?presetBaseArgv(command):(()=>{let argv=parseEngineCommand(command);return argv.length>0?argv:null})();if(!base)return interactiveEngineCommand(spec.vendor,spec.effort,spec.model);return withEngineHostedArgs(withEngineModel(withEngineEffort(base,vendor,spec.effort),vendor,spec.model),vendor)}function presetBaseArgv(id){let override=getPersistedString(engineCommandKey(id))?.trim();if(override){let argv=parseEngineCommand(override);if(argv.length>0)return argv}return defaultEngineCommand(id)}function sessionProtocol(vendor){let id=vendor?.trim();if(!id)return"claude";return getEngineProtocol(id)??id}function protocolEntry(vendor){return engineEntry(sessionProtocol(vendor))}function withPinnedSessionId(argv,vendor,newId=randomUUID){let identity=engineEntry(sessionProtocol(vendor)).sessionIdentity;if(!acceptsPinnedSession(identity,argv))return{argv,sessionId:null};let sessionId=newId();return{argv:pinSessionArgv(identity,argv,sessionId),sessionId}}function engineResumeArgv(base,vendor,sessionId){return resumeSessionArgv(engineEntry(sessionProtocol(vendor)).sessionIdentity,base,sessionId)}function engineCanFork(vendor){return acceptsSessionFork(engineEntry(sessionProtocol(vendor)).sessionIdentity)}function engineForkArgv(base,vendor,sourceId,newId){return forkSessionArgvFor(engineEntry(sessionProtocol(vendor)).sessionIdentity,base,sourceId,newId)}var ID_RE=/^tab-(\d+)$/;function tabOrdinalOf(id){let match=ID_RE.exec(id);return match?Number(match[1]):null}var sameValue=(a,b)=>a===b||JSON.stringify(a)===JSON.stringify(b);function insertAfter(tabs,row,after){if(after===null)return[row,...tabs];let i=after===void 0?-1:tabs.findIndex((t)=>t.id===after);return i<0?[...tabs,row]:[...tabs.slice(0,i+1),row,...tabs.slice(i+1)]}function applyTabOps(current,ops,tombstones=new Set){let state=current,changed=!1,opened=[],set=(next)=>{state=next,changed=!0};for(let op of ops)switch(op.op){case"seed":{if(state===null||state.tabs.length===0){let floor=Math.max(op.state.nextOrdinal,maxOrdinal(op.state)+1,state?.nextOrdinal??0);set({...op.state,nextOrdinal:floor})}break}case"forget":{if(state!==null)set(null);break}case"open":{let base=state??{tabs:[],nextOrdinal:1},wanted=op.row.id;if(wanted!==void 0&&(base.tabs.some((t)=>t.id===wanted)||tombstones.has(wanted))){opened.push(null);break}let ordinal=wanted!==void 0?tabOrdinalOf(wanted)??op.row.ordinal??base.nextOrdinal:base.nextOrdinal,id=wanted??`tab-${ordinal}`,row={...op.row,id,ordinal};set({...base,tabs:insertAfter(base.tabs,row,op.after),nextOrdinal:Math.max(base.nextOrdinal,ordinal+1)}),opened.push(id);break}case"patch":{if(!state)break;let i=state.tabs.findIndex((t)=>t.id===op.id),row=state.tabs[i];if(!row)break;let next={...row},rowChanged=!1;for(let[key,value]of Object.entries(op.set??{})){if(key==="id"||key==="ordinal"||sameValue(next[key],value))continue;next[key]=value,rowChanged=!0}for(let key of op.unset??[]){if(key==="id"||key==="ordinal"||key==="kind"||!(key in next))continue;delete next[key],rowChanged=!0}if(!rowChanged)break;let tabs=[...state.tabs];tabs[i]=next,set({...state,tabs});break}case"close":{if(!state||!state.tabs.some((t)=>t.id===op.id))break;tombstones.add(op.id);let tabs=state.tabs.filter((t)=>t.id!==op.id),reopen=tabs.length===0&&op.reopenAs!==void 0?{reopenAs:op.reopenAs}:{},{activeId,...rest}=state;set({...rest,tabs,...activeId!==void 0&&activeId!==op.id?{activeId}:{},...reopen});break}case"order":{if(!state)break;let byId=new Map(state.tabs.map((t)=>[t.id,t])),tabs=[...op.ids.flatMap((id)=>{let row=byId.get(id);if(!row)return[];return byId.delete(id),[row]}),...state.tabs.filter((t)=>byId.has(t.id))];if(tabs.every((t,i)=>t===state?.tabs[i]))break;set({...state,tabs});break}case"focus":{if(!state||state.activeId===op.id||!state.tabs.some((t)=>t.id===op.id))break;set({...state,activeId:op.id});break}case"meta":{if(!state||sameValue(state.reopenAs,op.reopenAs))break;let{reopenAs:_drop,...rest}=state;set(op.reopenAs===void 0?rest:{...rest,reopenAs:op.reopenAs});break}}return{state,changed,opened}}function maxOrdinal(state){return state.tabs.reduce((max,tab)=>Math.max(max,tab.ordinal),0)}function reserveOrdinals(state,count){let base=state??{tabs:[],nextOrdinal:1},from=Math.max(base.nextOrdinal,maxOrdinal(base)+1);return{state:{...base,nextOrdinal:from+count},from}}function releaseOrdinals(state,from,to){if(!state||state.nextOrdinal!==to||from>=to)return state;let floor=Math.max(from,maxOrdinal(state)+1);return floor<state.nextOrdinal?{...state,nextOrdinal:floor}:state}function diffTabs(prev,next){if(prev===null)return[{op:"seed",state:next}];let ops=[],prevById=new Map(prev.tabs.map((t)=>[t.id,t])),nextIds=new Set(next.tabs.map((t)=>t.id));for(let row of prev.tabs){let reopen=next.tabs.length===0&&next.reopenAs!==void 0?{reopenAs:next.reopenAs}:{};if(!nextIds.has(row.id))ops.push({op:"close",id:row.id,...reopen})}next.tabs.forEach((row,i)=>{let before=prevById.get(row.id);if(!before){ops.push({op:"open",row,after:i===0?null:next.tabs[i-1]?.id??null});return}if(before===row)return;let set={},unset=[];for(let[key,value]of Object.entries(row))if(key!=="id"&&key!=="ordinal"&&!sameValue(before[key],value))set[key]=value;for(let key of Object.keys(before))if(!(key in row))unset.push(key);if(Object.keys(set).length>0||unset.length>0)ops.push({op:"patch",id:row.id,...Object.keys(set).length>0?{set}:{},...unset.length>0?{unset}:{}})});let kept=next.tabs.filter((t)=>prevById.has(t.id)).map((t)=>t.id),prevKept=prev.tabs.filter((t)=>nextIds.has(t.id)).map((t)=>t.id);if(kept.some((id,i)=>id!==prevKept[i]))ops.push({op:"order",ids:next.tabs.map((t)=>t.id)});if(!sameValue(prev.reopenAs,next.reopenAs)&&next.tabs.length>0)ops.push({op:"meta",reopenAs:next.reopenAs});return ops}
3
3
  export{engineCommandKey,engineNameKey,engineDisplayName,humanizeSlug,engineRenamedFrom,defaultEngineCommand,interactiveEngineCommand,roveApiInvocation,pickUnclaimedSessionId,GENERIC_PROTOCOL,ENGINE_PROTOCOLS,engineProtocolKey,getEngineProtocol,listPresetIds,describePreset,listEnginePresets,resolveCommandProtocol,engineLaunchArgv,sessionProtocol,protocolEntry,withPinnedSessionId,engineResumeArgv,engineCanFork,engineForkArgv,applyTabOps,reserveOrdinals,releaseOrdinals,diffTabs};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{MachineFeed}from"./chunk-7xsactw5.js";import{COLORBLIND_KEY,DEFAULT_BASE_REF,DEFAULT_COLORBLIND,DEFAULT_GLYPHS,DEFAULT_GLYPH_SET,DEFAULT_PREFIX_TAP_PRESENTATION,DEFAULT_RUNNING_TITLE,DEFAULT_SCROLLBACK_ROWS,DEFAULT_TASK_COLORS,DEFAULT_WORKING_BORDER,GLYPH_SETS,GLYPH_SET_KEY,PREFIX_TAP_PRESENTATIONS,PREFIX_TAP_PRESENTATION_KEY,RUNNING_TITLE_KEY,SCROLLBACK_ROWS_KEY,SCROLLBACK_ROWS_MAX,SCROLLBACK_ROWS_MIN,SPLIT_STYLE_KEY,TAB_STRIP_HIDE_SINGLE_KEY,TAB_STRIP_MODES,TAB_STRIP_MODE_KEY,TASK_COLORS_KEY,WORKING_BORDER_KEY,appearanceChoices,buildPRPrompt,cloneRepo,conversationTitleOf,createKeybindingsFile,deriveFolderName,detailFragment,detectWorktreeOpener,diffCommentsKey,displayEndpoint,engineIntegrations,findAvailableFolderName,formatDiffComments,getCurrentBranch,issueChatTaskTitle,issueProjectPrompt,issueWorktreePrompt,listLocalBranches,normalizeColorblind,normalizeGlyphSet,normalizePrefixTapPresentation,normalizeRunningTitle,normalizeScrollbackRows,normalizeSplitStyle,normalizeTaskColors,normalizeWorkingBorder,openExternally,openWorktree,prChip,readPluginRows,resolveCloneTarget,resolveTabStripMode,setPluginEnabled,spawnDetached,taskColor,unsentComments,validateCloneTarget,validateGitUrl,validateRepoPath,worktreeRowLabel}from"./chunk-7zn9xwsn.js";import"./chunk-c25vea1q.js";import"./chunk-p2cbtrzg.js";import"./chunk-e288cp6w.js";import{buildCIPromptForWorktree}from"./chunk-vkz6kkmm.js";import{checkFrame,ghText,isLoopbackHost,parseFailedRunLog,runIdFromDetailsUrl}from"./chunk-16e6jqq6.js";import{tabStatus,taskStatus}from"./chunk-6hcyvg0m.js";import{installSkillErrors,missingSkillNames}from"./chunk-pqc8bnsf.js";import{invokeVerb}from"./chunk-gqq51hqn.js";import{argvToParams,executeVerb}from"./chunk-j4tmz36m.js";import{DEFAULT_SOUND_VOLUME,FINISHED_ALERTS_KEY,RAIL_FOLD_STYLE_KEY,RoveKeymap,SOUND_VOLUME_KEY,SOUND_VOLUME_STEPS,ZEN_ACTIVE_KEY,ZEN_DEFAULT,attentionEdges,attentionKindFor,normalizeSoundVolume,prefixFirstStrokes,readKeybindingsFile,resetKeybindingsFileCache,resolveUserKeybindings}from"./chunk-bbq6wc47.js";import{RemoteOrchestrator,liveRowTokens}from"./chunk-bqecpzgk.js";import{startFileWatchTrigger}from"./chunk-r3s2t9af.js";import"./chunk-6xr1prk6.js";import{UPDATE_CHANNEL_KEY,UPDATE_NOTIFY_KEY,normalizeReleaseChannel,preferredReleaseChannel}from"./chunk-ydaj339x.js";import{updaterShell,updaterShellFailureHint}from"./chunk-8kspedny.js";import{HOSTED_THEMES,ThemeInstallError,hostedThemeUrl,parseTheme,writeUserTheme}from"./chunk-xaam0d8r.js";import{buildContext,checkRef,worktreeDiff,worktreeRefs}from"./chunk-qk7h3fe6.js";import{AUTO_ROUTING_TIERS,autoRoutingKey,describeTierBlock,listFiles,liveSourceProtocol,loadFileContent,loadPreviewData,planWorktreeHandoff,readAutoRoutingTable,readClassifierConfig,resolveBase,secretStatus,tierBlock}from"./chunk-yeq2pc68.js";import{ensurePluginEnginesLoaded}from"./chunk-kdnk8m5j.js";import"./chunk-65893xxt.js";import{listPaneLaunches}from"./chunk-rjfdzjhj.js";import{detectEngineStatus,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-zpxpwgds.js";import{DEFAULT_EDITOR_KIND,EDITOR_CUSTOM_KEY,EDITOR_KINDS,EDITOR_KIND_KEY,normalizeEditorKind}from"./chunk-agvtzads.js";import"./chunk-pm91e38v.js";import{deriveTitleFromPrompt}from"./chunk-2xsxcdp6.js";import"./chunk-17e2tgyg.js";import{PROJECT_SIBLING_BASE,WORKTREE_BASE_CUSTOM_KEY,worktreeBaseKindOf}from"./chunk-1vxtd8rh.js";import"./chunk-q8ffd1pc.js";import"./chunk-4hestsjp.js";import"./chunk-qgrg9a5n.js";import"./chunk-2bgmby1d.js";import{loadPluginRegistry}from"./chunk-n0rdn2fn.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import{FEEDBACK_KINDS,isFeedbackKind}from"./chunk-ph9m6y5j.js";import{forwardVerb,invokeRouted,machineDaemonSocket,requireMachine}from"./chunk-g6bybfvj.js";import{localPtySocketPath}from"./chunk-6aysj339.js";import{repoIdOf}from"./chunk-vp29jgbt.js";import{WORKTREE_BASE_KEY}from"./chunk-gq36nzg8.js";import"./chunk-sq6zj3fb.js";import"./chunk-qkehg2c1.js";import"./chunk-mz72jber.js";import"./chunk-ydb5bhbh.js";import{ensurePtyHostReachable}from"./chunk-d4zw1g83.js";import"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import{DEFAULT_THEME,DEFAULT_THEME_MODE,FOCUS_ACCENT_SLOTS,THEME_MODE_PREFERENCES,defaultTransparentBackground,diffInks,resolveTheme}from"./chunk-92hpkjkk.js";import"./chunk-rxqdw6s5.js";import{resolveThemeSlotHex}from"./chunk-8ng1756g.js";import{BUNDLED_THEME_JSONS,loadUserThemes,userThemesDir}from"./chunk-kxp04jnp.js";import{conversationTitle,expandHome,filterSubdirs,initialTabs,listSubdirs,moveTab,splitPathForDirSuggest,stripTrailingSlash,tabPtyKeyFor}from"./chunk-za8pnw78.js";import{AUTO_STATUS_KEY,DISPATCHER_KEY}from"./chunk-qecygh3f.js";import{defaultEngineCommand,engineDisplayName,engineRenamedFrom,protocolEntry,roveApiInvocation}from"./chunk-rjq38twt.js";import{ApiError,REMOTE_CALLER}from"./chunk-r5j8fycq.js";import{BUILTIN_MODS,installedBuiltinMods,isBuiltinModId,setBuiltinModInstalled}from"./chunk-xfgqae9t.js";import"./chunk-j1z9kgyd.js";import"./chunk-g9ba25q5.js";import"./chunk-ggnq2vvk.js";import"./chunk-hpay0ax8.js";import{isNonEmptyRepoFile}from"./chunk-catrr0z3.js";import{terminalTabsKey}from"./chunk-mdc7b01e.js";import"./chunk-tn9gtf18.js";import"./chunk-895yqjjz.js";import"./chunk-sak1tphp.js";import"./chunk-y1xnjx8x.js";import{ensureDaemonReachable}from"./chunk-cb80ft39.js";import"./chunk-mdwqpnde.js";import"./chunk-mv229800.js";import"./chunk-5rgrde6b.js";import{engineEntry,vendorsWithTurnReader}from"./chunk-4gjvmfa9.js";import"./chunk-2tfnscxk.js";import{installedEngineIds}from"./chunk-hzz020xx.js";import"./chunk-w7zv47mp.js";import"./chunk-etfh8f4z.js";import{resolvePreferredVendor,setRepoLastActiveVendor}from"./chunk-9rj2fx6v.js";import{getDisabledEngineIds,getSavedRepos,resolveMainRepoRoot}from"./chunk-rfp0ayra.js";import"./chunk-0r1jf8m9.js";import"./chunk-t7j8g9f6.js";import"./chunk-dmzg9zdc.js";import"./chunk-40dgv828.js";import"./chunk-kg9kmwt9.js";import"./chunk-6xppe9bj.js";import{CURRENT_VERSION,DEFAULT_RELEASE_CHANNEL,RELEASE_CHANNELS,channelOf,checkLatestVersion,fetchReleaseNotes,fetchReleaseNotesRange,updateCommandFor}from"./chunk-jxqhq9va.js";import"./chunk-zsfyj36g.js";import"./chunk-2r1fgng9.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import{loadStateFile,replaceStateFile,updateStateFile}from"./chunk-32j6y5d1.js";import"./chunk-4d5xp2p0.js";import{DEFAULT_LOCALE,LOCALES,isLocaleId}from"./chunk-b4egks20.js";import"./chunk-cmp64q4j.js";import{RoveDaemonClient,isDaemonVersionStale}from"./chunk-496egqmk.js";import{MOD_INPUT_MAX,MOD_KEY_PATTERN,MOD_PANE_ID_PATTERN,ROVE_API_VERSION}from"./chunk-96kvwzj8.js";import"./chunk-7bakcyes.js";import{roveCliInvocation}from"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import{MULTI_REPO_CAP,rollupPr}from"./chunk-x1jxxmtc.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";import{ALL_VENDORS,isBuiltinVendor}from"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import{defaultUiPrefsStatePath,promptAttachmentsDir,resolveProductHomeDir,roveStateDir}from"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import{samePath}from"./chunk-pn5ygqn6.js";import{defaultDaemonSocketPath,defaultPtyHostSocketPath}from"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import{__commonJS,__require,__toESM}from"./chunk-91sykzqq.js";var require_ms=__commonJS((exports,module)=>{var s=1000,m=s*60,h=m*60,d=h*24,w=d*7,y=d*365.25;module.exports=function(val,options){options=options||{};var type=typeof val;if(type==="string"&&val.length>0)return parse(val);else if(type==="number"&&isFinite(val))return options.long?fmtLong(val):fmtShort(val);throw Error("val is not a non-empty string or a valid number. val="+JSON.stringify(val))};function parse(str){if(str=String(str),str.length>100)return;var match=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);if(!match)return;var n=parseFloat(match[1]),type=(match[2]||"ms").toLowerCase();switch(type){case"years":case"year":case"yrs":case"yr":case"y":return n*y;case"weeks":case"week":case"w":return n*w;case"days":case"day":case"d":return n*d;case"hours":case"hour":case"hrs":case"hr":case"h":return n*h;case"minutes":case"minute":case"mins":case"min":case"m":return n*m;case"seconds":case"second":case"secs":case"sec":case"s":return n*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}function fmtShort(ms){var msAbs=Math.abs(ms);if(msAbs>=d)return Math.round(ms/d)+"d";if(msAbs>=h)return Math.round(ms/h)+"h";if(msAbs>=m)return Math.round(ms/m)+"m";if(msAbs>=s)return Math.round(ms/s)+"s";return ms+"ms"}function fmtLong(ms){var msAbs=Math.abs(ms);if(msAbs>=d)return plural(ms,msAbs,d,"day");if(msAbs>=h)return plural(ms,msAbs,h,"hour");if(msAbs>=m)return plural(ms,msAbs,m,"minute");if(msAbs>=s)return plural(ms,msAbs,s,"second");return ms+" ms"}function plural(ms,msAbs,n,name){var isPlural=msAbs>=n*1.5;return Math.round(ms/n)+" "+name+(isPlural?"s":"")}});var require_common=__commonJS((exports,module)=>{function setup(env){createDebug.debug=createDebug,createDebug.default=createDebug,createDebug.coerce=coerce,createDebug.disable=disable,createDebug.enable=enable,createDebug.enabled=enabled,createDebug.humanize=require_ms(),createDebug.destroy=destroy,Object.keys(env).forEach((key)=>{createDebug[key]=env[key]}),createDebug.names=[],createDebug.skips=[],createDebug.formatters={};function selectColor(namespace){let hash=0;for(let i=0;i<namespace.length;i++)hash=(hash<<5)-hash+namespace.charCodeAt(i),hash|=0;return createDebug.colors[Math.abs(hash)%createDebug.colors.length]}createDebug.selectColor=selectColor;function createDebug(namespace){let prevTime,enableOverride=null,namespacesCache,enabledCache;function debug(...args){if(!debug.enabled)return;let self=debug,curr=Number(new Date),ms=curr-(prevTime||curr);if(self.diff=ms,self.prev=prevTime,self.curr=curr,prevTime=curr,args[0]=createDebug.coerce(args[0]),typeof args[0]!=="string")args.unshift("%O");let index=0;args[0]=args[0].replace(/%([a-zA-Z%])/g,(match,format)=>{if(match==="%%")return"%";index++;let formatter=createDebug.formatters[format];if(typeof formatter==="function"){let val=args[index];match=formatter.call(self,val),args.splice(index,1),index--}return match}),createDebug.formatArgs.call(self,args),(self.log||createDebug.log).apply(self,args)}if(debug.namespace=namespace,debug.useColors=createDebug.useColors(),debug.color=createDebug.selectColor(namespace),debug.extend=extend,debug.destroy=createDebug.destroy,Object.defineProperty(debug,"enabled",{enumerable:!0,configurable:!1,get:()=>{if(enableOverride!==null)return enableOverride;if(namespacesCache!==createDebug.namespaces)namespacesCache=createDebug.namespaces,enabledCache=createDebug.enabled(namespace);return enabledCache},set:(v)=>{enableOverride=v}}),typeof createDebug.init==="function")createDebug.init(debug);return debug}function extend(namespace,delimiter){let newDebug=createDebug(this.namespace+(typeof delimiter>"u"?":":delimiter)+namespace);return newDebug.log=this.log,newDebug}function enable(namespaces){createDebug.save(namespaces),createDebug.namespaces=namespaces,createDebug.names=[],createDebug.skips=[];let split=(typeof namespaces==="string"?namespaces:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let ns of split)if(ns[0]==="-")createDebug.skips.push(ns.slice(1));else createDebug.names.push(ns)}function matchesTemplate(search,template){let searchIndex=0,templateIndex=0,starIndex=-1,matchIndex=0;while(searchIndex<search.length)if(templateIndex<template.length&&(template[templateIndex]===search[searchIndex]||template[templateIndex]==="*"))if(template[templateIndex]==="*")starIndex=templateIndex,matchIndex=searchIndex,templateIndex++;else searchIndex++,templateIndex++;else if(starIndex!==-1)templateIndex=starIndex+1,matchIndex++,searchIndex=matchIndex;else return!1;while(templateIndex<template.length&&template[templateIndex]==="*")templateIndex++;return templateIndex===template.length}function disable(){let namespaces=[...createDebug.names,...createDebug.skips.map((namespace)=>"-"+namespace)].join(",");return createDebug.enable(""),namespaces}function enabled(name){for(let skip of createDebug.skips)if(matchesTemplate(name,skip))return!1;for(let ns of createDebug.names)if(matchesTemplate(name,ns))return!0;return!1}function coerce(val){if(val instanceof Error)return val.stack||val.message;return val}function destroy(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return createDebug.enable(createDebug.load()),createDebug}module.exports=setup});var require_browser=__commonJS((exports,module)=>{exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.storage=localstorage();exports.destroy=(()=>{let warned=!1;return()=>{if(!warned)warned=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}})();exports.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function useColors(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let m;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(m=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(m[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function formatArgs(args){if(args[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+args[0]+(this.useColors?"%c ":" ")+"+"+module.exports.humanize(this.diff),!this.useColors)return;let c="color: "+this.color;args.splice(1,0,c,"color: inherit");let index=0,lastC=0;args[0].replace(/%[a-zA-Z%]/g,(match)=>{if(match==="%%")return;if(index++,match==="%c")lastC=index}),args.splice(lastC,0,c)}exports.log=console.debug||console.log||(()=>{});function save(namespaces){try{if(namespaces)exports.storage.setItem("debug",namespaces);else exports.storage.removeItem("debug")}catch(error){}}function load(){let r;try{r=exports.storage.getItem("debug")||exports.storage.getItem("DEBUG")}catch(error){}if(!r&&typeof process<"u"&&"env"in process)r=process.env.DEBUG;return r}function localstorage(){try{return localStorage}catch(error){}}module.exports=require_common()(exports);var{formatters}=module.exports;formatters.j=function(v){try{return JSON.stringify(v)}catch(error){return"[UnexpectedJSONParseError]: "+error.message}}});var require_has_flag=__commonJS((exports,module)=>{module.exports=(flag,argv=process.argv)=>{let prefix=flag.startsWith("-")?"":flag.length===1?"-":"--",position=argv.indexOf(prefix+flag),terminatorPosition=argv.indexOf("--");return position!==-1&&(terminatorPosition===-1||position<terminatorPosition)}});var require_supports_color=__commonJS((exports,module)=>{var os=__require("os"),tty=__require("tty"),hasFlag=require_has_flag(),{env}=process,forceColor;if(hasFlag("no-color")||hasFlag("no-colors")||hasFlag("color=false")||hasFlag("color=never"))forceColor=0;else if(hasFlag("color")||hasFlag("colors")||hasFlag("color=true")||hasFlag("color=always"))forceColor=1;if("FORCE_COLOR"in env)if(env.FORCE_COLOR==="true")forceColor=1;else if(env.FORCE_COLOR==="false")forceColor=0;else forceColor=env.FORCE_COLOR.length===0?1:Math.min(parseInt(env.FORCE_COLOR,10),3);function translateLevel(level){if(level===0)return!1;return{level,hasBasic:!0,has256:level>=2,has16m:level>=3}}function supportsColor(haveStream,streamIsTTY){if(forceColor===0)return 0;if(hasFlag("color=16m")||hasFlag("color=full")||hasFlag("color=truecolor"))return 3;if(hasFlag("color=256"))return 2;if(haveStream&&!streamIsTTY&&forceColor===void 0)return 0;let min=forceColor||0;if(env.TERM==="dumb")return min;if(process.platform==="win32"){let osRelease=os.release().split(".");if(Number(osRelease[0])>=10&&Number(osRelease[2])>=10586)return Number(osRelease[2])>=14931?3:2;return 1}if("CI"in env){if(["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some((sign)=>(sign in env))||env.CI_NAME==="codeship")return 1;return min}if("TEAMCITY_VERSION"in env)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION)?1:0;if(env.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in env){let version=parseInt((env.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(env.TERM_PROGRAM){case"iTerm.app":return version>=3?3:2;case"Apple_Terminal":return 2}}if(/-256(color)?$/i.test(env.TERM))return 2;if(/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM))return 1;if("COLORTERM"in env)return 1;return min}function getSupportLevel(stream){let level=supportsColor(stream,stream&&stream.isTTY);return translateLevel(level)}module.exports={supportsColor:getSupportLevel,stdout:translateLevel(supportsColor(!0,tty.isatty(1))),stderr:translateLevel(supportsColor(!0,tty.isatty(2)))}});var require_node=__commonJS((exports,module)=>{var tty=__require("tty"),util=__require("util");exports.init=init;exports.log=log;exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.destroy=util.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");exports.colors=[6,2,3,4,5,1];try{let supportsColor=require_supports_color();if(supportsColor&&(supportsColor.stderr||supportsColor).level>=2)exports.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221]}catch(error){}exports.inspectOpts=Object.keys(process.env).filter((key)=>{return/^debug_/i.test(key)}).reduce((obj,key)=>{let prop=key.substring(6).toLowerCase().replace(/_([a-z])/g,(_,k)=>{return k.toUpperCase()}),val=process.env[key];if(/^(yes|on|true|enabled)$/i.test(val))val=!0;else if(/^(no|off|false|disabled)$/i.test(val))val=!1;else if(val==="null")val=null;else val=Number(val);return obj[prop]=val,obj},{});function useColors(){return"colors"in exports.inspectOpts?Boolean(exports.inspectOpts.colors):tty.isatty(process.stderr.fd)}function formatArgs(args){let{namespace:name,useColors:useColors2}=this;if(useColors2){let c=this.color,colorCode="\x1B[3"+(c<8?c:"8;5;"+c),prefix=` ${colorCode};1m${name} \x1B[0m`;args[0]=prefix+args[0].split(`
2
+ import{MachineFeed}from"./chunk-7xsactw5.js";import{COLORBLIND_KEY,DEFAULT_BASE_REF,DEFAULT_COLORBLIND,DEFAULT_GLYPHS,DEFAULT_GLYPH_SET,DEFAULT_PREFIX_TAP_PRESENTATION,DEFAULT_RUNNING_TITLE,DEFAULT_SCROLLBACK_ROWS,DEFAULT_TASK_COLORS,DEFAULT_WORKING_BORDER,GLYPH_SETS,GLYPH_SET_KEY,PREFIX_TAP_PRESENTATIONS,PREFIX_TAP_PRESENTATION_KEY,RUNNING_TITLE_KEY,SCROLLBACK_ROWS_KEY,SCROLLBACK_ROWS_MAX,SCROLLBACK_ROWS_MIN,SPLIT_STYLE_KEY,TAB_STRIP_HIDE_SINGLE_KEY,TAB_STRIP_MODES,TAB_STRIP_MODE_KEY,TASK_COLORS_KEY,WORKING_BORDER_KEY,appearanceChoices,buildPRPrompt,cloneRepo,conversationTitleOf,createKeybindingsFile,deriveFolderName,detailFragment,detectWorktreeOpener,diffCommentsKey,displayEndpoint,engineIntegrations,findAvailableFolderName,formatDiffComments,getCurrentBranch,issueChatTaskTitle,issueProjectPrompt,issueWorktreePrompt,listLocalBranches,normalizeColorblind,normalizeGlyphSet,normalizePrefixTapPresentation,normalizeRunningTitle,normalizeScrollbackRows,normalizeSplitStyle,normalizeTaskColors,normalizeWorkingBorder,openExternally,openWorktree,prChip,readPluginRows,resolveCloneTarget,resolveTabStripMode,setPluginEnabled,spawnDetached,taskColor,unsentComments,validateCloneTarget,validateGitUrl,validateRepoPath,worktreeRowLabel}from"./chunk-mcq5ykax.js";import"./chunk-c25vea1q.js";import"./chunk-c8qjy6rx.js";import"./chunk-e288cp6w.js";import{buildCIPromptForWorktree}from"./chunk-vkz6kkmm.js";import{checkFrame,ghText,isLoopbackHost,parseFailedRunLog,runIdFromDetailsUrl}from"./chunk-xr117xs9.js";import{tabStatus,taskStatus}from"./chunk-6hcyvg0m.js";import{installSkillErrors,missingSkillNames}from"./chunk-h27064am.js";import{invokeVerb}from"./chunk-9vnbp5db.js";import{argvToParams,executeVerb}from"./chunk-9jjs5wev.js";import{DEFAULT_SOUND_VOLUME,FINISHED_ALERTS_KEY,RAIL_FOLD_STYLE_KEY,RoveKeymap,SOUND_VOLUME_KEY,SOUND_VOLUME_STEPS,ZEN_ACTIVE_KEY,ZEN_DEFAULT,attentionEdges,attentionKindFor,normalizeSoundVolume,prefixFirstStrokes,readKeybindingsFile,resetKeybindingsFileCache,resolveUserKeybindings}from"./chunk-bbq6wc47.js";import{RemoteOrchestrator,liveRowTokens}from"./chunk-bqecpzgk.js";import{startFileWatchTrigger}from"./chunk-r3s2t9af.js";import"./chunk-6xr1prk6.js";import{UPDATE_CHANNEL_KEY,UPDATE_NOTIFY_KEY,normalizeReleaseChannel,preferredReleaseChannel}from"./chunk-ydaj339x.js";import{updaterShell,updaterShellFailureHint}from"./chunk-8kspedny.js";import{HOSTED_THEMES,ThemeInstallError,hostedThemeUrl,parseTheme,writeUserTheme}from"./chunk-xaam0d8r.js";import{buildContext,checkRef,worktreeDiff,worktreeRefs}from"./chunk-n3ewtd3b.js";import{AUTO_ROUTING_TIERS,autoRoutingKey,describeTierBlock,listFiles,liveSourceProtocol,loadFileContent,loadPreviewData,planWorktreeHandoff,readAutoRoutingTable,readClassifierConfig,resolveBase,secretStatus,tierBlock}from"./chunk-pebgqr0z.js";import{ensurePluginEnginesLoaded}from"./chunk-23maf8ch.js";import"./chunk-65893xxt.js";import{listPaneLaunches}from"./chunk-rjfdzjhj.js";import{detectEngineStatus,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-eyaaaprw.js";import{DEFAULT_EDITOR_KIND,EDITOR_CUSTOM_KEY,EDITOR_KINDS,EDITOR_KIND_KEY,normalizeEditorKind}from"./chunk-cacct9gd.js";import"./chunk-pm91e38v.js";import{deriveTitleFromPrompt}from"./chunk-2xsxcdp6.js";import"./chunk-17e2tgyg.js";import{PROJECT_SIBLING_BASE,WORKTREE_BASE_CUSTOM_KEY,worktreeBaseKindOf}from"./chunk-ee8917py.js";import"./chunk-q8ffd1pc.js";import"./chunk-4hestsjp.js";import"./chunk-qgrg9a5n.js";import"./chunk-2bgmby1d.js";import{loadPluginRegistry}from"./chunk-n0rdn2fn.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import{FEEDBACK_KINDS,isFeedbackKind}from"./chunk-8hk78wty.js";import{forwardVerb,invokeRouted,machineDaemonSocket,requireMachine}from"./chunk-adsfeq6x.js";import{localPtySocketPath}from"./chunk-6aysj339.js";import{repoIdOf}from"./chunk-vp29jgbt.js";import{WORKTREE_BASE_KEY}from"./chunk-gq36nzg8.js";import"./chunk-sq6zj3fb.js";import"./chunk-qkehg2c1.js";import"./chunk-w4b9nc3w.js";import"./chunk-xehd2vx3.js";import{ensurePtyHostReachable}from"./chunk-d4zw1g83.js";import"./chunk-w77s2df8.js";import"./chunk-mqfvzdpr.js";import{DEFAULT_THEME,DEFAULT_THEME_MODE,FOCUS_ACCENT_SLOTS,THEME_MODE_PREFERENCES,defaultTransparentBackground,diffInks,resolveTheme}from"./chunk-92hpkjkk.js";import"./chunk-rxqdw6s5.js";import{resolveThemeSlotHex}from"./chunk-8ng1756g.js";import{BUNDLED_THEME_JSONS,loadUserThemes,userThemesDir}from"./chunk-kxp04jnp.js";import{conversationTitle,expandHome,filterSubdirs,initialTabs,listSubdirs,moveTab,splitPathForDirSuggest,stripTrailingSlash,tabPtyKeyFor}from"./chunk-5x9j58xk.js";import{AUTO_STATUS_KEY,DISPATCHER_KEY}from"./chunk-ypfrkpe9.js";import{defaultEngineCommand,engineDisplayName,engineRenamedFrom,protocolEntry,roveApiInvocation}from"./chunk-0m8javx8.js";import{ApiError,REMOTE_CALLER}from"./chunk-r5j8fycq.js";import{BUILTIN_MODS,installedBuiltinMods,isBuiltinModId,setBuiltinModInstalled}from"./chunk-xfgqae9t.js";import"./chunk-j1z9kgyd.js";import"./chunk-g9ba25q5.js";import"./chunk-paashxkd.js";import"./chunk-hpay0ax8.js";import{isNonEmptyRepoFile}from"./chunk-catrr0z3.js";import{terminalTabsKey}from"./chunk-mdc7b01e.js";import"./chunk-tn9gtf18.js";import"./chunk-22emnsn5.js";import"./chunk-sak1tphp.js";import"./chunk-y1xnjx8x.js";import{ensureDaemonReachable}from"./chunk-cb80ft39.js";import"./chunk-mdwqpnde.js";import"./chunk-mv229800.js";import"./chunk-jnt3nf6w.js";import{engineEntry,vendorsWithTurnReader}from"./chunk-hgtf6yvg.js";import"./chunk-2tfnscxk.js";import{installedEngineIds}from"./chunk-betn5ma1.js";import"./chunk-w7zv47mp.js";import"./chunk-etfh8f4z.js";import{resolvePreferredVendor,setRepoLastActiveVendor}from"./chunk-8ttn73cv.js";import{getDisabledEngineIds,getSavedRepos,resolveMainRepoRoot}from"./chunk-gygdyf0s.js";import"./chunk-0r1jf8m9.js";import"./chunk-t7j8g9f6.js";import"./chunk-dmzg9zdc.js";import"./chunk-40dgv828.js";import"./chunk-kg9kmwt9.js";import"./chunk-6xppe9bj.js";import{CURRENT_VERSION,DEFAULT_RELEASE_CHANNEL,RELEASE_CHANNELS,channelOf,checkLatestVersion,fetchReleaseNotes,fetchReleaseNotesRange,updateCommandFor}from"./chunk-jxqhq9va.js";import"./chunk-zsfyj36g.js";import"./chunk-2r1fgng9.js";import"./chunk-2brn8e1y.js";import"./chunk-7mwvvj46.js";import{loadStateFile,replaceStateFile,updateStateFile}from"./chunk-32j6y5d1.js";import"./chunk-4d5xp2p0.js";import{DEFAULT_LOCALE,LOCALES,isLocaleId}from"./chunk-b4egks20.js";import"./chunk-cmp64q4j.js";import{RoveDaemonClient,isDaemonVersionStale}from"./chunk-496egqmk.js";import{MOD_INPUT_MAX,MOD_KEY_PATTERN,MOD_PANE_ID_PATTERN,ROVE_API_VERSION}from"./chunk-96kvwzj8.js";import"./chunk-7bakcyes.js";import{roveCliInvocation}from"./chunk-8qkyd589.js";import"./chunk-7kysxgbq.js";import"./chunk-hz1x3hak.js";import{MULTI_REPO_CAP,rollupPr}from"./chunk-x1jxxmtc.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";import{ALL_VENDORS,isBuiltinVendor}from"./chunk-h2m7em1e.js";import"./chunk-7ghwdjdc.js";import"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import{defaultUiPrefsStatePath,promptAttachmentsDir,resolveProductHomeDir,roveStateDir}from"./chunk-z1nj22va.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-0g4wc808.js";import{samePath}from"./chunk-pn5ygqn6.js";import{defaultDaemonSocketPath,defaultPtyHostSocketPath}from"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import"./chunk-pxk2c2vj.js";import{__commonJS,__require,__toESM}from"./chunk-91sykzqq.js";var require_ms=__commonJS((exports,module)=>{var s=1000,m=s*60,h=m*60,d=h*24,w=d*7,y=d*365.25;module.exports=function(val,options){options=options||{};var type=typeof val;if(type==="string"&&val.length>0)return parse(val);else if(type==="number"&&isFinite(val))return options.long?fmtLong(val):fmtShort(val);throw Error("val is not a non-empty string or a valid number. val="+JSON.stringify(val))};function parse(str){if(str=String(str),str.length>100)return;var match=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);if(!match)return;var n=parseFloat(match[1]),type=(match[2]||"ms").toLowerCase();switch(type){case"years":case"year":case"yrs":case"yr":case"y":return n*y;case"weeks":case"week":case"w":return n*w;case"days":case"day":case"d":return n*d;case"hours":case"hour":case"hrs":case"hr":case"h":return n*h;case"minutes":case"minute":case"mins":case"min":case"m":return n*m;case"seconds":case"second":case"secs":case"sec":case"s":return n*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}function fmtShort(ms){var msAbs=Math.abs(ms);if(msAbs>=d)return Math.round(ms/d)+"d";if(msAbs>=h)return Math.round(ms/h)+"h";if(msAbs>=m)return Math.round(ms/m)+"m";if(msAbs>=s)return Math.round(ms/s)+"s";return ms+"ms"}function fmtLong(ms){var msAbs=Math.abs(ms);if(msAbs>=d)return plural(ms,msAbs,d,"day");if(msAbs>=h)return plural(ms,msAbs,h,"hour");if(msAbs>=m)return plural(ms,msAbs,m,"minute");if(msAbs>=s)return plural(ms,msAbs,s,"second");return ms+" ms"}function plural(ms,msAbs,n,name){var isPlural=msAbs>=n*1.5;return Math.round(ms/n)+" "+name+(isPlural?"s":"")}});var require_common=__commonJS((exports,module)=>{function setup(env){createDebug.debug=createDebug,createDebug.default=createDebug,createDebug.coerce=coerce,createDebug.disable=disable,createDebug.enable=enable,createDebug.enabled=enabled,createDebug.humanize=require_ms(),createDebug.destroy=destroy,Object.keys(env).forEach((key)=>{createDebug[key]=env[key]}),createDebug.names=[],createDebug.skips=[],createDebug.formatters={};function selectColor(namespace){let hash=0;for(let i=0;i<namespace.length;i++)hash=(hash<<5)-hash+namespace.charCodeAt(i),hash|=0;return createDebug.colors[Math.abs(hash)%createDebug.colors.length]}createDebug.selectColor=selectColor;function createDebug(namespace){let prevTime,enableOverride=null,namespacesCache,enabledCache;function debug(...args){if(!debug.enabled)return;let self=debug,curr=Number(new Date),ms=curr-(prevTime||curr);if(self.diff=ms,self.prev=prevTime,self.curr=curr,prevTime=curr,args[0]=createDebug.coerce(args[0]),typeof args[0]!=="string")args.unshift("%O");let index=0;args[0]=args[0].replace(/%([a-zA-Z%])/g,(match,format)=>{if(match==="%%")return"%";index++;let formatter=createDebug.formatters[format];if(typeof formatter==="function"){let val=args[index];match=formatter.call(self,val),args.splice(index,1),index--}return match}),createDebug.formatArgs.call(self,args),(self.log||createDebug.log).apply(self,args)}if(debug.namespace=namespace,debug.useColors=createDebug.useColors(),debug.color=createDebug.selectColor(namespace),debug.extend=extend,debug.destroy=createDebug.destroy,Object.defineProperty(debug,"enabled",{enumerable:!0,configurable:!1,get:()=>{if(enableOverride!==null)return enableOverride;if(namespacesCache!==createDebug.namespaces)namespacesCache=createDebug.namespaces,enabledCache=createDebug.enabled(namespace);return enabledCache},set:(v)=>{enableOverride=v}}),typeof createDebug.init==="function")createDebug.init(debug);return debug}function extend(namespace,delimiter){let newDebug=createDebug(this.namespace+(typeof delimiter>"u"?":":delimiter)+namespace);return newDebug.log=this.log,newDebug}function enable(namespaces){createDebug.save(namespaces),createDebug.namespaces=namespaces,createDebug.names=[],createDebug.skips=[];let split=(typeof namespaces==="string"?namespaces:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let ns of split)if(ns[0]==="-")createDebug.skips.push(ns.slice(1));else createDebug.names.push(ns)}function matchesTemplate(search,template){let searchIndex=0,templateIndex=0,starIndex=-1,matchIndex=0;while(searchIndex<search.length)if(templateIndex<template.length&&(template[templateIndex]===search[searchIndex]||template[templateIndex]==="*"))if(template[templateIndex]==="*")starIndex=templateIndex,matchIndex=searchIndex,templateIndex++;else searchIndex++,templateIndex++;else if(starIndex!==-1)templateIndex=starIndex+1,matchIndex++,searchIndex=matchIndex;else return!1;while(templateIndex<template.length&&template[templateIndex]==="*")templateIndex++;return templateIndex===template.length}function disable(){let namespaces=[...createDebug.names,...createDebug.skips.map((namespace)=>"-"+namespace)].join(",");return createDebug.enable(""),namespaces}function enabled(name){for(let skip of createDebug.skips)if(matchesTemplate(name,skip))return!1;for(let ns of createDebug.names)if(matchesTemplate(name,ns))return!0;return!1}function coerce(val){if(val instanceof Error)return val.stack||val.message;return val}function destroy(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return createDebug.enable(createDebug.load()),createDebug}module.exports=setup});var require_browser=__commonJS((exports,module)=>{exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.storage=localstorage();exports.destroy=(()=>{let warned=!1;return()=>{if(!warned)warned=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}})();exports.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function useColors(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let m;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(m=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(m[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function formatArgs(args){if(args[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+args[0]+(this.useColors?"%c ":" ")+"+"+module.exports.humanize(this.diff),!this.useColors)return;let c="color: "+this.color;args.splice(1,0,c,"color: inherit");let index=0,lastC=0;args[0].replace(/%[a-zA-Z%]/g,(match)=>{if(match==="%%")return;if(index++,match==="%c")lastC=index}),args.splice(lastC,0,c)}exports.log=console.debug||console.log||(()=>{});function save(namespaces){try{if(namespaces)exports.storage.setItem("debug",namespaces);else exports.storage.removeItem("debug")}catch(error){}}function load(){let r;try{r=exports.storage.getItem("debug")||exports.storage.getItem("DEBUG")}catch(error){}if(!r&&typeof process<"u"&&"env"in process)r=process.env.DEBUG;return r}function localstorage(){try{return localStorage}catch(error){}}module.exports=require_common()(exports);var{formatters}=module.exports;formatters.j=function(v){try{return JSON.stringify(v)}catch(error){return"[UnexpectedJSONParseError]: "+error.message}}});var require_has_flag=__commonJS((exports,module)=>{module.exports=(flag,argv=process.argv)=>{let prefix=flag.startsWith("-")?"":flag.length===1?"-":"--",position=argv.indexOf(prefix+flag),terminatorPosition=argv.indexOf("--");return position!==-1&&(terminatorPosition===-1||position<terminatorPosition)}});var require_supports_color=__commonJS((exports,module)=>{var os=__require("os"),tty=__require("tty"),hasFlag=require_has_flag(),{env}=process,forceColor;if(hasFlag("no-color")||hasFlag("no-colors")||hasFlag("color=false")||hasFlag("color=never"))forceColor=0;else if(hasFlag("color")||hasFlag("colors")||hasFlag("color=true")||hasFlag("color=always"))forceColor=1;if("FORCE_COLOR"in env)if(env.FORCE_COLOR==="true")forceColor=1;else if(env.FORCE_COLOR==="false")forceColor=0;else forceColor=env.FORCE_COLOR.length===0?1:Math.min(parseInt(env.FORCE_COLOR,10),3);function translateLevel(level){if(level===0)return!1;return{level,hasBasic:!0,has256:level>=2,has16m:level>=3}}function supportsColor(haveStream,streamIsTTY){if(forceColor===0)return 0;if(hasFlag("color=16m")||hasFlag("color=full")||hasFlag("color=truecolor"))return 3;if(hasFlag("color=256"))return 2;if(haveStream&&!streamIsTTY&&forceColor===void 0)return 0;let min=forceColor||0;if(env.TERM==="dumb")return min;if(process.platform==="win32"){let osRelease=os.release().split(".");if(Number(osRelease[0])>=10&&Number(osRelease[2])>=10586)return Number(osRelease[2])>=14931?3:2;return 1}if("CI"in env){if(["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some((sign)=>(sign in env))||env.CI_NAME==="codeship")return 1;return min}if("TEAMCITY_VERSION"in env)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION)?1:0;if(env.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in env){let version=parseInt((env.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(env.TERM_PROGRAM){case"iTerm.app":return version>=3?3:2;case"Apple_Terminal":return 2}}if(/-256(color)?$/i.test(env.TERM))return 2;if(/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM))return 1;if("COLORTERM"in env)return 1;return min}function getSupportLevel(stream){let level=supportsColor(stream,stream&&stream.isTTY);return translateLevel(level)}module.exports={supportsColor:getSupportLevel,stdout:translateLevel(supportsColor(!0,tty.isatty(1))),stderr:translateLevel(supportsColor(!0,tty.isatty(2)))}});var require_node=__commonJS((exports,module)=>{var tty=__require("tty"),util=__require("util");exports.init=init;exports.log=log;exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.destroy=util.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");exports.colors=[6,2,3,4,5,1];try{let supportsColor=require_supports_color();if(supportsColor&&(supportsColor.stderr||supportsColor).level>=2)exports.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221]}catch(error){}exports.inspectOpts=Object.keys(process.env).filter((key)=>{return/^debug_/i.test(key)}).reduce((obj,key)=>{let prop=key.substring(6).toLowerCase().replace(/_([a-z])/g,(_,k)=>{return k.toUpperCase()}),val=process.env[key];if(/^(yes|on|true|enabled)$/i.test(val))val=!0;else if(/^(no|off|false|disabled)$/i.test(val))val=!1;else if(val==="null")val=null;else val=Number(val);return obj[prop]=val,obj},{});function useColors(){return"colors"in exports.inspectOpts?Boolean(exports.inspectOpts.colors):tty.isatty(process.stderr.fd)}function formatArgs(args){let{namespace:name,useColors:useColors2}=this;if(useColors2){let c=this.color,colorCode="\x1B[3"+(c<8?c:"8;5;"+c),prefix=` ${colorCode};1m${name} \x1B[0m`;args[0]=prefix+args[0].split(`
3
3
  `).join(`
4
4
  `+prefix),args.push(colorCode+"m+"+module.exports.humanize(this.diff)+"\x1B[0m")}else args[0]=getDate()+name+" "+args[0]}function getDate(){if(exports.inspectOpts.hideDate)return"";return new Date().toISOString()+" "}function log(...args){return process.stderr.write(util.formatWithOptions(exports.inspectOpts,...args)+`
5
5
  `)}function save(namespaces){if(namespaces)process.env.DEBUG=namespaces;else delete process.env.DEBUG}function load(){return process.env.DEBUG}function init(debug){debug.inspectOpts={};let keys=Object.keys(exports.inspectOpts);for(let i=0;i<keys.length;i++)debug.inspectOpts[keys[i]]=exports.inspectOpts[keys[i]]}module.exports=require_common()(exports);var{formatters}=module.exports;formatters.o=function(v){return this.inspectOpts.colors=this.useColors,util.inspect(v,this.inspectOpts).split(`
@@ -99,7 +99,7 @@ usage: rove-bridge [--preset tailscale|cf|relay] [--host <addr>]... [--port <n>]
99
99
  `){finish(),resolve(value);return}if(ch==="\x03"||ch==="\x04"){finish(),reject(Error("cancelled"));return}if(ch==="\x7F"||ch==="\b")value=[...value].slice(0,-1).join("");else if(ch>=" ")value+=ch}};stdin.on("data",onData)})}async function runPasswordAction(action,bridgeDir,prompt=promptHidden){let paths=webPasswordPaths(bridgeDir);if(action==="unlock")return writeLockout(paths.lockout,EMPTY_LOCKOUT),console.log("password login unlocked"),0;if(action==="clear-password")return console.log(clearPassword(paths.password)?"browser password removed":"no browser password was set"),writeLockout(paths.lockout,EMPTY_LOCKOUT),0;let first=await prompt("New browser password: ");if(first.length<MIN_PASSWORD_LENGTH||first.length>MAX_PASSWORD_LENGTH)return console.error(`the password must be ${MIN_PASSWORD_LENGTH}-${MAX_PASSWORD_LENGTH} characters; nothing changed`),1;if(await prompt("Again: ")!==first)return console.error("the two entries differ; nothing changed"),1;return writePassword(paths.password,await hashPassword(first)),writeLockout(paths.lockout,EMPTY_LOCKOUT),console.log(`browser password set (${paths.password}). A page without a token now shows a password field;
100
100
  each login gets its own device token (see --list-devices).`),0}class PromptFeed{now;listeners=new Set;seen=new Set;constructor(now=Date.now){this.now=now}push(prompt){if(!prompt||typeof prompt.promptId!=="string"||typeof prompt.title!=="string")return;if(typeof prompt.at!=="number"||this.now()-prompt.at>600000)return;if(this.seen.has(prompt.promptId))return;this.seen.add(prompt.promptId);let{promptId,title,placeholder,initial,at}=prompt,clean={promptId,title,at,...typeof placeholder==="string"?{placeholder}:{},...typeof initial==="string"?{initial}:{}};for(let listener of this.listeners)listener(clean)}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}}import{createHash as createHash2}from"crypto";import{existsSync as existsSync3,readFileSync as readFileSync3}from"fs";import{createCipheriv,createECDH,createPrivateKey,hkdfSync,randomBytes as randomBytes3,sign}from"crypto";var RECORD_SIZE=4096,VAPID_SUBJECT="https://rove.run",JWT_LIFETIME_S=43200,b64url=(bytes)=>Buffer.from(bytes).toString("base64url"),fromB64url=(text2)=>Buffer.from(text2,"base64url");function generateVapidKeys(){let ecdh=createECDH("prime256v1");return ecdh.generateKeys(),{publicKey:b64url(ecdh.getPublicKey()),privateKey:b64url(ecdh.getPrivateKey())}}var hkdf=(ikm,salt,info,length)=>Buffer.from(hkdfSync("sha256",ikm,salt,info,length));function encryptPayload(plaintext,keys,fixed={}){let uaPublic=fromB64url(keys.p256dh),authSecret=fromB64url(keys.auth),server=createECDH("prime256v1");if(fixed.serverPrivateKey)server.setPrivateKey(Buffer.from(fixed.serverPrivateKey));else server.generateKeys();let asPublic=server.getPublicKey(),ecdhSecret=server.computeSecret(uaPublic),keyInfo=Buffer.concat([Buffer.from("WebPush: info\x00"),uaPublic,asPublic]),ikm=hkdf(ecdhSecret,authSecret,keyInfo,32),salt=Buffer.from(fixed.salt??randomBytes3(16)),cek=hkdf(ikm,salt,Buffer.from("Content-Encoding: aes128gcm\x00"),16),nonce=hkdf(ikm,salt,Buffer.from("Content-Encoding: nonce\x00"),12),cipher=createCipheriv("aes-128-gcm",cek,nonce),sealed=Buffer.concat([cipher.update(Buffer.concat([plaintext,Buffer.from([2])])),cipher.final()]),header=Buffer.alloc(21);return salt.copy(header,0),header.writeUInt32BE(RECORD_SIZE,16),header.writeUInt8(asPublic.length,20),Buffer.concat([header,asPublic,sealed,cipher.getAuthTag()])}function vapidAuthorization(endpoint,vapid,nowMs=Date.now()){let pub=fromB64url(vapid.publicKey),key=createPrivateKey({format:"jwk",key:{kty:"EC",crv:"P-256",d:vapid.privateKey,x:b64url(pub.subarray(1,33)),y:b64url(pub.subarray(33,65))}}),part=(value)=>b64url(Buffer.from(JSON.stringify(value))),claims={aud:new URL(endpoint).origin,exp:Math.floor(nowMs/1000)+JWT_LIFETIME_S,sub:VAPID_SUBJECT},unsigned=`${part({typ:"JWT",alg:"ES256"})}.${part(claims)}`,signature=sign("sha256",Buffer.from(unsigned),{key,dsaEncoding:"ieee-p1363"});return`vapid t=${unsigned}.${b64url(signature)}, k=${vapid.publicKey}`}var PUSH_HOSTS=[/^fcm\.googleapis\.com$/,/(^|\.)push\.apple\.com$/,/^updates\.push\.services\.mozilla\.com$/,/(^|\.)notify\.windows\.com$/];function isPushEndpoint(endpoint){let url;try{url=new URL(endpoint)}catch{return!1}return url.protocol==="https:"&&url.port===""&&!url.username&&PUSH_HOSTS.some((host)=>host.test(url.hostname))}async function sendPush(target,payload,vapid,fetchImpl=fetch){let body=encryptPayload(Buffer.from(JSON.stringify(payload)),target);return(await fetchImpl(target.endpoint,{method:"POST",headers:{Authorization:vapidAuthorization(target.endpoint,vapid),"Content-Encoding":"aes128gcm","Content-Type":"application/octet-stream",TTL:String(86400),Urgency:"high"},body,signal:AbortSignal.timeout(1e4)})).status}var MAX_SUBSCRIPTIONS=32,sharedCredential=(token)=>`token:${createHash2("sha256").update(token).digest("hex").slice(0,32)}`;class PushHub{deps;file;visible=new Set;previous=null;unsubscribeFeed=null;constructor(deps){this.deps=deps;this.file=this.load(),this.follow()}publicKey(){return this.file.vapid.publicKey}subscribe(raw,credential){let target=parseSubscription(raw),now=(this.deps.now??(()=>new Date))().toISOString(),others=this.file.subscriptions.filter((s)=>s.endpoint!==target.endpoint);if(others.length>=MAX_SUBSCRIPTIONS)throw new BridgeError("TOO_MANY",`at most ${MAX_SUBSCRIPTIONS} browsers can be subscribed`);this.save([...others,{...target,credential,createdAt:now}])}unsubscribe(endpoint,credential){let before=this.file.subscriptions,after=before.filter((s)=>!(s.endpoint===endpoint&&s.credential===credential));if(after.length===before.length)return!1;return this.save(after),!0}subscribed(endpoint,credential){return this.file.subscriptions.some((s)=>s.endpoint===endpoint&&s.credential===credential)}setVisible(viewer,visible){if(visible)this.visible.add(viewer);else this.visible.delete(viewer)}follow(){let want=this.file.subscriptions.length>0;if(want&&!this.unsubscribeFeed)this.previous=null,this.unsubscribeFeed=this.deps.feed.subscribe((payload)=>void this.onTasks(payload));else if(!want&&this.unsubscribeFeed)this.unsubscribeFeed(),this.unsubscribeFeed=null}async onTasks(payload){let next=new Map;for(let task of payload.tasks)if(task.activity)next.set(task.id,task.activity.state);let edges=attentionEdges(this.previous,next,null,attentionKindFor);if(this.previous=next,edges.length===0||this.visible.size>0||!this.deps.crossTask())return;let titles=new Map(payload.tasks.map((task)=>[task.id,task.title])),live=this.file.subscriptions.filter((s)=>this.deps.credentialValid(s.credential)),gone=new Set(this.file.subscriptions.filter((s)=>!live.includes(s)).map((s)=>s.endpoint)),send=this.deps.send??((target,message,vapid)=>sendPush(target,message,vapid));for(let{key,kind}of edges){let message={taskId:key,kind,title:titles.get(key)??key};await Promise.all(live.map(async(s)=>{try{let status=await send(s,message,this.file.vapid);if(status===404||status===410)gone.add(s.endpoint);else if(status>=400)this.deps.log?.(`[rove-bridge] push ${new URL(s.endpoint).host}: HTTP ${status}`)}catch(err){this.deps.log?.(`[rove-bridge] push ${new URL(s.endpoint).host}: ${String(err)}`)}}))}if(gone.size>0)this.save(this.file.subscriptions.filter((s)=>!gone.has(s.endpoint)))}load(){try{if(existsSync3(this.deps.path)){let raw=JSON.parse(readFileSync3(this.deps.path,"utf8"));if(raw?.vapid?.publicKey&&raw.vapid.privateKey&&Array.isArray(raw.subscriptions))return raw}}catch{}let fresh={vapid:generateVapidKeys(),subscriptions:[]};return writeOwnerOnly(this.deps.path,`${JSON.stringify(fresh,null,2)}
101
101
  `),fresh}save(subscriptions){this.file={...this.file,subscriptions},writeOwnerOnly(this.deps.path,`${JSON.stringify(this.file,null,2)}
102
- `),this.follow()}}function parseSubscription(raw){let sub=raw,endpoint=sub?.endpoint;if(typeof endpoint!=="string"||!isPushEndpoint(endpoint))throw new BridgeError("BAD_ARGS","endpoint must be a browser push service URL");let{p256dh,auth}=sub?.keys??{};if(typeof p256dh!=="string"||fromB64url(p256dh).length!==65||fromB64url(p256dh)[0]!==4)throw new BridgeError("BAD_ARGS","keys.p256dh must be an uncompressed P-256 key");if(typeof auth!=="string"||fromB64url(auth).length!==16)throw new BridgeError("BAD_ARGS","keys.auth must be 16 bytes");return{endpoint,p256dh,auth}}import{isAbsolute,normalize}from"path";function gateRows(gates,tasks){let titles=new Map(tasks.map((t)=>[t.id,t.title]));return gates.filter((g)=>g.status==="open"||g.status==="answered"&&g.handoff==="undelivered").map((g)=>({id:g.id,taskId:g.taskId,tabId:g.tabId,question:g.question,options:g.options.map((o)=>({key:o.key,label:o.label,...o.detail?{detail:o.detail}:{}})),...g.recommended?{recommended:g.recommended}:{},...g.context?{context:g.context}:{},status:g.status,...g.status==="answered"&&g.handoff?{handoff:g.handoff}:{},createdAt:g.createdAt,label:titles.get(g.taskId)??g.taskId})).sort((a,b)=>a.createdAt.localeCompare(b.createdAt)||a.id.localeCompare(b.id,void 0,{numeric:!0}))}function dismissHitsOnlyGates(attention,taskId,tabId){let here=attention.filter((r)=>r.taskId===taskId&&r.tabId===(tabId??null));return here.length>0&&here.every((r)=>r.state==="decision_needed")}function flag(name,value){return`--${name}=${value}`}function oneOf(args,name,values){let v=args[name];if(typeof v!=="string"||!values.includes(v))throw new BridgeError("BAD_ARGS",`${name} must be one of ${values.join("|")}`);return v}function optOneOf(args,name,values){let v=args[name];if(v===void 0||v===null||v==="")return;return oneOf(args,name,values)}function bool2(args,name){let v=args[name];if(typeof v!=="boolean")throw new BridgeError("BAD_ARGS",`${name} must be a boolean`);return v}function text2(args,name,max){let v=args[name];if(typeof v!=="string"||v.trim().length===0)throw new BridgeError("BAD_ARGS",`${name} must be non-empty text`);if(v.length>max)throw new BridgeError("BAD_ARGS",`${name} is longer than ${max} characters`);return v}function optText(args,name,max){let v=args[name];if(v===void 0||v===null||v==="")return;return text2(args,name,max)}function sendReason(reason){if(reason===void 0||reason===null||reason==="")return;return typeof reason==="string"?reason:JSON.stringify(reason)}function taskId(args,name="taskId"){let v=args[name];if(typeof v!=="string"||!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(v))throw new BridgeError("BAD_ARGS",`${name} is not a task id`);return v}function tabId(args,name="tabId"){let v=args[name];if(typeof v!=="string"||!/^tab-\d{1,6}$/.test(v))throw new BridgeError("BAD_ARGS",`${name} is not a tab id`);return v}function absPath(args,name){let v=args[name];if(typeof v!=="string"||!v.startsWith("/")||v.includes("\x00"))throw new BridgeError("BAD_ARGS",`${name} must be an absolute path`);return v}import{execFile}from"child_process";import{statSync}from"fs";function projectKey(path){try{return resolveMainRepoRoot(path)}catch{return path}}var taskOpDeps={savedRepos:()=>getSavedRepos(),rememberEngine:(repo,engine)=>{setRepoLastActiveVendor(projectKey(repo),engine)},preferredEngine:(repo)=>resolvePreferredVendor(repo===void 0?void 0:projectKey(repo)),listLocalBranches,getCurrentBranch,validateRepoPath,isDirectory:(path)=>{try{return statSync(path).isDirectory()}catch{return!1}},cloneRepo,validateGitUrl,validateCloneTarget,resolveCloneTarget,findAvailableFolderName,deriveFolderName,gh:runGh,repoId:(path)=>repoIdOf(path),fetchPullHead},GIT_REF=/^[A-Za-z0-9][A-Za-z0-9._/-]{0,199}$/,MODEL=/^[A-Za-z0-9][A-Za-z0-9._:/@+-]{0,99}$/,EFFORT_LEVEL=/^[a-z0-9][a-z0-9-]{0,19}$/,ENGINE_ID=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,FOLDER=/^[A-Za-z0-9_][A-Za-z0-9._-]{0,99}$/;function gitRef(args,name){let v=args[name];if(typeof v!=="string"||!GIT_REF.test(v)||v.includes("..")||v.includes("//")||v.includes("/.")||v.endsWith("/")||v.endsWith(".")||v.endsWith(".lock"))throw new BridgeError("BAD_ARGS",`${name} is not a valid git ref name`);return v}function optGitRef(args,name){let v=args[name];return v===void 0||v===null||v===""?void 0:gitRef(args,name)}function model(args,name="model"){let v=args[name];if(typeof v!=="string"||!MODEL.test(v))throw new BridgeError("BAD_ARGS",`${name} is not a model id`);return v}function optModel(args,name="model"){let v=args[name];return v===void 0||v===null||v===""?void 0:model(args,name)}function effortLevel(args,name="level"){let v=args[name];if(typeof v!=="string"||!EFFORT_LEVEL.test(v))throw new BridgeError("BAD_ARGS",`${name} is not an effort level`);return v}async function knownEngineIds(ctx){let res=await ctx.api.verb("engine-list",[]);return new Set((res.engines??[]).map((e)=>e.id))}function checkEngineShape(id,name){if(typeof id!=="string"||!ENGINE_ID.test(id))throw new BridgeError("BAD_ARGS",`${name} is not an engine id`);return id}async function engineId(args,name,ctx){let id=checkEngineShape(args[name],name);if(!(await knownEngineIds(ctx)).has(id))throw new BridgeError("UNKNOWN_ENGINE",`${name} ${id} is not a known engine`);return id}var FANOUT_CAP=10;function parseAgents(args,name="agents"){let raw=args[name];if(typeof raw!=="string"||raw.length===0||raw.length>300)throw new BridgeError("BAD_ARGS",`${name} must be engine:count pairs like claude:2,codex:1`);let plan=[],total=0;for(let part of raw.split(",")){let m=/^([^:]+):(\d{1,2})$/.exec(part);if(!m)throw new BridgeError("BAD_ARGS",`${name} entry "${part}" must be engine:count`);let id=checkEngineShape(m[1],name),n=Number.parseInt(m[2],10);if(n<1)throw new BridgeError("BAD_ARGS",`${name} count for ${id} must be at least 1`);if(plan.some((p)=>p.id===id))throw new BridgeError("BAD_ARGS",`${name} names ${id} twice`);if(total+=n,total>FANOUT_CAP)throw new BridgeError("BAD_ARGS",`${name} asks for more than ${FANOUT_CAP} agents`);plan.push({id,n})}return plan}async function checkAgentEngines(plan,ctx){let known=await knownEngineIds(ctx);for(let{id}of plan)if(!known.has(id))throw new BridgeError("UNKNOWN_ENGINE",`agents engine ${id} is not a known engine`)}async function knownRepo(args,ctx,name="repo"){let repo=absPath(args,name);if(taskOpDeps.savedRepos().includes(repo))return repo;let{tasks}=await ctx.api.rpc("task.list");if(!tasks.some((t)=>t.repo===repo))throw new BridgeError("UNKNOWN_REPO",`${repo} is not a known project`);return repo}function runGh(args,timeoutMs){let{promise,resolve}=Promise.withResolvers();return execFile("gh",[...args],{timeout:timeoutMs,maxBuffer:8000000,env:{...process.env,GH_PROMPT_DISABLED:"1",NO_COLOR:"1"}},(err,stdout,stderr)=>{if(!err)return resolve({ok:!0,stdout});if(err.code==="ENOENT")return resolve({ok:!1,reason:"missing"});let signedOut=/gh auth login|not logged in|authentication/i.test(stderr);resolve({ok:!1,reason:signedOut?"unauthenticated":"failed"})}),promise}function fetchPullHead(repo,number){let{promise,resolve}=Promise.withResolvers(),ref=`refs/rove/pr/${number}`;return execFile("git",["-C",repo,"fetch","--no-tags","--quiet","origin",`+refs/pull/${number}/head:${ref}`],{timeout:60000,env:{...process.env,GIT_TERMINAL_PROMPT:"0"}},(err,_stdout,stderr)=>resolve(err?{ok:!1,error:stderr.trim()||String(err.message)}:{ok:!0,ref})),promise}var SHORTHAND=/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9._-]{1,100}$/;async function githubCloneUrl(shorthand){let name=shorthand.replace(/\.git$/i,""),protocol=await taskOpDeps.gh(["config","get","git_protocol"],3000);return protocol.ok&&protocol.stdout.trim()==="ssh"?`git@github.com:${name}.git`:`https://github.com/${name}.git`}async function cloneSource(args){let raw=typeof args.url==="string"?args.url.trim():"";if(SHORTHAND.test(raw)&&!/\/\.+(git)?$/i.test(raw))return cloneUrl({url:await githubCloneUrl(raw)});return cloneUrl(args)}var REPO_ID=/^(?:[A-Za-z0-9][A-Za-z0-9.-]*\.[A-Za-z0-9.-]+(?:\/[A-Za-z0-9._-]+){2,}|[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9._-]{1,100})$/;function remoteRepoRef(args,name="repo"){let v=args[name];if(typeof v==="string"&&v.startsWith("/"))return absPath(args,name);if(typeof v==="string"&&REPO_ID.test(v))return v;try{return cloneUrl(args,name)}catch{throw new BridgeError("BAD_ARGS",`${name} must be an absolute path or a repo id (owner/name, host/owner/name, or a clone URL)`)}}var URL_SCHEME=/^(https?|ssh|git):\/\/[A-Za-z0-9[]\S*$/i,URL_SCP=/^[A-Za-z0-9._-]+@[A-Za-z0-9][A-Za-z0-9.-]*:\S+$/;function cloneUrl(args,name="url"){let v=args[name];if(typeof v!=="string")throw new BridgeError("BAD_ARGS",`${name} must be a git URL`);let url=v.trim(),lower=url.toLowerCase();if(url.length===0||url.length>2000||url.startsWith("-")||lower.startsWith("ext::")||lower.startsWith("fd::")||lower.startsWith("file:")||url.includes("@-")||/\p{Cc}/u.test(url)||!(URL_SCHEME.test(url)||URL_SCP.test(url)))throw new BridgeError("BAD_ARGS",`${name} must be an https, http, ssh or git URL (or user@host:path)`);return url}function cloneFolder(folder){if(!FOLDER.test(folder)||folder==="."||folder==="..")throw new BridgeError("BAD_ARGS","folder must be one plain directory name");return folder}function rowLabels(tasks,sources){let tabsByTask=new Map;for(let task of tasks){let snapshot=sources?.tabs(task.id);if(!snapshot)continue;let vendor=task.vendor??DEFAULT_TASK_VENDOR;tabsByTask.set(task.id,snapshot.tabs.map((tab)=>{let title=conversationTitle(tab,vendor,sources?.sessions.get(tabPtyKeyFor(task.id,tab)));return{id:tab.id,...title?{title}:{},engine:tab.kind==="engine"}}))}return new Map(tasks.map((task)=>{let liveTitle=conversationTitleOf(task,tabsByTask);return[task.id,worktreeRowLabel(task,liveTitle?{liveTitle}:{})]}))}function engineFor(task,engines){let command=task.command?.trim(),preset=(command?engines.find((e)=>e.id===command||e.command===command):void 0)??engines.find((e)=>e.builtin&&e.protocol===task.vendor);if(preset)return{id:preset.id,name:preset.name};return task.vendor?{id:null,name:task.vendor}:null}function rowChanges(map,worktreePath){if(!map||!map.has(worktreePath))return;let c=map.get(worktreePath);if(!c)return{unreadable:!0};return{added:c.added,deleted:c.deleted,...c.ahead!==void 0?{ahead:c.ahead}:{},...c.behind!==void 0?{behind:c.behind}:{}}}function rowTokenChips(map,taskId2,now){return liveRowTokens(map,taskId2,now).map((t)=>({text:t.text,...t.tone?{tone:t.tone}:{},source:t.source,expiresAt:t.expiresAt}))}var PR_CHIP_BY_GLYPH={[DEFAULT_GLYPHS.conflict]:"conflict",[DEFAULT_GLYPHS.checksFailing]:"failing",[DEFAULT_GLYPHS.checksPassing]:"passing"};function prChipKind(task){let chip=prChip(task);return chip?PR_CHIP_BY_GLYPH[chip.glyph]??null:null}function rowPr(pr){return{...pr.number!==void 0?{number:pr.number}:{},...pr.url?{url:pr.url}:{},...pr.title?{title:pr.title}:{},...pr.additions!==void 0?{additions:pr.additions}:{},...pr.deletions!==void 0?{deletions:pr.deletions}:{},lifecycle:pr.lifecycle,checkState:pr.checkState,...pr.reviewDecision?{reviewDecision:pr.reviewDecision}:{},...pr.mergeable?{mergeable:pr.mergeable}:{}}}function sessionPrRows(task){return(task.sessionPrs??[]).map((entry)=>{if(entry.status)return rowPr({...entry.status,url:entry.status.url??entry.url});let number=Number(entry.url.match(/\/pull\/(\d+)$/)?.[1]);return{...Number.isInteger(number)?{number}:{},url:entry.url,lifecycle:"unknown",checkState:"unknown"}})}function attentionRows(items,tasks){let byId=new Map(tasks.map((t)=>[t.id,t]));return items.map((i)=>{let resumeAt=i.state==="rate_limited"&&i.taskId?byId.get(i.taskId)?.quotaResume?.resumeAt:void 0,label=i.detail?.routine?.name,deliveryId=i.state==="report_missing"?i.detail?.delivery?.id:void 0,gateId=i.state==="decision_needed"?i.detail?.gate?.id:void 0,automationId=i.detail?.routine?.automationId;return{taskId:i.taskId,tabId:i.tabId,state:i.state,unread:i.unread,at:i.at,...resumeAt?{resumeAt}:{},...label?{label}:{},...deliveryId?{deliveryId}:{},...gateId?{gateId}:{},...automationId?{automationId}:{}}})}function machineOf2(task){let origin=task.origin;if(!origin||origin.machineId==="local")return{};return{machine:{id:origin.machineId,label:origin.hostLabel,...origin.stale?{stale:!0}:{}}}}function remoteRowStatus(activity){let tasks={};for(let[taskId2,entry]of activity){let tabless=tabStatus({activity:{state:entry.state,at:entry.at},viewed:!1});tasks[taskId2]={task:taskStatus({},{tabless}),tabs:{}}}return{tasks,liveness:!1}}function groupingInputs(status){if(!status)return{activity:null,liveTaskIds:null};let activity={},live=new Set;for(let[taskId2,{task,tabs}]of Object.entries(status.tasks)){if(task.state)activity[taskId2]={state:task.state,at:task.since};if(Object.values(tabs).some((tab)=>tab.alive))live.add(taskId2)}return{activity,liveTaskIds:status.liveness?live:null}}function taskRows(tasks,status,engines,now,extras){let byId=new Map(tasks.map((t)=>[t.id,t])),orderOf=new Map(tasks.map((t,i)=>[t.id,i]));return buildContext({repo:"",tasks,...groupingInputs(status),attention:[],gates:[],notes:[],now,limit:Number.MAX_SAFE_INTEGER}).tasks.flatMap((row)=>{let task=byId.get(row.taskId);if(!task)return[];let pr=rollupPr(task),changes=rowChanges(extras?.changes??null,task.worktreePath),sessionPrs=sessionPrRows(task),tokens=rowTokenChips(extras?.tokens,task.id,now),chip=prChipKind(task),daemon=status?.tasks[task.id];return[{id:task.id,title:task.title,label:extras?.labels?.get(task.id)??task.title,branch:task.branch,repo:task.repo,kind:task.kind??"task",status:task.status,group:row.group,rank:row.rank,activity:row.activity?{...row.activity,since:now-row.activity.forMs}:null,...daemon?{rowStatus:daemon.task,tabStatus:daemon.tabs}:{},engine:engineFor(task,engines),pr:pr?rowPr(pr):null,...sessionPrs.length>0?{sessionPrs}:{},report:task.report?{summary:task.report.summary??"",at:task.report.at}:null,deleting:task.deletion?.phase==="queued"||task.deletion?.phase==="running",pinned:task.pinned===!0,...task.groupId?{groupId:task.groupId}:{},...task.kept?{kept:!0}:{},...task.autoFixCi?{autoFixCi:{attempts:task.autoFixCi.attempts,...task.autoFixCi.stopped?{stopped:!0}:{}}}:{},...task.notes?{notes:task.notes}:{},...task.todos?{todos:task.todos}:{},...task.archived?{archived:!0}:{},...task.routine?{routine:!0}:{},...task.scratch?{scratch:!0}:{},...task.noProject?{noProject:!0}:{},order:orderOf.get(task.id)??0,createdAt:task.createdAt,updatedAt:task.updatedAt,...machineOf2(task),...task.repoId?{repoId:task.repoId}:{},...task.extraRepos?.length?{extraRepoCount:task.extraRepos.length}:{},...task.parentTaskId?{parentTaskId:task.parentTaskId}:{},...task.baseRef?{baseRef:task.baseRef}:{},...task.sharesWorkspaceOf?{sharesWorkspaceOf:task.sharesWorkspaceOf}:{},...changes?{changes}:{},...tokens.length>0?{rowTokens:tokens}:{},prChip:chip,...task.prompt!==void 0?{hasPrompt:!0}:{},...task.scheduledStart?{startsAt:task.scheduledStart.at}:{},prChipStale:chip!==null&&pr?.lastError!==void 0,...task.worktreePath?{workspace:task.worktreePath}:{noWorktree:!0}}]})}function newTabInvocation(taskId2,tab){let command=tab.engine?[flag("command",tab.engine)]:[];if(tab.prompt===void 0&&!tab.engine&&tab.latest)command.push("--latest");if(tab.replaceTab!==void 0)return{verb:"send",argv:[flag("task-id",taskId2),"--tab=new","--plain",flag("handoff-from",tab.replaceTab),"--replace",...tab.prompt?[flag("prompt",tab.prompt)]:[],...command]};if(tab.prompt!==void 0)return{verb:"send",argv:[flag("task-id",taskId2),"--tab=new","--plain",flag("prompt",tab.prompt),...command]};return{verb:"tab-new",argv:[flag("task-id",taskId2),flag("kind",tab.kind),...command]}}function tabRows(rows,statuses){let nameOf=(vendor)=>vendor?engineDisplayName(vendor):null;return rows.map((t)=>({id:t.id,kind:t.kind,title:t.title??t.lastTitle??t.autoTitle,engineName:t.kind==="engine"?nameOf(t.liveVendor??t.vendor):null,conversation:t.kind==="engine"?conversationTitle({...t,kind:"engine",vendor:t.vendor??void 0,liveVendor:t.liveVendor??void 0},t.liveVendor??t.vendor??DEFAULT_TASK_VENDOR,t.liveTitle):null,alive:t.alive,engineAlive:t.engineAlive,...t.exit?{exit:{code:t.exit.code,signal:t.exit.signal}}:{},...t.split?{split:t.split}:{},...t.viewOf?{viewOf:t.viewOf}:{},...statuses?.[t.id]?{status:statuses[t.id]}:{}}))}async function tryRead(read){try{return await read()}catch{return null}}var ENGINE_CACHE_MS=60000;function createRoveOps(client,signals,api=createBridgeApi(client)){let engineCache=null,engineLoad=null,engines=async()=>{let rows;if(engineCache&&Date.now()-engineCache.at<ENGINE_CACHE_MS)rows=engineCache.engines;else engineLoad??=loadEngines().finally(()=>{engineLoad=null}),rows=await engineLoad;let off=getDisabledEngineIds();return rows.map((row)=>({...row,enabled:!off.includes(row.id)}))},loadEngines=async()=>{let res=await api.verb("engine-list",[]),rows=await Promise.all(res.engines.map(async({id,name,command,protocol,builtin,models})=>{let status=await tryRead(()=>detectEngineStatus(id));return{id,name,command,protocol,builtin,models:models??null,effortLevels:[...engineEntry(protocol).effortLevels??[]],acceptsModel:engineEntry(protocol).modelArgv!==void 0,...status?{ready:status.binary.found&&status.account?.kind!=="none"}:{}}}));return engineCache={at:Date.now(),engines:rows},rows},getTask=async(taskId2)=>{return(await api.verb("get-task",[flag("task-id",taskId2)])).task};return{async tasks(){let{tasks}=await client.request("task.list"),[inbox,engineRows,titleSources]=await Promise.all([tryRead(()=>client.request("attention.list")),tryRead(engines),tryRead(async()=>await signals?.titleSources?.()??null)]),now=Date.now(),statuses=signals?.rowStatus?.()??null,localStatus=statuses?{tasks:statuses,liveness:!0}:null,remoteTasks=signals?.remote?.()??[],labels=rowLabels([...tasks,...remoteTasks],titleSources),localExtras=signals?{changes:signals.changes(),tokens:signals.tokens(),labels}:void 0,pushed=signals?.remoteLive?.(),remoteStatus=pushed?remoteRowStatus(pushed.activity):null,remoteExtras=pushed?{changes:pushed.changes,tokens:pushed.tokens,labels}:void 0,rowsOf=(archived2)=>{let pick=(list)=>list.filter((t)=>t.archived===!0===archived2),local=taskRows(pick(tasks),localStatus,engineRows??[],now,localExtras),remote=taskRows(pick(remoteTasks),remoteStatus,engineRows??[],now,remoteExtras).map((row)=>({...row,order:(row.order??0)+tasks.length}));return[...local,...remote]},archived=rowsOf(!0);return{tasks:rowsOf(!1),attention:attentionRows(inbox?.items??[],tasks),gates:gateRows(signals?.gates()??[],tasks),...archived.length>0?{archived}:{}}},engines,async repos(){let{tasks}=await client.request("task.list");return[...new Set([...getSavedRepos(),...tasks.map((t)=>t.repo)])].sort()},async createTask({repo,engine,prompt,title}){let argv=[flag("repo",repo)];if(engine)argv.push(flag("command",engine));if(title)argv.push(flag("title",title));if(prompt)argv.push(flag("prompt",prompt));return{taskId:(await api.verb("add",argv)).taskId}},async deleteTask(taskId2,force,cascade){let argv=[flag("task-id",taskId2),"--wait"];if(force)argv.push("--force");if(cascade)argv.push("--cascade");let res=await api.verb("delete",argv);return{status:res.status??(res.queued?"queued":"removed")}},async landTask(taskId2,strategy){let res=await api.verb("land",[flag("task-id",taskId2),flag("strategy",strategy)]);if(res.landedOn!==void 0)return{landedOn:res.landedOn,commit:res.commit??""};return{landedOn:res.pr?.url??`${res.branch??"branch"} (pushed)`,commit:"",published:{branch:res.branch??"",prUrl:res.pr?.url??null,prError:res.prError??null}}},async tabs(taskId2){let res=await api.verb("get-task",[flag("task-id",taskId2)]);return tabRows(res.tabs??[],signals?.rowStatus?.()?.[taskId2]?.tabs)},async newTab(taskId2,tab){let call=newTabInvocation(taskId2,tab),res=await api.verb(call.verb,call.argv),tabId2=res.tabId??res.session?.split("::")[1];if(!tabId2)throw new BridgeError("SESSION_FAILED","the new tab did not report its session");if(tab.engine&&api.machineOf?.(taskId2)===void 0){let task=await tryRead(()=>getTask(taskId2));if(task)taskOpDeps.rememberEngine(task.repo,tab.engine)}return{tabId:tabId2,...res.childTaskId?{taskId:res.childTaskId}:{}}},async closeTab(taskId2,tabId2){await api.verb("tab-close",[flag("task-id",taskId2),flag("tab",tabId2)])},async reviveTab(taskId2,tabId2,restartExited){let res=await api.verb("tab-revive",[flag("task-id",taskId2),flag("tab",tabId2),...restartExited?["--restart-exited"]:[]]);return{revived:res.revived,resumed:res.resumed}},worktreeOf:async(taskId2)=>{let task=await getTask(taskId2);if(!task.worktreePath)throw new BridgeError("NO_WORKTREE",`task ${taskId2} has no worktree yet`);return task.worktreePath},viewedSession(taskId2,tabId2){let tab=loadStateFile()[terminalTabsKey(taskId2)]?.tabs?.find((t)=>t.id===tabId2);return tab?.kind==="engine"&&tab.ptyTask?{taskId:tab.ptyTask.id,tabId:tab.ptyTask.tabId??"tab-1",cwd:tab.ptyTask.worktree}:null},machineOf:(taskId2)=>api.machineOf?.(taskId2),async diffFiles(taskId2){if(api.machineOf?.(taskId2))return api.verb("worktree-diff",[flag("task-id",taskId2)]).catch((err)=>{if(err instanceof BridgeError&&err.code==="NO_WORKTREE")return{base:null,files:[]};throw err});let task=await getTask(taskId2);if(!task.worktreePath)return{base:null,files:[]};return worktreeDiff(task.worktreePath,task.prStatus?.baseRef)},async diffRefs(taskId2){if(api.machineOf?.(taskId2))return api.verb("worktree-refs",[flag("task-id",taskId2)]);let task=await getTask(taskId2);if(!task.worktreePath)throw new BridgeError("NO_WORKTREE",`task ${taskId2} has no worktree yet`);return worktreeRefs(task.worktreePath)},async diffFile(taskId2,path,scope,ignoreWhitespace,ref,content){if(isAbsolute(path)||normalize(path).split(/[\\/]/).includes(".."))throw new BridgeError("BAD_ARGS","path must be relative to the worktree");if(ref!==void 0&&scope!=="task")throw new BridgeError("BAD_ARGS","base only applies to the task scope");if(api.machineOf?.(taskId2))return api.verb("worktree-diff-file",[flag("task-id",taskId2),flag("path",path),flag("scope",scope),...ref!==void 0?[flag("base",ref)]:[],...ignoreWhitespace?["--ignore-whitespace"]:[]]);let task=await getTask(taskId2);if(!task.worktreePath)throw new BridgeError("NO_WORKTREE",`task ${taskId2} has no worktree yet`);let opts={ignoreWhitespace:ignoreWhitespace===!0};if(scope==="working"&&content)return loadFileContent(task.worktreePath,path);if(scope==="working")return loadPreviewData(task.worktreePath,path,void 0,opts);let base;if(ref!==void 0){if(base=await checkRef(task.worktreePath,ref),!base)throw new BridgeError("BAD_REF",`${ref} is not a commit in this repository`)}else base=await resolveBase(task.worktreePath,task.prStatus?.baseRef);if(!base)throw new BridgeError("NO_BASE","could not resolve a base branch for this task");return loadPreviewData(task.worktreePath,path,scope==="task"?{base,working:!0}:{base},opts)},async dismissAttention(taskId2,tabId2,deliveryId){await client.request("attention.dismiss",{taskId:taskId2,...tabId2?{tabId:tabId2}:{},...deliveryId?{deliveryId}:{}})}}}function isPayload(value){return!!value&&typeof value==="object"&&"tasks"in value&&!!value.tasks&&typeof value.tasks==="object"&&"rev"in value&&typeof value.rev==="number"}class RowStatusFeed{client;statuses=null;rev=-1;viewing=new Map;listeners=new Set;constructor(client){this.client=client;client.on("row.status",(frame)=>this.accept(frame.payload,!1))}current(){return this.statuses}async resync(){this.accept(await this.client.request("status.list"),!0);for(let[viewer,view]of this.viewing)this.sendViewing(viewer,view.taskId,view.tabId,view.fields)}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}setViewing(viewer,taskId2,tabId2,fields={}){let known=this.viewing.get(viewer);if(taskId2===null){if(!this.viewing.delete(viewer))return}else{if(known?.taskId===taskId2&&known.tabId===tabId2&&JSON.stringify(known.fields)===JSON.stringify(fields))return;this.viewing.set(viewer,{taskId:taskId2,tabId:tabId2,fields})}this.sendViewing(viewer,taskId2,tabId2,fields)}noteInput(stream,data){if(!(data==="\r"||data.endsWith("\r")))return;let[taskId2,tabId2]=stream.split("::");if(!taskId2||!tabId2)return;if(this.statuses?.[taskId2]?.tabs[tabId2]?.kind!=="needs-input")return;this.client.request("activity.answered",{taskId:taskId2,tabId:tabId2}).catch(()=>{})}sendViewing(viewer,taskId2,tabId2,fields){let extra=taskId2!==null?{...tabId2?{tabId:tabId2}:{},...fields}:{};this.client.request("ui.viewing",{viewer,taskId:taskId2,...extra}).catch(()=>{})}accept(payload,reset){if(!isPayload(payload)||!reset&&payload.rev<=this.rev)return;this.rev=payload.rev,this.statuses=payload.tasks;for(let listener of this.listeners)listener()}}import{hostname as osHostname}from"os";var DESTRUCTIVE_CORE={"task.delete":!0,"task.land":!0,"tab.close":!0},DESTRUCTIVE_VERBS={delete:!0,land:!0,"remove-worktree":!0,"tab-close":!0,"issue-delete":!0,"routine-delete":!0,"note-delete":!0};function logDestructiveVerb(sink,verb,params){let ids=["task-id","tab","id"].filter((key)=>typeof params[key]==="string"||typeof params[key]==="number").map((key)=>`${key}=${String(params[key])}`);audit(sink,`api.invoke ${verb}`,ids)}function logDestructive(sink,req){let ids=["taskId","tabId","path"].filter((key)=>typeof req.args[key]==="string").map((key)=>`${key}=${String(req.args[key])}`);audit(sink,req.op,ids)}function audit(sink,what,ids){let line=`[rove-bridge] ${new Date().toISOString()} ${what} ${ids.join(" ")}`.trimEnd();(sink.log??((l)=>console.error(l)))(`${line} ${sink.who}`)}class UsageStore{rows=null;sessions=null;set(snapshot){this.rows=snapshot===null?null:[...snapshot.entries()].map(([vendor,usage])=>({vendor,capturedAt:usage.capturedAt,windows:usage.windows.map(({kind,label,percent,resetsAt})=>({kind,label,percent,resetsAt}))})).sort((a,b)=>a.vendor.localeCompare(b.vendor))}get(){return this.rows}setContext(map){this.sessions=map}context(session){return this.sessions?.get(session)??null}}var usageStore=new UsageStore;function contextMeter(usage,session){let ctx=usage.context(session);if(!ctx||ctx.contextTokens<=0)return null;let used=ctx.contextTokens,window2=ctx.contextWindowTokens??null,share=(n)=>Math.min(100,n/(window2??used)*100),rows=ctx.parts?.length?ctx.parts.map((part)=>({key:part.key,tokens:part.tokens,share:share(part.tokens)})):[{key:"used",tokens:used,share:share(used)}];if(window2)rows.push({key:"free",tokens:Math.max(0,window2-used)});return{percent:window2?share(used):null,used,window:window2,rows,approximate:ctx.approximate===!0}}function createContextOps(usage){return{"context.usage":{kind:"read",destructive:!1,wraps:"the bridge usage store's `usage.context` entry for taskId::tabId (the engine history reader's reading)",async run(args){let taskId2=optText(args,"taskId",64),tabId2=optText(args,"tabId",32);return{meter:taskId2&&tabId2?contextMeter(usage,`${taskId2}::${tabId2}`):null}}}}}var contextOps=createContextOps(usageStore);import{unlinkSync}from"fs";import{join as join2}from"path";var realDeps={installHooks:async()=>{let{ensureGlobalRoveHooks}=await import("./chunk-49nb02t5.js");await ensureGlobalRoveHooks({quiet:!0})},uninstallHooks:async()=>{let{activityHookAdapters}=await import("./chunk-ec3esgj4.js");await Promise.all(activityHookAdapters().map(async(adapter)=>{try{await adapter.removeActivityHooks(adapter.globalSettingsPath())}catch{}}))},resetState:()=>{replaceStateFile({});try{unlinkSync(join2(roveStateDir(),"tasks.json"))}catch(err){if(err.code!=="ENOENT")throw new BridgeError("RESET_FAILED",`could not remove tasks.json: ${err.message}`)}}};function createDevOps(deps){return{"engines.hooks.install":{kind:"write",destructive:!0,wraps:"Settings \u2192 Engines install row: ensureGlobalRoveHooks into every engine's own config",async run(){return await deps.installHooks(),{}}},"engines.hooks.uninstall":{kind:"write",destructive:!0,wraps:"Settings \u2192 Engines uninstall row: removeActivityHooks for every hook adapter",async run(){return await deps.uninstallHooks(),{}}},"dev.reset":{kind:"write",destructive:!0,wraps:"Settings \u2192 Dev reset: replaceStateFile({}), remove tasks.json, then daemon.stop {reason: restart} so its in-memory tasks go too (worktrees and engine history stay)",async run(_args,{api}){return deps.resetState(),await api.rpc("daemon.stop",{reason:"restart"}).catch(()=>{return}),{}}},"daemon.restart":{kind:"write",destructive:!0,wraps:"Settings \u2192 Dev restart: daemon RPC daemon.stop {reason: restart} (PTY host and engine sessions keep running)",async run(_args,{api}){return await api.rpc("daemon.stop",{reason:"restart"}).catch(()=>{return}),{}}}}}var devOps=createDevOps(realDeps);var MAX_FILES=50000,MAX_NOTES=200,NOTE_MAX=4000,PATH_MAX=1024,MAX_LINE=1e7,CODE_MAX=8000,stateNoteStore={read(id){let notes=[];return updateStateFile((state)=>{let v=state[diffCommentsKey(id)];return notes=Array.isArray(v)?v:[],!1}),notes},update(id,mutate){updateStateFile((state)=>{let v=state[diffCommentsKey(id)];state[diffCommentsKey(id)]=mutate(Array.isArray(v)?v:[]);return})}},defaultDeps={listFiles:(worktree)=>listFiles(worktree),notes:stateNoteStore,now:Date.now,newId:()=>crypto.randomUUID()};async function worktreeOf(api,id){let path=(await api.verb("get-task",[flag("task-id",id)])).task.worktreePath;if(!path)throw new BridgeError("NO_WORKTREE",`task ${id} has no worktree yet`);return path}function relPath(args,name){let v=text2(args,name,PATH_MAX);if(v.startsWith("/")||v.includes("\x00")||v.split(/[\\/]/).includes(".."))throw new BridgeError("BAD_ARGS",`${name} must be relative to the worktree`);return v}function lineNo(args,name){let v=optInt(args,name,1,MAX_LINE);if(v===void 0)throw new BridgeError("BAD_ARGS",`${name} must be an integer in 1..${MAX_LINE}`);return v}var samePath2=(a,b)=>a.replace(/^\/private\//,"/")===b.replace(/^\/private\//,"/");function createFilesOps(deps=defaultDeps){let spec=(s)=>s,sending=new Set;return{"files.list":spec({kind:"read",destructive:!1,wraps:"listFiles(worktree) \u2014 tracked + untracked-not-ignored files",async run(args,{api}){let id=taskId(args),all=api.machineOf?.(id)?(await api.verb("worktree-files",[flag("task-id",id)])).files:await deps.listFiles(await worktreeOf(api,id)),truncated=all.length>MAX_FILES;return{files:truncated?all.slice(0,MAX_FILES):all,truncated}}}),"file.read":spec({kind:"read",destructive:!1,wraps:"rove api worktree-file \u2014 one markdown/HTML/SVG/image/PDF file of the task's worktree (real path confined to it, 5 MB cap), base64",async run(args,{api}){return api.verb("worktree-file",[flag("task-id",taskId(args)),flag("path",relPath(args,"path"))])}}),"review.list":spec({kind:"read",destructive:!1,wraps:"state.json diffComments.<taskId>",async run(args){let notes=deps.notes.read(taskId(args));return{notes,unsent:unsentComments(notes).length}}}),"review.add":spec({kind:"write",destructive:!1,wraps:"state.json diffComments.<taskId> (append)",async run(args){let id=taskId(args),line=lineNo(args,"line"),startLine=optInt(args,"startLine",1,MAX_LINE);if(startLine!==void 0&&startLine>line)throw new BridgeError("BAD_ARGS","startLine is after line");let code=optText(args,"code",CODE_MAX),note={id:deps.newId(),filePath:relPath(args,"filePath"),...startLine!==void 0&&startLine!==line?{startLine}:{},line,body:text2(args,"body",NOTE_MAX),...code?{code}:{},createdAt:deps.now()};return deps.notes.update(id,(cur)=>{if(cur.length>=MAX_NOTES)throw new BridgeError("TOO_MANY_NOTES",`a task keeps at most ${MAX_NOTES} notes`);return[...cur,note]}),{note}}}),"review.edit":spec({kind:"write",destructive:!1,wraps:"state.json diffComments.<taskId> (rewrite one note's text in place)",async run(args){let id=taskId(args),noteId=text2(args,"id",128),body=text2(args,"body",NOTE_MAX),note;if(deps.notes.update(id,(cur)=>cur.map((c)=>{if(c.id!==noteId)return c;return note={...c,body},note})),!note)throw new BridgeError("NOT_FOUND","no such note");return{note}}}),"review.remove":spec({kind:"write",destructive:!0,wraps:"state.json diffComments.<taskId> (drop one note)",async run(args){let id=taskId(args),noteId=text2(args,"id",128),removed=!1;return deps.notes.update(id,(cur)=>{let next=cur.filter((c)=>c.id!==noteId);return removed=next.length!==cur.length,next}),{removed}}}),"review.send":spec({kind:"write",destructive:!1,wraps:"rove api send --plain (all unsent notes as one prompt; sentAt only on confirmed delivery)",async run(args,{api}){let id=taskId(args),tab=args.tabId===void 0||args.tabId===null||args.tabId===""?void 0:tabId(args);if(sending.has(id))throw new BridgeError("SEND_IN_FLIGHT","this task's notes are already being sent");let unsent=unsentComments(deps.notes.read(id));if(unsent.length===0)return{sent:0,delivered:!0};sending.add(id);try{let worktree=await worktreeOf(api,id).catch(()=>{return}),prompt=formatDiffComments(unsent,worktree),res=await api.verb("send",[flag("task-id",id),"--plain",flag("prompt",prompt),...tab?[flag("tab",tab)]:[]]);if(res.delivered!==!0||res.targetState)return{sent:0,delivered:!1,reason:sendReason(res.targetDetail??res.reason)??(res.targetState?`engine is ${res.targetState}`:"not confirmed")};let batch=new Set(unsent.map((c)=>c.id)),sentAt=deps.now();return deps.notes.update(id,(cur)=>cur.map((c)=>batch.has(c.id)&&c.sentAt===void 0?{...c,sentAt}:c)),{sent:unsent.length,delivered:!0}}finally{sending.delete(id)}}}),"worktrees.list":spec({kind:"read",destructive:!1,wraps:"daemon RPC worktree.list {network} + task.list (taskId/taskKind joined by path)",async run(args,{api}){let network=args.network===void 0?!0:args.network===!0;if(args.network!==void 0&&typeof args.network!=="boolean")throw new BridgeError("BAD_ARGS","network must be a boolean");let[list,tasks]=await Promise.all([api.rpc("worktree.list",{network}),api.rpc("task.list")]);return{projects:list.projects.map((p)=>({repo:p.repo,worktrees:p.worktrees.map((w)=>{let t=tasks.tasks.find((x)=>x.worktreePath&&samePath2(x.worktreePath,w.path));return t?{...w,taskId:t.id,taskKind:t.kind??"task"}:w})}))}}}),"worktrees.remove":spec({kind:"write",destructive:!0,wraps:"daemon RPC worktree.remove {path, force}",async run(args,{api}){let path=absPath(args,"path"),force=bool2(args,"force");if(!(await api.rpc("worktree.list",{network:!1})).projects.some((p)=>p.worktrees.some((w)=>w.path===path)))throw new BridgeError("UNKNOWN_WORKTREE","that path is not a listed worktree");try{let res=await api.rpc("worktree.remove",{path,force});return{removed:res.removed,...res.residue?{residue:res.residue}:{}}}catch(err){if(err instanceof BridgeError&&err.message.startsWith("DIRTY_WORKTREE: "))throw new BridgeError("DIRTY_WORKTREE",err.message.slice(16));throw err}}})}}var filesOps=createFilesOps();var GATE_ID=/^g-\d{1,9}$/,OPTION_KEY=/^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$/,TEXT_MAX=4000,DAEMON_CODE=/^(GATE_NOT_FOUND|GATE_NOT_OPEN|BAD_OPTION): /;function gateId(args){let v=args.gateId;if(typeof v!=="string"||!GATE_ID.test(v))throw new BridgeError("BAD_ARGS","gateId is not a gate id");return v}async function answer(args,ctx){let id=gateId(args),option=args.option;if(option!==void 0&&option!==null&&(typeof option!=="string"||!OPTION_KEY.test(option)))throw new BridgeError("BAD_ARGS","option is not an option key");let text3=optText(args,"text",TEXT_MAX);if(!option&&!text3)throw new BridgeError("BAD_ARGS","answer needs an option or text");try{return{delivered:(await ctx.api.rpc("gate.answer",{gateId:id,...option?{option}:{},...text3?{text:text3}:{},by:"bridge"})).delivered===!0}}catch(err){let message=err instanceof Error?err.message:String(err),code=DAEMON_CODE.exec(message)?.[1];if(code)throw new BridgeError(code,message.replace(DAEMON_CODE,""));throw err}}var gateAnswer={kind:"write",destructive:!1,wraps:"rpc gate.answer (by: bridge)",run:answer},GATE_OPS={"gate.answer":gateAnswer};var spec=(kind,wraps,run,destructive=!1)=>({kind,destructive,wraps,run}),githubAuthOps={"github.status":spec("read","github-status (on `machine`, else this machine)",async(args,ctx)=>{let out=await attempt(ctx.api.verb("github-status",[],machineOf(args)));return out.ok?{status:out.result}:{status:null,reason:out.reason,message:out.message}}),"github.login":spec("write","github-login [--cancel] (on `machine`, else this machine)",(args,ctx)=>attempt(ctx.api.verb("github-login",optBool(args,"cancel")?[flag("cancel","true")]:[],machineOf(args)))),"github.logout":spec("write","github-logout (this machine's gh, signed out)",(_args,ctx)=>attempt(ctx.api.verb("github-logout",[])),!0),"github.sync":spec("write","github-sync --to `machine` (this machine's account signed in there)",async(args,ctx)=>{let machine=machineOf(args);if(!machine)throw new BridgeError("BAD_ARGS","machine must name a registered machine");return attempt(ctx.api.verb("github-sync",[flag("to",machine)]))})};var LIST_TIMEOUT_MS=15000;function parseRepos(stdout){let rows;try{rows=JSON.parse(stdout)}catch{return null}if(!Array.isArray(rows))return null;return rows.flatMap((row)=>typeof row?.nameWithOwner==="string"?[{nameWithOwner:row.nameWithOwner,description:typeof row.description==="string"?row.description:"",isPrivate:row.isPrivate===!0}]:[])}var githubOps={"github.repos":{kind:"read",destructive:!1,wraps:"gh repo list --limit 100 --json nameWithOwner,description,isPrivate (the machine's own gh login)",async run(){let res=await taskOpDeps.gh(["repo","list","--limit","100","--json","nameWithOwner,description,isPrivate"],LIST_TIMEOUT_MS);if(!res.ok)return{repos:[],reason:res.reason};let repos=parseRepos(res.stdout);return repos?{repos}:{repos:[],reason:"failed"}}}};var CURSOR=/^[A-Za-z0-9._~=-]{1,1024}$/;function given(args,name){let v=args[name];return v!==void 0&&v!==null&&v!==""}function optCursor(args){let raw=optText(args,"cursor",1024);if(raw===void 0)return;if(!CURSOR.test(raw))throw new BridgeError("BAD_ARGS","cursor is not a read-output cursor");return raw}var insightOps={"output.read":{kind:"read",destructive:!1,wraps:"rove api read-output (structured engine history, else a labeled terminal tail)",run(args,{api}){let argv=[flag("task-id",taskId(args))];if(given(args,"tab"))argv.push(flag("tab",tabId(args,"tab")));let source=optOneOf(args,"source",["auto","history","terminal"]);if(source)argv.push(flag("source",source));let cursor=optCursor(args);if(cursor)argv.push(flag("cursor",cursor));let limit=optInt(args,"limit",1,50);if(limit!==void 0)argv.push(flag("limit",limit));return api.verb("read-output",argv)}},"repo.digest":{kind:"read",destructive:!1,wraps:"rove api digest",run(args,{api}){let argv=[flag("repo",absPath(args,"repo"))],days=optInt(args,"sinceDays",1,365);if(days!==void 0)argv.push(flag("since-days",days));return api.verb("digest",argv)}},"turns.list":{kind:"read",destructive:!1,wraps:"rove api agent-turns",async run(args,{api}){let argv=[];if(given(args,"taskId"))argv.push(flag("task-id",taskId(args)));if(given(args,"repo"))argv.push(flag("repo",absPath(args,"repo")));let days=optInt(args,"sinceDays",1,365);if(days!==void 0)argv.push(flag("since-days",days));let limit=optInt(args,"limit",1,500);if(limit!==void 0)argv.push(flag("limit",limit));return{...await api.verb("agent-turns",argv),readers:vendorsWithTurnReader()}}},"sessions.search":{kind:"read",destructive:!1,wraps:"rove api search (user and assistant prose in every task's engine history)",run(args,{api}){let query=optText(args,"query",200)?.trim();if(!query)throw new BridgeError("BAD_ARGS","query is required");let argv=[flag("query",query)];if(given(args,"repo"))argv.push(flag("repo",absPath(args,"repo")));let limit=optInt(args,"limit",1,100);if(limit!==void 0)argv.push(flag("limit",limit));return api.verb("search",argv)}}};var CHORD_MAX=64,realDeps2={read(){return resetKeybindingsFileCache(),readKeybindingsFile()},create:createKeybindingsFile,fireAction(target){let[cmd,...rest]=[...roveCliInvocation(),"plugin","action","invoke",target];return spawnDetached(cmd,rest,{onError:(err)=>console.warn(`[rove/plugins] ${target}: ${String(err)}`)})},platform:process.platform},same=(a,b)=>JSON.stringify(a??null)===JSON.stringify(b??null);function copyKeymap(){return RoveKeymap.map((row)=>({id:row.id,scope:row.scope,keys:[...row.keys],...row.prefixKeys?{prefixKeys:[...row.prefixKeys]}:{},...row.hint?{hint:{...row.hint}}:{}}))}function createKeybindingsOps(deps=realDeps2){return{"keybindings.get":{kind:"read",destructive:!1,wraps:"helper resolveUserKeybindings (the TUI's keybindings.yaml parser) on a copy of the default keymap",async run(){let file=deps.read(),rows=copyKeymap(),{report,prefix}=resolveUserKeybindings(file,rows,deps.platform),changed=[];for(let row of rows){let base=RoveKeymap.find((candidate)=>candidate.id===row.id);if(base&&same(base.keys,row.keys)&&same(base.prefixKeys,row.prefixKeys)&&same(base.hint,row.hint))continue;changed.push({id:row.id,keys:row.keys,...row.prefixKeys?{prefixKeys:row.prefixKeys}:{},...row.hint?{hint:row.hint}:{}})}return{path:report.path,exists:report.exists,rows:changed,prefix:{key:prefix.key,firstStrokes:prefixFirstStrokes(prefix),timeoutMs:prefix.timeoutMs},plugins:report.plugins,applied:report.applied,warnings:report.warnings}}},"keybindings.createFile":{kind:"write",destructive:!1,wraps:"helper createKeybindingsFile (the fixed, fully commented starter; never overwrites)",async run(){let file=deps.read();if(file.exists)return{path:file.path,created:!1};return{path:file.path,created:deps.create(file.path)}}},"plugin.chordAction":{kind:"write",destructive:!1,wraps:"rove plugin action invoke <target> (detached), only for an `action:` bound to this chord in keybindings.yaml",async run(a){let chord=str(a,"chord");if(chord.length>CHORD_MAX)throw new BridgeError("BAD_ARGS","chord is too long");let file=deps.read(),{report}=resolveUserKeybindings(file,copyKeymap(),deps.platform),bound=report.plugins.find((p)=>p.chord===chord&&p.kind==="action");if(!bound)throw new BridgeError("NOT_BOUND",`${chord} is not bound to a plugin action`);if(!deps.fireAction(bound.target))throw new BridgeError("SESSION_FAILED",`could not start plugin action ${bound.target}`);return{target:bound.target}}}}}var keybindingsOps=createKeybindingsOps();var PATH_MAX2=1000,PANE_ID=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,launchDeps={panes(){return listPaneLaunches({socketPath:defaultDaemonSocketPath(),binPath:ROVE_PRODUCT_NAME}).map((p)=>({id:`${p.pluginId}.${p.paneId}`,title:p.title,placement:p.placement}))}};async function tabNew(api,id,kind,extra){let res=await api.verb("tab-new",[flag("task-id",id),flag("kind",kind),...extra]);if(!res.tabId)throw new BridgeError("SESSION_FAILED","the new tab did not report its id");return{tabId:res.tabId,...res.leaf?{leaf:res.leaf}:{}}}var launchOps={"file.openInEditor":{kind:"write",destructive:!1,wraps:"rove api tab-new --kind editor (the Mac's configured editor on a file inside the task's worktree)",async run(a,{api}){let rel=optStr(a,"path")??"";if(!rel||rel.length>PATH_MAX2||rel.startsWith("/")||rel.includes("\x00")||rel.split(/[\\/]/).includes(".."))throw new BridgeError("BAD_ARGS","path must be relative to the worktree");let{tabId:opened}=await tabNew(api,taskId(a),"editor",[flag("file",rel)]);return{tabId:opened}}},"plugin.panes":{kind:"read",destructive:!1,wraps:"helper listPaneLaunches (panes of enabled plugins)",async run(){return{panes:launchDeps.panes()}}},"plugin.paneOpen":{kind:"write",destructive:!1,wraps:"rove api tab-new --kind pane (a registered plugin pane; its argv comes from the manifest)",async run(a,{api}){let pane=str(a,"pane");if(!PANE_ID.test(pane))throw new BridgeError("BAD_ARGS","pane is not a plugin pane id");let extra=[flag("pane",pane)];if(a.tabId!==void 0&&a.tabId!==null)extra.push(flag("tab",tabId(a)));return tabNew(api,taskId(a),"pane",extra)}},"tab.openViewport":{kind:"write",destructive:!1,wraps:"rove api tab-new --kind viewport (a tab showing another task's first engine session)",async run(a,{api}){let{tabId:opened}=await tabNew(api,taskId(a),"viewport",[flag("view-task",taskId(a,"viewTaskId"))]);return{tabId:opened}}}};var PLUGIN_ID=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;function control(a){let plugin=text2(a,"plugin",128),pane=text2(a,"pane",64),key=text2(a,"key",64);if(!PLUGIN_ID.test(plugin)||!MOD_PANE_ID_PATTERN.test(pane)||!MOD_KEY_PATTERN.test(key))throw new BridgeError("BAD_ARGS","plugin, pane or key is not a mod id");return{plugin,pane,key}}function delivered(res){if(!res.ok)throw new BridgeError("MOD_UNAVAILABLE",`the mod did not get it (${res.reason??"unknown"})`);return{}}var modsOps={"mod.press":{kind:"write",destructive:!1,wraps:"daemon RPC mod.press (forwards a button key to the mod that drew it)",async run(a,{api}){return delivered(await api.rpc("mod.press",control(a)))}},"mod.submit":{kind:"write",destructive:!1,wraps:"daemon RPC mod.submit (forwards an input field's text to the mod that drew it)",async run(a,{api}){let value=a.value;if(typeof value!=="string")throw new BridgeError("BAD_ARGS","value must be text");if(value.length>MOD_INPUT_MAX)throw new BridgeError("BAD_ARGS",`value is longer than ${MOD_INPUT_MAX} characters`);return delivered(await api.rpc("mod.submit",{...control(a),value}))}}};var ISSUE_STATUSES=["open","doing","hold","done"],TITLE_MAX=300,BODY_MAX=20000,NAME_MAX=120,PROMPT_MAX=20000,EVENT_LIMIT=12;function issueId(args){let id=optInt(args,"id",1,1e9);if(id===void 0)throw new BridgeError("BAD_ARGS","id must be an issue number");return id}function cron(args,name){let v=text2(args,name,120).trim();if(!/^[0-9A-Za-z*/,\-?#LW]+(?: [0-9A-Za-z*/,\-?#LW]+){4}$/.test(v))throw new BridgeError("BAD_ARGS",`${name} must be five space-separated cron fields`);return v}function setIfPresent(argv,name,value){if(value!==void 0)argv.push(flag(name,value))}var pagesOps={"issue.repos":{kind:"read",destructive:!1,wraps:"daemon RPC issue.repos",run:(_args,{api})=>api.rpc("issue.repos",{})},"issue.list":{kind:"read",destructive:!1,wraps:"rove api issue-list",run:(args,{api})=>api.verb("issue-list",[flag("repo",absPath(args,"repo"))])},"issue.create":{kind:"write",destructive:!1,wraps:"rove api issue-create",run:(args,{api})=>{let argv=[flag("repo",absPath(args,"repo")),flag("title",text2(args,"title",TITLE_MAX).trim())];return setIfPresent(argv,"body",optText(args,"body",BODY_MAX)),api.verb("issue-create",argv)}},"issue.update":{kind:"write",destructive:!1,wraps:"rove api issue-update (title/body and/or task link; task=none unlinks; clearBody stores one space, the verb cannot send an empty body)",run:(args,{api})=>{let title=optText(args,"title",TITLE_MAX),typed=optText(args,"body",BODY_MAX);if(optBool(args,"clearBody")&&typed!==void 0)throw new BridgeError("BAD_ARGS","body and clearBody are exclusive");let body=optBool(args,"clearBody")?" ":typed,task=optStr(args,"task")===void 0?void 0:taskId(args,"task");if(title===void 0&&body===void 0&&task===void 0)throw new BridgeError("BAD_ARGS","issue.update needs title, body and/or task");let argv=[flag("repo",absPath(args,"repo")),flag("id",issueId(args))];return setIfPresent(argv,"title",title?.trim()),setIfPresent(argv,"body",body),setIfPresent(argv,"task",task),api.verb("issue-update",argv)}},"issue.setStatus":{kind:"write",destructive:!1,wraps:"rove api issue-update --status",run:(args,{api})=>api.verb("issue-update",[flag("repo",absPath(args,"repo")),flag("id",issueId(args)),flag("status",oneOf(args,"status",ISSUE_STATUSES))])},"issue.delete":{kind:"write",destructive:!0,wraps:"rove api issue-delete (the tracker record only; a linked task and worktree stay)",run:(args,{api})=>api.verb("issue-delete",[flag("repo",absPath(args,"repo")),flag("id",issueId(args))])},"issue.prompt":{kind:"read",destructive:!1,wraps:"rove api issue-list + the kanban drawer's issueWorktreePrompt/issueProjectPrompt helpers",async run(args,{api}){let where=oneOf(args,"where",["worktree","project"]),id=issueId(args),issue=(await api.verb("issue-list",[flag("repo",absPath(args,"repo"))])).issues.find((i)=>i.id===id);if(!issue)throw new BridgeError("ISSUE_NOT_FOUND",`no issue #${id}`);let cli=roveApiInvocation();return{title:issueChatTaskTitle(issue),prompt:where==="worktree"?issueWorktreePrompt(issue,cli):issueProjectPrompt(issue,cli)}}},"task.events":{kind:"read",destructive:!1,wraps:"daemon RPC task.recentEvents, newest first, as the drawer's EVENTS rows",async run(args,{api}){let id=taskId(args),limit=optInt(args,"limit",1,100)??EVENT_LIMIT;try{return{events:(await api.rpc("task.recentEvents",{taskId:id})).events.slice(-limit).reverse().map((event)=>({kind:event.kind,at:event.at,tail:[detailFragment(event),event.vendor??""].filter((part)=>part.length>0).join(" \xB7 ")}))}}catch(err){if(err instanceof Error&&/task not found/i.test(err.message))return{events:[]};throw err}}},"routine.list":{kind:"read",destructive:!1,wraps:"rove api routine-list",run:(_args,{api})=>api.verb("routine-list",[])},"routine.create":{kind:"write",destructive:!1,wraps:"rove api routine-create (name, optional repo \u2014 absent = no project, prompt, schedule, optional existing conversation targetTask+targetTab; never a precheck)",run:(args,{api})=>{let argv=[optStr(args,"repo")===void 0?"--no-repo":flag("repo",absPath(args,"repo")),flag("name",text2(args,"name",NAME_MAX).trim()),flag("prompt",text2(args,"prompt",PROMPT_MAX)),flag("schedule",cron(args,"schedule"))],hasTask=optStr(args,"targetTask")!==void 0,hasTab=optStr(args,"targetTab")!==void 0;if(hasTask!==hasTab)throw new BridgeError("BAD_ARGS","targetTask and targetTab go together");if(hasTask)argv.push(flag("target-task",taskId(args,"targetTask")),flag("target-tab",tabId(args,"targetTab")));return api.verb("routine-create",argv)}},"routine.update":{kind:"write",destructive:!1,wraps:"rove api routine-update (name, prompt, schedule; never a precheck)",run:(args,{api})=>{let name=optText(args,"name",NAME_MAX),prompt=optText(args,"prompt",PROMPT_MAX),schedule=optStr(args,"schedule")===void 0?void 0:cron(args,"schedule");if(name===void 0&&prompt===void 0&&schedule===void 0)throw new BridgeError("BAD_ARGS","routine.update needs name, prompt and/or schedule");let argv=[flag("id",taskId(args,"id"))];return setIfPresent(argv,"name",name?.trim()),setIfPresent(argv,"prompt",prompt),setIfPresent(argv,"schedule",schedule),api.verb("routine-update",argv)}},"routine.setEnabled":{kind:"write",destructive:!1,wraps:"rove api routine-update --enabled",run:(args,{api})=>api.verb("routine-update",[flag("id",taskId(args,"id")),flag("enabled",String(bool2(args,"enabled")))])},"routine.runNow":{kind:"write",destructive:!1,wraps:"rove api routine-run-now (skips the precheck; the schedule does not shift)",run:(args,{api})=>api.verb("routine-run-now",[flag("id",taskId(args,"id"))])},"routine.runs":{kind:"read",destructive:!1,wraps:"rove api routine-runs",run:(args,{api})=>api.verb("routine-runs",[flag("id",taskId(args,"id"))])},"routine.delete":{kind:"write",destructive:!0,wraps:"rove api routine-delete (the routine and its history; tasks it created stay)",run:(args,{api})=>api.verb("routine-delete",[flag("id",taskId(args,"id"))])},"attention.dismissRoutine":{kind:"write",destructive:!1,wraps:"daemon RPC attention.dismissRoutine (a routine episode is keyed on its schedule, not a task)",run:(args,{api})=>api.rpc("attention.dismissRoutine",{automationId:taskId(args,"automationId")})},"workitem.list":{kind:"read",destructive:!1,wraps:"daemon RPC workitem.list (same call as rove api workitem-list, plus refresh)",run:(args,{api})=>{let state=optOneOf(args,"state",["open","closed","all"]),assignee=optOneOf(args,"assignee",["@me"]),search=optText(args,"search",200),limit=optInt(args,"limit",1,50);return api.rpc("workitem.list",{repo:absPath(args,"repo"),...state?{state}:{},...assignee?{assignee}:{},...search?{search}:{},...limit!==void 0?{limit}:{},...optBool(args,"refresh")?{refresh:!0}:{}})}},"workitem.links":{kind:"read",destructive:!1,wraps:"daemon RPC task.list, folded to the tasks already started from a GitHub issue of this repo",async run(args,{api}){let repo=absPath(args,"repo"),{tasks}=await api.rpc("task.list",{});return{links:tasks.flatMap((task)=>task.linkedWorkItem?.number!==void 0&&samePath(task.repo,repo)?[{number:task.linkedWorkItem.number,taskId:task.id}]:[])}}},"workitem.start":{kind:"write",destructive:!1,wraps:"rove api workitem-start",run(args,{api}){let number=optInt(args,"number",1,1e9);if(number===void 0)throw new BridgeError("BAD_ARGS","number must be an issue number");let argv=[flag("repo",absPath(args,"repo")),flag("number",number)];return setIfPresent(argv,"vendor",optOneOf(args,"engine",ALL_VENDORS)),api.verb("workitem-start",argv)}}};var URL_MAX=2048,panelOps={"browser.probe":{kind:"read",destructive:!1,wraps:"frame probe (HTTPS HEAD to a public address; reads X-Frame-Options and CSP frame-ancestors)",async run(a){let{url,origin}=a;if(typeof url!=="string"||url.length===0||url.length>URL_MAX)throw new BridgeError("BAD_ARGS","url must be a URL string");if(origin!==void 0&&(typeof origin!=="string"||origin.length>URL_MAX))throw new BridgeError("BAD_ARGS","origin must be the page's origin string");return checkFrame(url,origin===void 0?{}:{origin})}}};var VIEW_TIMEOUT_MS=1e4,LOG_TIMEOUT_MS=30000,MAX_CHECKS=60,CHECKS_TTL_MS=30000,LOG_TTL_MS=60000,MAX_CACHED=24,LOG_LINES=40,LOG_CHARS=4000,RUN_ID=/^\d{1,15}$/,RANK={fail:0,pending:1,pass:2,skipped:3},realDeps3={gh:ghText,now:Date.now};function field(entry,key){let v=typeof entry==="object"&&entry!==null?entry[key]:void 0;return typeof v==="string"?v:""}function checkState(entry){let status=field(entry,"status").toUpperCase(),conclusion=field(entry,"conclusion").toUpperCase(),context=field(entry,"state").toUpperCase();if(status&&status!=="COMPLETED")return"pending";if(conclusion)return conclusion==="SUCCESS"?"pass":["NEUTRAL","SKIPPED","CANCELLED"].includes(conclusion)?"skipped":"fail";if(context==="SUCCESS")return"pass";if(context==="FAILURE"||context==="ERROR")return"fail";return"pending"}function durationOf(entry){let start=Date.parse(field(entry,"startedAt")),end=Date.parse(field(entry,"completedAt"));return Number.isFinite(start)&&Number.isFinite(end)&&end>=start?end-start:null}function checkRows(rollup){return rollup.map((entry,i)=>{let url=field(entry,"detailsUrl")||field(entry,"targetUrl");return{i,name:field(entry,"name")||field(entry,"context")||"check",state:checkState(entry),durationMs:durationOf(entry),url,runId:runIdFromDetailsUrl(url)}}).sort((a,b)=>RANK[a.state]-RANK[b.state]||a.i-b.i).map(({i:_,...row})=>row)}function cache(ttl){let map=new Map;return{get(key,now){let hit=map.get(key);return hit&&now-hit.at<ttl?hit.value:void 0},set(key,value,now){map.delete(key),map.set(key,{at:now,value});for(let old of map.keys()){if(map.size<=MAX_CACHED)break;map.delete(old)}}}}async function worktreeOf2(ctx,id){let res=await ctx.api.verb("get-task",[flag("task-id",id)]),{worktreePath,prStatus}=res.task;if(!worktreePath)throw new BridgeError("NO_WORKTREE",`task ${id} has no worktree yet`);return{worktree:worktreePath,pr:prStatus?.number}}function prChecksOps(deps=realDeps3){let checks=cache(CHECKS_TTL_MS),logs=cache(LOG_TTL_MS);return{"pr.checks":{kind:"read",destructive:!1,wraps:"gh pr view <n> --json statusCheckRollup,mergeable,mergeStateStatus,reviewDecision,isDraft (cached 30s)",async run(a,ctx){let id=taskId(a),{worktree,pr}=await worktreeOf2(ctx,id);if(pr===void 0)return{outcome:"none"};let key=`${id}:${pr}`,cached=a.fresh===!0?void 0:checks.get(key,deps.now());if(cached)return cached;let read=await deps.gh(["pr","view",String(pr),"--json","statusCheckRollup,mergeable,mergeStateStatus,reviewDecision,isDraft"],worktree,VIEW_TIMEOUT_MS);if(!read.ok)return{outcome:"unavailable",detail:read.detail};let view;try{view=JSON.parse(read.stdout)}catch{return{outcome:"unavailable",detail:"gh returned unreadable JSON"}}let rows=checkRows(Array.isArray(view.statusCheckRollup)?view.statusCheckRollup:[]),result={outcome:"ok",total:rows.length,checks:rows.slice(0,MAX_CHECKS),mergeable:typeof view.mergeable==="string"?view.mergeable:"",mergeState:typeof view.mergeStateStatus==="string"?view.mergeStateStatus:"",review:typeof view.reviewDecision==="string"?view.reviewDecision:"",draft:view.isDraft===!0};return checks.set(key,result,deps.now()),result}},"pr.checkLog":{kind:"read",destructive:!1,wraps:"gh run view <runId> --log-failed (last 40 lines of one job; cached 60s)",async run(a,ctx){let id=taskId(a),run=optText(a,"runId",20)??"";if(!RUN_ID.test(run))throw new BridgeError("BAD_ARGS","runId must be a run number");let job=optText(a,"job",200)??"";if(!job)throw new BridgeError("BAD_ARGS","job is required");let{worktree}=await worktreeOf2(ctx,id),byJob=logs.get(`${worktree}:${run}`,deps.now());if(!byJob){let read=await deps.gh(["run","view",run,"--log-failed"],worktree,LOG_TIMEOUT_MS);if(!read.ok)return{outcome:"unavailable",detail:read.detail};byJob=parseFailedRunLog(read.stdout,LOG_LINES),logs.set(`${worktree}:${run}`,byJob,deps.now())}let tail=(byJob.get(job)??[]).join(`
102
+ `),this.follow()}}function parseSubscription(raw){let sub=raw,endpoint=sub?.endpoint;if(typeof endpoint!=="string"||!isPushEndpoint(endpoint))throw new BridgeError("BAD_ARGS","endpoint must be a browser push service URL");let{p256dh,auth}=sub?.keys??{};if(typeof p256dh!=="string"||fromB64url(p256dh).length!==65||fromB64url(p256dh)[0]!==4)throw new BridgeError("BAD_ARGS","keys.p256dh must be an uncompressed P-256 key");if(typeof auth!=="string"||fromB64url(auth).length!==16)throw new BridgeError("BAD_ARGS","keys.auth must be 16 bytes");return{endpoint,p256dh,auth}}import{isAbsolute,normalize}from"path";function gateRows(gates,tasks){let titles=new Map(tasks.map((t)=>[t.id,t.title]));return gates.filter((g)=>g.status==="open"||g.status==="answered"&&g.handoff==="undelivered").map((g)=>({id:g.id,taskId:g.taskId,tabId:g.tabId,question:g.question,options:g.options.map((o)=>({key:o.key,label:o.label,...o.detail?{detail:o.detail}:{}})),...g.recommended?{recommended:g.recommended}:{},...g.context?{context:g.context}:{},status:g.status,...g.status==="answered"&&g.handoff?{handoff:g.handoff}:{},createdAt:g.createdAt,label:titles.get(g.taskId)??g.taskId})).sort((a,b)=>a.createdAt.localeCompare(b.createdAt)||a.id.localeCompare(b.id,void 0,{numeric:!0}))}function dismissHitsOnlyGates(attention,taskId,tabId){let here=attention.filter((r)=>r.taskId===taskId&&r.tabId===(tabId??null));return here.length>0&&here.every((r)=>r.state==="decision_needed")}function flag(name,value){return`--${name}=${value}`}function oneOf(args,name,values){let v=args[name];if(typeof v!=="string"||!values.includes(v))throw new BridgeError("BAD_ARGS",`${name} must be one of ${values.join("|")}`);return v}function optOneOf(args,name,values){let v=args[name];if(v===void 0||v===null||v==="")return;return oneOf(args,name,values)}function bool2(args,name){let v=args[name];if(typeof v!=="boolean")throw new BridgeError("BAD_ARGS",`${name} must be a boolean`);return v}function text2(args,name,max){let v=args[name];if(typeof v!=="string"||v.trim().length===0)throw new BridgeError("BAD_ARGS",`${name} must be non-empty text`);if(v.length>max)throw new BridgeError("BAD_ARGS",`${name} is longer than ${max} characters`);return v}function optText(args,name,max){let v=args[name];if(v===void 0||v===null||v==="")return;return text2(args,name,max)}function sendReason(reason){if(reason===void 0||reason===null||reason==="")return;return typeof reason==="string"?reason:JSON.stringify(reason)}function taskId(args,name="taskId"){let v=args[name];if(typeof v!=="string"||!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(v))throw new BridgeError("BAD_ARGS",`${name} is not a task id`);return v}function tabId(args,name="tabId"){let v=args[name];if(typeof v!=="string"||!/^tab-\d{1,6}$/.test(v))throw new BridgeError("BAD_ARGS",`${name} is not a tab id`);return v}function absPath(args,name){let v=args[name];if(typeof v!=="string"||!v.startsWith("/")||v.includes("\x00"))throw new BridgeError("BAD_ARGS",`${name} must be an absolute path`);return v}import{execFile}from"child_process";import{statSync}from"fs";function projectKey(path){try{return resolveMainRepoRoot(path)}catch{return path}}var taskOpDeps={savedRepos:()=>getSavedRepos(),rememberEngine:(repo,engine)=>{setRepoLastActiveVendor(projectKey(repo),engine)},preferredEngine:(repo)=>resolvePreferredVendor(repo===void 0?void 0:projectKey(repo)),listLocalBranches,getCurrentBranch,validateRepoPath,isDirectory:(path)=>{try{return statSync(path).isDirectory()}catch{return!1}},cloneRepo,validateGitUrl,validateCloneTarget,resolveCloneTarget,findAvailableFolderName,deriveFolderName,gh:runGh,repoId:(path)=>repoIdOf(path),fetchPullHead},GIT_REF=/^[A-Za-z0-9][A-Za-z0-9._/-]{0,199}$/,MODEL=/^[A-Za-z0-9][A-Za-z0-9._:/@+-]{0,99}$/,EFFORT_LEVEL=/^[a-z0-9][a-z0-9-]{0,19}$/,ENGINE_ID=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,FOLDER=/^[A-Za-z0-9_][A-Za-z0-9._-]{0,99}$/;function gitRef(args,name){let v=args[name];if(typeof v!=="string"||!GIT_REF.test(v)||v.includes("..")||v.includes("//")||v.includes("/.")||v.endsWith("/")||v.endsWith(".")||v.endsWith(".lock"))throw new BridgeError("BAD_ARGS",`${name} is not a valid git ref name`);return v}function optGitRef(args,name){let v=args[name];return v===void 0||v===null||v===""?void 0:gitRef(args,name)}function model(args,name="model"){let v=args[name];if(typeof v!=="string"||!MODEL.test(v))throw new BridgeError("BAD_ARGS",`${name} is not a model id`);return v}function optModel(args,name="model"){let v=args[name];return v===void 0||v===null||v===""?void 0:model(args,name)}function effortLevel(args,name="level"){let v=args[name];if(typeof v!=="string"||!EFFORT_LEVEL.test(v))throw new BridgeError("BAD_ARGS",`${name} is not an effort level`);return v}async function knownEngineIds(ctx){let res=await ctx.api.verb("engine-list",[]);return new Set((res.engines??[]).map((e)=>e.id))}function checkEngineShape(id,name){if(typeof id!=="string"||!ENGINE_ID.test(id))throw new BridgeError("BAD_ARGS",`${name} is not an engine id`);return id}async function engineId(args,name,ctx){let id=checkEngineShape(args[name],name);if(!(await knownEngineIds(ctx)).has(id))throw new BridgeError("UNKNOWN_ENGINE",`${name} ${id} is not a known engine`);return id}var FANOUT_CAP=10;function parseAgents(args,name="agents"){let raw=args[name];if(typeof raw!=="string"||raw.length===0||raw.length>300)throw new BridgeError("BAD_ARGS",`${name} must be engine:count pairs like claude:2,codex:1`);let plan=[],total=0;for(let part of raw.split(",")){let m=/^([^:]+):(\d{1,2})$/.exec(part);if(!m)throw new BridgeError("BAD_ARGS",`${name} entry "${part}" must be engine:count`);let id=checkEngineShape(m[1],name),n=Number.parseInt(m[2],10);if(n<1)throw new BridgeError("BAD_ARGS",`${name} count for ${id} must be at least 1`);if(plan.some((p)=>p.id===id))throw new BridgeError("BAD_ARGS",`${name} names ${id} twice`);if(total+=n,total>FANOUT_CAP)throw new BridgeError("BAD_ARGS",`${name} asks for more than ${FANOUT_CAP} agents`);plan.push({id,n})}return plan}async function checkAgentEngines(plan,ctx){let known=await knownEngineIds(ctx);for(let{id}of plan)if(!known.has(id))throw new BridgeError("UNKNOWN_ENGINE",`agents engine ${id} is not a known engine`)}async function knownRepo(args,ctx,name="repo"){let repo=absPath(args,name);if(taskOpDeps.savedRepos().includes(repo))return repo;let{tasks}=await ctx.api.rpc("task.list");if(!tasks.some((t)=>t.repo===repo))throw new BridgeError("UNKNOWN_REPO",`${repo} is not a known project`);return repo}function runGh(args,timeoutMs){let{promise,resolve}=Promise.withResolvers();return execFile("gh",[...args],{timeout:timeoutMs,maxBuffer:8000000,env:{...process.env,GH_PROMPT_DISABLED:"1",NO_COLOR:"1"}},(err,stdout,stderr)=>{if(!err)return resolve({ok:!0,stdout});if(err.code==="ENOENT")return resolve({ok:!1,reason:"missing"});let signedOut=/gh auth login|not logged in|authentication/i.test(stderr);resolve({ok:!1,reason:signedOut?"unauthenticated":"failed"})}),promise}function fetchPullHead(repo,number){let{promise,resolve}=Promise.withResolvers(),ref=`refs/rove/pr/${number}`;return execFile("git",["-C",repo,"fetch","--no-tags","--quiet","origin",`+refs/pull/${number}/head:${ref}`],{timeout:60000,env:{...process.env,GIT_TERMINAL_PROMPT:"0"}},(err,_stdout,stderr)=>resolve(err?{ok:!1,error:stderr.trim()||String(err.message)}:{ok:!0,ref})),promise}var SHORTHAND=/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9._-]{1,100}$/;async function githubCloneUrl(shorthand){let name=shorthand.replace(/\.git$/i,""),protocol=await taskOpDeps.gh(["config","get","git_protocol"],3000);return protocol.ok&&protocol.stdout.trim()==="ssh"?`git@github.com:${name}.git`:`https://github.com/${name}.git`}async function cloneSource(args){let raw=typeof args.url==="string"?args.url.trim():"";if(SHORTHAND.test(raw)&&!/\/\.+(git)?$/i.test(raw))return cloneUrl({url:await githubCloneUrl(raw)});return cloneUrl(args)}var REPO_ID=/^(?:[A-Za-z0-9][A-Za-z0-9.-]*\.[A-Za-z0-9.-]+(?:\/[A-Za-z0-9._-]+){2,}|[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9._-]{1,100})$/;function remoteRepoRef(args,name="repo"){let v=args[name];if(typeof v==="string"&&v.startsWith("/"))return absPath(args,name);if(typeof v==="string"&&REPO_ID.test(v))return v;try{return cloneUrl(args,name)}catch{throw new BridgeError("BAD_ARGS",`${name} must be an absolute path or a repo id (owner/name, host/owner/name, or a clone URL)`)}}var URL_SCHEME=/^(https?|ssh|git):\/\/[A-Za-z0-9[]\S*$/i,URL_SCP=/^[A-Za-z0-9._-]+@[A-Za-z0-9][A-Za-z0-9.-]*:\S+$/;function cloneUrl(args,name="url"){let v=args[name];if(typeof v!=="string")throw new BridgeError("BAD_ARGS",`${name} must be a git URL`);let url=v.trim(),lower=url.toLowerCase();if(url.length===0||url.length>2000||url.startsWith("-")||lower.startsWith("ext::")||lower.startsWith("fd::")||lower.startsWith("file:")||url.includes("@-")||/\p{Cc}/u.test(url)||!(URL_SCHEME.test(url)||URL_SCP.test(url)))throw new BridgeError("BAD_ARGS",`${name} must be an https, http, ssh or git URL (or user@host:path)`);return url}function cloneFolder(folder){if(!FOLDER.test(folder)||folder==="."||folder==="..")throw new BridgeError("BAD_ARGS","folder must be one plain directory name");return folder}function rowLabels(tasks,sources){let tabsByTask=new Map;for(let task of tasks){let snapshot=sources?.tabs(task.id);if(!snapshot)continue;let vendor=task.vendor??DEFAULT_TASK_VENDOR;tabsByTask.set(task.id,snapshot.tabs.map((tab)=>{let title=conversationTitle(tab,vendor,sources?.sessions.get(tabPtyKeyFor(task.id,tab)));return{id:tab.id,...title?{title}:{},engine:tab.kind==="engine"}}))}return new Map(tasks.map((task)=>{let liveTitle=conversationTitleOf(task,tabsByTask);return[task.id,worktreeRowLabel(task,liveTitle?{liveTitle}:{})]}))}function engineFor(task,engines){let command=task.command?.trim(),preset=(command?engines.find((e)=>e.id===command||e.command===command):void 0)??engines.find((e)=>e.builtin&&e.protocol===task.vendor);if(preset)return{id:preset.id,name:preset.name};return task.vendor?{id:null,name:task.vendor}:null}function rowChanges(map,worktreePath){if(!map||!map.has(worktreePath))return;let c=map.get(worktreePath);if(!c)return{unreadable:!0};return{added:c.added,deleted:c.deleted,...c.ahead!==void 0?{ahead:c.ahead}:{},...c.behind!==void 0?{behind:c.behind}:{}}}function rowTokenChips(map,taskId2,now){return liveRowTokens(map,taskId2,now).map((t)=>({text:t.text,...t.tone?{tone:t.tone}:{},source:t.source,expiresAt:t.expiresAt}))}var PR_CHIP_BY_GLYPH={[DEFAULT_GLYPHS.conflict]:"conflict",[DEFAULT_GLYPHS.checksFailing]:"failing",[DEFAULT_GLYPHS.checksPassing]:"passing"};function prChipKind(task){let chip=prChip(task);return chip?PR_CHIP_BY_GLYPH[chip.glyph]??null:null}function rowPr(pr){return{...pr.number!==void 0?{number:pr.number}:{},...pr.url?{url:pr.url}:{},...pr.title?{title:pr.title}:{},...pr.additions!==void 0?{additions:pr.additions}:{},...pr.deletions!==void 0?{deletions:pr.deletions}:{},lifecycle:pr.lifecycle,checkState:pr.checkState,...pr.reviewDecision?{reviewDecision:pr.reviewDecision}:{},...pr.mergeable?{mergeable:pr.mergeable}:{}}}function sessionPrRows(task){return(task.sessionPrs??[]).map((entry)=>{if(entry.status)return rowPr({...entry.status,url:entry.status.url??entry.url});let number=Number(entry.url.match(/\/pull\/(\d+)$/)?.[1]);return{...Number.isInteger(number)?{number}:{},url:entry.url,lifecycle:"unknown",checkState:"unknown"}})}function attentionRows(items,tasks){let byId=new Map(tasks.map((t)=>[t.id,t]));return items.map((i)=>{let resumeAt=i.state==="rate_limited"&&i.taskId?byId.get(i.taskId)?.quotaResume?.resumeAt:void 0,label=i.detail?.routine?.name,deliveryId=i.state==="report_missing"?i.detail?.delivery?.id:void 0,gateId=i.state==="decision_needed"?i.detail?.gate?.id:void 0,automationId=i.detail?.routine?.automationId;return{taskId:i.taskId,tabId:i.tabId,state:i.state,unread:i.unread,at:i.at,...resumeAt?{resumeAt}:{},...label?{label}:{},...deliveryId?{deliveryId}:{},...gateId?{gateId}:{},...automationId?{automationId}:{}}})}function machineOf2(task){let origin=task.origin;if(!origin||origin.machineId==="local")return{};return{machine:{id:origin.machineId,label:origin.hostLabel,...origin.stale?{stale:!0}:{}}}}function remoteRowStatus(activity){let tasks={};for(let[taskId2,entry]of activity){let tabless=tabStatus({activity:{state:entry.state,at:entry.at},viewed:!1});tasks[taskId2]={task:taskStatus({},{tabless}),tabs:{}}}return{tasks,liveness:!1}}function groupingInputs(status){if(!status)return{activity:null,liveTaskIds:null};let activity={},live=new Set;for(let[taskId2,{task,tabs}]of Object.entries(status.tasks)){if(task.state)activity[taskId2]={state:task.state,at:task.since};if(Object.values(tabs).some((tab)=>tab.alive))live.add(taskId2)}return{activity,liveTaskIds:status.liveness?live:null}}function taskRows(tasks,status,engines,now,extras){let byId=new Map(tasks.map((t)=>[t.id,t])),orderOf=new Map(tasks.map((t,i)=>[t.id,i]));return buildContext({repo:"",tasks,...groupingInputs(status),attention:[],gates:[],notes:[],now,limit:Number.MAX_SAFE_INTEGER}).tasks.flatMap((row)=>{let task=byId.get(row.taskId);if(!task)return[];let pr=rollupPr(task),changes=rowChanges(extras?.changes??null,task.worktreePath),sessionPrs=sessionPrRows(task),tokens=rowTokenChips(extras?.tokens,task.id,now),chip=prChipKind(task),daemon=status?.tasks[task.id];return[{id:task.id,title:task.title,label:extras?.labels?.get(task.id)??task.title,branch:task.branch,repo:task.repo,kind:task.kind??"task",status:task.status,group:row.group,rank:row.rank,activity:row.activity?{...row.activity,since:now-row.activity.forMs}:null,...daemon?{rowStatus:daemon.task,tabStatus:daemon.tabs}:{},engine:engineFor(task,engines),pr:pr?rowPr(pr):null,...sessionPrs.length>0?{sessionPrs}:{},report:task.report?{summary:task.report.summary??"",at:task.report.at}:null,deleting:task.deletion?.phase==="queued"||task.deletion?.phase==="running",pinned:task.pinned===!0,...task.groupId?{groupId:task.groupId}:{},...task.kept?{kept:!0}:{},...task.autoFixCi?{autoFixCi:{attempts:task.autoFixCi.attempts,...task.autoFixCi.stopped?{stopped:!0}:{}}}:{},...task.notes?{notes:task.notes}:{},...task.todos?{todos:task.todos}:{},...task.archived?{archived:!0}:{},...task.routine?{routine:!0}:{},...task.scratch?{scratch:!0}:{},...task.noProject?{noProject:!0}:{},order:orderOf.get(task.id)??0,createdAt:task.createdAt,updatedAt:task.updatedAt,...machineOf2(task),...task.repoId?{repoId:task.repoId}:{},...task.extraRepos?.length?{extraRepoCount:task.extraRepos.length}:{},...task.parentTaskId?{parentTaskId:task.parentTaskId}:{},...task.baseRef?{baseRef:task.baseRef}:{},...task.sharesWorkspaceOf?{sharesWorkspaceOf:task.sharesWorkspaceOf}:{},...changes?{changes}:{},...tokens.length>0?{rowTokens:tokens}:{},prChip:chip,...task.prompt!==void 0?{hasPrompt:!0}:{},...task.scheduledStart?{startsAt:task.scheduledStart.at}:{},prChipStale:chip!==null&&pr?.lastError!==void 0,...task.worktreePath?{workspace:task.worktreePath}:{noWorktree:!0}}]})}function newTabInvocation(taskId2,tab){let command=tab.engine?[flag("command",tab.engine)]:[];if(tab.prompt===void 0&&!tab.engine&&tab.latest)command.push("--latest");if(tab.replaceTab!==void 0)return{verb:"send",argv:[flag("task-id",taskId2),"--tab=new","--plain",flag("handoff-from",tab.replaceTab),"--replace",...tab.prompt?[flag("prompt",tab.prompt)]:[],...command]};if(tab.prompt!==void 0)return{verb:"send",argv:[flag("task-id",taskId2),"--tab=new","--plain",flag("prompt",tab.prompt),...command]};return{verb:"tab-new",argv:[flag("task-id",taskId2),flag("kind",tab.kind),...command]}}function tabRows(rows,statuses){let nameOf=(vendor)=>vendor?engineDisplayName(vendor):null;return rows.map((t)=>({id:t.id,kind:t.kind,title:t.title??t.lastTitle??t.autoTitle,engineName:t.kind==="engine"?nameOf(t.liveVendor??t.vendor):null,conversation:t.kind==="engine"?conversationTitle({...t,kind:"engine",vendor:t.vendor??void 0,liveVendor:t.liveVendor??void 0},t.liveVendor??t.vendor??DEFAULT_TASK_VENDOR,t.liveTitle):null,alive:t.alive,engineAlive:t.engineAlive,...t.exit?{exit:{code:t.exit.code,signal:t.exit.signal}}:{},...t.split?{split:t.split}:{},...t.viewOf?{viewOf:t.viewOf}:{},...statuses?.[t.id]?{status:statuses[t.id]}:{}}))}async function tryRead(read){try{return await read()}catch{return null}}var ENGINE_CACHE_MS=60000;function createRoveOps(client,signals,api=createBridgeApi(client)){let engineCache=null,engineLoad=null,engines=async()=>{let rows;if(engineCache&&Date.now()-engineCache.at<ENGINE_CACHE_MS)rows=engineCache.engines;else engineLoad??=loadEngines().finally(()=>{engineLoad=null}),rows=await engineLoad;let off=getDisabledEngineIds();return rows.map((row)=>({...row,enabled:!off.includes(row.id)}))},loadEngines=async()=>{let res=await api.verb("engine-list",[]),rows=await Promise.all(res.engines.map(async({id,name,command,protocol,builtin,models})=>{let status=await tryRead(()=>detectEngineStatus(id));return{id,name,command,protocol,builtin,models:models??null,effortLevels:[...engineEntry(protocol).effortLevels??[]],acceptsModel:engineEntry(protocol).modelArgv!==void 0,...status?{ready:status.binary.found&&status.account?.kind!=="none"}:{}}}));return engineCache={at:Date.now(),engines:rows},rows},getTask=async(taskId2)=>{return(await api.verb("get-task",[flag("task-id",taskId2)])).task};return{async tasks(){let{tasks}=await client.request("task.list"),[inbox,engineRows,titleSources]=await Promise.all([tryRead(()=>client.request("attention.list")),tryRead(engines),tryRead(async()=>await signals?.titleSources?.()??null)]),now=Date.now(),statuses=signals?.rowStatus?.()??null,localStatus=statuses?{tasks:statuses,liveness:!0}:null,remoteTasks=signals?.remote?.()??[],labels=rowLabels([...tasks,...remoteTasks],titleSources),localExtras=signals?{changes:signals.changes(),tokens:signals.tokens(),labels}:void 0,pushed=signals?.remoteLive?.(),remoteStatus=pushed?remoteRowStatus(pushed.activity):null,remoteExtras=pushed?{changes:pushed.changes,tokens:pushed.tokens,labels}:void 0,rowsOf=(archived2)=>{let pick=(list)=>list.filter((t)=>t.archived===!0===archived2),local=taskRows(pick(tasks),localStatus,engineRows??[],now,localExtras),remote=taskRows(pick(remoteTasks),remoteStatus,engineRows??[],now,remoteExtras).map((row)=>({...row,order:(row.order??0)+tasks.length}));return[...local,...remote]},archived=rowsOf(!0);return{tasks:rowsOf(!1),attention:attentionRows(inbox?.items??[],tasks),gates:gateRows(signals?.gates()??[],tasks),...archived.length>0?{archived}:{}}},engines,async repos(){let{tasks}=await client.request("task.list");return[...new Set([...getSavedRepos(),...tasks.map((t)=>t.repo)])].sort()},async createTask({repo,engine,prompt,title}){let argv=[flag("repo",repo)];if(engine)argv.push(flag("command",engine));if(title)argv.push(flag("title",title));if(prompt)argv.push(flag("prompt",prompt));return{taskId:(await api.verb("add",argv)).taskId}},async deleteTask(taskId2,force,cascade){let argv=[flag("task-id",taskId2),"--wait"];if(force)argv.push("--force");if(cascade)argv.push("--cascade");let res=await api.verb("delete",argv);return{status:res.status??(res.queued?"queued":"removed")}},async landTask(taskId2,strategy){let res=await api.verb("land",[flag("task-id",taskId2),flag("strategy",strategy)]);if(res.landedOn!==void 0)return{landedOn:res.landedOn,commit:res.commit??""};return{landedOn:res.pr?.url??`${res.branch??"branch"} (pushed)`,commit:"",published:{branch:res.branch??"",prUrl:res.pr?.url??null,prError:res.prError??null}}},async tabs(taskId2){let res=await api.verb("get-task",[flag("task-id",taskId2)]);return tabRows(res.tabs??[],signals?.rowStatus?.()?.[taskId2]?.tabs)},async newTab(taskId2,tab){let call=newTabInvocation(taskId2,tab),res=await api.verb(call.verb,call.argv),tabId2=res.tabId??res.session?.split("::")[1];if(!tabId2)throw new BridgeError("SESSION_FAILED","the new tab did not report its session");if(tab.engine&&api.machineOf?.(taskId2)===void 0){let task=await tryRead(()=>getTask(taskId2));if(task)taskOpDeps.rememberEngine(task.repo,tab.engine)}return{tabId:tabId2,...res.childTaskId?{taskId:res.childTaskId}:{}}},async closeTab(taskId2,tabId2){await api.verb("tab-close",[flag("task-id",taskId2),flag("tab",tabId2)])},async reviveTab(taskId2,tabId2,restartExited){let res=await api.verb("tab-revive",[flag("task-id",taskId2),flag("tab",tabId2),...restartExited?["--restart-exited"]:[]]);return{revived:res.revived,resumed:res.resumed}},worktreeOf:async(taskId2)=>{let task=await getTask(taskId2);if(!task.worktreePath)throw new BridgeError("NO_WORKTREE",`task ${taskId2} has no worktree yet`);return task.worktreePath},viewedSession(taskId2,tabId2){let tab=loadStateFile()[terminalTabsKey(taskId2)]?.tabs?.find((t)=>t.id===tabId2);return tab?.kind==="engine"&&tab.ptyTask?{taskId:tab.ptyTask.id,tabId:tab.ptyTask.tabId??"tab-1",cwd:tab.ptyTask.worktree}:null},machineOf:(taskId2)=>api.machineOf?.(taskId2),async diffFiles(taskId2){if(api.machineOf?.(taskId2))return api.verb("worktree-diff",[flag("task-id",taskId2)]).catch((err)=>{if(err instanceof BridgeError&&err.code==="NO_WORKTREE")return{base:null,files:[]};throw err});let task=await getTask(taskId2);if(!task.worktreePath)return{base:null,files:[]};return worktreeDiff(task.worktreePath,task.prStatus?.baseRef)},async diffRefs(taskId2){if(api.machineOf?.(taskId2))return api.verb("worktree-refs",[flag("task-id",taskId2)]);let task=await getTask(taskId2);if(!task.worktreePath)throw new BridgeError("NO_WORKTREE",`task ${taskId2} has no worktree yet`);return worktreeRefs(task.worktreePath)},async diffFile(taskId2,path,scope,ignoreWhitespace,ref,content){if(isAbsolute(path)||normalize(path).split(/[\\/]/).includes(".."))throw new BridgeError("BAD_ARGS","path must be relative to the worktree");if(ref!==void 0&&scope!=="task")throw new BridgeError("BAD_ARGS","base only applies to the task scope");if(api.machineOf?.(taskId2))return api.verb("worktree-diff-file",[flag("task-id",taskId2),flag("path",path),flag("scope",scope),...ref!==void 0?[flag("base",ref)]:[],...ignoreWhitespace?["--ignore-whitespace"]:[]]);let task=await getTask(taskId2);if(!task.worktreePath)throw new BridgeError("NO_WORKTREE",`task ${taskId2} has no worktree yet`);let opts={ignoreWhitespace:ignoreWhitespace===!0};if(scope==="working"&&content)return loadFileContent(task.worktreePath,path);if(scope==="working")return loadPreviewData(task.worktreePath,path,void 0,opts);let base;if(ref!==void 0){if(base=await checkRef(task.worktreePath,ref),!base)throw new BridgeError("BAD_REF",`${ref} is not a commit in this repository`)}else base=await resolveBase(task.worktreePath,task.prStatus?.baseRef);if(!base)throw new BridgeError("NO_BASE","could not resolve a base branch for this task");return loadPreviewData(task.worktreePath,path,scope==="task"?{base,working:!0}:{base},opts)},async dismissAttention(taskId2,tabId2,deliveryId){await client.request("attention.dismiss",{taskId:taskId2,...tabId2?{tabId:tabId2}:{},...deliveryId?{deliveryId}:{}})}}}function isPayload(value){return!!value&&typeof value==="object"&&"tasks"in value&&!!value.tasks&&typeof value.tasks==="object"&&"rev"in value&&typeof value.rev==="number"}class RowStatusFeed{client;statuses=null;rev=-1;viewing=new Map;listeners=new Set;constructor(client){this.client=client;client.on("row.status",(frame)=>this.accept(frame.payload,!1))}current(){return this.statuses}async resync(){this.accept(await this.client.request("status.list"),!0);for(let[viewer,view]of this.viewing)this.sendViewing(viewer,view.taskId,view.tabId,view.fields)}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}setViewing(viewer,taskId2,tabId2,fields={}){let known=this.viewing.get(viewer);if(taskId2===null){if(!this.viewing.delete(viewer))return}else{if(known?.taskId===taskId2&&known.tabId===tabId2&&JSON.stringify(known.fields)===JSON.stringify(fields))return;this.viewing.set(viewer,{taskId:taskId2,tabId:tabId2,fields})}this.sendViewing(viewer,taskId2,tabId2,fields)}noteInput(stream,data){if(!(data==="\r"||data.endsWith("\r")))return;let[taskId2,tabId2]=stream.split("::");if(!taskId2||!tabId2)return;if(this.statuses?.[taskId2]?.tabs[tabId2]?.kind!=="needs-input")return;this.client.request("activity.answered",{taskId:taskId2,tabId:tabId2}).catch(()=>{})}sendViewing(viewer,taskId2,tabId2,fields){let extra=taskId2!==null?{...tabId2?{tabId:tabId2}:{},...fields}:{};this.client.request("ui.viewing",{viewer,taskId:taskId2,...extra}).catch(()=>{})}accept(payload,reset){if(!isPayload(payload)||!reset&&payload.rev<=this.rev)return;this.rev=payload.rev,this.statuses=payload.tasks;for(let listener of this.listeners)listener()}}import{hostname as osHostname}from"os";var DESTRUCTIVE_CORE={"task.delete":!0,"task.land":!0,"tab.close":!0},DESTRUCTIVE_VERBS={delete:!0,land:!0,"remove-worktree":!0,"tab-close":!0,"issue-delete":!0,"routine-delete":!0,"note-delete":!0};function logDestructiveVerb(sink,verb,params){let ids=["task-id","tab","id"].filter((key)=>typeof params[key]==="string"||typeof params[key]==="number").map((key)=>`${key}=${String(params[key])}`);audit(sink,`api.invoke ${verb}`,ids)}function logDestructive(sink,req){let ids=["taskId","tabId","path"].filter((key)=>typeof req.args[key]==="string").map((key)=>`${key}=${String(req.args[key])}`);audit(sink,req.op,ids)}function audit(sink,what,ids){let line=`[rove-bridge] ${new Date().toISOString()} ${what} ${ids.join(" ")}`.trimEnd();(sink.log??((l)=>console.error(l)))(`${line} ${sink.who}`)}class UsageStore{rows=null;sessions=null;set(snapshot){this.rows=snapshot===null?null:[...snapshot.entries()].map(([vendor,usage])=>({vendor,capturedAt:usage.capturedAt,windows:usage.windows.map(({kind,label,percent,resetsAt})=>({kind,label,percent,resetsAt}))})).sort((a,b)=>a.vendor.localeCompare(b.vendor))}get(){return this.rows}setContext(map){this.sessions=map}context(session){return this.sessions?.get(session)??null}}var usageStore=new UsageStore;function contextMeter(usage,session){let ctx=usage.context(session);if(!ctx||ctx.contextTokens<=0)return null;let used=ctx.contextTokens,window2=ctx.contextWindowTokens??null,share=(n)=>Math.min(100,n/(window2??used)*100),rows=ctx.parts?.length?ctx.parts.map((part)=>({key:part.key,tokens:part.tokens,share:share(part.tokens)})):[{key:"used",tokens:used,share:share(used)}];if(window2)rows.push({key:"free",tokens:Math.max(0,window2-used)});return{percent:window2?share(used):null,used,window:window2,rows,approximate:ctx.approximate===!0}}function createContextOps(usage){return{"context.usage":{kind:"read",destructive:!1,wraps:"the bridge usage store's `usage.context` entry for taskId::tabId (the engine history reader's reading)",async run(args){let taskId2=optText(args,"taskId",64),tabId2=optText(args,"tabId",32);return{meter:taskId2&&tabId2?contextMeter(usage,`${taskId2}::${tabId2}`):null}}}}}var contextOps=createContextOps(usageStore);import{unlinkSync}from"fs";import{join as join2}from"path";var realDeps={installHooks:async()=>{let{ensureGlobalRoveHooks}=await import("./chunk-eznnpst5.js");await ensureGlobalRoveHooks({quiet:!0})},uninstallHooks:async()=>{let{activityHookAdapters}=await import("./chunk-pmz7t8xx.js");await Promise.all(activityHookAdapters().map(async(adapter)=>{try{await adapter.removeActivityHooks(adapter.globalSettingsPath())}catch{}}))},resetState:()=>{replaceStateFile({});try{unlinkSync(join2(roveStateDir(),"tasks.json"))}catch(err){if(err.code!=="ENOENT")throw new BridgeError("RESET_FAILED",`could not remove tasks.json: ${err.message}`)}}};function createDevOps(deps){return{"engines.hooks.install":{kind:"write",destructive:!0,wraps:"Settings \u2192 Engines install row: ensureGlobalRoveHooks into every engine's own config",async run(){return await deps.installHooks(),{}}},"engines.hooks.uninstall":{kind:"write",destructive:!0,wraps:"Settings \u2192 Engines uninstall row: removeActivityHooks for every hook adapter",async run(){return await deps.uninstallHooks(),{}}},"dev.reset":{kind:"write",destructive:!0,wraps:"Settings \u2192 Dev reset: replaceStateFile({}), remove tasks.json, then daemon.stop {reason: restart} so its in-memory tasks go too (worktrees and engine history stay)",async run(_args,{api}){return deps.resetState(),await api.rpc("daemon.stop",{reason:"restart"}).catch(()=>{return}),{}}},"daemon.restart":{kind:"write",destructive:!0,wraps:"Settings \u2192 Dev restart: daemon RPC daemon.stop {reason: restart} (PTY host and engine sessions keep running)",async run(_args,{api}){return await api.rpc("daemon.stop",{reason:"restart"}).catch(()=>{return}),{}}}}}var devOps=createDevOps(realDeps);var MAX_FILES=50000,MAX_NOTES=200,NOTE_MAX=4000,PATH_MAX=1024,MAX_LINE=1e7,CODE_MAX=8000,stateNoteStore={read(id){let notes=[];return updateStateFile((state)=>{let v=state[diffCommentsKey(id)];return notes=Array.isArray(v)?v:[],!1}),notes},update(id,mutate){updateStateFile((state)=>{let v=state[diffCommentsKey(id)];state[diffCommentsKey(id)]=mutate(Array.isArray(v)?v:[]);return})}},defaultDeps={listFiles:(worktree)=>listFiles(worktree),notes:stateNoteStore,now:Date.now,newId:()=>crypto.randomUUID()};async function worktreeOf(api,id){let path=(await api.verb("get-task",[flag("task-id",id)])).task.worktreePath;if(!path)throw new BridgeError("NO_WORKTREE",`task ${id} has no worktree yet`);return path}function relPath(args,name){let v=text2(args,name,PATH_MAX);if(v.startsWith("/")||v.includes("\x00")||v.split(/[\\/]/).includes(".."))throw new BridgeError("BAD_ARGS",`${name} must be relative to the worktree`);return v}function lineNo(args,name){let v=optInt(args,name,1,MAX_LINE);if(v===void 0)throw new BridgeError("BAD_ARGS",`${name} must be an integer in 1..${MAX_LINE}`);return v}var samePath2=(a,b)=>a.replace(/^\/private\//,"/")===b.replace(/^\/private\//,"/");function createFilesOps(deps=defaultDeps){let spec=(s)=>s,sending=new Set;return{"files.list":spec({kind:"read",destructive:!1,wraps:"listFiles(worktree) \u2014 tracked + untracked-not-ignored files",async run(args,{api}){let id=taskId(args),all=api.machineOf?.(id)?(await api.verb("worktree-files",[flag("task-id",id)])).files:await deps.listFiles(await worktreeOf(api,id)),truncated=all.length>MAX_FILES;return{files:truncated?all.slice(0,MAX_FILES):all,truncated}}}),"file.read":spec({kind:"read",destructive:!1,wraps:"rove api worktree-file \u2014 one markdown/HTML/SVG/image/PDF file of the task's worktree (real path confined to it, 5 MB cap), base64",async run(args,{api}){return api.verb("worktree-file",[flag("task-id",taskId(args)),flag("path",relPath(args,"path"))])}}),"review.list":spec({kind:"read",destructive:!1,wraps:"state.json diffComments.<taskId>",async run(args){let notes=deps.notes.read(taskId(args));return{notes,unsent:unsentComments(notes).length}}}),"review.add":spec({kind:"write",destructive:!1,wraps:"state.json diffComments.<taskId> (append)",async run(args){let id=taskId(args),line=lineNo(args,"line"),startLine=optInt(args,"startLine",1,MAX_LINE);if(startLine!==void 0&&startLine>line)throw new BridgeError("BAD_ARGS","startLine is after line");let code=optText(args,"code",CODE_MAX),note={id:deps.newId(),filePath:relPath(args,"filePath"),...startLine!==void 0&&startLine!==line?{startLine}:{},line,body:text2(args,"body",NOTE_MAX),...code?{code}:{},createdAt:deps.now()};return deps.notes.update(id,(cur)=>{if(cur.length>=MAX_NOTES)throw new BridgeError("TOO_MANY_NOTES",`a task keeps at most ${MAX_NOTES} notes`);return[...cur,note]}),{note}}}),"review.edit":spec({kind:"write",destructive:!1,wraps:"state.json diffComments.<taskId> (rewrite one note's text in place)",async run(args){let id=taskId(args),noteId=text2(args,"id",128),body=text2(args,"body",NOTE_MAX),note;if(deps.notes.update(id,(cur)=>cur.map((c)=>{if(c.id!==noteId)return c;return note={...c,body},note})),!note)throw new BridgeError("NOT_FOUND","no such note");return{note}}}),"review.remove":spec({kind:"write",destructive:!0,wraps:"state.json diffComments.<taskId> (drop one note)",async run(args){let id=taskId(args),noteId=text2(args,"id",128),removed=!1;return deps.notes.update(id,(cur)=>{let next=cur.filter((c)=>c.id!==noteId);return removed=next.length!==cur.length,next}),{removed}}}),"review.send":spec({kind:"write",destructive:!1,wraps:"rove api send --plain (all unsent notes as one prompt; sentAt only on confirmed delivery)",async run(args,{api}){let id=taskId(args),tab=args.tabId===void 0||args.tabId===null||args.tabId===""?void 0:tabId(args);if(sending.has(id))throw new BridgeError("SEND_IN_FLIGHT","this task's notes are already being sent");let unsent=unsentComments(deps.notes.read(id));if(unsent.length===0)return{sent:0,delivered:!0};sending.add(id);try{let worktree=await worktreeOf(api,id).catch(()=>{return}),prompt=formatDiffComments(unsent,worktree),res=await api.verb("send",[flag("task-id",id),"--plain",flag("prompt",prompt),...tab?[flag("tab",tab)]:[]]);if(res.delivered!==!0||res.targetState)return{sent:0,delivered:!1,reason:sendReason(res.targetDetail??res.reason)??(res.targetState?`engine is ${res.targetState}`:"not confirmed")};let batch=new Set(unsent.map((c)=>c.id)),sentAt=deps.now();return deps.notes.update(id,(cur)=>cur.map((c)=>batch.has(c.id)&&c.sentAt===void 0?{...c,sentAt}:c)),{sent:unsent.length,delivered:!0}}finally{sending.delete(id)}}}),"worktrees.list":spec({kind:"read",destructive:!1,wraps:"daemon RPC worktree.list {network} + task.list (taskId/taskKind joined by path)",async run(args,{api}){let network=args.network===void 0?!0:args.network===!0;if(args.network!==void 0&&typeof args.network!=="boolean")throw new BridgeError("BAD_ARGS","network must be a boolean");let[list,tasks]=await Promise.all([api.rpc("worktree.list",{network}),api.rpc("task.list")]);return{projects:list.projects.map((p)=>({repo:p.repo,worktrees:p.worktrees.map((w)=>{let t=tasks.tasks.find((x)=>x.worktreePath&&samePath2(x.worktreePath,w.path));return t?{...w,taskId:t.id,taskKind:t.kind??"task"}:w})}))}}}),"worktrees.remove":spec({kind:"write",destructive:!0,wraps:"daemon RPC worktree.remove {path, force}",async run(args,{api}){let path=absPath(args,"path"),force=bool2(args,"force");if(!(await api.rpc("worktree.list",{network:!1})).projects.some((p)=>p.worktrees.some((w)=>w.path===path)))throw new BridgeError("UNKNOWN_WORKTREE","that path is not a listed worktree");try{let res=await api.rpc("worktree.remove",{path,force});return{removed:res.removed,...res.residue?{residue:res.residue}:{}}}catch(err){if(err instanceof BridgeError&&err.message.startsWith("DIRTY_WORKTREE: "))throw new BridgeError("DIRTY_WORKTREE",err.message.slice(16));throw err}}})}}var filesOps=createFilesOps();var GATE_ID=/^g-\d{1,9}$/,OPTION_KEY=/^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$/,TEXT_MAX=4000,DAEMON_CODE=/^(GATE_NOT_FOUND|GATE_NOT_OPEN|BAD_OPTION): /;function gateId(args){let v=args.gateId;if(typeof v!=="string"||!GATE_ID.test(v))throw new BridgeError("BAD_ARGS","gateId is not a gate id");return v}async function answer(args,ctx){let id=gateId(args),option=args.option;if(option!==void 0&&option!==null&&(typeof option!=="string"||!OPTION_KEY.test(option)))throw new BridgeError("BAD_ARGS","option is not an option key");let text3=optText(args,"text",TEXT_MAX);if(!option&&!text3)throw new BridgeError("BAD_ARGS","answer needs an option or text");try{return{delivered:(await ctx.api.rpc("gate.answer",{gateId:id,...option?{option}:{},...text3?{text:text3}:{},by:"bridge"})).delivered===!0}}catch(err){let message=err instanceof Error?err.message:String(err),code=DAEMON_CODE.exec(message)?.[1];if(code)throw new BridgeError(code,message.replace(DAEMON_CODE,""));throw err}}var gateAnswer={kind:"write",destructive:!1,wraps:"rpc gate.answer (by: bridge)",run:answer},GATE_OPS={"gate.answer":gateAnswer};var spec=(kind,wraps,run,destructive=!1)=>({kind,destructive,wraps,run}),githubAuthOps={"github.status":spec("read","github-status (on `machine`, else this machine)",async(args,ctx)=>{let out=await attempt(ctx.api.verb("github-status",[],machineOf(args)));return out.ok?{status:out.result}:{status:null,reason:out.reason,message:out.message}}),"github.login":spec("write","github-login [--cancel] (on `machine`, else this machine)",(args,ctx)=>attempt(ctx.api.verb("github-login",optBool(args,"cancel")?[flag("cancel","true")]:[],machineOf(args)))),"github.logout":spec("write","github-logout (this machine's gh, signed out)",(_args,ctx)=>attempt(ctx.api.verb("github-logout",[])),!0),"github.sync":spec("write","github-sync --to `machine` (this machine's account signed in there)",async(args,ctx)=>{let machine=machineOf(args);if(!machine)throw new BridgeError("BAD_ARGS","machine must name a registered machine");return attempt(ctx.api.verb("github-sync",[flag("to",machine)]))})};var LIST_TIMEOUT_MS=15000;function parseRepos(stdout){let rows;try{rows=JSON.parse(stdout)}catch{return null}if(!Array.isArray(rows))return null;return rows.flatMap((row)=>typeof row?.nameWithOwner==="string"?[{nameWithOwner:row.nameWithOwner,description:typeof row.description==="string"?row.description:"",isPrivate:row.isPrivate===!0}]:[])}var githubOps={"github.repos":{kind:"read",destructive:!1,wraps:"gh repo list --limit 100 --json nameWithOwner,description,isPrivate (the machine's own gh login)",async run(){let res=await taskOpDeps.gh(["repo","list","--limit","100","--json","nameWithOwner,description,isPrivate"],LIST_TIMEOUT_MS);if(!res.ok)return{repos:[],reason:res.reason};let repos=parseRepos(res.stdout);return repos?{repos}:{repos:[],reason:"failed"}}}};var CURSOR=/^[A-Za-z0-9._~=-]{1,1024}$/;function given(args,name){let v=args[name];return v!==void 0&&v!==null&&v!==""}function optCursor(args){let raw=optText(args,"cursor",1024);if(raw===void 0)return;if(!CURSOR.test(raw))throw new BridgeError("BAD_ARGS","cursor is not a read-output cursor");return raw}var insightOps={"output.read":{kind:"read",destructive:!1,wraps:"rove api read-output (structured engine history, else a labeled terminal tail)",run(args,{api}){let argv=[flag("task-id",taskId(args))];if(given(args,"tab"))argv.push(flag("tab",tabId(args,"tab")));let source=optOneOf(args,"source",["auto","history","terminal"]);if(source)argv.push(flag("source",source));let cursor=optCursor(args);if(cursor)argv.push(flag("cursor",cursor));let limit=optInt(args,"limit",1,50);if(limit!==void 0)argv.push(flag("limit",limit));return api.verb("read-output",argv)}},"repo.digest":{kind:"read",destructive:!1,wraps:"rove api digest",run(args,{api}){let argv=[flag("repo",absPath(args,"repo"))],days=optInt(args,"sinceDays",1,365);if(days!==void 0)argv.push(flag("since-days",days));return api.verb("digest",argv)}},"turns.list":{kind:"read",destructive:!1,wraps:"rove api agent-turns",async run(args,{api}){let argv=[];if(given(args,"taskId"))argv.push(flag("task-id",taskId(args)));if(given(args,"repo"))argv.push(flag("repo",absPath(args,"repo")));let days=optInt(args,"sinceDays",1,365);if(days!==void 0)argv.push(flag("since-days",days));let limit=optInt(args,"limit",1,500);if(limit!==void 0)argv.push(flag("limit",limit));return{...await api.verb("agent-turns",argv),readers:vendorsWithTurnReader()}}},"sessions.search":{kind:"read",destructive:!1,wraps:"rove api search (user and assistant prose in every task's engine history)",run(args,{api}){let query=optText(args,"query",200)?.trim();if(!query)throw new BridgeError("BAD_ARGS","query is required");let argv=[flag("query",query)];if(given(args,"repo"))argv.push(flag("repo",absPath(args,"repo")));let limit=optInt(args,"limit",1,100);if(limit!==void 0)argv.push(flag("limit",limit));return api.verb("search",argv)}}};var CHORD_MAX=64,realDeps2={read(){return resetKeybindingsFileCache(),readKeybindingsFile()},create:createKeybindingsFile,fireAction(target){let[cmd,...rest]=[...roveCliInvocation(),"plugin","action","invoke",target];return spawnDetached(cmd,rest,{onError:(err)=>console.warn(`[rove/plugins] ${target}: ${String(err)}`)})},platform:process.platform},same=(a,b)=>JSON.stringify(a??null)===JSON.stringify(b??null);function copyKeymap(){return RoveKeymap.map((row)=>({id:row.id,scope:row.scope,keys:[...row.keys],...row.prefixKeys?{prefixKeys:[...row.prefixKeys]}:{},...row.hint?{hint:{...row.hint}}:{}}))}function createKeybindingsOps(deps=realDeps2){return{"keybindings.get":{kind:"read",destructive:!1,wraps:"helper resolveUserKeybindings (the TUI's keybindings.yaml parser) on a copy of the default keymap",async run(){let file=deps.read(),rows=copyKeymap(),{report,prefix}=resolveUserKeybindings(file,rows,deps.platform),changed=[];for(let row of rows){let base=RoveKeymap.find((candidate)=>candidate.id===row.id);if(base&&same(base.keys,row.keys)&&same(base.prefixKeys,row.prefixKeys)&&same(base.hint,row.hint))continue;changed.push({id:row.id,keys:row.keys,...row.prefixKeys?{prefixKeys:row.prefixKeys}:{},...row.hint?{hint:row.hint}:{}})}return{path:report.path,exists:report.exists,rows:changed,prefix:{key:prefix.key,firstStrokes:prefixFirstStrokes(prefix),timeoutMs:prefix.timeoutMs},plugins:report.plugins,applied:report.applied,warnings:report.warnings}}},"keybindings.createFile":{kind:"write",destructive:!1,wraps:"helper createKeybindingsFile (the fixed, fully commented starter; never overwrites)",async run(){let file=deps.read();if(file.exists)return{path:file.path,created:!1};return{path:file.path,created:deps.create(file.path)}}},"plugin.chordAction":{kind:"write",destructive:!1,wraps:"rove plugin action invoke <target> (detached), only for an `action:` bound to this chord in keybindings.yaml",async run(a){let chord=str(a,"chord");if(chord.length>CHORD_MAX)throw new BridgeError("BAD_ARGS","chord is too long");let file=deps.read(),{report}=resolveUserKeybindings(file,copyKeymap(),deps.platform),bound=report.plugins.find((p)=>p.chord===chord&&p.kind==="action");if(!bound)throw new BridgeError("NOT_BOUND",`${chord} is not bound to a plugin action`);if(!deps.fireAction(bound.target))throw new BridgeError("SESSION_FAILED",`could not start plugin action ${bound.target}`);return{target:bound.target}}}}}var keybindingsOps=createKeybindingsOps();var PATH_MAX2=1000,PANE_ID=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,launchDeps={panes(){return listPaneLaunches({socketPath:defaultDaemonSocketPath(),binPath:ROVE_PRODUCT_NAME}).map((p)=>({id:`${p.pluginId}.${p.paneId}`,title:p.title,placement:p.placement}))}};async function tabNew(api,id,kind,extra){let res=await api.verb("tab-new",[flag("task-id",id),flag("kind",kind),...extra]);if(!res.tabId)throw new BridgeError("SESSION_FAILED","the new tab did not report its id");return{tabId:res.tabId,...res.leaf?{leaf:res.leaf}:{}}}var launchOps={"file.openInEditor":{kind:"write",destructive:!1,wraps:"rove api tab-new --kind editor (the Mac's configured editor on a file inside the task's worktree)",async run(a,{api}){let rel=optStr(a,"path")??"";if(!rel||rel.length>PATH_MAX2||rel.startsWith("/")||rel.includes("\x00")||rel.split(/[\\/]/).includes(".."))throw new BridgeError("BAD_ARGS","path must be relative to the worktree");let{tabId:opened}=await tabNew(api,taskId(a),"editor",[flag("file",rel)]);return{tabId:opened}}},"plugin.panes":{kind:"read",destructive:!1,wraps:"helper listPaneLaunches (panes of enabled plugins)",async run(){return{panes:launchDeps.panes()}}},"plugin.paneOpen":{kind:"write",destructive:!1,wraps:"rove api tab-new --kind pane (a registered plugin pane; its argv comes from the manifest)",async run(a,{api}){let pane=str(a,"pane");if(!PANE_ID.test(pane))throw new BridgeError("BAD_ARGS","pane is not a plugin pane id");let extra=[flag("pane",pane)];if(a.tabId!==void 0&&a.tabId!==null)extra.push(flag("tab",tabId(a)));return tabNew(api,taskId(a),"pane",extra)}},"tab.openViewport":{kind:"write",destructive:!1,wraps:"rove api tab-new --kind viewport (a tab showing another task's first engine session)",async run(a,{api}){let{tabId:opened}=await tabNew(api,taskId(a),"viewport",[flag("view-task",taskId(a,"viewTaskId"))]);return{tabId:opened}}}};var PLUGIN_ID=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;function control(a){let plugin=text2(a,"plugin",128),pane=text2(a,"pane",64),key=text2(a,"key",64);if(!PLUGIN_ID.test(plugin)||!MOD_PANE_ID_PATTERN.test(pane)||!MOD_KEY_PATTERN.test(key))throw new BridgeError("BAD_ARGS","plugin, pane or key is not a mod id");return{plugin,pane,key}}function delivered(res){if(!res.ok)throw new BridgeError("MOD_UNAVAILABLE",`the mod did not get it (${res.reason??"unknown"})`);return{}}var modsOps={"mod.press":{kind:"write",destructive:!1,wraps:"daemon RPC mod.press (forwards a button key to the mod that drew it)",async run(a,{api}){return delivered(await api.rpc("mod.press",control(a)))}},"mod.submit":{kind:"write",destructive:!1,wraps:"daemon RPC mod.submit (forwards an input field's text to the mod that drew it)",async run(a,{api}){let value=a.value;if(typeof value!=="string")throw new BridgeError("BAD_ARGS","value must be text");if(value.length>MOD_INPUT_MAX)throw new BridgeError("BAD_ARGS",`value is longer than ${MOD_INPUT_MAX} characters`);return delivered(await api.rpc("mod.submit",{...control(a),value}))}}};var ISSUE_STATUSES=["open","doing","hold","done"],TITLE_MAX=300,BODY_MAX=20000,NAME_MAX=120,PROMPT_MAX=20000,EVENT_LIMIT=12;function issueId(args){let id=optInt(args,"id",1,1e9);if(id===void 0)throw new BridgeError("BAD_ARGS","id must be an issue number");return id}function cron(args,name){let v=text2(args,name,120).trim();if(!/^[0-9A-Za-z*/,\-?#LW]+(?: [0-9A-Za-z*/,\-?#LW]+){4}$/.test(v))throw new BridgeError("BAD_ARGS",`${name} must be five space-separated cron fields`);return v}function setIfPresent(argv,name,value){if(value!==void 0)argv.push(flag(name,value))}var pagesOps={"issue.repos":{kind:"read",destructive:!1,wraps:"daemon RPC issue.repos",run:(_args,{api})=>api.rpc("issue.repos",{})},"issue.list":{kind:"read",destructive:!1,wraps:"rove api issue-list",run:(args,{api})=>api.verb("issue-list",[flag("repo",absPath(args,"repo"))])},"issue.create":{kind:"write",destructive:!1,wraps:"rove api issue-create",run:(args,{api})=>{let argv=[flag("repo",absPath(args,"repo")),flag("title",text2(args,"title",TITLE_MAX).trim())];return setIfPresent(argv,"body",optText(args,"body",BODY_MAX)),api.verb("issue-create",argv)}},"issue.update":{kind:"write",destructive:!1,wraps:"rove api issue-update (title/body and/or task link; task=none unlinks; clearBody stores one space, the verb cannot send an empty body)",run:(args,{api})=>{let title=optText(args,"title",TITLE_MAX),typed=optText(args,"body",BODY_MAX);if(optBool(args,"clearBody")&&typed!==void 0)throw new BridgeError("BAD_ARGS","body and clearBody are exclusive");let body=optBool(args,"clearBody")?" ":typed,task=optStr(args,"task")===void 0?void 0:taskId(args,"task");if(title===void 0&&body===void 0&&task===void 0)throw new BridgeError("BAD_ARGS","issue.update needs title, body and/or task");let argv=[flag("repo",absPath(args,"repo")),flag("id",issueId(args))];return setIfPresent(argv,"title",title?.trim()),setIfPresent(argv,"body",body),setIfPresent(argv,"task",task),api.verb("issue-update",argv)}},"issue.setStatus":{kind:"write",destructive:!1,wraps:"rove api issue-update --status",run:(args,{api})=>api.verb("issue-update",[flag("repo",absPath(args,"repo")),flag("id",issueId(args)),flag("status",oneOf(args,"status",ISSUE_STATUSES))])},"issue.delete":{kind:"write",destructive:!0,wraps:"rove api issue-delete (the tracker record only; a linked task and worktree stay)",run:(args,{api})=>api.verb("issue-delete",[flag("repo",absPath(args,"repo")),flag("id",issueId(args))])},"issue.prompt":{kind:"read",destructive:!1,wraps:"rove api issue-list + the kanban drawer's issueWorktreePrompt/issueProjectPrompt helpers",async run(args,{api}){let where=oneOf(args,"where",["worktree","project"]),id=issueId(args),issue=(await api.verb("issue-list",[flag("repo",absPath(args,"repo"))])).issues.find((i)=>i.id===id);if(!issue)throw new BridgeError("ISSUE_NOT_FOUND",`no issue #${id}`);let cli=roveApiInvocation();return{title:issueChatTaskTitle(issue),prompt:where==="worktree"?issueWorktreePrompt(issue,cli):issueProjectPrompt(issue,cli)}}},"task.events":{kind:"read",destructive:!1,wraps:"daemon RPC task.recentEvents, newest first, as the drawer's EVENTS rows",async run(args,{api}){let id=taskId(args),limit=optInt(args,"limit",1,100)??EVENT_LIMIT;try{return{events:(await api.rpc("task.recentEvents",{taskId:id})).events.slice(-limit).reverse().map((event)=>({kind:event.kind,at:event.at,tail:[detailFragment(event),event.vendor??""].filter((part)=>part.length>0).join(" \xB7 ")}))}}catch(err){if(err instanceof Error&&/task not found/i.test(err.message))return{events:[]};throw err}}},"routine.list":{kind:"read",destructive:!1,wraps:"rove api routine-list",run:(_args,{api})=>api.verb("routine-list",[])},"routine.create":{kind:"write",destructive:!1,wraps:"rove api routine-create (name, optional repo \u2014 absent = no project, prompt, schedule, optional existing conversation targetTask+targetTab; never a precheck)",run:(args,{api})=>{let argv=[optStr(args,"repo")===void 0?"--no-repo":flag("repo",absPath(args,"repo")),flag("name",text2(args,"name",NAME_MAX).trim()),flag("prompt",text2(args,"prompt",PROMPT_MAX)),flag("schedule",cron(args,"schedule"))],hasTask=optStr(args,"targetTask")!==void 0,hasTab=optStr(args,"targetTab")!==void 0;if(hasTask!==hasTab)throw new BridgeError("BAD_ARGS","targetTask and targetTab go together");if(hasTask)argv.push(flag("target-task",taskId(args,"targetTask")),flag("target-tab",tabId(args,"targetTab")));return api.verb("routine-create",argv)}},"routine.update":{kind:"write",destructive:!1,wraps:"rove api routine-update (name, prompt, schedule; never a precheck)",run:(args,{api})=>{let name=optText(args,"name",NAME_MAX),prompt=optText(args,"prompt",PROMPT_MAX),schedule=optStr(args,"schedule")===void 0?void 0:cron(args,"schedule");if(name===void 0&&prompt===void 0&&schedule===void 0)throw new BridgeError("BAD_ARGS","routine.update needs name, prompt and/or schedule");let argv=[flag("id",taskId(args,"id"))];return setIfPresent(argv,"name",name?.trim()),setIfPresent(argv,"prompt",prompt),setIfPresent(argv,"schedule",schedule),api.verb("routine-update",argv)}},"routine.setEnabled":{kind:"write",destructive:!1,wraps:"rove api routine-update --enabled",run:(args,{api})=>api.verb("routine-update",[flag("id",taskId(args,"id")),flag("enabled",String(bool2(args,"enabled")))])},"routine.runNow":{kind:"write",destructive:!1,wraps:"rove api routine-run-now (skips the precheck; the schedule does not shift)",run:(args,{api})=>api.verb("routine-run-now",[flag("id",taskId(args,"id"))])},"routine.runs":{kind:"read",destructive:!1,wraps:"rove api routine-runs",run:(args,{api})=>api.verb("routine-runs",[flag("id",taskId(args,"id"))])},"routine.delete":{kind:"write",destructive:!0,wraps:"rove api routine-delete (the routine and its history; tasks it created stay)",run:(args,{api})=>api.verb("routine-delete",[flag("id",taskId(args,"id"))])},"attention.dismissRoutine":{kind:"write",destructive:!1,wraps:"daemon RPC attention.dismissRoutine (a routine episode is keyed on its schedule, not a task)",run:(args,{api})=>api.rpc("attention.dismissRoutine",{automationId:taskId(args,"automationId")})},"workitem.list":{kind:"read",destructive:!1,wraps:"daemon RPC workitem.list (same call as rove api workitem-list, plus refresh)",run:(args,{api})=>{let state=optOneOf(args,"state",["open","closed","all"]),assignee=optOneOf(args,"assignee",["@me"]),search=optText(args,"search",200),limit=optInt(args,"limit",1,50);return api.rpc("workitem.list",{repo:absPath(args,"repo"),...state?{state}:{},...assignee?{assignee}:{},...search?{search}:{},...limit!==void 0?{limit}:{},...optBool(args,"refresh")?{refresh:!0}:{}})}},"workitem.links":{kind:"read",destructive:!1,wraps:"daemon RPC task.list, folded to the tasks already started from a GitHub issue of this repo",async run(args,{api}){let repo=absPath(args,"repo"),{tasks}=await api.rpc("task.list",{});return{links:tasks.flatMap((task)=>task.linkedWorkItem?.number!==void 0&&samePath(task.repo,repo)?[{number:task.linkedWorkItem.number,taskId:task.id}]:[])}}},"workitem.start":{kind:"write",destructive:!1,wraps:"rove api workitem-start",run(args,{api}){let number=optInt(args,"number",1,1e9);if(number===void 0)throw new BridgeError("BAD_ARGS","number must be an issue number");let argv=[flag("repo",absPath(args,"repo")),flag("number",number)];return setIfPresent(argv,"vendor",optOneOf(args,"engine",ALL_VENDORS)),api.verb("workitem-start",argv)}}};var URL_MAX=2048,panelOps={"browser.probe":{kind:"read",destructive:!1,wraps:"frame probe (HTTPS HEAD to a public address; reads X-Frame-Options and CSP frame-ancestors)",async run(a){let{url,origin}=a;if(typeof url!=="string"||url.length===0||url.length>URL_MAX)throw new BridgeError("BAD_ARGS","url must be a URL string");if(origin!==void 0&&(typeof origin!=="string"||origin.length>URL_MAX))throw new BridgeError("BAD_ARGS","origin must be the page's origin string");return checkFrame(url,origin===void 0?{}:{origin})}}};var VIEW_TIMEOUT_MS=1e4,LOG_TIMEOUT_MS=30000,MAX_CHECKS=60,CHECKS_TTL_MS=30000,LOG_TTL_MS=60000,MAX_CACHED=24,LOG_LINES=40,LOG_CHARS=4000,RUN_ID=/^\d{1,15}$/,RANK={fail:0,pending:1,pass:2,skipped:3},realDeps3={gh:ghText,now:Date.now};function field(entry,key){let v=typeof entry==="object"&&entry!==null?entry[key]:void 0;return typeof v==="string"?v:""}function checkState(entry){let status=field(entry,"status").toUpperCase(),conclusion=field(entry,"conclusion").toUpperCase(),context=field(entry,"state").toUpperCase();if(status&&status!=="COMPLETED")return"pending";if(conclusion)return conclusion==="SUCCESS"?"pass":["NEUTRAL","SKIPPED","CANCELLED"].includes(conclusion)?"skipped":"fail";if(context==="SUCCESS")return"pass";if(context==="FAILURE"||context==="ERROR")return"fail";return"pending"}function durationOf(entry){let start=Date.parse(field(entry,"startedAt")),end=Date.parse(field(entry,"completedAt"));return Number.isFinite(start)&&Number.isFinite(end)&&end>=start?end-start:null}function checkRows(rollup){return rollup.map((entry,i)=>{let url=field(entry,"detailsUrl")||field(entry,"targetUrl");return{i,name:field(entry,"name")||field(entry,"context")||"check",state:checkState(entry),durationMs:durationOf(entry),url,runId:runIdFromDetailsUrl(url)}}).sort((a,b)=>RANK[a.state]-RANK[b.state]||a.i-b.i).map(({i:_,...row})=>row)}function cache(ttl){let map=new Map;return{get(key,now){let hit=map.get(key);return hit&&now-hit.at<ttl?hit.value:void 0},set(key,value,now){map.delete(key),map.set(key,{at:now,value});for(let old of map.keys()){if(map.size<=MAX_CACHED)break;map.delete(old)}}}}async function worktreeOf2(ctx,id){let res=await ctx.api.verb("get-task",[flag("task-id",id)]),{worktreePath,prStatus}=res.task;if(!worktreePath)throw new BridgeError("NO_WORKTREE",`task ${id} has no worktree yet`);return{worktree:worktreePath,pr:prStatus?.number}}function prChecksOps(deps=realDeps3){let checks=cache(CHECKS_TTL_MS),logs=cache(LOG_TTL_MS);return{"pr.checks":{kind:"read",destructive:!1,wraps:"gh pr view <n> --json statusCheckRollup,mergeable,mergeStateStatus,reviewDecision,isDraft (cached 30s)",async run(a,ctx){let id=taskId(a),{worktree,pr}=await worktreeOf2(ctx,id);if(pr===void 0)return{outcome:"none"};let key=`${id}:${pr}`,cached=a.fresh===!0?void 0:checks.get(key,deps.now());if(cached)return cached;let read=await deps.gh(["pr","view",String(pr),"--json","statusCheckRollup,mergeable,mergeStateStatus,reviewDecision,isDraft"],worktree,VIEW_TIMEOUT_MS);if(!read.ok)return{outcome:"unavailable",detail:read.detail};let view;try{view=JSON.parse(read.stdout)}catch{return{outcome:"unavailable",detail:"gh returned unreadable JSON"}}let rows=checkRows(Array.isArray(view.statusCheckRollup)?view.statusCheckRollup:[]),result={outcome:"ok",total:rows.length,checks:rows.slice(0,MAX_CHECKS),mergeable:typeof view.mergeable==="string"?view.mergeable:"",mergeState:typeof view.mergeStateStatus==="string"?view.mergeStateStatus:"",review:typeof view.reviewDecision==="string"?view.reviewDecision:"",draft:view.isDraft===!0};return checks.set(key,result,deps.now()),result}},"pr.checkLog":{kind:"read",destructive:!1,wraps:"gh run view <runId> --log-failed (last 40 lines of one job; cached 60s)",async run(a,ctx){let id=taskId(a),run=optText(a,"runId",20)??"";if(!RUN_ID.test(run))throw new BridgeError("BAD_ARGS","runId must be a run number");let job=optText(a,"job",200)??"";if(!job)throw new BridgeError("BAD_ARGS","job is required");let{worktree}=await worktreeOf2(ctx,id),byJob=logs.get(`${worktree}:${run}`,deps.now());if(!byJob){let read=await deps.gh(["run","view",run,"--log-failed"],worktree,LOG_TIMEOUT_MS);if(!read.ok)return{outcome:"unavailable",detail:read.detail};byJob=parseFailedRunLog(read.stdout,LOG_LINES),logs.set(`${worktree}:${run}`,byJob,deps.now())}let tail=(byJob.get(job)??[]).join(`
103
103
  `);return tail?{outcome:"ok",tail:tail.slice(-LOG_CHARS)}:{outcome:"none"}}}}}var PR_CHECKS_OPS=prChecksOps();var SLOTS={text:null,background:null,textMuted:"text",backgroundPanel:"background",backgroundElement:"background",backgroundMenu:"backgroundElement",border:"text",borderActive:"border",borderSubtle:"border",primary:"text",secondary:"text",accent:"primary",error:"text",warning:"text",success:"text",info:"text",diffAdded:"success",diffRemoved:"error",diffLineNumber:"textMuted",syntaxType:"info",diffAddedBg:"background",diffRemovedBg:"background"},hex2=(n)=>n.toString(16).padStart(2,"0"),rgbHex=(c)=>`#${c.toInts().slice(0,3).map(hex2).join("")}`;function palette(theme,mode){let out={},slot=(name)=>{let known=out[name];if(known)return known;let fallback=SLOTS[name],value=resolveThemeSlotHex(theme,name,mode)??(fallback?slot(fallback):name==="background"?"#000000":"#ffffff");return out[name]=value,value};for(let name of Object.keys(SLOTS))slot(name);let cb=diffInks(resolveTheme(theme,mode),!0);return out.diffAddedColorblind=rgbHex(cb.added),out.diffAddedBgColorblind=rgbHex(cb.addedBg),out}function taskColors(theme,mode,ids){let resolved=resolveTheme(theme,mode);return Object.fromEntries(ids.map((id)=>[id,rgbHex(taskColor(id,resolved))]))}var realDeps4={load:loadStateFile,update:(compute)=>{updateStateFile((state)=>{for(let[key,value]of Object.entries(compute(state)))if(value===void 0)delete state[key];else state[key]=value;return})},themes:()=>{let user=loadUserThemes(),names=new Set(user.map((u)=>u.name));return[...Object.entries(BUNDLED_THEME_JSONS).filter(([name])=>!names.has(name)).map(([name,theme])=>({name,bundled:!0,theme})),...user.map((u)=>({name:u.name,bundled:!1,theme:u.theme}))]}},MAX_TASK_IDS=500,MODES=["dark","light"];function readAll(deps,state){let themes=deps.themes(),names=themes.map((t)=>t.name),prefs={},options={};for(let[name,def]of Object.entries(PREF_DEFS))if(prefs[name]=def.read(state),def.kind==="enum")options[name]=def.choices(names);else if(def.kind==="int")options[name]={min:def.min,max:def.max};return{prefs,options,info:prefInfo(state),themes}}function createPrefsOps(deps){return{"prefs.get":{kind:"read",destructive:!1,wraps:"state.json Settings keys read through the TUI normalizers, plus resolved theme palettes and glyph sets",async run(){let{prefs,options,info,themes}=readAll(deps,deps.load());return{prefs,options,info,glyphSets:GLYPH_SETS,themes:themes.map((t)=>({name:t.name,bundled:t.bundled,dark:palette(t.theme,"dark"),light:palette(t.theme,"light")}))}}},"prefs.set":{kind:"write",destructive:!1,wraps:"state.json: one allowlisted Settings key per call, value checked against the TUI's own choices",async run(args){let name=args.key;if(typeof name!=="string"||!Object.hasOwn(PREF_DEFS,name))throw new BridgeError("BAD_ARGS",`key must be one of ${Object.keys(PREF_DEFS).join("|")}`);let def=PREF_DEFS[name],names=deps.themes().map((t)=>t.name),value=checkPrefValue(name,def,args.value,names);deps.update((fresh)=>def.write(value,fresh));let{prefs}=readAll(deps,deps.load());return{key:name,value:prefs[name],prefs}}},"theme.taskColors":{kind:"read",destructive:!1,wraps:"the TUI's taskColor(taskId, theme) for each id under one theme and mode",async run(args){let{themes}=readAll(deps,deps.load()),theme=themes.find((t)=>t.name===args.theme);if(!theme)throw new BridgeError("BAD_ARGS","theme is not an installed theme");let mode=MODES.find((m)=>m===args.mode);if(!mode)throw new BridgeError("BAD_ARGS","mode must be dark|light");let ids=args.taskIds;if(!Array.isArray(ids)||ids.length>MAX_TASK_IDS||!ids.every((id)=>typeof id==="string"&&id.length<=64))throw new BridgeError("BAD_ARGS",`taskIds must be at most ${MAX_TASK_IDS} task ids`);return{colors:taskColors(theme.theme,mode,ids)}}}}}var prefsOps=createPrefsOps(realDeps4);var PROMPT_ID=/^[A-Za-z0-9-]{1,64}$/,ANSWER_MAX=4000,promptOps={"ui.promptReply":{kind:"write",destructive:!1,wraps:"daemon RPC ui.promptReply (answers or cancels a plugin's input dialog; first answer wins)",async run(a,{api}){let promptId=a.promptId;if(typeof promptId!=="string"||!PROMPT_ID.test(promptId))throw new BridgeError("BAD_ARGS","promptId is not a prompt id");let value=a.value;if(value!==void 0&&(typeof value!=="string"||value.length>ANSWER_MAX))throw new BridgeError("BAD_ARGS",`value must be text of at most ${ANSWER_MAX} characters`);if(!(await api.rpc("ui.promptReply",{promptId,...value!==void 0?{value}:{}})).ok)throw new BridgeError("PROMPT_GONE","this question was already answered or timed out");return{}}}};var GH_TIMEOUT_MS=20000,TTL_MS=60000,LIMIT=50,SEARCH="is:pr is:open review-requested:@me archived:false sort:updated-desc",QUERY=`query($q: String!, $n: Int!) {
104
104
  search(query: $q, type: ISSUE, first: $n) {
105
105
  nodes {
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{isEngineActivityKind}from"./chunk-17e2tgyg.js";import{loadPluginRegistry,readPluginManifest}from"./chunk-n0rdn2fn.js";import{connectIfRunning}from"./chunk-cb80ft39.js";import{activityHookAdapters}from"./chunk-4gjvmfa9.js";import{getPersistedString,setPersistedString}from"./chunk-rfp0ayra.js";import{flagValue}from"./chunk-zsfyj36g.js";import{readRoveEnv}from"./chunk-nc46gddg.js";import{join,resolve}from"path";var STDIN_READ_TIMEOUT_MS=500;async function readTextWithTimeout(read,timeoutMs=STDIN_READ_TIMEOUT_MS){let raceTimer;try{return await Promise.race([read(),new Promise((resolve2)=>{raceTimer=setTimeout(()=>resolve2(""),timeoutMs)})])}finally{if(raceTimer!==void 0)clearTimeout(raceTimer)}}async function readStdinText(isComplete){let bun=globalThis.Bun;if(bun)return bun.stdin.text();if(process.stdin.isTTY)return"";let chunks=[];try{for await(let chunk of process.stdin)if(chunks.push(chunk),isComplete?.(Buffer.concat(chunks).toString("utf8")))break}finally{process.stdin.destroy()}return Buffer.concat(chunks).toString("utf8")}function isCompleteJson(text){try{return JSON.parse(text),!0}catch{return!1}}async function readStdinPayload(){try{let text=await readTextWithTimeout(()=>readStdinText(isCompleteJson));if(!text.trim())return{};let parsed=JSON.parse(text);return parsed&&typeof parsed==="object"&&!Array.isArray(parsed)?parsed:{}}catch{return{}}}async function runHookSubcommand(argv){let[verb,...rest]=argv;if(verb==="setup"){await runHookSetup(rest);return}if(verb==="cleanup"){await runHookCleanup();return}try{if(!verb||!isEngineActivityKind(verb))return;let payload=await readStdinPayload(),payloadFlag=flagValue(rest,"--payload");if(payloadFlag)try{let extra=JSON.parse(payloadFlag);if(extra&&typeof extra==="object"&&!Array.isArray(extra))Object.assign(payload,extra)}catch{}let taskId=flagValue(rest,"--task-id"),envTaskId=process.env.ROVE_TASK_ID,envTabId=process.env.ROVE_TAB_ID,engine=flagValue(rest,"--engine"),adapters=activityHookAdapters().filter((a)=>!engine||a.vendor===engine);if(!taskId&&adapters.some((a)=>a.isUnattendedSession?.(process.env)===!0))return;let cwd=typeof payload.cwd==="string"&&payload.cwd?payload.cwd:void 0;for(let adapter of adapters){if(cwd)break;cwd=adapter.cwdFromPayload?.(payload)}cwd||=process.cwd();let detail;for(let adapter of adapters)if(detail=adapter.activityDetailFromPayload(verb,payload),detail)break;let session;for(let adapter of adapters)if(session=adapter.sessionFromPayload(payload),session)break;let client=await connectIfRunning();if(!client)return;try{let effectiveTaskId=taskId??envTaskId;await client.request("engine.reportEvent",{...effectiveTaskId?{taskId:effectiveTaskId}:{cwd},kind:verb,...engine?{engine}:{},...envTabId?{tabId:envTabId}:{},...detail?{detail}:{},...session?{sessionId:session.sessionId}:{},...session?.transcriptPath?{transcriptPath:session.transcriptPath}:{}})}finally{client.close()}}catch(err){if(readRoveEnv("HOOK_DEBUG"))console.error(`[rove hook] ${verb} failed:`,err instanceof Error?err.message:String(err))}}var SYNC_SETTING_KEY="externalWorktreeSync";function worktreeSyncAdapters(){return activityHookAdapters().filter((a)=>a.supportsWorktreeSync())}function globalSettingsPath(){return worktreeSyncAdapters()[0]?.globalSettingsPath()}function persistedSyncPath(stored){if(!stored||stored==="off")return;if(stored==="global")return globalSettingsPath();if(stored.startsWith("repo:"))return join(resolve(stored.slice(5)),".claude","settings.json");return stored}async function ensureGlobalRoveHooks(opts={}){try{let toolEvents=pluginsWantToolEvents();for(let a of activityHookAdapters()){let external=await a.externallyManagedHooks?.();if(external){if(external.notice)process.stderr.write(`
2
+ import{isEngineActivityKind}from"./chunk-17e2tgyg.js";import{loadPluginRegistry,readPluginManifest}from"./chunk-n0rdn2fn.js";import{connectIfRunning}from"./chunk-cb80ft39.js";import{activityHookAdapters}from"./chunk-hgtf6yvg.js";import{getPersistedString,setPersistedString}from"./chunk-gygdyf0s.js";import{flagValue}from"./chunk-zsfyj36g.js";import{readRoveEnv}from"./chunk-nc46gddg.js";import{join,resolve}from"path";var STDIN_READ_TIMEOUT_MS=500;async function readTextWithTimeout(read,timeoutMs=STDIN_READ_TIMEOUT_MS){let raceTimer;try{return await Promise.race([read(),new Promise((resolve2)=>{raceTimer=setTimeout(()=>resolve2(""),timeoutMs)})])}finally{if(raceTimer!==void 0)clearTimeout(raceTimer)}}async function readStdinText(isComplete){let bun=globalThis.Bun;if(bun)return bun.stdin.text();if(process.stdin.isTTY)return"";let chunks=[];try{for await(let chunk of process.stdin)if(chunks.push(chunk),isComplete?.(Buffer.concat(chunks).toString("utf8")))break}finally{process.stdin.destroy()}return Buffer.concat(chunks).toString("utf8")}function isCompleteJson(text){try{return JSON.parse(text),!0}catch{return!1}}async function readStdinPayload(){try{let text=await readTextWithTimeout(()=>readStdinText(isCompleteJson));if(!text.trim())return{};let parsed=JSON.parse(text);return parsed&&typeof parsed==="object"&&!Array.isArray(parsed)?parsed:{}}catch{return{}}}async function runHookSubcommand(argv){let[verb,...rest]=argv;if(verb==="setup"){await runHookSetup(rest);return}if(verb==="cleanup"){await runHookCleanup();return}try{if(!verb||!isEngineActivityKind(verb))return;let payload=await readStdinPayload(),payloadFlag=flagValue(rest,"--payload");if(payloadFlag)try{let extra=JSON.parse(payloadFlag);if(extra&&typeof extra==="object"&&!Array.isArray(extra))Object.assign(payload,extra)}catch{}let taskId=flagValue(rest,"--task-id"),envTaskId=process.env.ROVE_TASK_ID,envTabId=process.env.ROVE_TAB_ID,engine=flagValue(rest,"--engine"),adapters=activityHookAdapters().filter((a)=>!engine||a.vendor===engine);if(!taskId&&adapters.some((a)=>a.isUnattendedSession?.(process.env)===!0))return;let cwd=typeof payload.cwd==="string"&&payload.cwd?payload.cwd:void 0;for(let adapter of adapters){if(cwd)break;cwd=adapter.cwdFromPayload?.(payload)}cwd||=process.cwd();let detail;for(let adapter of adapters)if(detail=adapter.activityDetailFromPayload(verb,payload),detail)break;let session;for(let adapter of adapters)if(session=adapter.sessionFromPayload(payload),session)break;let client=await connectIfRunning();if(!client)return;try{let effectiveTaskId=taskId??envTaskId;await client.request("engine.reportEvent",{...effectiveTaskId?{taskId:effectiveTaskId}:{cwd},kind:verb,...engine?{engine}:{},...envTabId?{tabId:envTabId}:{},...detail?{detail}:{},...session?{sessionId:session.sessionId}:{},...session?.transcriptPath?{transcriptPath:session.transcriptPath}:{}})}finally{client.close()}}catch(err){if(readRoveEnv("HOOK_DEBUG"))console.error(`[rove hook] ${verb} failed:`,err instanceof Error?err.message:String(err))}}var SYNC_SETTING_KEY="externalWorktreeSync";function worktreeSyncAdapters(){return activityHookAdapters().filter((a)=>a.supportsWorktreeSync())}function globalSettingsPath(){return worktreeSyncAdapters()[0]?.globalSettingsPath()}function persistedSyncPath(stored){if(!stored||stored==="off")return;if(stored==="global")return globalSettingsPath();if(stored.startsWith("repo:"))return join(resolve(stored.slice(5)),".claude","settings.json");return stored}async function ensureGlobalRoveHooks(opts={}){try{let toolEvents=pluginsWantToolEvents();for(let a of activityHookAdapters()){let external=await a.externallyManagedHooks?.();if(external){if(external.notice)process.stderr.write(`
3
3
  ${external.notice}
4
4
  `);continue}let enginePath=a.globalSettingsPath();if(!enginePath)continue;await a.installActivityHooks(enginePath,{toolEvents,quiet:opts.quiet}),await a.removeWorktreeWatchHook(enginePath)}await cleanupWorktreeSyncHook()}catch{}}function pluginsWantToolEvents(){try{for(let entry of loadPluginRegistry().plugins){if(!entry.enabled)continue;try{if(readPluginManifest(entry.root).manifest.events.some((e)=>e.on.startsWith("tool.")))return!0}catch{}}}catch{}return!1}async function cleanupWorktreeSyncHook(){let adapters=worktreeSyncAdapters();if(adapters.length===0)return;let stored=getPersistedString(SYNC_SETTING_KEY),paths=new Set;for(let adapter of adapters){let file=adapter.globalSettingsPath();if(file)paths.add(file)}let prev=persistedSyncPath(stored);if(prev)paths.add(prev);for(let a of adapters)for(let p of paths)await a.removeWorktreeSyncHook(p);if(stored!=="off")setPersistedString(SYNC_SETTING_KEY,"off")}async function runHookCleanup(){let claude=activityHookAdapters().find((a)=>a.vendor==="claude"),path=claude?.globalSettingsPath();if(!claude||!path){process.stdout.write(`rove hook cleanup: no Claude hook adapter \u2014 nothing to do.
5
5
  `);return}await claude.removeActivityHooks(path),await claude.removeWorktreeWatchHook(path),process.stdout.write([`rove hook cleanup: removed Rove's settings-managed hooks from ${path}.`,"Only Rove's own entries were touched; your other hooks are intact.","The Claude Code plugin's hooks.json now carries these events (if the plugin","is not installed, the next Rove launch reinstalls the settings-managed set).",""].join(`