@cryptiklemur/lattice 1.46.7 → 2.0.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 (599) hide show
  1. package/README.md +14 -36
  2. package/bin/lattice +5 -21
  3. package/dist/client/assets/abap-DOv5zRgd.js +1 -0
  4. package/dist/client/assets/actionscript-3-D_b0n2Ff.js +1 -0
  5. package/dist/client/assets/ada-C6m8O36S.js +1 -0
  6. package/dist/client/assets/andromeeda-LdzAHaKR.js +1 -0
  7. package/dist/client/assets/angular-html-BBi1Szz5.js +1 -0
  8. package/dist/client/assets/angular-ts-2PMpSPqc.js +1 -0
  9. package/dist/client/assets/apache-CE7PmWoU.js +1 -0
  10. package/dist/client/assets/apex-DOfNfL0V.js +1 -0
  11. package/dist/client/assets/apl-B-NEtBvQ.js +1 -0
  12. package/dist/client/assets/applescript-D4zGaScB.js +1 -0
  13. package/dist/client/assets/ara-DMoCP0pJ.js +1 -0
  14. package/dist/client/assets/asciidoc-BkmPq932.js +1 -0
  15. package/dist/client/assets/asm-ClIKbvsu.js +1 -0
  16. package/dist/client/assets/astro-mxH1DA5Z.js +1 -0
  17. package/dist/client/assets/aurora-x-DTcNXZIS.js +1 -0
  18. package/dist/client/assets/awk-D1ZOsISX.js +1 -0
  19. package/dist/client/assets/ayu-dark-DpNcORnA.js +1 -0
  20. package/dist/client/assets/ayu-light-lHqf0ddo.js +1 -0
  21. package/dist/client/assets/ayu-mirage-Dji5RWiH.js +1 -0
  22. package/dist/client/assets/ballerina-H14_EqPr.js +1 -0
  23. package/dist/client/assets/bat-cyb3gF8B.js +1 -0
  24. package/dist/client/assets/beancount-D84pBacF.js +1 -0
  25. package/dist/client/assets/berry-B29XeKK4.js +1 -0
  26. package/dist/client/assets/bibtex-Hs7VvQaV.js +1 -0
  27. package/dist/client/assets/bicep-CugTE5CQ.js +1 -0
  28. package/dist/client/assets/bird2-mieRHotO.js +1 -0
  29. package/dist/client/assets/blade-BUQ9XSm3.js +1 -0
  30. package/dist/client/assets/bsl-BRmzGEWg.js +1 -0
  31. package/dist/client/assets/c-DrQixLw7.js +1 -0
  32. package/dist/client/assets/c3-Dx2gByXW.js +1 -0
  33. package/dist/client/assets/cadence-CCTSwj3w.js +1 -0
  34. package/dist/client/assets/cairo-CaIu88t6.js +1 -0
  35. package/dist/client/assets/catppuccin-frappe-DQrU04q0.js +1 -0
  36. package/dist/client/assets/catppuccin-latte-B_oiWZka.js +1 -0
  37. package/dist/client/assets/catppuccin-macchiato-D8VB2qi4.js +1 -0
  38. package/dist/client/assets/catppuccin-mocha-5vkMJ1Mb.js +1 -0
  39. package/dist/client/assets/clarity-BbUNTPrg.js +1 -0
  40. package/dist/client/assets/clojure-Bcw7lCta.js +1 -0
  41. package/dist/client/assets/cmake-DM0FE-T9.js +1 -0
  42. package/dist/client/assets/cobol-42amjOMh.js +1 -0
  43. package/dist/client/assets/codeowners-CBvEPOlS.js +1 -0
  44. package/dist/client/assets/codeql-CjS8Tp16.js +1 -0
  45. package/dist/client/assets/coffee-CMSEUKyy.js +1 -0
  46. package/dist/client/assets/common-lisp-BCx4dVK8.js +1 -0
  47. package/dist/client/assets/coq-Ddo7YIsR.js +1 -0
  48. package/dist/client/assets/cpp-C4yJBzl2.js +1 -0
  49. package/dist/client/assets/crystal-DZ27EoiA.js +1 -0
  50. package/dist/client/assets/csharp-Kzd7Ey2d.js +1 -0
  51. package/dist/client/assets/css-CdQwkSNm.js +1 -0
  52. package/dist/client/assets/csv-DGwgERVJ.js +1 -0
  53. package/dist/client/assets/cue-CMabdDG0.js +1 -0
  54. package/dist/client/assets/cypher-CJUzJAhQ.js +1 -0
  55. package/dist/client/assets/d-BvLF4qGs.js +1 -0
  56. package/dist/client/assets/dark-plus-BMwvn5lx.js +1 -0
  57. package/dist/client/assets/dart-DxXbDeKR.js +1 -0
  58. package/dist/client/assets/dax-BvrCypuS.js +1 -0
  59. package/dist/client/assets/desktop-BEul_kAS.js +1 -0
  60. package/dist/client/assets/diff-B7rhrwA5.js +1 -0
  61. package/dist/client/assets/dist-CBRIe7YG.js +153 -0
  62. package/dist/client/assets/docker-9Zbx0dQX.js +1 -0
  63. package/dist/client/assets/dotenv-C0epktMv.js +1 -0
  64. package/dist/client/assets/dracula-CBD4ckb0.js +1 -0
  65. package/dist/client/assets/dracula-soft-CuGBZj_h.js +1 -0
  66. package/dist/client/assets/dream-maker-D6UB367x.js +1 -0
  67. package/dist/client/assets/edge-J8VemHZC.js +1 -0
  68. package/dist/client/assets/elixir-DU66qSn_.js +1 -0
  69. package/dist/client/assets/elm-8cz1JjRg.js +1 -0
  70. package/dist/client/assets/emacs-lisp-DFyMFAZA.js +1 -0
  71. package/dist/client/assets/erb-DMl63J6s.js +1 -0
  72. package/dist/client/assets/erlang-LvhGhZI3.js +1 -0
  73. package/dist/client/assets/everforest-dark-BhFNrp2k.js +1 -0
  74. package/dist/client/assets/everforest-light-CpIbZ9aT.js +1 -0
  75. package/dist/client/assets/fennel-CH1ohGYX.js +1 -0
  76. package/dist/client/assets/fish-D2X4h_sR.js +1 -0
  77. package/dist/client/assets/fluent-B_In4uB6.js +1 -0
  78. package/dist/client/assets/fortran-fixed-form-BXvkHMbK.js +1 -0
  79. package/dist/client/assets/fortran-free-form-Bw_JZ1tj.js +1 -0
  80. package/dist/client/assets/fsharp-uxIU8dwY.js +1 -0
  81. package/dist/client/assets/gdresource-DkI-mZL2.js +1 -0
  82. package/dist/client/assets/gdscript-DDro0rs8.js +1 -0
  83. package/dist/client/assets/gdshader-DkUeC1ld.js +1 -0
  84. package/dist/client/assets/genie-khT2hrp-.js +1 -0
  85. package/dist/client/assets/gherkin-CPELKal0.js +1 -0
  86. package/dist/client/assets/git-commit-a3TktZ3A.js +1 -0
  87. package/dist/client/assets/git-rebase-DjlZL8cj.js +1 -0
  88. package/dist/client/assets/github-dark-DQp1Qkx5.js +1 -0
  89. package/dist/client/assets/github-dark-default-BroO-mT3.js +1 -0
  90. package/dist/client/assets/github-dark-dimmed-D8UZ8uTL.js +1 -0
  91. package/dist/client/assets/github-dark-high-contrast-CM0RRMCj.js +1 -0
  92. package/dist/client/assets/github-light-BRTmX4Ht.js +1 -0
  93. package/dist/client/assets/github-light-default-dl7biQ4g.js +1 -0
  94. package/dist/client/assets/github-light-high-contrast-Cvzq8ZXJ.js +1 -0
  95. package/dist/client/assets/gleam-7UVjplRF.js +1 -0
  96. package/dist/client/assets/glimmer-js-Fu7vOQY-.js +1 -0
  97. package/dist/client/assets/glimmer-ts-AJljRs0A.js +1 -0
  98. package/dist/client/assets/glsl-CfodGzSv.js +1 -0
  99. package/dist/client/assets/gn-EcrZPIZo.js +1 -0
  100. package/dist/client/assets/gnuplot-CcsFlqcz.js +1 -0
  101. package/dist/client/assets/go-TqNfhUhh.js +1 -0
  102. package/dist/client/assets/graphql-C8GPKPx1.js +1 -0
  103. package/dist/client/assets/groovy-bfrzFpSZ.js +1 -0
  104. package/dist/client/assets/gruvbox-dark-hard-CBFL_VqK.js +1 -0
  105. package/dist/client/assets/gruvbox-dark-medium-Dn18r-Yz.js +1 -0
  106. package/dist/client/assets/gruvbox-dark-soft-DUyKWd02.js +1 -0
  107. package/dist/client/assets/gruvbox-light-hard-DV9RwKs4.js +1 -0
  108. package/dist/client/assets/gruvbox-light-medium-Ba-VIg48.js +1 -0
  109. package/dist/client/assets/gruvbox-light-soft-CVIZMKFx.js +1 -0
  110. package/dist/client/assets/hack-Gp6OuE21.js +1 -0
  111. package/dist/client/assets/haml-BOyG6GfM.js +1 -0
  112. package/dist/client/assets/handlebars-B9IoVRxd.js +1 -0
  113. package/dist/client/assets/haskell-DzEtL6Zk.js +1 -0
  114. package/dist/client/assets/haxe-wLDEcRoz.js +1 -0
  115. package/dist/client/assets/hcl-C1fs3gTM.js +1 -0
  116. package/dist/client/assets/hjson-B4b85MZo.js +1 -0
  117. package/dist/client/assets/hlsl-JhqkHhML.js +1 -0
  118. package/dist/client/assets/horizon-DMOEeSnA.js +1 -0
  119. package/dist/client/assets/horizon-bright-CPVackS9.js +1 -0
  120. package/dist/client/assets/houston-DSlR9wH9.js +1 -0
  121. package/dist/client/assets/html-CFrSukiU.js +1 -0
  122. package/dist/client/assets/html-derivative-D0_gRK_M.js +1 -0
  123. package/dist/client/assets/http-D4MmFixi.js +1 -0
  124. package/dist/client/assets/hurl-D1xbk-LS.js +1 -0
  125. package/dist/client/assets/hxml-Bdi_kWeE.js +1 -0
  126. package/dist/client/assets/hy-uAHU8420.js +1 -0
  127. package/dist/client/assets/imba-CPCwfD-G.js +1 -0
  128. package/dist/client/assets/index-DrTbNMzI.css +2 -0
  129. package/dist/client/assets/index-ZIuI5BCP.js +284 -0
  130. package/dist/client/assets/ini-2Ew1Qzj6.js +1 -0
  131. package/dist/client/assets/java-CfPMY1Dv.js +1 -0
  132. package/dist/client/assets/javascript-B8vNHeqm.js +1 -0
  133. package/dist/client/assets/jinja-CF0K8bFV.js +1 -0
  134. package/dist/client/assets/jison-BP7my5TL.js +1 -0
  135. package/dist/client/assets/json-TeXNjpMZ.js +1 -0
  136. package/dist/client/assets/json5-Dl8gAgq4.js +1 -0
  137. package/dist/client/assets/jsonc-C9b23pMf.js +1 -0
  138. package/dist/client/assets/jsonl-DkF3QjsY.js +1 -0
  139. package/dist/client/assets/jsonnet-DH4UkOBo.js +1 -0
  140. package/dist/client/assets/jssm-CBV9_O8o.js +1 -0
  141. package/dist/client/assets/jsx-C86NmHc2.js +1 -0
  142. package/dist/client/assets/julia-C58U_aQP.js +1 -0
  143. package/dist/client/assets/just-h6Vco8Qu.js +1 -0
  144. package/dist/client/assets/kanagawa-dragon-DLDXA4f2.js +1 -0
  145. package/dist/client/assets/kanagawa-lotus-qAvw6eOU.js +1 -0
  146. package/dist/client/assets/kanagawa-wave-DFO_g5Mb.js +1 -0
  147. package/dist/client/assets/kdl-BQl-X5Uf.js +1 -0
  148. package/dist/client/assets/kotlin-d6oenWPH.js +1 -0
  149. package/dist/client/assets/kusto-Cpu9Tdho.js +1 -0
  150. package/dist/client/assets/laserwave-Bbquw0Nf.js +1 -0
  151. package/dist/client/assets/latex-DRsNisjT.js +1 -0
  152. package/dist/client/assets/lean-CvyEisyW.js +1 -0
  153. package/dist/client/assets/less-B9RQiV1N.js +1 -0
  154. package/dist/client/assets/light-plus-Ch1Usv7R.js +1 -0
  155. package/dist/client/assets/liquid-C9jXC9M7.js +1 -0
  156. package/dist/client/assets/llvm-DtrwjsAs.js +1 -0
  157. package/dist/client/assets/log-JKbKuM4J.js +1 -0
  158. package/dist/client/assets/logo-BsxZM_eb.js +1 -0
  159. package/dist/client/assets/lua-BUYvdn-F.js +1 -0
  160. package/dist/client/assets/luau-D9oeBRnv.js +1 -0
  161. package/dist/client/assets/make-DLuqI3Sa.js +1 -0
  162. package/dist/client/assets/markdown-hfQzyr6v.js +1 -0
  163. package/dist/client/assets/marko-BqB4tqw-.js +1 -0
  164. package/dist/client/assets/material-theme-darker-yvetTWEr.js +1 -0
  165. package/dist/client/assets/material-theme-kX26WiJU.js +1 -0
  166. package/dist/client/assets/material-theme-lighter-L4j3qddN.js +1 -0
  167. package/dist/client/assets/material-theme-ocean-BnNk1wNQ.js +1 -0
  168. package/dist/client/assets/material-theme-palenight-W0qbGyud.js +1 -0
  169. package/dist/client/assets/matlab-Cz4xBfaA.js +1 -0
  170. package/dist/client/assets/mdc-C8Rs68Nw.js +1 -0
  171. package/dist/client/assets/mdx-Crds6sJw.js +1 -0
  172. package/dist/client/assets/mermaid-Bk1sayFm.js +1 -0
  173. package/dist/client/assets/min-dark-DK6uq44k.js +1 -0
  174. package/dist/client/assets/min-light-lr1QiEOE.js +1 -0
  175. package/dist/client/assets/mipsasm-D3Vr1VJI.js +1 -0
  176. package/dist/client/assets/mojo-D3ai4ATt.js +1 -0
  177. package/dist/client/assets/monokai-DZSWSdmN.js +1 -0
  178. package/dist/client/assets/moonbit-c7XV1V8w.js +1 -0
  179. package/dist/client/assets/move--lg8RSZu.js +1 -0
  180. package/dist/client/assets/narrat-Bn_PlXDl.js +1 -0
  181. package/dist/client/assets/nextflow-DXxhyYjQ.js +1 -0
  182. package/dist/client/assets/nextflow-groovy-CUrXbMOF.js +1 -0
  183. package/dist/client/assets/nginx-Dj6E3HRL.js +1 -0
  184. package/dist/client/assets/night-owl-DnKT96OJ.js +1 -0
  185. package/dist/client/assets/night-owl-light-gVSh6ltn.js +1 -0
  186. package/dist/client/assets/nim-BizJb4iF.js +1 -0
  187. package/dist/client/assets/nix-DE1Q2B1F.js +1 -0
  188. package/dist/client/assets/nord-CbYaE7ZY.js +1 -0
  189. package/dist/client/assets/nushell-BBFYNdNE.js +1 -0
  190. package/dist/client/assets/objective-c-mc6rHp-y.js +1 -0
  191. package/dist/client/assets/objective-cpp-D96wcRis.js +1 -0
  192. package/dist/client/assets/ocaml-Ddt3E4VO.js +1 -0
  193. package/dist/client/assets/odin-BUZTfc03.js +1 -0
  194. package/dist/client/assets/one-dark-pro-CLMO01es.js +1 -0
  195. package/dist/client/assets/one-light-27sfjFDM.js +1 -0
  196. package/dist/client/assets/openscad-C-XxCD_t.js +1 -0
  197. package/dist/client/assets/pascal-BvJwb9Ca.js +1 -0
  198. package/dist/client/assets/perl-DnJAtWNn.js +1 -0
  199. package/dist/client/assets/php-BeY_VEeb.js +1 -0
  200. package/dist/client/assets/pkl-DtSDxyR8.js +1 -0
  201. package/dist/client/assets/plastic-Dd1-4HJb.js +1 -0
  202. package/dist/client/assets/plsql-CgEVu7mV.js +1 -0
  203. package/dist/client/assets/po-BNFx8QMG.js +1 -0
  204. package/dist/client/assets/poimandres-DdZFFINT.js +1 -0
  205. package/dist/client/assets/polar-DcGwqI2v.js +1 -0
  206. package/dist/client/assets/postcss-BgFCg0uM.js +1 -0
  207. package/dist/client/assets/powerquery-BNMZnWRc.js +1 -0
  208. package/dist/client/assets/powershell-CeNh_gMu.js +1 -0
  209. package/dist/client/assets/prisma-C4wKi9Xs.js +1 -0
  210. package/dist/client/assets/prolog-DcNkIfZZ.js +1 -0
  211. package/dist/client/assets/proto-BqsNb_Ru.js +1 -0
  212. package/dist/client/assets/pug-DXhFbVDh.js +1 -0
  213. package/dist/client/assets/puppet-BLvi8DVC.js +1 -0
  214. package/dist/client/assets/purescript-B_tjgp5s.js +1 -0
  215. package/dist/client/assets/python-xLLWlBd0.js +1 -0
  216. package/dist/client/assets/qml-CngzXsz8.js +1 -0
  217. package/dist/client/assets/qmldir-CDe6ORFD.js +1 -0
  218. package/dist/client/assets/qss-CvW7b9vz.js +1 -0
  219. package/dist/client/assets/r-BMmy9apu.js +1 -0
  220. package/dist/client/assets/racket-CA2oKVL1.js +1 -0
  221. package/dist/client/assets/raku-D9dEetfn.js +1 -0
  222. package/dist/client/assets/razor-kIo5DNUk.js +1 -0
  223. package/dist/client/assets/red-Cj1vpJ_n.js +1 -0
  224. package/dist/client/assets/reg-CHsE82Pk.js +1 -0
  225. package/dist/client/assets/regexp-BIa5IayX.js +1 -0
  226. package/dist/client/assets/rel-SUS6CYTF.js +1 -0
  227. package/dist/client/assets/riscv-xyAKa3qa.js +1 -0
  228. package/dist/client/assets/ron-D5BrJbC5.js +1 -0
  229. package/dist/client/assets/rose-pine-Dd0RAvir.js +1 -0
  230. package/dist/client/assets/rose-pine-dawn-CeS_2jlO.js +1 -0
  231. package/dist/client/assets/rose-pine-moon-CQrvtQEF.js +1 -0
  232. package/dist/client/assets/rosmsg-Bie95NPX.js +1 -0
  233. package/dist/client/assets/rst-McWv3WP0.js +1 -0
  234. package/dist/client/assets/ruby-CkenUDKe.js +1 -0
  235. package/dist/client/assets/rust-CAON_J-7.js +1 -0
  236. package/dist/client/assets/sas-Dgn9Yrr5.js +1 -0
  237. package/dist/client/assets/sass-CKkv3rB4.js +1 -0
  238. package/dist/client/assets/scala-BADlfUbE.js +1 -0
  239. package/dist/client/assets/scheme-Bv8vdcS_.js +1 -0
  240. package/dist/client/assets/scss-Tfn9jzBB.js +1 -0
  241. package/dist/client/assets/sdbl-TUdAkzzL.js +1 -0
  242. package/dist/client/assets/shaderlab-C5utLNvK.js +1 -0
  243. package/dist/client/assets/shellscript-vGpgBWOS.js +1 -0
  244. package/dist/client/assets/shellsession-7CA0dOzR.js +1 -0
  245. package/dist/client/assets/slack-dark-BeQrlvP4.js +1 -0
  246. package/dist/client/assets/slack-ochin-DaA1aBiy.js +1 -0
  247. package/dist/client/assets/smalltalk-C1k1DVft.js +1 -0
  248. package/dist/client/assets/snazzy-light-C9Bzvwcg.js +1 -0
  249. package/dist/client/assets/solarized-dark--ZJpQY8O.js +1 -0
  250. package/dist/client/assets/solarized-light-wzNWfjF2.js +1 -0
  251. package/dist/client/assets/solidity-CaEDdWYR.js +1 -0
  252. package/dist/client/assets/soy-DbBURueN.js +1 -0
  253. package/dist/client/assets/sparql-nVt1Q8sD.js +1 -0
  254. package/dist/client/assets/splunk-mpBjmHRA.js +1 -0
  255. package/dist/client/assets/sql-BJGtbEM8.js +1 -0
  256. package/dist/client/assets/ssh-config-DqmSAS3N.js +1 -0
  257. package/dist/client/assets/stata-L0kV9FQT.js +1 -0
  258. package/dist/client/assets/stylus-mNYBrtqL.js +1 -0
  259. package/dist/client/assets/surrealql-C17jcHRl.js +1 -0
  260. package/dist/client/assets/svelte-B5_CmVcu.js +1 -0
  261. package/dist/client/assets/swift-BXoR6L-y.js +1 -0
  262. package/dist/client/assets/synthwave-84-ybvkLGau.js +1 -0
  263. package/dist/client/assets/system-verilog-BnyrpGlO.js +1 -0
  264. package/dist/client/assets/systemd-BBVr_qxh.js +1 -0
  265. package/dist/client/assets/talonscript-l0qUQn2r.js +1 -0
  266. package/dist/client/assets/tasl-BzcMwPTS.js +1 -0
  267. package/dist/client/assets/tcl-CQgtyMkG.js +1 -0
  268. package/dist/client/assets/templ-C5f2EORt.js +1 -0
  269. package/dist/client/assets/terraform-BgPqtSWN.js +1 -0
  270. package/dist/client/assets/tex-DvaBtCMN.js +1 -0
  271. package/dist/client/assets/tokyo-night-BZt2NwCl.js +1 -0
  272. package/dist/client/assets/toml-CpHBCfVl.js +1 -0
  273. package/dist/client/assets/ts-tags-DlZzQdBU.js +1 -0
  274. package/dist/client/assets/tsv-DYxH1-vL.js +1 -0
  275. package/dist/client/assets/tsx-DaLOIju9.js +1 -0
  276. package/dist/client/assets/turtle-DdFFvP5J.js +1 -0
  277. package/dist/client/assets/twig-BB7320dl.js +1 -0
  278. package/dist/client/assets/typescript-D8B-VgXj.js +1 -0
  279. package/dist/client/assets/typespec-CHOxKRtr.js +1 -0
  280. package/dist/client/assets/typst-C0VS9TQm.js +1 -0
  281. package/dist/client/assets/v-CfOPGXPl.js +1 -0
  282. package/dist/client/assets/vala-DYqHmNOK.js +1 -0
  283. package/dist/client/assets/vb-DUBgqZ02.js +1 -0
  284. package/dist/client/assets/verilog-BxybH_AY.js +1 -0
  285. package/dist/client/assets/vesper-BDlBlJR-.js +1 -0
  286. package/dist/client/assets/vhdl-DBoxxi7I.js +1 -0
  287. package/dist/client/assets/viml-C8vROCgw.js +1 -0
  288. package/dist/client/assets/vitesse-black-CUBzmgJa.js +1 -0
  289. package/dist/client/assets/vitesse-dark-COrLBgkv.js +1 -0
  290. package/dist/client/assets/vitesse-light-ThZGgLQK.js +1 -0
  291. package/dist/client/assets/vue-DylGFDrG.js +1 -0
  292. package/dist/client/assets/vue-html-Dt8r3B9y.js +1 -0
  293. package/dist/client/assets/vue-vine-DdN02uhY.js +1 -0
  294. package/dist/client/assets/vyper-D08CaD4o.js +1 -0
  295. package/dist/client/assets/wasm-CoVafRYN.js +1 -0
  296. package/dist/client/assets/wasm-DiIFv9DE.js +1 -0
  297. package/dist/client/assets/wenyan-GlRgAbTB.js +1 -0
  298. package/dist/client/assets/wgsl-BmWpQFqb.js +1 -0
  299. package/dist/client/assets/wikitext-Axug2vPC.js +1 -0
  300. package/dist/client/assets/wit-Dk1fPIaK.js +1 -0
  301. package/dist/client/assets/wolfram-DMhXlmnL.js +1 -0
  302. package/dist/client/assets/xml-CBEuB6I0.js +1 -0
  303. package/dist/client/assets/xsl-CuhlgDL5.js +1 -0
  304. package/dist/client/assets/yaml-Da6ymghi.js +1 -0
  305. package/dist/client/assets/zenscript-x7PXwj2_.js +1 -0
  306. package/dist/client/assets/zig-BlD2NI35.js +1 -0
  307. package/dist/client/index.html +21 -0
  308. package/dist/client/manifest.webmanifest +1 -0
  309. package/dist/client/registerSW.js +1 -0
  310. package/dist/client/sw-push.js +53 -0
  311. package/dist/client/sw.js +1 -0
  312. package/dist/client/workbox-b51dd497.js +1 -0
  313. package/{client/index.html → index.html} +1 -1
  314. package/package.json +62 -14
  315. package/public/icons/icon-192.svg +11 -0
  316. package/public/icons/icon-512.svg +11 -0
  317. package/public/sw-push.js +53 -0
  318. package/{client/src → src/client}/components/analytics/AnalyticsView.tsx +70 -78
  319. package/{client/src → src/client}/components/analytics/ChartCard.tsx +8 -2
  320. package/{client/src → src/client}/components/analytics/QuickStats.tsx +12 -10
  321. package/{client/src → src/client}/components/analytics/charts/ActivityCalendar.tsx +5 -3
  322. package/{client/src → src/client}/components/analytics/charts/CacheEfficiencyChart.tsx +1 -1
  323. package/{client/src → src/client}/components/analytics/charts/ContextUtilizationChart.tsx +33 -25
  324. package/{client/src → src/client}/components/analytics/charts/CostAreaChart.tsx +4 -4
  325. package/{client/src → src/client}/components/analytics/charts/CostDistributionChart.tsx +1 -0
  326. package/{client/src → src/client}/components/analytics/charts/CostDonutChart.tsx +1 -0
  327. package/{client/src → src/client}/components/analytics/charts/CumulativeCostChart.tsx +1 -0
  328. package/{client/src → src/client}/components/analytics/charts/HourlyHeatmap.tsx +5 -3
  329. package/{client/src → src/client}/components/analytics/charts/ProjectRadar.tsx +30 -26
  330. package/{client/src → src/client}/components/analytics/charts/ResponseTimeScatter.tsx +16 -10
  331. package/{client/src → src/client}/components/analytics/charts/SessionBubbleChart.tsx +23 -16
  332. package/{client/src → src/client}/components/analytics/charts/SessionTimeline.tsx +5 -3
  333. package/{client/src → src/client}/components/analytics/charts/TokenFlowChart.tsx +3 -3
  334. package/{client/src → src/client}/components/analytics/charts/ToolSunburst.tsx +26 -23
  335. package/{client/src → src/client}/components/chat/ChatView.tsx +65 -96
  336. package/src/client/components/chat/ElicitationCard.tsx +235 -0
  337. package/{client/src → src/client}/components/chat/Message.tsx +261 -8
  338. package/{client/src → src/client}/components/chat/ModelSelector.tsx +29 -8
  339. package/src/client/components/settings/Appearance.tsx +275 -0
  340. package/{client/src → src/client}/components/settings/BudgetSettings.tsx +6 -2
  341. package/{client/src → src/client}/components/settings/Notifications.tsx +35 -0
  342. package/src/client/components/settings/ThemePreview.tsx +140 -0
  343. package/src/client/components/settings/ThemeWizard.tsx +405 -0
  344. package/{client/src → src/client}/components/sidebar/ProjectRail.tsx +43 -169
  345. package/{client/src → src/client}/components/sidebar/SessionList.tsx +27 -49
  346. package/{client/src → src/client}/components/sidebar/Sidebar.tsx +2 -6
  347. package/src/client/components/sidebar/UserIsland.tsx +282 -0
  348. package/{client/src → src/client}/components/sidebar/UserMenu.tsx +4 -2
  349. package/src/client/components/ui/ContextMenu.tsx +153 -0
  350. package/{client/src → src/client}/components/ui/PopupMenu.tsx +4 -2
  351. package/src/client/components/ui/SaveFooter.tsx +63 -0
  352. package/{client/src → src/client}/components/workspace/TabBar.tsx +17 -64
  353. package/{client/src → src/client}/hooks/useAnalytics.ts +17 -8
  354. package/src/client/hooks/usePushNotifications.ts +92 -0
  355. package/{client/src → src/client}/hooks/useSession.ts +123 -49
  356. package/{client/src → src/client}/hooks/useWebSocket.ts +0 -3
  357. package/src/client/lib/theme-derive.ts +196 -0
  358. package/{client/src → src/client}/stores/analytics.ts +20 -6
  359. package/{client/src → src/client}/stores/session.ts +63 -15
  360. package/{client/src → src/client}/stores/sidebar.ts +3 -1
  361. package/{client/src → src/client}/themes/index.ts +26 -0
  362. package/{server/src → src/server}/analytics/engine.ts +87 -30
  363. package/src/server/assets.ts +45 -0
  364. package/src/server/daemon.ts +547 -0
  365. package/{server/src → src/server}/handlers/analytics.ts +13 -8
  366. package/{server/src → src/server}/handlers/chat.ts +83 -1
  367. package/{server/src → src/server}/handlers/mesh.ts +3 -2
  368. package/{server/src → src/server}/handlers/plugins.ts +10 -13
  369. package/{server/src → src/server}/handlers/session.ts +7 -16
  370. package/{server/src → src/server}/handlers/settings.ts +3 -0
  371. package/{server/src → src/server}/handlers/skills.ts +7 -9
  372. package/src/server/handlers/themes.ts +121 -0
  373. package/{server/src → src/server}/handlers/update.ts +5 -23
  374. package/{server/src → src/server}/index.ts +100 -134
  375. package/{server/src → src/server}/mesh/connector.ts +1 -1
  376. package/{server/src → src/server}/project/context-breakdown.ts +4 -5
  377. package/{server/src → src/server}/project/pty-worker.cjs +1 -1
  378. package/{server/src → src/server}/project/sdk-bridge.ts +526 -428
  379. package/{server/src → src/server}/project/session.ts +117 -42
  380. package/{server/src → src/server}/project/terminal.ts +7 -24
  381. package/src/server/project/warmup.ts +285 -0
  382. package/src/server/push.ts +121 -0
  383. package/src/server/runtime.ts +1 -0
  384. package/src/server/tui.ts +103 -0
  385. package/{server/src → src/server}/update-checker.ts +10 -10
  386. package/{server/src → src/server}/ws/broadcast.ts +8 -8
  387. package/{server/src → src/server}/ws/router.ts +21 -25
  388. package/{shared/src → src/shared}/analytics.ts +1 -0
  389. package/{shared/src → src/shared}/constants.ts +1 -0
  390. package/{shared/src → src/shared}/messages.ts +151 -15
  391. package/{shared/src → src/shared}/models.ts +7 -1
  392. package/tsconfig.json +7 -8
  393. package/{client/vite.config.ts → vite.config.ts} +14 -18
  394. package/.editorconfig +0 -12
  395. package/.github/workflows/ci.yml +0 -81
  396. package/.github/workflows/release.yml +0 -87
  397. package/.impeccable.md +0 -66
  398. package/.releaserc.json +0 -33
  399. package/.serena/memories/code_style_and_conventions.md +0 -35
  400. package/.serena/memories/project_overview.md +0 -51
  401. package/.serena/memories/suggested_commands.md +0 -32
  402. package/.serena/memories/task_completion_checklist.md +0 -15
  403. package/.serena/project.yml +0 -152
  404. package/CLAUDE.md +0 -71
  405. package/CONTRIBUTING.md +0 -93
  406. package/bun.lock +0 -2246
  407. package/bunfig.toml +0 -2
  408. package/client/package.json +0 -43
  409. package/client/src/components/settings/Appearance.tsx +0 -152
  410. package/client/src/components/sidebar/UserIsland.tsx +0 -136
  411. package/client/src/components/ui/SaveFooter.tsx +0 -38
  412. package/client/tsconfig.json +0 -18
  413. package/install.sh +0 -71
  414. package/playwright.config.ts +0 -19
  415. package/scripts/build-binary.ts +0 -157
  416. package/scripts/postinstall.js +0 -31
  417. package/server/package.json +0 -24
  418. package/server/src/_generated/embedded-assets.ts +0 -2
  419. package/server/src/assets.ts +0 -69
  420. package/server/src/daemon.ts +0 -442
  421. package/server/src/runtime.ts +0 -4
  422. package/server/tsconfig.json +0 -20
  423. package/shared/package.json +0 -11
  424. package/shared/tsconfig.json +0 -15
  425. package/tests/accessibility.spec.ts +0 -77
  426. package/tests/keyboard-shortcuts.spec.ts +0 -70
  427. package/tests/message-actions.spec.ts +0 -112
  428. package/tests/onboarding.spec.ts +0 -72
  429. package/tests/session-flow.spec.ts +0 -117
  430. package/tests/session-preview.spec.ts +0 -83
  431. package/themes/amoled.json +0 -20
  432. package/themes/ayu-light.json +0 -9
  433. package/themes/catppuccin-latte.json +0 -9
  434. package/themes/catppuccin-mocha.json +0 -9
  435. package/themes/clay-light.json +0 -10
  436. package/themes/clay.json +0 -10
  437. package/themes/dracula.json +0 -9
  438. package/themes/everforest-light.json +0 -9
  439. package/themes/everforest.json +0 -9
  440. package/themes/github-light.json +0 -9
  441. package/themes/gruvbox-dark.json +0 -9
  442. package/themes/gruvbox-light.json +0 -9
  443. package/themes/monokai.json +0 -9
  444. package/themes/nord-light.json +0 -9
  445. package/themes/nord.json +0 -9
  446. package/themes/one-dark.json +0 -9
  447. package/themes/one-light.json +0 -9
  448. package/themes/rose-pine-dawn.json +0 -9
  449. package/themes/rose-pine.json +0 -9
  450. package/themes/solarized-dark.json +0 -9
  451. package/themes/solarized-light.json +0 -9
  452. package/themes/tokyo-night-light.json +0 -9
  453. package/themes/tokyo-night.json +0 -9
  454. package/tp.js +0 -19
  455. /package/{client/public → dist/client}/icons/icon-192.svg +0 -0
  456. /package/{client/public → dist/client}/icons/icon-512.svg +0 -0
  457. /package/{client/src → src/client}/App.tsx +0 -0
  458. /package/{client/src → src/client}/commands.ts +0 -0
  459. /package/{client/src → src/client}/components/analytics/PeriodSelector.tsx +0 -0
  460. /package/{client/src → src/client}/components/analytics/chartTokens.ts +0 -0
  461. /package/{client/src → src/client}/components/analytics/charts/DailySummaryCards.tsx +0 -0
  462. /package/{client/src → src/client}/components/analytics/charts/NodeFleetOverview.tsx +0 -0
  463. /package/{client/src → src/client}/components/analytics/charts/PermissionBreakdown.tsx +0 -0
  464. /package/{client/src → src/client}/components/analytics/charts/SessionComplexityList.tsx +0 -0
  465. /package/{client/src → src/client}/components/analytics/charts/TokenSankeyChart.tsx +0 -0
  466. /package/{client/src → src/client}/components/analytics/charts/ToolTreemap.tsx +0 -0
  467. /package/{client/src → src/client}/components/auth/PassphrasePrompt.tsx +0 -0
  468. /package/{client/src → src/client}/components/chat/AttachmentChips.tsx +0 -0
  469. /package/{client/src → src/client}/components/chat/ChatInput.tsx +0 -0
  470. /package/{client/src → src/client}/components/chat/CommandPalette.tsx +0 -0
  471. /package/{client/src → src/client}/components/chat/PermissionModeSelector.tsx +0 -0
  472. /package/{client/src → src/client}/components/chat/PromptQuestion.tsx +0 -0
  473. /package/{client/src → src/client}/components/chat/StatusBar.tsx +0 -0
  474. /package/{client/src → src/client}/components/chat/TodoCard.tsx +0 -0
  475. /package/{client/src → src/client}/components/chat/ToolGroup.tsx +0 -0
  476. /package/{client/src → src/client}/components/chat/ToolResultRenderer.tsx +0 -0
  477. /package/{client/src → src/client}/components/chat/VoiceRecorder.tsx +0 -0
  478. /package/{client/src → src/client}/components/chat/toolSummary.ts +0 -0
  479. /package/{client/src → src/client}/components/dashboard/DashboardView.tsx +0 -0
  480. /package/{client/src → src/client}/components/dashboard/ProjectDashboardView.tsx +0 -0
  481. /package/{client/src → src/client}/components/mesh/NodeBadge.tsx +0 -0
  482. /package/{client/src → src/client}/components/mesh/PairingDialog.tsx +0 -0
  483. /package/{client/src → src/client}/components/project-settings/ProjectClaude.tsx +0 -0
  484. /package/{client/src → src/client}/components/project-settings/ProjectEnvironment.tsx +0 -0
  485. /package/{client/src → src/client}/components/project-settings/ProjectGeneral.tsx +0 -0
  486. /package/{client/src → src/client}/components/project-settings/ProjectMcp.tsx +0 -0
  487. /package/{client/src → src/client}/components/project-settings/ProjectMemory.tsx +0 -0
  488. /package/{client/src → src/client}/components/project-settings/ProjectNotifications.tsx +0 -0
  489. /package/{client/src → src/client}/components/project-settings/ProjectPermissions.tsx +0 -0
  490. /package/{client/src → src/client}/components/project-settings/ProjectPlugins.tsx +0 -0
  491. /package/{client/src → src/client}/components/project-settings/ProjectRules.tsx +0 -0
  492. /package/{client/src → src/client}/components/project-settings/ProjectSettingsView.tsx +0 -0
  493. /package/{client/src → src/client}/components/project-settings/ProjectSkills.tsx +0 -0
  494. /package/{client/src → src/client}/components/settings/ClaudeSettings.tsx +0 -0
  495. /package/{client/src → src/client}/components/settings/Editor.tsx +0 -0
  496. /package/{client/src → src/client}/components/settings/Environment.tsx +0 -0
  497. /package/{client/src → src/client}/components/settings/GlobalMcp.tsx +0 -0
  498. /package/{client/src → src/client}/components/settings/GlobalMemory.tsx +0 -0
  499. /package/{client/src → src/client}/components/settings/GlobalPlugins.tsx +0 -0
  500. /package/{client/src → src/client}/components/settings/GlobalRules.tsx +0 -0
  501. /package/{client/src → src/client}/components/settings/GlobalSkills.tsx +0 -0
  502. /package/{client/src → src/client}/components/settings/MeshStatus.tsx +0 -0
  503. /package/{client/src → src/client}/components/settings/SettingsView.tsx +0 -0
  504. /package/{client/src → src/client}/components/settings/SkillMarketplace.tsx +0 -0
  505. /package/{client/src → src/client}/components/settings/mcp-shared.tsx +0 -0
  506. /package/{client/src → src/client}/components/settings/skill-shared.tsx +0 -0
  507. /package/{client/src → src/client}/components/setup/SetupWizard.tsx +0 -0
  508. /package/{client/src → src/client}/components/sidebar/AddProjectModal.tsx +0 -0
  509. /package/{client/src → src/client}/components/sidebar/NodeSettingsModal.tsx +0 -0
  510. /package/{client/src → src/client}/components/sidebar/ProjectDropdown.tsx +0 -0
  511. /package/{client/src → src/client}/components/sidebar/SearchFilter.tsx +0 -0
  512. /package/{client/src → src/client}/components/sidebar/SettingsSidebar.tsx +0 -0
  513. /package/{client/src → src/client}/components/ui/CommandPalette.tsx +0 -0
  514. /package/{client/src → src/client}/components/ui/ErrorBoundary.tsx +0 -0
  515. /package/{client/src → src/client}/components/ui/IconPicker.tsx +0 -0
  516. /package/{client/src → src/client}/components/ui/KeyboardShortcuts.tsx +0 -0
  517. /package/{client/src → src/client}/components/ui/LatticeLogomark.tsx +0 -0
  518. /package/{client/src → src/client}/components/ui/NodeDisconnectedOverlay.tsx +0 -0
  519. /package/{client/src → src/client}/components/ui/Toast.tsx +0 -0
  520. /package/{client/src → src/client}/components/ui/UpdateBanner.tsx +0 -0
  521. /package/{client/src → src/client}/components/ui/UpdatePrompt.tsx +0 -0
  522. /package/{client/src → src/client}/components/workspace/BookmarksView.tsx +0 -0
  523. /package/{client/src → src/client}/components/workspace/FileBrowser.tsx +0 -0
  524. /package/{client/src → src/client}/components/workspace/FileTree.tsx +0 -0
  525. /package/{client/src → src/client}/components/workspace/FileViewer.tsx +0 -0
  526. /package/{client/src → src/client}/components/workspace/NoteCard.tsx +0 -0
  527. /package/{client/src → src/client}/components/workspace/NotesView.tsx +0 -0
  528. /package/{client/src → src/client}/components/workspace/ScheduledTasksView.tsx +0 -0
  529. /package/{client/src → src/client}/components/workspace/SplitPane.tsx +0 -0
  530. /package/{client/src → src/client}/components/workspace/TaskCard.tsx +0 -0
  531. /package/{client/src → src/client}/components/workspace/TaskEditModal.tsx +0 -0
  532. /package/{client/src → src/client}/components/workspace/TerminalInstance.tsx +0 -0
  533. /package/{client/src → src/client}/components/workspace/TerminalView.tsx +0 -0
  534. /package/{client/src → src/client}/components/workspace/WorkspaceView.tsx +0 -0
  535. /package/{client/src → src/client}/hooks/useAttachments.ts +0 -0
  536. /package/{client/src → src/client}/hooks/useBookmarks.ts +0 -0
  537. /package/{client/src → src/client}/hooks/useEditorConfig.ts +0 -0
  538. /package/{client/src → src/client}/hooks/useFocusTrap.ts +0 -0
  539. /package/{client/src → src/client}/hooks/useIdleDetection.ts +0 -0
  540. /package/{client/src → src/client}/hooks/useInstallPrompt.ts +0 -0
  541. /package/{client/src → src/client}/hooks/useMesh.ts +0 -0
  542. /package/{client/src → src/client}/hooks/useNotifications.ts +0 -0
  543. /package/{client/src → src/client}/hooks/useOnline.ts +0 -0
  544. /package/{client/src → src/client}/hooks/useProjectSettings.ts +0 -0
  545. /package/{client/src → src/client}/hooks/useProjects.ts +0 -0
  546. /package/{client/src → src/client}/hooks/useSaveState.ts +0 -0
  547. /package/{client/src → src/client}/hooks/useSidebar.ts +0 -0
  548. /package/{client/src → src/client}/hooks/useSkills.ts +0 -0
  549. /package/{client/src → src/client}/hooks/useSpinnerVerb.ts +0 -0
  550. /package/{client/src → src/client}/hooks/useSwipeDrawer.ts +0 -0
  551. /package/{client/src → src/client}/hooks/useTheme.ts +0 -0
  552. /package/{client/src → src/client}/hooks/useTimeTick.ts +0 -0
  553. /package/{client/src → src/client}/hooks/useVoiceRecorder.ts +0 -0
  554. /package/{client/src → src/client}/hooks/useWorkspace.ts +0 -0
  555. /package/{client/src → src/client}/lib/workspace-url.ts +0 -0
  556. /package/{client/src → src/client}/main.tsx +0 -0
  557. /package/{client/src → src/client}/providers/WebSocketProvider.tsx +0 -0
  558. /package/{client/src → src/client}/router.tsx +0 -0
  559. /package/{client/src → src/client}/stores/bookmarks.ts +0 -0
  560. /package/{client/src → src/client}/stores/mesh.ts +0 -0
  561. /package/{client/src → src/client}/stores/theme.ts +0 -0
  562. /package/{client/src → src/client}/stores/workspace.ts +0 -0
  563. /package/{client/src → src/client}/styles/global.css +0 -0
  564. /package/{client/src → src/client}/styles/theme-vars.css +0 -0
  565. /package/{client/src → src/client}/utils/editorUrl.ts +0 -0
  566. /package/{client/src → src/client}/utils/findDuplicateKeys.ts +0 -0
  567. /package/{client/src → src/client}/utils/formatSessionTitle.ts +0 -0
  568. /package/{client/src → src/client}/vite-env.d.ts +0 -0
  569. /package/{server/src → src/server}/auth/passphrase.ts +0 -0
  570. /package/{server/src → src/server}/config.ts +0 -0
  571. /package/{server/src → src/server}/features/ralph-loop.ts +0 -0
  572. /package/{server/src → src/server}/features/scheduler.ts +0 -0
  573. /package/{server/src → src/server}/features/sticky-notes.ts +0 -0
  574. /package/{server/src → src/server}/handlers/attachment.ts +0 -0
  575. /package/{server/src → src/server}/handlers/bookmarks.ts +0 -0
  576. /package/{server/src → src/server}/handlers/editor.ts +0 -0
  577. /package/{server/src → src/server}/handlers/fs.ts +0 -0
  578. /package/{server/src → src/server}/handlers/loop.ts +0 -0
  579. /package/{server/src → src/server}/handlers/memory.ts +0 -0
  580. /package/{server/src → src/server}/handlers/notes.ts +0 -0
  581. /package/{server/src → src/server}/handlers/project-settings.ts +0 -0
  582. /package/{server/src → src/server}/handlers/scheduler.ts +0 -0
  583. /package/{server/src → src/server}/handlers/terminal.ts +0 -0
  584. /package/{server/src → src/server}/identity.ts +0 -0
  585. /package/{server/src → src/server}/logger.ts +0 -0
  586. /package/{server/src → src/server}/mesh/crypto.ts +0 -0
  587. /package/{server/src → src/server}/mesh/discovery.ts +0 -0
  588. /package/{server/src → src/server}/mesh/pairing.ts +0 -0
  589. /package/{server/src → src/server}/mesh/peers.ts +0 -0
  590. /package/{server/src → src/server}/mesh/proxy.ts +0 -0
  591. /package/{server/src → src/server}/mesh/session-sync.ts +0 -0
  592. /package/{server/src → src/server}/project/bookmarks.ts +0 -0
  593. /package/{server/src → src/server}/project/file-browser.ts +0 -0
  594. /package/{server/src → src/server}/project/project-files.ts +0 -0
  595. /package/{server/src → src/server}/project/registry.ts +0 -0
  596. /package/{server/src → src/server}/tls.ts +0 -0
  597. /package/{server/src → src/server}/ws/server.ts +0 -0
  598. /package/{shared/src → src/shared}/index.ts +0 -0
  599. /package/{shared/src → src/shared}/project-settings.ts +0 -0
@@ -4,7 +4,7 @@ import type { SDKMessage, SDKPartialAssistantMessage, SDKResultMessage, SDKUserM
4
4
  import type { CanUseTool, PermissionMode, PermissionResult, PermissionUpdate } from "@anthropic-ai/claude-agent-sdk";
5
5
  type MessageParam = SDKUserMessage["message"];
6
6
  import type { Attachment } from "@lattice/shared";
7
- import { existsSync, readFileSync, writeFileSync, mkdirSync, statSync, readdirSync, readlinkSync } from "node:fs";
7
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
8
8
  import { join, resolve } from "node:path";
9
9
  import { homedir } from "node:os";
10
10
  import { sendTo, broadcast } from "../ws/broadcast";
@@ -15,6 +15,29 @@ import { guessContextWindow, getSessionTitle, renameSession, listSessions, inval
15
15
  import { getLatticeHome, loadConfig } from "../config";
16
16
  import { log } from "../logger";
17
17
  import { getDailySpend, invalidateDailySpendCache } from "../analytics/engine";
18
+ import { getWarmupModels, cacheRateLimitEntry } from "./warmup";
19
+ import { execSync } from "node:child_process";
20
+ import { sendPush } from "../push";
21
+
22
+ var HIDDEN_TOOLS = new Set([
23
+ "TaskUpdate", "TaskCreate", "TaskGet", "TaskList", "TaskOutput", "TaskStop",
24
+ "TodoWrite", "TodoRead",
25
+ "EnterPlanMode", "ExitPlanMode",
26
+ "ToolSearch",
27
+ ]);
28
+
29
+ var claudeExePath: string | null = null;
30
+
31
+ function getClaudeExecutablePath(): string {
32
+ if (claudeExePath) return claudeExePath;
33
+ try {
34
+ claudeExePath = execSync("which claude", { encoding: "utf-8" }).trim();
35
+ log.chat("Using system claude: %s", claudeExePath);
36
+ } catch {
37
+ claudeExePath = "claude";
38
+ }
39
+ return claudeExePath;
40
+ }
18
41
 
19
42
  interface PendingPermission {
20
43
  resolve: (result: PermissionResult) => void;
@@ -28,6 +51,15 @@ interface PendingPermission {
28
51
  }
29
52
 
30
53
  var pendingPermissions = new Map<string, PendingPermission>();
54
+
55
+ interface PendingElicitation {
56
+ resolve: (result: { action: "accept" | "decline"; content?: Record<string, unknown> }) => void;
57
+ clientId: string;
58
+ sessionId: string;
59
+ }
60
+
61
+ var pendingElicitations = new Map<string, PendingElicitation>();
62
+
31
63
  var autoApprovedTools = new Map<string, Set<string>>();
32
64
  var sessionPermissionOverrides = new Map<string, PermissionMode>();
33
65
 
@@ -49,87 +81,79 @@ export interface ModelEntry {
49
81
  displayName: string;
50
82
  }
51
83
 
52
- var KNOWN_MODELS: ModelEntry[] = [
53
- { value: "default", displayName: "Default" },
54
- { value: "opus", displayName: "Opus" },
55
- { value: "sonnet", displayName: "Sonnet" },
56
- { value: "haiku", displayName: "Haiku" },
57
- ];
58
-
59
84
  export function getAvailableModels(): ModelEntry[] {
60
- return KNOWN_MODELS.slice();
85
+ return getWarmupModels();
61
86
  }
62
87
 
63
- var activeStreams = new Map<string, Query>();
88
+ interface MessageQueue {
89
+ push(msg: SDKUserMessage): void;
90
+ end(): void;
91
+ [Symbol.asyncIterator](): AsyncIterator<SDKUserMessage>;
92
+ }
93
+
94
+ function createMessageQueue(): MessageQueue {
95
+ var queue: SDKUserMessage[] = [];
96
+ var waiting: ((result: IteratorResult<SDKUserMessage>) => void) | null = null;
97
+ var ended = false;
98
+
99
+ return {
100
+ push: function (msg: SDKUserMessage) {
101
+ if (waiting) {
102
+ var resolve = waiting;
103
+ waiting = null;
104
+ resolve({ value: msg, done: false });
105
+ } else {
106
+ queue.push(msg);
107
+ }
108
+ },
109
+ end: function () {
110
+ ended = true;
111
+ if (waiting) {
112
+ var resolve = waiting;
113
+ waiting = null;
114
+ resolve({ value: undefined as any, done: true });
115
+ }
116
+ },
117
+ [Symbol.asyncIterator]: function () {
118
+ return {
119
+ next: function (): Promise<IteratorResult<SDKUserMessage>> {
120
+ if (queue.length > 0) {
121
+ return Promise.resolve({ value: queue.shift()!, done: false });
122
+ }
123
+ if (ended) {
124
+ return Promise.resolve({ value: undefined as any, done: true });
125
+ }
126
+ return new Promise(function (resolve) {
127
+ waiting = resolve;
128
+ });
129
+ },
130
+ };
131
+ },
132
+ };
133
+ }
134
+
135
+ interface SessionStream {
136
+ sessionId: string;
137
+ messageQueue: MessageQueue;
138
+ queryInstance: Query;
139
+ abortController: AbortController;
140
+ projectSlug: string;
141
+ clientId: string;
142
+ cwd: string;
143
+ turnStartTime: number;
144
+ firstUserMessage: string;
145
+ currentModel: string | undefined;
146
+ activeToolBlocks: Record<number, { id: string; name: string; inputJson: string }>;
147
+ hiddenToolIds: Set<string>;
148
+ turnDoneSent: boolean;
149
+ messageUUIDs: Array<{ uuid: string; type: string }>;
150
+ ended: boolean;
151
+ }
152
+
153
+ var sessionStreams = new Map<string, SessionStream>();
64
154
  var pendingStreams = new Set<string>();
65
- var streamMetadata = new Map<string, { projectSlug: string; clientId: string; startedAt: number }>();
66
155
  var interruptedSessions = new Set<string>();
67
156
 
68
- // Track external lock state so we only broadcast on changes
69
- var externalLockState = new Map<string, boolean>();
70
- var watchedSessions = new Set<string>();
71
- var remoteSessionWatchers = new Map<string, Set<string>>();
72
-
73
- /**
74
- * Start polling a session's lock file for external CLI usage.
75
- * Called when a client activates a session.
76
- */
77
- export function watchSessionLock(sessionId: string): void {
78
- watchedSessions.add(sessionId);
79
- }
80
-
81
- /**
82
- * Stop polling a session's lock file.
83
- */
84
- export function unwatchSessionLock(sessionId: string): void {
85
- watchedSessions.delete(sessionId);
86
- externalLockState.delete(sessionId);
87
- }
88
-
89
- export function addRemoteSessionWatcher(sessionId: string, nodeId: string): void {
90
- var watchers = remoteSessionWatchers.get(sessionId);
91
- if (!watchers) {
92
- watchers = new Set();
93
- remoteSessionWatchers.set(sessionId, watchers);
94
- }
95
- watchers.add(nodeId);
96
- }
97
-
98
- export function getBusyOwner(sessionId: string): "cli" | "lattice" | undefined {
99
- if (activeStreams.has(sessionId)) return "lattice";
100
- if (isSessionLockedByExternal(sessionId)) return "cli";
101
- return undefined;
102
- }
103
-
104
- // Poll every 3 seconds for external lock changes
105
- setInterval(function () {
106
- for (var sessionId of watchedSessions) {
107
- var busy = isSessionBusy(sessionId);
108
- var prev = externalLockState.get(sessionId) ?? false;
109
-
110
- if (busy !== prev) {
111
- externalLockState.set(sessionId, busy);
112
- var owner = busy ? getBusyOwner(sessionId) : undefined;
113
- broadcast({ type: "session:busy", sessionId, busy: busy, busyOwner: owner });
114
-
115
- var watchers = remoteSessionWatchers.get(sessionId);
116
- if (watchers) {
117
- var { getPeerConnection } = require("../mesh/connector") as typeof import("../mesh/connector");
118
- for (var nodeId of watchers) {
119
- var peerWs = getPeerConnection(nodeId);
120
- if (peerWs) {
121
- peerWs.send(JSON.stringify({
122
- type: "mesh:proxy_response",
123
- projectSlug: "",
124
- requestId: "busy-" + sessionId,
125
- payload: { type: "session:busy", sessionId, busy: busy, busyOwner: owner },
126
- }));
127
- }
128
- }
129
- }
130
- }
131
- }
132
- }, 3000);
133
157
 
134
158
  function getStreamStatePath(): string {
135
159
  return join(getLatticeHome(), "active-streams.json");
@@ -137,8 +161,10 @@ function getStreamStatePath(): string {
137
161
 
138
162
  function persistStreamState(): void {
139
163
  var entries: Record<string, { projectSlug: string; clientId: string; startedAt: number }> = {};
140
- streamMetadata.forEach(function (meta, sessionId) {
141
- entries[sessionId] = meta;
164
+ sessionStreams.forEach(function (session, sessionId) {
165
+ if (!session.ended) {
166
+ entries[sessionId] = { projectSlug: session.projectSlug, clientId: session.clientId, startedAt: session.turnStartTime };
167
+ }
142
168
  });
143
169
  var dir = getLatticeHome();
144
170
  if (!existsSync(dir)) {
@@ -191,6 +217,30 @@ export function cleanupClientPermissions(clientId: string): void {
191
217
  }
192
218
  }
193
219
 
220
+ export function getPendingElicitation(requestId: string): PendingElicitation | undefined {
221
+ return pendingElicitations.get(requestId);
222
+ }
223
+
224
+ export function resolveElicitation(requestId: string, result: { action: "accept" | "decline"; content?: Record<string, unknown> }): void {
225
+ var pending = pendingElicitations.get(requestId);
226
+ if (!pending) return;
227
+ pendingElicitations.delete(requestId);
228
+ pending.resolve(result);
229
+ }
230
+
231
+ export function cleanupClientElicitations(clientId: string): void {
232
+ var toRemove: string[] = [];
233
+ pendingElicitations.forEach(function (entry, requestId) {
234
+ if (entry.clientId === clientId) {
235
+ toRemove.push(requestId);
236
+ entry.resolve({ action: "decline" });
237
+ }
238
+ });
239
+ for (var i = 0; i < toRemove.length; i++) {
240
+ pendingElicitations.delete(toRemove[i]);
241
+ }
242
+ }
243
+
194
244
  export function addAutoApprovedTool(sessionId: string, toolName: string): void {
195
245
  var tools = autoApprovedTools.get(sessionId);
196
246
  if (!tools) {
@@ -205,110 +255,43 @@ export function setSessionPermissionOverride(sessionId: string, mode: Permission
205
255
  }
206
256
 
207
257
  export function getActiveStream(sessionId: string): Query | undefined {
208
- return activeStreams.get(sessionId);
258
+ var session = sessionStreams.get(sessionId);
259
+ return session && !session.ended ? session.queryInstance : undefined;
209
260
  }
210
261
 
211
- export function getActiveStreamCount(): number {
212
- return activeStreams.size;
262
+ export function getSessionStream(sessionId: string): SessionStream | undefined {
263
+ var session = sessionStreams.get(sessionId);
264
+ return session && !session.ended ? session : undefined;
213
265
  }
214
266
 
215
- export function getActiveSessionCountForProject(projectPath: string): number {
267
+ export function getActiveStreamCount(): number {
216
268
  var count = 0;
217
- var hash = projectPath.replace(/\//g, "-");
218
- var dir = join(homedir(), ".claude", "projects", hash);
219
-
220
- for (var [sessionId] of activeStreams) {
221
- if (existsSync(join(dir, sessionId + ".jsonl"))) count++;
222
- }
223
-
224
- if (cliActiveProjects.has(projectPath)) count++;
225
-
269
+ sessionStreams.forEach(function (session) {
270
+ if (!session.ended) count++;
271
+ });
226
272
  return count;
227
273
  }
228
274
 
229
- /**
230
- * Check if a session is controlled by an external process (not Lattice).
231
- * Lattice's own active streams are handled by isProcessing on the client,
232
- * so this ONLY returns true for external CLI instances.
233
- */
234
- export function isSessionBusy(sessionId: string): boolean {
235
- if (activeStreams.has(sessionId)) return true;
236
- return isSessionLockedByExternal(sessionId);
237
- }
238
-
239
- /**
240
- * Check if a PID is the Lattice daemon or one of its child processes.
241
- * The SDK spawns child processes (e.g. claude-agent-sdk/cli.js) that hold
242
- * lock files — those are NOT external.
243
- */
244
- var cliActiveProjects = new Set<string>();
245
-
246
- function refreshCliDetection(): void {
247
- var newActive = new Set<string>();
248
- var cliPids = getClaudeCliPidsAsync();
249
- for (var i = 0; i < cliPids.length; i++) {
250
- newActive.add(cliPids[i].cwd);
251
- }
252
- cliActiveProjects = newActive;
253
- }
254
-
255
- function getClaudeCliPidsAsync(): Array<{ pid: number; cwd: string; cmdline: string[] }> {
256
- var results: Array<{ pid: number; cwd: string; cmdline: string[] }> = [];
257
- try {
258
- var procEntries = readdirSync("/proc").filter(function (e) { return /^\d+$/.test(e); });
259
- for (var i = 0; i < procEntries.length; i++) {
260
- var pid = parseInt(procEntries[i], 10);
261
- if (pid === process.pid) continue;
262
- try {
263
- var cmdline = readFileSync("/proc/" + pid + "/cmdline", "utf-8").split("\0");
264
- var exe = cmdline[0] || "";
265
- if (!exe.endsWith("/claude") && exe !== "claude") continue;
266
- var cwd = readlinkSync("/proc/" + pid + "/cwd");
267
- results.push({ pid, cwd, cmdline });
268
- } catch {}
269
- }
270
- } catch {}
271
- return results;
272
- }
273
-
274
- setInterval(refreshCliDetection, 10000);
275
-
276
- function getProjectPathForSession(sessionId: string): string | null {
277
- var config = loadConfig();
278
- for (var i = 0; i < config.projects.length; i++) {
279
- var hash = config.projects[i].path.replace(/\//g, "-");
280
- var jsonlPath = join(homedir(), ".claude", "projects", hash, sessionId + ".jsonl");
281
- if (existsSync(jsonlPath)) return config.projects[i].path;
282
- }
283
- return null;
275
+ export function getActiveStreamCountForProject(projectSlug: string): number {
276
+ var count = 0;
277
+ sessionStreams.forEach(function (session) {
278
+ if (!session.ended && session.projectSlug === projectSlug) count++;
279
+ });
280
+ return count;
284
281
  }
285
282
 
286
-
287
- function isSessionLockedByExternal(sessionId: string): boolean {
288
- if (activeStreams.has(sessionId)) return false;
289
- var projectPath = getProjectPathForSession(sessionId);
290
- if (!projectPath) return false;
291
- return cliActiveProjects.has(projectPath);
283
+ export function getSessionStreamClientId(sessionId: string): string | undefined {
284
+ var session = sessionStreams.get(sessionId);
285
+ return session && !session.ended ? session.clientId : undefined;
292
286
  }
293
287
 
294
- export function stopExternalSession(sessionId: string): boolean {
295
- var projectPath = getProjectPathForSession(sessionId);
296
- if (!projectPath) return false;
297
- var pids = getClaudeCliPidsAsync();
298
- for (var i = 0; i < pids.length; i++) {
299
- if (pids[i].cwd === projectPath) {
300
- try {
301
- process.kill(pids[i].pid, "SIGINT");
302
- return true;
303
- } catch {}
304
- }
288
+ export function endSessionStream(sessionId: string): void {
289
+ var session = sessionStreams.get(sessionId);
290
+ if (session && !session.ended) {
291
+ session.ended = true;
292
+ session.messageQueue.end();
293
+ session.abortController.abort();
305
294
  }
306
- return false;
307
- }
308
-
309
- export function getSessionStreamClientId(sessionId: string): string | undefined {
310
- var meta = streamMetadata.get(sessionId);
311
- return meta ? meta.clientId : undefined;
312
295
  }
313
296
 
314
297
  export function matchesAllowRules(rules: string[], toolName: string, currentRule: string): boolean {
@@ -423,12 +406,104 @@ function isDefaultTitle(title: string): boolean {
423
406
  return false;
424
407
  }
425
408
 
409
+ function resolvePromptText(text: string): string {
410
+ if (text.startsWith("/")) {
411
+ var parts = text.split(/\s+/);
412
+ var skillName = parts[0].slice(1);
413
+ var skillArgs = parts.slice(1).join(" ");
414
+ var skillContent = resolveSkillContent(skillName);
415
+ if (skillContent) {
416
+ return "<skill-name>" + skillName + "</skill-name>\n" +
417
+ "<skill-content>\n" + skillContent + "\n</skill-content>\n" +
418
+ (skillArgs ? "<skill-args>" + skillArgs + "</skill-args>\n" : "") +
419
+ "Execute this skill. Follow its instructions exactly.";
420
+ }
421
+ }
422
+ return text;
423
+ }
424
+
425
+ function buildSDKUserMessage(prompt: string, attachments: Attachment[] | undefined, sessionId: string): SDKUserMessage {
426
+ if (attachments && attachments.length > 0) {
427
+ var contentBlocks: Array<{ type: "text"; text: string } | { type: "image"; source: { type: "base64"; media_type: string; data: string } }> = [];
428
+ contentBlocks.push({ type: "text", text: prompt });
429
+
430
+ for (var ai = 0; ai < attachments.length; ai++) {
431
+ var att = attachments[ai];
432
+ if (att.type === "image" && att.mimeType && !att.mimeType.includes("svg")) {
433
+ contentBlocks.push({
434
+ type: "image",
435
+ source: {
436
+ type: "base64",
437
+ media_type: att.mimeType,
438
+ data: att.content,
439
+ },
440
+ });
441
+ } else {
442
+ var prefix = att.name ? "[Attached: " + att.name + "]\n" : "";
443
+ contentBlocks.push({
444
+ type: "text",
445
+ text: prefix + att.content,
446
+ });
447
+ }
448
+ }
449
+
450
+ return {
451
+ type: "user",
452
+ message: { role: "user", content: contentBlocks } as MessageParam,
453
+ parent_tool_use_id: null,
454
+ session_id: sessionId,
455
+ };
456
+ }
457
+
458
+ return {
459
+ type: "user",
460
+ message: { role: "user", content: [{ type: "text", text: prompt }] } as MessageParam,
461
+ parent_tool_use_id: null,
462
+ session_id: sessionId,
463
+ };
464
+ }
465
+
466
+ function pushToExistingStream(session: SessionStream, options: ChatStreamOptions): void {
467
+ var { text, attachments, clientId, sessionId, model } = options;
468
+
469
+ session.clientId = clientId;
470
+ session.turnStartTime = Date.now();
471
+ session.turnDoneSent = false;
472
+ session.activeToolBlocks = {};
473
+
474
+ var prompt = resolvePromptText(text);
475
+ var userMsg = buildSDKUserMessage(prompt, attachments, sessionId);
476
+
477
+ sendTo(clientId, {
478
+ type: "chat:user_message",
479
+ text,
480
+ uuid: crypto.randomUUID(),
481
+ });
482
+
483
+ if (model && model !== "default" && model !== session.currentModel) {
484
+ void session.queryInstance.setModel(model).catch(function (err) {
485
+ log.chat("Failed to switch model: %O", err);
486
+ });
487
+ session.currentModel = model;
488
+ }
489
+
490
+ broadcast({ type: "session:busy", sessionId, busy: true }, clientId);
491
+ session.messageQueue.push(userMsg);
492
+ }
493
+
426
494
  export function startChatStream(options: ChatStreamOptions): void {
427
495
  var { projectSlug, sessionId, text, attachments, clientId, cwd, env, model, effort, isNewSession } = options;
496
+
497
+ var existing = sessionStreams.get(sessionId);
498
+ if (existing && !existing.ended) {
499
+ pushToExistingStream(existing, options);
500
+ return;
501
+ }
502
+
428
503
  var startTime = Date.now();
429
504
  var firstUserMessage = text;
430
505
 
431
- if (activeStreams.has(sessionId) || pendingStreams.has(sessionId)) {
506
+ if (pendingStreams.has(sessionId)) {
432
507
  sendTo(clientId, { type: "chat:error", message: "Session already has an active stream." });
433
508
  return;
434
509
  }
@@ -481,19 +556,63 @@ export function startChatStream(options: ChatStreamOptions): void {
481
556
  } catch {}
482
557
  }
483
558
 
559
+ var abortController = new AbortController();
560
+ var currentClientId = clientId;
561
+
484
562
  var queryOptions: Parameters<typeof query>[0]["options"] = {
485
563
  cwd,
486
564
  permissionMode: effectiveMode,
487
565
  promptSuggestions: true,
566
+ settingSources: ["user", "project", "local"],
567
+ includePartialMessages: true,
568
+ enableFileCheckpointing: true,
569
+ agentProgressSummaries: true,
570
+ extraArgs: { "replay-user-messages": null },
571
+ abortController,
572
+ pathToClaudeCodeExecutable: getClaudeExecutablePath(),
488
573
  additionalDirectories: savedAdditionalDirs.length > 0 ? savedAdditionalDirs : undefined,
489
574
  mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers as Record<string, any> : undefined,
575
+ stderr: function (data: string) {
576
+ if (data.includes("error") || data.includes("Error") || data.includes("credit") || data.includes("Credit") || data.includes("billing") || data.includes("auth")) {
577
+ log.chat("SDK stderr: %s", data.trim());
578
+ }
579
+ },
490
580
  };
491
581
 
492
582
  (queryOptions as any).toolConfig = {
493
583
  askUserQuestion: { previewFormat: "html" },
494
584
  };
495
585
 
586
+ queryOptions.onElicitation = function (request: any, opts: any) {
587
+ return new Promise(function (resolve) {
588
+ var requestId = crypto.randomUUID();
589
+ var activeClientId = (sessionStreams.get(sessionId) || { clientId: currentClientId }).clientId;
590
+ pendingElicitations.set(requestId, { resolve, clientId: activeClientId, sessionId });
591
+ sendTo(activeClientId, {
592
+ type: "chat:elicitation_request",
593
+ requestId,
594
+ serverName: request.serverName || "MCP Server",
595
+ message: request.message || "",
596
+ mode: request.mode || "form",
597
+ url: request.url || null,
598
+ requestedSchema: request.requestedSchema || null,
599
+ });
600
+ sendPush({ type: "elicitation", title: "Input Required", body: (request.serverName || "MCP Server") + " needs your input", sessionId });
601
+ if (opts && opts.signal) {
602
+ opts.signal.addEventListener("abort", function () {
603
+ if (pendingElicitations.has(requestId)) {
604
+ pendingElicitations.delete(requestId);
605
+ resolve({ action: "decline" });
606
+ }
607
+ }, { once: true });
608
+ }
609
+ });
610
+ } as any;
611
+
496
612
  queryOptions.canUseTool = function (toolName, input, options) {
613
+ var ss = sessionStreams.get(sessionId);
614
+ var activeClientId = ss ? ss.clientId : currentClientId;
615
+
497
616
  var approved = autoApprovedTools.get(sessionId);
498
617
  if (approved && approved.has(toolName)) {
499
618
  return Promise.resolve({ behavior: "allow", updatedInput: input, toolUseID: options.toolUseID } as PermissionResult);
@@ -502,7 +621,7 @@ export function startChatStream(options: ChatStreamOptions): void {
502
621
  if (toolName === "AskUserQuestion") {
503
622
  var promptRequestId = options.toolUseID;
504
623
  var questions = (input as { questions: Array<{ question: string; header: string; options: Array<{ label: string; description: string; preview?: string }>; multiSelect: boolean }> }).questions;
505
- sendTo(clientId, {
624
+ sendTo(activeClientId, {
506
625
  type: "chat:prompt_request",
507
626
  requestId: promptRequestId,
508
627
  questions: questions,
@@ -514,7 +633,7 @@ export function startChatStream(options: ChatStreamOptions): void {
514
633
  toolUseID: options.toolUseID,
515
634
  input: input,
516
635
  suggestions: undefined,
517
- clientId: clientId,
636
+ clientId: activeClientId,
518
637
  sessionId: sessionId,
519
638
  promptType: "question",
520
639
  });
@@ -522,7 +641,7 @@ export function startChatStream(options: ChatStreamOptions): void {
522
641
  }
523
642
 
524
643
  if (toolName === "ExitPlanMode") {
525
- sendTo(clientId, {
644
+ sendTo(activeClientId, {
526
645
  type: "chat:plan_mode",
527
646
  active: false,
528
647
  });
@@ -571,7 +690,7 @@ export function startChatStream(options: ChatStreamOptions): void {
571
690
  var rule = buildPermissionRule(toolName, input);
572
691
  var title = options.title || rule;
573
692
 
574
- sendTo(clientId, {
693
+ sendTo(activeClientId, {
575
694
  type: "chat:permission_request",
576
695
  requestId: requestId,
577
696
  tool: toolName,
@@ -580,6 +699,7 @@ export function startChatStream(options: ChatStreamOptions): void {
580
699
  decisionReason: options.decisionReason,
581
700
  permissionRule: rule,
582
701
  });
702
+ sendPush({ type: "permission_request", title: "Permission Required", body: toolName + ": " + title, sessionId });
583
703
 
584
704
  return new Promise<PermissionResult>(function (resolve) {
585
705
  pendingPermissions.set(requestId, {
@@ -588,7 +708,7 @@ export function startChatStream(options: ChatStreamOptions): void {
588
708
  toolUseID: options.toolUseID,
589
709
  input: input,
590
710
  suggestions: options.suggestions,
591
- clientId: clientId,
711
+ clientId: activeClientId,
592
712
  sessionId: sessionId,
593
713
  });
594
714
 
@@ -597,7 +717,7 @@ export function startChatStream(options: ChatStreamOptions): void {
597
717
  if (pendingPermissions.has(requestId)) {
598
718
  pendingPermissions.delete(requestId);
599
719
  resolve({ behavior: "deny", message: "Stream aborted.", toolUseID: options.toolUseID });
600
- sendTo(clientId, { type: "chat:permission_resolved", requestId: requestId, status: "denied" });
720
+ sendTo(activeClientId, { type: "chat:permission_resolved", requestId: requestId, status: "denied" });
601
721
  }
602
722
  }, { once: true });
603
723
  }
@@ -647,19 +767,7 @@ export function startChatStream(options: ChatStreamOptions): void {
647
767
  queryOptions.env = env;
648
768
  }
649
769
 
650
- var prompt = text;
651
- if (text.startsWith("/")) {
652
- var parts = text.split(/\s+/);
653
- var skillName = parts[0].slice(1);
654
- var skillArgs = parts.slice(1).join(" ");
655
- var skillContent = resolveSkillContent(skillName);
656
- if (skillContent) {
657
- prompt = "<skill-name>" + skillName + "</skill-name>\n" +
658
- "<skill-content>\n" + skillContent + "\n</skill-content>\n" +
659
- (skillArgs ? "<skill-args>" + skillArgs + "</skill-args>\n" : "") +
660
- "Execute this skill. Follow its instructions exactly.";
661
- }
662
- }
770
+ var prompt = resolvePromptText(text);
663
771
 
664
772
  sendTo(clientId, {
665
773
  type: "chat:user_message",
@@ -667,71 +775,53 @@ export function startChatStream(options: ChatStreamOptions): void {
667
775
  uuid: crypto.randomUUID(),
668
776
  });
669
777
 
670
- var activeToolBlocks: Record<number, { id: string; name: string; inputJson: string }> = {};
671
- var doneSent = false;
672
-
673
- var queryPrompt: string | AsyncIterable<SDKUserMessage>;
674
-
675
- if (attachments && attachments.length > 0) {
676
- var contentBlocks: Array<{ type: "text"; text: string } | { type: "image"; source: { type: "base64"; media_type: string; data: string } }> = [];
677
- contentBlocks.push({ type: "text", text: prompt });
678
-
679
- for (var ai = 0; ai < attachments.length; ai++) {
680
- var att = attachments[ai];
681
- if (att.type === "image" && att.mimeType && !att.mimeType.includes("svg")) {
682
- contentBlocks.push({
683
- type: "image",
684
- source: {
685
- type: "base64",
686
- media_type: att.mimeType,
687
- data: att.content,
688
- },
689
- });
690
- } else {
691
- var prefix = att.name ? "[Attached: " + att.name + "]\n" : "";
692
- contentBlocks.push({
693
- type: "text",
694
- text: prefix + att.content,
695
- });
696
- }
697
- }
698
-
699
- var userMessage: SDKUserMessage = {
700
- type: "user",
701
- message: { role: "user", content: contentBlocks } as MessageParam,
702
- parent_tool_use_id: null,
703
- session_id: sessionId,
704
- };
778
+ var mq = createMessageQueue();
779
+ var firstMsg = buildSDKUserMessage(prompt, attachments, sessionId);
780
+ mq.push(firstMsg);
705
781
 
706
- queryPrompt = (async function* () {
707
- yield userMessage;
708
- })();
709
- } else {
710
- queryPrompt = prompt;
711
- }
712
-
713
- var stream = query({ prompt: queryPrompt, options: queryOptions });
782
+ var stream = query({ prompt: mq as any, options: queryOptions });
714
783
  pendingStreams.delete(sessionId);
715
- activeStreams.set(sessionId, stream);
716
- streamMetadata.set(sessionId, { projectSlug, clientId, startedAt: Date.now() });
784
+
785
+ var sessionStream: SessionStream = {
786
+ sessionId,
787
+ messageQueue: mq,
788
+ queryInstance: stream,
789
+ abortController,
790
+ projectSlug,
791
+ clientId,
792
+ cwd,
793
+ turnStartTime: startTime,
794
+ firstUserMessage: text,
795
+ currentModel: model,
796
+ activeToolBlocks: {},
797
+ hiddenToolIds: new Set<string>(),
798
+ turnDoneSent: false,
799
+ messageUUIDs: [],
800
+ ended: false,
801
+ };
802
+ sessionStreams.set(sessionId, sessionStream);
717
803
  persistStreamState();
718
804
  broadcast({ type: "session:busy", sessionId, busy: true }, clientId);
719
805
 
720
806
  void (async function () {
721
807
  try {
722
808
  for await (var msg of stream) {
723
- processMessage(msg);
809
+ processMessage(sessionStream, msg);
724
810
  }
725
811
  } catch (err: unknown) {
726
812
  var errMsg = err instanceof Error ? err.message : String(err);
727
- console.error("[lattice] SDK stream error: " + errMsg);
728
- sendTo(clientId, { type: "chat:error", message: errMsg });
813
+ if (errMsg.includes("aborted") || errMsg.includes("AbortError")) {
814
+ log.chat("Session %s stream aborted", sessionId);
815
+ } else {
816
+ console.error("[lattice] SDK stream error: " + errMsg);
817
+ sendTo(sessionStream.clientId, { type: "chat:error", message: errMsg });
818
+ }
729
819
  } finally {
820
+ sessionStream.ended = true;
730
821
  pendingStreams.delete(sessionId);
731
- activeStreams.delete(sessionId);
732
- streamMetadata.delete(sessionId);
822
+ sessionStreams.delete(sessionId);
733
823
  persistStreamState();
734
- broadcast({ type: "session:busy", sessionId, busy: false }, clientId);
824
+ broadcast({ type: "session:busy", sessionId, busy: false }, sessionStream.clientId);
735
825
 
736
826
  var toCleanup: string[] = [];
737
827
  pendingPermissions.forEach(function (entry, reqId) {
@@ -743,234 +833,242 @@ export function startChatStream(options: ChatStreamOptions): void {
743
833
  });
744
834
  toCleanup.forEach(function (reqId) { pendingPermissions.delete(reqId); });
745
835
 
836
+ var elicitToCleanup: string[] = [];
837
+ pendingElicitations.forEach(function (entry, reqId) {
838
+ if (entry.sessionId === sessionId) {
839
+ elicitToCleanup.push(reqId);
840
+ entry.resolve({ action: "decline" });
841
+ }
842
+ });
843
+ elicitToCleanup.forEach(function (reqId) { pendingElicitations.delete(reqId); });
844
+
746
845
  autoApprovedTools.delete(sessionId);
747
846
  sessionPermissionOverrides.delete(sessionId);
748
847
 
749
- if (!doneSent) {
750
- doneSent = true;
751
- sendTo(clientId, { type: "chat:done", cost: 0, duration: Date.now() - startTime });
848
+ if (!sessionStream.turnDoneSent) {
849
+ sessionStream.turnDoneSent = true;
850
+ sendTo(sessionStream.clientId, { type: "chat:done", cost: 0, duration: Date.now() - sessionStream.turnStartTime });
752
851
  }
753
852
  }
754
853
  })();
854
+ }
755
855
 
756
- function processMessage(msg: SDKMessage): void {
856
+ function processMessage(ss: SessionStream, msg: SDKMessage): void {
857
+ var sessionId = ss.sessionId;
757
858
 
758
- if (msg.type === "system") {
759
- var sysMsg = msg as { type: "system"; subtype?: string; mcp_servers?: { name: string; status: string }[]; tools?: string[] };
760
- if (sysMsg.subtype === "init") {
761
- var toolCount = (sysMsg.tools || []).length;
762
- var mcpCount = (sysMsg.mcp_servers || []).filter(function (s) { return s.status === "connected"; }).length;
763
- log.chat("Session ready: %d tools, %d MCP servers connected", toolCount, mcpCount);
764
- }
765
- return;
859
+ if (msg.type === "system") {
860
+ var sysMsg = msg as { type: "system"; subtype?: string; mcp_servers?: { name: string; status: string }[]; tools?: string[] };
861
+ if (sysMsg.subtype === "init") {
862
+ var toolCount = (sysMsg.tools || []).length;
863
+ var mcpCount = (sysMsg.mcp_servers || []).filter(function (s) { return s.status === "connected"; }).length;
864
+ log.chat("Session ready: %d tools, %d MCP servers connected", toolCount, mcpCount);
766
865
  }
866
+ return;
867
+ }
767
868
 
768
- if (msg.type === "assistant") {
769
- var assistantMsg = msg as { type: "assistant"; message: { content: unknown; model?: string; usage?: { input_tokens?: number; output_tokens?: number; cache_read_input_tokens?: number; cache_creation_input_tokens?: number } } };
770
- var msgUsage = assistantMsg.message.usage;
771
- if (msgUsage && msgUsage.input_tokens != null) {
772
- sendTo(clientId, {
773
- type: "chat:context_usage",
774
- inputTokens: msgUsage.input_tokens || 0,
775
- outputTokens: msgUsage.output_tokens || 0,
776
- cacheReadTokens: msgUsage.cache_read_input_tokens || 0,
777
- cacheCreationTokens: msgUsage.cache_creation_input_tokens || 0,
778
- contextWindow: guessContextWindow(assistantMsg.message.model || ""),
779
- });
780
- }
781
- var aContent = assistantMsg.message.content;
782
- if (Array.isArray(aContent)) {
783
- for (var ai = 0; ai < aContent.length; ai++) {
784
- var aBlock = aContent[ai] as { type?: string; text?: string; id?: string; name?: string; input?: unknown };
785
- if (aBlock.type === "text" && aBlock.text) {
786
- sendTo(clientId, { type: "chat:delta", text: aBlock.text });
787
- } else if (aBlock.type === "tool_use" && aBlock.id && aBlock.name) {
788
- sendTo(clientId, {
789
- type: "chat:tool_start",
790
- toolId: aBlock.id,
791
- name: aBlock.name,
792
- args: JSON.stringify(aBlock.input ?? {}),
793
- });
794
- if (aBlock.name === "TodoWrite" && aBlock.input) {
795
- var todoInput = aBlock.input as { todos?: Array<{ id?: string; content: string; status: string; activeForm?: string }> };
796
- if (todoInput.todos) {
797
- sendTo(clientId, {
798
- type: "chat:todo_update",
799
- todos: todoInput.todos.map(function (t, idx) {
800
- return { id: t.id || String(idx), content: t.content, status: t.status, priority: "medium" };
801
- }),
802
- });
803
- }
804
- }
805
- if (aBlock.name === "EnterPlanMode") {
806
- sendTo(clientId, { type: "chat:plan_mode", active: true });
807
- }
808
- if (aBlock.name === "ExitPlanMode") {
809
- sendTo(clientId, { type: "chat:plan_mode", active: false });
810
- }
811
- }
812
- }
813
- } else if (typeof aContent === "string" && aContent) {
814
- sendTo(clientId, { type: "chat:delta", text: aContent });
815
- }
816
- return;
869
+ if (msg.type === "assistant") {
870
+ var assistantMsg = msg as { type: "assistant"; message: { content: unknown; model?: string; usage?: { input_tokens?: number; output_tokens?: number; cache_read_input_tokens?: number; cache_creation_input_tokens?: number } } };
871
+ var msgUsage = assistantMsg.message.usage;
872
+ if (msgUsage && msgUsage.input_tokens != null) {
873
+ sendTo(ss.clientId, {
874
+ type: "chat:context_usage",
875
+ inputTokens: msgUsage.input_tokens || 0,
876
+ outputTokens: msgUsage.output_tokens || 0,
877
+ cacheReadTokens: msgUsage.cache_read_input_tokens || 0,
878
+ cacheCreationTokens: msgUsage.cache_creation_input_tokens || 0,
879
+ contextWindow: guessContextWindow(assistantMsg.message.model || ""),
880
+ });
817
881
  }
882
+ return;
883
+ }
818
884
 
819
- if (msg.type === "stream_event") {
820
- var partial = msg as SDKPartialAssistantMessage;
821
- var evt = partial.event;
822
-
823
- if (evt.type === "content_block_start") {
824
- var block = (evt as { content_block: { type: string; id?: string; name?: string }; index: number }).content_block;
825
- var idx = (evt as { index: number }).index;
826
- if (block.type === "tool_use" && block.id && block.name) {
827
- activeToolBlocks[idx] = { id: block.id, name: block.name, inputJson: "" };
828
- sendTo(clientId, {
885
+ if (msg.type === "stream_event") {
886
+ var partial = msg as SDKPartialAssistantMessage;
887
+ var evt = partial.event;
888
+
889
+ if (evt.type === "content_block_start") {
890
+ var block = (evt as { content_block: { type: string; id?: string; name?: string }; index: number }).content_block;
891
+ var idx = (evt as { index: number }).index;
892
+ if (block.type === "tool_use" && block.id && block.name) {
893
+ ss.activeToolBlocks[idx] = { id: block.id, name: block.name, inputJson: "" };
894
+ if (HIDDEN_TOOLS.has(block.name)) {
895
+ ss.hiddenToolIds.add(block.id);
896
+ } else {
897
+ sendTo(ss.clientId, {
829
898
  type: "chat:tool_start",
830
899
  toolId: block.id,
831
900
  name: block.name,
832
901
  args: "",
833
902
  });
834
903
  }
835
- return;
836
904
  }
905
+ return;
906
+ }
837
907
 
838
- if (evt.type === "content_block_delta") {
839
- var deltaEvt = evt as { index: number; delta: { type: string; text?: string; partial_json?: string } };
840
- var blockIdx = deltaEvt.index;
908
+ if (evt.type === "content_block_delta") {
909
+ var deltaEvt = evt as { index: number; delta: { type: string; text?: string; partial_json?: string } };
910
+ var blockIdx = deltaEvt.index;
841
911
 
842
- if (deltaEvt.delta.type === "text_delta" && typeof deltaEvt.delta.text === "string") {
843
- sendTo(clientId, { type: "chat:delta", text: deltaEvt.delta.text });
844
- } else if (deltaEvt.delta.type === "input_json_delta" && activeToolBlocks[blockIdx]) {
845
- activeToolBlocks[blockIdx].inputJson += deltaEvt.delta.partial_json || "";
846
- var updatedTool = activeToolBlocks[blockIdx];
847
- sendTo(clientId, {
912
+ if (deltaEvt.delta.type === "text_delta" && typeof deltaEvt.delta.text === "string") {
913
+ sendTo(ss.clientId, { type: "chat:delta", text: deltaEvt.delta.text });
914
+ } else if (deltaEvt.delta.type === "input_json_delta" && ss.activeToolBlocks[blockIdx]) {
915
+ ss.activeToolBlocks[blockIdx].inputJson += deltaEvt.delta.partial_json || "";
916
+ }
917
+ return;
918
+ }
919
+
920
+ if (evt.type === "content_block_stop") {
921
+ var stopIdx = (evt as { index: number }).index;
922
+ var stoppedBlock = ss.activeToolBlocks[stopIdx];
923
+ if (stoppedBlock) {
924
+ if (!HIDDEN_TOOLS.has(stoppedBlock.name)) {
925
+ sendTo(ss.clientId, {
848
926
  type: "chat:tool_start",
849
- toolId: updatedTool.id,
850
- name: updatedTool.name,
851
- args: updatedTool.inputJson,
927
+ toolId: stoppedBlock.id,
928
+ name: stoppedBlock.name,
929
+ args: stoppedBlock.inputJson,
852
930
  });
853
931
  }
854
- return;
855
- }
856
-
857
- if (evt.type === "content_block_stop") {
858
- var stopIdx = (evt as { index: number }).index;
859
- var stoppedBlock = activeToolBlocks[stopIdx];
860
- if (stoppedBlock) {
861
- if (stoppedBlock.name === "TodoWrite" && stoppedBlock.inputJson) {
862
- try {
863
- var todoInput = JSON.parse(stoppedBlock.inputJson) as { todos?: Array<{ id?: string; content: string; status: string; activeForm?: string }> };
864
- if (todoInput.todos) {
865
- sendTo(clientId, {
866
- type: "chat:todo_update",
867
- todos: todoInput.todos.map(function (t, idx) {
868
- return { id: t.id || String(idx), content: t.content, status: t.status, priority: "medium" };
869
- }),
870
- });
871
- }
872
- } catch {}
873
- }
874
- if (stoppedBlock.name === "EnterPlanMode") {
875
- sendTo(clientId, { type: "chat:plan_mode", active: true });
876
- }
877
- if (stoppedBlock.name === "ExitPlanMode") {
878
- sendTo(clientId, { type: "chat:plan_mode", active: false });
879
- }
880
- delete activeToolBlocks[stopIdx];
932
+ if (stoppedBlock.name === "TodoWrite" && stoppedBlock.inputJson) {
933
+ try {
934
+ var todoInput = JSON.parse(stoppedBlock.inputJson) as { todos?: Array<{ id?: string; content: string; status: string; activeForm?: string }> };
935
+ if (todoInput.todos) {
936
+ sendTo(ss.clientId, {
937
+ type: "chat:todo_update",
938
+ todos: todoInput.todos.map(function (t, idx) {
939
+ return { id: t.id || String(idx), content: t.content, status: t.status, priority: "medium" };
940
+ }),
941
+ });
942
+ }
943
+ } catch {}
944
+ }
945
+ if (stoppedBlock.name === "EnterPlanMode") {
946
+ sendTo(ss.clientId, { type: "chat:plan_mode", active: true });
947
+ }
948
+ if (stoppedBlock.name === "ExitPlanMode") {
949
+ sendTo(ss.clientId, { type: "chat:plan_mode", active: false });
881
950
  }
882
- return;
951
+ delete ss.activeToolBlocks[stopIdx];
883
952
  }
884
-
885
953
  return;
886
954
  }
887
955
 
888
- if (msg.type === "user") {
889
- var userMsg = msg as { type: "user"; message: { content: unknown }; tool_use_result?: unknown };
890
- var content = userMsg.message.content;
891
- if (Array.isArray(content)) {
892
- for (var i = 0; i < content.length; i++) {
893
- var item = content[i] as { type?: string; tool_use_id?: string; content?: unknown };
894
- if (item.type === "tool_result" && item.tool_use_id) {
895
- var resultContent = typeof item.content === "string"
896
- ? item.content
897
- : JSON.stringify(item.content ?? "");
898
- sendTo(clientId, {
899
- type: "chat:tool_result",
900
- toolId: item.tool_use_id,
901
- content: resultContent,
902
- });
903
- }
956
+ return;
957
+ }
958
+
959
+ if (msg.type === "user") {
960
+ var userMsg = msg as { type: "user"; message: { content: unknown }; uuid?: string; tool_use_result?: unknown };
961
+ if (userMsg.uuid) {
962
+ ss.messageUUIDs.push({ uuid: userMsg.uuid, type: "user" });
963
+ sendTo(ss.clientId, { type: "chat:message_uuid" as any, uuid: userMsg.uuid, messageType: "user" });
964
+ }
965
+ var content = userMsg.message.content;
966
+ if (Array.isArray(content)) {
967
+ for (var i = 0; i < content.length; i++) {
968
+ var item = content[i] as { type?: string; tool_use_id?: string; content?: unknown };
969
+ if (item.type === "tool_result" && item.tool_use_id) {
970
+ if (ss.hiddenToolIds.has(item.tool_use_id)) continue;
971
+ var resultContent = typeof item.content === "string"
972
+ ? item.content
973
+ : JSON.stringify(item.content ?? "");
974
+ sendTo(ss.clientId, {
975
+ type: "chat:tool_result",
976
+ toolId: item.tool_use_id,
977
+ content: resultContent,
978
+ });
904
979
  }
905
980
  }
906
- return;
907
981
  }
982
+ return;
983
+ }
908
984
 
909
- if (msg.type === "prompt_suggestion") {
910
- var suggestion = (msg as { type: string; suggestion: string }).suggestion;
911
- if (suggestion) {
912
- sendTo(clientId, { type: "chat:prompt_suggestion", suggestion: suggestion });
913
- }
914
- return;
915
- }
985
+ if (msg.type === "rate_limit_event") {
986
+ var rlMsg = msg as { type: string; rate_limit_info: { status: string; utilization?: number; resetsAt?: number; rateLimitType?: string; overageStatus?: string; overageResetsAt?: number; isUsingOverage?: boolean } };
987
+ var rli = rlMsg.rate_limit_info;
988
+ cacheRateLimitEntry({
989
+ status: rli.status,
990
+ utilization: rli.utilization,
991
+ resetsAt: rli.resetsAt,
992
+ rateLimitType: rli.rateLimitType,
993
+ overageStatus: rli.overageStatus,
994
+ overageResetsAt: rli.overageResetsAt,
995
+ isUsingOverage: rli.isUsingOverage,
996
+ });
997
+ sendTo(ss.clientId, {
998
+ type: "chat:rate_limit",
999
+ status: rli.status,
1000
+ utilization: rli.utilization,
1001
+ resetsAt: rli.resetsAt,
1002
+ rateLimitType: rli.rateLimitType,
1003
+ overageStatus: rli.overageStatus,
1004
+ overageResetsAt: rli.overageResetsAt,
1005
+ isUsingOverage: rli.isUsingOverage,
1006
+ } as any);
1007
+ return;
1008
+ }
916
1009
 
917
- if (msg.type === "result") {
918
- var resultMsg = msg as SDKResultMessage;
919
- var dur = Date.now() - startTime;
920
- var cost = resultMsg.total_cost_usd || 0;
1010
+ if (msg.type === "prompt_suggestion") {
1011
+ var suggestion = (msg as { type: string; suggestion: string }).suggestion;
1012
+ if (suggestion) {
1013
+ sendTo(ss.clientId, { type: "chat:prompt_suggestion", suggestion: suggestion });
1014
+ }
1015
+ return;
1016
+ }
921
1017
 
922
- if (resultMsg.usage && resultMsg.modelUsage) {
923
- var contextWindow = 0;
924
- var modelKeys = Object.keys(resultMsg.modelUsage);
925
- for (var mk = 0; mk < modelKeys.length; mk++) {
926
- var mu = resultMsg.modelUsage[modelKeys[mk]];
927
- if (mu.contextWindow > contextWindow) {
928
- contextWindow = mu.contextWindow;
929
- }
1018
+ if (msg.type === "result") {
1019
+ var resultMsg = msg as SDKResultMessage;
1020
+ var dur = Date.now() - ss.turnStartTime;
1021
+ var cost = resultMsg.total_cost_usd || 0;
1022
+
1023
+ if (resultMsg.usage && resultMsg.modelUsage) {
1024
+ var contextWindow = 0;
1025
+ var modelKeys = Object.keys(resultMsg.modelUsage);
1026
+ for (var mk = 0; mk < modelKeys.length; mk++) {
1027
+ var mu = resultMsg.modelUsage[modelKeys[mk]];
1028
+ if (mu.contextWindow > contextWindow) {
1029
+ contextWindow = mu.contextWindow;
930
1030
  }
931
- sendTo(clientId, {
932
- type: "chat:context_usage",
933
- inputTokens: resultMsg.usage.input_tokens || 0,
934
- outputTokens: resultMsg.usage.output_tokens || 0,
935
- cacheReadTokens: resultMsg.usage.cache_read_input_tokens || 0,
936
- cacheCreationTokens: resultMsg.usage.cache_creation_input_tokens || 0,
937
- contextWindow: contextWindow,
938
- });
939
1031
  }
1032
+ sendTo(ss.clientId, {
1033
+ type: "chat:context_usage",
1034
+ inputTokens: resultMsg.usage.input_tokens || 0,
1035
+ outputTokens: resultMsg.usage.output_tokens || 0,
1036
+ cacheReadTokens: resultMsg.usage.cache_read_input_tokens || 0,
1037
+ cacheCreationTokens: resultMsg.usage.cache_creation_input_tokens || 0,
1038
+ contextWindow: contextWindow,
1039
+ });
1040
+ }
940
1041
 
941
- doneSent = true;
942
- activeStreams.delete(sessionId);
943
- streamMetadata.delete(sessionId);
944
- persistStreamState();
945
- sendTo(clientId, { type: "chat:done", cost: cost, duration: dur });
946
- invalidateDailySpendCache();
947
- var budgetConfig = loadConfig().costBudget;
948
- if (budgetConfig) {
949
- sendTo(clientId, {
950
- type: "budget:status",
951
- dailySpend: getDailySpend(),
952
- dailyLimit: budgetConfig.dailyLimit,
953
- enforcement: budgetConfig.enforcement,
954
- } as never);
955
- }
956
- broadcast({ type: "session:busy", sessionId, busy: false }, clientId);
957
- syncSessionToPeers(cwd, projectSlug, sessionId);
958
-
959
- void getSessionTitle(projectSlug, sessionId).then(function (currentTitle) {
960
- if (!isDefaultTitle(currentTitle)) return;
961
- var newTitle = generateSessionTitle(firstUserMessage);
962
- if (!newTitle) return;
963
- void renameSession(projectSlug, sessionId, newTitle).then(function (ok) {
964
- if (!ok) return;
965
- log.session("Auto-titled session %s: %s", sessionId, newTitle);
966
- invalidateSessionCache(projectSlug);
967
- void listSessions(projectSlug, { limit: 40 }).then(function (result) {
968
- broadcast({ type: "session:list", projectSlug, sessions: result.sessions, totalCount: result.totalCount });
969
- });
1042
+ ss.turnDoneSent = true;
1043
+ sendTo(ss.clientId, { type: "chat:done", cost: cost, duration: dur });
1044
+ sendPush({ type: "done", title: "Task Complete", body: "Claude finished responding", sessionId, projectSlug: ss.projectSlug });
1045
+ invalidateDailySpendCache();
1046
+ var budgetConfig = loadConfig().costBudget;
1047
+ if (budgetConfig) {
1048
+ sendTo(ss.clientId, {
1049
+ type: "budget:status",
1050
+ dailySpend: getDailySpend(),
1051
+ dailyLimit: budgetConfig.dailyLimit,
1052
+ enforcement: budgetConfig.enforcement,
1053
+ } as never);
1054
+ }
1055
+ broadcast({ type: "session:busy", sessionId, busy: false }, ss.clientId);
1056
+ syncSessionToPeers(ss.cwd, ss.projectSlug, sessionId);
1057
+
1058
+ void getSessionTitle(ss.projectSlug, sessionId).then(function (currentTitle) {
1059
+ if (!isDefaultTitle(currentTitle)) return;
1060
+ var newTitle = generateSessionTitle(ss.firstUserMessage);
1061
+ if (!newTitle) return;
1062
+ void renameSession(ss.projectSlug, sessionId, newTitle).then(function (ok) {
1063
+ if (!ok) return;
1064
+ log.session("Auto-titled session %s: %s", sessionId, newTitle);
1065
+ invalidateSessionCache(ss.projectSlug);
1066
+ void listSessions(ss.projectSlug, { limit: 40 }).then(function (result) {
1067
+ broadcast({ type: "session:list", projectSlug: ss.projectSlug, sessions: result.sessions, totalCount: result.totalCount });
970
1068
  });
971
1069
  });
1070
+ });
972
1071
 
973
- return;
974
- }
1072
+ return;
975
1073
  }
976
1074
  }