@sma1lboy/rove 0.9.154 → 0.9.156

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 (145) hide show
  1. package/dist/cli/chunk-0fhab4tq.js +2 -0
  2. package/dist/cli/{chunk-79gqh5p2.js → chunk-0wnfq5sx.js} +1 -1
  3. package/dist/cli/{chunk-pxtx1gcf.js → chunk-1aqmmea7.js} +1 -1
  4. package/dist/cli/{chunk-9zb2wkfr.js → chunk-25hxhtdr.js} +1 -1
  5. package/dist/cli/{chunk-aedrswty.js → chunk-2ernbaey.js} +3 -3
  6. package/dist/cli/{chunk-73qrq7bg.js → chunk-32h9htyh.js} +1 -1
  7. package/dist/cli/{chunk-d393z1mj.js → chunk-38272eqv.js} +1 -1
  8. package/dist/cli/chunk-39x1ztey.js +4 -0
  9. package/dist/cli/{chunk-s8eh3cf1.js → chunk-3wj69b0a.js} +1 -1
  10. package/dist/cli/{chunk-94z64m9x.js → chunk-3xcz7mz7.js} +2 -2
  11. package/dist/cli/{chunk-5wzap7r2.js → chunk-41ahvk51.js} +1 -1
  12. package/dist/cli/{chunk-5bn91n19.js → chunk-4502n1bk.js} +1 -1
  13. package/dist/cli/{chunk-8kvyjb4p.js → chunk-45p9xh44.js} +1 -1
  14. package/dist/cli/{chunk-183ptzzh.js → chunk-4a37bmpm.js} +1 -1
  15. package/dist/cli/{chunk-7z9cqycv.js → chunk-4gjr08g0.js} +1 -1
  16. package/dist/cli/chunk-4pmd0mxp.js +4 -0
  17. package/dist/cli/{chunk-ke95ebrz.js → chunk-5f80ggc3.js} +1 -1
  18. package/dist/cli/{chunk-rsqx358z.js → chunk-5v893waj.js} +1 -1
  19. package/dist/cli/{chunk-8gsqypg8.js → chunk-6123622n.js} +2 -2
  20. package/dist/cli/{chunk-4exg1101.js → chunk-667hcm3g.js} +2 -2
  21. package/dist/cli/{chunk-43n38xv5.js → chunk-6bbj9axg.js} +2 -2
  22. package/dist/cli/{chunk-5snrwe65.js → chunk-6pt23vas.js} +1 -1
  23. package/dist/cli/{chunk-3ztek08w.js → chunk-7j5372wb.js} +1 -1
  24. package/dist/cli/chunk-7ntf5hdf.js +15 -0
  25. package/dist/cli/chunk-7x88845e.js +2 -0
  26. package/dist/cli/{chunk-h3hw5vpc.js → chunk-88vvd6qz.js} +1 -1
  27. package/dist/cli/chunk-8kaqpb7t.js +2 -0
  28. package/dist/cli/chunk-8kj2s16b.js +7 -0
  29. package/dist/cli/{chunk-mb5m7ex7.js → chunk-91f68r6e.js} +1 -1
  30. package/dist/cli/{chunk-55xkvzvw.js → chunk-98zhyhpz.js} +1 -1
  31. package/dist/cli/{chunk-j5bmtpkc.js → chunk-9g7hamhv.js} +1 -1
  32. package/dist/cli/{chunk-y9ksfpbp.js → chunk-9xt05etk.js} +1 -1
  33. package/dist/cli/{chunk-8qb8kksk.js → chunk-9ypg30c1.js} +1 -1
  34. package/dist/cli/{chunk-gc25wht3.js → chunk-aak5ttgt.js} +1 -1
  35. package/dist/cli/{chunk-nywh3yb9.js → chunk-axfn4f28.js} +1 -1
  36. package/dist/cli/{chunk-8r1pnch1.js → chunk-bwyskwer.js} +1 -1
  37. package/dist/cli/{chunk-51y7sjhe.js → chunk-c43g3qcb.js} +1 -1
  38. package/dist/cli/chunk-caqpt09m.js +3 -0
  39. package/dist/cli/{chunk-07k2njwk.js → chunk-ch9b1d5y.js} +1 -1
  40. package/dist/cli/{chunk-mf7xghwj.js → chunk-cqaxnve9.js} +1 -1
  41. package/dist/cli/chunk-d2p1za6y.js +2 -0
  42. package/dist/cli/{chunk-rrzepm47.js → chunk-d57awd05.js} +2 -2
  43. package/dist/cli/{chunk-2z90jxcn.js → chunk-de751t37.js} +1 -1
  44. package/dist/cli/chunk-dmdpsw2y.js +2 -0
  45. package/dist/cli/{chunk-37gnmm2m.js → chunk-ds9qf1w1.js} +1 -1
  46. package/dist/cli/{chunk-703edkrq.js → chunk-dwbtszh0.js} +1 -1
  47. package/dist/cli/chunk-dzd1wy5a.js +2 -0
  48. package/dist/cli/{chunk-svpn3av1.js → chunk-e17gszac.js} +1 -1
  49. package/dist/cli/{chunk-es2agvre.js → chunk-e9cpb5jt.js} +15 -14
  50. package/dist/cli/{chunk-8ad0ba2n.js → chunk-esk240e5.js} +2 -2
  51. package/dist/cli/{chunk-yshnare4.js → chunk-exggdhpt.js} +1 -1
  52. package/dist/cli/chunk-fd2zhddn.js +3 -0
  53. package/dist/cli/{chunk-tt0fde40.js → chunk-fm5s7njg.js} +1 -1
  54. package/dist/cli/{chunk-cb2fpajx.js → chunk-g56kvet6.js} +1 -1
  55. package/dist/cli/{chunk-z83wxkg6.js → chunk-g90z5s39.js} +2 -2
  56. package/dist/cli/{chunk-9gz7jmgq.js → chunk-gkfd073t.js} +1 -1
  57. package/dist/cli/chunk-hj08heah.js +10 -0
  58. package/dist/cli/{chunk-rgnnq8wk.js → chunk-j20cerws.js} +1 -1
  59. package/dist/cli/{chunk-grh6dvfv.js → chunk-k2ckx8zw.js} +1 -1
  60. package/dist/cli/{chunk-c6mthex1.js → chunk-ksbvcxc3.js} +1 -1
  61. package/dist/cli/{chunk-deejtpcr.js → chunk-kt1ppyje.js} +1 -1
  62. package/dist/cli/{chunk-fg38d91k.js → chunk-m45w6v9d.js} +4 -4
  63. package/dist/cli/{chunk-vpzvcxc1.js → chunk-max057d8.js} +1 -1
  64. package/dist/cli/{chunk-1a7ctg07.js → chunk-mbvk5758.js} +1 -1
  65. package/dist/cli/chunk-mcdv19rs.js +3 -0
  66. package/dist/cli/{chunk-xhn25xaa.js → chunk-me2752c0.js} +1 -1
  67. package/dist/cli/chunk-mhs6yywx.js +2 -0
  68. package/dist/cli/{chunk-ffgb1a1n.js → chunk-mhzv94cg.js} +1 -1
  69. package/dist/cli/{chunk-z4c6bmw0.js → chunk-mkkp4c5t.js} +2 -2
  70. package/dist/cli/{chunk-kwe61yx7.js → chunk-mnqxgvyb.js} +1 -1
  71. package/dist/cli/{chunk-d809qqsk.js → chunk-mp8v5gn8.js} +1 -1
  72. package/dist/cli/chunk-mqnr4p48.js +2 -0
  73. package/dist/cli/{chunk-4wwx51m5.js → chunk-mqqnk8w7.js} +1 -1
  74. package/dist/cli/{chunk-4tzgma89.js → chunk-msr1xtay.js} +1 -1
  75. package/dist/cli/{chunk-86bjqmg1.js → chunk-n4nntq73.js} +1 -1
  76. package/dist/cli/{chunk-g5nz190n.js → chunk-n7n12868.js} +1 -1
  77. package/dist/cli/{chunk-btadstee.js → chunk-n80h9k0r.js} +1 -1
  78. package/dist/cli/chunk-ngnrz33z.js +3 -0
  79. package/dist/cli/{chunk-pdh5w4ht.js → chunk-nm0pq5r6.js} +1 -1
  80. package/dist/cli/{chunk-p1d3ag8b.js → chunk-nss70xwr.js} +1 -1
  81. package/dist/cli/{chunk-v9p6gxm0.js → chunk-ntt7gy5a.js} +1 -1
  82. package/dist/cli/chunk-nx7ahbsg.js +2 -0
  83. package/dist/cli/{chunk-yk2ha5yj.js → chunk-nyv7a76k.js} +1 -1
  84. package/dist/cli/{chunk-ef11h2am.js → chunk-p7s4xwgx.js} +1 -1
  85. package/dist/cli/{chunk-rkt1qjec.js → chunk-ptjc5mtc.js} +1 -1
  86. package/dist/cli/{chunk-4y2vsnhs.js → chunk-qch6g9za.js} +2 -2
  87. package/dist/cli/chunk-r05r01nv.js +3 -0
  88. package/dist/cli/{chunk-dp3rdb1p.js → chunk-r0z1bhjg.js} +1 -1
  89. package/dist/cli/{chunk-3bfm4hrs.js → chunk-r3k9rbwm.js} +1 -1
  90. package/dist/cli/chunk-r639wna1.js +2 -0
  91. package/dist/cli/chunk-rc668r26.js +2 -0
  92. package/dist/cli/{chunk-ea1r26pa.js → chunk-sfv15era.js} +1 -1
  93. package/dist/cli/chunk-sram9jmt.js +2 -0
  94. package/dist/cli/{chunk-92vsj4mv.js → chunk-svg7ee0z.js} +1 -1
  95. package/dist/cli/{chunk-z1e1bsv5.js → chunk-t27t2x9b.js} +1 -1
  96. package/dist/cli/{chunk-c1xp9qx6.js → chunk-t3z4etp5.js} +1 -1
  97. package/dist/cli/{chunk-mmd7zehs.js → chunk-t7xhb2jx.js} +1 -1
  98. package/dist/cli/chunk-t90vnrpk.js +2 -0
  99. package/dist/cli/{chunk-a4h476hv.js → chunk-vj2vdx3w.js} +1 -1
  100. package/dist/cli/chunk-wbt845s6.js +4 -0
  101. package/dist/cli/{chunk-e8493db0.js → chunk-wdhcrcre.js} +1 -1
  102. package/dist/cli/{chunk-k1tm3bys.js → chunk-we0gedwp.js} +1 -1
  103. package/dist/cli/{chunk-g6ww85sh.js → chunk-ybcacmqv.js} +1 -1
  104. package/dist/cli/{chunk-h5jhdjv7.js → chunk-yfy6031g.js} +1 -1
  105. package/dist/cli/{chunk-ewdhz3dv.js → chunk-yhwb91e4.js} +1 -1
  106. package/dist/cli/chunk-yqvrr5kt.js +2 -0
  107. package/dist/cli/{chunk-r8mk1aw4.js → chunk-ywtsabyg.js} +1 -1
  108. package/dist/cli/{chunk-5c3d1y0r.js → chunk-zd3wmj4d.js} +1 -1
  109. package/dist/cli/{chunk-xtr7ks02.js → chunk-zftxrnwh.js} +1 -1
  110. package/dist/cli/{chunk-b9h2ywc7.js → chunk-zqfbyq0a.js} +1 -1
  111. package/dist/cli/chunk-zwaf2mzz.js +2 -0
  112. package/dist/cli/index.js +7 -7
  113. package/dist/cli/kobe-run.js +1 -1
  114. package/dist/cli/kobe.js +6 -6
  115. package/dist/cli/pty-host-node.mjs +7 -6
  116. package/dist/cli/rove-run.js +1 -1
  117. package/dist/cli/rove.js +6 -6
  118. package/dist/skills/rove/references/api-flags.md +9 -5
  119. package/package.json +1 -1
  120. package/dist/cli/chunk-4c220qpj.js +0 -16
  121. package/dist/cli/chunk-4gaqhq8t.js +0 -2
  122. package/dist/cli/chunk-6t2zhxmq.js +0 -2
  123. package/dist/cli/chunk-7h7tqran.js +0 -2
  124. package/dist/cli/chunk-8ddjfc2v.js +0 -4
  125. package/dist/cli/chunk-9j7507ap.js +0 -2
  126. package/dist/cli/chunk-9k5p5852.js +0 -7
  127. package/dist/cli/chunk-9tw3vt9p.js +0 -2
  128. package/dist/cli/chunk-aeq5xmtq.js +0 -3
  129. package/dist/cli/chunk-aq912vvw.js +0 -3
  130. package/dist/cli/chunk-arf294te.js +0 -2
  131. package/dist/cli/chunk-ea0fm583.js +0 -2
  132. package/dist/cli/chunk-evmfa4v5.js +0 -2
  133. package/dist/cli/chunk-fm6e40pe.js +0 -2
  134. package/dist/cli/chunk-fna6sxe4.js +0 -5
  135. package/dist/cli/chunk-j2j1kq3m.js +0 -2
  136. package/dist/cli/chunk-kpf3yaj9.js +0 -3
  137. package/dist/cli/chunk-m6n0mkye.js +0 -2
  138. package/dist/cli/chunk-makzf3q1.js +0 -9
  139. package/dist/cli/chunk-nzy3yafz.js +0 -2
  140. package/dist/cli/chunk-p8hzr9m6.js +0 -2
  141. package/dist/cli/chunk-q3fc7t7p.js +0 -3
  142. package/dist/cli/chunk-r94jdy8g.js +0 -2
  143. package/dist/cli/chunk-snzh4n0v.js +0 -3
  144. package/dist/cli/chunk-st4xag8b.js +0 -2
  145. package/dist/cli/chunk-x760j10f.js +0 -3
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{canonicalize}from"./chunk-5snrwe65.js";import{applyJitter,exponentialBackoff}from"./chunk-gwcneg6c.js";import{getRemoteRepoConfig,isRemoteRepoKey,resolveRepoRoot}from"./chunk-deejtpcr.js";var canonPath=canonicalize;function randomDirTaskSuffix(){return Math.random().toString(36).slice(2,6).padEnd(4,"0")}function titleFromRepo(repo){let segs=repo.split(/[/\\]/).filter(Boolean);return segs.length>0?segs[segs.length-1]??repo:repo}function normalizeMainRepo(repo){let normalized=resolveRepoRoot(repo);return{repo:normalized,key:isRemoteRepoKey(normalized)?normalized:canonPath(normalized)}}function repoWorkingDir(repo){return getRemoteRepoConfig(repo)?.basePath??repo}var GH_PR_VIEW_FIELDS="number,url,title,state,baseRefName,reviewDecision,mergeable,statusCheckRollup";function lifecycleFromState(state,reviewDecision){switch((state??"").toUpperCase()){case"MERGED":return"merged";case"CLOSED":return"closed";case"OPEN":return(reviewDecision??"").toUpperCase()==="APPROVED"?"ready_to_merge":"open";default:return"unknown"}}function entryCheckState(entry){let status=(entry.status??"").toUpperCase(),conclusion=(entry.conclusion??"").toUpperCase(),contextState=(entry.state??"").toUpperCase();if(status&&status!=="COMPLETED")return"pending";if(conclusion){if(conclusion==="SUCCESS"||conclusion==="NEUTRAL"||conclusion==="SKIPPED")return"passing";return"failing"}if(contextState==="SUCCESS")return"passing";if(contextState==="PENDING"||contextState==="EXPECTED")return"pending";if(contextState==="FAILURE"||contextState==="ERROR")return"failing";return"unknown"}function checkStateFromRollup(rollup){if(!rollup||rollup.length===0)return"none";let sawPending=!1,sawPassing=!1;for(let entry of rollup){let s=entryCheckState(entry);if(s==="failing")return"failing";if(s==="pending")sawPending=!0;else if(s==="passing")sawPassing=!0}if(sawPending)return"pending";if(sawPassing)return"passing";return"unknown"}function mapGhPrView(view,at){if(!view||typeof view.number!=="number")return null;return{provider:"github",lifecycle:lifecycleFromState(view.state,view.reviewDecision),checkState:checkStateFromRollup(view.statusCheckRollup),number:view.number,url:view.url,title:view.title,baseRef:view.baseRefName,reviewDecision:view.reviewDecision||void 0,mergeable:view.mergeable||void 0,lastCheckedAt:at}}function samePrStatus(a,b){if(a===b)return!0;if(!a||!b)return!1;return a.provider===b.provider&&a.lifecycle===b.lifecycle&&a.checkState===b.checkState&&a.number===b.number&&a.url===b.url&&a.title===b.title&&a.baseRef===b.baseRef&&a.reviewDecision===b.reviewDecision&&a.mergeable===b.mergeable}var NO_REMOTE_PATTERNS=["none of the git remotes","no git remote","to use github cli in a github repository","not a github repository"],AUTH_PATTERNS=["gh auth login","authentication required","not logged in","http 401","bad credentials","requires authentication"],NETWORK_PATTERNS=["could not resolve host","no such host","dial tcp","connection refused","connection reset","network is unreachable","i/o timeout","timeout","tls handshake","http 5","rate limit","try again"];function matchesAny(haystack,needles){return needles.some((n)=>haystack.includes(n))}function classifyGhFailure(s){if(s.parseError)return{kind:"error",error:"parse"};if(s.timedOut)return{kind:"error",error:"timeout"};if(s.spawnError)return{kind:"error",error:"missing-binary"};let err=(s.stderr??"").toLowerCase();if(matchesAny(err,NO_REMOTE_PATTERNS))return{kind:"error",error:"no-remote"};if(matchesAny(err,AUTH_PATTERNS))return{kind:"error",error:"auth"};if(matchesAny(err,NETWORK_PATTERNS))return{kind:"error",error:"network"};return{kind:"error",error:"unknown"}}function nextPrPoll(outcome,prevFailures,now,cfg,rand=Math.random){let at=(delay)=>now+applyJitter(delay,cfg.jitterRatio,rand);if(outcome.kind==="pr")return{nextAllowedAt:at(outcome.settled?cfg.settledMs:cfg.tickMs),failures:0};if(outcome.kind==="empty")return{nextAllowedAt:at(cfg.noPrMs),failures:0};if(outcome.error==="no-remote")return{nextAllowedAt:at(cfg.noRemoteMs),failures:0};let failures=prevFailures+1;return{nextAllowedAt:at(exponentialBackoff(cfg.failureBaseMs,failures-1,cfg.failureCapMs)),failures}}function checkResolutionNotify(prev,next){if(prev!=="pending")return null;if(next==="passing"||next==="failing")return next;return null}
2
+ import{canonicalize}from"./chunk-6pt23vas.js";import{applyJitter,exponentialBackoff}from"./chunk-gwcneg6c.js";import{getRemoteRepoConfig,isRemoteRepoKey,resolveRepoRoot}from"./chunk-kt1ppyje.js";var canonPath=canonicalize;function randomDirTaskSuffix(){return Math.random().toString(36).slice(2,6).padEnd(4,"0")}function titleFromRepo(repo){let segs=repo.split(/[/\\]/).filter(Boolean);return segs.length>0?segs[segs.length-1]??repo:repo}function normalizeMainRepo(repo){let normalized=resolveRepoRoot(repo);return{repo:normalized,key:isRemoteRepoKey(normalized)?normalized:canonPath(normalized)}}function repoWorkingDir(repo){return getRemoteRepoConfig(repo)?.basePath??repo}var GH_PR_VIEW_FIELDS="number,url,title,state,baseRefName,reviewDecision,mergeable,statusCheckRollup";function lifecycleFromState(state,reviewDecision){switch((state??"").toUpperCase()){case"MERGED":return"merged";case"CLOSED":return"closed";case"OPEN":return(reviewDecision??"").toUpperCase()==="APPROVED"?"ready_to_merge":"open";default:return"unknown"}}function entryCheckState(entry){let status=(entry.status??"").toUpperCase(),conclusion=(entry.conclusion??"").toUpperCase(),contextState=(entry.state??"").toUpperCase();if(status&&status!=="COMPLETED")return"pending";if(conclusion){if(conclusion==="SUCCESS"||conclusion==="NEUTRAL"||conclusion==="SKIPPED")return"passing";return"failing"}if(contextState==="SUCCESS")return"passing";if(contextState==="PENDING"||contextState==="EXPECTED")return"pending";if(contextState==="FAILURE"||contextState==="ERROR")return"failing";return"unknown"}function checkStateFromRollup(rollup){if(!rollup||rollup.length===0)return"none";let sawPending=!1,sawPassing=!1;for(let entry of rollup){let s=entryCheckState(entry);if(s==="failing")return"failing";if(s==="pending")sawPending=!0;else if(s==="passing")sawPassing=!0}if(sawPending)return"pending";if(sawPassing)return"passing";return"unknown"}function mapGhPrView(view,at){if(!view||typeof view.number!=="number")return null;return{provider:"github",lifecycle:lifecycleFromState(view.state,view.reviewDecision),checkState:checkStateFromRollup(view.statusCheckRollup),number:view.number,url:view.url,title:view.title,baseRef:view.baseRefName,reviewDecision:view.reviewDecision||void 0,mergeable:view.mergeable||void 0,lastCheckedAt:at}}function samePrStatus(a,b){if(a===b)return!0;if(!a||!b)return!1;return a.provider===b.provider&&a.lifecycle===b.lifecycle&&a.checkState===b.checkState&&a.number===b.number&&a.url===b.url&&a.title===b.title&&a.baseRef===b.baseRef&&a.reviewDecision===b.reviewDecision&&a.mergeable===b.mergeable}var NO_REMOTE_PATTERNS=["none of the git remotes","no git remote","to use github cli in a github repository","not a github repository"],AUTH_PATTERNS=["gh auth login","authentication required","not logged in","http 401","bad credentials","requires authentication"],NETWORK_PATTERNS=["could not resolve host","no such host","dial tcp","connection refused","connection reset","network is unreachable","i/o timeout","timeout","tls handshake","http 5","rate limit","try again"];function matchesAny(haystack,needles){return needles.some((n)=>haystack.includes(n))}function classifyGhFailure(s){if(s.parseError)return{kind:"error",error:"parse"};if(s.timedOut)return{kind:"error",error:"timeout"};if(s.spawnError)return{kind:"error",error:"missing-binary"};let err=(s.stderr??"").toLowerCase();if(matchesAny(err,NO_REMOTE_PATTERNS))return{kind:"error",error:"no-remote"};if(matchesAny(err,AUTH_PATTERNS))return{kind:"error",error:"auth"};if(matchesAny(err,NETWORK_PATTERNS))return{kind:"error",error:"network"};return{kind:"error",error:"unknown"}}function nextPrPoll(outcome,prevFailures,now,cfg,rand=Math.random){let at=(delay)=>now+applyJitter(delay,cfg.jitterRatio,rand);if(outcome.kind==="pr")return{nextAllowedAt:at(outcome.settled?cfg.settledMs:cfg.tickMs),failures:0};if(outcome.kind==="empty")return{nextAllowedAt:at(cfg.noPrMs),failures:0};if(outcome.error==="no-remote")return{nextAllowedAt:at(cfg.noRemoteMs),failures:0};let failures=prevFailures+1;return{nextAllowedAt:at(exponentialBackoff(cfg.failureBaseMs,failures-1,cfg.failureCapMs)),failures}}function checkResolutionNotify(prev,next){if(prev!=="pending")return null;if(next==="passing"||next==="failing")return next;return null}
3
3
  export{GH_PR_VIEW_FIELDS,mapGhPrView,samePrStatus,classifyGhFailure,nextPrPoll,checkResolutionNotify,canonPath,randomDirTaskSuffix,titleFromRepo,normalizeMainRepo,repoWorkingDir};
@@ -0,0 +1,4 @@
1
+ // @bun
2
+ import{canonPath,normalizeMainRepo,randomDirTaskSuffix,repoWorkingDir,samePrStatus,titleFromRepo}from"./chunk-vj2vdx3w.js";import{readLastActiveTaskId,writeLastActiveTaskId}from"./chunk-t7xhb2jx.js";import{GitWorktreeManager,defaultExecDeps,isDirtyOutput,parseDirtyPaths}from"./chunk-hj08heah.js";import{resolvePreferredVendor}from"./chunk-caqpt09m.js";import{READ_ONLY_GIT_ENV}from"./chunk-6xppe9bj.js";import{CannotDeleteMainTaskError,DirtyWorktreeError,EmptyBranchDirtyWorktreeError,EmptyBranchError,GitCommandFailedError,IllegalTransitionError,LandConflictError,MainCheckoutDirtyError,MissingRefError,PLACEHOLDER_TASK_TITLE,TaskDeletingError,TaskNotFoundError,WorktreeRemoveFailedError,isPlaceholderDerivedBranch}from"./chunk-r05r01nv.js";import{canonicalize,listWorktreeDirNames}from"./chunk-6pt23vas.js";import{detectLanguage}from"./chunk-hape5vwj.js";import{createStateCell}from"./chunk-sdyzxayr.js";import{addSavedRepo,getSavedRepos,isGitRepo,removeSavedRepo,resolveRepoRoot}from"./chunk-kt1ppyje.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{projectRejection,rejectionReason}from"./chunk-3wj69b0a.js";async function createTaskRow(deps,input){if(!input.repo)throw Error("createTask: repo is required");let repo=(await deps.mainTasks.ensureIfEligible(input.repo,input.projectIntent??"explicit"))?.repo??normalizeMainRepo(input.repo).repo,title=(input.title??PLACEHOLDER_TASK_TITLE).trim()||PLACEHOLDER_TASK_TITLE;return await deps.store.create({repo,title,branch:input.branch??"",worktreePath:"",status:"backlog",kind:"task",vendor:input.vendor??DEFAULT_TASK_VENDOR,...input.command?.trim()?{command:input.command.trim()}:{},...input.modelEffort?{modelEffort:input.modelEffort}:{},...input.groupId?{groupId:input.groupId}:{},...input.dispatcher?{dispatcher:input.dispatcher}:{},...input.routine?{routine:input.routine}:{},...input.baseRef?.trim()?{baseRef:input.baseRef.trim()}:{}})}async function openDirectoryTaskRow(deps,input){if(!input.dir)throw Error("openDirectoryTask: dir is required");let dir=canonPath(input.dir);return deps.store.create({repo:dir,title:input.scratch?"":`${titleFromRepo(dir)}-${randomDirTaskSuffix()}`,branch:"",worktreePath:dir,status:"backlog",kind:"dir",...input.scratch?{scratch:!0}:{},vendor:input.vendor??resolvePreferredVendor()})}async function adoptScratchRepoRow(deps,id,repo){let task=deps.store.get(id);if(!task||task.kind!=="dir"||task.scratch!==!0)return;let dir=canonPath(repo);await deps.store.update(id,{repo:dir,worktreePath:dir,scratch:!1,title:titleFromRepo(dir)})}function baseRepoCtx(repo,deps){let basePath=deps.remoteBasePath(repo);return{exec:deps.execForRepo(repo),dir:basePath??repo}}async function landGit(exec,dir,args,opts){let r=await exec.run(["git",...args],{cwd:dir,env:opts?.readOnly?READ_ONLY_GIT_ENV:void 0});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}async function isDirty(exec,dir){return isDirtyOutput((await landGit(exec,dir,["status","--porcelain"],{readOnly:!0})).stdout)}async function landPreflight(task,deps=defaultExecDeps){let refuse=(pf,refusal)=>{let refused={...pf,refusal};return{...refused,message:landRefusalError(task,refused).message}},branch=task.branch.trim();if(!branch)throw Error(`landPreflight: task ${task.id} has no branch to land (never materialised)`);let{exec,dir}=baseRepoCtx(task.repo,deps),headOut=await landGit(exec,dir,["symbolic-ref","--short","HEAD"],{readOnly:!0}),landedOn=headOut.stdout.trim();if(headOut.exitCode!==0||!landedOn){let headCommit=await landGit(exec,dir,["rev-parse","--verify","--quiet","HEAD"],{readOnly:!0}),detached=headCommit.exitCode===0&&headCommit.stdout.trim().length>0;return refuse({branch,landedOn:"",baseDir:dir},detached?"DETACHED_HEAD":"UNREADABLE_BASE")}if(landedOn===branch)return refuse({branch,landedOn,baseDir:dir},"SAME_BRANCH");let baseDirty=await isDirty(exec,dir),aheadOut=await landGit(exec,dir,["rev-list","--count",`${landedOn}..${branch}`],{readOnly:!0});if(aheadOut.exitCode!==0){let baseHead=await landGit(exec,dir,["rev-parse","--verify","--quiet","HEAD"],{readOnly:!0});if(baseHead.exitCode!==0||!baseHead.stdout.trim())return refuse({branch,landedOn,baseDirty,baseDir:dir},"UNBORN_BASE");return refuse({branch,landedOn,baseDirty,baseDir:dir},baseDirty?"MAIN_CHECKOUT_DIRTY":"MISSING_REF")}let parsed=Number.parseInt(aheadOut.stdout.trim(),10),base={branch,landedOn,baseDirty,baseDir:dir,...Number.isFinite(parsed)?{ahead:parsed}:{}};if(baseDirty)return refuse(base,"MAIN_CHECKOUT_DIRTY");if(base.ahead!==0)return base;let worktreePath=task.worktreePath.trim();if(worktreePath){let manager=new GitWorktreeManager(deps),dirty=!1;try{dirty=await manager.isDirty(worktreePath)}catch{dirty=!1}if(dirty){let wtExec=deps.execForPath(worktreePath),files=parseDirtyPaths((await landGit(wtExec,worktreePath,["status","--porcelain"],{readOnly:!0})).stdout);return refuse({...base,dirtyFiles:files},"EMPTY_BRANCH_DIRTY_WORKTREE")}}return refuse(base,"EMPTY_BRANCH")}function landRefusalError(task,pf){switch(pf.refusal){case"DETACHED_HEAD":return Error(`landTask: base checkout at ${pf.baseDir} is in detached-HEAD state; check out a branch first`);case"UNREADABLE_BASE":return Error(`landTask: could not read HEAD of the base checkout at ${pf.baseDir} \u2014 is it still a git repo?`);case"UNBORN_BASE":return Error(`landTask: base checkout at ${pf.baseDir} is on '${pf.landedOn}' but has no commits yet, so there is nothing to merge '${pf.branch}' into; make the first commit there (or \`git merge --ff-only ${pf.branch}\`) and land again`);case"SAME_BRANCH":return Error(`landTask: base checkout is already on '${pf.branch}' \u2014 nothing to land onto`);case"MAIN_CHECKOUT_DIRTY":return new MainCheckoutDirtyError(task.repo,pf.baseDir);case"MISSING_REF":return new MissingRefError(pf.branch,pf.landedOn,pf.baseDir);case"EMPTY_BRANCH_DIRTY_WORKTREE":return new EmptyBranchDirtyWorktreeError(pf.branch,pf.landedOn,task.worktreePath.trim(),[...pf.dirtyFiles??[]]);case"EMPTY_BRANCH":return new EmptyBranchError(pf.branch,pf.landedOn)}}import path from"path";async function landTaskWithCleanup(task,opts,deps){if(task.kind==="main")throw Error("landTask: a main task has no branch to land");if(task.kind==="dir")throw Error("landTask: a directory task has no Rove-managed branch to land");let result=await landTask(task,{strategy:opts.strategy}),worktree=opts.removeWorktree===!1?void 0:await removeLandedWorktree(task,opts.callerCwd,deps),branchAnchor=null,branchKept,worktreeGone=!task.worktreePath.trim()||worktree?.removed===!0;if(opts.deleteBranch&&!worktreeGone)branchKept={reason:worktree?.reason??`worktree ${task.worktreePath} was kept, and still has the branch checked out`};else if(opts.deleteBranch){let outcome=await deps.worktrees.deleteBranch(task.repo,result.branch,{force:!0,onAnchor:(record)=>{branchAnchor=record}});if(!outcome.deleted)branchKept={reason:outcome.reason}}return{...result,...worktree?{worktree}:{},...branchAnchor?{branchAnchor}:{},...branchKept?{branchKept}:{}}}async function removeLandedWorktree(task,callerCwd,deps){let worktreePath=task.worktreePath.trim();if(!worktreePath)return{removed:!1,reason:"task has no worktree on disk (never materialised)"};let wt=canonicalize(worktreePath);if(wt===canonicalize(task.repo))return{removed:!1,reason:"refusing to remove the base checkout"};if(callerCwd){let rel=path.relative(wt,canonicalize(callerCwd));if(rel===""||!rel.startsWith("..")&&!path.isAbsolute(rel))return{removed:!1,reason:`refusing to remove the caller's own worktree (${worktreePath}) \u2014 re-run from outside it`}}if(deps.tearDownSession)try{await deps.tearDownSession(task.id)}catch{}let residue;try{await deps.worktrees.remove(worktreePath,{onResidue:(r)=>{residue=r}})}catch(err){return{removed:!1,reason:errText(err)}}try{await deps.clearWorktreePath(task.id)}catch(err){return{removed:!0,reason:`worktree removed, but clearing the task's worktree path failed: ${errText(err)}`,...residue?{residue}:{}}}return{removed:!0,...residue?{residue}:{}}}function errText(err){return err instanceof Error?err.message:String(err)}async function conflictedFiles(exec,dir){return(await landGit(exec,dir,["diff","--name-only","--diff-filter=U"],{readOnly:!0})).stdout.split(`
3
+ `).map((l)=>l.trim()).filter((l)=>l.length>0)}async function landTask(task,input={},deps=defaultExecDeps){let strategy=input.strategy??"merge",preflight=await landPreflight(task,deps);if(preflight.refusal)throw landRefusalError(task,{...preflight,refusal:preflight.refusal});let{branch,landedOn}=preflight,{exec,dir}=baseRepoCtx(task.repo,deps);if(strategy==="squash"){if((await landGit(exec,dir,["merge","--squash",branch])).exitCode!==0){let files=await conflictedFiles(exec,dir);throw await landGit(exec,dir,["merge","--abort"]).catch(()=>{}),await landGit(exec,dir,["reset","--hard","HEAD"]).catch(()=>{}),new LandConflictError(task.id,branch,files)}let commit=await landGit(exec,dir,["commit","--no-edit","-m",`Land ${branch} (squash)`]);if(commit.exitCode!==0){if((await landGit(exec,dir,["diff","--cached","--quiet"],{readOnly:!0})).exitCode===0)throw await landGit(exec,dir,["reset","--hard","HEAD"]).catch(()=>{}),Error(`landTask: '${branch}' has nothing to land onto '${landedOn}' (already merged or empty)`);throw new GitCommandFailedError(`commit (squash-landing '${branch}' onto '${landedOn}')`,commit.stderr,"the squashed merge is left STAGED in the base checkout \u2014 fix the cause and `git commit` it, or `git reset --hard HEAD` to discard")}}else{let before=(await landGit(exec,dir,["rev-parse","HEAD"],{readOnly:!0})).stdout.trim(),merge=await landGit(exec,dir,["merge","--no-ff","-m",`Land ${branch}`,branch]);if(merge.exitCode!==0){let files=await conflictedFiles(exec,dir);if(await landGit(exec,dir,["merge","--abort"]).catch(()=>{}),files.length===0)throw new GitCommandFailedError(`merge --no-ff (landing '${branch}' onto '${landedOn}')`,merge.stderr,"the merge was aborted, so the base checkout is unchanged");throw new LandConflictError(task.id,branch,files)}let after=(await landGit(exec,dir,["rev-parse","HEAD"],{readOnly:!0})).stdout.trim();if(before===after)throw Error(`landTask: '${branch}' has nothing to land onto '${landedOn}' (already merged or empty)`)}let shaOut=await landGit(exec,dir,["rev-parse","--short","HEAD"],{readOnly:!0});return{branch,strategy,landedOn,commit:shaOut.stdout.trim()}}class MainTaskCoordinator{store;forgetWorktree;locks=new Map;constructor(store,forgetWorktree){this.store=store;this.forgetWorktree=forgetWorktree}async ensure(repo){let task=await this.ensureIfEligible(repo,"explicit");if(task)return task;let{repo:normalizedRepo}=normalizeMainRepo(repo),rejected=projectRejection(normalizedRepo,isGitRepo,"explicit")??"notGitRepo";throw Error(`cannot add ${normalizedRepo} as a project: ${rejectionReason(rejected)}`)}async ensureIfEligible(repo,intent="derived"){let{repo:normalizedRepo,key}=normalizeMainRepo(repo),onThisRoot=(task)=>normalizeMainRepo(task.repo).key===key,existing=this.store.list().find((task)=>task.kind==="main"&&onThisRoot(task));if(existing)return existing;if(projectRejection(normalizedRepo,isGitRepo,intent))return null;let inflight=this.locks.get(key);if(inflight)return inflight;let promise=(async()=>{addSavedRepo(normalizedRepo,{intent:"explicit"});let adoptable=this.store.list().find((task)=>task.kind==="dir"&&task.scratch!==!0&&onThisRoot(task));if(adoptable)return await this.store.update(adoptable.id,this.mainShape(normalizedRepo));return await this.store.create({...this.mainShape(normalizedRepo),status:"backlog",vendor:resolvePreferredVendor(normalizedRepo)})})();this.locks.set(key,promise);try{return await promise}finally{this.locks.delete(key)}}mainShape(normalizedRepo){return{kind:"main",title:titleFromRepo(normalizedRepo),repo:normalizedRepo,branch:"",worktreePath:repoWorkingDir(normalizedRepo)}}async forget(repo){if(!repo)throw Error("forgetProject: repo is required");let key=normalizeMainRepo(repo).key;for(let saved of getSavedRepos())if(normalizeMainRepo(saved).key===key)removeSavedRepo(saved);for(let task of this.store.list()){if(task.kind!=="main")continue;if(normalizeMainRepo(task.repo).key!==key)continue;await this.store.remove(task.id),this.forgetWorktree(task.id)}}}function promotableDirTasks(deps){let claimed=new Set(deps.tasks.filter((task)=>task.kind==="main").map((task)=>task.repo)),seen=new Set,out=[];for(let task of deps.tasks){if(task.kind!=="dir"||task.scratch===!0)continue;let path2=task.repo;if(!path2||claimed.has(path2)||seen.has(path2))continue;if(!deps.isRepoRoot(path2))continue;seen.add(path2),out.push(task)}return out}class TaskDeletionCoordinator{store;worktrees;forgetTask;onSalvage;onResidue;onBranchKept;constructor(store,worktrees,forgetTask,onSalvage,onResidue,onBranchKept){this.store=store;this.worktrees=worktrees;this.forgetTask=forgetTask;this.onSalvage=onSalvage;this.onResidue=onResidue;this.onBranchKept=onBranchKept}async prepare(id,opts){let task=this.store.get(id);if(!task)return!1;if(task.kind==="main")throw new CannotDeleteMainTaskError;if(task.deletion?.phase==="queued"||task.deletion?.phase==="running")return!0;let force=opts?.force===!0;if(task.worktreePath&&!force&&task.kind!=="dir"){let dirty=!1,ignored=[],probed=!0;try{dirty=await this.worktrees.isDirty(task.worktreePath)}catch{probed=!1}if(probed&&!dirty)ignored=await this.worktrees.ignoredWork(task.worktreePath);if(dirty||ignored==="unknown"||ignored.length>0)throw new DirtyWorktreeError(task.id,ignored)}return await this.store.update(task.id,{deletion:{phase:"queued",force,deleteBranch:opts?.deleteBranch===!0,requestedAt:new Date().toISOString()}}),!0}async begin(id){let task=this.store.get(id);if(!task||!task.deletion||task.deletion.phase==="error")return!1;if(task.deletion.phase!=="running")await this.store.update(task.id,{deletion:{...task.deletion,phase:"running"}});return!0}async finish(id){let task=this.store.get(id);if(!task?.deletion||task.deletion.phase!=="running")return;try{if(task.worktreePath&&task.kind!=="dir")await this.worktrees.remove(task.worktreePath,{force:task.deletion.force,deleteBranch:task.deletion.deleteBranch===!0,repo:task.repo,branch:task.branch,onSalvage:(record)=>{if(record)this.onSalvage?.(task.id,record)},onResidue:(residue)=>this.onResidue?.(task.id,residue),onBranchKept:(kept)=>this.onBranchKept?.(task.id,kept)})}catch(cause){let failure=new WorktreeRemoveFailedError(task.id,cause);throw await this.store.update(task.id,{deletion:{...task.deletion,phase:"error",error:errorMessage(failure)}}),failure}await this.store.remove(task.id),this.forgetTask(task.id)}async deleteNow(id,opts){if(!await this.prepare(id,opts))return;if(!await this.begin(id))return;await this.finish(id)}}var TYPE_PREFIXES=new Set(["feat","feature","fix","bugfix","hotfix","chore","docs","doc","refactor","test","tests","ci","build","perf","style","revert","release"]),BRAND_TOKENS=new Set(["rove","kobe"]);function inferBranchStyle(names){let typed=new Map,bare=0;for(let raw of new Set(names)){let name=raw.trim();if(!name||name==="HEAD")continue;let slash=name.indexOf("/");if(slash===-1){bare+=1;continue}let prefix=name.slice(0,slash);if(TYPE_PREFIXES.has(prefix))typed.set(prefix,(typed.get(prefix)??0)+1)}let typedTotal=0;for(let n of typed.values())typedTotal+=n;if(typedTotal===0||typedTotal<bare)return{kind:"bare"};let best="",bestN=0;for(let[prefix,n]of typed)if(n>bestN||n===bestN&&(best===""||prefix<best))best=prefix,bestN=n;return{kind:"typed",defaultPrefix:best}}function slugTokens(title){return title.toLowerCase().replace(/[^a-z0-9]+/g,"-").split("-").filter((t)=>t.length>0&&!BRAND_TOKENS.has(t))}function capSlug(tokens){return tokens.join("-").slice(0,32).replace(/-+$/,"")}function deriveConventionBranch(title,style){let tokens=slugTokens(title);if(style.kind==="typed"){let first=tokens[0];return`${first!==void 0&&TYPE_PREFIXES.has(first)?tokens.shift():style.defaultPrefix}/${capSlug(tokens)||"task"}`}return capSlug(tokens)||"task"}function uniqueBranchName(base,taken,taskId){if(!taken.has(base))return base;for(let n=2;n<=99;n+=1){let candidate=`${base}-${n}`;if(!taken.has(candidate))return candidate}return`${base}-${taskId.slice(-6).toLowerCase()}`}class TaskEditor{store;worktrees;constructor(store,worktrees){this.store=store,this.worktrees=worktrees}requireTask(id){let task=this.store.get(id);if(!task)throw new TaskNotFoundError(String(id));return task}async setTitle(id,title){let trimmed=title.trim();if(!trimmed)throw Error("setTitle: title is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.title===trimmed&&task.scratch!==!0)return;await this.store.update(task.id,{title:trimmed,...task.scratch===!0?{scratch:!1}:{}}),await this.followBranchToTitle(task,trimmed)}async followBranchToTitle(taskBefore,newTitle){if(taskBefore.kind==="main"||!taskBefore.worktreePath)return;if(!isPlaceholderDerivedBranch(taskBefore.branch,taskBefore.id))return;try{let names=await this.worktrees.listBranchNames(taskBefore.repo),base=deriveConventionBranch(newTitle,inferBranchStyle(names));if(base===taskBefore.branch)return;if(await this.worktrees.branchHasUpstream(taskBefore.worktreePath,taskBefore.branch))return;let taken=new Set(names.filter((n)=>n!==taskBefore.branch)),nextBranch=uniqueBranchName(base,taken,taskBefore.id);await this.setBranch(taskBefore.id,nextBranch)}catch(err){console.error(`[rove] follow-branch-to-title failed for ${taskBefore.id}:`,err)}}async setBranch(id,branch){let trimmed=branch.trim();if(!trimmed)throw Error("setBranch: branch is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.kind==="main")throw Error("setBranch: a main task tracks the repo's own branch; rename it with git directly");if(task.kind==="dir")throw Error("setBranch: a directory task tracks its own checkout; rename branches with git directly");if(task.branch===trimmed)return;if(task.worktreePath)await this.worktrees.renameBranch(task.worktreePath,task.branch,trimmed);await this.store.update(task.id,{branch:trimmed})}async observeLanguage(id,text){let observed=detectLanguage(text);if(!observed)return;let task=this.requireTask(id);if(task.observedLanguage===observed)return;await this.store.update(task.id,{observedLanguage:observed})}async setVendor(id,vendor,effort){let task=this.requireTask(id),nextEffort=effort?.trim()?effort.trim():void 0,effortChanges=effort!==void 0&&task.modelEffort!==nextEffort;if(task.vendor===vendor&&!effortChanges)return;await this.store.update(task.id,{vendor,...effort!==void 0?{modelEffort:nextEffort}:{}})}async setCommand(id,command,vendor){let trimmed=command.trim();if(!trimmed)throw Error("setCommand: command is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.command===trimmed&&(vendor===void 0||task.vendor===vendor))return;await this.store.update(task.id,{command:trimmed,...vendor?{vendor}:{}})}async setPinned(id,pinned){let task=this.requireTask(id);if(task.kind==="main")return;let next=pinned??!task.pinned;if((task.pinned??!1)===next)return;await this.store.update(task.id,{pinned:next})}async moveTask(id,delta){let task=this.requireTask(id),isMain=task.kind==="main",groupIds=this.store.list().filter((t)=>isMain?(t.kind??"task")==="main":(t.kind??"task")!=="main"&&t.repo===task.repo&&(t.pinned??!1)===(task.pinned??!1)).map((t)=>String(t.id));await this.store.move(task.id,delta,groupIds)}async setStatus(id,status){let task=this.requireTask(id);if(task.status===status)return;if(task.status==="done"&&status==="error"||task.status==="error"&&status==="done")throw new IllegalTransitionError(task.status,status,task.id);await this.store.update(task.id,{status})}async setPRStatus(id,prStatus){let task=this.requireTask(id);if((task.prStatus?.lastError??null)===(prStatus?.lastError??null)&&samePrStatus(task.prStatus,prStatus??void 0))return;await this.store.update(task.id,{prStatus:prStatus??void 0})}async setQuotaResume(id,state){let task=this.requireTask(id);if((task.quotaResume?.resumeAt??null)===(state?.resumeAt??null))return;await this.store.update(task.id,{quotaResume:state??void 0})}async setLinkedWorkItem(id,item){let task=this.requireTask(id);if((task.linkedWorkItem?.url??null)===(item?.url??null))return;await this.store.update(task.id,{linkedWorkItem:item??void 0})}async setPrompt(id,prompt){if(prompt.trim().length===0)throw Error("setPrompt: prompt is required (empty or whitespace-only rejected)");let task=this.requireTask(id);if(task.prompt===prompt)return;await this.store.update(task.id,{prompt})}}import{basename}from"path";var ANIMAL_NAMES=["aardvark","addax","adder","agouti","albatross","alpaca","anaconda","anchovy","anglerfish","anole","anteater","antelope","ape","argali","armadillo","avocet","axolotl","baboon","badger","banteng","barracuda","basilisk","bass","bat","beagle","bear","beaver","bee","beetle","beluga","betta","bison","blackbird","blenny","bluebird","bluegill","boar","bobcat","bonito","bovid","buffalo","bullfrog","bunting","bushbuck","butterfly","buzzard","caiman","camel","canary","capybara","caracal","cardinal","caribou","carp","cassowary","caterpillar","catfish","chameleon","chamois","char","cheetah","chickadee","chimp","chinchilla","chipmunk","chough","cicada","civet","clam","clownfish","cobra","cockatoo","condor","coot","copperhead","coral","cormorant","cougar","coyote","crab","crane","crawfish","crayfish","cricket","crocodile","crow","cuckoo","curlew","cuttlefish","deer","dikdik","dingo","dolphin","donkey","dormouse","dotterel","dove","dragonfly","dromedary","duck","dugong","dunlin","eagle","echidna","eel","egret","eider","eland","elephant","elk","emu","ermine","falcon","fawn","ferret","finch","firefly","flamingo","flounder","fox","frog","gadwall","gannet","gaur","gazelle","gecko","gemsbok","gerbil","gharial","gibbon","gnu","goat","goby","godwit","goldfish","goose","gopher","goral","gorilla","goshawk","grackle","grasshopper","grayling","grebe","grouse","guanaco","guillemot","guineafowl","guppy","halibut","hammerhead","hamster","hare","harrier","hartebeest","hawk","hedgehog","heron","herring","hippo","hornbill","hornet","horse","hummingbird","hyena","ibex","ibis","iguana","impala","indri","jacana","jackal","jaguar","jay","jellyfish","jerboa","junco","kakapo","kangaroo","kestrel","killdeer","kingfisher","kinglet","kite","kiwi","koala","kookaburra","krait","krill","kudu","ladybug","lamprey","langur","lapwing","lark","lemming","lemur","leopard","limpet","lion","lionfish","lizard","llama","lobster","locust","loon","lorikeet","loris","lynx","macaque","macaw","mackerel","magpie","mallard","mamba","mammoth","manatee","mandrill","manta","mantis","marlin","marmoset","marmot","marten","meerkat","merganser","mink","minnow","mole","mongoose","monitor","monkey","moose","moth","mouflon","mouse","mudpuppy","mule","muntjac","musk","muskox","muskrat","mussel","mustang","narwhal","newt","nightingale","numbat","nuthatch","nyala","ocelot","octopus","okapi","opossum","orangutan","orca","oriole","oryx","osprey","ostrich","otter","owl","oyster","oystercatcher","paca","panda","pangolin","panther","parakeet","parrot","parrotfish","partridge","peafowl","pelican","penguin","perch","petrel","pheasant","pigeon","pika","pike","pintail","pipefish","platypus","plover","pollock","pony","porcupine","porpoise","possum","ptarmigan","puffin","puma","pupfish","python","quail","quetzal","quokka","quoll","rabbit","raccoon","rail","rat","rattler","raven","ray","redpoll","reindeer","remora","rhino","roadrunner","robin","rook","sable","sailfish","salamander","salmon","sandpiper","sardine","scallop","scaup","scorpion","seahorse","seal","serval","shark","shearwater","shrew","shrike","shrimp","siskin","sitatunga","skate","skink","skua","skunk","sloth","smelt","snail","snipe","solenodon","sparrow","spider","springbok","squid","squirrel","starfish","starling","stilt","stingray","stoat","stork","sunbird","sunfish","swallow","swan","swift","swordfish","tahr","takin","tamarin","tanager","tapir","tarantula","tarpon","tarsier","teal","tenrec","terrapin","tern","tetra","thrasher","thrush","tiger","toad","tortoise","toucan","treecreeper","treefrog","trout","tuatara","tuna","turkey","turtle","urchin","urial","vicuna","viper","vole","vulture","wagtail","wallaby","walleye","walrus","warbler","warthog","waterbuck","weasel","wildebeest","wolf","wolverine","wombat","woodcock","woodpecker","wrasse","wren","yak","zebra","zebu","zorilla"];class SlugAllocator{activeSlugs;random;pool;pendingByRepo=new Map;chain=Promise.resolve();constructor(activeSlugs,options={}){this.activeSlugs=activeSlugs;if(this.random=options.random??Math.random,this.pool=options.pool??ANIMAL_NAMES,this.pool.length===0)throw Error("SlugAllocator: animal pool cannot be empty")}async allocate(repo){let previous=this.chain,release;this.chain=new Promise((resolve)=>{release=resolve}),await previous;try{return await this.pickLocked(repo)}finally{release()}}commit(repo,slug){this.deletePending(repo,slug)}cancel(repo,slug){this.deletePending(repo,slug)}async pickLocked(repo){let occupied=await this.occupiedSlugs(repo),candidates=this.pool.filter((n)=>!occupied.has(n));if(candidates.length>0){let pick=candidates[Math.floor(this.random()*candidates.length)];return this.addPending(repo,pick),pick}let base=this.pool[Math.floor(this.random()*this.pool.length)];for(let v=2;;v++){let candidate=`${base}-v${v}`;if(!occupied.has(candidate))return this.addPending(repo,candidate),candidate}}async occupiedSlugs(repo){let set=new Set(this.pendingByRepo.get(repo)??[]);for(let slug of this.activeSlugs(repo))if(slug)set.add(slug);for(let dir of await listWorktreeDirNames(repo))set.add(dir);return set}addPending(repo,slug){let pending=this.pendingByRepo.get(repo);if(!pending)pending=new Set,this.pendingByRepo.set(repo,pending);pending.add(slug)}deletePending(repo,slug){let pending=this.pendingByRepo.get(repo);if(!pending)return;if(pending.delete(slug),pending.size===0)this.pendingByRepo.delete(repo)}}class WorktreeCoordinator{store;worktrees;canonPath;ensureProject;slugs;worktreeLocks=new Map;adoptLocks=new Map;reservedBranches=new Set;constructor(store,worktrees,canonPath2,ensureProject){this.store=store,this.worktrees=worktrees,this.canonPath=canonPath2,this.ensureProject=ensureProject,this.slugs=new SlugAllocator((repo)=>this.store.list().filter((t)=>t.repo===repo&&t.kind!=="main").map((t)=>{return t.worktreePath.match(/([^/\\]+)[/\\]*$/)?.[1]??""}).filter((s)=>s.length>0))}forget(id){this.worktreeLocks.delete(id)}async ensure(task){let inflight=this.worktreeLocks.get(task.id);if(inflight)return inflight;let work=this.createWorktree(task);this.worktreeLocks.set(task.id,work);try{return await work}finally{this.worktreeLocks.delete(task.id)}}async createWorktree(task){let slug=await this.slugs.allocate(task.repo),branch=task.branch||await this.deriveAutoBranch(task),baseRef=task.baseRef,info;try{info=await this.worktrees.createForTask({repo:task.repo,slug,branch,baseRef})}catch(err){throw this.slugs.cancel(task.repo,slug),err}finally{this.reservedBranches.delete(branch)}try{await this.store.update(task.id,{worktreePath:info.path,branch})}catch(err){throw await this.rollbackWorktree(info.path),this.slugs.cancel(task.repo,slug),err}return this.slugs.commit(task.repo,slug),info.path}async deriveAutoBranch(task){let names=await this.worktrees.listBranchNames(task.repo),base=deriveConventionBranch(task.title,inferBranchStyle(names)),taken=new Set([...names,...this.reservedBranches]),branch=uniqueBranchName(base,taken,task.id);return this.reservedBranches.add(branch),branch}async rollbackWorktree(worktreePath){try{await this.worktrees.remove(worktreePath,{force:!0})}catch(err){console.error(`[rove] ensureWorktree rollback failed for ${worktreePath}:`,err)}}async discoverAdoptable(repo){let all=await this.worktrees.listAll(repo),linked=new Set(this.store.list().filter((t)=>t.worktreePath).map((t)=>this.canonPath(t.worktreePath)));return all.filter((wt)=>!linked.has(this.canonPath(wt.path)))}async adopt(input){let target=this.canonPath(input.worktreePath),inflight=this.adoptLocks.get(target);if(inflight)return inflight;let work=this.adoptLocked(input,target);this.adoptLocks.set(target,work);try{return await work}finally{this.adoptLocks.delete(target)}}async adoptLocked(input,target){let existing=this.store.list().find((t)=>t.worktreePath&&this.canonPath(t.worktreePath)===target);if(existing){if(input.ifExists==="return")return existing;throw Error(`adoptWorktree: ${input.worktreePath} is already adopted as a task`)}let match=(await this.worktrees.listAdoptablePaths(input.repo)).find((wt)=>this.canonPath(wt.path)===target);if(!match)throw Error(`adoptWorktree: ${input.worktreePath} is not an adoptable git worktree of ${input.repo} (unknown, detached, or the main checkout)`);let branch=input.branch?.trim()||match.branch,title=(input.title??basename(match.path)).trim()||PLACEHOLDER_TASK_TITLE;return await this.ensureProject(input.repo),this.store.create({repo:input.repo,title,branch,worktreePath:match.path,status:"backlog",kind:"task",vendor:input.vendor??DEFAULT_TASK_VENDOR})}}class Orchestrator{store;worktrees;worktreeCoordinator;editor;deletions;tasksAcc;activeTaskAcc;unsubscribeStore;mainTasks;tearDownSession;constructor(deps){this.store=deps.store,this.worktrees=deps.worktrees,this.tearDownSession=deps.tearDownSession,this.worktreeCoordinator=new WorktreeCoordinator(this.store,this.worktrees,canonPath,(repo)=>this.mainTasks.ensureIfEligible(repo)),this.mainTasks=new MainTaskCoordinator(this.store,(id)=>this.worktreeCoordinator.forget(id)),this.editor=new TaskEditor(this.store,this.worktrees),this.deletions=new TaskDeletionCoordinator(this.store,this.worktrees,(id)=>this.worktreeCoordinator.forget(id),deps.onSalvage,deps.onWorktreeResidue,deps.onBranchKept),this.tasksAcc=createStateCell(this.store.list());let persistedFocus=readLastActiveTaskId();this.activeTaskAcc=createStateCell(persistedFocus&&this.store.get(persistedFocus)?persistedFocus:null),this.unsubscribeStore=this.store.subscribe((snapshot)=>{this.tasksAcc.set(snapshot.slice())})}async init(){try{let promotable=promotableDirTasks({tasks:this.store.list(),isRepoRoot:(path2)=>isGitRepo(path2)&&resolveRepoRoot(path2)===path2});for(let task of promotable)await this.mainTasks.ensureIfEligible(task.repo,"explicit")}catch{}}activeTaskSignal(){return this.activeTaskAcc}async setActiveTask(id){let next=id===null?null:String(id);if(next&&this.store.get(next)?.deletion)throw new TaskDeletingError(next);if(this.activeTaskAcc.set(next),next&&this.store.get(next))writeLastActiveTaskId(next),this.store.touchRecency(next)}tasksSignal(){return this.tasksAcc}subscribeTasks(listener){return this.store.subscribe(listener)}dispose(){this.unsubscribeStore()}listTasks(){return this.store.list()}getTask(id){return this.store.get(id)}createTask=(input)=>createTaskRow({store:this.store,mainTasks:this.mainTasks},input);openDirectoryTask=(input)=>openDirectoryTaskRow({store:this.store},input);adoptScratchRepo=(id,repo)=>adoptScratchRepoRow({store:this.store},id,repo);async ensureMainTask(repo){return await this.mainTasks.ensure(repo)}async ensureWorktree(id){let task=this.requireTask(id);if(task.deletion)throw new TaskDeletingError(String(task.id));if(task.kind==="main")return repoWorkingDir(task.repo);if(task.kind==="dir")return task.worktreePath;if(task.worktreePath){if(await this.worktrees.pathExists(task.worktreePath))return task.worktreePath;return await this.worktrees.pruneWorktrees(task.repo),await this.store.update(task.id,{worktreePath:""}),this.worktreeCoordinator.ensure({...task,worktreePath:""})}return this.worktreeCoordinator.ensure(task)}async clearWorktreePath(id){let task=this.store.get(id);if(!task||!task.worktreePath)return;if(task.kind==="main"||task.kind==="dir")return;await this.store.update(task.id,{worktreePath:""}),this.worktreeCoordinator.forget(task.id)}setTitle=(id,title)=>this.editor.setTitle(id,title);setBranch=(id,branch)=>this.editor.setBranch(id,branch);observeLanguage=(id,text)=>this.editor.observeLanguage(id,text);setVendor=(id,vendor,effort)=>this.editor.setVendor(id,vendor,effort);setCommand=(id,command,vendor)=>this.editor.setCommand(id,command,vendor);setPinned=(id,pinned)=>this.editor.setPinned(id,pinned);moveTask=(id,delta)=>this.editor.moveTask(id,delta);setStatus=(id,status)=>this.editor.setStatus(id,status);setPRStatus=(id,prStatus)=>this.editor.setPRStatus(id,prStatus);setLinkedWorkItem=(id,item)=>this.editor.setLinkedWorkItem(id,item);setQuotaResume=(id,state)=>this.editor.setQuotaResume(id,state);setPrompt=(id,prompt)=>this.editor.setPrompt(id,prompt);async deleteTask(id,opts){await this.deletions.deleteNow(id,opts)}async prepareTaskDeletion(id,opts){return this.deletions.prepare(id,opts)}async beginTaskDeletion(id){return this.deletions.begin(id)}async finishTaskDeletion(id){return this.deletions.finish(id)}async landPreflight(id){let task=this.requireTask(id);if(task.kind==="main")throw Error("landTask: a main task has no branch to land");if(task.kind==="dir")throw Error("landTask: a directory task has no Rove-managed branch to land");if(task.deletion)throw new TaskDeletingError(String(task.id));return landPreflight(task)}async landTask(id,opts){let task=this.requireTask(id);if(task.deletion)throw new TaskDeletingError(String(task.id));return landTaskWithCleanup(task,opts??{},{worktrees:this.worktrees,clearWorktreePath:(tid)=>this.clearWorktreePath(tid),tearDownSession:this.tearDownSession})}async forgetProject(repo){await this.mainTasks.forget(repo)}async discoverAdoptableWorktrees(repo){if(!repo)throw Error("discoverAdoptableWorktrees: repo is required");return this.worktreeCoordinator.discoverAdoptable(repo)}async adoptWorktree(input){if(!input.repo)throw Error("adoptWorktree: repo is required");if(!input.worktreePath)throw Error("adoptWorktree: worktreePath is required");return this.worktreeCoordinator.adopt(input)}requireTask(id){let task=this.store.get(id);if(!task)throw new TaskNotFoundError(String(id));return task}}
4
+ export{Orchestrator};
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{logDaemonInfo}from"./chunk-1cjd7h8p.js";import{resolveKobeSpawn,spawnDetachedDaemon,testDaemonResponds}from"./chunk-5bn91n19.js";import{isProcessAlive,stopDaemonProcess}from"./chunk-pdh5w4ht.js";import{readPidFile}from"./chunk-4wwx51m5.js";import{KobeDaemonClient}from"./chunk-79gqh5p2.js";import{defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath}from"./chunk-x760j10f.js";import{spawn}from"child_process";import{existsSync}from"fs";import{rename,rm}from"fs/promises";import{basename,delimiter,dirname,join,resolve}from"path";import{fileURLToPath}from"url";var PTY_HOST_START_ARGS=["pty-host"],PTY_HOST_NODE_BUNDLE="pty-host-node.mjs",PTY_HOST_NODE_DEV_CACHE="../../.cache/pty-host-node.mjs",PTY_HOST_NODE_ENTRY="../daemon/pty-host-node-entry.ts";function resolveNodeBinary(env=process.env,exists=existsSync,platform=process.platform){let dirs=(env.PATH??env.Path??"").split(delimiter).filter((dir)=>dir.length>0),suffixes=platform==="win32"?(env.PATHEXT??".EXE;.CMD;.BAT").split(";").filter((ext)=>ext.length>0):[""];for(let dir of dirs)for(let suffix of suffixes){let candidate=join(dir,`node${suffix}`);if(exists(candidate))return candidate}return null}async function bundleWithBun(entry,outFile,io){let{build,rename:move,discard}=io??{build:(config)=>Bun.build(config),rename,discard:(path)=>rm(path,{force:!0})},staging=`${outFile}.${process.pid}.tmp`,built=await build({entrypoints:[entry],outdir:dirname(staging),target:"node",format:"esm",naming:basename(staging),external:["node-pty"]});if(!built.success)return await discard(staging).catch(()=>{}),built;return await move(staging,outFile),built}async function resolveNodePtyHostSpawn(deps={}){let platform=deps.platform??process.platform;if(platform!=="win32")return null;let here=deps.moduleDir??dirname(fileURLToPath(import.meta.url)),exists=deps.exists??existsSync,bundle=deps.bundle??bundleWithBun,node=resolveNodeBinary(deps.env??process.env,exists,platform);if(!node)throw Error("Rove: the Windows PTY host runs under node, but no node was found on PATH. "+"Install Node.js (https://nodejs.org) and restart Rove \u2014 engine and terminal sessions cannot start without it.");let packaged=resolve(here,PTY_HOST_NODE_BUNDLE);if(exists(packaged))return[node,packaged];let entry=resolve(here,PTY_HOST_NODE_ENTRY);if(!exists(entry))throw Error(`Rove: no Windows PTY host found (looked for ${packaged} and ${entry})`);let cache=resolve(here,PTY_HOST_NODE_DEV_CACHE),built=await bundle(entry,cache);if(!built.success)throw Error(`Rove: could not build the Windows PTY host \u2014 ${built.logs.map(String).join("; ")}`);return[node,cache]}var BUSY_PTY_HOST_GRACE_MS=15000;async function liveChildCount(pid){try{let proc=spawn("/bin/ps",["-A","-o","ppid="],{stdio:["ignore","pipe","ignore"]});return(await new Promise((done)=>{let out="";proc.stdout.on("data",(chunk)=>{out+=String(chunk)}),proc.on("close",()=>done(out)),proc.on("error",()=>done(""))})).split(`
2
+ import{logDaemonInfo}from"./chunk-1cjd7h8p.js";import{resolveKobeSpawn,spawnDetachedDaemon,testDaemonResponds}from"./chunk-4502n1bk.js";import{isProcessAlive,stopDaemonProcess}from"./chunk-nm0pq5r6.js";import{readPidFile}from"./chunk-mqqnk8w7.js";import{KobeDaemonClient}from"./chunk-0wnfq5sx.js";import{defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath}from"./chunk-mcdv19rs.js";import{spawn}from"child_process";import{existsSync}from"fs";import{rename,rm}from"fs/promises";import{basename,delimiter,dirname,join,resolve}from"path";import{fileURLToPath}from"url";var PTY_HOST_START_ARGS=["pty-host"],PTY_HOST_NODE_BUNDLE="pty-host-node.mjs",PTY_HOST_NODE_DEV_CACHE="../../.cache/pty-host-node.mjs",PTY_HOST_NODE_ENTRY="../daemon/pty-host-node-entry.ts";function resolveNodeBinary(env=process.env,exists=existsSync,platform=process.platform){let dirs=(env.PATH??env.Path??"").split(delimiter).filter((dir)=>dir.length>0),suffixes=platform==="win32"?(env.PATHEXT??".EXE;.CMD;.BAT").split(";").filter((ext)=>ext.length>0):[""];for(let dir of dirs)for(let suffix of suffixes){let candidate=join(dir,`node${suffix}`);if(exists(candidate))return candidate}return null}async function bundleWithBun(entry,outFile,io){let{build,rename:move,discard}=io??{build:(config)=>Bun.build(config),rename,discard:(path)=>rm(path,{force:!0})},staging=`${outFile}.${process.pid}.tmp`,built=await build({entrypoints:[entry],outdir:dirname(staging),target:"node",format:"esm",naming:basename(staging),external:["node-pty"]});if(!built.success)return await discard(staging).catch(()=>{}),built;return await move(staging,outFile),built}async function resolveNodePtyHostSpawn(deps={}){let platform=deps.platform??process.platform;if(platform!=="win32")return null;let here=deps.moduleDir??dirname(fileURLToPath(import.meta.url)),exists=deps.exists??existsSync,bundle=deps.bundle??bundleWithBun,node=resolveNodeBinary(deps.env??process.env,exists,platform);if(!node)throw Error("Rove: the Windows PTY host runs under node, but no node was found on PATH. "+"Install Node.js (https://nodejs.org) and restart Rove \u2014 engine and terminal sessions cannot start without it.");let packaged=resolve(here,PTY_HOST_NODE_BUNDLE);if(exists(packaged))return[node,packaged];let entry=resolve(here,PTY_HOST_NODE_ENTRY);if(!exists(entry))throw Error(`Rove: no Windows PTY host found (looked for ${packaged} and ${entry})`);let cache=resolve(here,PTY_HOST_NODE_DEV_CACHE),built=await bundle(entry,cache);if(!built.success)throw Error(`Rove: could not build the Windows PTY host \u2014 ${built.logs.map(String).join("; ")}`);return[node,cache]}var BUSY_PTY_HOST_GRACE_MS=15000;async function liveChildCount(pid){try{let proc=spawn("/bin/ps",["-A","-o","ppid="],{stdio:["ignore","pipe","ignore"]});return(await new Promise((done)=>{let out="";proc.stdout.on("data",(chunk)=>{out+=String(chunk)}),proc.on("close",()=>done(out)),proc.on("error",()=>done(""))})).split(`
3
3
  `).filter((row)=>Number(row.trim())===pid).length}catch{return 0}}async function ensurePtyHostReachable(){let socketPath=defaultPtyHostSocketPath();if(await testDaemonResponds(socketPath))return socketPath;let hostPid=await readPidFile(defaultPtyHostPidPath());if(hostPid!==null&&hostPid!==process.pid&&isProcessAlive(hostPid)){let deadline2=Date.now()+BUSY_PTY_HOST_GRACE_MS;while(Date.now()<deadline2){if(await new Promise((resolveTimer)=>setTimeout(resolveTimer,250)),await testDaemonResponds(socketPath))return socketPath;if(!isProcessAlive(hostPid))break}if(isProcessAlive(hostPid)){let sessions=await liveChildCount(hostPid);if(sessions>0)throw Error(`rove: the pty host (pid ${hostPid}) is not answering but still holds ${sessions} live session(s) \u2014 refusing to restart it, which would kill every engine running in them. Inspect it with \`rove api pty-list\`, or kill ${hostPid} yourself once you have accepted losing those sessions.`)}}await stopDaemonProcess(socketPath,defaultPtyHostPidPath()).catch(()=>{});let[command,...args]=await resolveNodePtyHostSpawn()??resolveKobeSpawn(PTY_HOST_START_ARGS);spawnDetachedDaemon(command??"",args,process.env,defaultPtyHostLogPath());let deadline=Date.now()+5000;while(Date.now()<deadline){if(await testDaemonResponds(socketPath))return socketPath;await new Promise((resolveTimer)=>setTimeout(resolveTimer,100))}throw Error(`rove: pty host did not start (or stayed wedged) at ${socketPath}`)}async function sweepPtyHostSessions(liveTaskIds,homeDir){let client=new KobeDaemonClient(defaultPtyHostSocketPath(homeDir));try{await client.connect();let{sessions}=await client.request("pty.list"),currentTasks;for(let session of sessions){if(!currentTasks){let ids=liveTaskIds();if(ids===null)return;currentTasks=new Set(ids)}if(currentTasks.has(session.key.split("::")[0]??session.key))continue;if(!session.generation){logDaemonInfo("pty-sweep",`skipped ${session.key}: host has no session generation; restart it when sessions can be interrupted`);continue}await client.request("pty.kill",{key:session.key,expectedGeneration:session.generation}),currentTasks=void 0}}catch{}finally{client.close()}}async function ptyHostHasLiveSessions(homeDir){let client=new KobeDaemonClient(defaultPtyHostSocketPath(homeDir));try{await client.connect();let result=await client.request("pty.list");if(!Array.isArray(result.sessions)||result.sessions.some((s)=>typeof s.alive!=="boolean"))return null;return result.sessions.some((s)=>s.alive)}catch(err){if(err instanceof Error&&"code"in err&&(err.code==="ENOENT"||err.code==="ECONNREFUSED")){let pid=await readPidFile(defaultPtyHostPidPath(homeDir));return pid!==null&&isProcessAlive(pid)?null:!1}return null}finally{client.close()}}
4
4
  export{resolveNodeBinary,ensurePtyHostReachable,sweepPtyHostSessions,ptyHostHasLiveSessions};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{TaskDeletingError,deriveTitleFromPrompt}from"./chunk-aq912vvw.js";import{ComposerBusyError,awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp,sessionHasEngine,trustEngineWorktree}from"./chunk-ffgb1a1n.js";import{engineLaunchArgv,protocolEntry}from"./chunk-rkt1qjec.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{engineEntry}from"./chunk-7z9cqycv.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";var MAX_SESSIONS_SCANNED=8;function titleFromMessages(messages){let firstUser=messages.find((m)=>m.role==="user");if(!firstUser)return"";let text=firstUser.blocks.filter((b)=>b.type==="text").map((b)=>b.text).join(" "),title=deriveTitleFromPrompt(text);return title.length>0?Buffer.from(title,"utf8").toString("utf8"):title}async function deriveTitleFromSession(worktree,vendor=DEFAULT_TASK_VENDOR){if(!worktree)return"";let{history}=protocolEntry(vendor),ids=await history.listSessionIdsForWorktree(worktree);for(let sessionId of ids.slice(0,MAX_SESSIONS_SCANNED)){let title=titleFromMessages(await history.readHistory(sessionId));if(title)return title}return""}async function deriveTitleFromSessionId(vendor,sessionId){if(!sessionId)return"";try{return titleFromMessages(await protocolEntry(vendor).history.readHistory(sessionId))}catch{return""}}async function getTask(link,taskId){let{task}=await link.request("task.get",{taskId});return task}async function ensureTaskWorktree(link,taskId){let task=await getTask(link,taskId);if(task.deletion)throw new TaskDeletingError(taskId);if(task.worktreePath)return{task,worktreePath:task.worktreePath};let{worktreePath}=await link.request("task.ensureWorktree",{taskId});if(!worktreePath)throw Error(`task ${taskId} has no worktree`);return{task,worktreePath}}async function ensureTaskSessionAdapter(link,taskId){let{task,worktreePath}=await ensureTaskWorktree(link,taskId),launch=taskEngineLaunch(task,worktreePath,{kind:"repo-init"}),host=await ensureHostedSessionHost();try{if(!(await ensureHostedEngine(host.rpc,worktreePath,launch)).alive)throw Error(`failed to start hosted engine session for ${taskId}`);if(launch.firstMessage){let engineBin=engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort})[0];await pastePromptWhenEngineUp(host.rpc,launch.key,engineBin,launch.firstMessage,{initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs}).catch(()=>!1)}}finally{host.close()}return{session:launch.key,worktreePath}}async function startTaskSessionWithPromptAdapter(link,taskId,prompt){let{task,worktreePath}=await ensureTaskWorktree(link,taskId);await link.request("task.observeLanguage",{taskId,text:prompt}).catch(()=>{});let launch=taskEngineLaunch(task,worktreePath,{kind:"new-task",prompt}),host=await ensureHostedSessionHost();try{if(!(await ensureHostedEngine(host.rpc,worktreePath,launch)).alive)return{started:!1,error:"hosted session did not open"};let engineBin=engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort})[0],wait={initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs};if(launch.firstMessage){if(await pastePromptWhenEngineUp(host.rpc,launch.key,engineBin,launch.firstMessage,wait)!==null)return{started:!0};return{started:!1,error:await startFailureReason(host.rpc,launch.key)}}if(await awaitEngineProcess(host.rpc,launch.key,engineBin,wait)!==null)return{started:!0};return{started:!1,error:await startFailureReason(host.rpc,launch.key)}}finally{host.close()}}async function startFailureReason(rpc,key){let tail=await hostedSessionFailureLine(rpc,key),base="engine process never started";return tail?`engine process never started; last session output: ${tail}`:"engine process never started"}function taskEngineLaunch(task,worktreePath,promptIntent){return trustEngineWorktree(task.vendor,worktreePath),buildEngineSessionLaunch({task:{id:task.id,kind:task.kind,vendor:task.vendor,repo:task.repo},worktreePath,shell:resolveLoginShell({fallback:"/bin/zsh"}),argv:engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort}),promptIntent})}async function deliverPromptToLiveEngineAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return!1;try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0]);if(!key)return!1;if(!await sessionHasEngine(sessions.find((s)=>s.key===key)?.pid,engineArgv))return!1;let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})!==null}catch(err){if(err instanceof ComposerBusyError)throw err;return!1}finally{host.close()}}function tabIdFromHostedKey(key){return key.split("::")[1]??"tab-1"}async function deliverPromptToLiveEngineDetailedAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0]);if(!key)return{outcome:"no-session"};if(!await sessionHasEngine(sessions.find((s)=>s.key===key)?.pid,engineArgv))return{outcome:"no-engine",tabId:tabIdFromHostedKey(key)};let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:tabIdFromHostedKey(key)}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:tabIdFromHostedKey(key),layer:err.layer};throw err}}catch{return{outcome:"no-session"}}finally{host.close()}}async function deliverPromptToLiveEngineTabDetailedAdapter(target,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let key=`${target.id}::${target.tabId}`,sessions;try{sessions=await listHostedSessions(host.rpc)}catch{return{outcome:"no-session"}}let session=sessions.find((candidate)=>candidate.alive&&candidate.key===key);if(!session)return{outcome:"no-session"};let engineArgv=engineLaunchArgv({command:target.command,vendor:target.vendor});if(!await sessionHasEngine(session.pid,engineArgv))return{outcome:"no-engine",tabId:target.tabId};let manifest=target.vendor?engineEntry(target.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:target.tabId}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:target.tabId,layer:err.layer};throw err}}finally{host.close()}}async function tearDownTaskSessionAdapter(taskId){let host=await openHostedSessionHost();if(!host)return;try{await killHostedSessions(host.rpc,hostedTaskKeys(await listHostedSessions(host.rpc),taskId))}catch{}finally{host.close()}}
2
+ import{TaskDeletingError,deriveTitleFromPrompt}from"./chunk-r05r01nv.js";import{ComposerBusyError,awaitEngineProcess,buildEngineSessionLaunch,deliverToHostedKey,ensureHostedEngine,ensureHostedSessionHost,findHostedEngineKey,hostedSessionFailureLine,hostedTaskKeys,killHostedSessions,listHostedSessions,openHostedSessionHost,pastePromptWhenEngineUp,sessionHasEngine,trustEngineWorktree}from"./chunk-mhzv94cg.js";import{engineLaunchArgv,protocolEntry}from"./chunk-ptjc5mtc.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{engineEntry}from"./chunk-4gjr08g0.js";import{DEFAULT_TASK_VENDOR}from"./chunk-xy8be792.js";var MAX_SESSIONS_SCANNED=8;function titleFromMessages(messages){let firstUser=messages.find((m)=>m.role==="user");if(!firstUser)return"";let text=firstUser.blocks.filter((b)=>b.type==="text").map((b)=>b.text).join(" "),title=deriveTitleFromPrompt(text);return title.length>0?Buffer.from(title,"utf8").toString("utf8"):title}async function deriveTitleFromSession(worktree,vendor=DEFAULT_TASK_VENDOR){if(!worktree)return"";let{history}=protocolEntry(vendor),ids=await history.listSessionIdsForWorktree(worktree);for(let sessionId of ids.slice(0,MAX_SESSIONS_SCANNED)){let title=titleFromMessages(await history.readHistory(sessionId));if(title)return title}return""}async function deriveTitleFromSessionId(vendor,sessionId){if(!sessionId)return"";try{return titleFromMessages(await protocolEntry(vendor).history.readHistory(sessionId))}catch{return""}}async function getTask(link,taskId){let{task}=await link.request("task.get",{taskId});return task}async function ensureTaskWorktree(link,taskId){let task=await getTask(link,taskId);if(task.deletion)throw new TaskDeletingError(taskId);if(task.worktreePath)return{task,worktreePath:task.worktreePath};let{worktreePath}=await link.request("task.ensureWorktree",{taskId});if(!worktreePath)throw Error(`task ${taskId} has no worktree`);return{task,worktreePath}}async function ensureTaskSessionAdapter(link,taskId){let{task,worktreePath}=await ensureTaskWorktree(link,taskId),launch=taskEngineLaunch(task,worktreePath,{kind:"repo-init"}),host=await ensureHostedSessionHost();try{if(!(await ensureHostedEngine(host.rpc,worktreePath,launch)).alive)throw Error(`failed to start hosted engine session for ${taskId}`);if(launch.firstMessage){let engineBin=engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort})[0];await pastePromptWhenEngineUp(host.rpc,launch.key,engineBin,launch.firstMessage,{initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs}).catch(()=>!1)}}finally{host.close()}return{session:launch.key,worktreePath}}async function startTaskSessionWithPromptAdapter(link,taskId,prompt){let{task,worktreePath}=await ensureTaskWorktree(link,taskId);await link.request("task.observeLanguage",{taskId,text:prompt}).catch(()=>{});let launch=taskEngineLaunch(task,worktreePath,{kind:"new-task",prompt}),host=await ensureHostedSessionHost();try{if(!(await ensureHostedEngine(host.rpc,worktreePath,launch)).alive)return{started:!1,error:"hosted session did not open"};let engineBin=engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort})[0],wait={initMarkerPath:launch.initMarkerPath,initTimeoutMs:launch.initTimeoutMs};if(launch.firstMessage){if(await pastePromptWhenEngineUp(host.rpc,launch.key,engineBin,launch.firstMessage,wait)!==null)return{started:!0};return{started:!1,error:await startFailureReason(host.rpc,launch.key)}}if(await awaitEngineProcess(host.rpc,launch.key,engineBin,wait)!==null)return{started:!0};return{started:!1,error:await startFailureReason(host.rpc,launch.key)}}finally{host.close()}}async function startFailureReason(rpc,key){let tail=await hostedSessionFailureLine(rpc,key),base="engine process never started";return tail?`engine process never started; last session output: ${tail}`:"engine process never started"}function taskEngineLaunch(task,worktreePath,promptIntent){return trustEngineWorktree(task.vendor,worktreePath),buildEngineSessionLaunch({task:{id:task.id,kind:task.kind,vendor:task.vendor,repo:task.repo},worktreePath,shell:resolveLoginShell({fallback:"/bin/zsh"}),argv:engineLaunchArgv({command:task.command,vendor:task.vendor,effort:task.modelEffort}),promptIntent})}async function deliverPromptToLiveEngineAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return!1;try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0]);if(!key)return!1;if(!await sessionHasEngine(sessions.find((s)=>s.key===key)?.pid,engineArgv))return!1;let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})!==null}catch(err){if(err instanceof ComposerBusyError)throw err;return!1}finally{host.close()}}function tabIdFromHostedKey(key){return key.split("::")[1]??"tab-1"}async function deliverPromptToLiveEngineDetailedAdapter(task,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let sessions=await listHostedSessions(host.rpc),engineArgv=engineLaunchArgv({command:task.command,vendor:task.vendor}),key=findHostedEngineKey(sessions,task.id,engineArgv[0]);if(!key)return{outcome:"no-session"};if(!await sessionHasEngine(sessions.find((s)=>s.key===key)?.pid,engineArgv))return{outcome:"no-engine",tabId:tabIdFromHostedKey(key)};let manifest=task.vendor?engineEntry(task.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:tabIdFromHostedKey(key)}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:tabIdFromHostedKey(key),layer:err.layer};throw err}}catch{return{outcome:"no-session"}}finally{host.close()}}async function deliverPromptToLiveEngineTabDetailedAdapter(target,prompt){let host=await openHostedSessionHost();if(!host)return{outcome:"no-session"};try{let key=`${target.id}::${target.tabId}`,sessions;try{sessions=await listHostedSessions(host.rpc)}catch{return{outcome:"no-session"}}let session=sessions.find((candidate)=>candidate.alive&&candidate.key===key);if(!session)return{outcome:"no-session"};let engineArgv=engineLaunchArgv({command:target.command,vendor:target.vendor});if(!await sessionHasEngine(session.pid,engineArgv))return{outcome:"no-engine",tabId:target.tabId};let manifest=target.vendor?engineEntry(target.vendor).screenManifest:void 0;try{return await deliverToHostedKey(host.rpc,key,prompt,{screenManifest:manifest})===null?{outcome:"no-session"}:{outcome:"delivered",tabId:target.tabId}}catch(err){if(err instanceof ComposerBusyError)return{outcome:"busy",tabId:target.tabId,layer:err.layer};throw err}}finally{host.close()}}async function tearDownTaskSessionAdapter(taskId){let host=await openHostedSessionHost();if(!host)return;try{await killHostedSessions(host.rpc,hostedTaskKeys(await listHostedSessions(host.rpc),taskId))}catch{}finally{host.close()}}
3
3
  export{deriveTitleFromSession,deriveTitleFromSessionId,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,tearDownTaskSessionAdapter};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{describeAccount,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-yshnare4.js";import{t}from"./chunk-p1d3ag8b.js";import{createInterface}from"readline";function daemonRestartFix(cliName,reason){return{kind:"run",id:"daemon-restart",label:t(`doctor.fix.${reason}`),command:[cliName,"daemon","restart"],why:t("doctor.fix.daemonRestartWhy")}}function skillInstallFix(installCommand,stale){return{kind:"run",id:"skill-install",label:t(stale?"doctor.fix.skillStale":"doctor.fix.skillMissing"),command:installCommand.split(" "),why:t("doctor.fix.skillInstallWhy")}}function resetManualFix(cliName,reason){return{kind:"manual",id:`reset:${reason}`,label:t(`doctor.fix.${reason}`),action:`${cliName} reset`,why:t("doctor.fix.resetWhy")}}function killOrphansManualFix(cliName,count){return{kind:"manual",id:"kill-orphans",label:t("doctor.fix.orphans",{count}),action:`${cliName} doctor --kill-orphans`,why:t("doctor.fix.orphansWhy")}}function engineTabsManualFix(){return{kind:"manual",id:"engine-tabs",label:t("doctor.fix.engineTabs"),action:t("doctor.fix.engineTabsAction"),why:t("doctor.fix.engineTabsWhy")}}function reinstallManualFix(){return{kind:"manual",id:"reinstall",label:t("doctor.fix.staleInstall"),action:t("doctor.fix.staleInstallAction"),why:t("doctor.fix.staleInstallWhy")}}function spawnHelperFix(paths){return{kind:"run",id:"spawn-helper-chmod",label:t("doctor.fix.spawnHelper"),command:["chmod","755",...paths],why:t("doctor.fix.spawnHelperWhy")}}function humanOnlyFix(reason,vars){return{kind:"manual",id:reason,label:t(`doctor.fix.${reason}`),action:t(`doctor.fix.${reason}Action`,vars),why:t("doctor.fix.humanOnlyWhy")}}function noEngineFix(signedOut){return signedOut.length>0?humanOnlyFix("noEngineLogin",{list:signedOut.join(", ")}):humanOnlyFix("noEngine")}function noEngineAction(signedOut){return signedOut.length>0?t("doctor.fix.noEngineLoginAction",{list:signedOut.join(", ")}):t("doctor.fix.noEngineAction")}function dedupeFixes(fixes){let seen=new Set;return fixes.filter((fix)=>{if(seen.has(fix.id))return!1;return seen.add(fix.id),!0})}async function applyFixes(collected,rt){let fixes=dedupeFixes(collected);if(fixes.length===0){rt.out(""),rt.out(t("doctor.fix.none"));return}let runnable=fixes.filter((fix)=>fix.kind==="run");if(runnable.length>0){rt.out(""),rt.out(t("doctor.fix.header"));for(let fix of runnable){if(rt.out(` ${fix.label}`),rt.out(` ${t("doctor.fix.willRun",{command:fix.command.join(" ")})}`),rt.out(` ${fix.why}`),!rt.interactive)continue;if(!await rt.confirm(` ${t("doctor.fix.confirmPrompt")}`)){rt.out(` ${t("doctor.fix.skipped")}`);continue}let code=await rt.exec(fix.command);rt.out(code===0?` ${t("doctor.fix.done")}`:` ${t("doctor.fix.failed",{code})}`)}if(!rt.interactive)rt.out(` ${t("doctor.fix.nonInteractive")}`)}let manual=fixes.filter((fix)=>fix.kind==="manual");if(manual.length>0){rt.out(""),rt.out(t("doctor.fix.manualHeader"));for(let fix of manual)rt.out(` ${fix.label}`),rt.out(` \u2192 ${fix.action}`),rt.out(` ${fix.why}`)}}async function confirmTty(question){let readline=createInterface({input:process.stdin,output:process.stdout});try{let answer=await new Promise((resolve)=>readline.question(question,resolve));return answer.trim().toLowerCase()==="y"||answer.trim().toLowerCase()==="yes"}finally{readline.close()}}async function execInherited(command){try{return await Bun.spawn([...command],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited}catch{return 127}}function defaultFixRuntime(){return{confirm:confirmTty,exec:execInherited,out:(line)=>console.log(line),interactive:process.stdin.isTTY===!0}}async function probeGit(){try{let proc=Bun.spawn(["git","--version"],{stdin:"ignore",stdout:"pipe",stderr:"ignore"}),text=(await new Response(proc.stdout).text()).trim();if(await proc.exited===0&&text)return{line:`git: \u2713 ${text}`,found:!0}}catch{}return{line:"git: \u2717 not found on PATH",found:!1}}function binaryLabel(binary){return binary.found?`\u2713 ${binary.path}`:`\u2717 ${binary.error}`}async function probeEngines(){let statuses=await detectEngineStatuses(await probeableEngineIds()),lines=["engines:"];for(let status of statuses){let account=describeAccount(status.account),name=`${status.vendor.padEnd(7)} `;if(lines.push(` ${name}${binaryLabel(status.binary)}${status.binary.found?` \u2014 ${account}`:""}`),status.accountError)lines.push(` \u26A0 ${status.accountError}`)}let{usable,signedOut}=summarizeEngines(statuses);return{lines,anyUsable:usable.length>0,signedOut}}async function checkOnboardingEnv(){let[git,engines]=await Promise.all([probeGit(),probeEngines()]);return{git,engines}}
2
+ import{describeAccount,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-exggdhpt.js";import{t}from"./chunk-nss70xwr.js";import{createInterface}from"readline";function daemonRestartFix(cliName,reason){return{kind:"run",id:"daemon-restart",label:t(`doctor.fix.${reason}`),command:[cliName,"daemon","restart"],why:t("doctor.fix.daemonRestartWhy")}}function skillInstallFix(installCommand,stale){return{kind:"run",id:"skill-install",label:t(stale?"doctor.fix.skillStale":"doctor.fix.skillMissing"),command:installCommand.split(" "),why:t("doctor.fix.skillInstallWhy")}}function resetManualFix(cliName,reason){return{kind:"manual",id:`reset:${reason}`,label:t(`doctor.fix.${reason}`),action:`${cliName} reset`,why:t("doctor.fix.resetWhy")}}function killOrphansManualFix(cliName,count){return{kind:"manual",id:"kill-orphans",label:t("doctor.fix.orphans",{count}),action:`${cliName} doctor --kill-orphans`,why:t("doctor.fix.orphansWhy")}}function engineTabsManualFix(){return{kind:"manual",id:"engine-tabs",label:t("doctor.fix.engineTabs"),action:t("doctor.fix.engineTabsAction"),why:t("doctor.fix.engineTabsWhy")}}function reinstallManualFix(){return{kind:"manual",id:"reinstall",label:t("doctor.fix.staleInstall"),action:t("doctor.fix.staleInstallAction"),why:t("doctor.fix.staleInstallWhy")}}function spawnHelperFix(paths){return{kind:"run",id:"spawn-helper-chmod",label:t("doctor.fix.spawnHelper"),command:["chmod","755",...paths],why:t("doctor.fix.spawnHelperWhy")}}function humanOnlyFix(reason,vars){return{kind:"manual",id:reason,label:t(`doctor.fix.${reason}`),action:t(`doctor.fix.${reason}Action`,vars),why:t("doctor.fix.humanOnlyWhy")}}function noEngineFix(signedOut){return signedOut.length>0?humanOnlyFix("noEngineLogin",{list:signedOut.join(", ")}):humanOnlyFix("noEngine")}function noEngineAction(signedOut){return signedOut.length>0?t("doctor.fix.noEngineLoginAction",{list:signedOut.join(", ")}):t("doctor.fix.noEngineAction")}function dedupeFixes(fixes){let seen=new Set;return fixes.filter((fix)=>{if(seen.has(fix.id))return!1;return seen.add(fix.id),!0})}async function applyFixes(collected,rt){let fixes=dedupeFixes(collected);if(fixes.length===0){rt.out(""),rt.out(t("doctor.fix.none"));return}let runnable=fixes.filter((fix)=>fix.kind==="run");if(runnable.length>0){rt.out(""),rt.out(t("doctor.fix.header"));for(let fix of runnable){if(rt.out(` ${fix.label}`),rt.out(` ${t("doctor.fix.willRun",{command:fix.command.join(" ")})}`),rt.out(` ${fix.why}`),!rt.interactive)continue;if(!await rt.confirm(` ${t("doctor.fix.confirmPrompt")}`)){rt.out(` ${t("doctor.fix.skipped")}`);continue}let code=await rt.exec(fix.command);rt.out(code===0?` ${t("doctor.fix.done")}`:` ${t("doctor.fix.failed",{code})}`)}if(!rt.interactive)rt.out(` ${t("doctor.fix.nonInteractive")}`)}let manual=fixes.filter((fix)=>fix.kind==="manual");if(manual.length>0){rt.out(""),rt.out(t("doctor.fix.manualHeader"));for(let fix of manual)rt.out(` ${fix.label}`),rt.out(` \u2192 ${fix.action}`),rt.out(` ${fix.why}`)}}async function confirmTty(question){let readline=createInterface({input:process.stdin,output:process.stdout});try{let answer=await new Promise((resolve)=>readline.question(question,resolve));return answer.trim().toLowerCase()==="y"||answer.trim().toLowerCase()==="yes"}finally{readline.close()}}async function execInherited(command){try{return await Bun.spawn([...command],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited}catch{return 127}}function defaultFixRuntime(){return{confirm:confirmTty,exec:execInherited,out:(line)=>console.log(line),interactive:process.stdin.isTTY===!0}}async function probeGit(){try{let proc=Bun.spawn(["git","--version"],{stdin:"ignore",stdout:"pipe",stderr:"ignore"}),text=(await new Response(proc.stdout).text()).trim();if(await proc.exited===0&&text)return{line:`git: \u2713 ${text}`,found:!0}}catch{}return{line:"git: \u2717 not found on PATH",found:!1}}function binaryLabel(binary){return binary.found?`\u2713 ${binary.path}`:`\u2717 ${binary.error}`}async function probeEngines(){let statuses=await detectEngineStatuses(await probeableEngineIds()),lines=["engines:"];for(let status of statuses){let account=describeAccount(status.account),name=`${status.vendor.padEnd(7)} `;if(lines.push(` ${name}${binaryLabel(status.binary)}${status.binary.found?` \u2014 ${account}`:""}`),status.accountError)lines.push(` \u26A0 ${status.accountError}`)}let{usable,signedOut}=summarizeEngines(statuses);return{lines,anyUsable:usable.length>0,signedOut}}async function checkOnboardingEnv(){let[git,engines]=await Promise.all([probeGit(),probeEngines()]);return{git,engines}}
3
3
  export{daemonRestartFix,skillInstallFix,resetManualFix,killOrphansManualFix,engineTabsManualFix,reinstallManualFix,spawnHelperFix,humanOnlyFix,noEngineFix,noEngineAction,applyFixes,defaultFixRuntime,probeGit,probeEngines,checkOnboardingEnv};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{binaryAvailable,resolveEditorCommand}from"./chunk-gc25wht3.js";import"./chunk-6xppe9bj.js";import"./chunk-2fypr41w.js";import"./chunk-deejtpcr.js";import"./chunk-rsqx358z.js";import"./chunk-a3a9gdc4.js";import"./chunk-s8eh3cf1.js";import{kvStatePath}from"./chunk-07k2njwk.js";import{activeCliName}from"./chunk-ef11h2am.js";import"./chunk-8ddjfc2v.js";import"./chunk-cb2fpajx.js";import"./chunk-3bfm4hrs.js";import"./chunk-wqfp8d9w.js";import{existsSync,mkdirSync,writeFileSync}from"fs";import{dirname}from"path";var CLI_NAME=activeCliName();function printUsage(out){out.write([`Usage: ${CLI_NAME} config [--path]`,"","Open Rove's user config (state.json \u2014 theme, locale, engine + editor prefs)","in your editor. The editor is your configured one (Settings \u2192 General \u2192","Editor); left on Auto it is $VISUAL / $EDITOR, else the first of","nvim / vim / emacs / nano.","Rove re-reads the file on its next launch.","","Options:"," --path Print the config file path and exit (don't open an editor)"," -h, --help Print this help",""].join(`
2
+ import{binaryAvailable,resolveEditorCommand}from"./chunk-aak5ttgt.js";import"./chunk-6xppe9bj.js";import"./chunk-2fypr41w.js";import"./chunk-kt1ppyje.js";import"./chunk-5v893waj.js";import"./chunk-a3a9gdc4.js";import"./chunk-3wj69b0a.js";import{kvStatePath}from"./chunk-ch9b1d5y.js";import{activeCliName}from"./chunk-p7s4xwgx.js";import"./chunk-4pmd0mxp.js";import"./chunk-g56kvet6.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";import{existsSync,mkdirSync,writeFileSync}from"fs";import{dirname}from"path";var CLI_NAME=activeCliName();function printUsage(out){out.write([`Usage: ${CLI_NAME} config [--path]`,"","Open Rove's user config (state.json \u2014 theme, locale, engine + editor prefs)","in your editor. The editor is your configured one (Settings \u2192 General \u2192","Editor); left on Auto it is $VISUAL / $EDITOR, else the first of","nvim / vim / emacs / nano.","Rove re-reads the file on its next launch.","","Options:"," --path Print the config file path and exit (don't open an editor)"," -h, --help Print this help",""].join(`
3
3
  `))}async function runConfigSubcommand(argv=[]){if(argv.some((a)=>a==="-h"||a==="--help"||a==="help")){printUsage(process.stdout);return}let path=kvStatePath();if(argv.some((a)=>a==="--path"||a==="path")){console.log(path);return}let unknown=argv.find((a)=>a.length>0);if(unknown!==void 0)process.stderr.write(`${CLI_NAME} config: unexpected argument "${unknown}"
4
4
  `),printUsage(process.stderr),process.exit(2);if(!existsSync(path))mkdirSync(dirname(path),{recursive:!0}),writeFileSync(path,`{}
5
5
  `);let resolved=await resolveEditorCommand(path);if(!resolved||!await binaryAvailable(resolved.bin))process.stderr.write(`${CLI_NAME} config: no editor found \u2014 set $EDITOR (or Settings \u2192 General \u2192 Editor), or edit directly:
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{defaultClientLogPath,defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath,defaultPtyExitsPath,defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,defaultWebTokenPath,fitSocketPath,isWindowsPipePath,legacyDaemonPidPath,legacyDaemonSocketPath,legacyPtyHostPidPath,legacyPtyHostSocketPath,legacyRuntimePath,resolveDaemonHomeDir,shortHomeTag,windowsPipePath}from"./chunk-x760j10f.js";import"./chunk-3bfm4hrs.js";import"./chunk-wqfp8d9w.js";export{windowsPipePath,shortHomeTag,resolveDaemonHomeDir,legacyRuntimePath,legacyPtyHostSocketPath,legacyPtyHostPidPath,legacyDaemonSocketPath,legacyDaemonPidPath,isWindowsPipePath,fitSocketPath,defaultWebTokenPath,defaultPtyHostSocketPath,defaultPtyHostPidPath,defaultPtyHostLogPath,defaultPtyFreezeDir,defaultPtyExitsPath,defaultDaemonSocketPath,defaultDaemonPidPath,defaultDaemonLogPath,defaultClientLogPath};
2
+ import{defaultClientLogPath,defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath,defaultPtyExitsPath,defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,defaultWebTokenPath,fitSocketPath,isWindowsPipePath,legacyDaemonPidPath,legacyDaemonSocketPath,legacyPtyHostPidPath,legacyPtyHostSocketPath,legacyRuntimePath,resolveDaemonHomeDir,shortHomeTag,windowsPipePath}from"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{windowsPipePath,shortHomeTag,resolveDaemonHomeDir,legacyRuntimePath,legacyPtyHostSocketPath,legacyPtyHostPidPath,legacyDaemonSocketPath,legacyDaemonPidPath,isWindowsPipePath,fitSocketPath,defaultWebTokenPath,defaultPtyHostSocketPath,defaultPtyHostPidPath,defaultPtyHostLogPath,defaultPtyFreezeDir,defaultPtyExitsPath,defaultDaemonSocketPath,defaultDaemonPidPath,defaultDaemonLogPath,defaultClientLogPath};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{ENGINE_NOT_OBSERVED_REASON,ENGINE_START_POLL_MS,ENGINE_START_PROBE_MS,deferOrThrow,deliverHostedPrompt,deliverToKey,ensurePtyHost,findEngineKey,isTaskKey,killTaskSessions,listSessions,listSessionsOrNull,openPtyHost,outcomeFields,resolveComposerManifest,taskKeys}from"./chunk-ngnrz33z.js";import"./chunk-qch6g9za.js";import"./chunk-mhzv94cg.js";import"./chunk-ds9qf1w1.js";import"./chunk-bkba9c4n.js";import"./chunk-g2advs8t.js";import"./chunk-wdhcrcre.js";import"./chunk-ptjc5mtc.js";import"./chunk-7q67dz4c.js";import"./chunk-1cjd7h8p.js";import"./chunk-b99tf0jr.js";import"./chunk-t27t2x9b.js";import"./chunk-hape5vwj.js";import"./chunk-de751t37.js";import"./chunk-fm5s7njg.js";import"./chunk-nss70xwr.js";import"./chunk-fd2zhddn.js";import"./chunk-sdyzxayr.js";import"./chunk-zqfbyq0a.js";import"./chunk-jvxh93nz.js";import"./chunk-4502n1bk.js";import"./chunk-nm0pq5r6.js";import"./chunk-mqqnk8w7.js";import"./chunk-0wnfq5sx.js";import"./chunk-7j5372wb.js";import"./chunk-mnqxgvyb.js";import"./chunk-n7n12868.js";import"./chunk-4gjr08g0.js";import"./chunk-sfv15era.js";import"./chunk-w7zv47mp.js";import"./chunk-gwcneg6c.js";import"./chunk-25hxhtdr.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-kt1ppyje.js";import"./chunk-5v893waj.js";import"./chunk-axfn4f28.js";import"./chunk-xy8be792.js";import"./chunk-a3a9gdc4.js";import"./chunk-2brn8e1y.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-bq3fyc0p.js";import"./chunk-p7s4xwgx.js";import"./chunk-4pmd0mxp.js";import"./chunk-g56kvet6.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{taskKeys,resolveComposerManifest,outcomeFields,openPtyHost,listSessionsOrNull,listSessions,killTaskSessions,isTaskKey,findEngineKey,ensurePtyHost,deliverToKey,deliverHostedPrompt,deferOrThrow,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{API_SCHEMA_VERSION,API_VERBS,RETIRED_VERBS,VERBS,VERB_GROUPS,VerbArgs,apiUsage,buildCountPlan,defaultApiRuntime,deliverPrompt,findVerb,fullSchema,parseAgentsSpec,parseFlags,schemaIndex,takeIdentityWarning,validateAgainstSpec,verbHelp,verbSchema}from"./chunk-9k5p5852.js";import{ensurePluginEnginesLoaded}from"./chunk-v9p6gxm0.js";import{openDaemonSession}from"./chunk-pxtx1gcf.js";import"./chunk-8qb8kksk.js";import"./chunk-aq912vvw.js";import"./chunk-d393z1mj.js";import"./chunk-qkehg2c1.js";import"./chunk-55xkvzvw.js";import"./chunk-4tzgma89.js";import{ApiError,splitDaemonCode}from"./chunk-snzh4n0v.js";import"./chunk-4y2vsnhs.js";import"./chunk-ffgb1a1n.js";import"./chunk-37gnmm2m.js";import"./chunk-bkba9c4n.js";import"./chunk-g2advs8t.js";import"./chunk-e8493db0.js";import"./chunk-rkt1qjec.js";import"./chunk-7q67dz4c.js";import"./chunk-1cjd7h8p.js";import"./chunk-b99tf0jr.js";import"./chunk-z1e1bsv5.js";import"./chunk-hape5vwj.js";import"./chunk-2z90jxcn.js";import"./chunk-tt0fde40.js";import"./chunk-p1d3ag8b.js";import"./chunk-q3fc7t7p.js";import"./chunk-sdyzxayr.js";import"./chunk-b9h2ywc7.js";import"./chunk-jvxh93nz.js";import"./chunk-5bn91n19.js";import"./chunk-pdh5w4ht.js";import"./chunk-4wwx51m5.js";import"./chunk-79gqh5p2.js";import"./chunk-3ztek08w.js";import"./chunk-kwe61yx7.js";import"./chunk-g5nz190n.js";import"./chunk-7z9cqycv.js";import"./chunk-ea1r26pa.js";import"./chunk-w7zv47mp.js";import"./chunk-gwcneg6c.js";import"./chunk-9zb2wkfr.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-deejtpcr.js";import"./chunk-rsqx358z.js";import"./chunk-nywh3yb9.js";import"./chunk-xy8be792.js";import"./chunk-a3a9gdc4.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-s8eh3cf1.js";import"./chunk-07k2njwk.js";import"./chunk-bq3fyc0p.js";import"./chunk-ef11h2am.js";import"./chunk-8ddjfc2v.js";import"./chunk-cb2fpajx.js";import"./chunk-grh6dvfv.js";import"./chunk-pw6yfj10.js";import"./chunk-rxvbm4vt.js";import"./chunk-x760j10f.js";import"./chunk-3bfm4hrs.js";import"./chunk-wqfp8d9w.js";function emit(value,pretty){let warning=takeIdentityWarning(),payload=warning&&value&&typeof value==="object"&&!Array.isArray(value)?{...value,identityWarning:warning}:value,text=pretty?JSON.stringify(payload,null,2):JSON.stringify(payload);process.stdout.write(`${text}
2
+ import{API_SCHEMA_VERSION,API_VERBS,RETIRED_VERBS,VERBS,VERB_GROUPS,VerbArgs,apiUsage,buildCountPlan,defaultApiRuntime,deliverPrompt,findVerb,fullSchema,parseAgentsSpec,parseFlags,schemaIndex,takeIdentityWarning,validateAgainstSpec,verbHelp,verbSchema}from"./chunk-8kj2s16b.js";import{ensurePluginEnginesLoaded}from"./chunk-ntt7gy5a.js";import{openDaemonSession}from"./chunk-1aqmmea7.js";import"./chunk-9ypg30c1.js";import"./chunk-r05r01nv.js";import"./chunk-6pt23vas.js";import"./chunk-38272eqv.js";import"./chunk-5f80ggc3.js";import"./chunk-qkehg2c1.js";import"./chunk-98zhyhpz.js";import"./chunk-msr1xtay.js";import{ApiError,splitDaemonCode}from"./chunk-ngnrz33z.js";import"./chunk-qch6g9za.js";import"./chunk-mhzv94cg.js";import"./chunk-ds9qf1w1.js";import"./chunk-bkba9c4n.js";import"./chunk-g2advs8t.js";import"./chunk-wdhcrcre.js";import"./chunk-ptjc5mtc.js";import"./chunk-7q67dz4c.js";import"./chunk-1cjd7h8p.js";import"./chunk-b99tf0jr.js";import"./chunk-t27t2x9b.js";import"./chunk-hape5vwj.js";import"./chunk-de751t37.js";import"./chunk-fm5s7njg.js";import"./chunk-nss70xwr.js";import"./chunk-fd2zhddn.js";import"./chunk-sdyzxayr.js";import"./chunk-zqfbyq0a.js";import"./chunk-jvxh93nz.js";import"./chunk-4502n1bk.js";import"./chunk-nm0pq5r6.js";import"./chunk-mqqnk8w7.js";import"./chunk-0wnfq5sx.js";import"./chunk-7j5372wb.js";import"./chunk-mnqxgvyb.js";import"./chunk-n7n12868.js";import"./chunk-4gjr08g0.js";import"./chunk-sfv15era.js";import"./chunk-w7zv47mp.js";import"./chunk-gwcneg6c.js";import"./chunk-25hxhtdr.js";import"./chunk-7jkf3tvr.js";import"./chunk-2fypr41w.js";import"./chunk-kt1ppyje.js";import"./chunk-5v893waj.js";import"./chunk-axfn4f28.js";import"./chunk-xy8be792.js";import"./chunk-a3a9gdc4.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-3wj69b0a.js";import"./chunk-ch9b1d5y.js";import"./chunk-bq3fyc0p.js";import"./chunk-p7s4xwgx.js";import"./chunk-4pmd0mxp.js";import"./chunk-g56kvet6.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-rxvbm4vt.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";function emit(value,pretty){let warning=takeIdentityWarning(),payload=warning&&value&&typeof value==="object"&&!Array.isArray(value)?{...value,identityWarning:warning}:value,text=pretty?JSON.stringify(payload,null,2):JSON.stringify(payload);process.stdout.write(`${text}
3
3
  `)}function fail(message,code,exitCode=1,data){process.stderr.write(`${JSON.stringify({error:{message,code,...data}})}
4
4
  `),process.exit(exitCode)}function makeContext(verb,flags,client,runtime){return{args:new VerbArgs(verb,flags),client,runtime}}var SCHEMA_STEP={hint:"list every valid verb + flag as JSON, then retry with a real verb",nextCommandArgs:["api","schema"]};function unknownVerbError(verbName){let retired=RETIRED_VERBS[verbName];if(retired)return new ApiError(`unknown verb: ${verbName} (removed)`,"UNKNOWN_VERB",{hint:retired.hint,nextCommandArgs:[...retired.nextCommandArgs]});return new ApiError(`unknown verb: ${verbName}`,"BAD_VERB",SCHEMA_STEP)}function toApiError(err){if(err instanceof ApiError)return err;let message=errorMessage(err);if(/task not found/i.test(message))return new ApiError(message,"TASK_NOT_FOUND",{hint:"that task id does not exist (deleted or mistyped) \u2014 list live tasks and retry with a real id",nextCommandArgs:["api","list"]});if(/unknown daemon request:/i.test(message))return versionSkewError(message);let coded=splitDaemonCode(message);if(coded)return new ApiError(coded.rest,coded.code);return new ApiError(message,"RPC_ERROR")}function versionSkewError(message){return new ApiError(message,"DAEMON_VERSION_SKEW",{hint:"the running daemon is a different build than this CLI, so it does not serve this verb \u2014 restart the daemon to pick up this build, then retry (if the verb is gone for good, `rove api schema` lists what this daemon actually serves)",nextCommandArgs:["daemon","restart"]})}async function invokeVerb(verbName,argv,deps){let verb=findVerb(verbName);if(!verb)throw unknownVerbError(verbName);let booleanFlags=new Set(verb.flags.filter((f)=>f.type==="bool").map((f)=>f.name)),parsed=parseFlags(argv,booleanFlags);validateAgainstSpec(verb,parsed.flags);try{return await verb.handler(makeContext(verb,parsed.flags,deps.client,deps.runtime??defaultApiRuntime))}catch(err){throw toApiError(err)}}async function runApiSubcommand(argv){let[verbName,...rest]=argv;if(!verbName||verbName==="--help"||verbName==="-h"||verbName==="help"){if(!verbName)fail(apiUsage(),"MISSING_VERB",2);process.stdout.write(`${apiUsage()}
5
5
  `);return}ensurePluginEnginesLoaded();let verb=findVerb(verbName);if(!verb){let err=unknownVerbError(verbName);fail(`${err.message}
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{ENGINE_EXIT_BANNER,engineExitCodeFromTail,plainTail,readPtyExitRecords,readPtyExitStore,recordEngineExit,recordPtyExit}from"./chunk-yk2ha5yj.js";import"./chunk-rxvbm4vt.js";import"./chunk-x760j10f.js";import"./chunk-3bfm4hrs.js";import"./chunk-wqfp8d9w.js";export{recordPtyExit,recordEngineExit,readPtyExitStore,readPtyExitRecords,plainTail,engineExitCodeFromTail,ENGINE_EXIT_BANNER};
2
+ import{ENGINE_EXIT_BANNER,engineExitCodeFromTail,plainTail,readPtyExitRecords,readPtyExitStore,recordEngineExit,recordPtyExit}from"./chunk-nyv7a76k.js";import"./chunk-rxvbm4vt.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{recordPtyExit,recordEngineExit,readPtyExitStore,readPtyExitRecords,plainTail,engineExitCodeFromTail,ENGINE_EXIT_BANNER};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{embeddedTerminalEnv}from"./chunk-ef39ym8f.js";import{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{DEFAULT_TERMINAL_COLORS,foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors}from"./chunk-7q67dz4c.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-1cjd7h8p.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{ensureOwnerOnlyStateDir,listenOnUnixSocket}from"./chunk-4wwx51m5.js";import{DAEMON_PROTOCOL_VERSION,frameToLine}from"./chunk-3ztek08w.js";import"./chunk-kwe61yx7.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import{recordPtyExit}from"./chunk-yk2ha5yj.js";import"./chunk-rxvbm4vt.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,isWindowsPipePath,legacyPtyHostPidPath,legacyPtyHostSocketPath,resolveDaemonHomeDir}from"./chunk-x760j10f.js";import{COMPAT_STATE_DIR_BASENAME,ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-3bfm4hrs.js";import"./chunk-wqfp8d9w.js";import{readFileSync as readFileSync2}from"fs";import{mkdir,unlink,writeFile}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync,symlinkSync}from"fs";import{homedir}from"os";import{join}from"path";var PTY_HOST_DATA_ENTRIES=["pty-exits.json","pty-sessions"];function lstatIfExists(path){try{return lstatSync(path)}catch{return}}function migrateLegacyPtyHostData(homeDir=readRoveHomeDirEnv()??homedir()){let canonicalDir=join(homeDir,ROVE_STATE_DIR_BASENAME),legacyDir=join(homeDir,COMPAT_STATE_DIR_BASENAME);if(canonicalDir===legacyDir)return[];let moved=[];for(let name of PTY_HOST_DATA_ENTRIES){let canonical=join(canonicalDir,name),legacy=join(legacyDir,name);try{if(existsSync(canonical))continue;let stat=lstatIfExists(legacy);if(!stat||stat.isSymbolicLink())continue;mkdirSync(canonicalDir,{recursive:!0}),renameSync(legacy,canonical),moved.push(name);try{symlinkSync(canonical,legacy)}catch{}}catch{}}return moved}import{randomUUID}from"crypto";import{chmodSync,mkdirSync as mkdirSync2,readFileSync,readdirSync,renameSync as renameSync2,rmSync,statSync,writeFileSync}from"fs";import{join as join2}from"path";import{StringDecoder}from"string_decoder";var FREEZE_VERSION=1;function freezeSession(session,now=new Date){return{v:FREEZE_VERSION,key:session.key,cwd:session.cwd,command:[...session.command],cols:session.cols,rows:session.rows,title:session.title,totalBytes:session.totalBytes,exit:session.exit,...session.lastHumanWriteMs?{lastHumanWriteMs:session.lastHumanWriteMs}:{},ringB64:Buffer.concat(session.chunks).toString("base64"),updatedAt:now.toISOString()}}function thawRing(record,cap){let ring;try{ring=Buffer.from(record.ringB64,"base64")}catch{return null}let trimmed=ring.byteLength>cap?ring.subarray(ring.byteLength-cap):ring;return{chunks:trimmed.byteLength>0?[trimmed]:[],bytes:trimmed.byteLength}}function thawSession(record,cap){let ring=thawRing(record,cap);if(!ring)return null;return{key:record.key,generation:randomUUID(),cwd:record.cwd,proc:null,alive:!1,chunks:[...ring.chunks],bytes:ring.bytes,totalBytes:Math.max(record.totalBytes,ring.bytes),cols:record.cols,rows:record.rows,command:record.command,title:record.title,titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:DEFAULT_TERMINAL_COLORS,sinks:new Map,parked:!1,parkedScreenBytes:0,exit:record.exit,restored:!0,lastFreezeAtMs:0,lastHumanWriteMs:record.lastHumanWriteMs??0}}function recordFile(dir,key){return join2(dir,`${encodeURIComponent(key)}.json`)}function parseRecord(raw){try{let parsed=JSON.parse(raw);if(parsed?.v!==FREEZE_VERSION)return null;if(typeof parsed.key!=="string"||parsed.key.length===0)return null;if(parsed.key.startsWith("::"))return null;if(typeof parsed.cwd!=="string"||!Array.isArray(parsed.command))return null;if(typeof parsed.ringB64!=="string"||typeof parsed.totalBytes!=="number")return null;return parsed}catch{return null}}var FREEZE_TTL_MS=1209600000,FREEZE_RESTORE_MAX_BYTES=67108864;function updatedAtMs(record){let t=Date.parse(record.updatedAt);return Number.isFinite(t)?t:0}function loadFrozenSessions(dir=defaultPtyFreezeDir(),now=Date.now(),report){let names;try{names=readdirSync(dir)}catch{return[]}let entries=[];for(let name of names){if(!name.endsWith(".json"))continue;try{let st=statSync(join2(dir,name));entries.push({name,size:st.size,mtimeMs:st.mtimeMs})}catch{}}entries.sort((a,b)=>b.mtimeMs-a.mtimeMs);let kept=[],stale=[],bytesRead=0,deferred=0,unreadable=0;for(let entry of entries){if(now-entry.mtimeMs>FREEZE_TTL_MS){stale.push(entry.name);continue}if(bytesRead+entry.size>FREEZE_RESTORE_MAX_BYTES&&kept.length>0){deferred++;continue}let record=null;try{record=parseRecord(readFileSync(join2(dir,entry.name),"utf8"))}catch{}if(bytesRead+=entry.size,!record){unreadable++;continue}if(now-updatedAtMs(record)>FREEZE_TTL_MS)stale.push(entry.name);else kept.push(record)}for(let name of stale)try{rmSync(join2(dir,name),{force:!0})}catch{}return kept.sort((a,b)=>updatedAtMs(b)-updatedAtMs(a)),report?.({restored:kept.length,bytesRead,deferred,expired:stale.length,unreadable}),kept}var DIR_MODE=448,FILE_MODE=384;function tightenExistingPermissions(dir){try{chmodSync(dir,DIR_MODE)}catch{}let names;try{names=readdirSync(dir)}catch{return}for(let name of names){if(!name.endsWith(".json"))continue;try{chmodSync(join2(dir,name),FILE_MODE)}catch{}}}function fileFreezeSink(dir=defaultPtyFreezeDir()){return tightenExistingPermissions(dir),{save(record){try{mkdirSync2(dir,{recursive:!0,mode:DIR_MODE});let target=recordFile(dir,record.key),staging=`${target}.${process.pid}.tmp`;writeFileSync(staging,JSON.stringify(record),{encoding:"utf8",mode:FILE_MODE}),renameSync2(staging,target)}catch{}},drop(key){try{rmSync(recordFile(dir,key),{force:!0})}catch{}}}}function clearFrozenSessions(dir=defaultPtyFreezeDir()){try{rmSync(dir,{recursive:!0,force:!0})}catch{}}import{randomUUID as randomUUID3}from"crypto";function bunTerminalDriver(spawn){let spawnTerminal=spawn??((argv,options)=>Bun.spawn(argv,options));return(request)=>{let proc=spawnTerminal([...request.argv],{cwd:request.cwd,env:request.env,terminal:{cols:request.cols,rows:request.rows,name:"xterm-256color",data:(_terminal,data)=>request.onData(data)}});return{pid:proc.pid,exited:proc.exited.then(()=>({code:proc.exitCode??null,signal:proc.signalCode??null}),()=>({code:null,signal:null})),write:(data)=>proc.terminal?.write(data),resize:(cols,rows)=>proc.terminal?.resize(cols,rows),close:()=>proc.terminal?.close(),kill:(signal)=>proc.kill(signal)}}}import{randomUUID as randomUUID2}from"crypto";import{StringDecoder as StringDecoder2}from"string_decoder";function freshSessionState(key,spec,argv){return{key,generation:randomUUID2(),cwd:spec.cwd,proc:null,alive:!0,chunks:[],bytes:0,totalBytes:0,cols:spec.cols??80,rows:spec.rows??24,command:argv,title:"",titleCarry:"",titleDecoder:new StringDecoder2("utf8"),colorQueryCarry:"",defaultColors:parseTerminalDefaultColors(spec.defaultColors)??DEFAULT_TERMINAL_COLORS,sinks:new Map,parked:!1,parkedScreenBytes:0,exit:null,restored:!1,lastFreezeAtMs:0,frozenTotalBytes:0,lastHumanWriteMs:0}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,totalBytes:s.totalBytes,parked:s.parked,parkedScreenBytes:s.parkedScreenBytes,exit:s.exit,restored:s.restored||void 0}}function describeExit(exit){if(exit?.signal)return` (signal ${exit.signal})`;if(exit&&exit.code!==null)return` (code ${exit.code})`;return" (cause unknown)"}function ringTail(chunks,bytes,maxBytes){let skip=Math.max(0,bytes-maxBytes),seen=0,parts=[];for(let chunk of chunks){if(seen+chunk.byteLength>skip)parts.push(seen>=skip?chunk:chunk.subarray(skip-seen));seen+=chunk.byteLength}return Buffer.concat(parts).toString("utf8")}function hostStats(sessions,perSessionCap,parkRestoreDeltas,parkRestoreFallbacks){let ringBytes=0,count=0,parkedSessions=0,parkedScreenBytes=0;for(let session of sessions)if(count++,ringBytes+=session.bytes,session.parked)parkedSessions++,parkedScreenBytes+=session.parkedScreenBytes;return{ringBytes,ringCapacityBytes:count*perSessionCap,parkedSessions,parkedScreenBytes,parkRestoreDeltas,parkRestoreFallbacks}}var OSC_TITLE_RE=/\x1b\][02];([^\x07\x1b]*)(?:\x07|\x1b\\)/g,TITLE_CARRY_CAP=1024;function titleCarryFrom(rest){let osc=rest.lastIndexOf("\x1B]");if(osc!==-1)return rest.slice(osc,osc+TITLE_CARRY_CAP);return rest.endsWith("\x1B")?"\x1B":""}function foldOscTitle(prevCarry,chunkText){let text=prevCarry+chunkText,title=null,end=0;OSC_TITLE_RE.lastIndex=0;for(let match=OSC_TITLE_RE.exec(text);match;match=OSC_TITLE_RE.exec(text))title=match[1]??"",end=match.index+match[0].length;return{title,carry:titleCarryFrom(text.slice(end))}}function scanOscTitle(session,buf){let{title,carry}=foldOscTitle(session.titleCarry,session.titleDecoder.write(buf));if(title!==null)session.title=title;session.titleCarry=carry}function peekRing(session,sinceOffset,humanWriteQuietMs){if(!session)return{exists:!1,alive:!1,pid:null,offset:0,data:"",sinceValid:!1,exit:null};let windowStart=session.totalBytes-session.bytes,buf=Buffer.concat(session.chunks),sinceValid=!1;if(sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes)buf=buf.subarray(sinceOffset-windowStart),sinceValid=!0;return{exists:!0,alive:session.alive,pid:session.proc?.pid??null,offset:session.totalBytes,data:buf.toString("base64"),sinceValid,exit:session.exit??null,...session.lastHumanWriteMs&&session.lastHumanWriteMs>0?{lastHumanWriteMs:session.lastHumanWriteMs,humanWriteQuietMs}:{}}}async function settledWithin(exited,ms){let timer,settled=await Promise.race([exited.then(()=>!0,()=>!0),new Promise((resolve)=>{timer=setTimeout(()=>resolve(!1),ms)})]);if(timer)clearTimeout(timer);return settled}function signalProcessGroup(pid,signal,fallback,platform=process.platform,onSignal){if(platform!=="win32"&&pid>1)try{process.kill(-pid,signal),onSignal?.(`sent ${signal} to process group -${pid}`);return}catch{}try{fallback(),onSignal?.(`sent ${signal} to pid ${pid} (per-process fallback)`)}catch{}}var TERMINATION_GRACE_MS=500;async function terminatePtyChild(proc,onSettled,onSignal){if(signalProcessGroup(proc.pid,"SIGTERM",()=>proc.kill("SIGTERM"),process.platform,onSignal),!await settledWithin(proc.exited,TERMINATION_GRACE_MS))signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS);onSettled()}class PtyChildController{deps;constructor(deps){this.deps=deps}spawn(key,spec,spare=!1){let argv=spec.command&&spec.command.length>0?[...spec.command]:[spec.shell??resolveLoginShell()],session=freshSessionState(key,spec,argv);if(this.startChild(session),session.alive)this.deps.log?.("pty",`spawned ${argv[0]} for ${key} (pid ${session.proc?.pid})`),this.deps.onSessionStart?.(spare);return session}startChild(session){session.generation=randomUUID3();try{session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...session.command],cwd:session.cwd,env:embeddedTerminalEnv(process.env,{TERM:"xterm-256color",COLUMNS:String(session.cols),LINES:String(session.rows),BASH_SILENCE_DEPRECATION_WARNING:"1",KOBE_TERMINAL_PTY:"1"}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0,session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session))}catch(err){session.alive=!1,this.deps.log?.("pty",`spawn failed for ${session.key}: ${err instanceof Error?err.message:String(err)}`)}}async endChild(session){if(!session.alive)return;let proc=session.proc;if(!proc){this.markExited(session);return}await terminatePtyChild(proc,()=>this.markExited(session),(line)=>this.deps.log?.("pty-signal",`${session.key}: ${line}`))}markExited(session,exit){if(!session.alive)return;session.alive=!1;let sessionExit={code:exit?.code??null,signal:exit?.signal??null,at:new Date().toISOString()};session.exit=sessionExit;try{session.proc?.close()}catch{}this.deps.onExit?.(session,sessionExit)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,buf.toString("latin1"));session.colorQueryCarry=colorQueries.carry;for(let slot of colorQueries.slots)try{session.proc?.write(formatDefaultColorReply(slot,session.defaultColors))}catch{}scanOscTitle(session,buf),session.chunks.push(buf),session.bytes+=buf.byteLength,session.totalBytes+=buf.byteLength;while(session.bytes>this.deps.scrollbackCap&&session.chunks.length>1){let dropped=session.chunks.shift();if(dropped)session.bytes-=dropped.byteLength}this.deps.onOutput?.(session,buf)}}function shouldFreeze(session,now){let appended=session.totalBytes-(session.frozenTotalBytes??0);if(appended<=0)return!1;let since=now-session.lastFreezeAtMs;if(since<5000)return!1;return appended>=65536||since>=60000}class WarmSpare{deps;spare=null;constructor(deps){this.deps=deps}warm(cwd,shell,cols=80,rows=24){let argv0=shell??resolveLoginShell();if(this.spare?.alive&&this.spare.cwd===cwd&&this.spare.command[0]===argv0)return;let old=this.spare;if(this.spare=null,old)this.deps.endChild(old);let session=this.deps.spawn("::spare",{cwd,command:[argv0],cols,rows},!0);this.spare=session.alive?session:null}adopt(key,spec){let spare=this.spare;if(!spare?.alive||spare.cwd!==spec.cwd)return null;let want=spec.command&&spec.command.length>0?spec.command:[spec.shell??resolveLoginShell()];if(want.length!==1||want[0]!==spare.command[0])return null;this.spare=null,spare.key=key,spare.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??spare.defaultColors;let cols=spec.cols??spare.cols,rows=spec.rows??spare.rows;if(spare.cols!==cols||spare.rows!==rows){spare.cols=cols,spare.rows=rows;try{spare.proc?.resize(cols,rows)}catch{return this.deps.markExited(spare),null}}return this.deps.log?.("pty",`adopted warm shell for ${key} (pid ${spare.proc?.pid})`),this.deps.onSessionStart?.(),this.warm(spec.cwd,spare.command[0],cols,rows),spare}async end(){let spare=this.spare;if(this.spare=null,spare)await this.deps.endChild(spare)}}var LOGGED_WRITE_BYTES=1024,DEFAULT_SCROLLBACK_CAP=524288,EXIT_TAIL_BYTES=16384,DEFAULT_HUMAN_WRITE_QUIET_MS=1e4;function resolveHumanWriteQuietMs(){let raw=process.env.KOBE_PTY_HUMAN_WRITE_QUIET_MS;if(raw===void 0)return DEFAULT_HUMAN_WRITE_QUIET_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_HUMAN_WRITE_QUIET_MS}class PtyHost{sessions=new Map;opts;scrollbackCap;humanWriteQuietMs;parkRestoreDeltas=0;parkRestoreFallbacks=0;childController;warmSpare;constructor(opts={}){this.opts=opts,this.scrollbackCap=opts.scrollbackCap??DEFAULT_SCROLLBACK_CAP,this.humanWriteQuietMs=opts.humanWriteQuietMs??resolveHumanWriteQuietMs(),this.childController=new PtyChildController({driver:opts.driver,scrollbackCap:this.scrollbackCap,onSessionStart:(spare)=>{if(!spare)this.opts.onSessionStart?.()},onOutput:(session,data)=>{if(session.sinks.size===0){this.maybeFreeze(session);return}let frame={type:"event",name:"pty.data",payload:{key:session.key,data:data.toString("base64")}};for(let sink of session.sinks.values())sink(frame);this.maybeFreeze(session)},onExit:(session,exit)=>{let frame={type:"event",name:"pty.exit",payload:{key:session.key,pid:session.proc?.pid??null,...exit}};for(let sink of session.sinks.values())sink(frame);if(this.opts.log?.("pty",`session ${session.key} exited${describeExit(exit)}`),this.maybeFreeze(session,!0),!session.closedByRequest)try{this.opts.onSessionExit?.({key:session.key,pid:session.proc?.pid??null,exit,tail:ringTail(session.chunks,session.bytes,EXIT_TAIL_BYTES)})}catch{}this.opts.onSessionEnd?.()},log:(event,message)=>this.opts.log?.(event,message)}),this.warmSpare=new WarmSpare({spawn:(key,spec,spare)=>this.childController.spawn(key,spec,spare),endChild:(session)=>this.childController.endChild(session),markExited:(session)=>this.childController.markExited(session),log:(event,message)=>this.opts.log?.(event,message),onSessionStart:()=>this.opts.onSessionStart?.()})}open(key,spec,token,sink,sinceOffset,sincePid){let session=this.sessions.get(key),created=!1,respawned=!1;if(!session)created=!0,session=this.warmSpare.adopt(key,spec)??this.childController.spawn(key,spec),this.sessions.set(key,session);else if(!session.alive&&session.restored)this.respawn(session,spec),respawned=session.alive;else if(session.alive&&spec.cols!==void 0&&spec.rows!==void 0&&(session.cols!==spec.cols||session.rows!==spec.rows))this.resize(key,spec.cols,spec.rows);let defaultColors=parseTerminalDefaultColors(spec.defaultColors);if(defaultColors)session.defaultColors=defaultColors;session.sinks.set(token,sink),session.parked=!1,session.parkedScreenBytes=0;let windowStart=session.totalBytes-session.bytes,replay=Buffer.concat(session.chunks),sinceValid=!1;if(!created&&sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes&&sincePid!==void 0&&sincePid===session.proc?.pid)replay=replay.subarray(sinceOffset-windowStart),sinceValid=!0;if(sinceOffset!==void 0&&sincePid!==void 0)if(sinceValid)this.parkRestoreDeltas++;else this.parkRestoreFallbacks++;return{replay:replay.toString("base64"),alive:session.alive,pid:session.proc?.pid??null,created,respawned,offset:session.totalBytes,sinceValid}}warm(cwd,shell,cols=80,rows=24){this.warmSpare.warm(cwd,shell,cols,rows)}write(key,data,client){let session=this.sessions.get(key);if(!session?.alive||data.length===0)return;if(client!==void 0&&session.sinks.has(client))session.lastHumanWriteMs=Date.now();if(data.length>=LOGGED_WRITE_BYTES)this.opts.log?.("pty",`wrote ${data.length} bytes to ${key}`);try{session.proc?.write(data)}catch(error){this.opts.log?.("pty",`write failed on ${key} (${data.length} bytes): ${String(error)}`)}}resize(key,cols,rows){let session=this.sessions.get(key);if(!session?.alive)return;session.cols=cols,session.rows=rows;try{session.proc?.resize(cols,rows)}catch{}}killIfGeneration(key,expectedGeneration){let session=this.sessions.get(key);if(!session)return{killed:!1,reason:"missing-session"};if(session.generation!==expectedGeneration)return{killed:!1,reason:"generation-mismatch"};return this.kill(key),{killed:!0}}kill(key){let session=this.sessions.get(key);if(!session)return Promise.resolve();return this.sessions.delete(key),session.closedByRequest=!0,this.opts.freeze?.drop(key),this.childController.endChild(session)}rename(from,to){let session=this.sessions.get(from);if(!session||from===to||this.sessions.has(to))return!1;return this.sessions.delete(from),session.key=to,this.sessions.set(to,session),this.opts.freeze?.drop(from),this.maybeFreeze(session,!0),this.opts.log?.("pty",`renamed session ${from} \u2192 ${to}`),!0}detach(key,token,parked=!1,parkedScreenBytes=0){let session=this.sessions.get(key);if(!session)return;session.sinks.delete(token),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(!session.sinks.delete(token))continue;this.applyParkedOnDetach(session)}}applyParkedOnDetach(session,parked=!1,parkedScreenBytes=0){if(session.sinks.size!==0)return;session.parked=parked,session.parkedScreenBytes=parked?Math.max(0,parkedScreenBytes):0}list(){return Array.from(this.sessions.values(),(s)=>sessionInfo(s))}peek(key,sinceOffset){return peekRing(this.sessions.get(key),sinceOffset,this.humanWriteQuietMs)}stats(){return hostStats(this.sessions.values(),this.scrollbackCap,this.parkRestoreDeltas,this.parkRestoreFallbacks)}sweepTasks(liveTaskIds){for(let key of Array.from(this.sessions.keys())){let taskId=key.split("::")[0]??key;if(!liveTaskIds.has(taskId))this.kill(key)}}async killAll(){let sessions=Array.from(this.sessions.keys(),(key)=>this.kill(key));sessions.push(this.warmSpare.end()),await Promise.all(sessions)}async shutdown(){this.flushFrozen();let endings=Array.from(this.sessions.values(),(session)=>this.childController.endChild(session));endings.push(this.warmSpare.end()),await Promise.all(endings)}flushFrozen(){for(let session of this.sessions.values())this.maybeFreeze(session,!0)}restoreFrozen(records){let restoredCount=0;for(let record of records){if(this.sessions.has(record.key))continue;let session=thawSession(record,this.scrollbackCap);if(!session)continue;this.sessions.set(record.key,session),restoredCount++}if(restoredCount>0)this.opts.log?.("pty",`restored ${restoredCount} frozen session(s) from disk`);return restoredCount}respawn(session,spec){if(session.restored=!1,session.exit=null,spec.command&&spec.command.length>0)session.command=[...spec.command];if(session.cols=spec.cols??session.cols,session.rows=spec.rows??session.rows,session.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??session.defaultColors,this.childController.startChild(session),!session.alive)return;this.opts.log?.("pty",`respawned restored session ${session.key} (pid ${session.proc?.pid})`),this.opts.onSessionStart?.()}maybeFreeze(session,force=!1){let freeze=this.opts.freeze;if(!freeze||session.key.startsWith("::"))return;if(session.closedByRequest)return;let now=Date.now();if(!force&&!shouldFreeze(session,now))return;session.lastFreezeAtMs=now,session.frozenTotalBytes=session.totalBytes,freeze.save(freezeSession(session))}liveCount(){let n=0;for(let session of this.sessions.values())if(session.alive)n++;return n}}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.KOBE_PTY_MAX_LIFETIME_MS;if(raw===void 0)return null;let n=Number(raw);return Number.isFinite(n)&&n>0?n:null}function resolveIdleExitMs(){let raw=process.env.KOBE_PTY_IDLE_EXIT_MS;if(raw===void 0)return DEFAULT_IDLE_EXIT_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_IDLE_EXIT_MS}async function startPtyHostServer(options={}){migrateLegacyPtyHostData();let socketPath=options.socketPath??defaultPtyHostSocketPath(),pidPath=options.pidPath??defaultPtyHostPidPath(),freezeDir=options.freezeDir??defaultPtyFreezeDir(),idleExitMs=options.idleExitMs||resolveIdleExitMs(),orphanCheckMs=options.orphanCheckMs||DEFAULT_ORPHAN_CHECK_MS,maxLifetimeMs=options.maxLifetimeMs??resolveMaxLifetimeMs(),bootedAtMs=Date.now(),log=options.log??(()=>{}),clients=new Set,stopping=!1,wipeFreezeOnStop=!1,idleTimer=null,cancelIdle=()=>{if(idleTimer)clearTimeout(idleTimer);idleTimer=null},armIdle=()=>{if(stopping)return;cancelIdle(),idleTimer=setTimeout(()=>{if(stopping||ptys.liveCount()>0)return;log("idle",`no live sessions for ${idleExitMs}ms \u2014 exiting`),stop()},idleExitMs)},orphaned=()=>{if(maxLifetimeMs!==null&&Date.now()-bootedAtMs>=maxLifetimeMs)return`exceeded its ${maxLifetimeMs}ms lifetime ceiling`;let owner;try{owner=readFileSync2(pidPath,"utf8").trim()}catch{return`pidfile ${pidPath} is gone`}let pid=Number.parseInt(owner,10);if(pid===process.pid)return null;return Number.isInteger(pid)?`pidfile ${pidPath} now names pid ${pid}`:`pidfile ${pidPath} is unreadable`},orphanTimer=setInterval(()=>{if(stopping)return;let reason=orphaned();if(!reason)return;log("orphan",`${reason} \u2014 exiting rather than outliving my owner`),stop()},orphanCheckMs);orphanTimer.unref?.();let ptys=new PtyHost({onSessionStart:cancelIdle,onSessionEnd:()=>{if(ptys.liveCount()===0)armIdle()},onSessionExit:(info)=>{try{recordPtyExit(info)}catch(err){log("pty",`exit record write failed for ${info.key}: ${err instanceof Error?err.message:String(err)}`)}},freeze:fileFreezeSink(freezeDir),driver:options.driver,log});ptys.restoreFrozen(loadFrozenSessions(freezeDir,Date.now(),(s)=>{let mib=(bytes)=>`${Math.round(bytes/1048576)}MB`,notes=[`restored ${s.restored} (${mib(s.bytesRead)})`];if(s.deferred>0)notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);if(s.expired>0)notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS/86400000}-day TTL`);if(s.unreadable>0)notes.push(`${s.unreadable} unreadable`);log("freeze",notes.join(", "))}));let pipeSocket=isWindowsPipePath(socketPath);if(await ensureOwnerOnlyStateDir(resolveDaemonHomeDir()),!pipeSocket)await mkdir(dirname(socketPath),{recursive:!0});await mkdir(dirname(pidPath),{recursive:!0});let server=createServer((socket)=>{let client={socket,writer:new ClientWriter(socket,{onOverflow:()=>{log("backpressure","disconnecting PTY client whose critical queue exceeded 8MiB"),socket.destroy()}})};clients.add(client);let receiver=new LineReceiver;socket.on("data",(chunk)=>{if(!receiver.push(chunk,(line)=>handleLine(client,line)))log("framing","disconnecting PTY client whose request exceeded 8MiB"),socket.destroy()}),socket.on("error",()=>{}),socket.on("close",()=>{clients.delete(client),ptys.detachClient(client)})}),api={socketPath,pidPath,async close(){if(stopping)return;if(stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown(),wipeFreezeOnStop)clearFrozenSessions(freezeDir);for(let client of Array.from(clients))client.socket.destroy();if(await new Promise((resolve)=>server.close(()=>resolve())),!pipeSocket)await unlink(socketPath).catch(()=>{});await unlink(pidPath).catch(()=>{})}};async function stop(){await api.close().catch((err)=>logDaemonError("pty-host-shutdown",err)),options.onStop?.()}function dispatch(req,client){switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.open":{let payload=objectPayload(req.payload);return ptys.open(requireString(payload,"key"),{cwd:requireString(payload,"cwd"),command:Array.isArray(payload.command)?payload.command.filter((c)=>typeof c==="string"):void 0,shell:typeof payload.shell==="string"?payload.shell:void 0,cols:typeof payload.cols==="number"?payload.cols:void 0,rows:typeof payload.rows==="number"?payload.rows:void 0,defaultColors:parseTerminalDefaultColors(payload.defaultColors)??void 0},client,(frame)=>writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0)}case"pty.write":{let payload=objectPayload(req.payload);return ptys.write(requireString(payload,"key"),typeof payload.data==="string"?payload.data:"",client),{}}case"pty.resize":{let payload=objectPayload(req.payload);return ptys.resize(requireString(payload,"key"),typeof payload.cols==="number"?payload.cols:80,typeof payload.rows==="number"?payload.rows:24),{}}case"pty.kill":{let payload=objectPayload(req.payload),key=requireString(payload,"key");if("expectedGeneration"in payload)return ptys.killIfGeneration(key,requireString(payload,"expectedGeneration"));return ptys.kill(key),{}}case"pty.rename":{let payload=objectPayload(req.payload);return{renamed:ptys.rename(requireString(payload,"from"),requireString(payload,"to"))}}case"pty.detach":{let payload=objectPayload(req.payload);ptys.detach(requireString(payload,"key"),client,payload.parked===!0,typeof payload.parkedScreenBytes==="number"?payload.parkedScreenBytes:0)}return{};case"pty.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),stats:ptys.stats()};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0)}case"pty.warm":{let payload=objectPayload(req.payload);return ptys.warm(requireString(payload,"cwd"),typeof payload.shell==="string"?payload.shell:void 0,typeof payload.cols==="number"?payload.cols:void 0,typeof payload.rows==="number"?payload.rows:void 0),{}}case"pty.sweep":{let payload=objectPayload(req.payload),ids=Array.isArray(payload.liveTaskIds)?payload.liveTaskIds.filter((id)=>typeof id==="string"):[];return ptys.sweepTasks(new Set(ids)),{}}case"daemon.stop":return wipeFreezeOnStop=!0,setTimeout(()=>void stop(),0).unref(),{};default:throw Error(`unknown pty-host request: ${req.name}`)}}function handleLine(client,line){if(line.trim().length>0){let frame=null;try{frame=JSON.parse(line)}catch{writeFrame(client,{type:"response",id:"parse-error",error:{message:"malformed frame"}})}if(frame)if(frame.type!=="request")writeFrame(client,{type:"response",id:"parse-error",error:{message:"requests only"}});else try{writeFrame(client,{type:"response",id:frame.id,name:frame.name,payload:dispatch(frame,client)})}catch(err){writeFrame(client,{type:"response",id:frame.id,name:frame.name,error:{message:err instanceof Error?err.message:String(err)}})}}}if(await listenOnUnixSocket(server,socketPath),await writeFile(pidPath,`${process.pid}
2
+ import{embeddedTerminalEnv}from"./chunk-ef39ym8f.js";import{ClientWriter,LineReceiver,linkLegacyRuntimePath,objectPayload,requireString}from"./chunk-rz8zs7j8.js";import{DEFAULT_TERMINAL_COLORS,foldDefaultColorQueries,formatDefaultColorReply,parseTerminalDefaultColors}from"./chunk-7q67dz4c.js";import{installDaemonCrashHandlers,logDaemonError}from"./chunk-1cjd7h8p.js";import{resolveLoginShell}from"./chunk-b99tf0jr.js";import{ensureOwnerOnlyStateDir,listenOnUnixSocket}from"./chunk-mqqnk8w7.js";import{DAEMON_PROTOCOL_VERSION,frameToLine}from"./chunk-7j5372wb.js";import"./chunk-mnqxgvyb.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import{recordPtyExit}from"./chunk-nyv7a76k.js";import"./chunk-rxvbm4vt.js";import{defaultPtyFreezeDir,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath,isWindowsPipePath,legacyPtyHostPidPath,legacyPtyHostSocketPath,resolveDaemonHomeDir}from"./chunk-mcdv19rs.js";import{COMPAT_STATE_DIR_BASENAME,ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";import{readFileSync as readFileSync2}from"fs";import{mkdir,unlink,writeFile}from"fs/promises";import{createServer}from"net";import{dirname}from"path";import{existsSync,lstatSync,mkdirSync,renameSync,symlinkSync}from"fs";import{homedir}from"os";import{join}from"path";var PTY_HOST_DATA_ENTRIES=["pty-exits.json","pty-sessions"];function lstatIfExists(path){try{return lstatSync(path)}catch{return}}function migrateLegacyPtyHostData(homeDir=readRoveHomeDirEnv()??homedir()){let canonicalDir=join(homeDir,ROVE_STATE_DIR_BASENAME),legacyDir=join(homeDir,COMPAT_STATE_DIR_BASENAME);if(canonicalDir===legacyDir)return[];let moved=[];for(let name of PTY_HOST_DATA_ENTRIES){let canonical=join(canonicalDir,name),legacy=join(legacyDir,name);try{if(existsSync(canonical))continue;let stat=lstatIfExists(legacy);if(!stat||stat.isSymbolicLink())continue;mkdirSync(canonicalDir,{recursive:!0}),renameSync(legacy,canonical),moved.push(name);try{symlinkSync(canonical,legacy)}catch{}}catch{}}return moved}import{randomUUID}from"crypto";import{chmodSync,mkdirSync as mkdirSync2,readFileSync,readdirSync,renameSync as renameSync2,rmSync,statSync,writeFileSync}from"fs";import{join as join2}from"path";import{StringDecoder}from"string_decoder";var FREEZE_VERSION=1;function freezeSession(session,now=new Date){return{v:FREEZE_VERSION,key:session.key,cwd:session.cwd,command:[...session.command],cols:session.cols,rows:session.rows,title:session.title,totalBytes:session.totalBytes,exit:session.exit,...session.lastHumanWriteMs?{lastHumanWriteMs:session.lastHumanWriteMs}:{},ringB64:Buffer.concat(session.chunks).toString("base64"),updatedAt:now.toISOString()}}function thawRing(record,cap){let ring;try{ring=Buffer.from(record.ringB64,"base64")}catch{return null}let trimmed=ring.byteLength>cap?ring.subarray(ring.byteLength-cap):ring;return{chunks:trimmed.byteLength>0?[trimmed]:[],bytes:trimmed.byteLength}}function thawSession(record,cap){let ring=thawRing(record,cap);if(!ring)return null;return{key:record.key,generation:randomUUID(),cwd:record.cwd,proc:null,alive:!1,chunks:[...ring.chunks],bytes:ring.bytes,totalBytes:Math.max(record.totalBytes,ring.bytes),cols:record.cols,rows:record.rows,command:record.command,title:record.title,titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:DEFAULT_TERMINAL_COLORS,sinks:new Map,parked:!1,parkedScreenBytes:0,exit:record.exit,restored:!0,lastFreezeAtMs:0,lastHumanWriteMs:record.lastHumanWriteMs??0}}function recordFile(dir,key){return join2(dir,`${encodeURIComponent(key)}.json`)}function parseRecord(raw){try{let parsed=JSON.parse(raw);if(parsed?.v!==FREEZE_VERSION)return null;if(typeof parsed.key!=="string"||parsed.key.length===0)return null;if(parsed.key.startsWith("::"))return null;if(typeof parsed.cwd!=="string"||!Array.isArray(parsed.command))return null;if(typeof parsed.ringB64!=="string"||typeof parsed.totalBytes!=="number")return null;return parsed}catch{return null}}var FREEZE_TTL_MS=1209600000,FREEZE_RESTORE_MAX_BYTES=67108864;function updatedAtMs(record){let t=Date.parse(record.updatedAt);return Number.isFinite(t)?t:0}function loadFrozenSessions(dir=defaultPtyFreezeDir(),now=Date.now(),report){let names;try{names=readdirSync(dir)}catch{return[]}let entries=[];for(let name of names){if(!name.endsWith(".json"))continue;try{let st=statSync(join2(dir,name));entries.push({name,size:st.size,mtimeMs:st.mtimeMs})}catch{}}entries.sort((a,b)=>b.mtimeMs-a.mtimeMs);let kept=[],stale=[],bytesRead=0,deferred=0,unreadable=0;for(let entry of entries){if(now-entry.mtimeMs>FREEZE_TTL_MS){stale.push(entry.name);continue}if(bytesRead+entry.size>FREEZE_RESTORE_MAX_BYTES&&kept.length>0){deferred++;continue}let record=null;try{record=parseRecord(readFileSync(join2(dir,entry.name),"utf8"))}catch{}if(bytesRead+=entry.size,!record){unreadable++;continue}if(now-updatedAtMs(record)>FREEZE_TTL_MS)stale.push(entry.name);else kept.push(record)}for(let name of stale)try{rmSync(join2(dir,name),{force:!0})}catch{}return kept.sort((a,b)=>updatedAtMs(b)-updatedAtMs(a)),report?.({restored:kept.length,bytesRead,deferred,expired:stale.length,unreadable}),kept}var DIR_MODE=448,FILE_MODE=384;function tightenExistingPermissions(dir){try{chmodSync(dir,DIR_MODE)}catch{}let names;try{names=readdirSync(dir)}catch{return}for(let name of names){if(!name.endsWith(".json"))continue;try{chmodSync(join2(dir,name),FILE_MODE)}catch{}}}function fileFreezeSink(dir=defaultPtyFreezeDir()){return tightenExistingPermissions(dir),{save(record){try{mkdirSync2(dir,{recursive:!0,mode:DIR_MODE});let target=recordFile(dir,record.key),staging=`${target}.${process.pid}.tmp`;writeFileSync(staging,JSON.stringify(record),{encoding:"utf8",mode:FILE_MODE}),renameSync2(staging,target)}catch{}},drop(key){try{rmSync(recordFile(dir,key),{force:!0})}catch{}}}}function clearFrozenSessions(dir=defaultPtyFreezeDir()){try{rmSync(dir,{recursive:!0,force:!0})}catch{}}import{randomUUID as randomUUID3}from"crypto";function bunTerminalDriver(spawn){let spawnTerminal=spawn??((argv,options)=>Bun.spawn(argv,options));return(request)=>{let proc=spawnTerminal([...request.argv],{cwd:request.cwd,env:request.env,terminal:{cols:request.cols,rows:request.rows,name:"xterm-256color",data:(_terminal,data)=>request.onData(data)}});return{pid:proc.pid,exited:proc.exited.then(()=>({code:proc.exitCode??null,signal:proc.signalCode??null}),()=>({code:null,signal:null})),write:(data)=>proc.terminal?.write(data),resize:(cols,rows)=>proc.terminal?.resize(cols,rows),close:()=>proc.terminal?.close(),kill:(signal)=>proc.kill(signal)}}}import{randomUUID as randomUUID2}from"crypto";import{StringDecoder as StringDecoder2}from"string_decoder";function freshSessionState(key,spec,argv){return{key,generation:randomUUID2(),cwd:spec.cwd,proc:null,alive:!0,chunks:[],bytes:0,totalBytes:0,cols:spec.cols??80,rows:spec.rows??24,command:argv,title:"",titleCarry:"",titleDecoder:new StringDecoder2("utf8"),colorQueryCarry:"",defaultColors:parseTerminalDefaultColors(spec.defaultColors)??DEFAULT_TERMINAL_COLORS,sinks:new Map,parked:!1,parkedScreenBytes:0,exit:null,restored:!1,lastFreezeAtMs:0,frozenTotalBytes:0,lastHumanWriteMs:0}}function sessionInfo(s){return{key:s.key,generation:s.generation,alive:s.alive,pid:s.proc?.pid??null,command:s.command,title:s.title,totalBytes:s.totalBytes,parked:s.parked,parkedScreenBytes:s.parkedScreenBytes,exit:s.exit,restored:s.restored||void 0}}function describeExit(exit){if(exit?.signal)return` (signal ${exit.signal})`;if(exit&&exit.code!==null)return` (code ${exit.code})`;return" (cause unknown)"}function ringTail(chunks,bytes,maxBytes){let skip=Math.max(0,bytes-maxBytes),seen=0,parts=[];for(let chunk of chunks){if(seen+chunk.byteLength>skip)parts.push(seen>=skip?chunk:chunk.subarray(skip-seen));seen+=chunk.byteLength}return Buffer.concat(parts).toString("utf8")}function hostStats(sessions,perSessionCap,parkRestoreDeltas,parkRestoreFallbacks){let ringBytes=0,count=0,parkedSessions=0,parkedScreenBytes=0;for(let session of sessions)if(count++,ringBytes+=session.bytes,session.parked)parkedSessions++,parkedScreenBytes+=session.parkedScreenBytes;return{ringBytes,ringCapacityBytes:count*perSessionCap,parkedSessions,parkedScreenBytes,parkRestoreDeltas,parkRestoreFallbacks}}var OSC_TITLE_RE=/\x1b\][02];([^\x07\x1b]*)(?:\x07|\x1b\\)/g,TITLE_CARRY_CAP=1024;function titleCarryFrom(rest){let osc=rest.lastIndexOf("\x1B]");if(osc!==-1)return rest.slice(osc,osc+TITLE_CARRY_CAP);return rest.endsWith("\x1B")?"\x1B":""}function foldOscTitle(prevCarry,chunkText){let text=prevCarry+chunkText,title=null,end=0;OSC_TITLE_RE.lastIndex=0;for(let match=OSC_TITLE_RE.exec(text);match;match=OSC_TITLE_RE.exec(text))title=match[1]??"",end=match.index+match[0].length;return{title,carry:titleCarryFrom(text.slice(end))}}function scanOscTitle(session,buf){let{title,carry}=foldOscTitle(session.titleCarry,session.titleDecoder.write(buf));if(title!==null)session.title=title;session.titleCarry=carry}function peekRing(session,sinceOffset,humanWriteQuietMs){if(!session)return{exists:!1,alive:!1,pid:null,offset:0,data:"",sinceValid:!1,exit:null};let windowStart=session.totalBytes-session.bytes,buf=Buffer.concat(session.chunks),sinceValid=!1;if(sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes)buf=buf.subarray(sinceOffset-windowStart),sinceValid=!0;return{exists:!0,alive:session.alive,pid:session.proc?.pid??null,offset:session.totalBytes,data:buf.toString("base64"),sinceValid,exit:session.exit??null,...session.lastHumanWriteMs&&session.lastHumanWriteMs>0?{lastHumanWriteMs:session.lastHumanWriteMs,humanWriteQuietMs}:{}}}async function settledWithin(exited,ms){let timer,settled=await Promise.race([exited.then(()=>!0,()=>!0),new Promise((resolve)=>{timer=setTimeout(()=>resolve(!1),ms)})]);if(timer)clearTimeout(timer);return settled}function signalProcessGroup(pid,signal,fallback,platform=process.platform,onSignal){if(platform!=="win32"&&pid>1)try{process.kill(-pid,signal),onSignal?.(`sent ${signal} to process group -${pid}`);return}catch{}try{fallback(),onSignal?.(`sent ${signal} to pid ${pid} (per-process fallback)`)}catch{}}var TERMINATION_GRACE_MS=500;async function terminatePtyChild(proc,onSettled,onSignal){if(signalProcessGroup(proc.pid,"SIGTERM",()=>proc.kill("SIGTERM"),process.platform,onSignal),!await settledWithin(proc.exited,TERMINATION_GRACE_MS))signalProcessGroup(proc.pid,"SIGKILL",()=>proc.kill("SIGKILL"),process.platform,onSignal),await settledWithin(proc.exited,TERMINATION_GRACE_MS);onSettled()}class PtyChildController{deps;constructor(deps){this.deps=deps}spawn(key,spec,spare=!1){let argv=spec.command&&spec.command.length>0?[...spec.command]:[spec.shell??resolveLoginShell()],session=freshSessionState(key,spec,argv);if(this.startChild(session),session.alive)this.deps.log?.("pty",`spawned ${argv[0]} for ${key} (pid ${session.proc?.pid})`),this.deps.onSessionStart?.(spare);return session}startChild(session){session.generation=randomUUID3();try{session.proc=(this.deps.driver??bunTerminalDriver())({argv:[...session.command],cwd:session.cwd,env:embeddedTerminalEnv(process.env,{TERM:"xterm-256color",COLUMNS:String(session.cols),LINES:String(session.rows),BASH_SILENCE_DEPRECATION_WARNING:"1",KOBE_TERMINAL_PTY:"1"}),cols:session.cols,rows:session.rows,onData:(data)=>this.onData(session,data)}),session.alive=!0,session.proc.exited.then((exit)=>this.markExited(session,exit),()=>this.markExited(session))}catch(err){session.alive=!1,this.deps.log?.("pty",`spawn failed for ${session.key}: ${err instanceof Error?err.message:String(err)}`)}}async endChild(session){if(!session.alive)return;let proc=session.proc;if(!proc){this.markExited(session);return}await terminatePtyChild(proc,()=>this.markExited(session),(line)=>this.deps.log?.("pty-signal",`${session.key}: ${line}`))}markExited(session,exit){if(!session.alive)return;session.alive=!1;let sessionExit={code:exit?.code??null,signal:exit?.signal??null,at:new Date().toISOString()};session.exit=sessionExit;try{session.proc?.close()}catch{}this.deps.onExit?.(session,sessionExit)}onData(session,data){let buf=typeof data==="string"?Buffer.from(data,"utf8"):Buffer.from(data),colorQueries=foldDefaultColorQueries(session.colorQueryCarry,buf.toString("latin1"));session.colorQueryCarry=colorQueries.carry;for(let slot of colorQueries.slots)try{session.proc?.write(formatDefaultColorReply(slot,session.defaultColors))}catch{}scanOscTitle(session,buf),session.chunks.push(buf),session.bytes+=buf.byteLength,session.totalBytes+=buf.byteLength;while(session.bytes>this.deps.scrollbackCap&&session.chunks.length>1){let dropped=session.chunks.shift();if(dropped)session.bytes-=dropped.byteLength}this.deps.onOutput?.(session,buf)}}function shouldFreeze(session,now){let appended=session.totalBytes-(session.frozenTotalBytes??0);if(appended<=0)return!1;let since=now-session.lastFreezeAtMs;if(since<5000)return!1;return appended>=65536||since>=60000}class WarmSpare{deps;spare=null;constructor(deps){this.deps=deps}warm(cwd,shell,cols=80,rows=24){let argv0=shell??resolveLoginShell();if(this.spare?.alive&&this.spare.cwd===cwd&&this.spare.command[0]===argv0)return;let old=this.spare;if(this.spare=null,old)this.deps.endChild(old);let session=this.deps.spawn("::spare",{cwd,command:[argv0],cols,rows},!0);this.spare=session.alive?session:null}adopt(key,spec){let spare=this.spare;if(!spare?.alive||spare.cwd!==spec.cwd)return null;let want=spec.command&&spec.command.length>0?spec.command:[spec.shell??resolveLoginShell()];if(want.length!==1||want[0]!==spare.command[0])return null;this.spare=null,spare.key=key,spare.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??spare.defaultColors;let cols=spec.cols??spare.cols,rows=spec.rows??spare.rows;if(spare.cols!==cols||spare.rows!==rows){spare.cols=cols,spare.rows=rows;try{spare.proc?.resize(cols,rows)}catch{return this.deps.markExited(spare),null}}return this.deps.log?.("pty",`adopted warm shell for ${key} (pid ${spare.proc?.pid})`),this.deps.onSessionStart?.(),this.warm(spec.cwd,spare.command[0],cols,rows),spare}async end(){let spare=this.spare;if(this.spare=null,spare)await this.deps.endChild(spare)}}var LOGGED_WRITE_BYTES=1024,DEFAULT_SCROLLBACK_CAP=524288,EXIT_TAIL_BYTES=16384,DEFAULT_HUMAN_WRITE_QUIET_MS=1e4;function resolveHumanWriteQuietMs(){let raw=process.env.KOBE_PTY_HUMAN_WRITE_QUIET_MS;if(raw===void 0)return DEFAULT_HUMAN_WRITE_QUIET_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_HUMAN_WRITE_QUIET_MS}class PtyHost{sessions=new Map;opts;scrollbackCap;humanWriteQuietMs;parkRestoreDeltas=0;parkRestoreFallbacks=0;childController;warmSpare;constructor(opts={}){this.opts=opts,this.scrollbackCap=opts.scrollbackCap??DEFAULT_SCROLLBACK_CAP,this.humanWriteQuietMs=opts.humanWriteQuietMs??resolveHumanWriteQuietMs(),this.childController=new PtyChildController({driver:opts.driver,scrollbackCap:this.scrollbackCap,onSessionStart:(spare)=>{if(!spare)this.opts.onSessionStart?.()},onOutput:(session,data)=>{if(session.sinks.size===0){this.maybeFreeze(session);return}let frame={type:"event",name:"pty.data",payload:{key:session.key,data:data.toString("base64")}};for(let sink of session.sinks.values())sink(frame);this.maybeFreeze(session)},onExit:(session,exit)=>{let frame={type:"event",name:"pty.exit",payload:{key:session.key,pid:session.proc?.pid??null,...exit}};for(let sink of session.sinks.values())sink(frame);if(this.opts.log?.("pty",`session ${session.key} exited${describeExit(exit)}`),this.maybeFreeze(session,!0),!session.closedByRequest)try{this.opts.onSessionExit?.({key:session.key,pid:session.proc?.pid??null,exit,tail:ringTail(session.chunks,session.bytes,EXIT_TAIL_BYTES)})}catch{}this.opts.onSessionEnd?.()},log:(event,message)=>this.opts.log?.(event,message)}),this.warmSpare=new WarmSpare({spawn:(key,spec,spare)=>this.childController.spawn(key,spec,spare),endChild:(session)=>this.childController.endChild(session),markExited:(session)=>this.childController.markExited(session),log:(event,message)=>this.opts.log?.(event,message),onSessionStart:()=>this.opts.onSessionStart?.()})}open(key,spec,token,sink,sinceOffset,sincePid){let session=this.sessions.get(key),created=!1,respawned=!1;if(!session)created=!0,session=this.warmSpare.adopt(key,spec)??this.childController.spawn(key,spec),this.sessions.set(key,session);else if(!session.alive&&session.restored)this.respawn(session,spec),respawned=session.alive;else if(session.alive&&spec.cols!==void 0&&spec.rows!==void 0&&(session.cols!==spec.cols||session.rows!==spec.rows))this.resize(key,spec.cols,spec.rows);let defaultColors=parseTerminalDefaultColors(spec.defaultColors);if(defaultColors)session.defaultColors=defaultColors;session.sinks.set(token,sink),session.parked=!1,session.parkedScreenBytes=0;let windowStart=session.totalBytes-session.bytes,replay=Buffer.concat(session.chunks),sinceValid=!1;if(!created&&sinceOffset!==void 0&&sinceOffset>=windowStart&&sinceOffset<=session.totalBytes&&sincePid!==void 0&&sincePid===session.proc?.pid)replay=replay.subarray(sinceOffset-windowStart),sinceValid=!0;if(sinceOffset!==void 0&&sincePid!==void 0)if(sinceValid)this.parkRestoreDeltas++;else this.parkRestoreFallbacks++;return{replay:replay.toString("base64"),alive:session.alive,pid:session.proc?.pid??null,created,respawned,offset:session.totalBytes,sinceValid}}warm(cwd,shell,cols=80,rows=24){this.warmSpare.warm(cwd,shell,cols,rows)}write(key,data,client){let session=this.sessions.get(key);if(!session?.alive||data.length===0)return;if(client!==void 0&&session.sinks.has(client))session.lastHumanWriteMs=Date.now();if(data.length>=LOGGED_WRITE_BYTES)this.opts.log?.("pty",`wrote ${data.length} bytes to ${key}`);try{session.proc?.write(data)}catch(error){this.opts.log?.("pty",`write failed on ${key} (${data.length} bytes): ${String(error)}`)}}resize(key,cols,rows){let session=this.sessions.get(key);if(!session?.alive)return;session.cols=cols,session.rows=rows;try{session.proc?.resize(cols,rows)}catch{}}killIfGeneration(key,expectedGeneration){let session=this.sessions.get(key);if(!session)return{killed:!1,reason:"missing-session"};if(session.generation!==expectedGeneration)return{killed:!1,reason:"generation-mismatch"};return this.kill(key),{killed:!0}}kill(key){let session=this.sessions.get(key);if(!session)return Promise.resolve();return this.sessions.delete(key),session.closedByRequest=!0,this.opts.freeze?.drop(key),this.childController.endChild(session)}rename(from,to){let session=this.sessions.get(from);if(!session||from===to||this.sessions.has(to))return!1;return this.sessions.delete(from),session.key=to,this.sessions.set(to,session),this.opts.freeze?.drop(from),this.maybeFreeze(session,!0),this.opts.log?.("pty",`renamed session ${from} \u2192 ${to}`),!0}detach(key,token,parked=!1,parkedScreenBytes=0){let session=this.sessions.get(key);if(!session)return;session.sinks.delete(token),this.applyParkedOnDetach(session,parked,parkedScreenBytes)}detachClient(token){for(let session of this.sessions.values()){if(!session.sinks.delete(token))continue;this.applyParkedOnDetach(session)}}applyParkedOnDetach(session,parked=!1,parkedScreenBytes=0){if(session.sinks.size!==0)return;session.parked=parked,session.parkedScreenBytes=parked?Math.max(0,parkedScreenBytes):0}list(){return Array.from(this.sessions.values(),(s)=>sessionInfo(s))}peek(key,sinceOffset){return peekRing(this.sessions.get(key),sinceOffset,this.humanWriteQuietMs)}stats(){return hostStats(this.sessions.values(),this.scrollbackCap,this.parkRestoreDeltas,this.parkRestoreFallbacks)}sweepTasks(liveTaskIds){for(let key of Array.from(this.sessions.keys())){let taskId=key.split("::")[0]??key;if(!liveTaskIds.has(taskId))this.kill(key)}}async killAll(){let sessions=Array.from(this.sessions.keys(),(key)=>this.kill(key));sessions.push(this.warmSpare.end()),await Promise.all(sessions)}async shutdown(){this.flushFrozen();let endings=Array.from(this.sessions.values(),(session)=>this.childController.endChild(session));endings.push(this.warmSpare.end()),await Promise.all(endings)}flushFrozen(){for(let session of this.sessions.values())this.maybeFreeze(session,!0)}restoreFrozen(records){let restoredCount=0;for(let record of records){if(this.sessions.has(record.key))continue;let session=thawSession(record,this.scrollbackCap);if(!session)continue;this.sessions.set(record.key,session),restoredCount++}if(restoredCount>0)this.opts.log?.("pty",`restored ${restoredCount} frozen session(s) from disk`);return restoredCount}respawn(session,spec){if(session.restored=!1,session.exit=null,spec.command&&spec.command.length>0)session.command=[...spec.command];if(session.cols=spec.cols??session.cols,session.rows=spec.rows??session.rows,session.defaultColors=parseTerminalDefaultColors(spec.defaultColors)??session.defaultColors,this.childController.startChild(session),!session.alive)return;this.opts.log?.("pty",`respawned restored session ${session.key} (pid ${session.proc?.pid})`),this.opts.onSessionStart?.()}maybeFreeze(session,force=!1){let freeze=this.opts.freeze;if(!freeze||session.key.startsWith("::"))return;if(session.closedByRequest)return;let now=Date.now();if(!force&&!shouldFreeze(session,now))return;session.lastFreezeAtMs=now,session.frozenTotalBytes=session.totalBytes,freeze.save(freezeSession(session))}liveCount(){let n=0;for(let session of this.sessions.values())if(session.alive)n++;return n}}var DEFAULT_IDLE_EXIT_MS=60000,DEFAULT_ORPHAN_CHECK_MS=30000;function resolveMaxLifetimeMs(){let raw=process.env.KOBE_PTY_MAX_LIFETIME_MS;if(raw===void 0)return null;let n=Number(raw);return Number.isFinite(n)&&n>0?n:null}function resolveIdleExitMs(){let raw=process.env.KOBE_PTY_IDLE_EXIT_MS;if(raw===void 0)return DEFAULT_IDLE_EXIT_MS;let n=Number(raw);return Number.isFinite(n)&&n>=0?n:DEFAULT_IDLE_EXIT_MS}async function startPtyHostServer(options={}){migrateLegacyPtyHostData();let socketPath=options.socketPath??defaultPtyHostSocketPath(),pidPath=options.pidPath??defaultPtyHostPidPath(),freezeDir=options.freezeDir??defaultPtyFreezeDir(),idleExitMs=options.idleExitMs||resolveIdleExitMs(),orphanCheckMs=options.orphanCheckMs||DEFAULT_ORPHAN_CHECK_MS,maxLifetimeMs=options.maxLifetimeMs??resolveMaxLifetimeMs(),bootedAtMs=Date.now(),log=options.log??(()=>{}),clients=new Set,stopping=!1,wipeFreezeOnStop=!1,idleTimer=null,cancelIdle=()=>{if(idleTimer)clearTimeout(idleTimer);idleTimer=null},armIdle=()=>{if(stopping)return;cancelIdle(),idleTimer=setTimeout(()=>{if(stopping||ptys.liveCount()>0)return;log("idle",`no live sessions for ${idleExitMs}ms \u2014 exiting`),stop()},idleExitMs)},orphaned=()=>{if(maxLifetimeMs!==null&&Date.now()-bootedAtMs>=maxLifetimeMs)return`exceeded its ${maxLifetimeMs}ms lifetime ceiling`;let owner;try{owner=readFileSync2(pidPath,"utf8").trim()}catch{return`pidfile ${pidPath} is gone`}let pid=Number.parseInt(owner,10);if(pid===process.pid)return null;return Number.isInteger(pid)?`pidfile ${pidPath} now names pid ${pid}`:`pidfile ${pidPath} is unreadable`},orphanTimer=setInterval(()=>{if(stopping)return;let reason=orphaned();if(!reason)return;log("orphan",`${reason} \u2014 exiting rather than outliving my owner`),stop()},orphanCheckMs);orphanTimer.unref?.();let ptys=new PtyHost({onSessionStart:cancelIdle,onSessionEnd:()=>{if(ptys.liveCount()===0)armIdle()},onSessionExit:(info)=>{try{recordPtyExit(info)}catch(err){log("pty",`exit record write failed for ${info.key}: ${err instanceof Error?err.message:String(err)}`)}},freeze:fileFreezeSink(freezeDir),driver:options.driver,log});ptys.restoreFrozen(loadFrozenSessions(freezeDir,Date.now(),(s)=>{let mib=(bytes)=>`${Math.round(bytes/1048576)}MB`,notes=[`restored ${s.restored} (${mib(s.bytesRead)})`];if(s.deferred>0)notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);if(s.expired>0)notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS/86400000}-day TTL`);if(s.unreadable>0)notes.push(`${s.unreadable} unreadable`);log("freeze",notes.join(", "))}));let pipeSocket=isWindowsPipePath(socketPath);if(await ensureOwnerOnlyStateDir(resolveDaemonHomeDir()),!pipeSocket)await mkdir(dirname(socketPath),{recursive:!0});await mkdir(dirname(pidPath),{recursive:!0});let server=createServer((socket)=>{let client={socket,writer:new ClientWriter(socket,{onOverflow:()=>{log("backpressure","disconnecting PTY client whose critical queue exceeded 8MiB"),socket.destroy()}})};clients.add(client);let receiver=new LineReceiver;socket.on("data",(chunk)=>{if(!receiver.push(chunk,(line)=>handleLine(client,line)))log("framing","disconnecting PTY client whose request exceeded 8MiB"),socket.destroy()}),socket.on("error",()=>{}),socket.on("close",()=>{clients.delete(client),ptys.detachClient(client)})}),api={socketPath,pidPath,async close(){if(stopping)return;if(stopping=!0,cancelIdle(),clearInterval(orphanTimer),await ptys.shutdown(),wipeFreezeOnStop)clearFrozenSessions(freezeDir);for(let client of Array.from(clients))client.socket.destroy();if(await new Promise((resolve)=>server.close(()=>resolve())),!pipeSocket)await unlink(socketPath).catch(()=>{});await unlink(pidPath).catch(()=>{})}};async function stop(){await api.close().catch((err)=>logDaemonError("pty-host-shutdown",err)),options.onStop?.()}function dispatch(req,client){switch(req.name){case"hello":return{protocolVersion:DAEMON_PROTOCOL_VERSION,ptyHost:!0,pid:process.pid};case"pty.open":{let payload=objectPayload(req.payload);return ptys.open(requireString(payload,"key"),{cwd:requireString(payload,"cwd"),command:Array.isArray(payload.command)?payload.command.filter((c)=>typeof c==="string"):void 0,shell:typeof payload.shell==="string"?payload.shell:void 0,cols:typeof payload.cols==="number"?payload.cols:void 0,rows:typeof payload.rows==="number"?payload.rows:void 0,defaultColors:parseTerminalDefaultColors(payload.defaultColors)??void 0},client,(frame)=>writeFrame(client,frame),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0,typeof payload.sincePid==="number"?payload.sincePid:void 0)}case"pty.write":{let payload=objectPayload(req.payload);return ptys.write(requireString(payload,"key"),typeof payload.data==="string"?payload.data:"",client),{}}case"pty.resize":{let payload=objectPayload(req.payload);return ptys.resize(requireString(payload,"key"),typeof payload.cols==="number"?payload.cols:80,typeof payload.rows==="number"?payload.rows:24),{}}case"pty.kill":{let payload=objectPayload(req.payload),key=requireString(payload,"key");if("expectedGeneration"in payload)return ptys.killIfGeneration(key,requireString(payload,"expectedGeneration"));return ptys.kill(key),{}}case"pty.rename":{let payload=objectPayload(req.payload);return{renamed:ptys.rename(requireString(payload,"from"),requireString(payload,"to"))}}case"pty.detach":{let payload=objectPayload(req.payload);ptys.detach(requireString(payload,"key"),client,payload.parked===!0,typeof payload.parkedScreenBytes==="number"?payload.parkedScreenBytes:0)}return{};case"pty.list":return{pid:process.pid,rssBytes:process.memoryUsage().rss,sessions:ptys.list(),stats:ptys.stats()};case"pty.peek":{let payload=objectPayload(req.payload);return ptys.peek(requireString(payload,"key"),typeof payload.sinceOffset==="number"?payload.sinceOffset:void 0)}case"pty.warm":{let payload=objectPayload(req.payload);return ptys.warm(requireString(payload,"cwd"),typeof payload.shell==="string"?payload.shell:void 0,typeof payload.cols==="number"?payload.cols:void 0,typeof payload.rows==="number"?payload.rows:void 0),{}}case"pty.sweep":{let payload=objectPayload(req.payload),ids=Array.isArray(payload.liveTaskIds)?payload.liveTaskIds.filter((id)=>typeof id==="string"):[];return ptys.sweepTasks(new Set(ids)),{}}case"daemon.stop":return wipeFreezeOnStop=!0,setTimeout(()=>void stop(),0).unref(),{};default:throw Error(`unknown pty-host request: ${req.name}`)}}function handleLine(client,line){if(line.trim().length>0){let frame=null;try{frame=JSON.parse(line)}catch{writeFrame(client,{type:"response",id:"parse-error",error:{message:"malformed frame"}})}if(frame)if(frame.type!=="request")writeFrame(client,{type:"response",id:"parse-error",error:{message:"requests only"}});else try{writeFrame(client,{type:"response",id:frame.id,name:frame.name,payload:dispatch(frame,client)})}catch(err){writeFrame(client,{type:"response",id:frame.id,name:frame.name,error:{message:err instanceof Error?err.message:String(err)}})}}}if(await listenOnUnixSocket(server,socketPath),await writeFile(pidPath,`${process.pid}
3
3
  `,"utf8"),!pipeSocket){let home=resolveDaemonHomeDir();await linkLegacyRuntimePath(socketPath,legacyPtyHostSocketPath(home)),await linkLegacyRuntimePath(pidPath,legacyPtyHostPidPath(home))}return armIdle(),log("boot",`pty host listening on ${socketPath}`),api}function writeFrame(client,frame){client.writer.write(frameToLine(frame))}async function runPtyHostSubcommand(_argv){rotateLogIfNeeded(defaultPtyHostLogPath()),installDaemonCrashHandlers();let server=await startPtyHostServer({log:(event,message)=>console.log(`[pty-host ${event}] ${message}`),onStop:()=>process.exit(0)});console.log(`rove pty-host: listening on ${server.socketPath}`);let shutdown=async()=>{await server.close(),process.exit(0)};process.once("SIGINT",()=>void shutdown()),process.once("SIGTERM",()=>void shutdown())}export{runPtyHostSubcommand};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{errorMessage}from"./chunk-2brn8e1y.js";import{roveStateDir}from"./chunk-07k2njwk.js";var claude_default={$schema:"https://opencode.ai/theme.json",defs:{darkBg:"#141413",darkBgRaised:"#1A1917",darkBgInset:"#2B2A27",darkBgMenu:"#33312E",darkBorderSubtle:"#2B2A27",darkBorder:"#3A3835",darkBorderActive:"#5C5853",darkText:"#EAE7DF",darkTextMuted:"#A9A39A",darkTextSubtle:"#6B665F",darkPrimary:"#CC785C",darkSecondary:"#D4967E",darkAccent:"#CC785C",darkAccentHover:"#E0AB96",darkRed:"#D47563",darkOrange:"#D97757",darkYellow:"#E8C96B",darkGreen:"#9ACA86",darkBlue:"#61AAF2",darkViolet:"#9B87F5",darkTerracotta:"#BF4D43",lightBg:"#FAF9F5",lightBgRaised:"#F0EEE6",lightBgInset:"#EAE7DF",lightBgMenu:"#E2DED4",lightBorderSubtle:"#EAE7DF",lightBorder:"#D9D5CC",lightBorderActive:"#A9A39A",lightText:"#1A1917",lightTextMuted:"#6B665F",lightTextSubtle:"#8D877D",lightPrimary:"#C96442",lightSecondary:"#B85F3D",lightAccent:"#CC785C",lightAccentHover:"#B85F3D",lightRed:"#A84B3A",lightOrange:"#C96442",lightYellow:"#8A6220",lightGreen:"#2E7C4C",lightBlue:"#207FDE",lightViolet:"#7B5BB6",lightTerracotta:"#BF4D43"},theme:{primary:{dark:"darkPrimary",light:"lightPrimary"},secondary:{dark:"darkSecondary",light:"lightSecondary"},accent:{dark:"darkAccent",light:"lightAccent"},error:{dark:"darkRed",light:"lightRed"},warning:{dark:"darkYellow",light:"lightYellow"},success:{dark:"darkGreen",light:"lightGreen"},info:{dark:"darkBlue",light:"lightBlue"},text:{dark:"darkText",light:"lightText"},textMuted:{dark:"darkTextMuted",light:"lightTextMuted"},background:{dark:"darkBg",light:"lightBg"},backgroundPanel:{dark:"darkBgRaised",light:"lightBgRaised"},backgroundElement:{dark:"darkBgInset",light:"lightBgInset"},backgroundMenu:{dark:"darkBgMenu",light:"lightBgMenu"},backgroundDialog:{dark:"darkBgRaised",light:"lightBgRaised"},border:{dark:"darkBorder",light:"lightBorder"},borderActive:{dark:"darkBorderActive",light:"lightBorderActive"},borderSubtle:{dark:"darkBorderSubtle",light:"lightBorderSubtle"},diffAdded:{dark:"darkGreen",light:"lightGreen"},diffRemoved:{dark:"darkRed",light:"lightRed"},diffContext:{dark:"darkTextMuted",light:"lightTextSubtle"},diffHunkHeader:{dark:"darkTextMuted",light:"lightTextSubtle"},diffHighlightAdded:{dark:"#B5E0A0",light:"#1F6638"},diffHighlightRemoved:{dark:"#E89180",light:"#8A3A2C"},diffAddedBg:{dark:"#1F2A1F",light:"#E5EEDF"},diffRemovedBg:{dark:"#2A1F1C",light:"#F5DAD3"},diffContextBg:{dark:"darkBgRaised",light:"lightBgRaised"},diffLineNumber:{dark:"darkTextSubtle",light:"lightTextSubtle"},diffAddedLineNumberBg:{dark:"#1A2419",light:"#D5E2CC"},diffRemovedLineNumberBg:{dark:"#241915",light:"#EBC8BE"},markdownText:{dark:"darkText",light:"lightText"},markdownHeading:{dark:"darkPrimary",light:"lightPrimary"},markdownLink:{dark:"darkAccent",light:"lightAccent"},markdownLinkText:{dark:"darkBlue",light:"lightBlue"},markdownCode:{dark:"darkSecondary",light:"lightSecondary"},markdownBlockQuote:{dark:"darkTextMuted",light:"lightTextMuted"},markdownEmph:{dark:"darkYellow",light:"lightYellow"},markdownStrong:{dark:"darkPrimary",light:"lightPrimary"},markdownHorizontalRule:{dark:"darkTextMuted",light:"lightTextMuted"},markdownListItem:{dark:"darkAccent",light:"lightAccent"},markdownListEnumeration:{dark:"darkBlue",light:"lightBlue"},markdownImage:{dark:"darkAccent",light:"lightAccent"},markdownImageText:{dark:"darkBlue",light:"lightBlue"},markdownCodeBlock:{dark:"darkText",light:"lightText"},markdownQuote:{dark:"darkTextMuted",light:"lightTextMuted"},syntaxComment:{dark:"darkTextSubtle",light:"lightTextSubtle"},syntaxKeyword:{dark:"darkPrimary",light:"lightPrimary"},syntaxFunction:{dark:"darkBlue",light:"lightBlue"},syntaxVariable:{dark:"darkText",light:"lightText"},syntaxString:{dark:"darkGreen",light:"lightGreen"},syntaxNumber:{dark:"darkOrange",light:"lightOrange"},syntaxType:{dark:"darkViolet",light:"lightViolet"},syntaxOperator:{dark:"darkSecondary",light:"lightSecondary"},syntaxPunctuation:{dark:"darkText",light:"lightText"},selectedListItemText:{dark:"darkBg",light:"lightBg"}}};var conductor_default={$schema:"https://opencode.ai/theme.json",defs:{darkStep1:"#0a0a0a",darkStep2:"#111111",darkStep3:"#181818",darkStep4:"#1f1f1f",darkStep5:"#2a2a2a",darkStep6:"#363636",darkStep7:"#444444",darkStep8:"#5a5a5a",darkStep9:"#7a7a7a",darkStep10:"#9a9a9a",darkStep11:"#909090",darkStep12:"#e8e8e8",darkAccent:"#7da5c8",darkAccentBright:"#9bc3e3",darkRed:"#e06c75",darkOrange:"#d6a668",darkGreen:"#7fd88f",darkCyan:"#7da5c8",darkYellow:"#d6a668",lightStep1:"#fafafa",lightStep2:"#f3f3f3",lightStep3:"#ececec",lightStep4:"#e2e2e2",lightStep5:"#d4d4d4",lightStep6:"#bdbdbd",lightStep7:"#9c9c9c",lightStep8:"#7c7c7c",lightStep9:"#5b5b5b",lightStep10:"#404040",lightStep11:"#6c6c6c",lightStep12:"#1a1a1a",lightAccent:"#3d6f9f",lightAccentBright:"#1a4f87",lightRed:"#c9343a",lightOrange:"#a06b1a",lightGreen:"#3d9a57",lightCyan:"#3d6f9f",lightYellow:"#a06b1a"},theme:{primary:{dark:"darkStep12",light:"lightStep12"},secondary:{dark:"darkAccentBright",light:"lightAccentBright"},accent:{dark:"darkAccent",light:"lightAccent"},error:{dark:"darkRed",light:"lightRed"},warning:{dark:"darkOrange",light:"lightOrange"},success:{dark:"darkGreen",light:"lightGreen"},info:{dark:"darkCyan",light:"lightCyan"},text:{dark:"darkStep12",light:"lightStep12"},textMuted:{dark:"darkStep11",light:"lightStep11"},background:{dark:"darkStep1",light:"lightStep1"},backgroundPanel:{dark:"darkStep2",light:"lightStep2"},backgroundElement:{dark:"darkStep3",light:"lightStep3"},backgroundMenu:{dark:"darkStep4",light:"lightStep4"},border:{dark:"darkStep6",light:"lightStep6"},borderActive:{dark:"darkStep8",light:"lightStep8"},borderSubtle:{dark:"darkStep4",light:"lightStep4"},diffAdded:{dark:"#7fd88f",light:"#3d9a57"},diffRemoved:{dark:"#e06c75",light:"#c9343a"},diffContext:{dark:"darkStep10",light:"lightStep10"},diffHunkHeader:{dark:"darkStep10",light:"lightStep10"},diffHighlightAdded:{dark:"#9be5ad",light:"#2d7a3f"},diffHighlightRemoved:{dark:"#f08490",light:"#a82530"},diffAddedBg:{dark:"#15241a",light:"#d8efdc"},diffRemovedBg:{dark:"#2a1518",light:"#f5dadc"},diffContextBg:{dark:"darkStep2",light:"lightStep2"},diffLineNumber:{dark:"darkStep9",light:"lightStep9"},diffAddedLineNumberBg:{dark:"#0f1c14",light:"#c5deca"},diffRemovedLineNumberBg:{dark:"#221012",light:"#e5c5c8"},markdownText:{dark:"darkStep12",light:"lightStep12"},markdownHeading:{dark:"darkStep12",light:"lightStep12"},markdownLink:{dark:"darkAccent",light:"lightAccent"},markdownCode:{dark:"darkAccentBright",light:"lightAccentBright"},markdownCodeBlock:{dark:"darkStep12",light:"lightStep12"},markdownQuote:{dark:"darkStep11",light:"lightStep11"},selectedListItemText:{dark:"darkStep1",light:"lightStep1"}}};var tokyonight_default={$schema:"https://opencode.ai/theme.json",defs:{darkStep1:"#1a1b26",darkStep2:"#1e2030",darkStep3:"#222436",darkStep4:"#292e42",darkStep5:"#3b4261",darkStep6:"#545c7e",darkStep7:"#737aa2",darkStep8:"#9099b2",darkStep9:"#82aaff",darkStep10:"#89b4fa",darkStep11:"#828bb8",darkStep12:"#c8d3f5",darkRed:"#ff757f",darkOrange:"#ff966c",darkYellow:"#ffc777",darkGreen:"#c3e88d",darkCyan:"#86e1fc",darkPurple:"#c099ff",lightStep1:"#e1e2e7",lightStep2:"#d5d6db",lightStep3:"#c8c9ce",lightStep4:"#b9bac1",lightStep5:"#a8aecb",lightStep6:"#9699a8",lightStep7:"#737a8c",lightStep8:"#5a607d",lightStep9:"#2e7de9",lightStep10:"#1a6ce7",lightStep11:"#8990a3",lightStep12:"#3760bf",lightRed:"#f52a65",lightOrange:"#b15c00",lightYellow:"#8c6c3e",lightGreen:"#587539",lightCyan:"#007197",lightPurple:"#9854f1"},theme:{primary:{dark:"darkStep9",light:"lightStep9"},secondary:{dark:"darkPurple",light:"lightPurple"},accent:{dark:"darkOrange",light:"lightOrange"},error:{dark:"darkRed",light:"lightRed"},warning:{dark:"darkOrange",light:"lightOrange"},success:{dark:"darkGreen",light:"lightGreen"},info:{dark:"darkStep9",light:"lightStep9"},text:{dark:"darkStep12",light:"lightStep12"},textMuted:{dark:"darkStep11",light:"lightStep11"},background:{dark:"darkStep1",light:"lightStep1"},backgroundPanel:{dark:"darkStep2",light:"lightStep2"},backgroundElement:{dark:"darkStep3",light:"lightStep3"},border:{dark:"darkStep7",light:"lightStep7"},borderActive:{dark:"darkStep8",light:"lightStep8"},borderSubtle:{dark:"darkStep6",light:"lightStep6"},diffAdded:{dark:"#4fd6be",light:"#1e725c"},diffRemoved:{dark:"#c53b53",light:"#c53b53"},diffContext:{dark:"#828bb8",light:"#7086b5"},diffHunkHeader:{dark:"#828bb8",light:"#7086b5"},diffHighlightAdded:{dark:"#b8db87",light:"#4db380"},diffHighlightRemoved:{dark:"#e26a75",light:"#f52a65"},diffAddedBg:{dark:"#20303b",light:"#d5e5d5"},diffRemovedBg:{dark:"#37222c",light:"#f7d8db"},diffContextBg:{dark:"darkStep2",light:"lightStep2"},diffLineNumber:{dark:"#8f909a",light:"#59595b"},diffAddedLineNumberBg:{dark:"#1b2b34",light:"#c5d5c5"},diffRemovedLineNumberBg:{dark:"#2d1f26",light:"#e7c8cb"},markdownText:{dark:"darkStep12",light:"lightStep12"},markdownHeading:{dark:"darkPurple",light:"lightPurple"},markdownLink:{dark:"darkStep9",light:"lightStep9"},markdownLinkText:{dark:"darkCyan",light:"lightCyan"},markdownCode:{dark:"darkGreen",light:"lightGreen"},markdownBlockQuote:{dark:"darkYellow",light:"lightYellow"},markdownEmph:{dark:"darkYellow",light:"lightYellow"},markdownStrong:{dark:"darkOrange",light:"lightOrange"},markdownHorizontalRule:{dark:"darkStep11",light:"lightStep11"},markdownListItem:{dark:"darkStep9",light:"lightStep9"},markdownListEnumeration:{dark:"darkCyan",light:"lightCyan"},markdownImage:{dark:"darkStep9",light:"lightStep9"},markdownImageText:{dark:"darkCyan",light:"lightCyan"},markdownCodeBlock:{dark:"darkStep12",light:"lightStep12"},syntaxComment:{dark:"darkStep11",light:"lightStep11"},syntaxKeyword:{dark:"darkPurple",light:"lightPurple"},syntaxFunction:{dark:"darkStep9",light:"lightStep9"},syntaxVariable:{dark:"darkRed",light:"lightRed"},syntaxString:{dark:"darkGreen",light:"lightGreen"},syntaxNumber:{dark:"darkOrange",light:"lightOrange"},syntaxType:{dark:"darkYellow",light:"lightYellow"},syntaxOperator:{dark:"darkCyan",light:"lightCyan"},syntaxPunctuation:{dark:"darkStep12",light:"lightStep12"}}};var BUNDLED_THEME_JSONS={claude:claude_default,conductor:conductor_default,tokyonight:tokyonight_default};function isPlainObject(v){return typeof v==="object"&&v!==null&&!Array.isArray(v)}function validateTheme(value){if(!isPlainObject(value))return{ok:!1,reason:"theme must be a JSON object at the top level"};let obj=value;if(!("theme"in obj))return{ok:!1,reason:"missing required key `theme`"};let theme=obj.theme;if(!isPlainObject(theme))return{ok:!1,reason:"`theme` must be an object map"};if("defs"in obj&&obj.defs!==void 0){if(!isPlainObject(obj.defs))return{ok:!1,reason:"`defs` must be an object map"};for(let[k,v]of Object.entries(obj.defs))if(typeof v!=="string")return{ok:!1,reason:`defs.${k} must be a string (hex like "#abc" or a ref name)`}}for(let[slot,raw]of Object.entries(theme)){if(typeof raw==="string")continue;if(!isPlainObject(raw))return{ok:!1,reason:`theme.${slot} must be a string or a { dark, light } object (got ${raw===null?"null":Array.isArray(raw)?"array":typeof raw})`};let variant=raw;if(typeof variant.dark!=="string")return{ok:!1,reason:`theme.${slot}.dark must be a string`};if(typeof variant.light!=="string")return{ok:!1,reason:`theme.${slot}.light must be a string`}}if("$schema"in obj&&obj.$schema!==void 0&&typeof obj.$schema!=="string")return{ok:!1,reason:"`$schema` must be a string when present"};return{ok:!0,theme:obj}}import{readFileSync,readdirSync}from"fs";import{join}from"path";function userThemesDir(){return join(roveStateDir(),"themes")}function loadUserThemes(){let dir=userThemesDir(),entries;try{entries=readdirSync(dir)}catch{return[]}let out=[];for(let file of entries){if(!file.endsWith(".json"))continue;let path=join(dir,file),parsed;try{let text=readFileSync(path,"utf8");parsed=JSON.parse(text)}catch(err){let msg=errorMessage(err);console.warn(`[rove] skipping user theme ${path}: invalid JSON \u2014 ${msg}`);continue}let result=validateTheme(parsed);if(!result.ok){console.warn(`[rove] skipping user theme ${path}: ${result.reason}`);continue}let name=file.slice(0,-5);out.push({name,theme:result.theme})}return out}
2
+ import{errorMessage}from"./chunk-2brn8e1y.js";import{roveStateDir}from"./chunk-ch9b1d5y.js";var claude_default={$schema:"https://opencode.ai/theme.json",defs:{darkBg:"#141413",darkBgRaised:"#1A1917",darkBgInset:"#2B2A27",darkBgMenu:"#33312E",darkBorderSubtle:"#2B2A27",darkBorder:"#3A3835",darkBorderActive:"#5C5853",darkText:"#EAE7DF",darkTextMuted:"#A9A39A",darkTextSubtle:"#6B665F",darkPrimary:"#CC785C",darkSecondary:"#D4967E",darkAccent:"#CC785C",darkAccentHover:"#E0AB96",darkRed:"#D47563",darkOrange:"#D97757",darkYellow:"#E8C96B",darkGreen:"#9ACA86",darkBlue:"#61AAF2",darkViolet:"#9B87F5",darkTerracotta:"#BF4D43",lightBg:"#FAF9F5",lightBgRaised:"#F0EEE6",lightBgInset:"#EAE7DF",lightBgMenu:"#E2DED4",lightBorderSubtle:"#EAE7DF",lightBorder:"#D9D5CC",lightBorderActive:"#A9A39A",lightText:"#1A1917",lightTextMuted:"#6B665F",lightTextSubtle:"#8D877D",lightPrimary:"#C96442",lightSecondary:"#B85F3D",lightAccent:"#CC785C",lightAccentHover:"#B85F3D",lightRed:"#A84B3A",lightOrange:"#C96442",lightYellow:"#8A6220",lightGreen:"#2E7C4C",lightBlue:"#207FDE",lightViolet:"#7B5BB6",lightTerracotta:"#BF4D43"},theme:{primary:{dark:"darkPrimary",light:"lightPrimary"},secondary:{dark:"darkSecondary",light:"lightSecondary"},accent:{dark:"darkAccent",light:"lightAccent"},error:{dark:"darkRed",light:"lightRed"},warning:{dark:"darkYellow",light:"lightYellow"},success:{dark:"darkGreen",light:"lightGreen"},info:{dark:"darkBlue",light:"lightBlue"},text:{dark:"darkText",light:"lightText"},textMuted:{dark:"darkTextMuted",light:"lightTextMuted"},background:{dark:"darkBg",light:"lightBg"},backgroundPanel:{dark:"darkBgRaised",light:"lightBgRaised"},backgroundElement:{dark:"darkBgInset",light:"lightBgInset"},backgroundMenu:{dark:"darkBgMenu",light:"lightBgMenu"},backgroundDialog:{dark:"darkBgRaised",light:"lightBgRaised"},border:{dark:"darkBorder",light:"lightBorder"},borderActive:{dark:"darkBorderActive",light:"lightBorderActive"},borderSubtle:{dark:"darkBorderSubtle",light:"lightBorderSubtle"},diffAdded:{dark:"darkGreen",light:"lightGreen"},diffRemoved:{dark:"darkRed",light:"lightRed"},diffContext:{dark:"darkTextMuted",light:"lightTextSubtle"},diffHunkHeader:{dark:"darkTextMuted",light:"lightTextSubtle"},diffHighlightAdded:{dark:"#B5E0A0",light:"#1F6638"},diffHighlightRemoved:{dark:"#E89180",light:"#8A3A2C"},diffAddedBg:{dark:"#1F2A1F",light:"#E5EEDF"},diffRemovedBg:{dark:"#2A1F1C",light:"#F5DAD3"},diffContextBg:{dark:"darkBgRaised",light:"lightBgRaised"},diffLineNumber:{dark:"darkTextSubtle",light:"lightTextSubtle"},diffAddedLineNumberBg:{dark:"#1A2419",light:"#D5E2CC"},diffRemovedLineNumberBg:{dark:"#241915",light:"#EBC8BE"},markdownText:{dark:"darkText",light:"lightText"},markdownHeading:{dark:"darkPrimary",light:"lightPrimary"},markdownLink:{dark:"darkAccent",light:"lightAccent"},markdownLinkText:{dark:"darkBlue",light:"lightBlue"},markdownCode:{dark:"darkSecondary",light:"lightSecondary"},markdownBlockQuote:{dark:"darkTextMuted",light:"lightTextMuted"},markdownEmph:{dark:"darkYellow",light:"lightYellow"},markdownStrong:{dark:"darkPrimary",light:"lightPrimary"},markdownHorizontalRule:{dark:"darkTextMuted",light:"lightTextMuted"},markdownListItem:{dark:"darkAccent",light:"lightAccent"},markdownListEnumeration:{dark:"darkBlue",light:"lightBlue"},markdownImage:{dark:"darkAccent",light:"lightAccent"},markdownImageText:{dark:"darkBlue",light:"lightBlue"},markdownCodeBlock:{dark:"darkText",light:"lightText"},markdownQuote:{dark:"darkTextMuted",light:"lightTextMuted"},syntaxComment:{dark:"darkTextSubtle",light:"lightTextSubtle"},syntaxKeyword:{dark:"darkPrimary",light:"lightPrimary"},syntaxFunction:{dark:"darkBlue",light:"lightBlue"},syntaxVariable:{dark:"darkText",light:"lightText"},syntaxString:{dark:"darkGreen",light:"lightGreen"},syntaxNumber:{dark:"darkOrange",light:"lightOrange"},syntaxType:{dark:"darkViolet",light:"lightViolet"},syntaxOperator:{dark:"darkSecondary",light:"lightSecondary"},syntaxPunctuation:{dark:"darkText",light:"lightText"},selectedListItemText:{dark:"darkBg",light:"lightBg"}}};var conductor_default={$schema:"https://opencode.ai/theme.json",defs:{darkStep1:"#0a0a0a",darkStep2:"#111111",darkStep3:"#181818",darkStep4:"#1f1f1f",darkStep5:"#2a2a2a",darkStep6:"#363636",darkStep7:"#444444",darkStep8:"#5a5a5a",darkStep9:"#7a7a7a",darkStep10:"#9a9a9a",darkStep11:"#909090",darkStep12:"#e8e8e8",darkAccent:"#7da5c8",darkAccentBright:"#9bc3e3",darkRed:"#e06c75",darkOrange:"#d6a668",darkGreen:"#7fd88f",darkCyan:"#7da5c8",darkYellow:"#d6a668",lightStep1:"#fafafa",lightStep2:"#f3f3f3",lightStep3:"#ececec",lightStep4:"#e2e2e2",lightStep5:"#d4d4d4",lightStep6:"#bdbdbd",lightStep7:"#9c9c9c",lightStep8:"#7c7c7c",lightStep9:"#5b5b5b",lightStep10:"#404040",lightStep11:"#6c6c6c",lightStep12:"#1a1a1a",lightAccent:"#3d6f9f",lightAccentBright:"#1a4f87",lightRed:"#c9343a",lightOrange:"#a06b1a",lightGreen:"#3d9a57",lightCyan:"#3d6f9f",lightYellow:"#a06b1a"},theme:{primary:{dark:"darkStep12",light:"lightStep12"},secondary:{dark:"darkAccentBright",light:"lightAccentBright"},accent:{dark:"darkAccent",light:"lightAccent"},error:{dark:"darkRed",light:"lightRed"},warning:{dark:"darkOrange",light:"lightOrange"},success:{dark:"darkGreen",light:"lightGreen"},info:{dark:"darkCyan",light:"lightCyan"},text:{dark:"darkStep12",light:"lightStep12"},textMuted:{dark:"darkStep11",light:"lightStep11"},background:{dark:"darkStep1",light:"lightStep1"},backgroundPanel:{dark:"darkStep2",light:"lightStep2"},backgroundElement:{dark:"darkStep3",light:"lightStep3"},backgroundMenu:{dark:"darkStep4",light:"lightStep4"},border:{dark:"darkStep6",light:"lightStep6"},borderActive:{dark:"darkStep8",light:"lightStep8"},borderSubtle:{dark:"darkStep4",light:"lightStep4"},diffAdded:{dark:"#7fd88f",light:"#3d9a57"},diffRemoved:{dark:"#e06c75",light:"#c9343a"},diffContext:{dark:"darkStep10",light:"lightStep10"},diffHunkHeader:{dark:"darkStep10",light:"lightStep10"},diffHighlightAdded:{dark:"#9be5ad",light:"#2d7a3f"},diffHighlightRemoved:{dark:"#f08490",light:"#a82530"},diffAddedBg:{dark:"#15241a",light:"#d8efdc"},diffRemovedBg:{dark:"#2a1518",light:"#f5dadc"},diffContextBg:{dark:"darkStep2",light:"lightStep2"},diffLineNumber:{dark:"darkStep9",light:"lightStep9"},diffAddedLineNumberBg:{dark:"#0f1c14",light:"#c5deca"},diffRemovedLineNumberBg:{dark:"#221012",light:"#e5c5c8"},markdownText:{dark:"darkStep12",light:"lightStep12"},markdownHeading:{dark:"darkStep12",light:"lightStep12"},markdownLink:{dark:"darkAccent",light:"lightAccent"},markdownCode:{dark:"darkAccentBright",light:"lightAccentBright"},markdownCodeBlock:{dark:"darkStep12",light:"lightStep12"},markdownQuote:{dark:"darkStep11",light:"lightStep11"},selectedListItemText:{dark:"darkStep1",light:"lightStep1"}}};var tokyonight_default={$schema:"https://opencode.ai/theme.json",defs:{darkStep1:"#1a1b26",darkStep2:"#1e2030",darkStep3:"#222436",darkStep4:"#292e42",darkStep5:"#3b4261",darkStep6:"#545c7e",darkStep7:"#737aa2",darkStep8:"#9099b2",darkStep9:"#82aaff",darkStep10:"#89b4fa",darkStep11:"#828bb8",darkStep12:"#c8d3f5",darkRed:"#ff757f",darkOrange:"#ff966c",darkYellow:"#ffc777",darkGreen:"#c3e88d",darkCyan:"#86e1fc",darkPurple:"#c099ff",lightStep1:"#e1e2e7",lightStep2:"#d5d6db",lightStep3:"#c8c9ce",lightStep4:"#b9bac1",lightStep5:"#a8aecb",lightStep6:"#9699a8",lightStep7:"#737a8c",lightStep8:"#5a607d",lightStep9:"#2e7de9",lightStep10:"#1a6ce7",lightStep11:"#8990a3",lightStep12:"#3760bf",lightRed:"#f52a65",lightOrange:"#b15c00",lightYellow:"#8c6c3e",lightGreen:"#587539",lightCyan:"#007197",lightPurple:"#9854f1"},theme:{primary:{dark:"darkStep9",light:"lightStep9"},secondary:{dark:"darkPurple",light:"lightPurple"},accent:{dark:"darkOrange",light:"lightOrange"},error:{dark:"darkRed",light:"lightRed"},warning:{dark:"darkOrange",light:"lightOrange"},success:{dark:"darkGreen",light:"lightGreen"},info:{dark:"darkStep9",light:"lightStep9"},text:{dark:"darkStep12",light:"lightStep12"},textMuted:{dark:"darkStep11",light:"lightStep11"},background:{dark:"darkStep1",light:"lightStep1"},backgroundPanel:{dark:"darkStep2",light:"lightStep2"},backgroundElement:{dark:"darkStep3",light:"lightStep3"},border:{dark:"darkStep7",light:"lightStep7"},borderActive:{dark:"darkStep8",light:"lightStep8"},borderSubtle:{dark:"darkStep6",light:"lightStep6"},diffAdded:{dark:"#4fd6be",light:"#1e725c"},diffRemoved:{dark:"#c53b53",light:"#c53b53"},diffContext:{dark:"#828bb8",light:"#7086b5"},diffHunkHeader:{dark:"#828bb8",light:"#7086b5"},diffHighlightAdded:{dark:"#b8db87",light:"#4db380"},diffHighlightRemoved:{dark:"#e26a75",light:"#f52a65"},diffAddedBg:{dark:"#20303b",light:"#d5e5d5"},diffRemovedBg:{dark:"#37222c",light:"#f7d8db"},diffContextBg:{dark:"darkStep2",light:"lightStep2"},diffLineNumber:{dark:"#8f909a",light:"#59595b"},diffAddedLineNumberBg:{dark:"#1b2b34",light:"#c5d5c5"},diffRemovedLineNumberBg:{dark:"#2d1f26",light:"#e7c8cb"},markdownText:{dark:"darkStep12",light:"lightStep12"},markdownHeading:{dark:"darkPurple",light:"lightPurple"},markdownLink:{dark:"darkStep9",light:"lightStep9"},markdownLinkText:{dark:"darkCyan",light:"lightCyan"},markdownCode:{dark:"darkGreen",light:"lightGreen"},markdownBlockQuote:{dark:"darkYellow",light:"lightYellow"},markdownEmph:{dark:"darkYellow",light:"lightYellow"},markdownStrong:{dark:"darkOrange",light:"lightOrange"},markdownHorizontalRule:{dark:"darkStep11",light:"lightStep11"},markdownListItem:{dark:"darkStep9",light:"lightStep9"},markdownListEnumeration:{dark:"darkCyan",light:"lightCyan"},markdownImage:{dark:"darkStep9",light:"lightStep9"},markdownImageText:{dark:"darkCyan",light:"lightCyan"},markdownCodeBlock:{dark:"darkStep12",light:"lightStep12"},syntaxComment:{dark:"darkStep11",light:"lightStep11"},syntaxKeyword:{dark:"darkPurple",light:"lightPurple"},syntaxFunction:{dark:"darkStep9",light:"lightStep9"},syntaxVariable:{dark:"darkRed",light:"lightRed"},syntaxString:{dark:"darkGreen",light:"lightGreen"},syntaxNumber:{dark:"darkOrange",light:"lightOrange"},syntaxType:{dark:"darkYellow",light:"lightYellow"},syntaxOperator:{dark:"darkCyan",light:"lightCyan"},syntaxPunctuation:{dark:"darkStep12",light:"lightStep12"}}};var BUNDLED_THEME_JSONS={claude:claude_default,conductor:conductor_default,tokyonight:tokyonight_default};function isPlainObject(v){return typeof v==="object"&&v!==null&&!Array.isArray(v)}function validateTheme(value){if(!isPlainObject(value))return{ok:!1,reason:"theme must be a JSON object at the top level"};let obj=value;if(!("theme"in obj))return{ok:!1,reason:"missing required key `theme`"};let theme=obj.theme;if(!isPlainObject(theme))return{ok:!1,reason:"`theme` must be an object map"};if("defs"in obj&&obj.defs!==void 0){if(!isPlainObject(obj.defs))return{ok:!1,reason:"`defs` must be an object map"};for(let[k,v]of Object.entries(obj.defs))if(typeof v!=="string")return{ok:!1,reason:`defs.${k} must be a string (hex like "#abc" or a ref name)`}}for(let[slot,raw]of Object.entries(theme)){if(typeof raw==="string")continue;if(!isPlainObject(raw))return{ok:!1,reason:`theme.${slot} must be a string or a { dark, light } object (got ${raw===null?"null":Array.isArray(raw)?"array":typeof raw})`};let variant=raw;if(typeof variant.dark!=="string")return{ok:!1,reason:`theme.${slot}.dark must be a string`};if(typeof variant.light!=="string")return{ok:!1,reason:`theme.${slot}.light must be a string`}}if("$schema"in obj&&obj.$schema!==void 0&&typeof obj.$schema!=="string")return{ok:!1,reason:"`$schema` must be a string when present"};return{ok:!0,theme:obj}}import{readFileSync,readdirSync}from"fs";import{join}from"path";function userThemesDir(){return join(roveStateDir(),"themes")}function loadUserThemes(){let dir=userThemesDir(),entries;try{entries=readdirSync(dir)}catch{return[]}let out=[];for(let file of entries){if(!file.endsWith(".json"))continue;let path=join(dir,file),parsed;try{let text=readFileSync(path,"utf8");parsed=JSON.parse(text)}catch(err){let msg=errorMessage(err);console.warn(`[rove] skipping user theme ${path}: invalid JSON \u2014 ${msg}`);continue}let result=validateTheme(parsed);if(!result.ok){console.warn(`[rove] skipping user theme ${path}: ${result.reason}`);continue}let name=file.slice(0,-5);out.push({name,theme:result.theme})}return out}
3
3
  export{BUNDLED_THEME_JSONS,validateTheme,userThemesDir,loadUserThemes};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{KobeDaemonClient,RpcTimeoutError}from"./chunk-0wnfq5sx.js";import"./chunk-7j5372wb.js";import"./chunk-mnqxgvyb.js";import"./chunk-k2ckx8zw.js";import"./chunk-pw6yfj10.js";import"./chunk-mcdv19rs.js";import"./chunk-r3k9rbwm.js";import"./chunk-wqfp8d9w.js";export{RpcTimeoutError,KobeDaemonClient};