relay-ide 0.1.0

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 (506) hide show
  1. package/README.md +259 -0
  2. package/dist/bin/claude-remote-cli.js +390 -0
  3. package/dist/bin/relay-ide.js +390 -0
  4. package/dist/frontend/assets/abap-BdImnpbu.js +1 -0
  5. package/dist/frontend/assets/actionscript-3-CoDkCxhg.js +1 -0
  6. package/dist/frontend/assets/ada-bCR0ucgS.js +1 -0
  7. package/dist/frontend/assets/andromeeda-C4gqWexZ.js +1 -0
  8. package/dist/frontend/assets/angular-html-DA-rfuFy.js +1 -0
  9. package/dist/frontend/assets/angular-ts-BrjP3tb8.js +1 -0
  10. package/dist/frontend/assets/apache-Pmp26Uib.js +1 -0
  11. package/dist/frontend/assets/apex-D8_7TLub.js +1 -0
  12. package/dist/frontend/assets/apl-CORt7UWP.js +1 -0
  13. package/dist/frontend/assets/applescript-Co6uUVPk.js +1 -0
  14. package/dist/frontend/assets/ara-BRHolxvo.js +1 -0
  15. package/dist/frontend/assets/asciidoc-Ve4PFQV2.js +1 -0
  16. package/dist/frontend/assets/asm-D_Q5rh1f.js +1 -0
  17. package/dist/frontend/assets/astro-HNnZUWAn.js +1 -0
  18. package/dist/frontend/assets/aurora-x-D-2ljcwZ.js +1 -0
  19. package/dist/frontend/assets/awk-DMzUqQB5.js +1 -0
  20. package/dist/frontend/assets/ayu-dark-DYE7WIF3.js +1 -0
  21. package/dist/frontend/assets/ayu-light-BA47KaF1.js +1 -0
  22. package/dist/frontend/assets/ayu-mirage-32ctXXKs.js +1 -0
  23. package/dist/frontend/assets/ballerina-BFfxhgS-.js +1 -0
  24. package/dist/frontend/assets/bat-BkioyH1T.js +1 -0
  25. package/dist/frontend/assets/beancount-k_qm7-4y.js +1 -0
  26. package/dist/frontend/assets/berry-uYugtg8r.js +1 -0
  27. package/dist/frontend/assets/bibtex-CHM0blh-.js +1 -0
  28. package/dist/frontend/assets/bicep-Bmn6On1c.js +1 -0
  29. package/dist/frontend/assets/bird2-BIv1doCn.js +1 -0
  30. package/dist/frontend/assets/blade-BjGOyj-B.js +1 -0
  31. package/dist/frontend/assets/bsl-BO_Y6i37.js +1 -0
  32. package/dist/frontend/assets/c-BIGW1oBm.js +1 -0
  33. package/dist/frontend/assets/c3-eo99z4R2.js +1 -0
  34. package/dist/frontend/assets/cadence-Bv_4Rxtq.js +1 -0
  35. package/dist/frontend/assets/cairo-KRGpt6FW.js +1 -0
  36. package/dist/frontend/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  37. package/dist/frontend/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  38. package/dist/frontend/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  39. package/dist/frontend/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  40. package/dist/frontend/assets/clarity-D53aC0YG.js +1 -0
  41. package/dist/frontend/assets/clojure-P80f7IUj.js +1 -0
  42. package/dist/frontend/assets/cmake-D1j8_8rp.js +1 -0
  43. package/dist/frontend/assets/cobol-nBiQ_Alo.js +1 -0
  44. package/dist/frontend/assets/codeowners-Bp6g37R7.js +1 -0
  45. package/dist/frontend/assets/codeql-DsOJ9woJ.js +1 -0
  46. package/dist/frontend/assets/coffee-Ch7k5sss.js +1 -0
  47. package/dist/frontend/assets/common-lisp-Cg-RD9OK.js +1 -0
  48. package/dist/frontend/assets/coq-DkFqJrB1.js +1 -0
  49. package/dist/frontend/assets/cpp-CofmeUqb.js +1 -0
  50. package/dist/frontend/assets/crystal-DNxU26gB.js +1 -0
  51. package/dist/frontend/assets/csharp-COcwbKMJ.js +1 -0
  52. package/dist/frontend/assets/css-CLj8gQPS.js +1 -0
  53. package/dist/frontend/assets/csv-fuZLfV_i.js +1 -0
  54. package/dist/frontend/assets/cue-D82EKSYY.js +1 -0
  55. package/dist/frontend/assets/cypher-COkxafJQ.js +1 -0
  56. package/dist/frontend/assets/d-85-TOEBH.js +1 -0
  57. package/dist/frontend/assets/dark-plus-C3mMm8J8.js +1 -0
  58. package/dist/frontend/assets/dart-bE4Kk8sk.js +1 -0
  59. package/dist/frontend/assets/dax-CEL-wOlO.js +1 -0
  60. package/dist/frontend/assets/desktop-BmXAJ9_W.js +1 -0
  61. package/dist/frontend/assets/diff-D97Zzqfu.js +1 -0
  62. package/dist/frontend/assets/docker-BcOcwvcX.js +1 -0
  63. package/dist/frontend/assets/dotenv-Da5cRb03.js +1 -0
  64. package/dist/frontend/assets/dracula-BzJJZx-M.js +1 -0
  65. package/dist/frontend/assets/dracula-soft-BXkSAIEj.js +1 -0
  66. package/dist/frontend/assets/dream-maker-BtqSS_iP.js +1 -0
  67. package/dist/frontend/assets/edge-FbVlp4U3.js +1 -0
  68. package/dist/frontend/assets/elixir-CkH2-t6x.js +1 -0
  69. package/dist/frontend/assets/elm-DbKCFpqz.js +1 -0
  70. package/dist/frontend/assets/emacs-lisp-CXvaQtF9.js +1 -0
  71. package/dist/frontend/assets/erb-BYCe7drp.js +1 -0
  72. package/dist/frontend/assets/erlang-DsQrWhSR.js +1 -0
  73. package/dist/frontend/assets/everforest-dark-BgDCqdQA.js +1 -0
  74. package/dist/frontend/assets/everforest-light-C8M2exoo.js +1 -0
  75. package/dist/frontend/assets/fennel-BYunw83y.js +1 -0
  76. package/dist/frontend/assets/fish-BvzEVeQv.js +1 -0
  77. package/dist/frontend/assets/fluent-C4IJs8-o.js +1 -0
  78. package/dist/frontend/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
  79. package/dist/frontend/assets/fortran-free-form-BxgE0vQu.js +1 -0
  80. package/dist/frontend/assets/fsharp-CXgrBDvD.js +1 -0
  81. package/dist/frontend/assets/gdresource-BOOCDP_w.js +1 -0
  82. package/dist/frontend/assets/gdscript-C5YyOfLZ.js +1 -0
  83. package/dist/frontend/assets/gdshader-DkwncUOv.js +1 -0
  84. package/dist/frontend/assets/genie-D0YGMca9.js +1 -0
  85. package/dist/frontend/assets/gherkin-DyxjwDmM.js +1 -0
  86. package/dist/frontend/assets/git-commit-F4YmCXRG.js +1 -0
  87. package/dist/frontend/assets/git-rebase-r7XF79zn.js +1 -0
  88. package/dist/frontend/assets/github-dark-DHJKELXO.js +1 -0
  89. package/dist/frontend/assets/github-dark-default-Cuk6v7N8.js +1 -0
  90. package/dist/frontend/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  91. package/dist/frontend/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  92. package/dist/frontend/assets/github-light-DAi9KRSo.js +1 -0
  93. package/dist/frontend/assets/github-light-default-D7oLnXFd.js +1 -0
  94. package/dist/frontend/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  95. package/dist/frontend/assets/gleam-BspZqrRM.js +1 -0
  96. package/dist/frontend/assets/glimmer-js-ByusRIyA.js +1 -0
  97. package/dist/frontend/assets/glimmer-ts-BfAWNZQY.js +1 -0
  98. package/dist/frontend/assets/glsl-DplSGwfg.js +1 -0
  99. package/dist/frontend/assets/gn-n2N0HUVH.js +1 -0
  100. package/dist/frontend/assets/gnuplot-DdkO51Og.js +1 -0
  101. package/dist/frontend/assets/go-C27-OAKa.js +1 -0
  102. package/dist/frontend/assets/graphql-ChdNCCLP.js +1 -0
  103. package/dist/frontend/assets/groovy-gcz8RCvz.js +1 -0
  104. package/dist/frontend/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  105. package/dist/frontend/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  106. package/dist/frontend/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  107. package/dist/frontend/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  108. package/dist/frontend/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  109. package/dist/frontend/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  110. package/dist/frontend/assets/hack-i7_Ulhet.js +1 -0
  111. package/dist/frontend/assets/haml-D5jkg6IW.js +1 -0
  112. package/dist/frontend/assets/handlebars-BpdQsYii.js +1 -0
  113. package/dist/frontend/assets/haskell-Df6bDoY_.js +1 -0
  114. package/dist/frontend/assets/haxe-CzTSHFRz.js +1 -0
  115. package/dist/frontend/assets/hcl-BWvSN4gD.js +1 -0
  116. package/dist/frontend/assets/hjson-D5-asLiD.js +1 -0
  117. package/dist/frontend/assets/hlsl-D3lLCCz7.js +1 -0
  118. package/dist/frontend/assets/horizon-BUw7H-hv.js +1 -0
  119. package/dist/frontend/assets/horizon-bright-CUuTKBJd.js +1 -0
  120. package/dist/frontend/assets/houston-DnULxvSX.js +1 -0
  121. package/dist/frontend/assets/html-derivative-DlHx6ybY.js +1 -0
  122. package/dist/frontend/assets/html-pp8916En.js +1 -0
  123. package/dist/frontend/assets/http-jrhK8wxY.js +1 -0
  124. package/dist/frontend/assets/hurl-irOxFIW8.js +1 -0
  125. package/dist/frontend/assets/hxml-Bvhsp5Yf.js +1 -0
  126. package/dist/frontend/assets/hy-DFXneXwc.js +1 -0
  127. package/dist/frontend/assets/imba-DGztddWO.js +1 -0
  128. package/dist/frontend/assets/ini-BEwlwnbL.js +1 -0
  129. package/dist/frontend/assets/java-CylS5w8V.js +1 -0
  130. package/dist/frontend/assets/javascript-wDzz0qaB.js +1 -0
  131. package/dist/frontend/assets/jinja-f2NsQr07.js +1 -0
  132. package/dist/frontend/assets/jison-wvAkD_A8.js +1 -0
  133. package/dist/frontend/assets/json-Cp-IABpG.js +1 -0
  134. package/dist/frontend/assets/json5-C9tS-k6U.js +1 -0
  135. package/dist/frontend/assets/jsonc-Des-eS-w.js +1 -0
  136. package/dist/frontend/assets/jsonl-DcaNXYhu.js +1 -0
  137. package/dist/frontend/assets/jsonnet-DFQXde-d.js +1 -0
  138. package/dist/frontend/assets/jssm-C2t-YnRu.js +1 -0
  139. package/dist/frontend/assets/jsx-g9-lgVsj.js +1 -0
  140. package/dist/frontend/assets/julia-CxzCAyBv.js +1 -0
  141. package/dist/frontend/assets/just-VxiPbLrw.js +1 -0
  142. package/dist/frontend/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  143. package/dist/frontend/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  144. package/dist/frontend/assets/kanagawa-wave-DWedfzmr.js +1 -0
  145. package/dist/frontend/assets/kdl-DV7GczEv.js +1 -0
  146. package/dist/frontend/assets/kotlin-BdnUsdx6.js +1 -0
  147. package/dist/frontend/assets/kusto-wEQ09or8.js +1 -0
  148. package/dist/frontend/assets/laserwave-DUszq2jm.js +1 -0
  149. package/dist/frontend/assets/latex-CWtU0Tv5.js +1 -0
  150. package/dist/frontend/assets/lean-BZvkOJ9d.js +1 -0
  151. package/dist/frontend/assets/less-B1dDrJ26.js +1 -0
  152. package/dist/frontend/assets/light-plus-B7mTdjB0.js +1 -0
  153. package/dist/frontend/assets/liquid-C0sCDyMI.js +1 -0
  154. package/dist/frontend/assets/llvm-DjAJT7YJ.js +1 -0
  155. package/dist/frontend/assets/log-2UxHyX5q.js +1 -0
  156. package/dist/frontend/assets/logo-BtOb2qkB.js +1 -0
  157. package/dist/frontend/assets/lua-BaeVxFsk.js +1 -0
  158. package/dist/frontend/assets/luau-C-HG3fhB.js +1 -0
  159. package/dist/frontend/assets/main-CL5_Wlhv.css +32 -0
  160. package/dist/frontend/assets/main-Czet4Z1x.js +371 -0
  161. package/dist/frontend/assets/make-CHLpvVh8.js +1 -0
  162. package/dist/frontend/assets/markdown-Cvjx9yec.js +1 -0
  163. package/dist/frontend/assets/marko-DjSrsDqO.js +1 -0
  164. package/dist/frontend/assets/material-theme-D5KoaKCx.js +1 -0
  165. package/dist/frontend/assets/material-theme-darker-BfHTSMKl.js +1 -0
  166. package/dist/frontend/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  167. package/dist/frontend/assets/material-theme-ocean-CyktbL80.js +1 -0
  168. package/dist/frontend/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  169. package/dist/frontend/assets/matlab-D7o27uSR.js +1 -0
  170. package/dist/frontend/assets/mdc-DTYItulj.js +1 -0
  171. package/dist/frontend/assets/mdx-Cmh6b_Ma.js +1 -0
  172. package/dist/frontend/assets/mermaid-mWjccvbQ.js +1 -0
  173. package/dist/frontend/assets/min-dark-CafNBF8u.js +1 -0
  174. package/dist/frontend/assets/min-light-CTRr51gU.js +1 -0
  175. package/dist/frontend/assets/mipsasm-CKIfxQSi.js +1 -0
  176. package/dist/frontend/assets/mojo-rZm6bMo-.js +1 -0
  177. package/dist/frontend/assets/monokai-D4h5O-jR.js +1 -0
  178. package/dist/frontend/assets/moonbit-_H4v1dQx.js +1 -0
  179. package/dist/frontend/assets/move-IF9eRakj.js +1 -0
  180. package/dist/frontend/assets/narrat-DRg8JJMk.js +1 -0
  181. package/dist/frontend/assets/nextflow-C-mBbutL.js +1 -0
  182. package/dist/frontend/assets/nextflow-groovy-vE_lwT2v.js +1 -0
  183. package/dist/frontend/assets/nginx-BpAMiNFr.js +1 -0
  184. package/dist/frontend/assets/night-owl-C39BiMTA.js +1 -0
  185. package/dist/frontend/assets/night-owl-light-CMTm3GFP.js +1 -0
  186. package/dist/frontend/assets/nim-BIad80T-.js +1 -0
  187. package/dist/frontend/assets/nix-CwoSXNpI.js +1 -0
  188. package/dist/frontend/assets/nord-Ddv68eIx.js +1 -0
  189. package/dist/frontend/assets/nushell-Cz2AlsmD.js +1 -0
  190. package/dist/frontend/assets/objective-c-DXmwc3jG.js +1 -0
  191. package/dist/frontend/assets/objective-cpp-CLxacb5B.js +1 -0
  192. package/dist/frontend/assets/ocaml-C0hk2d4L.js +1 -0
  193. package/dist/frontend/assets/odin-BBf5iR-q.js +1 -0
  194. package/dist/frontend/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  195. package/dist/frontend/assets/one-light-C3Wv6jpd.js +1 -0
  196. package/dist/frontend/assets/openscad-C4EeE6gA.js +1 -0
  197. package/dist/frontend/assets/pascal-D93ZcfNL.js +1 -0
  198. package/dist/frontend/assets/perl-NvoQZIq0.js +1 -0
  199. package/dist/frontend/assets/php-R6g_5hLQ.js +1 -0
  200. package/dist/frontend/assets/pkl-u5AG7uiY.js +1 -0
  201. package/dist/frontend/assets/plastic-3e1v2bzS.js +1 -0
  202. package/dist/frontend/assets/plsql-ChMvpjG-.js +1 -0
  203. package/dist/frontend/assets/po-BTJTHyun.js +1 -0
  204. package/dist/frontend/assets/poimandres-CS3Unz2-.js +1 -0
  205. package/dist/frontend/assets/polar-C0HS_06l.js +1 -0
  206. package/dist/frontend/assets/postcss-CXtECtnM.js +1 -0
  207. package/dist/frontend/assets/powerquery-CEu0bR-o.js +1 -0
  208. package/dist/frontend/assets/powershell-Dpen1YoG.js +1 -0
  209. package/dist/frontend/assets/prisma-Dd19v3D-.js +1 -0
  210. package/dist/frontend/assets/prolog-CbFg5uaA.js +1 -0
  211. package/dist/frontend/assets/proto-C7zT0LnQ.js +1 -0
  212. package/dist/frontend/assets/pug-DKIMFp6K.js +1 -0
  213. package/dist/frontend/assets/puppet-BMWR74SV.js +1 -0
  214. package/dist/frontend/assets/purescript-CklMAg4u.js +1 -0
  215. package/dist/frontend/assets/python-B6aJPvgy.js +1 -0
  216. package/dist/frontend/assets/qml-3beO22l8.js +1 -0
  217. package/dist/frontend/assets/qmldir-C8lEn-DE.js +1 -0
  218. package/dist/frontend/assets/qss-IeuSbFQv.js +1 -0
  219. package/dist/frontend/assets/r-Dspwwk_N.js +1 -0
  220. package/dist/frontend/assets/racket-BqYA7rlc.js +1 -0
  221. package/dist/frontend/assets/raku-DXvB9xmW.js +1 -0
  222. package/dist/frontend/assets/razor-BDqjjVU7.js +1 -0
  223. package/dist/frontend/assets/red-bN70gL4F.js +1 -0
  224. package/dist/frontend/assets/reg-C-SQnVFl.js +1 -0
  225. package/dist/frontend/assets/regexp-CDVJQ6XC.js +1 -0
  226. package/dist/frontend/assets/rel-C3B-1QV4.js +1 -0
  227. package/dist/frontend/assets/riscv-BM1_JUlF.js +1 -0
  228. package/dist/frontend/assets/ron-D8l8udqQ.js +1 -0
  229. package/dist/frontend/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
  230. package/dist/frontend/assets/rose-pine-moon-D4_iv3hh.js +1 -0
  231. package/dist/frontend/assets/rose-pine-qdsjHGoJ.js +1 -0
  232. package/dist/frontend/assets/rosmsg-BJDFO7_C.js +1 -0
  233. package/dist/frontend/assets/rst-CRjBmOyv.js +1 -0
  234. package/dist/frontend/assets/ruby-Wjq7vjNf.js +1 -0
  235. package/dist/frontend/assets/rust-B1yitclQ.js +1 -0
  236. package/dist/frontend/assets/sas-cz2c8ADy.js +1 -0
  237. package/dist/frontend/assets/sass-Cj5Yp3dK.js +1 -0
  238. package/dist/frontend/assets/scala-C151Ov-r.js +1 -0
  239. package/dist/frontend/assets/scheme-C98Dy4si.js +1 -0
  240. package/dist/frontend/assets/scss-D5BDwBP9.js +1 -0
  241. package/dist/frontend/assets/sdbl-DVxCFoDh.js +1 -0
  242. package/dist/frontend/assets/shaderlab-Dg9Lc6iA.js +1 -0
  243. package/dist/frontend/assets/shellscript-Yzrsuije.js +1 -0
  244. package/dist/frontend/assets/shellsession-BADoaaVG.js +1 -0
  245. package/dist/frontend/assets/slack-dark-BthQWCQV.js +1 -0
  246. package/dist/frontend/assets/slack-ochin-DqwNpetd.js +1 -0
  247. package/dist/frontend/assets/smalltalk-BERRCDM3.js +1 -0
  248. package/dist/frontend/assets/snazzy-light-Bw305WKR.js +1 -0
  249. package/dist/frontend/assets/solarized-dark-DXbdFlpD.js +1 -0
  250. package/dist/frontend/assets/solarized-light-L9t79GZl.js +1 -0
  251. package/dist/frontend/assets/solidity-rGO070M0.js +1 -0
  252. package/dist/frontend/assets/soy-8wufbnw4.js +1 -0
  253. package/dist/frontend/assets/sparql-rVzFXLq3.js +1 -0
  254. package/dist/frontend/assets/splunk-BtCnVYZw.js +1 -0
  255. package/dist/frontend/assets/sql-BLtJtn59.js +1 -0
  256. package/dist/frontend/assets/ssh-config-_ykCGR6B.js +1 -0
  257. package/dist/frontend/assets/stata-BH5u7GGu.js +1 -0
  258. package/dist/frontend/assets/stylus-BEDo0Tqx.js +1 -0
  259. package/dist/frontend/assets/surrealql-Bq5Q-fJD.js +1 -0
  260. package/dist/frontend/assets/svelte-Cy7k_4gC.js +1 -0
  261. package/dist/frontend/assets/swift-D82vCrfD.js +1 -0
  262. package/dist/frontend/assets/synthwave-84-CbfX1IO0.js +1 -0
  263. package/dist/frontend/assets/system-verilog-CnnmHF94.js +1 -0
  264. package/dist/frontend/assets/systemd-4A_iFExJ.js +1 -0
  265. package/dist/frontend/assets/talonscript-CkByrt1z.js +1 -0
  266. package/dist/frontend/assets/tasl-QIJgUcNo.js +1 -0
  267. package/dist/frontend/assets/tcl-dwOrl1Do.js +1 -0
  268. package/dist/frontend/assets/templ-DhtptRzy.js +1 -0
  269. package/dist/frontend/assets/terraform-BETggiCN.js +1 -0
  270. package/dist/frontend/assets/tex-idrVyKtj.js +1 -0
  271. package/dist/frontend/assets/tokyo-night-hegEt444.js +1 -0
  272. package/dist/frontend/assets/toml-vGWfd6FD.js +1 -0
  273. package/dist/frontend/assets/ts-tags-DQrlYJgV.js +1 -0
  274. package/dist/frontend/assets/tsv-B_m7g4N7.js +1 -0
  275. package/dist/frontend/assets/tsx-COt5Ahok.js +1 -0
  276. package/dist/frontend/assets/turtle-BsS91CYL.js +1 -0
  277. package/dist/frontend/assets/twig-xg9kU7Mw.js +1 -0
  278. package/dist/frontend/assets/typescript-BPQ3VLAy.js +1 -0
  279. package/dist/frontend/assets/typespec-CAFt9gP4.js +1 -0
  280. package/dist/frontend/assets/typst-DHCkPAjA.js +1 -0
  281. package/dist/frontend/assets/v-BcVCzyr7.js +1 -0
  282. package/dist/frontend/assets/vala-CsfeWuGM.js +1 -0
  283. package/dist/frontend/assets/vb-D17OF-Vu.js +1 -0
  284. package/dist/frontend/assets/verilog-BQ8w6xss.js +1 -0
  285. package/dist/frontend/assets/vesper-DU1UobuO.js +1 -0
  286. package/dist/frontend/assets/vhdl-CeAyd5Ju.js +1 -0
  287. package/dist/frontend/assets/viml-CJc9bBzg.js +1 -0
  288. package/dist/frontend/assets/vitesse-black-Bkuqu6BP.js +1 -0
  289. package/dist/frontend/assets/vitesse-dark-D0r3Knsf.js +1 -0
  290. package/dist/frontend/assets/vitesse-light-CVO1_9PV.js +1 -0
  291. package/dist/frontend/assets/vue-D2xRrEX4.js +1 -0
  292. package/dist/frontend/assets/vue-html-AaS7Mt5G.js +1 -0
  293. package/dist/frontend/assets/vue-vine-BoDAl6tE.js +1 -0
  294. package/dist/frontend/assets/vyper-CDx5xZoG.js +1 -0
  295. package/dist/frontend/assets/wasm-CG6Dc4jp.js +1 -0
  296. package/dist/frontend/assets/wasm-MzD3tlZU.js +1 -0
  297. package/dist/frontend/assets/wenyan-BV7otONQ.js +1 -0
  298. package/dist/frontend/assets/wgsl-Dx-B1_4e.js +1 -0
  299. package/dist/frontend/assets/wikitext-BhOHFoWU.js +1 -0
  300. package/dist/frontend/assets/wit-5i3qLPDT.js +1 -0
  301. package/dist/frontend/assets/wolfram-lXgVvXCa.js +1 -0
  302. package/dist/frontend/assets/xml-sdJ4AIDG.js +1 -0
  303. package/dist/frontend/assets/xsl-CtQFsRM5.js +1 -0
  304. package/dist/frontend/assets/yaml-Buea-lGh.js +1 -0
  305. package/dist/frontend/assets/zenscript-DVFEvuxE.js +1 -0
  306. package/dist/frontend/assets/zig-VOosw3JB.js +1 -0
  307. package/dist/frontend/icon-192.png +0 -0
  308. package/dist/frontend/icon-512.png +0 -0
  309. package/dist/frontend/icon.svg +8 -0
  310. package/dist/frontend/index.html +30 -0
  311. package/dist/frontend/manifest.json +25 -0
  312. package/dist/frontend/sw.js +66 -0
  313. package/dist/server/agent-events.js +39 -0
  314. package/dist/server/analytics.js +885 -0
  315. package/dist/server/auth.js +65 -0
  316. package/dist/server/belayer/executor.js +200 -0
  317. package/dist/server/belayer/intake.js +27 -0
  318. package/dist/server/belayer/pipeline.js +97 -0
  319. package/dist/server/belayer/pr-lifecycle.js +69 -0
  320. package/dist/server/belayer/prompts.js +154 -0
  321. package/dist/server/belayer/types.js +23 -0
  322. package/dist/server/branch-linker.js +137 -0
  323. package/dist/server/browser-content.js +145 -0
  324. package/dist/server/clipboard.js +63 -0
  325. package/dist/server/codex-hooks-adapter.js +93 -0
  326. package/dist/server/config.js +325 -0
  327. package/dist/server/gh-routes.js +163 -0
  328. package/dist/server/gh.js +276 -0
  329. package/dist/server/git-routes.js +154 -0
  330. package/dist/server/git.js +694 -0
  331. package/dist/server/github-app.js +218 -0
  332. package/dist/server/github-graphql.js +178 -0
  333. package/dist/server/hooks.js +373 -0
  334. package/dist/server/index.js +1549 -0
  335. package/dist/server/integration-github.js +137 -0
  336. package/dist/server/integration-jira.js +210 -0
  337. package/dist/server/integration-linear.js +176 -0
  338. package/dist/server/logger.js +18 -0
  339. package/dist/server/mobile-input-pipeline.js +129 -0
  340. package/dist/server/opencode-relay.js +53 -0
  341. package/dist/server/org-dashboard.js +241 -0
  342. package/dist/server/output-parsers/claude-parser.js +56 -0
  343. package/dist/server/output-parsers/codex-parser.js +13 -0
  344. package/dist/server/output-parsers/index.js +14 -0
  345. package/dist/server/output-parsers/null-parser.js +12 -0
  346. package/dist/server/output-parsers/opencode-parser.js +77 -0
  347. package/dist/server/pty-handler.js +586 -0
  348. package/dist/server/push.js +84 -0
  349. package/dist/server/review-poller.js +237 -0
  350. package/dist/server/sdk-handler.js +539 -0
  351. package/dist/server/service.js +189 -0
  352. package/dist/server/sessions.js +638 -0
  353. package/dist/server/telemetry.js +236 -0
  354. package/dist/server/ticket-transitions.js +166 -0
  355. package/dist/server/types.js +146 -0
  356. package/dist/server/utils.js +23 -0
  357. package/dist/server/watcher.js +661 -0
  358. package/dist/server/webhook-manager.js +547 -0
  359. package/dist/server/webhooks.js +73 -0
  360. package/dist/server/workspace-groups.js +363 -0
  361. package/dist/server/workspaces.js +1207 -0
  362. package/dist/server/ws.js +192 -0
  363. package/dist/test/EmptyState.spec.js +51 -0
  364. package/dist/test/action-coverage.test.js +139 -0
  365. package/dist/test/actions/registry.test.js +59 -0
  366. package/dist/test/actions/shortcuts.test.js +79 -0
  367. package/dist/test/agent-events.test.js +151 -0
  368. package/dist/test/analytics.test.js +158 -0
  369. package/dist/test/attention.test.js +91 -0
  370. package/dist/test/auth.test.js +105 -0
  371. package/dist/test/backend-state.test.js +47 -0
  372. package/dist/test/belayer-executor.test.js +33 -0
  373. package/dist/test/belayer-intake.test.js +44 -0
  374. package/dist/test/belayer-pipeline.test.js +113 -0
  375. package/dist/test/belayer-pr-lifecycle.test.js +26 -0
  376. package/dist/test/belayer-prompts.test.js +60 -0
  377. package/dist/test/belayer-types.test.js +69 -0
  378. package/dist/test/bin/claude-remote-cli.js +214 -0
  379. package/dist/test/boot-state.test.js +133 -0
  380. package/dist/test/branch-lifecycle.test.js +75 -0
  381. package/dist/test/branch-linker.test.js +236 -0
  382. package/dist/test/branch-rename.test.js +45 -0
  383. package/dist/test/branch-watcher.test.js +115 -0
  384. package/dist/test/browser-cli.test.js +91 -0
  385. package/dist/test/browser-content.test.js +93 -0
  386. package/dist/test/browser-tabs-ui.test.js +39 -0
  387. package/dist/test/changed-files-api.test.js +140 -0
  388. package/dist/test/clipboard.test.js +12 -0
  389. package/dist/test/codex-hooks-adapter.test.js +237 -0
  390. package/dist/test/components/EmptyState.spec.js +51 -0
  391. package/dist/test/components/ErrorToast.spec.js +65 -0
  392. package/dist/test/components/TuiCheckbox.spec.js +120 -0
  393. package/dist/test/components/TuiInput.spec.js +186 -0
  394. package/dist/test/components/leaf-component-migration.spec.js +104 -0
  395. package/dist/test/config-freshness.test.js +63 -0
  396. package/dist/test/config.test.js +813 -0
  397. package/dist/test/diff-summary.test.js +98 -0
  398. package/dist/test/display-state.test.js +179 -0
  399. package/dist/test/event-message-types.test.js +32 -0
  400. package/dist/test/file-tree-utils.test.js +167 -0
  401. package/dist/test/framework-types.test.js +183 -0
  402. package/dist/test/frameworks-api.test.js +93 -0
  403. package/dist/test/frontend/src/lib/pr-state.js +114 -0
  404. package/dist/test/fs-browse.test.js +246 -0
  405. package/dist/test/fuzzy-scorer.test.js +145 -0
  406. package/dist/test/gh-routes.test.js +156 -0
  407. package/dist/test/git-changed-files.test.js +152 -0
  408. package/dist/test/git-routes.test.js +146 -0
  409. package/dist/test/git-utils.test.js +68 -0
  410. package/dist/test/git-watcher.test.js +110 -0
  411. package/dist/test/git.test.js +140 -0
  412. package/dist/test/github-app.test.js +455 -0
  413. package/dist/test/github-graphql.test.js +301 -0
  414. package/dist/test/greetings.test.js +83 -0
  415. package/dist/test/hooks-agent-event.test.js +412 -0
  416. package/dist/test/hooks.test.js +149 -0
  417. package/dist/test/integration-github.test.js +220 -0
  418. package/dist/test/integration-jira.test.js +238 -0
  419. package/dist/test/integration-linear.test.js +293 -0
  420. package/dist/test/mobile-input.test.js +235 -0
  421. package/dist/test/opencode-relay.test.js +107 -0
  422. package/dist/test/org-dashboard.test.js +349 -0
  423. package/dist/test/output-parser.test.js +217 -0
  424. package/dist/test/paths.test.js +32 -0
  425. package/dist/test/pr-state.test.js +407 -0
  426. package/dist/test/pr-status.test.js +82 -0
  427. package/dist/test/presets.test.js +242 -0
  428. package/dist/test/pty-handler-multi-agent.test.js +149 -0
  429. package/dist/test/pty-handler.test.js +146 -0
  430. package/dist/test/pull-requests.test.js +78 -0
  431. package/dist/test/review-poller.test.js +349 -0
  432. package/dist/test/server/analytics.js +121 -0
  433. package/dist/test/server/auth.js +63 -0
  434. package/dist/test/server/branch-linker.js +124 -0
  435. package/dist/test/server/clipboard.js +56 -0
  436. package/dist/test/server/config.js +137 -0
  437. package/dist/test/server/git.js +308 -0
  438. package/dist/test/server/hooks.js +196 -0
  439. package/dist/test/server/index.js +1124 -0
  440. package/dist/test/server/integration-github.js +117 -0
  441. package/dist/test/server/integration-jira.js +164 -0
  442. package/dist/test/server/integration-linear.js +176 -0
  443. package/dist/test/server/mobile-input-pipeline.js +123 -0
  444. package/dist/test/server/org-dashboard.js +184 -0
  445. package/dist/test/server/output-parsers/claude-parser.js +54 -0
  446. package/dist/test/server/output-parsers/codex-parser.js +13 -0
  447. package/dist/test/server/output-parsers/index.js +7 -0
  448. package/dist/test/server/pty-handler.js +310 -0
  449. package/dist/test/server/push.js +80 -0
  450. package/dist/test/server/review-poller.js +218 -0
  451. package/dist/test/server/service.js +169 -0
  452. package/dist/test/server/sessions.js +434 -0
  453. package/dist/test/server/ticket-transitions.js +216 -0
  454. package/dist/test/server/types.js +20 -0
  455. package/dist/test/server/utils.js +22 -0
  456. package/dist/test/server/watcher.js +139 -0
  457. package/dist/test/server/workspaces.js +657 -0
  458. package/dist/test/server/ws.js +152 -0
  459. package/dist/test/server-startup.test.js +62 -0
  460. package/dist/test/service.test.js +43 -0
  461. package/dist/test/session-analytics-api.test.js +123 -0
  462. package/dist/test/session-analytics.test.js +425 -0
  463. package/dist/test/session-intent.test.js +249 -0
  464. package/dist/test/sessions.test.js +1152 -0
  465. package/dist/test/sidebar-items.test.js +164 -0
  466. package/dist/test/stores/boot-state-store.test.js +165 -0
  467. package/dist/test/stores/sessions-logic.test.js +191 -0
  468. package/dist/test/stores/toasts-store.test.js +66 -0
  469. package/dist/test/stores/ui-store.test.js +203 -0
  470. package/dist/test/stores/unread-store.test.js +97 -0
  471. package/dist/test/telemetry-api.test.js +54 -0
  472. package/dist/test/telemetry-sync.test.js +68 -0
  473. package/dist/test/telemetry.test.js +295 -0
  474. package/dist/test/terminal-zoom.test.js +102 -0
  475. package/dist/test/test/analytics.test.js +152 -0
  476. package/dist/test/test/auth.test.js +95 -0
  477. package/dist/test/test/branch-linker.test.js +231 -0
  478. package/dist/test/test/branch-rename.test.js +45 -0
  479. package/dist/test/test/clipboard.test.js +12 -0
  480. package/dist/test/test/config.test.js +281 -0
  481. package/dist/test/test/fs-browse.test.js +202 -0
  482. package/dist/test/test/git.test.js +67 -0
  483. package/dist/test/test/hooks.test.js +139 -0
  484. package/dist/test/test/integration-github.test.js +203 -0
  485. package/dist/test/test/integration-jira.test.js +294 -0
  486. package/dist/test/test/integration-linear.test.js +293 -0
  487. package/dist/test/test/mobile-input.test.js +193 -0
  488. package/dist/test/test/org-dashboard.test.js +240 -0
  489. package/dist/test/test/output-parser.test.js +95 -0
  490. package/dist/test/test/paths.test.js +32 -0
  491. package/dist/test/test/pr-state.test.js +220 -0
  492. package/dist/test/test/pull-requests.test.js +67 -0
  493. package/dist/test/test/review-poller.test.js +235 -0
  494. package/dist/test/test/service.test.js +43 -0
  495. package/dist/test/test/sessions.test.js +750 -0
  496. package/dist/test/test/ticket-transitions.test.js +130 -0
  497. package/dist/test/test/version.test.js +34 -0
  498. package/dist/test/test/worktrees.test.js +256 -0
  499. package/dist/test/ticket-transitions.test.js +312 -0
  500. package/dist/test/unread.test.js +23 -0
  501. package/dist/test/version.test.js +34 -0
  502. package/dist/test/webhook-manager.test.js +484 -0
  503. package/dist/test/webhooks.test.js +208 -0
  504. package/dist/test/workspace-groups.test.js +377 -0
  505. package/dist/test/worktrees.test.js +531 -0
  506. package/package.json +88 -0
@@ -0,0 +1,638 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { execFile } from 'node:child_process';
5
+ import { promisify } from 'node:util';
6
+ import { AGENT_COMMANDS, AGENT_CONTINUE_ARGS, AGENT_YOLO_ARGS, resolveFramework, } from './types.js';
7
+ import { createPtySession, upgradeHooksSettings } from './pty-handler.js';
8
+ import { cleanupCodexHooksAdapter } from './codex-hooks-adapter.js';
9
+ import { getWorkingTreeDiff } from './git.js';
10
+ import { getPrForBranch, isStalePr } from './gh.js';
11
+ import { trackEvent, recordSessionEvent, upsertSessionRollup, } from './analytics.js';
12
+ import { createLogger } from './logger.js';
13
+ const execFileAsync = promisify(execFile);
14
+ const logger = createLogger('sessions');
15
+ const STALE_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes
16
+ // In-memory registry: id -> Session
17
+ const sessions = new Map();
18
+ // Session metadata cache: session ID or worktree path -> SessionMeta
19
+ const metaCache = new Map();
20
+ // Module-level defaults for hooks injection (set via configure())
21
+ let defaultPort;
22
+ let defaultForceOutputParser;
23
+ let defaultConfigDir;
24
+ function configure(opts) {
25
+ defaultPort = opts.port;
26
+ defaultForceOutputParser = opts.forceOutputParser;
27
+ defaultConfigDir = opts.configDir;
28
+ }
29
+ let terminalCounter = 0;
30
+ let agentCounter = 0;
31
+ const stateChangeCallbacks = [];
32
+ function onStateChange(cb) {
33
+ stateChangeCallbacks.push(cb);
34
+ }
35
+ const sessionCreateCallbacks = [];
36
+ function onSessionCreate(cb) {
37
+ sessionCreateCallbacks.push(cb);
38
+ }
39
+ function fireSessionCreate(sessionId, cwd, branchName) {
40
+ for (const cb of sessionCreateCallbacks) {
41
+ try {
42
+ cb(sessionId, cwd, branchName);
43
+ }
44
+ catch (err) {
45
+ logger.error('sessionCreate callback error:', err);
46
+ }
47
+ }
48
+ }
49
+ const sessionEndCallbacks = [];
50
+ function onSessionEnd(cb) {
51
+ sessionEndCallbacks.push(cb);
52
+ }
53
+ function fireSessionEnd(sessionId, cwd, branchName) {
54
+ for (const cb of sessionEndCallbacks) {
55
+ try {
56
+ cb(sessionId, cwd, branchName);
57
+ }
58
+ catch (err) {
59
+ logger.error('sessionEnd callback error:', err);
60
+ }
61
+ }
62
+ }
63
+ export function fireStateChange(sessionId, state) {
64
+ for (const cb of [...stateChangeCallbacks])
65
+ cb(sessionId, state);
66
+ }
67
+ export function computeBackendState(session) {
68
+ // permission-prompt takes highest priority
69
+ if (session.agentState === 'permission-prompt')
70
+ return 'permission';
71
+ // error
72
+ if (session.agentState === 'error')
73
+ return 'error';
74
+ // processing = running
75
+ if (session.agentState === 'processing')
76
+ return 'running';
77
+ // initializing
78
+ if (session.agentState === 'initializing')
79
+ return 'initializing';
80
+ // idle or waiting-for-input = idle (explicitly idle-like agent states)
81
+ if (session.agentState === 'idle' ||
82
+ session.agentState === 'waiting-for-input')
83
+ return 'idle';
84
+ // For sessions without a recognized agentState (terminal/custom), fall back to idle flag
85
+ return session.idle ? 'idle' : 'running';
86
+ }
87
+ const backendStateChangeCallbacks = [];
88
+ export function onBackendStateChange(cb) {
89
+ backendStateChangeCallbacks.push(cb);
90
+ }
91
+ export function fireBackendStateIfChanged(session) {
92
+ const newState = computeBackendState(session);
93
+ let permissionType;
94
+ if (newState === 'permission') {
95
+ permissionType =
96
+ session.currentActivity?.tool === 'AskUserQuestion'
97
+ ? 'question'
98
+ : 'approval';
99
+ }
100
+ if (session._lastEmittedBackendState === newState &&
101
+ session._lastEmittedPermissionType === permissionType)
102
+ return;
103
+ session._lastEmittedBackendState = newState;
104
+ session._lastEmittedPermissionType = permissionType;
105
+ for (const cb of [...backendStateChangeCallbacks]) {
106
+ try {
107
+ cb(session.id, newState, permissionType);
108
+ }
109
+ catch (err) {
110
+ logger.error('backendStateChange callback error:', err);
111
+ }
112
+ }
113
+ }
114
+ function create({ id: providedId, needsBranchRename, branchRenamePrompt, initialPrompt, workspaceId, additionalDirs, agent = 'claude', cols = 80, rows = 24, args = [], port, forceOutputParser, frameworks, ...rest }) {
115
+ const id = providedId || crypto.randomBytes(8).toString('hex');
116
+ const ptyParams = {
117
+ ...rest,
118
+ id,
119
+ agent,
120
+ cols,
121
+ rows,
122
+ args,
123
+ port: port ?? defaultPort,
124
+ forceOutputParser: forceOutputParser ?? defaultForceOutputParser,
125
+ configDir: rest.configDir ?? defaultConfigDir,
126
+ frameworks,
127
+ };
128
+ const { session: ptySession, result } = createPtySession(ptyParams, sessions, stateChangeCallbacks, sessionEndCallbacks, fireBackendStateIfChanged);
129
+ trackEvent({
130
+ category: 'session',
131
+ action: 'created',
132
+ target: id,
133
+ properties: {
134
+ agent,
135
+ type: rest.type ?? 'agent',
136
+ workspace: rest.repoPath,
137
+ mode: rest.command ? 'terminal' : 'agent',
138
+ },
139
+ session_id: id,
140
+ });
141
+ if (needsBranchRename) {
142
+ ptySession.needsBranchRename = true;
143
+ }
144
+ if (branchRenamePrompt) {
145
+ ptySession.branchRenamePrompt = branchRenamePrompt;
146
+ }
147
+ if (initialPrompt) {
148
+ ptySession.initialPrompt = initialPrompt;
149
+ }
150
+ if (workspaceId) {
151
+ ptySession.workspaceId = workspaceId;
152
+ }
153
+ if (additionalDirs?.length) {
154
+ ptySession.additionalDirs = additionalDirs;
155
+ }
156
+ fireSessionCreate(id, ptySession.cwd, ptySession.branchName);
157
+ // Record session start for analytics
158
+ recordSessionEvent({
159
+ session_id: id,
160
+ repo_path: ptySession.repoPath,
161
+ event_type: 'session_start',
162
+ timestamp: new Date().toISOString(),
163
+ });
164
+ upsertSessionRollup({
165
+ sessionId: id,
166
+ repoPath: ptySession.repoPath,
167
+ repoName: ptySession.repoName,
168
+ agentType: agent,
169
+ startedAt: new Date().toISOString(),
170
+ });
171
+ if (initialPrompt) {
172
+ const promptHandler = (changedId, state) => {
173
+ if (changedId === id &&
174
+ state === 'waiting-for-input' &&
175
+ ptySession.initialPrompt) {
176
+ const prompt = ptySession.initialPrompt;
177
+ ptySession.initialPrompt = undefined; // one-shot
178
+ // Small delay to ensure the agent's input handler is ready
179
+ setTimeout(() => {
180
+ try {
181
+ ptySession.pty.write(prompt + '\n');
182
+ }
183
+ catch (err) {
184
+ logger.error('Failed to inject initial prompt:', err);
185
+ }
186
+ }, 500);
187
+ // Remove this handler after firing
188
+ const idx = stateChangeCallbacks.indexOf(promptHandler);
189
+ if (idx !== -1)
190
+ stateChangeCallbacks.splice(idx, 1);
191
+ }
192
+ };
193
+ stateChangeCallbacks.push(promptHandler);
194
+ }
195
+ return { ...result, needsBranchRename: !!ptySession.needsBranchRename };
196
+ }
197
+ function get(id) {
198
+ return sessions.get(id);
199
+ }
200
+ function list() {
201
+ return Array.from(sessions.values())
202
+ .map((s) => ({
203
+ id: s.id,
204
+ type: s.type,
205
+ agent: s.agent,
206
+ mode: s.mode,
207
+ repoPath: s.repoPath,
208
+ worktreePath: s.worktreePath,
209
+ cwd: s.cwd,
210
+ repoName: s.repoName,
211
+ branchName: s.branchName,
212
+ displayName: s.displayName,
213
+ createdAt: s.createdAt,
214
+ lastActivity: s.lastActivity,
215
+ idle: s.idle,
216
+ customCommand: s.customCommand,
217
+ useTmux: s.useTmux,
218
+ tmuxSessionName: s.tmuxSessionName,
219
+ status: s.status,
220
+ needsBranchRename: !!s.needsBranchRename,
221
+ agentState: s.agentState,
222
+ currentActivity: s.currentActivity,
223
+ ...(s.workspaceId ? { workspaceId: s.workspaceId } : {}),
224
+ ...(s.additionalDirs?.length
225
+ ? { additionalDirs: s.additionalDirs }
226
+ : {}),
227
+ ...(s.dataQuality !== undefined ? { dataQuality: s.dataQuality } : {}),
228
+ }))
229
+ .sort((a, b) => b.lastActivity.localeCompare(a.lastActivity));
230
+ }
231
+ function updateDisplayName(id, displayName) {
232
+ const session = sessions.get(id);
233
+ if (!session)
234
+ throw new Error('Session not found: ' + id);
235
+ session.displayName = displayName;
236
+ return { id, displayName };
237
+ }
238
+ function kill(id) {
239
+ const session = sessions.get(id);
240
+ if (!session) {
241
+ throw new Error(`Session not found: ${id}`);
242
+ }
243
+ try {
244
+ session.pty.kill('SIGTERM');
245
+ }
246
+ catch {
247
+ // PTY may already be dead (e.g. disconnected sessions) — still delete from registry
248
+ }
249
+ if (session.tmuxSessionName) {
250
+ execFile('tmux', ['kill-session', '-t', session.tmuxSessionName], () => { });
251
+ }
252
+ const durationS = Math.round((Date.now() - new Date(session.createdAt).getTime()) / 1000);
253
+ trackEvent({
254
+ category: 'session',
255
+ action: 'ended',
256
+ target: id,
257
+ properties: {
258
+ agent: session.agent,
259
+ type: session.type,
260
+ workspace: session.repoPath,
261
+ duration_s: durationS,
262
+ },
263
+ session_id: id,
264
+ });
265
+ fireSessionEnd(id, session.cwd, session.branchName);
266
+ // Clean up codex hooks adapter temp directory to avoid leaking temp files
267
+ if (session.agent === 'codex' && session.hooksActive) {
268
+ cleanupCodexHooksAdapter(id);
269
+ }
270
+ sessions.delete(id);
271
+ }
272
+ function killAllTmuxSessions() {
273
+ for (const session of sessions.values()) {
274
+ if (session.tmuxSessionName) {
275
+ execFile('tmux', ['kill-session', '-t', session.tmuxSessionName], () => { });
276
+ }
277
+ }
278
+ }
279
+ function resize(id, cols, rows) {
280
+ const session = sessions.get(id);
281
+ if (!session) {
282
+ throw new Error(`Session not found: ${id}`);
283
+ }
284
+ session.pty.resize(cols, rows);
285
+ }
286
+ function write(id, data) {
287
+ const session = sessions.get(id);
288
+ if (!session) {
289
+ throw new Error(`Session not found: ${id}`);
290
+ }
291
+ session.pty.write(data);
292
+ }
293
+ function nextTerminalName() {
294
+ return `Terminal ${++terminalCounter}`;
295
+ }
296
+ function nextAgentName() {
297
+ return `Agent ${++agentCounter}`;
298
+ }
299
+ function serializeAll(configDir) {
300
+ const scrollbackDirPath = path.join(configDir, 'scrollback');
301
+ fs.mkdirSync(scrollbackDirPath, { recursive: true });
302
+ const serializedPty = [];
303
+ for (const session of sessions.values()) {
304
+ // Write scrollback to disk
305
+ const scrollbackPath = path.join(scrollbackDirPath, session.id + '.buf');
306
+ fs.writeFileSync(scrollbackPath, session.scrollback.join(''), 'utf-8');
307
+ serializedPty.push({
308
+ id: session.id,
309
+ type: session.type,
310
+ agent: session.agent,
311
+ repoPath: session.repoPath,
312
+ worktreePath: session.worktreePath,
313
+ cwd: session.cwd,
314
+ repoName: session.repoName,
315
+ branchName: session.branchName,
316
+ displayName: session.displayName,
317
+ createdAt: session.createdAt,
318
+ lastActivity: session.lastActivity,
319
+ useTmux: session.useTmux,
320
+ tmuxSessionName: session.tmuxSessionName || '',
321
+ customCommand: session.customCommand,
322
+ yolo: session.yolo,
323
+ claudeArgs: session.sessionArgs ?? session.claudeArgs,
324
+ hookToken: session.hookToken,
325
+ hooksActive: session.hooksActive,
326
+ continuePolicy: session.continuePolicy,
327
+ ...(session.needsBranchRename
328
+ ? { needsBranchRename: true }
329
+ : {}),
330
+ ...(session.branchRenamePrompt
331
+ ? { branchRenamePrompt: session.branchRenamePrompt }
332
+ : {}),
333
+ ...(session.workspaceId ? { workspaceId: session.workspaceId } : {}),
334
+ ...(session.additionalDirs?.length
335
+ ? { additionalDirs: session.additionalDirs }
336
+ : {}),
337
+ });
338
+ }
339
+ const pending = {
340
+ version: 4,
341
+ timestamp: new Date().toISOString(),
342
+ sessions: serializedPty,
343
+ };
344
+ fs.writeFileSync(path.join(configDir, 'pending-sessions.json'), JSON.stringify(pending, null, 2), 'utf-8');
345
+ }
346
+ async function restoreFromDisk(configDir, workspaces, frameworks) {
347
+ const pendingPath = path.join(configDir, 'pending-sessions.json');
348
+ if (!fs.existsSync(pendingPath))
349
+ return 0;
350
+ let pending;
351
+ try {
352
+ pending = JSON.parse(fs.readFileSync(pendingPath, 'utf-8'));
353
+ }
354
+ catch {
355
+ fs.unlinkSync(pendingPath);
356
+ return 0;
357
+ }
358
+ // Ignore stale files (>5 minutes old)
359
+ if (Date.now() - new Date(pending.timestamp).getTime() > STALE_THRESHOLD_MS) {
360
+ fs.unlinkSync(pendingPath);
361
+ return 0;
362
+ }
363
+ // v2 → v3 migration
364
+ if (pending.version <= 2) {
365
+ for (const s of pending.sessions) {
366
+ const legacy = s;
367
+ // In v2 format, the field was called "repoPath" and stored the CWD
368
+ const v2Cwd = s['repoPath'];
369
+ if (!('cwd' in s) && v2Cwd) {
370
+ s.cwd = v2Cwd;
371
+ }
372
+ if (!('repoPath' in s) || v2Cwd === s.repoPath) {
373
+ // Derive repoPath from the configured workspaces (it's different from the old cwd meaning)
374
+ const configuredWorkspaces = workspaces ?? [];
375
+ const cwd = s.cwd ?? v2Cwd ?? '';
376
+ const matchedWorkspace = configuredWorkspaces.find((w) => cwd === w || cwd.startsWith(w + '/'));
377
+ if (!matchedWorkspace) {
378
+ logger.warn(`v2→v3 migration: no configured workspace matches cwd "${cwd}", using cwd as repoPath`);
379
+ }
380
+ s.repoPath = matchedWorkspace ?? cwd;
381
+ }
382
+ if (!('worktreePath' in s)) {
383
+ const cwd = s.cwd ?? '';
384
+ const repoPath = s.repoPath ?? '';
385
+ // If cwd differs from repoPath, it's a worktree
386
+ s.worktreePath = cwd !== repoPath ? cwd : null;
387
+ }
388
+ // Map old types to new
389
+ if (s.type === 'repo' || s.type === 'worktree') {
390
+ s.type = 'agent';
391
+ }
392
+ // Clean up legacy fields (repoPath is now kept as it's our real field)
393
+ delete legacy.root;
394
+ delete legacy.worktreeName;
395
+ }
396
+ }
397
+ // v3 → v4 migration: workspacePath → repoPath
398
+ // NOTE: This block also fires for v1/v2 files, but is a no-op for them because
399
+ // the v2→v3 block above already sets `repoPath`, so the `!('repoPath' in s)`
400
+ // guard is false. Correctness depends on sequential execution order.
401
+ if (pending.version <= 3) {
402
+ for (const s of pending.sessions) {
403
+ const legacy = s;
404
+ if ('workspacePath' in legacy && !('repoPath' in s)) {
405
+ s.repoPath = legacy.workspacePath;
406
+ delete legacy.workspacePath;
407
+ }
408
+ }
409
+ }
410
+ const scrollbackDirPath = path.join(configDir, 'scrollback');
411
+ let restored = 0;
412
+ // Restore PTY sessions
413
+ for (const s of pending.sessions) {
414
+ // Load scrollback from disk
415
+ let initialScrollback;
416
+ const scrollbackPath = path.join(scrollbackDirPath, s.id + '.buf');
417
+ try {
418
+ const data = fs.readFileSync(scrollbackPath, 'utf-8');
419
+ if (data.length > 0)
420
+ initialScrollback = [data];
421
+ }
422
+ catch {
423
+ // Missing scrollback is non-fatal
424
+ }
425
+ // Determine spawn command and args
426
+ let command;
427
+ let args = [];
428
+ if (s.customCommand) {
429
+ // Terminal session — respawn the shell
430
+ command = s.customCommand;
431
+ }
432
+ else if (s.useTmux && s.tmuxSessionName) {
433
+ // Tmux session — check if tmux session is still alive
434
+ let tmuxAlive = false;
435
+ try {
436
+ await execFileAsync('tmux', ['has-session', '-t', s.tmuxSessionName]);
437
+ tmuxAlive = true;
438
+ }
439
+ catch {
440
+ // tmux session is gone
441
+ }
442
+ if (tmuxAlive) {
443
+ // Attach to surviving tmux session
444
+ command = 'tmux';
445
+ args = ['-u', 'attach-session', '-t', s.tmuxSessionName];
446
+ // Upgrade hooks-settings.json to include statusLine if missing (migration for pre-telemetry sessions)
447
+ if (s.hooksActive && defaultConfigDir) {
448
+ const upgraded = upgradeHooksSettings(s.id, defaultConfigDir);
449
+ if (upgraded)
450
+ logger.info(`Upgraded hooks settings for session ${s.id} (added statusLine relay)`);
451
+ }
452
+ }
453
+ else {
454
+ // Tmux session died — fall back to agent with continue args + preserved flags
455
+ // Continue args first: Codex uses subcommands (resume --last) that must precede flags
456
+ let continueArgsList;
457
+ let yoloArgsList;
458
+ try {
459
+ const framework = resolveFramework(frameworks ? { frameworks } : {}, s.agent);
460
+ continueArgsList = framework.continueArgs;
461
+ yoloArgsList = framework.yoloArgs;
462
+ }
463
+ catch {
464
+ // Unknown framework — fall back to deprecated lookup tables
465
+ continueArgsList = AGENT_CONTINUE_ARGS[s.agent] ?? [];
466
+ yoloArgsList = AGENT_YOLO_ARGS[s.agent] ?? [];
467
+ }
468
+ args = [
469
+ ...continueArgsList,
470
+ ...(s.claudeArgs ?? []),
471
+ ...(s.yolo ? yoloArgsList : []),
472
+ ];
473
+ }
474
+ }
475
+ else {
476
+ // Non-tmux agent session — respawn with continue args + preserved flags
477
+ // Continue args first: Codex uses subcommands (resume --last) that must precede flags
478
+ let continueArgsList;
479
+ let yoloArgsList;
480
+ try {
481
+ const framework = resolveFramework({}, s.agent);
482
+ continueArgsList = framework.continueArgs;
483
+ yoloArgsList = framework.yoloArgs;
484
+ }
485
+ catch {
486
+ // Unknown framework — fall back to deprecated lookup tables
487
+ continueArgsList = AGENT_CONTINUE_ARGS[s.agent] ?? [];
488
+ yoloArgsList = AGENT_YOLO_ARGS[s.agent] ?? [];
489
+ }
490
+ args = [
491
+ ...continueArgsList,
492
+ ...(s.claudeArgs ?? []),
493
+ ...(s.yolo ? yoloArgsList : []),
494
+ ];
495
+ }
496
+ try {
497
+ const createParams = {
498
+ id: s.id,
499
+ type: s.type,
500
+ agent: s.agent,
501
+ repoName: s.repoName,
502
+ repoPath: s.repoPath,
503
+ worktreePath: s.worktreePath,
504
+ cwd: s.cwd,
505
+ branchName: s.branchName,
506
+ displayName: s.displayName,
507
+ args,
508
+ useTmux: false, // Don't re-wrap in tmux — either attaching to existing or using plain agent
509
+ tmuxSessionName: s.tmuxSessionName,
510
+ restored: true,
511
+ yolo: s.yolo ?? false,
512
+ claudeArgs: s.claudeArgs ?? [],
513
+ hookToken: s.hookToken,
514
+ hooksActive: s.hooksActive,
515
+ continuePolicy: s.continuePolicy ?? 'never',
516
+ ...(s.needsBranchRename ? { needsBranchRename: true } : {}),
517
+ ...(s.branchRenamePrompt
518
+ ? { branchRenamePrompt: s.branchRenamePrompt }
519
+ : {}),
520
+ ...(s.workspaceId ? { workspaceId: s.workspaceId } : {}),
521
+ ...(s.additionalDirs?.length
522
+ ? { additionalDirs: s.additionalDirs }
523
+ : {}),
524
+ };
525
+ if (command)
526
+ createParams.command = command;
527
+ if (initialScrollback)
528
+ createParams.initialScrollback = initialScrollback;
529
+ create(createParams);
530
+ restored++;
531
+ }
532
+ catch (err) {
533
+ logger.error(`Failed to restore session ${s.id} (${s.displayName})`, err);
534
+ }
535
+ // Clean up scrollback file
536
+ try {
537
+ fs.unlinkSync(scrollbackPath);
538
+ }
539
+ catch {
540
+ /* ignore */
541
+ }
542
+ }
543
+ // Clean up
544
+ try {
545
+ fs.unlinkSync(pendingPath);
546
+ }
547
+ catch {
548
+ /* ignore */
549
+ }
550
+ try {
551
+ fs.rmdirSync(path.join(configDir, 'scrollback'));
552
+ }
553
+ catch {
554
+ /* ignore — may not be empty */
555
+ }
556
+ // Sync counters to avoid duplicate display names after restore
557
+ for (const s of sessions.values()) {
558
+ const agentMatch = s.displayName?.match(/^Agent (\d+)$/);
559
+ if (agentMatch)
560
+ agentCounter = Math.max(agentCounter, parseInt(agentMatch[1], 10));
561
+ const termMatch = s.displayName?.match(/^Terminal (\d+)$/);
562
+ if (termMatch)
563
+ terminalCounter = Math.max(terminalCounter, parseInt(termMatch[1], 10));
564
+ }
565
+ return restored;
566
+ }
567
+ /** Returns the set of tmux session names currently owned by restored sessions */
568
+ function activeTmuxSessionNames() {
569
+ const names = new Set();
570
+ for (const session of sessions.values()) {
571
+ if (session.tmuxSessionName)
572
+ names.add(session.tmuxSessionName);
573
+ }
574
+ return names;
575
+ }
576
+ async function fetchMetaForSession(session) {
577
+ const repoPath = session.cwd;
578
+ const branch = session.branchName;
579
+ let prNumber = null;
580
+ let additions = 0;
581
+ let deletions = 0;
582
+ if (branch) {
583
+ try {
584
+ const pr = await getPrForBranch(repoPath, branch);
585
+ if (pr && !isStalePr(pr)) {
586
+ prNumber = pr.number;
587
+ additions = pr.additions;
588
+ deletions = pr.deletions;
589
+ }
590
+ }
591
+ catch {
592
+ /* gh CLI unavailable */
593
+ }
594
+ }
595
+ // Fallback to working tree diff if no PR data
596
+ if (additions === 0 && deletions === 0) {
597
+ const diff = await getWorkingTreeDiff(repoPath);
598
+ additions = diff.additions;
599
+ deletions = diff.deletions;
600
+ }
601
+ return {
602
+ prNumber,
603
+ additions,
604
+ deletions,
605
+ fetchedAt: new Date().toISOString(),
606
+ };
607
+ }
608
+ async function getSessionMeta(id, refresh = false) {
609
+ if (!refresh && metaCache.has(id))
610
+ return metaCache.get(id);
611
+ const session = sessions.get(id);
612
+ if (!session)
613
+ return metaCache.get(id) ?? null;
614
+ const summary = list().find((s) => s.id === id);
615
+ if (!summary)
616
+ return null;
617
+ const meta = await fetchMetaForSession(summary);
618
+ metaCache.set(id, meta);
619
+ return meta;
620
+ }
621
+ function getAllSessionMeta() {
622
+ const result = {};
623
+ for (const [key, meta] of metaCache) {
624
+ result[key] = meta;
625
+ }
626
+ return result;
627
+ }
628
+ // Populate cache for all active sessions (called on startup or refresh)
629
+ async function populateMetaCache() {
630
+ const allSessions = list();
631
+ await Promise.allSettled(allSessions.map(async (s) => {
632
+ if (!metaCache.has(s.id)) {
633
+ const meta = await fetchMetaForSession(s);
634
+ metaCache.set(s.id, meta);
635
+ }
636
+ }));
637
+ }
638
+ export { configure, create, get, list, kill, killAllTmuxSessions, resize, updateDisplayName, write, onStateChange, onSessionCreate, onSessionEnd, nextTerminalName, nextAgentName, serializeAll, restoreFromDisk, activeTmuxSessionNames, getSessionMeta, getAllSessionMeta, populateMetaCache, AGENT_COMMANDS, AGENT_CONTINUE_ARGS, AGENT_YOLO_ARGS, };