zidane 9.1.1 → 9.1.3

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 (279) hide show
  1. package/dist/{acp-Di9WvMDF.js → acp-CeCavNlg.js} +7 -7
  2. package/dist/{acp-Di9WvMDF.js.map → acp-CeCavNlg.js.map} +1 -1
  3. package/dist/acp-cli.js +5 -5
  4. package/dist/acp.d.ts +2 -2
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-DJhpTS-B.js → agent-Dh_XZ7fj.js} +74 -19
  7. package/dist/agent-Dh_XZ7fj.js.map +1 -0
  8. package/dist/agent.d.ts +1 -1
  9. package/dist/agent.js +1 -1
  10. package/dist/{auth-store-port-DFgf22oo.js → auth-store-port-BKpjlJ8a.js} +2 -2
  11. package/dist/{auth-store-port-DFgf22oo.js.map → auth-store-port-BKpjlJ8a.js.map} +1 -1
  12. package/dist/{auto-update-restart-BFB7Ek87.js → auto-update-restart-CQJtndMG.js} +277 -41
  13. package/dist/auto-update-restart-CQJtndMG.js.map +1 -0
  14. package/dist/{browser-BcoCCB_n.js → browser-BkdeKnxO.js} +56 -2
  15. package/dist/browser-BkdeKnxO.js.map +1 -0
  16. package/dist/{browser-entry-ypi8CyE-.d.ts → browser-entry-BCwruqNa.d.ts} +10 -10
  17. package/dist/{browser-entry-ypi8CyE-.d.ts.map → browser-entry-BCwruqNa.d.ts.map} +1 -1
  18. package/dist/channels.d.ts +5 -5
  19. package/dist/chat/browser.d.ts +4 -4
  20. package/dist/chat/browser.js +6 -6
  21. package/dist/chat/pure.d.ts +5 -5
  22. package/dist/chat/pure.js +8 -8
  23. package/dist/chat.d.ts +5 -5
  24. package/dist/chat.js +55 -55
  25. package/dist/chat.js.map +1 -1
  26. package/dist/{cli-shared-CabruH8Z.js → cli-shared-DeRHgYvl.js} +4 -4
  27. package/dist/{cli-shared-CabruH8Z.js.map → cli-shared-DeRHgYvl.js.map} +1 -1
  28. package/dist/cli-style-DBEm6CyT.js +105 -0
  29. package/dist/cli-style-DBEm6CyT.js.map +1 -0
  30. package/dist/{client-core-CIixwznM.d.ts → client-core-C_4m_oL6.d.ts} +4 -4
  31. package/dist/{client-core-CIixwznM.d.ts.map → client-core-C_4m_oL6.d.ts.map} +1 -1
  32. package/dist/{client-CCaIXWue.d.ts → client-ygTASGis.d.ts} +2 -2
  33. package/dist/{client-CCaIXWue.d.ts.map → client-ygTASGis.d.ts.map} +1 -1
  34. package/dist/codemode-worker.js +8 -5
  35. package/dist/codemode-worker.js.map +1 -1
  36. package/dist/codemode.d.ts +16 -0
  37. package/dist/codemode.d.ts.map +1 -1
  38. package/dist/codemode.js +2 -2
  39. package/dist/{connection-loop-QmWL-fJf.d.ts → connection-loop-D_pRONCr.d.ts} +4 -4
  40. package/dist/{connection-loop-QmWL-fJf.d.ts.map → connection-loop-D_pRONCr.d.ts.map} +1 -1
  41. package/dist/contexts/daytona.d.ts +3 -3
  42. package/dist/contexts/docker.d.ts +1 -1
  43. package/dist/contexts/e2b.d.ts +2 -2
  44. package/dist/contexts/sandbox.d.ts +1 -1
  45. package/dist/{contexts-C72b0mMa.js → contexts-DLZTSRHU.js} +17 -106
  46. package/dist/contexts-DLZTSRHU.js.map +1 -0
  47. package/dist/contexts.d.ts +4 -4
  48. package/dist/contexts.js +2 -2
  49. package/dist/{credentials-wwETW8rI.js → credentials-Bqg-qNBM.js} +2 -2
  50. package/dist/{credentials-wwETW8rI.js.map → credentials-Bqg-qNBM.js.map} +1 -1
  51. package/dist/{cwd-picker-CcekODCt.js → cwd-picker-BsHA6HKv.js} +4 -4
  52. package/dist/{cwd-picker-CcekODCt.js.map → cwd-picker-BsHA6HKv.js.map} +1 -1
  53. package/dist/daemon-cli.js +4 -3
  54. package/dist/daemon-cli.js.map +1 -1
  55. package/dist/{decisions-CXmK0nz9.js → decisions-hsw5XS2g.js} +3 -1
  56. package/dist/decisions-hsw5XS2g.js.map +1 -0
  57. package/dist/{discovery-DycXFxdA.js → discovery-CX7nbMCn.js} +4 -4
  58. package/dist/{discovery-DycXFxdA.js.map → discovery-CX7nbMCn.js.map} +1 -1
  59. package/dist/durable/sqlite.d.ts +2 -2
  60. package/dist/durable.d.ts +1 -1
  61. package/dist/{engine-VQ86XGdG.js → engine-CxBGgU94.js} +6 -6
  62. package/dist/{engine-VQ86XGdG.js.map → engine-CxBGgU94.js.map} +1 -1
  63. package/dist/{eval-Bod0I1W_.js → eval-CfGUDAkN.js} +3 -3
  64. package/dist/{eval-Bod0I1W_.js.map → eval-CfGUDAkN.js.map} +1 -1
  65. package/dist/eval.d.ts +1 -1
  66. package/dist/eval.js +1 -1
  67. package/dist/{executor-C7RQrkEq.js → executor-j_LFRBwS.js} +4 -4
  68. package/dist/{executor-C7RQrkEq.js.map → executor-j_LFRBwS.js.map} +1 -1
  69. package/dist/{extension-mark-BqKdEZwF.js → extension-mark-_rhkDWL5.js} +9 -6
  70. package/dist/extension-mark-_rhkDWL5.js.map +1 -0
  71. package/dist/extensions/testing.d.ts +1 -1
  72. package/dist/extensions/testing.js +2 -2
  73. package/dist/{extensions-BCx4QuGB.js → extensions-ADlhBQ_1.js} +8 -8
  74. package/dist/{extensions-BCx4QuGB.js.map → extensions-ADlhBQ_1.js.map} +1 -1
  75. package/dist/{extensions-client-D8tEAcMw.d.ts → extensions-client-D4Q2XRKV.d.ts} +31 -5
  76. package/dist/extensions-client-D4Q2XRKV.d.ts.map +1 -0
  77. package/dist/extensions.d.ts +1 -1
  78. package/dist/extensions.js +6 -6
  79. package/dist/{fold-rules-DvLK8pbf.d.ts → fold-rules-1DpDwG9h.d.ts} +2 -2
  80. package/dist/{fold-rules-DvLK8pbf.d.ts.map → fold-rules-1DpDwG9h.d.ts.map} +1 -1
  81. package/dist/{google-Crva32sk.js → google-B-Dhmzzf.js} +2 -2
  82. package/dist/{google-Crva32sk.js.map → google-B-Dhmzzf.js.map} +1 -1
  83. package/dist/{headless-CCm-jLLT.js → headless-CQm19BL0.js} +4 -4
  84. package/dist/{headless-CCm-jLLT.js.map → headless-CQm19BL0.js.map} +1 -1
  85. package/dist/headless.d.ts +1 -1
  86. package/dist/headless.js +1 -1
  87. package/dist/history-worker.js +1 -1
  88. package/dist/{host-wO_6GW0y.js → host-C61ntFBC.js} +276 -103
  89. package/dist/host-C61ntFBC.js.map +1 -0
  90. package/dist/{host-BHMs9jsN.js → host-DEoEzQal.js} +13 -4
  91. package/dist/host-DEoEzQal.js.map +1 -0
  92. package/dist/{host-scoped-settings-CrbcqOkP.js → host-scoped-settings-WBYaCork.js} +2 -2
  93. package/dist/{host-scoped-settings-CrbcqOkP.js.map → host-scoped-settings-WBYaCork.js.map} +1 -1
  94. package/dist/{host-signals-Jsjd_-4g.js → host-signals-Cb2TlGtN.js} +5 -5
  95. package/dist/{host-signals-Jsjd_-4g.js.map → host-signals-Cb2TlGtN.js.map} +1 -1
  96. package/dist/{host-version-CNAr9pov.js → host-version-BIx4CuBM.js} +2 -2
  97. package/dist/{host-version-CNAr9pov.js.map → host-version-BIx4CuBM.js.map} +1 -1
  98. package/dist/{index-C6nnKu32.d.ts → index-B0PLo9jn.d.ts} +4 -4
  99. package/dist/{index-C6nnKu32.d.ts.map → index-B0PLo9jn.d.ts.map} +1 -1
  100. package/dist/{index-Djnc8Peh.d.ts → index-De4x-s76.d.ts} +14 -14
  101. package/dist/{index-Djnc8Peh.d.ts.map → index-De4x-s76.d.ts.map} +1 -1
  102. package/dist/{index-CGbOWa7y.d.ts → index-WlE93Q6d.d.ts} +411 -3
  103. package/dist/index-WlE93Q6d.d.ts.map +1 -0
  104. package/dist/{index-CCf_WeTQ.d.ts → index-f-XWIoYo.d.ts} +2 -2
  105. package/dist/{index-CCf_WeTQ.d.ts.map → index-f-XWIoYo.d.ts.map} +1 -1
  106. package/dist/index.d.ts +5 -5
  107. package/dist/index.js +17 -17
  108. package/dist/ipc/browser-types.d.ts +304 -7
  109. package/dist/ipc/browser-types.d.ts.map +1 -1
  110. package/dist/ipc/browser.d.ts +4 -4
  111. package/dist/ipc/browser.js +2 -2
  112. package/dist/ipc/remote.d.ts +6 -6
  113. package/dist/ipc/remote.js +3 -3
  114. package/dist/{ipc-BzWhIybr.js → ipc-DiH_P-wr.js} +4 -4
  115. package/dist/{ipc-BzWhIybr.js.map → ipc-DiH_P-wr.js.map} +1 -1
  116. package/dist/ipc.d.ts +10 -10
  117. package/dist/ipc.js +8 -8
  118. package/dist/{json-Dj-YATkZ.js → json-BjClr43H.js} +2 -20
  119. package/dist/json-BjClr43H.js.map +1 -0
  120. package/dist/{links-CJG_rFvf.js → links-BbC_lOnn.js} +9 -9
  121. package/dist/{links-CJG_rFvf.js.map → links-BbC_lOnn.js.map} +1 -1
  122. package/dist/{loaded-entry-DTURJo_R.js → loaded-entry-C0vkCVNQ.js} +2 -2
  123. package/dist/{loaded-entry-DTURJo_R.js.map → loaded-entry-C0vkCVNQ.js.map} +1 -1
  124. package/dist/mcp.d.ts +1 -1
  125. package/dist/{media-type-BtA0cbfI.d.ts → media-type-ZSmAGHvg.d.ts} +188 -7
  126. package/dist/media-type-ZSmAGHvg.d.ts.map +1 -0
  127. package/dist/{memory-DuVGrzbl.js → memory-C3w8nO8f.js} +132 -31
  128. package/dist/memory-C3w8nO8f.js.map +1 -0
  129. package/dist/model-test-CAtJ76kM.js.map +1 -1
  130. package/dist/{move-session-kylExJ5H.js → move-session-D7ILECs-.js} +4 -4
  131. package/dist/{move-session-kylExJ5H.js.map → move-session-D7ILECs-.js.map} +1 -1
  132. package/dist/{nested-call-record-DlzPeTB7.js → nested-call-record-OayszZBQ.js} +4 -3
  133. package/dist/nested-call-record-OayszZBQ.js.map +1 -0
  134. package/dist/output/stream-json.d.ts +1 -1
  135. package/dist/output/terminal.d.ts +1 -1
  136. package/dist/{path-display-COVV71Yu.js → path-display-DRAEpKOU.js} +3 -3
  137. package/dist/{path-display-COVV71Yu.js.map → path-display-DRAEpKOU.js.map} +1 -1
  138. package/dist/plugins.d.ts +1 -1
  139. package/dist/{prelude-CVKoUzV8.js → prelude-BwiSR1uA.js} +16 -5
  140. package/dist/prelude-BwiSR1uA.js.map +1 -0
  141. package/dist/{presets-CBt6rFfS.js → presets-CMY43nUP.js} +3 -3
  142. package/dist/{presets-CBt6rFfS.js.map → presets-CMY43nUP.js.map} +1 -1
  143. package/dist/presets.d.ts +1 -1
  144. package/dist/presets.js +1 -1
  145. package/dist/{protocol-CEVqBO-q.d.ts → protocol-C2lqKuMd.d.ts} +50 -7
  146. package/dist/protocol-C2lqKuMd.d.ts.map +1 -0
  147. package/dist/protocol-DOGyHgLQ.js.map +1 -1
  148. package/dist/protocol-NSllElLw.js.map +1 -1
  149. package/dist/providers/anthropic.d.ts +1 -1
  150. package/dist/providers/arcee.d.ts +1 -1
  151. package/dist/providers/baseten.d.ts +1 -1
  152. package/dist/providers/cerebras.d.ts +1 -1
  153. package/dist/providers/google.d.ts +1 -1
  154. package/dist/providers/google.js +1 -1
  155. package/dist/providers/local.d.ts +1 -1
  156. package/dist/providers/neuralwatt.d.ts +1 -1
  157. package/dist/providers/openai-compat.d.ts +1 -1
  158. package/dist/providers/openai.d.ts +1 -1
  159. package/dist/providers/openrouter.d.ts +1 -1
  160. package/dist/providers/xai.d.ts +1 -1
  161. package/dist/{providers-Z0TaBp1O.js → providers-CpXV_uLE.js} +5 -5
  162. package/dist/providers-CpXV_uLE.js.map +1 -0
  163. package/dist/providers.d.ts +1 -1
  164. package/dist/providers.js +1 -1
  165. package/dist/{readonly-db-D7Z-k0pQ.js → readonly-db-DrbT8tX6.js} +2 -2
  166. package/dist/{readonly-db-D7Z-k0pQ.js.map → readonly-db-DrbT8tX6.js.map} +1 -1
  167. package/dist/{registry-BKjeBnoy.js → registry-CJHvmvaP.js} +2 -2
  168. package/dist/{registry-BKjeBnoy.js.map → registry-CJHvmvaP.js.map} +1 -1
  169. package/dist/{registry-B6Ww76iW.js → registry-CN6JlZKj.js} +2 -2
  170. package/dist/{registry-B6Ww76iW.js.map → registry-CN6JlZKj.js.map} +1 -1
  171. package/dist/{registry-B9INJwJR.js → registry-CnnKaY9s.js} +324 -39
  172. package/dist/registry-CnnKaY9s.js.map +1 -0
  173. package/dist/{remote-hosts-BMWoHCWO.js → remote-hosts-DoO9CJUQ.js} +4 -4
  174. package/dist/{remote-hosts-BMWoHCWO.js.map → remote-hosts-DoO9CJUQ.js.map} +1 -1
  175. package/dist/{repo-url-D4Dr8NfZ.js → repo-url-DLjjuVk_.js} +169 -2
  176. package/dist/repo-url-DLjjuVk_.js.map +1 -0
  177. package/dist/restate.d.ts +2 -2
  178. package/dist/{sandbox-BwiPGKF7.d.ts → sandbox-B4OW6oNx.d.ts} +2 -2
  179. package/dist/{sandbox-BwiPGKF7.d.ts.map → sandbox-B4OW6oNx.d.ts.map} +1 -1
  180. package/dist/script-progress-CrZ507Qq.js +900 -0
  181. package/dist/script-progress-CrZ507Qq.js.map +1 -0
  182. package/dist/session/sqlite.d.ts +1 -1
  183. package/dist/session.d.ts +1 -1
  184. package/dist/{setting-BQBSyUq0.js → setting-D_FpKFMw.js} +6 -6
  185. package/dist/{setting-BQBSyUq0.js.map → setting-D_FpKFMw.js.map} +1 -1
  186. package/dist/{settings-catalog-4IU2i_jG.js → settings-catalog-DEZlXP51.js} +14 -2
  187. package/dist/settings-catalog-DEZlXP51.js.map +1 -0
  188. package/dist/{settings-keys-iI_Y-7MC.js → settings-keys-CW2UgHgb.js} +3 -3
  189. package/dist/{settings-keys-iI_Y-7MC.js.map → settings-keys-CW2UgHgb.js.map} +1 -1
  190. package/dist/{skills-CFXRItJ6.js → skills-CEbosUlM.js} +2 -2
  191. package/dist/{skills-CFXRItJ6.js.map → skills-CEbosUlM.js.map} +1 -1
  192. package/dist/skills.d.ts +1 -1
  193. package/dist/skills.js +1 -1
  194. package/dist/{source-Bl1Z501r.js → source-3ZnEPOSa.js} +3 -2
  195. package/dist/source-3ZnEPOSa.js.map +1 -0
  196. package/dist/{sqlite-runtime-BZ2L4RaG.d.ts → sqlite-runtime-CS_LBaAN.d.ts} +2 -2
  197. package/dist/sqlite-runtime-CS_LBaAN.d.ts.map +1 -0
  198. package/dist/{src-BY_ND2xn.js → src-BmTXDta8.js} +2 -2
  199. package/dist/{src-BY_ND2xn.js.map → src-BmTXDta8.js.map} +1 -1
  200. package/dist/{store-C6gI7FfZ.js → store-ByCDaKgJ.js} +14 -3
  201. package/dist/store-ByCDaKgJ.js.map +1 -0
  202. package/dist/{system-freeze-m5o1sGIM.js → system-freeze-XgDPIwQS.js} +3 -3
  203. package/dist/{system-freeze-m5o1sGIM.js.map → system-freeze-XgDPIwQS.js.map} +1 -1
  204. package/dist/{todo-edits-CbukbjyV.js → todo-edits-Dyj32ds6.js} +4 -3
  205. package/dist/todo-edits-Dyj32ds6.js.map +1 -0
  206. package/dist/tools/fetch-url.d.ts +1 -1
  207. package/dist/tools/web-search.d.ts +1 -1
  208. package/dist/{tools-CVTGhggj.js → tools-BsrGQ8K4.js} +2 -2
  209. package/dist/{tools-CVTGhggj.js.map → tools-BsrGQ8K4.js.map} +1 -1
  210. package/dist/tools.d.ts +1 -1
  211. package/dist/tools.js +3 -3
  212. package/dist/{transcript-anchors-CiSi_UBn.js → transcript-anchors-DMjvyUjk.js} +3 -3
  213. package/dist/{transcript-anchors-CiSi_UBn.js.map → transcript-anchors-DMjvyUjk.js.map} +1 -1
  214. package/dist/{transcript-reconcile-jbSBjLq2.js → transcript-reconcile-DpQO85wl.js} +3 -3
  215. package/dist/{transcript-reconcile-jbSBjLq2.js.map → transcript-reconcile-DpQO85wl.js.map} +1 -1
  216. package/dist/tui.d.ts +9 -9
  217. package/dist/tui.d.ts.map +1 -1
  218. package/dist/tui.js +289 -38
  219. package/dist/tui.js.map +1 -1
  220. package/dist/{types-bDQagoiL.d.ts → types-2HrgolQz.d.ts} +20 -8
  221. package/dist/types-2HrgolQz.d.ts.map +1 -0
  222. package/dist/types-4q1bFG53.js +122 -0
  223. package/dist/types-4q1bFG53.js.map +1 -0
  224. package/dist/{types-DnRd9_cA.d.ts → types-SXqk6hLD.d.ts} +3 -3
  225. package/dist/{types-DnRd9_cA.d.ts.map → types-SXqk6hLD.d.ts.map} +1 -1
  226. package/dist/types-myxheQkw.js.map +1 -1
  227. package/dist/types.d.ts +3 -3
  228. package/dist/{usage-summary-BfcXjiSM.js → usage-summary-BM7B3JdI.js} +2 -2
  229. package/dist/{usage-summary-BfcXjiSM.js.map → usage-summary-BM7B3JdI.js.map} +1 -1
  230. package/dist/{version-DqqqvHDP.js → version-szdW1Od9.js} +2 -2
  231. package/dist/{version-DqqqvHDP.js.map → version-szdW1Od9.js.map} +1 -1
  232. package/dist/{wait-task-BX4NcOOm.js → wait-task-BiI5UaZQ.js} +13 -3
  233. package/dist/wait-task-BiI5UaZQ.js.map +1 -0
  234. package/dist/{wire-CLm2rMK0.js → wire-C3l9jl9x.js} +2 -2
  235. package/dist/{wire-CLm2rMK0.js.map → wire-C3l9jl9x.js.map} +1 -1
  236. package/dist/{write-file-0E6TUJ9A.js → write-file-Dquu7MzB.js} +5 -3
  237. package/dist/write-file-Dquu7MzB.js.map +1 -0
  238. package/dist/{ws-DfGGYQ4W.js → ws-CEHi0CiB.js} +4 -4
  239. package/dist/{ws-DfGGYQ4W.js.map → ws-CEHi0CiB.js.map} +1 -1
  240. package/dist/{ws-client-CFMbhsNq.js → ws-client-t8XNWxcq.js} +2 -2
  241. package/dist/{ws-client-CFMbhsNq.js.map → ws-client-t8XNWxcq.js.map} +1 -1
  242. package/docs/CHAT.md +55 -0
  243. package/docs/CODEMODE.md +37 -0
  244. package/docs/EXTENSIONS.md +8 -6
  245. package/docs/RELEASE-NOTES-NEXT.md +48 -1
  246. package/docs/RELEASE.md +9 -1
  247. package/package.json +2 -3
  248. package/dist/agent-DJhpTS-B.js.map +0 -1
  249. package/dist/auto-update-restart-BFB7Ek87.js.map +0 -1
  250. package/dist/browser-BcoCCB_n.js.map +0 -1
  251. package/dist/contexts-C72b0mMa.js.map +0 -1
  252. package/dist/decisions-CXmK0nz9.js.map +0 -1
  253. package/dist/extension-mark-BqKdEZwF.js.map +0 -1
  254. package/dist/extensions-client-D8tEAcMw.d.ts.map +0 -1
  255. package/dist/host-BHMs9jsN.js.map +0 -1
  256. package/dist/host-wO_6GW0y.js.map +0 -1
  257. package/dist/index-CGbOWa7y.d.ts.map +0 -1
  258. package/dist/json-Dj-YATkZ.js.map +0 -1
  259. package/dist/media-type-BtA0cbfI.d.ts.map +0 -1
  260. package/dist/memory-DuVGrzbl.js.map +0 -1
  261. package/dist/nested-call-events-BYk8XvGX.js +0 -182
  262. package/dist/nested-call-events-BYk8XvGX.js.map +0 -1
  263. package/dist/nested-call-record-DlzPeTB7.js.map +0 -1
  264. package/dist/prelude-CVKoUzV8.js.map +0 -1
  265. package/dist/protocol-CEVqBO-q.d.ts.map +0 -1
  266. package/dist/providers-Z0TaBp1O.js.map +0 -1
  267. package/dist/registry-B9INJwJR.js.map +0 -1
  268. package/dist/repo-url-D4Dr8NfZ.js.map +0 -1
  269. package/dist/settings-catalog-4IU2i_jG.js.map +0 -1
  270. package/dist/source-Bl1Z501r.js.map +0 -1
  271. package/dist/sqlite-runtime-BZ2L4RaG.d.ts.map +0 -1
  272. package/dist/store-C6gI7FfZ.js.map +0 -1
  273. package/dist/todo-edits-CbukbjyV.js.map +0 -1
  274. package/dist/types-DTMEhKJO.js +0 -14
  275. package/dist/types-DTMEhKJO.js.map +0 -1
  276. package/dist/types-bDQagoiL.d.ts.map +0 -1
  277. package/dist/wait-task-BX4NcOOm.js.map +0 -1
  278. package/dist/write-file-0E6TUJ9A.js.map +0 -1
  279. package/scripts/eval.ts +0 -179
@@ -1 +0,0 @@
1
- {"version":3,"file":"store-C6gI7FfZ.js","names":[],"sources":["../src/chat/injected-turn-notice.ts","../src/chat/replay-runs.ts","../src/chat/store.ts"],"sourcesContent":["import type { InjectedTurnReason } from '../types'\nimport type { StreamEvent } from './types'\n\n/**\n * The transcript row for a user turn the agent loop injected\n * (`SessionTurn.injected`). The model still sees the turn's text; the user\n * sees this one-line notice instead of a prompt bubble they never typed.\n */\nexport function injectedTurnNotice(reason: InjectedTurnReason): { notice: NonNullable<StreamEvent['notice']>, text: string } {\n switch (reason) {\n case 'refusal-retry':\n return { notice: { severity: 'warn', label: 'refusal' }, text: 'Provider refused, continuing' }\n case 'length-resume':\n return { notice: { severity: 'info', label: 'output limit' }, text: 'Hit the output limit, continuing' }\n case 'pause-resume':\n return { notice: { severity: 'info', label: 'pause' }, text: 'Provider paused the turn, continuing' }\n case 'tool-output-budget':\n return { notice: { severity: 'warn', label: 'tool output budget' }, text: 'Tool output exceeded the per-turn budget, asked the model to summarize' }\n }\n}\n","/**\n * Run-level reconstruction for transcript replay (`eventsFromTurns` in\n * `./store`): the run index (with records synthesized for legacy gaps),\n * `child-N` labels, ancestry and subtree totals, the spawn markers, and the\n * per-run receipts.\n */\nimport type { SessionRun } from '../session'\nimport type { SessionTurn } from '../types'\nimport type { ModelApproval, SpawnEndInfo, StreamEvent } from './types'\nimport { formatTokenUsage } from '../stats'\nimport { toolResultToText } from '../types'\nimport { previewLine } from './format'\nimport { readModelApproval } from './model-approval'\nimport { formatRunReceiptLine, hasRunReceipt, runReceiptFromRun } from './run-receipt'\nimport { spawnEndText, spawnPrompt } from './spawn-markers'\n\n/**\n * The run records a replay works from, by id: `runs[]` first-write-wins, plus\n * synthesized records for runs the turns reference but `runs[]` lacks.\n */\nexport function indexReplayRuns(turns: SessionTurn[], runs: readonly SessionRun[]): Map<string, SessionRun> {\n // First-write-wins on duplicate ids. Historical sessions persisted\n // before each mint re-synced the run counter with the session\n // (`syncRunCounter` in `src/agent-runtime.ts`) could have a child agent and\n // its parent both registering runs with the SAME `run_<n>` id — the subagent ran first (lands first in\n // `runs[]`), the parent's collision came later (lands last).\n // Last-write-wins would resolve the id to the collision (depth=0,\n // no parentRunId), the structural ancestry walk would return empty,\n // and the renderer would paint a subagent's transcript at depth 0:\n // indent gets crazy, spawn markers placed wrong, the whole block\n // looks \"off\". Preferring the FIRST entry keeps the depth + parent\n // info from the subagent record, which is what every turn under\n // that runId actually wants. Clean sessions have one entry per id,\n // so first/last makes no difference.\n const runById = new Map<string, SessionRun>()\n for (const run of runs) {\n if (!runById.has(run.id))\n runById.set(run.id, run)\n }\n\n // Defensive synthesis for legacy sessions whose `runs[]` is missing\n // entries the turns reference (e.g. the pre-fix `updateRun`-not-\n // upsert bug in the sqlite/memory stores dropped subagent records\n // silently). Without it, an orphan turn's `ancestryOf()` returns an\n // empty chain → depth = 0 → the subagent's user-text-block leaks\n // as a `user-prompt` event and pollutes the TUI's history.\n //\n // Inference is structural: walk turns chronologically, maintain a\n // stack of currently-open runIds, and decide whether a NEW runId\n // is nested or top-level based on whether the stack-top run has any\n // unresolved tool_calls. A nested runId pushes (depth grows); a\n // top-level runId resets the stack first. Tracked per-runId in\n // `pendingToolCallsPerRun` — incremented on `tool_call` blocks,\n // decremented on `tool_result` blocks.\n //\n // Without the nesting gate, the naive \"push every new runId, never\n // pop\" walk treated back-to-back top-level prompts as a deepening\n // chain of subagents, and synthesized depth grew unbounded —\n // `indentFor(36)` = 72 cells, which is the far-right rendering the\n // user reported for a session with many top-level chats plus one\n // missing run record. Real records (present in `runById`) are NEVER\n // overwritten — synthesis only fills the gap.\n const runStack: string[] = []\n const pendingToolCallsPerRun = new Map<string, Set<string>>()\n for (const turn of turns) {\n const rid = turn.runId\n if (!rid)\n continue\n const idxInStack = runStack.indexOf(rid)\n if (idxInStack >= 0) {\n // Already open — pop any deeper nesting that's now closed.\n runStack.length = idxInStack + 1\n }\n else {\n // New runId — nested only when the parent has a pending\n // SPAWN-shaped tool_call (the call that's waiting on a subagent).\n // Restricting to spawn-like names matters: a run killed mid-tool\n // (dev-loop restart, crash) leaves its ordinary tool_calls\n // unresolved FOREVER, and gating on \"any pending call\" would\n // synthesize every subsequent top-level run with a missing record\n // as that dead run's child — the user's own prompt\n // rendered as a `child-N` worker running `<prompt>` with `0 / 0 out`.\n const top = runStack[runStack.length - 1]\n const parentHasPending = top !== undefined && (pendingToolCallsPerRun.get(top)?.size ?? 0) > 0\n if (!parentHasPending) {\n // Fresh top-level — drop the stack so a long chat history\n // doesn't accumulate phantom depth.\n runStack.length = 0\n }\n runStack.push(rid)\n\n if (!runById.has(rid))\n runById.set(rid, synthesizedRun(turn, rid, runStack))\n }\n\n // Update the pending-tool-calls set for this turn's runId. Tracked\n // here (not in the synthesis branch alone) so we have an accurate\n // running view for every turn — the stack-top check above reads\n // this for the next iteration.\n const pending = pendingToolCallsPerRun.get(rid) ?? new Set<string>()\n for (const block of turn.content) {\n // Only spawn-shaped calls can open a child run — tracking every\n // tool_call would let a run killed mid-`shell`/`read_file` adopt\n // unrelated later runs as phantom children (see gate above).\n if (block.type === 'tool_call' && /spawn/i.test(block.name))\n pending.add(block.id)\n else if (block.type === 'tool_result')\n pending.delete(block.callId)\n }\n pendingToolCallsPerRun.set(rid, pending)\n }\n return runById\n}\n\n/** The record synthesized for a run whose own record is missing, at its place in the open-run stack. */\nfunction synthesizedRun(turn: SessionTurn, rid: string, runStack: readonly string[]): SessionRun {\n // Missing record — synthesize. Depth = stack depth - 1 (zero-based).\n // Prompt: the first user text-block on this turn (when present)\n // so the `child-N` spawn-start marker renders with a meaningful\n // preview rather than an empty string. Empty when the first\n // turn isn't a user turn or has no text block — `pushSpawnStart`\n // then falls through to the bare label.\n const depth = runStack.length - 1\n const parentRunId = depth > 0 ? runStack[depth - 1] : undefined\n let inferredPrompt = ''\n if (turn.role === 'user') {\n for (const block of turn.content) {\n if (block.type === 'text' && !block.systemNote && block.text.trim()) {\n inferredPrompt = block.text\n break\n }\n }\n }\n return {\n id: rid,\n startedAt: turn.createdAt,\n prompt: inferredPrompt,\n status: 'completed',\n depth,\n ...(parentRunId ? { parentRunId } : {}),\n }\n}\n\n/** `runId` → its friendly `child-N` label (the run id itself when it has none). */\nexport function childLabeler(runById: ReadonlyMap<string, SessionRun>): (runId: string) => string {\n // Build a chronological mapping from the persisted `runId` (e.g. `run_2`) to\n // a friendly `child-N` label that mirrors what the spawn tool emits live\n // (see the session-scoped counter in `src/tools/spawn-helpers.ts`). Without this the reloaded\n // transcript labels its subagent block `[run_2]` while the persisted tool\n // result text inside that very block says `[sub-agent child-1]`.\n //\n // Reads from `runById` (NOT the raw `runs` param) so synthesized\n // fallback runs from `indexReplayRuns`' legacy-session synthesis also get\n // a proper `child-N` label.\n const childLabelByRunId = new Map<string, string>()\n const childRuns = [...runById.values()]\n .filter(r => (r.depth ?? 0) > 0)\n .sort((a, b) => a.startedAt - b.startedAt)\n // Prefer the label persisted at `startRun` (`SessionRun.label`) — the\n // positional fallback covers legacy sessions and synthesized runs, but\n // can desync from announced labels under concurrent spawns or counter\n // drift, which would mislabel resume targets.\n childRuns.forEach((r, i) => childLabelByRunId.set(r.id, r.label ?? `child-${i + 1}`))\n return (runId: string) => childLabelByRunId.get(runId) ?? runId\n}\n\n/** `callId` → the tool name its assistant `tool_call` named. */\nexport function toolNamesByCallId(turns: SessionTurn[]): Map<string, string> {\n // Build a `callId → toolName` map from the assistant `tool_call` blocks so\n // we can tag each user-role `tool_result` event with the tool it answers.\n // The renderer uses this for tool-aware filters (e.g. hiding the spawn\n // tool's result when `hideSubagentOutput` is on).\n const toolByCallId = new Map<string, string>()\n for (const turn of turns) {\n if (turn.role !== 'assistant')\n continue\n for (const block of turn.content) {\n if (block.type === 'tool_call')\n toolByCallId.set(block.id, block.name)\n }\n }\n return toolByCallId\n}\n\n/** What a call's user-role `tool_result` replays onto its `tool` event. */\nexport interface ReplayedResult {\n /** The result's text: per-edit outcomes are parsed from it (`parseEditOutcomesFromResult`). */\n text: string\n /** The Model decision verdict stored on the result's metadata. */\n approval?: ModelApproval\n}\n\n/** `callId` → its user-role `tool_result` ({@link ReplayedResult}). */\nexport function resultsByCallId(turns: SessionTurn[]): Map<string, ReplayedResult> {\n // Live capture mutates `_outcomes` on input before tool execution; on\n // disk, only the tool_result body carries the post-decision shape, so the\n // replay parses it.\n const resultByCallId = new Map<string, ReplayedResult>()\n for (const turn of turns) {\n if (turn.role !== 'user')\n continue\n for (const block of turn.content) {\n if (block.type !== 'tool_result')\n continue\n const text = typeof block.output === 'string' ? block.output : toolResultToText(block.output)\n const approval = readModelApproval(block.metadata?.approval)\n resultByCallId.set(block.callId, approval ? { text, approval } : { text })\n }\n }\n return resultByCallId\n}\n\n/**\n * The `child-N` label of the subagent that spawned `run` — the live\n * `child:spawn:*` hook's `parentChildId`. Undefined for a direct child of a\n * top-level run (and for orphans whose parent record is gone).\n */\nexport function spawnerLabeler(\n runById: ReadonlyMap<string, SessionRun>,\n labelFor: (runId: string) => string,\n): (run: SessionRun) => string | undefined {\n return (run: SessionRun) => {\n const parent = run.parentRunId ? runById.get(run.parentRunId) : undefined\n return parent && (parent.depth ?? 0) > 0 ? labelFor(parent.id) : undefined\n }\n}\n\n/** A turn's run ancestry over `runById`. */\nexport function runAncestry(runById: ReadonlyMap<string, SessionRun>): (turnRunId: string | undefined) => SessionRun[] {\n // Ancestry chain for a turn's run — `[root child, …, the turn's own run]`,\n // excluding any depth-0 (top-level) ancestor since top-level runs don't\n // render spawn-start/spawn-end markers. Feeds the open-once /\n // close-after-last-subtree-turn logic in `eventsFromTurns`\n // (`./store`), so neither depth ≥ 2\n // (grandchild) sequences nor interleaved concurrent siblings emit\n // duplicate `spawn-start` / premature `spawn-end` markers.\n return (turnRunId: string | undefined): SessionRun[] => {\n if (!turnRunId)\n return []\n const chain: SessionRun[] = []\n let cursor: SessionRun | undefined = runById.get(turnRunId)\n const seen = new Set<string>()\n while (cursor) {\n // Defensive cycle guard — a corrupt run row pointing at its own\n // ancestor would otherwise loop forever.\n if (seen.has(cursor.id))\n break\n seen.add(cursor.id)\n if ((cursor.depth ?? 0) > 0)\n chain.unshift(cursor)\n cursor = cursor.parentRunId ? runById.get(cursor.parentRunId) : undefined\n }\n return chain\n }\n}\n\nexport interface SubtreeTotals { cost: number, tokensIn: number, tokensOut: number, cacheRead: number, cacheCreation: number }\n\n/** A run's totals summed over its whole subtree (itself and every descendant). */\nexport function runSubtreeTotals(runById: ReadonlyMap<string, SessionRun>): (root: SessionRun) => SubtreeTotals {\n // Children index for subtree aggregation. Run records are\n // deliberately per-run additive (children persist as their own runs —\n // folding cumulative totals into the parent would double-count, see the\n // session ledger in `finishRun`, `src/agent-run-finalize.ts`), while the\n // live spawn-end marker reports subtree totals (children folded into\n // `finalStats` there). Walk descendants here so live and reloaded markers\n // agree for nested spawns — on BOTH numbers, not just cost.\n const childRunsOf = new Map<string, SessionRun[]>()\n for (const run of runById.values()) {\n if (!run.parentRunId)\n continue\n const siblings = childRunsOf.get(run.parentRunId) ?? []\n siblings.push(run)\n childRunsOf.set(run.parentRunId, siblings)\n }\n return (root: SessionRun): SubtreeTotals => {\n const totals = { cost: 0, tokensIn: 0, tokensOut: 0, cacheRead: 0, cacheCreation: 0 }\n const queue = [root]\n const seen = new Set<string>()\n while (queue.length > 0) {\n const run = queue.pop() as SessionRun\n if (seen.has(run.id))\n continue\n seen.add(run.id)\n totals.cost += run.cost ?? run.turnUsage?.reduce((sum, u) => sum + (u.cost ?? 0), 0) ?? 0\n totals.tokensIn += run.tokensIn ?? run.totalUsage?.input ?? 0\n totals.tokensOut += run.tokensOut ?? run.totalUsage?.output ?? 0\n totals.cacheRead += run.totalUsage?.cacheRead ?? 0\n totals.cacheCreation += run.totalUsage?.cacheCreation ?? 0\n queue.push(...(childRunsOf.get(run.id) ?? []))\n }\n return totals\n }\n}\n\n/** The `spawn-end` marker closing a child run, carrying its subtree totals. */\nexport function spawnEndEvent(run: SessionRun, totals: SubtreeTotals, labelFor: (runId: string) => string, parentChildId?: string): StreamEvent {\n // Same caching gotcha as the live path: `tokensIn` mirrors\n // `AgentStats.totalIn` (new uncached only). `formatTokenUsage` folds\n // cache reads/creations into the headline `in` number. Totals span\n // the run's whole subtree — the live marker formats the child's\n // `finalStats`, which already folds grandchildren in.\n const usage = formatTokenUsage({\n totalIn: totals.tokensIn,\n totalOut: totals.tokensOut,\n totalCacheRead: totals.cacheRead,\n totalCacheCreation: totals.cacheCreation,\n })\n // Same facts as the live `spawn:complete` hook (`buildSpawnEndEvent`,\n // `src/chat/spawn-markers.ts`) so a reloaded transcript renders\n // byte-identical markers. `endedAt` is absent on runs synthesized from bare\n // turns (legacy sessions), so the duration drops. Zero/unknown cost is\n // omitted (no \"$0.00\" lies).\n const end: SpawnEndInfo = {\n status: run.status === 'aborted' || run.status === 'error' ? run.status : 'done',\n ...(run.endedAt !== undefined ? { durationMs: run.endedAt - run.startedAt } : {}),\n ...(totals.cost > 0 ? { costUsd: totals.cost } : {}),\n tokensIn: totals.tokensIn + totals.cacheRead + totals.cacheCreation,\n tokensOut: totals.tokensOut,\n }\n const model = run.turnUsage?.find(u => u.modelId)?.modelId\n const turns = run.turns ?? run.turnUsage?.length\n return {\n kind: 'spawn-end',\n text: spawnEndText(end, usage),\n childId: labelFor(run.id),\n depth: run.depth ?? 1,\n spawn: {\n startedAt: run.startedAt,\n task: previewLine(run.prompt, 80),\n ...(turns !== undefined ? { turns } : {}),\n ...(parentChildId ? { parentChildId } : {}),\n end,\n },\n ...(model ? { model } : {}),\n }\n}\n\n/** The `spawn-start` marker opening a child run. */\nexport function spawnStartEvent(run: SessionRun, labelFor: (runId: string) => string, parentChildId?: string): StreamEvent {\n // Single-line preview — newlines / tabs in the prompt collapse to\n // single spaces so the spawn-start marker stays on one visual row.\n // See the matching comment on `buildSpawnStartEvent` (`spawn-markers.ts`) for\n // the failure mode (multi-line prompt prints the marker across\n // multiple visual rows, the next event lands far right).\n const taskPreview = previewLine(run.prompt, 80)\n // Which model the child ran on — mirrors the live `spawn:before` hook's\n // `model`. Reconstructed from the first turn that recorded a model id\n // (providers echo it per turn; the run-level `totalUsage` aggregate\n // deliberately drops `modelId`, so per-turn usage is the only source).\n const model = run.turnUsage?.find(u => u.modelId)?.modelId\n // A resumed child (spawn `resume`) is tagged with the label of the run\n // it continues — mirrors the live `spawn:before` hook's `resumesChildId`.\n const resumes = run.resumedFromRunId ? labelFor(run.resumedFromRunId) : undefined\n return {\n kind: 'spawn-start',\n text: taskPreview,\n childId: labelFor(run.id),\n depth: run.depth ?? 1,\n spawn: {\n startedAt: run.startedAt,\n task: taskPreview,\n prompt: spawnPrompt(run.prompt),\n ...(resumes ? { resumes } : {}),\n ...(parentChildId ? { parentChildId } : {}),\n ...(run.parentCallId ? { callId: run.parentCallId } : {}),\n },\n ...(model ? { model } : {}),\n }\n}\n\n/**\n * Place each finished top-level run's receipt (and its error) after the last\n * event of its last turn. Returns the merged events (`events` itself when there\n * is nothing to place) and remaps `turnStarts` (ascending indexes into\n * `events`) in place to the merged array, in one walk.\n */\nexport function withRunReceipts(events: StreamEvent[], turns: SessionTurn[], runs: readonly SessionRun[], turnStarts: number[]): StreamEvent[] {\n /*\n * Per-run receipts. For every finished TOP-LEVEL run, a `run-summary` lands\n * right after the last event of that run — the same record and the same\n * formatter the live path uses at `run:end`, so a reloaded session shows\n * exactly the line the user saw when the run ended. Child runs (subagents)\n * get no receipt of their own: their spawn-end marker already carries their\n * totals, and a receipt per child would bury the parent's.\n */\n const lastTurnIdByRun = new Map<string, string>()\n for (const turn of turns) {\n if (turn.runId)\n lastTurnIdByRun.set(turn.runId, turn.id)\n }\n const receiptAfterTurn = new Map<string, StreamEvent[]>()\n let previousTopLevel: SessionRun | undefined\n for (const run of runs) {\n if (run.parentRunId !== undefined)\n continue\n // `/` command runs record no agent: compare with the last run that did.\n const previous = previousTopLevel\n if (run.agent)\n previousTopLevel = run\n if (run.endedAt === undefined)\n continue\n const lastTurnId = lastTurnIdByRun.get(run.id)\n if (!lastTurnId)\n continue\n const ending: StreamEvent[] = []\n if (run.status === 'error' && run.error)\n ending.push({ kind: 'error', text: run.error, ...(run.errorDetail ? { detail: run.errorDetail } : {}), turnId: lastTurnId })\n const receipt = runReceiptFromRun(run, Date.now(), previous)\n if (hasRunReceipt(receipt))\n ending.push({ kind: 'run-summary', text: formatRunReceiptLine(receipt), runSummary: receipt, turnId: lastTurnId })\n if (ending.length > 0)\n receiptAfterTurn.set(lastTurnId, ending)\n }\n if (receiptAfterTurn.size === 0)\n return events\n // Insert after the LAST event carrying that turn id (a turn can emit\n // several events — text, tool calls, spawn markers).\n const receiptAfterIndex = new Map<number, StreamEvent[]>()\n const lastIndexByTurn = new Map<string, number>()\n events.forEach((e, idx) => {\n if (e.turnId && receiptAfterTurn.has(e.turnId))\n lastIndexByTurn.set(e.turnId, idx)\n })\n if (lastIndexByTurn.size === 0)\n return events\n for (const [turnId, idx] of lastIndexByTurn)\n receiptAfterIndex.set(idx, receiptAfterTurn.get(turnId)!)\n // Splicing each receipt in place costs O(events) per run (quadratic on long\n // sessions); one walk into a fresh array keeps the same order.\n const out: StreamEvent[] = []\n let k = 0\n for (let i = 0; i < events.length; i++) {\n while (k < turnStarts.length && turnStarts[k]! <= i)\n turnStarts[k++] = out.length\n out.push(events[i]!)\n const ending = receiptAfterIndex.get(i)\n if (ending)\n out.push(...ending)\n }\n while (k < turnStarts.length)\n turnStarts[k++] = out.length\n return out\n}\n","import type { SessionData, SessionMetaRow, SessionRun, SessionStore } from '../session'\nimport type { JsonValue, SessionContentBlock, SessionTurn, ThinkingLevel, ToolResultContent } from '../types'\nimport type { ProviderKey } from './auth'\nimport type { ModelChainEntry } from './model-chain'\nimport type { OnboardingState } from './onboarding/types'\nimport type { ReplayedResult } from './replay-runs'\nimport type { EditOutcome, SessionEnvironmentSummary, SessionHeader, SessionMeta, Settings, StreamEvent } from './types'\nimport { Buffer } from 'node:buffer'\nimport { existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { writeFileAtomic } from '../atomic-write'\nimport { errorMessage } from '../errors'\nimport { readSessionFacets } from '../session/facets'\nimport { mergeReplyText } from '../session/reply-text'\nimport { isSystemNoteBlock } from '../system-notes'\nimport { unwrapCallTool } from '../tools/call-tool'\nimport { toolResultToText } from '../types'\nimport { commandNoteText, commandStepLabel, parseCommandHeader } from './command-notes'\nimport { parseEditOutcomesFromResult } from './edit-approval'\nimport { extractEditPayload } from './edit-diff'\nimport { ENVIRONMENT_METADATA_KEY, LOCAL_ENVIRONMENT, readSessionEnvironment } from './environment'\nimport { injectedTurnNotice } from './injected-turn-notice'\nimport { nestedRecordEvents } from './nested-call-events'\nimport { isMainSession, isSideSession, parseSessionEventXml } from './orchestration'\nimport { inferPromptRefs } from './prompt-segments'\nimport { childLabeler, indexReplayRuns, resultsByCallId, runAncestry, runSubtreeTotals, spawnEndEvent, spawnerLabeler, spawnStartEvent, toolNamesByCallId, withRunReceipts } from './replay-runs'\nimport { oneLineTitle, titleFromText } from './session-title-text'\nimport { readSessionSpaceId } from './spaces'\n\n// NOTE: `createTuiStore` lives in `src/session/sqlite.ts` so this module —\n// the public `zidane/chat` entry — does NOT statically import `bun:sqlite`.\n// A GUI consumer that imports `zidane/chat` does not transitively\n// pull in the Bun-only sqlite binding. Hosts construct their own store\n// (e.g. via `createTuiStore` from `zidane/session/sqlite` for terminal hosts)\n// and pass it through `runTui({ store })` / `resolveConfig({ store })`.\n\nfunction ensureStateDir(path: string): void {\n const dir = dirname(path)\n if (existsSync(dir))\n return\n try {\n mkdirSync(dir, { recursive: true })\n }\n catch (err) {\n throw new Error(\n `Could not create TUI state directory at \"${dir}\". `\n + `Override the location via \\`runTui({ storageDir, prefix })\\` or the `\n + `\\`ZIDANE_STORAGE_DIR\\` env var. Original error: ${errorMessage(err)}`,\n )\n }\n}\n\n// ---------------------------------------------------------------------------\n// Persisted UI state — what to resume on next launch.\n//\n// `StateStoreApi` is a thin facade that binds load/save to a specific JSON\n// path, so the rest of the UI can persist state without knowing the layout.\n// ---------------------------------------------------------------------------\n\n/** Settings the terminal UI remembers between launches. */\nexport interface TuiState {\n /** Provider key used last. */\n lastProvider?: ProviderKey\n /** Id of the session open last. Resume reopens it. */\n lastSessionId?: string\n /**\n * The host key of the saved server `lastSessionId` lives on (for a server,\n * its host id: `src/chat/hosts/session-key`), absent for a session on this\n * computer. Resume reopens it there, and only with remote hosts on. A\n * `--host` session writes neither field (see `lastSessionId`).\n * Read from the older `lastSessionHostId` too ({@link loadState}).\n */\n lastSessionHostKey?: string\n /** The space the TUI's sessions list last showed (Spaces on; see `./spaces`). Per surface: the GUI keeps its own. */\n lastSpaceId?: string\n /** Per-provider last-used model id. */\n lastModelByProvider?: Partial<Record<ProviderKey, string>>\n /**\n * Per-provider last-used account (a credential's stable id), next to\n * {@link lastModelByProvider}; absent for a provider = its active account.\n */\n lastAccountByProvider?: Partial<Record<ProviderKey, string>>\n /**\n * Last-applied model fallback chain (entry 0 = primary, mirroring\n * `lastProvider` + `lastModelByProvider`; entries 1+ = fallbacks).\n * Additive — absent for single-model users and older state files.\n * Restored on launch only when entry 0 still matches the resolved\n * primary; entries are re-validated against the live registry.\n */\n lastModelChain?: ModelChainEntry[]\n /**\n * Per-model last-picked reasoning effort. Keyed by model id (not provider)\n * so switching the same model across providers preserves the user's\n * intent. Models without reasoning support are absent from the map.\n */\n lastEffortByModel?: Record<string, ThinkingLevel>\n /**\n * Per-model last-picked custom options (e.g. `{ fast: true }`). Keyed by\n * model id like {@link lastEffortByModel}, so a toggle follows the model\n * across providers. Models with no options are absent from the map.\n */\n lastModelOptionsByModel?: Record<string, Record<string, boolean>>\n /**\n * Agent profile id saved by earlier builds.\n *\n * @deprecated No longer read: the agent profile is per-session and fresh\n * sessions always start in the default. Kept so older state files parse.\n */\n lastAgent?: string\n /** User-toggled transcript filters. Persisted so they outlive a launch. */\n settings?: Partial<Settings>\n /**\n * The setup wizard's records: a run in progress, the shared steps, and each\n * app's own steps (`docs/ONBOARDING.md`). Both apps read and write it.\n */\n onboarding?: OnboardingState\n /** The sidebar views a host's clients saved (`sidebar.setView`), by space id; each client checks what it reads. */\n sidebarViews?: Record<string, unknown>\n /** The space a host's clients showed last (`sidebar.setSpace`). The TUI keeps its own (`lastSpaceId`). */\n sidebarSpaceId?: string\n}\n\n/** Reads and writes the persisted {@link TuiState}. */\nexport interface StateStoreApi {\n /** Reads the saved state. */\n load: () => TuiState\n /** Writes the state. */\n save: (state: TuiState) => void\n /** The file, when the state lives in one: hosts watch it for changes other processes make. */\n path?: string\n}\n\n/**\n * Creates a {@link StateStoreApi} backed by the JSON file at `path`.\n *\n * @param path - Path of the state file.\n */\nexport function createStateStore(path: string): StateStoreApi {\n return {\n load: () => loadState(path),\n save: state => saveState(path, state),\n path,\n }\n}\n\n/**\n * Reads the TUI state file. Returns `{}` when it is missing or unreadable.\n *\n * @param path - Path of the state file.\n */\nexport function loadState(path: string): TuiState {\n if (!existsSync(path))\n return {}\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf-8'))\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))\n return withLegacyFields(parsed as TuiState & { lastSessionHostId?: unknown })\n }\n catch {\n // Corrupt state file → treat as absent so the user can reach the auth screen.\n }\n return {}\n}\n\n/** `lastSessionHostId` (earlier builds) is read as `lastSessionHostKey`, and leaves the state on its next save. */\nfunction withLegacyFields(state: TuiState & { lastSessionHostId?: unknown }): TuiState {\n const { lastSessionHostId: legacy, ...rest } = state\n if (rest.lastSessionHostKey === undefined && typeof legacy === 'string')\n return { ...rest, lastSessionHostKey: legacy }\n return rest\n}\n\n/**\n * Writes the TUI state file atomically, creating its directory when needed.\n *\n * @param path - Path of the state file.\n * @param state - The state to persist.\n */\nexport function saveState(path: string, state: TuiState): void {\n ensureStateDir(path)\n writeFileAtomic(path, JSON.stringify(state, null, 2))\n}\n\n// Re-export the model-info shape used by views below so callers don't have to\n// pull from `./config` for transcript helpers alone.\nexport type { ModelInfo } from './config'\n\n// ---------------------------------------------------------------------------\n// Session view helpers — derive UI-friendly shapes from persisted turns.\n// ---------------------------------------------------------------------------\n\n/**\n * Load every session and project it to the compact `SessionMeta` shape used by\n * the picker. Sorted by recency via the underlying store's `list()` contract\n * (sqlite store returns by `updated_at DESC`). `/side` sessions are left out,\n * like every session list (`isSideSession`).\n *\n * Robust to per-row failures: `Promise.allSettled` so a single corrupt or\n * unreadable row (malformed JSON, partial write, transient I/O error)\n * doesn't take down the entire picker. Failed rows are silently skipped;\n * a stderr line is emitted under `ZIDANE_DEBUG` for diagnosis.\n *\n * @param store - Session store to read from.\n * @param filter - Optional filter. `projectRoot` restricts the list to one project.\n * @param filter.projectRoot - Project to list. Omit to ignore the axis, `null` for untagged sessions.\n */\nexport async function listSessionMeta(\n store: SessionStore,\n filter?: {\n /**\n * Restrict to sessions belonging to this project. Omit to ignore\n * the axis; pass `null` to ask for untagged (legacy) sessions\n * specifically. The TUI defaults to passing the current git root /\n * cwd here so each project sees only its own conversations.\n */\n projectRoot?: string | null\n },\n): Promise<SessionMeta[]> {\n // Fast path: stores with an indexed summary query (sqlite) answer in a\n // single round-trip without materializing any session. Falls back to\n // the generic fan-out below on error so a store with a broken/legacy\n // index degrades to slow-but-correct instead of an empty picker.\n if (store.listMeta) {\n try {\n const rows = await store.listMeta(filter)\n return rows.filter(row => !isSideSession(row.metadata)).map(metaFromRow)\n }\n catch (err) {\n if (process.env.ZIDANE_DEBUG) {\n const cause = err instanceof Error ? err.message : String(err)\n process.stderr.write(`[zidane/chat] store.listMeta failed, falling back to full loads: ${cause}\\n`)\n }\n }\n }\n const ids = await store.list(filter)\n const settled = await Promise.allSettled(ids.map(async (id) => {\n const data = await store.load(id)\n return data && !isSideSession(data.metadata) ? metaFromData(id, data) : null\n }))\n const metas: SessionMeta[] = []\n for (let i = 0; i < settled.length; i++) {\n const result = settled[i]\n if (result.status === 'fulfilled' && result.value) {\n metas.push(result.value)\n }\n else if (result.status === 'rejected' && process.env.ZIDANE_DEBUG) {\n const cause = result.reason instanceof Error ? result.reason.message : String(result.reason)\n process.stderr.write(`[zidane/chat] failed to load session \"${ids[i]}\": ${cause}\\n`)\n }\n }\n return metas\n}\n\n/** Project a store header row to the picker's shape. */\nfunction metaFromRow(row: SessionMetaRow): SessionMeta {\n return {\n id: row.id,\n title: deriveSessionTitle(row.firstUserTurn ? [row.firstUserTurn] : [], row.metadata),\n turnCount: row.turnCount,\n userMessageCount: row.userMessageCount,\n runCount: row.runCount,\n ...(isMainSession(row.metadata) ? { isMain: true } : {}),\n ...metaSpace(row.metadata),\n ...(row.metadata?.favorite === true ? { favorite: true } : {}),\n ...(row.projectRoot ? { projectRoot: row.projectRoot } : {}),\n ...metaCwd(row.metadata),\n ...metaEnvironment(row.metadata),\n ...(typeof row.artifactCount === 'number' ? { artifactCount: row.artifactCount } : {}),\n ...metaFacets(row.metadata),\n updatedAt: row.updatedAt,\n }\n}\n\n/** Same projection from a fully materialized session (no header index). */\nfunction metaFromData(id: string, data: SessionData): SessionMeta {\n return {\n id,\n title: deriveSessionTitle(data.turns, data.metadata),\n // The out-of-band prompt snapshot (role `system`) is not a turn of the conversation.\n turnCount: data.turns.reduce((n, t) => t.role === 'system' ? n : n + 1, 0),\n userMessageCount: data.turns.reduce((n, t) => t.role === 'user' ? n + 1 : n, 0),\n runCount: data.runs.length,\n ...(isMainSession(data.metadata) ? { isMain: true } : {}),\n ...metaSpace(data.metadata),\n ...(data.metadata?.favorite === true ? { favorite: true } : {}),\n ...(data.projectRoot ? { projectRoot: data.projectRoot } : {}),\n ...metaCwd(data.metadata),\n ...metaEnvironment(data.metadata),\n ...metaFacets(data.metadata),\n updatedAt: data.updatedAt,\n }\n}\n\n/** The row's facet values, when the session has any (`src/session/facets.ts`). */\nfunction metaFacets(metadata: Record<string, unknown> | undefined): { facets?: SessionMeta['facets'] } {\n const facets = readSessionFacets(metadata)\n return Object.keys(facets).length > 0 ? { facets } : {}\n}\n\n/** The row's space id, when one other than Default is stamped (see `./spaces`). */\nfunction metaSpace(metadata: Record<string, unknown> | undefined): { spaceId?: string } {\n const spaceId = readSessionSpaceId(metadata)\n return spaceId ? { spaceId } : {}\n}\n\n/**\n * The environment summary for list rows — omitted for local sessions (the common case).\n *\n * @param metadata - Session metadata that may hold the environment record.\n */\nexport function sessionEnvironmentSummary(metadata: Record<string, unknown> | undefined): SessionEnvironmentSummary | undefined {\n if (!metadata?.[ENVIRONMENT_METADATA_KEY])\n return undefined\n const environment = readSessionEnvironment(metadata)\n if (environment.kind === LOCAL_ENVIRONMENT.kind && environment.state === 'ready')\n return undefined\n return {\n kind: environment.kind,\n state: environment.state,\n ...(environment.branch ? { branch: environment.branch } : {}),\n ...(environment.error ? { error: environment.error } : {}),\n ...(environment.suspended ? { suspended: true } : {}),\n ...(environment.execCwd ? { workspaceRoot: environment.execCwd } : {}),\n }\n}\n\nfunction metaEnvironment(metadata: Record<string, unknown> | undefined): { environment?: SessionEnvironmentSummary } {\n const environment = sessionEnvironmentSummary(metadata)\n return environment ? { environment } : {}\n}\n\nfunction metaCwd(metadata: Record<string, unknown> | undefined): { cwd?: string } {\n const cwd = metadata?.cwd\n return typeof cwd === 'string' && cwd.length > 0 ? { cwd } : {}\n}\n\n/**\n * One session's `SessionMeta` BY ID — the by-id complement to\n * `listSessionMeta`.\n *\n * For rows a filtered list cannot return: the orchestration main is\n * directory-less, so no project-scoped query yields it, and re-listing the\n * whole store on every sessions refresh just to find that one row is O(store).\n * Uses the store's indexed header read when it has one; degrades to a full\n * load otherwise. `null` = no such session.\n */\nexport async function getSessionMeta(store: SessionStore, id: string): Promise<SessionMeta | null> {\n if (store.getMeta) {\n try {\n const row = await store.getMeta(id)\n return row ? metaFromRow(row) : null\n }\n catch (err) {\n if (process.env.ZIDANE_DEBUG) {\n const cause = err instanceof Error ? err.message : String(err)\n process.stderr.write(`[zidane/chat] store.getMeta failed, falling back to a full load: ${cause}\\n`)\n }\n }\n }\n const data = await store.load(id)\n return data ? metaFromData(id, data) : null\n}\n\n/** The header fields both a store's `getMeta` row and a full load carry. */\nexport type SessionHeaderRead = Pick<SessionData, 'metadata' | 'projectRoot' | 'agentId' | 'updatedAt' | 'runOwner'> & { status?: SessionData['status'] }\n\n/**\n * One session's stored header (metadata, project root, agent, status)\n * without parsing its turns when the store keeps a header index\n * (`getMeta`); a full load otherwise, or when the indexed read fails.\n * Still a store read, so it sees other processes' writes. `null` = no such\n * session.\n *\n * @param store - Session store to read from.\n * @param id - Session id.\n */\nexport async function readSessionHeader(store: SessionStore, id: string): Promise<SessionHeaderRead | null> {\n if (store.getMeta) {\n try {\n return await store.getMeta(id)\n }\n catch (err) {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/chat] store.getMeta failed, falling back to a full load: ${errorMessage(err)}\\n`)\n }\n }\n return await store.load(id)\n}\n\n/**\n * {@link SessionHeader} of a fully materialized session.\n *\n * @param data - The loaded session.\n */\nexport function headerFromData(data: SessionData): SessionHeader {\n return {\n ...metaFromData(data.id, data),\n ...(data.agentId ? { agentId: data.agentId } : {}),\n status: data.status,\n metadata: data.metadata,\n createdAt: data.createdAt,\n }\n}\n\n/**\n * One session's header, without reading its turns when the store keeps a\n * header index (`getMeta`). A full load when it doesn't, or when the title\n * still has to be derived from the first message.\n *\n * @param store - Session store to read from.\n * @param id - Session id.\n */\nexport async function getSessionHeader(store: SessionStore, id: string): Promise<SessionHeader | null> {\n const row = store.getMeta ? await store.getMeta(id).catch(() => null) : null\n const titled = typeof row?.metadata.title === 'string' && row.metadata.title.trim() !== ''\n if (row && row.status !== undefined && (titled || row.firstUserTurn !== undefined || row.userMessageCount === 0)) {\n return {\n ...metaFromRow(row),\n ...(row.agentId ? { agentId: row.agentId } : {}),\n status: row.status,\n metadata: row.metadata,\n ...(row.createdAt !== undefined ? { createdAt: row.createdAt } : {}),\n }\n }\n const data = await store.load(id)\n return data ? headerFromData({ ...data, id }) : null\n}\n\n/**\n * Derive a short title from the first user message — returns null when empty.\n *\n * @param turns - Persisted turns in order.\n */\nexport function titleFromTurns(turns: SessionTurn[]): string | null {\n const first = turns.find(t => t.role === 'user')\n if (!first)\n return null\n for (const block of first.content) {\n const title = block.type === 'text' && !block.systemNote ? titleFromText(block.text) : null\n if (title)\n return title\n }\n return null\n}\n\n/**\n * Fallback title for a session with no stored `metadata.title` and no\n * turns to derive one from yet — i.e. a freshly created session. Shown\n * in the sessions list, chat header, and details modal until the first\n * message (or an explicitly generated title) gives it a real name.\n */\nexport const DEFAULT_SESSION_TITLE = 'New session'\n\n/**\n * Display title for a session — preferred sources, in order:\n *\n * 1. `metadata.title` if it's a non-empty string (typically set by\n * the session-details modal's \"generate title\" action), on one line\n * ({@link oneLineTitle}): whatever wrote it, a title never wraps.\n * 2. {@link titleFromTurns} — the first user message, one-line + clipped.\n * 3. {@link DEFAULT_SESSION_TITLE} (`'New session'`).\n *\n * Total / pure / defensive on non-string metadata values.\n *\n * @param turns - The session's turns, used when no title is stored.\n * @param metadata - Session metadata that may hold a stored `title`.\n */\nexport function deriveSessionTitle(\n turns: SessionTurn[],\n metadata?: Record<string, unknown>,\n): string {\n const stored = typeof metadata?.title === 'string' ? oneLineTitle(metadata.title) : ''\n if (stored.length > 0)\n return stored\n return titleFromTurns(turns) ?? DEFAULT_SESSION_TITLE\n}\n\n/**\n * Map a `compact-summary` content block to its `compact-summary` StreamEvent —\n * the single source of truth for the compaction boundary card. Used by\n * {@link eventsFromTurns} (reload / TUI live repaint) AND by chat hosts that\n * surface the boundary live without a full reload (the GUI broadcasts this\n * from the loop's `compact:end` hook), so the live card and the reloaded card\n * are byte-identical regardless of who created the marker (manual compaction or\n * loop-native auto-compaction — both share this block shape).\n *\n * @param block - The `compact-summary` content block.\n * @param turnId - Id of the turn holding the block, attached to the event when set.\n */\nexport function compactSummaryEvent(\n block: Extract<SessionContentBlock, { type: 'compact-summary' }>,\n turnId?: string,\n): StreamEvent {\n return {\n kind: 'compact-summary',\n text: block.summary,\n compact: {\n replacedCount: block.replacesTurnIds.length,\n model: block.model,\n ...(block.usage.provider ? { providerKey: block.usage.provider } : {}),\n compactedAt: block.compactedAt,\n inputTokens: block.usage.input ?? 0,\n outputTokens: block.usage.output ?? 0,\n cacheReadTokens: block.usage.cacheRead ?? 0,\n cacheCreationTokens: block.usage.cacheCreation ?? 0,\n ...(typeof block.usage.cost === 'number' && block.usage.cost > 0 ? { costUsd: block.usage.cost } : {}),\n },\n ...(turnId ? { turnId } : {}),\n }\n}\n\n/**\n * Decoded byte size of a base64 payload, computed arithmetically.\n * `Buffer.from(data, 'base64').length` decodes the whole attachment —\n * a full allocation per media block on EVERY `eventsFromTurns` replay\n * (session load/switch/export/search) just to label a chip with a size.\n */\nfunction base64DecodedSize(data: string): number {\n const padding = data.endsWith('==') ? 2 : data.endsWith('=') ? 1 : 0\n return Math.floor(data.length * 3 / 4) - padding\n}\n\n/** Severity values a persisted notice may carry. Anything else is ignored. */\nconst NOTICE_SEVERITIES = new Set(['info', 'warn', 'error'])\n\n/** A persisted notice, plus the origin the live event carried. */\ninterface PersistedNotice {\n notice: NonNullable<StreamEvent['notice']>\n /** Subagent that produced it, when the live event named one. */\n childId?: string\n /** Indent depth the live event rendered at. */\n depth?: number\n}\n\n/**\n * Read a persisted `metadata.command.notice` back into the event shape, or\n * `null` when the block is an ordinary command detail. Defensive because the\n * value round-tripped through JSON written by a possibly older build.\n */\nfunction readNoticeMeta(value: unknown): PersistedNotice | null {\n if (!value || typeof value !== 'object' || Array.isArray(value))\n return null\n const { severity, label, childId, depth } = value as {\n severity?: unknown\n label?: unknown\n childId?: unknown\n depth?: unknown\n }\n if (typeof severity !== 'string' || !NOTICE_SEVERITIES.has(severity))\n return null\n if (typeof label !== 'string' || label === '')\n return null\n return {\n notice: { severity: severity as NonNullable<StreamEvent['notice']>['severity'], label },\n ...(typeof childId === 'string' && childId !== '' ? { childId } : {}),\n ...(typeof depth === 'number' && Number.isFinite(depth) && depth >= 0 ? { depth: Math.floor(depth) } : {}),\n }\n}\n\n/** The notice a command block carries, or `null` for an ordinary detail block. */\nfunction noticeFromBlock(block: SessionTurn['content'][number]): PersistedNotice | null {\n if (block.type !== 'tool_result')\n return null\n const meta = block.metadata?.command\n if (!meta || typeof meta !== 'object' || Array.isArray(meta))\n return null\n return readNoticeMeta((meta as Record<string, unknown>).notice)\n}\n\n/**\n * Persisted form of a harness notice: a display-only `role: 'command'` turn,\n * which is the existing carrier for content that must survive a reload without\n * ever reaching the model.\n *\n * Pairs with the `readNoticeMeta` branch in {@link eventsFromTurns}. Callers\n * pre-mint `turnId` and emit the live event with the same id so the live row\n * and the reloaded row are the same row.\n *\n * `origin` carries the live event's `childId` / `depth`. A subagent notice is\n * persisted by the PARENT's depth-0 run, so without it the run-derived tag in\n * `eventsFromTurns` would reload the row un-indented and unattributed.\n */\nexport function noticeTurnContent(\n notice: NonNullable<StreamEvent['notice']>,\n text: string,\n origin: { childId?: string, depth?: number } = {},\n): SessionTurn['content'] {\n return [{\n type: 'tool_result' as const,\n callId: `notice_${crypto.randomUUID()}`,\n output: text,\n metadata: {\n command: {\n notice: {\n severity: notice.severity,\n label: notice.label,\n ...(origin.childId ? { childId: origin.childId } : {}),\n ...(origin.depth !== undefined ? { depth: origin.depth } : {}),\n },\n },\n },\n }]\n}\n\n/** The tag every event of one turn carries: its `turnId`, plus its subagent lane when nested. */\ninterface ReplayTag { turnId: string, childId?: string, depth?: number }\n\n/** What the per-turn replay reads and advances, turn after turn. */\ninterface ReplayState {\n events: StreamEvent[]\n runById: ReadonlyMap<string, SessionRun>\n toolByCallId: ReadonlyMap<string, string>\n resultByCallId: ReadonlyMap<string, ReplayedResult>\n /** Depth of the last turn that emitted events, `-1` before any. Decides separators between top-level turns. */\n lastDepthAtEmission: number\n // The running `/` command's invocation (`/commit args`) until the next typed prompt.\n commandInvocation: string | null\n // `runId + reason` of loop-injected turns already shown: one notice per run, not per retry.\n injectedNoticed: Set<string>\n /** The top-level run the current exchange shows: the last prompted one, or the last to reply. */\n exchangeRunId?: string\n}\n\n/** Attachment chips for a typed prompt, reconstructed from the turn's sibling blocks. */\nfunction promptAttachments(turn: SessionTurn, block: SessionContentBlock): { name: string, mediaType: string, size: number }[] {\n // Reconstruct attachment metadata from sibling content\n // blocks so the transcript shows chips after session reload.\n const attachments: { name: string, mediaType: string, size: number }[] = []\n for (const sibling of turn.content) {\n if (sibling.type === 'image' || sibling.type === 'audio' || sibling.type === 'video') {\n attachments.push({\n name: sibling.name ?? sibling.type,\n mediaType: sibling.mediaType,\n size: typeof sibling.data === 'string'\n ? base64DecodedSize(sibling.data)\n : 0,\n })\n }\n else if (sibling.type === 'document') {\n // Documents are structured blocks, not <attachment>-tagged\n // text — surface their own chip. Covers base64 (e.g. a PDF\n // prompt) AND text encoding (the shape `paste.txt` /\n // dragged-text-file attachments persist as); text-encoded\n // ones get a chip too.\n attachments.push({\n name: sibling.name ?? 'document',\n mediaType: sibling.mediaType,\n size: typeof sibling.data !== 'string'\n ? 0\n : sibling.encoding === 'text'\n ? Buffer.byteLength(sibling.data)\n : base64DecodedSize(sibling.data),\n })\n }\n else if (sibling !== block && sibling.type === 'text') {\n const m = sibling.text.match(/^<attachment\\s+(?:name=\"([^\"]+)\"\\s*)?(?:media_type=\"([^\"]+)\")?/)\n if (m) {\n attachments.push({\n name: m[1] ?? 'attachment',\n mediaType: m[2] ?? 'text/plain',\n size: sibling.text.length,\n })\n }\n }\n }\n return attachments\n}\n\n/** Replay one non-blank text block of a user turn. */\nfunction replayUserText(\n state: ReplayState,\n turn: SessionTurn,\n block: Extract<SessionContentBlock, { type: 'text' }>,\n depth: number,\n tag: ReplayTag,\n marker: { emitted: boolean },\n): void {\n const { events } = state\n // A system note is the harness talking to the model, not the user: no\n // row at all (the run receipt names the agent; the rest is the model's).\n if (isSystemNoteBlock(block))\n return\n\n // Background-task completion notifications ride as text\n // blocks carrying `<task-notification>` XML (the format\n // `renderTaskNotificationXml` produces). Detect and emit\n // them as their own structured event so the TUI can render\n // a banner — and IMPORTANT: DON'T also emit a `user-prompt`\n // event for the same text, otherwise the raw XML would\n // double-paint alongside the banner. Same dedupe pattern\n // the compact-summary path uses.\n // Pass the FULL tag (turnId + optional childId/depth) so a\n // subagent's task notification renders under the right\n // `child-N` lane instead of bleeding up to depth 0.\n const taskEvent = parseTaskNotificationBlock(block.text, tag)\n if (taskEvent) {\n events.push(taskEvent)\n return\n }\n\n // Cross-session event delivered to a main session. Same dedupe\n // rule as the task notification above: emit the structured row,\n // and DON'T also emit the `user-prompt` echo of the same text —\n // the model-facing `<session-event>` block is not a user message\n // and must not paint as one.\n const sessionEvent = parseSessionEventXml(block.text)\n if (sessionEvent) {\n events.push({ kind: 'session-event', text: sessionEvent.summary, sessionEvent, ...tag })\n return\n }\n\n // For child runs the \"user\" text is the spawn task itself, already\n // rendered as the `spawn-start` marker above. Drop the duplicate.\n //\n // `user-prompt` carries the **raw** text; the renderer prepends the\n // `❯ ` chevron. No prefix in the payload means `refs` offsets stay\n // raw (no shift), and consumers building user-message indices or\n // history can read `event.text` directly.\n if (depth === 0) {\n // Inside a `/` command nothing opens a new exchange: the prompt\n // a command sub-run was given is a step of the command's work\n // (label = its short `display`, body = the full prompt), and a\n // note the command left for the model (`turn.display`, no run)\n // is its receipt line, or nothing for a model-only note (`''`).\n // Same shapes the live hosts emit.\n const commandOrigin = turn.runId ? state.runById.get(turn.runId)?.origin : undefined\n if (commandOrigin?.kind === 'command') {\n events.push({\n kind: 'command-detail',\n label: commandOrigin.display ? commandStepLabel(commandOrigin.display) : 'prompt',\n text: block.text,\n ...tag,\n })\n state.exchangeRunId = turn.runId\n return\n }\n if (turn.display !== undefined && !turn.runId) {\n if (!marker.emitted && turn.display !== '')\n events.push({ kind: 'command-note', text: commandNoteText(turn.display, block.text, state.commandInvocation ?? undefined), ...tag })\n marker.emitted = true\n return\n }\n state.commandInvocation = null\n\n // Separator BEFORE the user prompt — matches the live\n // behavior, which only appends a separator when committing a\n // new prompt. Firing on every depth-0 turn pair would insert a\n // separator between every mid-exchange assistant tool turn and\n // its paired user-side tool_result turn, producing a 2-row gap\n // between consecutive `todowrite` calls in the replayed\n // transcript that is absent during the live cascade.\n if (state.lastDepthAtEmission === 0)\n events.push({ kind: 'separator', text: '' })\n state.exchangeRunId = turn.runId\n\n const attachments = promptAttachments(turn, block)\n\n // Mentions typed through a completion are not persisted: recover the file chips from the text.\n const refs = inferPromptRefs(block.text)\n events.push({\n kind: 'user-prompt',\n text: block.text,\n turnId: turn.id,\n ...(refs.length > 0 ? { refs } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n ...(block.origin ? { origin: block.origin } : {}),\n })\n }\n}\n\n/** Replay a user turn: typed prompts, notifications, tool results, compaction markers. */\nfunction replayUserTurn(state: ReplayState, turn: SessionTurn, depth: number, tag: ReplayTag): void {\n const { events } = state\n // The loop wrote this turn, not the user: a notice, not a prompt bubble.\n // Retries repeat within a run, so one notice per run and reason.\n if (turn.injected) {\n const key = `${turn.runId ?? ''}\\u0000${turn.injected}`\n if (!state.injectedNoticed.has(key)) {\n state.injectedNoticed.add(key)\n const { notice, text } = injectedTurnNotice(turn.injected)\n events.push({ kind: 'info', text, notice, ...tag })\n }\n return\n }\n // A display-marker turn (command sub-run prompt, or a context note)\n // emits its `❯ marker` echo ONCE, even across multiple text blocks.\n const marker = { emitted: false }\n const attachmentOnly = !turn.content.some(block => block.type === 'text' && !block.systemNote && block.text.trim())\n && turn.content.some(block => ['document', 'image', 'audio', 'video'].includes(block.type))\n const displayContent: SessionContentBlock[] = attachmentOnly\n ? [{ type: 'text', text: '[Attachment]' }, ...turn.content]\n : turn.content\n for (const block of displayContent) {\n if (block.type === 'text' && (block.text.trim() || block.systemNote?.label)) {\n replayUserText(state, turn, block, depth, tag, marker)\n }\n else if (block.type === 'tool_result') {\n const tool = state.toolByCallId.get(block.callId)\n // Spawn tool-results duplicate the spawn-end marker's `Tokens: …`\n // line — and on older sessions its \"N in / M out\" shape\n // disagrees with the cache-aware spawn-end. Strip it at the\n // display layer; the persisted output stays intact.\n const raw = toolResultText(block.output)\n const text = tool === 'spawn' ? stripSpawnTokensLine(raw) : raw\n // Calls the tool made (codemode's `tools.*`), as the live run streamed them.\n if (block.calls?.length)\n events.push(...nestedRecordEvents(block.calls, block.callId, tag))\n events.push({\n kind: 'tool-result',\n text,\n ...(tool ? { tool } : {}),\n callId: block.callId,\n // Same error bit as the live event, so a resync doesn't flip a failed call to ok.\n ...(block.isError ? { isError: true as const } : {}),\n ...(block.durationMs !== undefined ? { durationMs: block.durationMs } : {}),\n ...tag,\n })\n }\n else if (block.type === 'compact-summary') {\n // Compaction boundary — single event per marker block, via the\n // shared `compactSummaryEvent` mapper so the reloaded card matches\n // the live one byte-for-byte. The renderer reads `compact` for the\n // metadata badge; `text` carries the summary (the TUI keeps it\n // hidden by default so it doesn't read like new dialogue). Subagents\n // never produce these markers (compaction targets the top-level\n // conversation), so the ancestry tag isn't threaded — but `turnId`\n // is, so select-turn mode still highlights.\n events.push(compactSummaryEvent(block, turn.id))\n }\n }\n}\n\n/** The event a command turn's `tool_result` block replays as: a harness notice, a custom render, or a detail. */\nfunction commandToolResultEvent(block: Extract<SessionContentBlock, { type: 'tool_result' }>, tag: ReplayTag): StreamEvent {\n const meta = block.metadata?.command\n const commandMeta = (meta && typeof meta === 'object' && !Array.isArray(meta))\n ? meta as Record<string, unknown>\n : undefined\n // Harness notice (model fallback, repeat-guard trip, run error).\n // Replayed into the same `info` / `error` event the live path\n // emits, so a reopened conversation shows the identical row in\n // the same place instead of losing every harness event.\n const persistedNotice = readNoticeMeta(commandMeta?.notice)\n if (persistedNotice) {\n return {\n kind: persistedNotice.notice.severity === 'error' ? 'error' : 'info',\n text: toolResultText(block.output),\n notice: persistedNotice.notice,\n ...tag,\n // Origin wins over the run-derived tag: a subagent notice is\n // persisted by the parent's depth-0 run, so the tag alone would\n // reload it flat instead of indented under its child.\n ...(persistedNotice.childId ? { childId: persistedNotice.childId } : {}),\n ...(persistedNotice.depth !== undefined ? { depth: persistedNotice.depth } : {}),\n }\n }\n // Custom-rendered block: re-bind the renderer id + data; the\n // persisted output is the fallback (see commandBlocksToContent).\n const customMeta = commandMeta?.custom\n if (customMeta && typeof customMeta === 'object' && !Array.isArray(customMeta)\n && typeof (customMeta as { renderer?: unknown }).renderer === 'string') {\n // Persisted metadata is JsonValue by construction (see\n // commandBlocksToContent) — the cast re-narrows what JSON\n // round-tripping already guarantees.\n const bound = customMeta as { renderer: string, data?: JsonValue }\n return {\n kind: 'custom',\n text: toolResultText(block.output),\n custom: { renderer: bound.renderer, ...(bound.data !== undefined ? { data: bound.data } : {}) },\n ...tag,\n }\n }\n const label = typeof commandMeta?.label === 'string' ? commandMeta.label : undefined\n return {\n kind: 'command-detail',\n text: toolResultText(block.output),\n ...(label ? { label } : {}),\n ...(commandMeta?.syntax === 'diff' ? { syntax: 'diff' as const } : {}),\n ...tag,\n }\n}\n\n/** Replay a display-only `role: 'command'` turn. */\nfunction replayCommandTurn(state: ReplayState, turn: SessionTurn, tag: ReplayTag): void {\n const { events } = state\n // Display-only local output from a `/` command (never sent to the\n // model). Delimit from the prior exchange, then replay each block in\n // the same shape the live `emit()` path appends, so reloaded and live\n // command output look identical: plain text → full markdown;\n // `tool_result` blocks (detail output — diffs, logs) → a\n // `command-detail` event: dim label + line-capped body.\n //\n // Notice turns are exempt from the delimiter: live they are appended\n // straight into the running transcript with no separator, and\n // `marginTopFor` collapses consecutive ones into a single block. Pushing\n // one here would reload a burst of harness events as a double-spaced\n // ladder, and put a break mid-exchange that never existed live.\n //\n // The invocation header (`` `❯ /commit` ``, the first block of a\n // command's first turn) replays as the user's prompt; the command's\n // later turns continue that exchange, so they open no new one.\n const noticeOnly = turn.content.length > 0 && turn.content.every(block => noticeFromBlock(block) !== null)\n const first = turn.content[0]\n const invocation = first?.type === 'text' ? parseCommandHeader(first.text) : null\n if (invocation !== null)\n state.commandInvocation = invocation\n if (state.lastDepthAtEmission === 0 && !noticeOnly && (invocation !== null || state.commandInvocation === null))\n events.push({ kind: 'separator', text: '' })\n for (const block of turn.content) {\n if (invocation !== null && block === first) {\n events.push({ kind: 'user-prompt', text: invocation, synthetic: true, turnId: turn.id })\n }\n else if (block.type === 'text' && block.text.trim()) {\n events.push({ kind: 'markdown', text: block.text, streaming: false, ...tag })\n }\n else if (block.type === 'tool_result') {\n events.push(commandToolResultEvent(block, tag))\n }\n }\n}\n\n/** The `tool` event an assistant `tool_call` block replays as. */\nfunction toolCallEvent(\n block: Extract<SessionContentBlock, { type: 'tool_call' }>,\n resultByCallId: ReadonlyMap<string, ReplayedResult>,\n tag: ReplayTag,\n): StreamEvent {\n // Stable-tools dispatch persists the `call_tool { name, arguments }`\n // envelope (wire-valid history), but the LIVE `tool:before` hook\n // fired on the unwrapped inner call. Unwrap here too so a reloaded\n // transcript shows \"Coolify projects\" with its real arguments, not\n // \"Call tool\" — byte-for-byte the same event the live run emitted.\n const inner = unwrapCallTool(block.name, block.input)\n const { name, input } = inner ?? block\n // Historical replay has no pre-write snapshot for `write_file`\n // (the captured priorContent only exists at live-hook time).\n // `extractEditPayload` falls back to `oldString: ''` so the\n // diff renders as an all-add view — matches git's \"new file\"\n // convention and is the most honest reconstruction available.\n let edit = extractEditPayload(name, input)\n if (edit) {\n // Attach per-edit outcomes parsed out of the paired tool_result\n // body so a replayed transcript shows the same applied / denied\n // / skipped badges the live run displayed. Falls through when\n // the body is unstructured (legacy results, error preamble) —\n // the renderer treats absent outcomes as \"all applied\".\n const resultText = resultByCallId.get(block.id)?.text\n if (resultText) {\n const outcomes = parseEditOutcomesFromResult(resultText)\n if (outcomes && outcomes.length === edit.hunks.length)\n edit = { ...edit, outcomes }\n }\n }\n // Model decision: the verdict (approve or deny) is on the call's result metadata.\n const approval = resultByCallId.get(block.id)?.approval\n return {\n kind: 'tool',\n text: toolCallPreview(name, input),\n tool: name,\n input,\n ...(edit ? { edit } : {}),\n callId: block.id,\n ...(approval ? { approval } : {}),\n ...tag,\n }\n}\n\n/** Replay an assistant turn: text, reasoning, tool calls, server-tool blocks. */\nfunction replayAssistantTurn(state: ReplayState, turn: SessionTurn, tag: ReplayTag): void {\n const { events } = state\n // A cited Claude reply is persisted one text block per cited span: replay\n // it as the single message the live stream showed (`mergeReplyText`), not\n // one message per fragment.\n for (const block of mergeReplyText(turn)) {\n if (block.type === 'text' && block.text.trim()) {\n // Persisted turns are finalized — `streaming: false` so the markdown\n // renderer commits to the final layout (no heal pass needed).\n events.push({ kind: 'markdown', text: block.text, streaming: false, ...tag })\n }\n else if (block.type === 'thinking' && block.text.trim()) {\n // Reasoning is persisted as part of the assistant content (the\n // provider needs it echoed back), so replay it the same way the\n // live `stream:thinking` hook does: one event per line. The TUI\n // renderer gives consecutive thinking rows a fixed icon gutter so\n // replayed and streamed reasoning look identical. Without this,\n // reloading a session drops every trace.\n //\n // Blank lines are SKIPPED: a paragraph break inside one thinking\n // block would otherwise replay as an empty thinking event — a\n // bare icon row with no text, one per paragraph, in every\n // renderer (the GUI's \"double icon\" artifact).\n for (const line of block.text.split('\\n')) {\n if (line.trim())\n events.push({ kind: 'thinking', text: line, ...tag })\n }\n }\n else if (block.type === 'tool_call') {\n events.push(toolCallEvent(block, state.resultByCallId, tag))\n }\n else if (block.type === 'server_tool_use') {\n // Native server-tool invocation (Anthropic `web_search`). Live runs\n // emit the same shape from `stream:server_tool_use`; replay this\n // way so the transcript looks identical on reload.\n events.push({\n kind: 'tool',\n text: toolCallPreview(block.name, block.input),\n tool: block.name,\n input: block.input,\n callId: block.id,\n ...tag,\n })\n }\n else if (block.type === 'server_tool_result') {\n events.push({\n kind: 'tool-result',\n text: serverToolResultSummary(block.content),\n tool: block.toolName,\n callId: block.toolUseId,\n ...tag,\n })\n }\n }\n}\n\n/**\n * A top-level run nobody prompted (a wake: a background task or a worker\n * finished, a restart resumed) opens its own exchange, as the host's live\n * separator does at its start: its reply must not join the previous run's\n * and push that run's closing message into the earlier ones. Its trigger\n * (the task or worker banner) stays above, where it painted live. A `/`\n * command's sub-runs are steps of the command's exchange.\n */\nfunction openUnpromptedRun(state: ReplayState, turn: SessionTurn): void {\n const runId = turn.runId\n if (runId === undefined || runId === state.exchangeRunId)\n return\n const opensExchange = state.exchangeRunId !== undefined\n && state.runById.get(runId)?.origin?.kind !== 'command'\n && state.events.at(-1)?.kind !== 'separator'\n state.exchangeRunId = runId\n if (opensExchange)\n state.events.push({ kind: 'separator', text: '' })\n}\n\n/**\n * Replays persisted turns as a viewable transcript. Equivalent to `replayTurns(turns, runs).events`.\n * Mirrors the event shape produced live by the agent hooks so loaded and\n * streaming history render identically, including subagent ancestry when\n * `runs` is supplied:\n * - Every turn carries a `runId`, looked up in `runs` to get the run's\n * `depth`. The resulting events carry `{ depth, childId }`, the same\n * shape the live `child:*` bubble hooks produce.\n * - `spawn-start` / `spawn-end` markers land at each child-run boundary,\n * so the transcript reads the same as a live run did.\n * - For child runs (`depth > 0`), the user-role \"task\" text is suppressed\n * because `spawn-start` already shows it.\n *\n * @param turns - Persisted turns in order.\n * @param runs - Runs the turns belong to. Without them every event has depth 0.\n */\nexport function eventsFromTurns(\n turns: SessionTurn[],\n runs: readonly SessionRun[] = [],\n): StreamEvent[] {\n return replayTurns(turns, runs).events\n}\n\n/**\n * The whole replay, and where each turn's events start in it\n * (`turnStarts[turns.length]` = the end). A page of turns `[from, to)` is\n * `events.slice(turnStarts[from], turnStarts[to])`: consecutive pages\n * concatenate to exactly {@link eventsFromTurns} (exchange separators, run\n * receipts, subagent markers, tool names and command state as the whole\n * replay has them), because what a run or the turn before decides lands in\n * the page of the turn whose replay emitted it.\n *\n * @param turns - Persisted turns in order.\n * @param runs - Runs the turns belong to. Pass `[]` for none.\n */\nexport function replayTurns(\n turns: SessionTurn[],\n runs: readonly SessionRun[],\n): { events: StreamEvent[], turnStarts: number[] } {\n const runById = indexReplayRuns(turns, runs)\n const labelFor = childLabeler(runById)\n const toolByCallId = toolNamesByCallId(turns)\n const resultByCallId = resultsByCallId(turns)\n const ancestryOf = runAncestry(runById)\n const subtreeTotals = runSubtreeTotals(runById)\n const spawnerOf = spawnerLabeler(runById, labelFor)\n\n // Index of the last turn in each child run's subtree (its own turns and\n // its descendants'). Concurrent siblings interleave their turns, so\n // \"the run changed\" is no boundary: a run's `spawn-end` lands once, after\n // this turn, and its `spawn-start` once, at its first turn. Diffing an\n // open-run stack per turn would close and reopen siblings at every\n // switch — one \"Finished\" marker (all carrying the final totals) per switch.\n const chainByTurn = turns.map(turn => ancestryOf(turn.runId))\n const lastSubtreeTurn = new Map<string, number>()\n chainByTurn.forEach((chain, idx) => {\n for (const run of chain)\n lastSubtreeTurn.set(run.id, idx)\n })\n\n const events: StreamEvent[] = []\n /** Child runs whose `spawn-start` has been emitted. */\n const startedRuns = new Set<string>()\n /** Started runs still awaiting their `spawn-end`, in open order. */\n const openRuns: SessionRun[] = []\n const state: ReplayState = { events, runById, toolByCallId, resultByCallId, lastDepthAtEmission: -1, commandInvocation: null, injectedNoticed: new Set() }\n\n const pushSpawnEnd = (run: SessionRun) => {\n events.push(spawnEndEvent(run, subtreeTotals(run), labelFor, spawnerOf(run)))\n }\n\n const pushSpawnStart = (run: SessionRun) => {\n events.push(spawnStartEvent(run, labelFor, spawnerOf(run)))\n }\n\n /**\n * Emit `spawn-end` for every open run whose subtree ended before turn\n * `beforeTurn` — innermost (most recently opened) first, so a depth ≥ 2\n * chain closes child before parent. Lands right before the next turn's\n * events.\n */\n const closeFinishedRuns = (beforeTurn: number) => {\n for (let k = openRuns.length - 1; k >= 0; k--) {\n const run = openRuns[k]\n // Still running (a window reloaded mid-run): no \"finished\" marker, its\n // live events keep landing in an open box. Loads demote runs that died\n // with their process to `aborted` first (`demoteStaleRunningStatus`).\n if (run.status === 'running')\n continue\n if ((lastSubtreeTurn.get(run.id) ?? -1) < beforeTurn) {\n openRuns.splice(k, 1)\n pushSpawnEnd(run)\n }\n }\n }\n\n const turnStarts: number[] = []\n for (let i = 0; i < turns.length; i++) {\n turnStarts.push(events.length)\n const turn = turns[i]\n const targetChain = chainByTurn[i]\n const depth = targetChain.length // 0 for top-level, otherwise innermost depth\n\n closeFinishedRuns(i)\n // Open every not-yet-started run in the chain, outermost first.\n for (const run of targetChain) {\n if (startedRuns.has(run.id))\n continue\n startedRuns.add(run.id)\n openRuns.push(run)\n pushSpawnStart(run)\n }\n\n const subagentTag = depth > 0 && turn.runId ? { childId: labelFor(turn.runId), depth } : undefined\n // `turnId` tags every event so the TUI's select-turn mode can highlight\n // all events emitted by a single SessionTurn. Subagent ancestry stays in\n // a separate object so the spread order keeps existing tag overrides\n // (childId/depth) wins-last semantics intact.\n const tag = { turnId: turn.id, ...subagentTag }\n\n if (turn.role === 'user') {\n replayUserTurn(state, turn, depth, tag)\n state.lastDepthAtEmission = depth\n continue\n }\n\n if (turn.role === 'command') {\n replayCommandTurn(state, turn, tag)\n state.lastDepthAtEmission = depth\n continue\n }\n\n if (turn.role === 'assistant') {\n if (depth === 0)\n openUnpromptedRun(state, turn)\n replayAssistantTurn(state, turn, tag)\n state.lastDepthAtEmission = depth\n }\n }\n\n // Drain any trailing open child runs (e.g. session ended mid-spawn). Pop\n // innermost-first so depth ≥ 2 chains emit `spawn-end` in the right order.\n closeFinishedRuns(turns.length)\n turnStarts.push(events.length)\n\n // A receipt lands after its run's last event: every turn starting past it moves down.\n return { events: withRunReceipts(events, turns, runs, turnStarts), turnStarts }\n}\n\n/**\n * Pattern matching the leading `<task-notification>` shape that the\n * agent's notification-injection path produces (see\n * `renderTaskNotificationXml` in `src/agent-task-notifications.ts`). Anchored so a stray\n * notification-shaped phrase mid-prompt doesn't trigger a false-positive\n * detection — the model's wire format always starts the user-turn\n * content block with this exact opening tag.\n */\nconst TASK_NOTIFICATION_RE = /^\\s*<task-notification>([\\s\\S]*?)<\\/task-notification>\\s*$/\n\n/**\n * Per-field extractors. Compiled once at module load (parsing happens\n * on every session replay, and a fresh `new RegExp` per pick burns\n * cycles for no reason).\n */\nconst TASK_NOTIFICATION_FIELD_RES = {\n taskId: /<task-id>([\\s\\S]*?)<\\/task-id>/,\n status: /<status>([\\s\\S]*?)<\\/status>/,\n exitCode: /<exit-code>([\\s\\S]*?)<\\/exit-code>/,\n command: /<command>([\\s\\S]*?)<\\/command>/,\n outputFile: /<output-file>([\\s\\S]*?)<\\/output-file>/,\n durationMs: /<duration-ms>([\\s\\S]*?)<\\/duration-ms>/,\n summary: /<summary>([\\s\\S]*?)<\\/summary>/,\n} as const\n\n/**\n * Detect a `<task-notification>` text block on replay and convert it\n * into a structured `task-notification` StreamEvent so the TUI's banner\n * renderer can paint it cleanly. Returns `null` when the block isn't a\n * notification (the caller falls back to the normal user-prompt path).\n *\n * Reads every field DIRECTLY from its tag — does NOT parse `<summary>`\n * for the underlying data. The summary is a derived display string,\n * not a source of truth: changing its format (localization, signal in\n * the label, whatever) must NEVER break replay. Each field falls back\n * to a safe default so older transcripts pre-dating a tag addition\n * still render.\n */\nfunction parseTaskNotificationBlock(\n text: string,\n tag: { turnId: string, childId?: string, depth?: number },\n): StreamEvent | null {\n const m = text.match(TASK_NOTIFICATION_RE)\n if (!m)\n return null\n\n const body = m[1]\n const pick = (re: RegExp): string | undefined => {\n const inner = body.match(re)\n return inner ? unescapeXml(inner[1].trim()) : undefined\n }\n\n const taskId = pick(TASK_NOTIFICATION_FIELD_RES.taskId) ?? '?'\n const statusRaw = pick(TASK_NOTIFICATION_FIELD_RES.status) ?? 'exited'\n const status: 'exited' | 'killed' = statusRaw === 'killed' ? 'killed' : 'exited'\n const exitCode = Number.parseInt(pick(TASK_NOTIFICATION_FIELD_RES.exitCode) ?? '0', 10) || 0\n const command = pick(TASK_NOTIFICATION_FIELD_RES.command) ?? ''\n const outputPath = pick(TASK_NOTIFICATION_FIELD_RES.outputFile) ?? ''\n const durationMs = Number.parseInt(pick(TASK_NOTIFICATION_FIELD_RES.durationMs) ?? '0', 10) || 0\n const summary = pick(TASK_NOTIFICATION_FIELD_RES.summary)\n ?? `${taskId} ${statusRaw}${exitCode ? ` ${exitCode}` : ''}`\n\n return {\n kind: 'task-notification',\n text: summary,\n task: { taskId, status, exitCode, outputPath, command, durationMs },\n turnId: tag.turnId,\n ...(tag.childId !== undefined ? { childId: tag.childId } : {}),\n ...(tag.depth !== undefined ? { depth: tag.depth } : {}),\n }\n}\n\n/**\n * Reverse of `escapeXml` for the small set of entities the writer\n * emits. Not a full HTML entity decoder — just enough to round-trip\n * `<` / `>` / `&` / quotes through persistence.\n *\n * `&amp;` MUST be replaced last, otherwise `&amp;lt;` becomes `&lt;`\n * then `<` (data corruption — silent double-decode).\n */\nfunction unescapeXml(s: string): string {\n return s\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&apos;/g, '\\'')\n .replace(/&amp;/g, '&')\n}\n\n/**\n * Formats a tool call as `name(json args)`, or just the name when the input is empty.\n *\n * @param name - Tool name.\n * @param input - The tool call's input.\n */\nexport function toolCallPreview(name: string, input: Record<string, unknown>): string {\n const args = JSON.stringify(input)\n return args && args !== '{}' ? `${name}(${args})` : name\n}\n\n/**\n * One-line display summary for a server-tool-result block (currently only\n * Anthropic's `web_search_tool_result`). `content` is either an error object\n * (`{ error_code: '...' }`) or an array of result entries — we count the\n * latter and surface the code for the former. Kept terse on purpose; richer\n * formatting (titles + URLs per hit) is a separate UI pass.\n *\n * Falls back to `(opaque result)` for unrecognized shapes rather than an\n * empty string — an empty `text` field would render as a blank row in the\n * transcript with no signal that anything happened.\n */\nexport function serverToolResultSummary(content: unknown): string {\n if (Array.isArray(content)) {\n const n = content.length\n return n === 1 ? '1 result' : `${n} results`\n }\n if (content && typeof content === 'object') {\n const code = (content as { error_code?: unknown }).error_code\n if (typeof code === 'string')\n return `error: ${code}`\n }\n return '(opaque result)'\n}\n\n/**\n * Update the trailing `'tool'` event matching `callId` so its\n * `edit.outcomes` reflects the canonical merged outcomes the chat\n * layer's `tool:transform` hook just computed. Without this, the live\n * diff badges stay frozen at whatever the gate set (approval-side\n * outcomes) and never reflect body-side failures from `multi_edit`'s\n * best-effort run — only a session reload re-attaches the merged\n * outcomes via {@link eventsFromTurns}.\n *\n * Walks back-to-front because the matching event is overwhelmingly the\n * most recent (we're updating right after the body returned). Returns\n * the same reference when no match is found (or the event already\n * carries the target outcomes), so React skips the re-render.\n *\n * @param events - The current events.\n * @param callId - Call id of the tool event to update.\n * @param outcomes - The merged edit outcomes.\n */\nexport function updateToolEventOutcomes(\n events: readonly StreamEvent[],\n callId: string,\n outcomes: readonly EditOutcome[],\n): StreamEvent[] {\n for (let i = events.length - 1; i >= 0; i--) {\n const e = events[i]\n if (e.kind !== 'tool' || e.callId !== callId || !e.edit)\n continue\n if (e.edit.outcomes === outcomes)\n return events as StreamEvent[]\n const next = events.slice()\n next[i] = { ...e, edit: { ...e.edit, outcomes } }\n return next\n }\n return events as StreamEvent[]\n}\n\n/**\n * Render tool output as plain text, whether it's a string or structured content.\n *\n * @param output - A tool result, as a string or structured content.\n */\nexport function toolResultText(output: string | ToolResultContent[]): string {\n return typeof output === 'string' ? output : toolResultToText(output)\n}\n\n/**\n * Strip the `Tokens: …` line from a spawn tool-result. The spawn-end marker\n * displayed right above already shows the same stats; keeping the line in the\n * rendered tool-result body just produces a visible duplicate (and, on\n * reloaded older sessions, an *inconsistent* duplicate — the persisted line\n * can use the `13 in / 4075 out` shape while the freshly synthesized\n * spawn-end uses the cache-aware `in 92615 (cache 92602) / 4075 out` shape).\n *\n * Display-only: the persisted tool_result content is untouched, so the LLM\n * still sees the full string in its context window. Anchored to start-of-line\n * and matches both `Tokens: 13 in / 4075 out` (older) and `Tokens: in 13 …`\n * (`formatTokenUsage`) shapes.\n *\n * @param text - A spawn tool-result body.\n */\nexport function stripSpawnTokensLine(text: string): string {\n // Strict: only strip when the `Tokens: …` line is **immediately preceded\n // by** the spawn-tool header (`[sub-agent <id>] (Completed|Aborted|Failed|Timed) …`).\n // A bare `^Tokens:` multi-line regex would eat any body line that\n // happened to start with `Tokens:` — e.g. a model summarizing\n // \"Tokens: …\" inside its response. Anchored matching keeps the strip\n // local to the spawn header even if the model's response continues with\n // arbitrary content.\n //\n // `m` + `g` so every header in a multi-spawn result is handled, not just\n // the one at index 0. Every spawn tool-result is single-spawn so\n // `g` is a no-op. The multiline anchor would also strip every header's\n // tokens line in a body that concatenates multiple spawn outputs.\n return text.replace(\n /(^\\[sub-agent [^\\n]+\\n)Tokens:[^\\n]*\\n?/gm,\n '$1',\n )\n}\n\n// ---------------------------------------------------------------------------\n// Transcript visibility + select-turn navigation live in the node-free\n// `./turn-selection` leaf so a browser-context renderer can import them via\n// `zidane/chat/pure`. Re-exported here (and through `zidane/tui`) so existing\n// `zidane/chat` consumers keep their import paths.\n// ---------------------------------------------------------------------------\nexport {\n BASH_CALL_ID_PREFIX,\n CACHE_NOTICE_LABEL,\n EDIT_TOOL_NAMES,\n isCacheNotice,\n isEditErrorResult,\n isTurnHighlighted,\n isUserBashEvent,\n isVisible,\n isVisibleDuringSearch,\n messageSelectionOwnership,\n promptHistoryFromEvents,\n retagUserPromptEvents,\n selectableTurnIds,\n selectionAfterTurnRemoval,\n streamEventSearchText,\n turnSelectionOwnership,\n} from './turn-selection'\n\n/**\n * Default top-margin per kind (in rows). Spacing intent:\n * - `info` / `markdown` / `tool` / `error` / `spawn-start` open a new\n * block, so they each get one row of breathing room above.\n * - `thinking` / `tool-result` / `spawn-end` continue the previous\n * block and stay flush.\n *\n * Context-aware overrides live in {@link marginTopFor}.\n */\nconst MARGIN_TOP: Record<StreamEvent['kind'], number> = {\n 'separator': 0,\n 'user-prompt': 1,\n 'info': 1,\n // A reasoning run opens with breathing room (like a markdown block); the\n // run's continuation lines collapse to 0 via the rule in `marginTopFor`.\n 'thinking': 1,\n 'tool': 1,\n 'tool-result': 0,\n // Command details open a labeled block of their own (like a tool call\n // line does), so they get the same one-row gap above.\n 'command-detail': 1,\n 'error': 1,\n 'markdown': 1,\n 'spawn-start': 1,\n 'spawn-end': 0,\n // Draws no row of its own (its spawn call's row shows the wait).\n 'spawn-queued': 0,\n // Compact-summary opens its own block; visually it's the \"before /\n // after\" hinge between elided history and current context, so it\n // deserves the breathing room a markdown / user-prompt event gets.\n 'compact-summary': 1,\n // Task-notification banners open a new logical block (a task is done,\n // here's what happened) so they get the same gap a `tool` line gets.\n // Consecutive task-notifications stack tight via the rule in\n // `marginTopFor` — a burst of completed tasks reads as one stacked\n // log column rather than scattered banners.\n 'task-notification': 1,\n // A worker report opens its own block, like a task notification does.\n 'session-event': 1,\n // One blank line above: the receipt is a footer set off from the prose it\n // totals. It paints its own blank line BELOW (see `RunSummaryLine`), and\n // `marginTopFor` gives the next block 0 so the gap stays exactly one row.\n 'run-summary': 1,\n // Custom-rendered rows are command output in spirit (a command or\n // extension chose the presentation) — same breathing room as\n // `command-detail` / `markdown`.\n 'custom': 1,\n // The command's receipt closes its output with one row of air, like the run receipt.\n 'command-note': 1,\n}\n\nconst TOOL_KINDS: ReadonlySet<StreamEvent['kind']> = new Set(['tool', 'tool-result'])\n\n/**\n * Resolve the top margin (in rows) for an event given the one rendered\n * just before it. Context-aware rules:\n *\n * - A `tool` / `tool-result` event right after another\n * `tool` / `tool-result` collapses to a tight list — call→result\n * pairs and back-to-back calls read as one logical block.\n * - Consecutive `task-notification` banners stack tight — a burst of\n * background-task completions reads as one log column rather than\n * scattered banners.\n *\n * NB: parent-level events (`depth === 0`) following a subagent block\n * (`depth > 0`) get their normal default margin. The subagent's\n * `🌳` end-marker does not provide enough visual separation to\n * collapse the transition to 0: a 2-cell emoji on the same row as the\n * close marker doesn't create a vertical break, and in\n * hide-subagent-output mode the SubagentBlock box isn't rendered\n * either, so the parent's follow-up markdown would be glued directly\n * against the close line. Subagents should READ like\n * tool calls: open with breathing room, close tight inside, and open\n * a clean gap before the parent's next thought — that's the contract\n * the tool-call → markdown transition uses, mirrored here.\n *\n * Renderer-agnostic — TUI uses it as Yoga `marginTop`; a CSS host can\n * use the same number as the row's top margin in `em` / `rem`.\n *\n * @param event - The event being rendered.\n * @param previous - The event rendered just above it, if any.\n */\nexport function marginTopFor(event: StreamEvent, previous: StreamEvent | undefined): number {\n // First-block exception: spacing is single-direction (marginTop-only),\n // so the very first rendered block has no neighbor above to space\n // against — a gap there would just indent the transcript from its\n // container edge. Matches `SubagentBlock`'s `previous ? 1 : 0` rule so\n // every block kind starts flush.\n if (!previous)\n return 0\n // NB: an event directly after a `separator` keeps its own margin. A\n // separator is a semantic exchange boundary and paints zero rows (see\n // `EventLineImpl`'s `'separator'` case), so inter-block spacing is\n // exclusively the next block's margin. Collapsing the margin here too\n // would leave prompts with no gap at all.\n if (TOOL_KINDS.has(event.kind) && TOOL_KINDS.has(previous.kind))\n return 0\n // A spawn marker directly below the `spawn` tool call that created it —\n // or stacked under a sibling marker — reads as one fluid block, same rule\n // as consecutive tool rows. The gap only opens after prose/other kinds.\n if (event.kind === 'spawn-start' && previous\n && (TOOL_KINDS.has(previous.kind) || previous.kind === 'spawn-start' || previous.kind === 'spawn-end')) {\n return 0\n }\n if (event.kind === 'task-notification' && previous?.kind === 'task-notification')\n return 0\n // The run receipt paints its own trailing blank row so the last run of a\n // transcript still ends with one; the block after it must not add a second.\n if (previous.kind === 'run-summary')\n return 0\n // Consecutive notice rows stack tight, same rule as task banners. A burst of\n // harness events (a fallback, then the repeat-guard trip, then the run error)\n // reads as one block instead of a double-spaced ladder.\n if (event.notice && previous?.notice)\n return 0\n // Continuation lines of one reasoning run stack tight — only the first\n // thinking line (run start) gets the top gap.\n if (event.kind === 'thinking' && previous?.kind === 'thinking' && previous.childId === event.childId)\n return 0\n return MARGIN_TOP[event.kind] ?? 0\n}\n\n/**\n * Effective context size of the most recent assistant turn — drives the footer\n * indicator. Walk from the end of `turns` and return the cache-aware input-token total\n * of the most recent **parent** (depth-0) assistant turn. Subagent turns\n * are skipped because their context window is the child's, not the parent's\n * — surfacing a subagent's `usage.input` as the footer's \"context used\"\n * after a session ends mid-spawn would be misleading. The next prompt\n * feeds the parent, so the parent's last view is what matters.\n *\n * Zero-context placeholder turns are also skipped. `executeTurn`\n * synthesizes an assistant turn with `usage: { input: 0, output: 0 }`\n * when the provider stream throws / aborts before any usage is reported\n * (see `src/loop-turn-stream.ts`'s catch path) — that turn is purely a shape\n * contract for resume, not a real context-window measurement. Without\n * the skip, an abort mid-stream shadows the prior real turn and the\n * footer reads `ctx 0` on the next session load even though earlier\n * turns accumulated meaningful context (and `run.cost`).\n *\n * `runs` is optional. Without it depth is unknown, so every assistant turn\n * qualifies.\n *\n * @param turns - Persisted turns in order.\n * @param runs - Runs the turns belong to, used to skip subagent turns.\n */\nexport function lastContextSizeFromTurns(\n turns: SessionTurn[],\n runs: readonly SessionRun[] = [],\n): number {\n const childRunIds = new Set<string>()\n for (const run of runs) {\n if ((run.depth ?? 0) > 0)\n childRunIds.add(run.id)\n }\n for (let i = turns.length - 1; i >= 0; i--) {\n const turn = turns[i]\n if (turn.role !== 'assistant' || !turn.usage)\n continue\n if (turn.runId && childRunIds.has(turn.runId))\n continue\n const size = (turn.usage.input ?? 0)\n + (turn.usage.cacheRead ?? 0)\n + (turn.usage.cacheCreation ?? 0)\n if (size === 0)\n continue\n return size\n }\n return 0\n}\n\n/**\n * Sum provider-reported USD cost across every run in a session. Used to\n * seed the live cost indicator on session activation. Returns 0 when no\n * run carries a `cost` (most providers — only OpenRouter reports today).\n *\n * @param runs - The session's runs.\n */\nexport function sumRunCosts(runs: readonly SessionRun[]): number {\n let total = 0\n for (const run of runs) {\n if (run.cost)\n total += run.cost\n }\n return total\n}\n\n/** What a run readout shows of the run in progress: see {@link runProgress}. */\nexport interface RunProgress {\n /** When the run began (epoch ms, its run record). */\n startedAt: number\n /** Output tokens of the turns it has settled, its subagents' left out (the live count adds parent `turn:end`s). */\n outputTokens: number\n}\n\n/**\n * The session's top-level run in progress: the latest `running` run without\n * a parent (subagent runs share the session).\n *\n * @param runs - The session's runs.\n */\nexport function runInProgress(runs: readonly SessionRun[]): SessionRun | undefined {\n return runs.findLast(run => run.status === 'running' && !run.parentRunId)\n}\n\n/**\n * The top-level run in progress as its agent saved it: when it began and the\n * output its settled turns produced. A window that missed `run:start`\n * (opened or reattached mid-run) starts its run readout from these, so the\n * time and the count don't restart at zero. `undefined` when no top-level\n * run is in progress.\n *\n * @param data - The session's runs and turns.\n */\nexport function runProgress(data: Pick<SessionData, 'runs' | 'turns'>): RunProgress | undefined {\n const run = runInProgress(data.runs)\n if (!run)\n return undefined\n let outputTokens = 0\n for (const turn of data.turns) {\n if (turn.runId === run.id)\n outputTokens += turn.usage?.output ?? 0\n }\n return { startedAt: run.startedAt, outputTokens }\n}\n\n/** Per-model token/spend totals across a session — see {@link usageByModel}. */\nexport interface ModelUsageSummary {\n /** Provider-echoed model id, or `\"unknown\"` for turns that never recorded one. */\n modelId: string\n /** Number of turns on this model. */\n turns: number\n /** Fresh (uncached) input tokens. */\n input: number\n /** Output tokens. */\n output: number\n /** Tokens read from the prompt cache. */\n cacheRead: number\n /** Tokens written to the prompt cache. */\n cacheCreation: number\n /** Summed USD cost across turns that carried one (provider-reported or estimated). */\n cost: number\n /**\n * `false` when at least one turn had no cost figure (no published rate\n * for the model) — `cost` is then a floor, not a total.\n */\n costComplete: boolean\n}\n\n/**\n * Aggregate per-model token + spend totals across every run in a session.\n * Parent and subagent runs alike: each turn carries its own `modelId`, so\n * cost-tiered delegation (cheap spawn workers) shows up as separate rows\n * priced at their own rates. Sorted by cost (desc), then total tokens, so\n * the biggest spender reads first.\n *\n * @param runs - The session's runs.\n */\nexport function usageByModel(runs: readonly SessionRun[]): ModelUsageSummary[] {\n const byModel = new Map<string, ModelUsageSummary>()\n for (const run of runs) {\n for (const u of run.turnUsage ?? []) {\n const key = u.modelId ?? 'unknown'\n let row = byModel.get(key)\n if (!row) {\n row = { modelId: key, turns: 0, input: 0, output: 0, cacheRead: 0, cacheCreation: 0, cost: 0, costComplete: true }\n byModel.set(key, row)\n }\n row.turns += 1\n row.input += u.input\n row.output += u.output\n row.cacheRead += u.cacheRead ?? 0\n row.cacheCreation += u.cacheCreation ?? 0\n if (u.cost !== undefined)\n row.cost += u.cost\n else\n row.costComplete = false\n }\n }\n const totalTokens = (r: ModelUsageSummary) => r.input + r.output + r.cacheRead + r.cacheCreation\n return [...byModel.values()].sort((a, b) => (b.cost - a.cost) || (totalTokens(b) - totalTokens(a)))\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAQA,SAAgB,mBAAmB,QAA0F;CAC3H,QAAQ,QAAR;EACE,KAAK,iBACH,OAAO;GAAE,QAAQ;IAAE,UAAU;IAAQ,OAAO;GAAU;GAAG,MAAM;EAA+B;EAChG,KAAK,iBACH,OAAO;GAAE,QAAQ;IAAE,UAAU;IAAQ,OAAO;GAAe;GAAG,MAAM;EAAmC;EACzG,KAAK,gBACH,OAAO;GAAE,QAAQ;IAAE,UAAU;IAAQ,OAAO;GAAQ;GAAG,MAAM;EAAuC;EACtG,KAAK,sBACH,OAAO;GAAE,QAAQ;IAAE,UAAU;IAAQ,OAAO;GAAqB;GAAG,MAAM;EAAyE;CACvJ;AACF;;;;;;;ACCA,SAAgB,gBAAgB,OAAsB,MAAsD;CAc1G,MAAM,0BAAU,IAAI,IAAwB;CAC5C,KAAK,MAAM,OAAO,MAChB,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,GACrB,QAAQ,IAAI,IAAI,IAAI,GAAG;CAyB3B,MAAM,WAAqB,CAAC;CAC5B,MAAM,yCAAyB,IAAI,IAAyB;CAC5D,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,KAAK;EACjB,IAAI,CAAC,KACH;EACF,MAAM,aAAa,SAAS,QAAQ,GAAG;EACvC,IAAI,cAAc,GAEhB,SAAS,SAAS,aAAa;OAE5B;GASH,MAAM,MAAM,SAAS,SAAS,SAAS;GAEvC,IAAI,EADqB,QAAQ,KAAA,MAAc,uBAAuB,IAAI,GAAG,CAAC,EAAE,QAAQ,KAAK,IAI3F,SAAS,SAAS;GAEpB,SAAS,KAAK,GAAG;GAEjB,IAAI,CAAC,QAAQ,IAAI,GAAG,GAClB,QAAQ,IAAI,KAAK,eAAe,MAAM,KAAK,QAAQ,CAAC;EACxD;EAMA,MAAM,UAAU,uBAAuB,IAAI,GAAG,qBAAK,IAAI,IAAY;EACnE,KAAK,MAAM,SAAS,KAAK,SAIvB,IAAI,MAAM,SAAS,eAAe,SAAS,KAAK,MAAM,IAAI,GACxD,QAAQ,IAAI,MAAM,EAAE;OACjB,IAAI,MAAM,SAAS,eACtB,QAAQ,OAAO,MAAM,MAAM;EAE/B,uBAAuB,IAAI,KAAK,OAAO;CACzC;CACA,OAAO;AACT;;AAGA,SAAS,eAAe,MAAmB,KAAa,UAAyC;CAO/F,MAAM,QAAQ,SAAS,SAAS;CAChC,MAAM,cAAc,QAAQ,IAAI,SAAS,QAAQ,KAAK,KAAA;CACtD,IAAI,iBAAiB;CACrB,IAAI,KAAK,SAAS,QACX;OAAA,MAAM,SAAS,KAAK,SACvB,IAAI,MAAM,SAAS,UAAU,CAAC,MAAM,cAAc,MAAM,KAAK,KAAK,GAAG;GACnE,iBAAiB,MAAM;GACvB;EACF;;CAGJ,OAAO;EACL,IAAI;EACJ,WAAW,KAAK;EAChB,QAAQ;EACR,QAAQ;EACR;EACA,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;CACvC;AACF;;AAGA,SAAgB,aAAa,SAAqE;CAUhG,MAAM,oCAAoB,IAAI,IAAoB;CAQlD,CAPmB,GAAG,QAAQ,OAAO,CAAC,CAAC,CACpC,QAAO,OAAM,EAAE,SAAS,KAAK,CAAC,CAAC,CAC/B,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,SAK1B,CAAC,CAAC,SAAS,GAAG,MAAM,kBAAkB,IAAI,EAAE,IAAI,EAAE,SAAS,SAAS,IAAI,GAAG,CAAC;CACpF,QAAQ,UAAkB,kBAAkB,IAAI,KAAK,KAAK;AAC5D;;AAGA,SAAgB,kBAAkB,OAA2C;CAK3E,MAAM,+BAAe,IAAI,IAAoB;CAC7C,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,SAAS,aAChB;EACF,KAAK,MAAM,SAAS,KAAK,SACvB,IAAI,MAAM,SAAS,aACjB,aAAa,IAAI,MAAM,IAAI,MAAM,IAAI;CAE3C;CACA,OAAO;AACT;;AAWA,SAAgB,gBAAgB,OAAmD;CAIjF,MAAM,iCAAiB,IAAI,IAA4B;CACvD,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,SAAS,QAChB;EACF,KAAK,MAAM,SAAS,KAAK,SAAS;GAChC,IAAI,MAAM,SAAS,eACjB;GACF,MAAM,OAAO,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS,iBAAiB,MAAM,MAAM;GAC5F,MAAM,WAAW,kBAAkB,MAAM,UAAU,QAAQ;GAC3D,eAAe,IAAI,MAAM,QAAQ,WAAW;IAAE;IAAM;GAAS,IAAI,EAAE,KAAK,CAAC;EAC3E;CACF;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,eACd,SACA,UACyC;CACzC,QAAQ,QAAoB;EAC1B,MAAM,SAAS,IAAI,cAAc,QAAQ,IAAI,IAAI,WAAW,IAAI,KAAA;EAChE,OAAO,WAAW,OAAO,SAAS,KAAK,IAAI,SAAS,OAAO,EAAE,IAAI,KAAA;CACnE;AACF;;AAGA,SAAgB,YAAY,SAA2F;CAQrH,QAAQ,cAAgD;EACtD,IAAI,CAAC,WACH,OAAO,CAAC;EACV,MAAM,QAAsB,CAAC;EAC7B,IAAI,SAAiC,QAAQ,IAAI,SAAS;EAC1D,MAAM,uBAAO,IAAI,IAAY;EAC7B,OAAO,QAAQ;GAGb,IAAI,KAAK,IAAI,OAAO,EAAE,GACpB;GACF,KAAK,IAAI,OAAO,EAAE;GAClB,KAAK,OAAO,SAAS,KAAK,GACxB,MAAM,QAAQ,MAAM;GACtB,SAAS,OAAO,cAAc,QAAQ,IAAI,OAAO,WAAW,IAAI,KAAA;EAClE;EACA,OAAO;CACT;AACF;;AAKA,SAAgB,iBAAiB,SAA+E;CAQ9G,MAAM,8BAAc,IAAI,IAA0B;CAClD,KAAK,MAAM,OAAO,QAAQ,OAAO,GAAG;EAClC,IAAI,CAAC,IAAI,aACP;EACF,MAAM,WAAW,YAAY,IAAI,IAAI,WAAW,KAAK,CAAC;EACtD,SAAS,KAAK,GAAG;EACjB,YAAY,IAAI,IAAI,aAAa,QAAQ;CAC3C;CACA,QAAQ,SAAoC;EAC1C,MAAM,SAAS;GAAE,MAAM;GAAG,UAAU;GAAG,WAAW;GAAG,WAAW;GAAG,eAAe;EAAE;EACpF,MAAM,QAAQ,CAAC,IAAI;EACnB,MAAM,uBAAO,IAAI,IAAY;EAC7B,OAAO,MAAM,SAAS,GAAG;GACvB,MAAM,MAAM,MAAM,IAAI;GACtB,IAAI,KAAK,IAAI,IAAI,EAAE,GACjB;GACF,KAAK,IAAI,IAAI,EAAE;GACf,OAAO,QAAQ,IAAI,QAAQ,IAAI,WAAW,QAAQ,KAAK,MAAM,OAAO,EAAE,QAAQ,IAAI,CAAC,KAAK;GACxF,OAAO,YAAY,IAAI,YAAY,IAAI,YAAY,SAAS;GAC5D,OAAO,aAAa,IAAI,aAAa,IAAI,YAAY,UAAU;GAC/D,OAAO,aAAa,IAAI,YAAY,aAAa;GACjD,OAAO,iBAAiB,IAAI,YAAY,iBAAiB;GACzD,MAAM,KAAK,GAAI,YAAY,IAAI,IAAI,EAAE,KAAK,CAAC,CAAE;EAC/C;EACA,OAAO;CACT;AACF;;AAGA,SAAgB,cAAc,KAAiB,QAAuB,UAAqC,eAAqC;CAM9I,MAAM,QAAQ,iBAAiB;EAC7B,SAAS,OAAO;EAChB,UAAU,OAAO;EACjB,gBAAgB,OAAO;EACvB,oBAAoB,OAAO;CAC7B,CAAC;CAMD,MAAM,MAAoB;EACxB,QAAQ,IAAI,WAAW,aAAa,IAAI,WAAW,UAAU,IAAI,SAAS;EAC1E,GAAI,IAAI,YAAY,KAAA,IAAY,EAAE,YAAY,IAAI,UAAU,IAAI,UAAU,IAAI,CAAC;EAC/E,GAAI,OAAO,OAAO,IAAI,EAAE,SAAS,OAAO,KAAK,IAAI,CAAC;EAClD,UAAU,OAAO,WAAW,OAAO,YAAY,OAAO;EACtD,WAAW,OAAO;CACpB;CACA,MAAM,QAAQ,IAAI,WAAW,MAAK,MAAK,EAAE,OAAO,CAAC,EAAE;CACnD,MAAM,QAAQ,IAAI,SAAS,IAAI,WAAW;CAC1C,OAAO;EACL,MAAM;EACN,MAAM,aAAa,KAAK,KAAK;EAC7B,SAAS,SAAS,IAAI,EAAE;EACxB,OAAO,IAAI,SAAS;EACpB,OAAO;GACL,WAAW,IAAI;GACf,MAAM,YAAY,IAAI,QAAQ,EAAE;GAChC,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;GACvC,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;GACzC;EACF;EACA,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC3B;AACF;;AAGA,SAAgB,gBAAgB,KAAiB,UAAqC,eAAqC;CAMzH,MAAM,cAAc,YAAY,IAAI,QAAQ,EAAE;CAK9C,MAAM,QAAQ,IAAI,WAAW,MAAK,MAAK,EAAE,OAAO,CAAC,EAAE;CAGnD,MAAM,UAAU,IAAI,mBAAmB,SAAS,IAAI,gBAAgB,IAAI,KAAA;CACxE,OAAO;EACL,MAAM;EACN,MAAM;EACN,SAAS,SAAS,IAAI,EAAE;EACxB,OAAO,IAAI,SAAS;EACpB,OAAO;GACL,WAAW,IAAI;GACf,MAAM;GACN,QAAQ,YAAY,IAAI,MAAM;GAC9B,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;GAC7B,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;GACzC,GAAI,IAAI,eAAe,EAAE,QAAQ,IAAI,aAAa,IAAI,CAAC;EACzD;EACA,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC3B;AACF;;;;;;;AAQA,SAAgB,gBAAgB,QAAuB,OAAsB,MAA6B,YAAqC;CAS7I,MAAM,kCAAkB,IAAI,IAAoB;CAChD,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,OACP,gBAAgB,IAAI,KAAK,OAAO,KAAK,EAAE;CAE3C,MAAM,mCAAmB,IAAI,IAA2B;CACxD,IAAI;CACJ,KAAK,MAAM,OAAO,MAAM;EACtB,IAAI,IAAI,gBAAgB,KAAA,GACtB;EAEF,MAAM,WAAW;EACjB,IAAI,IAAI,OACN,mBAAmB;EACrB,IAAI,IAAI,YAAY,KAAA,GAClB;EACF,MAAM,aAAa,gBAAgB,IAAI,IAAI,EAAE;EAC7C,IAAI,CAAC,YACH;EACF,MAAM,SAAwB,CAAC;EAC/B,IAAI,IAAI,WAAW,WAAW,IAAI,OAChC,OAAO,KAAK;GAAE,MAAM;GAAS,MAAM,IAAI;GAAO,GAAI,IAAI,cAAc,EAAE,QAAQ,IAAI,YAAY,IAAI,CAAC;GAAI,QAAQ;EAAW,CAAC;EAC7H,MAAM,UAAU,kBAAkB,KAAK,KAAK,IAAI,GAAG,QAAQ;EAC3D,IAAI,cAAc,OAAO,GACvB,OAAO,KAAK;GAAE,MAAM;GAAe,MAAM,qBAAqB,OAAO;GAAG,YAAY;GAAS,QAAQ;EAAW,CAAC;EACnH,IAAI,OAAO,SAAS,GAClB,iBAAiB,IAAI,YAAY,MAAM;CAC3C;CACA,IAAI,iBAAiB,SAAS,GAC5B,OAAO;CAGT,MAAM,oCAAoB,IAAI,IAA2B;CACzD,MAAM,kCAAkB,IAAI,IAAoB;CAChD,OAAO,SAAS,GAAG,QAAQ;EACzB,IAAI,EAAE,UAAU,iBAAiB,IAAI,EAAE,MAAM,GAC3C,gBAAgB,IAAI,EAAE,QAAQ,GAAG;CACrC,CAAC;CACD,IAAI,gBAAgB,SAAS,GAC3B,OAAO;CACT,KAAK,MAAM,CAAC,QAAQ,QAAQ,iBAC1B,kBAAkB,IAAI,KAAK,iBAAiB,IAAI,MAAM,CAAE;CAG1D,MAAM,MAAqB,CAAC;CAC5B,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,OAAO,IAAI,WAAW,UAAU,WAAW,MAAO,GAChD,WAAW,OAAO,IAAI;EACxB,IAAI,KAAK,OAAO,EAAG;EACnB,MAAM,SAAS,kBAAkB,IAAI,CAAC;EACtC,IAAI,QACF,IAAI,KAAK,GAAG,MAAM;CACtB;CACA,OAAO,IAAI,WAAW,QACpB,WAAW,OAAO,IAAI;CACxB,OAAO;AACT;;;ACvZA,SAAS,eAAe,MAAoB;CAC1C,MAAM,MAAM,QAAQ,IAAI;CACxB,IAAI,WAAW,GAAG,GAChB;CACF,IAAI;EACF,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;CACpC,SACO,KAAK;EACV,MAAM,IAAI,MACR,4CAA4C,IAAI,yHAEK,aAAa,GAAG,GACvE;CACF;AACF;;;;;;AAuFA,SAAgB,iBAAiB,MAA6B;CAC5D,OAAO;EACL,YAAY,UAAU,IAAI;EAC1B,OAAM,UAAS,UAAU,MAAM,KAAK;EACpC;CACF;AACF;;;;;;AAOA,SAAgB,UAAU,MAAwB;CAChD,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO,CAAC;CACV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,MAAM,OAAO,CAAC;EACrD,IAAI,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GAC/D,OAAO,iBAAiB,MAAoD;CAChF,QACM,CAEN;CACA,OAAO,CAAC;AACV;;AAGA,SAAS,iBAAiB,OAA6D;CACrF,MAAM,EAAE,mBAAmB,QAAQ,GAAG,SAAS;CAC/C,IAAI,KAAK,uBAAuB,KAAA,KAAa,OAAO,WAAW,UAC7D,OAAO;EAAE,GAAG;EAAM,oBAAoB;CAAO;CAC/C,OAAO;AACT;;;;;;;AAQA,SAAgB,UAAU,MAAc,OAAuB;CAC7D,eAAe,IAAI;CACnB,gBAAgB,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AACtD;;;;;;;;;;;;;;;;AAyBA,eAAsB,gBACpB,OACA,QASwB;CAKxB,IAAI,MAAM,UACR,IAAI;EAEF,QAAO,MADY,MAAM,SAAS,MAAM,EAAA,CAC5B,QAAO,QAAO,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW;CACzE,SACO,KAAK;EACV,IAAI,QAAQ,IAAI,cAAc;GAC5B,MAAM,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAC7D,QAAQ,OAAO,MAAM,oEAAoE,MAAM,GAAG;EACpG;CACF;CAEF,MAAM,MAAM,MAAM,MAAM,KAAK,MAAM;CACnC,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,IAAI,OAAO,OAAO;EAC7D,MAAM,OAAO,MAAM,MAAM,KAAK,EAAE;EAChC,OAAO,QAAQ,CAAC,cAAc,KAAK,QAAQ,IAAI,aAAa,IAAI,IAAI,IAAI;CAC1E,CAAC,CAAC;CACF,MAAM,QAAuB,CAAC;CAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,QAAQ;EACvB,IAAI,OAAO,WAAW,eAAe,OAAO,OAC1C,MAAM,KAAK,OAAO,KAAK;OAEpB,IAAI,OAAO,WAAW,cAAc,QAAQ,IAAI,cAAc;GACjE,MAAM,QAAQ,OAAO,kBAAkB,QAAQ,OAAO,OAAO,UAAU,OAAO,OAAO,MAAM;GAC3F,QAAQ,OAAO,MAAM,yCAAyC,IAAI,GAAG,KAAK,MAAM,GAAG;EACrF;CACF;CACA,OAAO;AACT;;AAGA,SAAS,YAAY,KAAkC;CACrD,OAAO;EACL,IAAI,IAAI;EACR,OAAO,mBAAmB,IAAI,gBAAgB,CAAC,IAAI,aAAa,IAAI,CAAC,GAAG,IAAI,QAAQ;EACpF,WAAW,IAAI;EACf,kBAAkB,IAAI;EACtB,UAAU,IAAI;EACd,GAAI,cAAc,IAAI,QAAQ,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;EACtD,GAAG,UAAU,IAAI,QAAQ;EACzB,GAAI,IAAI,UAAU,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;EAC5D,GAAI,IAAI,cAAc,EAAE,aAAa,IAAI,YAAY,IAAI,CAAC;EAC1D,GAAG,QAAQ,IAAI,QAAQ;EACvB,GAAG,gBAAgB,IAAI,QAAQ;EAC/B,GAAI,OAAO,IAAI,kBAAkB,WAAW,EAAE,eAAe,IAAI,cAAc,IAAI,CAAC;EACpF,GAAG,WAAW,IAAI,QAAQ;EAC1B,WAAW,IAAI;CACjB;AACF;;AAGA,SAAS,aAAa,IAAY,MAAgC;CAChE,OAAO;EACL;EACA,OAAO,mBAAmB,KAAK,OAAO,KAAK,QAAQ;EAEnD,WAAW,KAAK,MAAM,QAAQ,GAAG,MAAM,EAAE,SAAS,WAAW,IAAI,IAAI,GAAG,CAAC;EACzE,kBAAkB,KAAK,MAAM,QAAQ,GAAG,MAAM,EAAE,SAAS,SAAS,IAAI,IAAI,GAAG,CAAC;EAC9E,UAAU,KAAK,KAAK;EACpB,GAAI,cAAc,KAAK,QAAQ,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;EACvD,GAAG,UAAU,KAAK,QAAQ;EAC1B,GAAI,KAAK,UAAU,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;EAC7D,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;EAC5D,GAAG,QAAQ,KAAK,QAAQ;EACxB,GAAG,gBAAgB,KAAK,QAAQ;EAChC,GAAG,WAAW,KAAK,QAAQ;EAC3B,WAAW,KAAK;CAClB;AACF;;AAGA,SAAS,WAAW,UAAmF;CACrG,MAAM,SAAS,kBAAkB,QAAQ;CACzC,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;AACxD;;AAGA,SAAS,UAAU,UAAqE;CACtF,MAAM,UAAU,mBAAmB,QAAQ;CAC3C,OAAO,UAAU,EAAE,QAAQ,IAAI,CAAC;AAClC;;;;;;AAOA,SAAgB,0BAA0B,UAAsF;CAC9H,IAAI,CAAC,WAAA,gBACH,OAAO,KAAA;CACT,MAAM,cAAc,uBAAuB,QAAQ;CACnD,IAAI,YAAY,SAAS,kBAAkB,QAAQ,YAAY,UAAU,SACvE,OAAO,KAAA;CACT,OAAO;EACL,MAAM,YAAY;EAClB,OAAO,YAAY;EACnB,GAAI,YAAY,SAAS,EAAE,QAAQ,YAAY,OAAO,IAAI,CAAC;EAC3D,GAAI,YAAY,QAAQ,EAAE,OAAO,YAAY,MAAM,IAAI,CAAC;EACxD,GAAI,YAAY,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;EACnD,GAAI,YAAY,UAAU,EAAE,eAAe,YAAY,QAAQ,IAAI,CAAC;CACtE;AACF;AAEA,SAAS,gBAAgB,UAA4F;CACnH,MAAM,cAAc,0BAA0B,QAAQ;CACtD,OAAO,cAAc,EAAE,YAAY,IAAI,CAAC;AAC1C;AAEA,SAAS,QAAQ,UAAiE;CAChF,MAAM,MAAM,UAAU;CACtB,OAAO,OAAO,QAAQ,YAAY,IAAI,SAAS,IAAI,EAAE,IAAI,IAAI,CAAC;AAChE;;;;;;;;;;;AAYA,eAAsB,eAAe,OAAqB,IAAyC;CACjG,IAAI,MAAM,SACR,IAAI;EACF,MAAM,MAAM,MAAM,MAAM,QAAQ,EAAE;EAClC,OAAO,MAAM,YAAY,GAAG,IAAI;CAClC,SACO,KAAK;EACV,IAAI,QAAQ,IAAI,cAAc;GAC5B,MAAM,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAC7D,QAAQ,OAAO,MAAM,oEAAoE,MAAM,GAAG;EACpG;CACF;CAEF,MAAM,OAAO,MAAM,MAAM,KAAK,EAAE;CAChC,OAAO,OAAO,aAAa,IAAI,IAAI,IAAI;AACzC;;;;;;;;;;;AAeA,eAAsB,kBAAkB,OAAqB,IAA+C;CAC1G,IAAI,MAAM,SACR,IAAI;EACF,OAAO,MAAM,MAAM,QAAQ,EAAE;CAC/B,SACO,KAAK;EACV,IAAI,QAAQ,IAAI,cACd,QAAQ,OAAO,MAAM,oEAAoE,aAAa,GAAG,EAAE,GAAG;CAClH;CAEF,OAAO,MAAM,MAAM,KAAK,EAAE;AAC5B;;;;;;AAOA,SAAgB,eAAe,MAAkC;CAC/D,OAAO;EACL,GAAG,aAAa,KAAK,IAAI,IAAI;EAC7B,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;EAChD,QAAQ,KAAK;EACb,UAAU,KAAK;EACf,WAAW,KAAK;CAClB;AACF;;;;;;;;;AAUA,eAAsB,iBAAiB,OAAqB,IAA2C;CACrG,MAAM,MAAM,MAAM,UAAU,MAAM,MAAM,QAAQ,EAAE,CAAC,CAAC,YAAY,IAAI,IAAI;CACxE,MAAM,SAAS,OAAO,KAAK,SAAS,UAAU,YAAY,IAAI,SAAS,MAAM,KAAK,MAAM;CACxF,IAAI,OAAO,IAAI,WAAW,KAAA,MAAc,UAAU,IAAI,kBAAkB,KAAA,KAAa,IAAI,qBAAqB,IAC5G,OAAO;EACL,GAAG,YAAY,GAAG;EAClB,GAAI,IAAI,UAAU,EAAE,SAAS,IAAI,QAAQ,IAAI,CAAC;EAC9C,QAAQ,IAAI;EACZ,UAAU,IAAI;EACd,GAAI,IAAI,cAAc,KAAA,IAAY,EAAE,WAAW,IAAI,UAAU,IAAI,CAAC;CACpE;CAEF,MAAM,OAAO,MAAM,MAAM,KAAK,EAAE;CAChC,OAAO,OAAO,eAAe;EAAE,GAAG;EAAM;CAAG,CAAC,IAAI;AAClD;;;;;;AAOA,SAAgB,eAAe,OAAqC;CAClE,MAAM,QAAQ,MAAM,MAAK,MAAK,EAAE,SAAS,MAAM;CAC/C,IAAI,CAAC,OACH,OAAO;CACT,KAAK,MAAM,SAAS,MAAM,SAAS;EACjC,MAAM,QAAQ,MAAM,SAAS,UAAU,CAAC,MAAM,aAAa,cAAc,MAAM,IAAI,IAAI;EACvF,IAAI,OACF,OAAO;CACX;CACA,OAAO;AACT;;;;;;;AAQA,MAAa,wBAAwB;;;;;;;;;;;;;;;AAgBrC,SAAgB,mBACd,OACA,UACQ;CACR,MAAM,SAAS,OAAO,UAAU,UAAU,WAAW,aAAa,SAAS,KAAK,IAAI;CACpF,IAAI,OAAO,SAAS,GAClB,OAAO;CACT,OAAO,eAAe,KAAK,KAAA;AAC7B;;;;;;;;;;;;;AAcA,SAAgB,oBACd,OACA,QACa;CACb,OAAO;EACL,MAAM;EACN,MAAM,MAAM;EACZ,SAAS;GACP,eAAe,MAAM,gBAAgB;GACrC,OAAO,MAAM;GACb,GAAI,MAAM,MAAM,WAAW,EAAE,aAAa,MAAM,MAAM,SAAS,IAAI,CAAC;GACpE,aAAa,MAAM;GACnB,aAAa,MAAM,MAAM,SAAS;GAClC,cAAc,MAAM,MAAM,UAAU;GACpC,iBAAiB,MAAM,MAAM,aAAa;GAC1C,qBAAqB,MAAM,MAAM,iBAAiB;GAClD,GAAI,OAAO,MAAM,MAAM,SAAS,YAAY,MAAM,MAAM,OAAO,IAAI,EAAE,SAAS,MAAM,MAAM,KAAK,IAAI,CAAC;EACtG;EACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;CAC7B;AACF;;;;;;;AAQA,SAAS,kBAAkB,MAAsB;CAC/C,MAAM,UAAU,KAAK,SAAS,IAAI,IAAI,IAAI,KAAK,SAAS,GAAG,IAAI,IAAI;CACnE,OAAO,KAAK,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI;AAC3C;;AAGA,MAAM,oCAAoB,IAAI,IAAI;CAAC;CAAQ;CAAQ;AAAO,CAAC;;;;;;AAgB3D,SAAS,eAAe,OAAwC;CAC9D,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAC5D,OAAO;CACT,MAAM,EAAE,UAAU,OAAO,SAAS,UAAU;CAM5C,IAAI,OAAO,aAAa,YAAY,CAAC,kBAAkB,IAAI,QAAQ,GACjE,OAAO;CACT,IAAI,OAAO,UAAU,YAAY,UAAU,IACzC,OAAO;CACT,OAAO;EACL,QAAQ;GAAY;GAA4D;EAAM;EACtF,GAAI,OAAO,YAAY,YAAY,YAAY,KAAK,EAAE,QAAQ,IAAI,CAAC;EACnE,GAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,EAAE,OAAO,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC;CAC1G;AACF;;AAGA,SAAS,gBAAgB,OAA+D;CACtF,IAAI,MAAM,SAAS,eACjB,OAAO;CACT,MAAM,OAAO,MAAM,UAAU;CAC7B,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACzD,OAAO;CACT,OAAO,eAAgB,KAAiC,MAAM;AAChE;;;;;;;;;;;;;;AAeA,SAAgB,kBACd,QACA,MACA,SAA+C,CAAC,GACxB;CACxB,OAAO,CAAC;EACN,MAAM;EACN,QAAQ,UAAU,OAAO,WAAW;EACpC,QAAQ;EACR,UAAU,EACR,SAAS,EACP,QAAQ;GACN,UAAU,OAAO;GACjB,OAAO,OAAO;GACd,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;GACpD,GAAI,OAAO,UAAU,KAAA,IAAY,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;EAC9D,EACF,EACF;CACF,CAAC;AACH;;AAsBA,SAAS,kBAAkB,MAAmB,OAAiF;CAG7H,MAAM,cAAmE,CAAC;CAC1E,KAAK,MAAM,WAAW,KAAK,SACzB,IAAI,QAAQ,SAAS,WAAW,QAAQ,SAAS,WAAW,QAAQ,SAAS,SAC3E,YAAY,KAAK;EACf,MAAM,QAAQ,QAAQ,QAAQ;EAC9B,WAAW,QAAQ;EACnB,MAAM,OAAO,QAAQ,SAAS,WAC1B,kBAAkB,QAAQ,IAAI,IAC9B;CACN,CAAC;MAEE,IAAI,QAAQ,SAAS,YAMxB,YAAY,KAAK;EACf,MAAM,QAAQ,QAAQ;EACtB,WAAW,QAAQ;EACnB,MAAM,OAAO,QAAQ,SAAS,WAC1B,IACA,QAAQ,aAAa,SACnB,OAAO,WAAW,QAAQ,IAAI,IAC9B,kBAAkB,QAAQ,IAAI;CACtC,CAAC;MAEE,IAAI,YAAY,SAAS,QAAQ,SAAS,QAAQ;EACrD,MAAM,IAAI,QAAQ,KAAK,MAAM,gEAAgE;EAC7F,IAAI,GACF,YAAY,KAAK;GACf,MAAM,EAAE,MAAM;GACd,WAAW,EAAE,MAAM;GACnB,MAAM,QAAQ,KAAK;EACrB,CAAC;CAEL;CAEF,OAAO;AACT;;AAGA,SAAS,eACP,OACA,MACA,OACA,OACA,KACA,QACM;CACN,MAAM,EAAE,WAAW;CAGnB,IAAI,kBAAkB,KAAK,GACzB;CAaF,MAAM,YAAY,2BAA2B,MAAM,MAAM,GAAG;CAC5D,IAAI,WAAW;EACb,OAAO,KAAK,SAAS;EACrB;CACF;CAOA,MAAM,eAAe,qBAAqB,MAAM,IAAI;CACpD,IAAI,cAAc;EAChB,OAAO,KAAK;GAAE,MAAM;GAAiB,MAAM,aAAa;GAAS;GAAc,GAAG;EAAI,CAAC;EACvF;CACF;CASA,IAAI,UAAU,GAAG;EAOf,MAAM,gBAAgB,KAAK,QAAQ,MAAM,QAAQ,IAAI,KAAK,KAAK,CAAC,EAAE,SAAS,KAAA;EAC3E,IAAI,eAAe,SAAS,WAAW;GACrC,OAAO,KAAK;IACV,MAAM;IACN,OAAO,cAAc,UAAU,iBAAiB,cAAc,OAAO,IAAI;IACzE,MAAM,MAAM;IACZ,GAAG;GACL,CAAC;GACD,MAAM,gBAAgB,KAAK;GAC3B;EACF;EACA,IAAI,KAAK,YAAY,KAAA,KAAa,CAAC,KAAK,OAAO;GAC7C,IAAI,CAAC,OAAO,WAAW,KAAK,YAAY,IACtC,OAAO,KAAK;IAAE,MAAM;IAAgB,MAAM,gBAAgB,KAAK,SAAS,MAAM,MAAM,MAAM,qBAAqB,KAAA,CAAS;IAAG,GAAG;GAAI,CAAC;GACrI,OAAO,UAAU;GACjB;EACF;EACA,MAAM,oBAAoB;EAS1B,IAAI,MAAM,wBAAwB,GAChC,OAAO,KAAK;GAAE,MAAM;GAAa,MAAM;EAAG,CAAC;EAC7C,MAAM,gBAAgB,KAAK;EAE3B,MAAM,cAAc,kBAAkB,MAAM,KAAK;EAGjD,MAAM,OAAO,gBAAgB,MAAM,IAAI;EACvC,OAAO,KAAK;GACV,MAAM;GACN,MAAM,MAAM;GACZ,QAAQ,KAAK;GACb,GAAI,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,CAAC;GAClC,GAAI,YAAY,SAAS,IAAI,EAAE,YAAY,IAAI,CAAC;GAChD,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;EACjD,CAAC;CACH;AACF;;AAGA,SAAS,eAAe,OAAoB,MAAmB,OAAe,KAAsB;CAClG,MAAM,EAAE,WAAW;CAGnB,IAAI,KAAK,UAAU;EACjB,MAAM,MAAM,GAAG,KAAK,SAAS,GAAG,QAAQ,KAAK;EAC7C,IAAI,CAAC,MAAM,gBAAgB,IAAI,GAAG,GAAG;GACnC,MAAM,gBAAgB,IAAI,GAAG;GAC7B,MAAM,EAAE,QAAQ,SAAS,mBAAmB,KAAK,QAAQ;GACzD,OAAO,KAAK;IAAE,MAAM;IAAQ;IAAM;IAAQ,GAAG;GAAI,CAAC;EACpD;EACA;CACF;CAGA,MAAM,SAAS,EAAE,SAAS,MAAM;CAGhC,MAAM,iBAFiB,CAAC,KAAK,QAAQ,MAAK,UAAS,MAAM,SAAS,UAAU,CAAC,MAAM,cAAc,MAAM,KAAK,KAAK,CAAC,KAC7G,KAAK,QAAQ,MAAK,UAAS;EAAC;EAAY;EAAS;EAAS;CAAO,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,IAExF,CAAC;EAAE,MAAM;EAAQ,MAAM;CAAe,GAAG,GAAG,KAAK,OAAO,IACxD,KAAK;CACT,KAAK,MAAM,SAAS,gBAClB,IAAI,MAAM,SAAS,WAAW,MAAM,KAAK,KAAK,KAAK,MAAM,YAAY,QACnE,eAAe,OAAO,MAAM,OAAO,OAAO,KAAK,MAAM;MAElD,IAAI,MAAM,SAAS,eAAe;EACrC,MAAM,OAAO,MAAM,aAAa,IAAI,MAAM,MAAM;EAKhD,MAAM,MAAM,eAAe,MAAM,MAAM;EACvC,MAAM,OAAO,SAAS,UAAU,qBAAqB,GAAG,IAAI;EAE5D,IAAI,MAAM,OAAO,QACf,OAAO,KAAK,GAAG,mBAAmB,MAAM,OAAO,MAAM,QAAQ,GAAG,CAAC;EACnE,OAAO,KAAK;GACV,MAAM;GACN;GACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;GACvB,QAAQ,MAAM;GAEd,GAAI,MAAM,UAAU,EAAE,SAAS,KAAc,IAAI,CAAC;GAClD,GAAI,MAAM,eAAe,KAAA,IAAY,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;GACzE,GAAG;EACL,CAAC;CACH,OACK,IAAI,MAAM,SAAS,mBAStB,OAAO,KAAK,oBAAoB,OAAO,KAAK,EAAE,CAAC;AAGrD;;AAGA,SAAS,uBAAuB,OAA8D,KAA6B;CACzH,MAAM,OAAO,MAAM,UAAU;CAC7B,MAAM,cAAe,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,IACxE,OACA,KAAA;CAKJ,MAAM,kBAAkB,eAAe,aAAa,MAAM;CAC1D,IAAI,iBACF,OAAO;EACL,MAAM,gBAAgB,OAAO,aAAa,UAAU,UAAU;EAC9D,MAAM,eAAe,MAAM,MAAM;EACjC,QAAQ,gBAAgB;EACxB,GAAG;EAIH,GAAI,gBAAgB,UAAU,EAAE,SAAS,gBAAgB,QAAQ,IAAI,CAAC;EACtE,GAAI,gBAAgB,UAAU,KAAA,IAAY,EAAE,OAAO,gBAAgB,MAAM,IAAI,CAAC;CAChF;CAIF,MAAM,aAAa,aAAa;CAChC,IAAI,cAAc,OAAO,eAAe,YAAY,CAAC,MAAM,QAAQ,UAAU,KACxE,OAAQ,WAAsC,aAAa,UAAU;EAIxE,MAAM,QAAQ;EACd,OAAO;GACL,MAAM;GACN,MAAM,eAAe,MAAM,MAAM;GACjC,QAAQ;IAAE,UAAU,MAAM;IAAU,GAAI,MAAM,SAAS,KAAA,IAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;GAAG;GAC9F,GAAG;EACL;CACF;CACA,MAAM,QAAQ,OAAO,aAAa,UAAU,WAAW,YAAY,QAAQ,KAAA;CAC3E,OAAO;EACL,MAAM;EACN,MAAM,eAAe,MAAM,MAAM;EACjC,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EACzB,GAAI,aAAa,WAAW,SAAS,EAAE,QAAQ,OAAgB,IAAI,CAAC;EACpE,GAAG;CACL;AACF;;AAGA,SAAS,kBAAkB,OAAoB,MAAmB,KAAsB;CACtF,MAAM,EAAE,WAAW;CAiBnB,MAAM,aAAa,KAAK,QAAQ,SAAS,KAAK,KAAK,QAAQ,OAAM,UAAS,gBAAgB,KAAK,MAAM,IAAI;CACzG,MAAM,QAAQ,KAAK,QAAQ;CAC3B,MAAM,aAAa,OAAO,SAAS,SAAS,mBAAmB,MAAM,IAAI,IAAI;CAC7E,IAAI,eAAe,MACjB,MAAM,oBAAoB;CAC5B,IAAI,MAAM,wBAAwB,KAAK,CAAC,eAAe,eAAe,QAAQ,MAAM,sBAAsB,OACxG,OAAO,KAAK;EAAE,MAAM;EAAa,MAAM;CAAG,CAAC;CAC7C,KAAK,MAAM,SAAS,KAAK,SACvB,IAAI,eAAe,QAAQ,UAAU,OACnC,OAAO,KAAK;EAAE,MAAM;EAAe,MAAM;EAAY,WAAW;EAAM,QAAQ,KAAK;CAAG,CAAC;MAEpF,IAAI,MAAM,SAAS,UAAU,MAAM,KAAK,KAAK,GAChD,OAAO,KAAK;EAAE,MAAM;EAAY,MAAM,MAAM;EAAM,WAAW;EAAO,GAAG;CAAI,CAAC;MAEzE,IAAI,MAAM,SAAS,eACtB,OAAO,KAAK,uBAAuB,OAAO,GAAG,CAAC;AAGpD;;AAGA,SAAS,cACP,OACA,gBACA,KACa;CAOb,MAAM,EAAE,MAAM,UADA,eAAe,MAAM,MAAM,MAAM,KACnB,KAAK;CAMjC,IAAI,OAAO,mBAAmB,MAAM,KAAK;CACzC,IAAI,MAAM;EAMR,MAAM,aAAa,eAAe,IAAI,MAAM,EAAE,CAAC,EAAE;EACjD,IAAI,YAAY;GACd,MAAM,WAAW,4BAA4B,UAAU;GACvD,IAAI,YAAY,SAAS,WAAW,KAAK,MAAM,QAC7C,OAAO;IAAE,GAAG;IAAM;GAAS;EAC/B;CACF;CAEA,MAAM,WAAW,eAAe,IAAI,MAAM,EAAE,CAAC,EAAE;CAC/C,OAAO;EACL,MAAM;EACN,MAAM,gBAAgB,MAAM,KAAK;EACjC,MAAM;EACN;EACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;EACvB,QAAQ,MAAM;EACd,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EAC/B,GAAG;CACL;AACF;;AAGA,SAAS,oBAAoB,OAAoB,MAAmB,KAAsB;CACxF,MAAM,EAAE,WAAW;CAInB,KAAK,MAAM,SAAS,eAAe,IAAI,GACrC,IAAI,MAAM,SAAS,UAAU,MAAM,KAAK,KAAK,GAG3C,OAAO,KAAK;EAAE,MAAM;EAAY,MAAM,MAAM;EAAM,WAAW;EAAO,GAAG;CAAI,CAAC;MAEzE,IAAI,MAAM,SAAS,cAAc,MAAM,KAAK,KAAK,GAY/C;OAAA,MAAM,QAAQ,MAAM,KAAK,MAAM,IAAI,GACtC,IAAI,KAAK,KAAK,GACZ,OAAO,KAAK;GAAE,MAAM;GAAY,MAAM;GAAM,GAAG;EAAI,CAAC;CAAA,OAGrD,IAAI,MAAM,SAAS,aACtB,OAAO,KAAK,cAAc,OAAO,MAAM,gBAAgB,GAAG,CAAC;MAExD,IAAI,MAAM,SAAS,mBAItB,OAAO,KAAK;EACV,MAAM;EACN,MAAM,gBAAgB,MAAM,MAAM,MAAM,KAAK;EAC7C,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,GAAG;CACL,CAAC;MAEE,IAAI,MAAM,SAAS,sBACtB,OAAO,KAAK;EACV,MAAM;EACN,MAAM,wBAAwB,MAAM,OAAO;EAC3C,MAAM,MAAM;EACZ,QAAQ,MAAM;EACd,GAAG;CACL,CAAC;AAGP;;;;;;;;;AAUA,SAAS,kBAAkB,OAAoB,MAAyB;CACtE,MAAM,QAAQ,KAAK;CACnB,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,eACzC;CACF,MAAM,gBAAgB,MAAM,kBAAkB,KAAA,KACzC,MAAM,QAAQ,IAAI,KAAK,CAAC,EAAE,QAAQ,SAAS,aAC3C,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,SAAS;CACnC,MAAM,gBAAgB;CACtB,IAAI,eACF,MAAM,OAAO,KAAK;EAAE,MAAM;EAAa,MAAM;CAAG,CAAC;AACrD;;;;;;;;;;;;;;;;;AAkBA,SAAgB,gBACd,OACA,OAA8B,CAAC,GAChB;CACf,OAAO,YAAY,OAAO,IAAI,CAAC,CAAC;AAClC;;;;;;;;;;;;;AAcA,SAAgB,YACd,OACA,MACiD;CACjD,MAAM,UAAU,gBAAgB,OAAO,IAAI;CAC3C,MAAM,WAAW,aAAa,OAAO;CACrC,MAAM,eAAe,kBAAkB,KAAK;CAC5C,MAAM,iBAAiB,gBAAgB,KAAK;CAC5C,MAAM,aAAa,YAAY,OAAO;CACtC,MAAM,gBAAgB,iBAAiB,OAAO;CAC9C,MAAM,YAAY,eAAe,SAAS,QAAQ;CAQlD,MAAM,cAAc,MAAM,KAAI,SAAQ,WAAW,KAAK,KAAK,CAAC;CAC5D,MAAM,kCAAkB,IAAI,IAAoB;CAChD,YAAY,SAAS,OAAO,QAAQ;EAClC,KAAK,MAAM,OAAO,OAChB,gBAAgB,IAAI,IAAI,IAAI,GAAG;CACnC,CAAC;CAED,MAAM,SAAwB,CAAC;;CAE/B,MAAM,8BAAc,IAAI,IAAY;;CAEpC,MAAM,WAAyB,CAAC;CAChC,MAAM,QAAqB;EAAE;EAAQ;EAAS;EAAc;EAAgB,qBAAqB;EAAI,mBAAmB;EAAM,iCAAiB,IAAI,IAAI;CAAE;CAEzJ,MAAM,gBAAgB,QAAoB;EACxC,OAAO,KAAK,cAAc,KAAK,cAAc,GAAG,GAAG,UAAU,UAAU,GAAG,CAAC,CAAC;CAC9E;CAEA,MAAM,kBAAkB,QAAoB;EAC1C,OAAO,KAAK,gBAAgB,KAAK,UAAU,UAAU,GAAG,CAAC,CAAC;CAC5D;;;;;;;CAQA,MAAM,qBAAqB,eAAuB;EAChD,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;GAC7C,MAAM,MAAM,SAAS;GAIrB,IAAI,IAAI,WAAW,WACjB;GACF,KAAK,gBAAgB,IAAI,IAAI,EAAE,KAAK,MAAM,YAAY;IACpD,SAAS,OAAO,GAAG,CAAC;IACpB,aAAa,GAAG;GAClB;EACF;CACF;CAEA,MAAM,aAAuB,CAAC;CAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,WAAW,KAAK,OAAO,MAAM;EAC7B,MAAM,OAAO,MAAM;EACnB,MAAM,cAAc,YAAY;EAChC,MAAM,QAAQ,YAAY;EAE1B,kBAAkB,CAAC;EAEnB,KAAK,MAAM,OAAO,aAAa;GAC7B,IAAI,YAAY,IAAI,IAAI,EAAE,GACxB;GACF,YAAY,IAAI,IAAI,EAAE;GACtB,SAAS,KAAK,GAAG;GACjB,eAAe,GAAG;EACpB;EAEA,MAAM,cAAc,QAAQ,KAAK,KAAK,QAAQ;GAAE,SAAS,SAAS,KAAK,KAAK;GAAG;EAAM,IAAI,KAAA;EAKzF,MAAM,MAAM;GAAE,QAAQ,KAAK;GAAI,GAAG;EAAY;EAE9C,IAAI,KAAK,SAAS,QAAQ;GACxB,eAAe,OAAO,MAAM,OAAO,GAAG;GACtC,MAAM,sBAAsB;GAC5B;EACF;EAEA,IAAI,KAAK,SAAS,WAAW;GAC3B,kBAAkB,OAAO,MAAM,GAAG;GAClC,MAAM,sBAAsB;GAC5B;EACF;EAEA,IAAI,KAAK,SAAS,aAAa;GAC7B,IAAI,UAAU,GACZ,kBAAkB,OAAO,IAAI;GAC/B,oBAAoB,OAAO,MAAM,GAAG;GACpC,MAAM,sBAAsB;EAC9B;CACF;CAIA,kBAAkB,MAAM,MAAM;CAC9B,WAAW,KAAK,OAAO,MAAM;CAG7B,OAAO;EAAE,QAAQ,gBAAgB,QAAQ,OAAO,MAAM,UAAU;EAAG;CAAW;AAChF;;;;;;;;;AAUA,MAAM,uBAAuB;;;;;;AAO7B,MAAM,8BAA8B;CAClC,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,SAAS;CACT,YAAY;CACZ,YAAY;CACZ,SAAS;AACX;;;;;;;;;;;;;;AAeA,SAAS,2BACP,MACA,KACoB;CACpB,MAAM,IAAI,KAAK,MAAM,oBAAoB;CACzC,IAAI,CAAC,GACH,OAAO;CAET,MAAM,OAAO,EAAE;CACf,MAAM,QAAQ,OAAmC;EAC/C,MAAM,QAAQ,KAAK,MAAM,EAAE;EAC3B,OAAO,QAAQ,YAAY,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,KAAA;CAChD;CAEA,MAAM,SAAS,KAAK,4BAA4B,MAAM,KAAK;CAC3D,MAAM,YAAY,KAAK,4BAA4B,MAAM,KAAK;CAC9D,MAAM,SAA8B,cAAc,WAAW,WAAW;CACxE,MAAM,WAAW,OAAO,SAAS,KAAK,4BAA4B,QAAQ,KAAK,KAAK,EAAE,KAAK;CAC3F,MAAM,UAAU,KAAK,4BAA4B,OAAO,KAAK;CAC7D,MAAM,aAAa,KAAK,4BAA4B,UAAU,KAAK;CACnE,MAAM,aAAa,OAAO,SAAS,KAAK,4BAA4B,UAAU,KAAK,KAAK,EAAE,KAAK;CAI/F,OAAO;EACL,MAAM;EACN,MALc,KAAK,4BAA4B,OAAO,KACnD,GAAG,OAAO,GAAG,YAAY,WAAW,IAAI,aAAa;EAKxD,MAAM;GAAE;GAAQ;GAAQ;GAAU;GAAY;GAAS;EAAW;EAClE,QAAQ,IAAI;EACZ,GAAI,IAAI,YAAY,KAAA,IAAY,EAAE,SAAS,IAAI,QAAQ,IAAI,CAAC;EAC5D,GAAI,IAAI,UAAU,KAAA,IAAY,EAAE,OAAO,IAAI,MAAM,IAAI,CAAC;CACxD;AACF;;;;;;;;;AAUA,SAAS,YAAY,GAAmB;CACtC,OAAO,EACJ,QAAQ,SAAS,GAAG,CAAC,CACrB,QAAQ,SAAS,GAAG,CAAC,CACrB,QAAQ,WAAW,IAAG,CAAC,CACvB,QAAQ,WAAW,GAAI,CAAC,CACxB,QAAQ,UAAU,GAAG;AAC1B;;;;;;;AAQA,SAAgB,gBAAgB,MAAc,OAAwC;CACpF,MAAM,OAAO,KAAK,UAAU,KAAK;CACjC,OAAO,QAAQ,SAAS,OAAO,GAAG,KAAK,GAAG,KAAK,KAAK;AACtD;;;;;;;;;;;;AAaA,SAAgB,wBAAwB,SAA0B;CAChE,IAAI,MAAM,QAAQ,OAAO,GAAG;EAC1B,MAAM,IAAI,QAAQ;EAClB,OAAO,MAAM,IAAI,aAAa,GAAG,EAAE;CACrC;CACA,IAAI,WAAW,OAAO,YAAY,UAAU;EAC1C,MAAM,OAAQ,QAAqC;EACnD,IAAI,OAAO,SAAS,UAClB,OAAO,UAAU;CACrB;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,wBACd,QACA,QACA,UACe;CACf,KAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;EAC3C,MAAM,IAAI,OAAO;EACjB,IAAI,EAAE,SAAS,UAAU,EAAE,WAAW,UAAU,CAAC,EAAE,MACjD;EACF,IAAI,EAAE,KAAK,aAAa,UACtB,OAAO;EACT,MAAM,OAAO,OAAO,MAAM;EAC1B,KAAK,KAAK;GAAE,GAAG;GAAG,MAAM;IAAE,GAAG,EAAE;IAAM;GAAS;EAAE;EAChD,OAAO;CACT;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,eAAe,QAA8C;CAC3E,OAAO,OAAO,WAAW,WAAW,SAAS,iBAAiB,MAAM;AACtE;;;;;;;;;;;;;;;;AAiBA,SAAgB,qBAAqB,MAAsB;CAazD,OAAO,KAAK,QACV,6CACA,IACF;AACF;;;;;;;;;;AAoCA,MAAM,aAAkD;CACtD,aAAa;CACb,eAAe;CACf,QAAQ;CAGR,YAAY;CACZ,QAAQ;CACR,eAAe;CAGf,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,eAAe;CACf,aAAa;CAEb,gBAAgB;CAIhB,mBAAmB;CAMnB,qBAAqB;CAErB,iBAAiB;CAIjB,eAAe;CAIf,UAAU;CAEV,gBAAgB;AAClB;AAEA,MAAM,6BAA+C,IAAI,IAAI,CAAC,QAAQ,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BpF,SAAgB,aAAa,OAAoB,UAA2C;CAM1F,IAAI,CAAC,UACH,OAAO;CAMT,IAAI,WAAW,IAAI,MAAM,IAAI,KAAK,WAAW,IAAI,SAAS,IAAI,GAC5D,OAAO;CAIT,IAAI,MAAM,SAAS,iBAAiB,aAC9B,WAAW,IAAI,SAAS,IAAI,KAAK,SAAS,SAAS,iBAAiB,SAAS,SAAS,cAC1F,OAAO;CAET,IAAI,MAAM,SAAS,uBAAuB,UAAU,SAAS,qBAC3D,OAAO;CAGT,IAAI,SAAS,SAAS,eACpB,OAAO;CAIT,IAAI,MAAM,UAAU,UAAU,QAC5B,OAAO;CAGT,IAAI,MAAM,SAAS,cAAc,UAAU,SAAS,cAAc,SAAS,YAAY,MAAM,SAC3F,OAAO;CACT,OAAO,WAAW,MAAM,SAAS;AACnC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,yBACd,OACA,OAA8B,CAAC,GACvB;CACR,MAAM,8BAAc,IAAI,IAAY;CACpC,KAAK,MAAM,OAAO,MAChB,KAAK,IAAI,SAAS,KAAK,GACrB,YAAY,IAAI,IAAI,EAAE;CAE1B,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;EAC1C,MAAM,OAAO,MAAM;EACnB,IAAI,KAAK,SAAS,eAAe,CAAC,KAAK,OACrC;EACF,IAAI,KAAK,SAAS,YAAY,IAAI,KAAK,KAAK,GAC1C;EACF,MAAM,QAAQ,KAAK,MAAM,SAAS,MAC7B,KAAK,MAAM,aAAa,MACxB,KAAK,MAAM,iBAAiB;EACjC,IAAI,SAAS,GACX;EACF,OAAO;CACT;CACA,OAAO;AACT;;;;;;;;AASA,SAAgB,YAAY,MAAqC;CAC/D,IAAI,QAAQ;CACZ,KAAK,MAAM,OAAO,MAChB,IAAI,IAAI,MACN,SAAS,IAAI;CAEjB,OAAO;AACT;;;;;;;AAgBA,SAAgB,cAAc,MAAqD;CACjF,OAAO,KAAK,UAAS,QAAO,IAAI,WAAW,aAAa,CAAC,IAAI,WAAW;AAC1E;;;;;;;;;;AAWA,SAAgB,YAAY,MAAoE;CAC9F,MAAM,MAAM,cAAc,KAAK,IAAI;CACnC,IAAI,CAAC,KACH,OAAO,KAAA;CACT,IAAI,eAAe;CACnB,KAAK,MAAM,QAAQ,KAAK,OACtB,IAAI,KAAK,UAAU,IAAI,IACrB,gBAAgB,KAAK,OAAO,UAAU;CAE1C,OAAO;EAAE,WAAW,IAAI;EAAW;CAAa;AAClD;;;;;;;;;;AAkCA,SAAgB,aAAa,MAAkD;CAC7E,MAAM,0BAAU,IAAI,IAA+B;CACnD,KAAK,MAAM,OAAO,MAChB,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,GAAG;EACnC,MAAM,MAAM,EAAE,WAAW;EACzB,IAAI,MAAM,QAAQ,IAAI,GAAG;EACzB,IAAI,CAAC,KAAK;GACR,MAAM;IAAE,SAAS;IAAK,OAAO;IAAG,OAAO;IAAG,QAAQ;IAAG,WAAW;IAAG,eAAe;IAAG,MAAM;IAAG,cAAc;GAAK;GACjH,QAAQ,IAAI,KAAK,GAAG;EACtB;EACA,IAAI,SAAS;EACb,IAAI,SAAS,EAAE;EACf,IAAI,UAAU,EAAE;EAChB,IAAI,aAAa,EAAE,aAAa;EAChC,IAAI,iBAAiB,EAAE,iBAAiB;EACxC,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,QAAQ,EAAE;OAEd,IAAI,eAAe;CACvB;CAEF,MAAM,eAAe,MAAyB,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE;CACnF,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAO,EAAE,OAAO,EAAE,QAAU,YAAY,CAAC,IAAI,YAAY,CAAC,CAAE;AACpG"}